├── README.md ├── djobs ├── __init__.py ├── settings.py ├── urls.py ├── views.py └── wsgi.py ├── manage.py ├── simpleblog ├── __init__.py ├── admin.py ├── forms.py ├── models.py ├── templatetags │ ├── __init__.py │ ├── filterlib.py │ └── gravatar.py ├── urls.py └── views.py ├── static ├── css │ ├── bootstrap-responsive.css │ ├── bootstrap-responsive.min.css │ ├── bootstrap.css │ ├── bootstrap.min.css │ ├── code.css │ ├── reset.css │ └── style.css ├── img │ ├── defaultavatar.png │ ├── glyphicons-halflings-white.png │ ├── glyphicons-halflings.png │ └── twitter_web_sprite_icons.png └── js │ ├── ajaxpost.js │ ├── bootstrap.js │ ├── bootstrap.min.js │ ├── jquery.js │ └── modernizr.js └── templates ├── base.html └── simpleblog ├── blog_add.html ├── blog_add_comments.html ├── blog_add_weibo.html ├── blog_base.html ├── blog_comments_show.html ├── blog_filter.html ├── blog_list.html ├── blog_show.html ├── blog_twitter.html └── share.html /README.md: -------------------------------------------------------------------------------- 1 | sblog 2 | ===== 3 | 4 | 一个使用django搭建的简易博客 5 | 6 | 前端使用bootstrap 7 | 8 | Admin 使用grappelli优化 9 | 使用说明: http://django-grappelli.readthedocs.org/en/latest/ 10 | 11 | 评论使用的系统自带comments 12 | 13 | 支持markdown 14 | 15 | 使用的gravatar头像服务 16 | 使用说明:http://en.gravatar.com/site/implement/images/django/ 17 | 18 | 21/9/12 19 | 20 | comments 添加了ajax支持 21 | 添加博客页面添加了添加标签 22 | 优化了界面 23 | 24 | 22/9/12 25 | 26 | 添加了增加多个标签 删除标签功能 27 | 添加了按标签检索功能 28 | 29 | 30 | 26/9/12 31 | 添加发布消息 32 | 添加代码高亮 使用markdown + Pygments 33 | 优化url 34 | 美化界面 -------------------------------------------------------------------------------- /djobs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gusibi/sblog/45f92e574878dabd1d92d0f3bd5eb85144344313/djobs/__init__.py -------------------------------------------------------------------------------- /djobs/settings.py: -------------------------------------------------------------------------------- 1 | # Django settings for djobs project. 2 | 3 | DEBUG = True 4 | TEMPLATE_DEBUG = DEBUG 5 | 6 | ADMINS = ( 7 | # ('Your Name', 'your_email@example.com'), 8 | ) 9 | 10 | # email 11 | EMAIL_HOST = 'smtp.gmail.com' 12 | EMAIL_HOST_USER = 'mail@gmail.com' 13 | EMAIL_HOST_PASSWORD = 'password' 14 | EMAIL_PORT = 587 15 | EMAIL_USE_TLS = True 16 | 17 | MANAGERS = ADMINS 18 | 19 | DATABASES = { 20 | 'default': { 21 | 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. 22 | 'NAME': '/home/gs/djobs/djobs/datas/mydata.db', # Or path to database file if using sqlite3. 23 | 'USER': '', # Not used with sqlite3. 24 | 'PASSWORD': '', # Not used with sqlite3. 25 | 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. 26 | 'PORT': '', # Set to empty string for default. Not used with sqlite3. 27 | } 28 | } 29 | 30 | # Local time zone for this installation. Choices can be found here: 31 | # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name 32 | # although not all choices may be available on all operating systems. 33 | # In a Windows environment this must be set to your system time zone. 34 | TIME_ZONE = 'Asia/Shanghai' 35 | 36 | # Language code for this installation. All choices can be found here: 37 | # http://www.i18nguy.com/unicode/language-identifiers.html 38 | LANGUAGE_CODE = 'en-us' 39 | 40 | SITE_ID = 1 41 | 42 | # If you set this to False, Django will make some optimizations so as not 43 | # to load the internationalization machinery. 44 | USE_I18N = True 45 | 46 | # If you set this to False, Django will not format dates, numbers and 47 | # calendars according to the current locale. 48 | USE_L10N = True 49 | 50 | # If you set this to False, Django will not use timezone-aware datetimes. 51 | USE_TZ = True 52 | 53 | # Absolute filesystem path to the directory that will hold user-uploaded files. 54 | # Example: "/home/media/media.lawrence.com/media/" 55 | MEDIA_ROOT = '' 56 | 57 | # URL that handles the media served from MEDIA_ROOT. Make sure to use a 58 | # trailing slash. 59 | # Examples: "http://media.lawrence.com/media/", "http://example.com/media/" 60 | MEDIA_URL = '' 61 | 62 | # Absolute path to the directory static files should be collected to. 63 | # Don't put anything in this directory yourself; store your static files 64 | # in apps' "static/" subdirectories and in STATICFILES_DIRS. 65 | # Example: "/home/media/media.lawrence.com/static/" 66 | STATIC_ROOT = 'static' 67 | 68 | # URL prefix for static files. 69 | # Example: "http://media.lawrence.com/static/" 70 | STATIC_URL = '/static/' 71 | 72 | # Additional locations of static files 73 | STATICFILES_DIRS = ( 74 | # Put strings here, like "/home/html/static" or "C:/www/django/static". 75 | # Always use forward slashes, even on Windows. 76 | # Don't forget to use absolute paths, not relative paths. 77 | '/home/gs/djobs/static', 78 | ) 79 | 80 | # List of finder classes that know how to find static files in 81 | # various locations. 82 | STATICFILES_FINDERS = ( 83 | 'django.contrib.staticfiles.finders.FileSystemFinder', 84 | 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 85 | # 'django.contrib.staticfiles.finders.DefaultStorageFinder', 86 | ) 87 | 88 | # Make this unique, and don't share it with anybody. 89 | SECRET_KEY = 'c@ys*2sff-a8cptyp*-#(l!1_$!zw1z650emky6bmbwp1n-%r9' 90 | 91 | # List of callables that know how to import templates from various sources. 92 | TEMPLATE_LOADERS = ( 93 | 'django.template.loaders.filesystem.Loader', 94 | 'django.template.loaders.app_directories.Loader', 95 | # 'django.template.loaders.eggs.Loader', 96 | ) 97 | 98 | MIDDLEWARE_CLASSES = ( 99 | 'django.middleware.common.CommonMiddleware', 100 | 'django.contrib.sessions.middleware.SessionMiddleware', 101 | 'django.middleware.csrf.CsrfViewMiddleware', 102 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 103 | 'django.contrib.messages.middleware.MessageMiddleware', 104 | 'django.middleware.locale.LocaleMiddleware', 105 | # Uncomment the next line for simple clickjacking protection: 106 | # 'django.middleware.clickjacking.XFrameOptionsMiddleware', 107 | ) 108 | 109 | ROOT_URLCONF = 'djobs.urls' 110 | 111 | # Python dotted path to the WSGI application used by Django's runserver. 112 | WSGI_APPLICATION = 'djobs.wsgi.application' 113 | 114 | TEMPLATE_DIRS = ( 115 | # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". 116 | # Always use forward slashes, even on Windows. 117 | # Don't forget to use absolute paths, not relative paths. 118 | "/home/gs/djobs/templates", 119 | "/home/gs/djobs/templates/simpleblog", 120 | ) 121 | 122 | TEMPLATE_CONTEXT_PROCESSORS = ( 123 | 'django.contrib.auth.context_processors.auth', 124 | 'django.contrib.messages.context_processors.messages', 125 | ) 126 | 127 | INSTALLED_APPS = ( 128 | 'django.contrib.auth', 129 | 'django.contrib.contenttypes', 130 | 'django.contrib.sessions', 131 | 'django.contrib.sites', 132 | 'django.contrib.messages', 133 | 'django.contrib.staticfiles', 134 | # Uncomment the next line to enable the admin: 135 | 'grappelli', 136 | 'django.contrib.admin', 137 | # Uncomment the next line to enable admin documentation: 138 | 'django.contrib.admindocs', 139 | 'django.contrib.markup', 140 | 'django.contrib.comments', 141 | 'django.contrib.staticfiles', 142 | 'simpleblog', 143 | ) 144 | 145 | # A sample logging configuration. The only tangible logging 146 | # performed by this configuration is to send an email to 147 | # the site admins on every HTTP 500 error when DEBUG=False. 148 | # See http://docs.djangoproject.com/en/dev/topics/logging for 149 | # more details on how to customize your logging configuration. 150 | LOGGING = { 151 | 'version': 1, 152 | 'disable_existing_loggers': False, 153 | 'filters': { 154 | 'require_debug_false': { 155 | '()': 'django.utils.log.RequireDebugFalse' 156 | } 157 | }, 158 | 'handlers': { 159 | 'mail_admins': { 160 | 'level': 'ERROR', 161 | 'filters': ['require_debug_false'], 162 | 'class': 'django.utils.log.AdminEmailHandler' 163 | } 164 | }, 165 | 'loggers': { 166 | 'django.request': { 167 | 'handlers': ['mail_admins'], 168 | 'level': 'ERROR', 169 | 'propagate': True, 170 | }, 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /djobs/urls.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from django.contrib.auth.views import login, logout 3 | from django.conf.urls import patterns, include, url 4 | # Uncomment the next two lines to enable the admin: 5 | from django.contrib import admin 6 | from django.conf import settings 7 | 8 | admin.autodiscover() 9 | 10 | urlpatterns = patterns(('djobs.views'), 11 | # Examples: 12 | # url(r'^$', 'djobs.views.home', name='home'), 13 | # url(r'^djobs/', include('djobs.foo.urls')), 14 | # Uncomment the admin/doc line below to enable admin documentation: 15 | url(r'^admin/doc/', include('django.contrib.admindocs.urls')), 16 | # Uncomment the next line to enable the admin: 17 | url(r'^admin/', include(admin.site.urls)), 18 | url(r'^comments/', include('django.contrib.comments.urls')), 19 | ) 20 | 21 | urlpatterns += patterns((''), 22 | (r'^simpleblog/', include('simpleblog.urls')), 23 | ) 24 | 25 | urlpatterns += patterns((''), 26 | #静态文件 27 | (r'^static/(?P.*)$', 'django.views.static.serve', 28 | {'document_root': settings.STATIC_ROOT} 29 | # {'document_root': '/home/gs/djobs/static/'} 30 | ), 31 | ) -------------------------------------------------------------------------------- /djobs/views.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | from django.template.loader import get_template 5 | from django.template import Context 6 | from django.http import HttpResponse 7 | from django.shortcuts import render_to_response 8 | import time 9 | import datetime 10 | 11 | 12 | def hello(request): 13 | return HttpResponse("hello world") 14 | 15 | 16 | def current_datetime(request): 17 | now = time.ctime() 18 | t = get_template('mytemp.html') 19 | html = t.render(Context({'current_date': now})) 20 | return HttpResponse(html) 21 | 22 | 23 | def hours_ahead(request, offset): 24 | try: 25 | offset = int(offset) 26 | except ValueError: 27 | raise Http404() 28 | links = ['link1','link2','link3','link4'] 29 | current_date = datetime.datetime.now() 30 | hours_ahead = datetime.datetime.now() + datetime.timedelta(hours=offset) 31 | return render_to_response('mytemp.html', locals()) 32 | 33 | 34 | def request_meta(request): 35 | values = request.META.items() 36 | values.sort() 37 | return render_to_response('request_meta.html', {'values': values}) 38 | -------------------------------------------------------------------------------- /djobs/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for djobs project. 3 | 4 | This module contains the WSGI application used by Django's development server 5 | and any production WSGI deployments. It should expose a module-level variable 6 | named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover 7 | this application via the ``WSGI_APPLICATION`` setting. 8 | 9 | Usually you will have the standard Django WSGI application here, but it also 10 | might make sense to replace the whole Django WSGI application with a custom one 11 | that later delegates to the Django one. For example, you could introduce WSGI 12 | middleware here, or combine a Django application with an application of another 13 | framework. 14 | 15 | """ 16 | import os 17 | 18 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djobs.settings") 19 | 20 | # This application object is used by any WSGI server configured to use this 21 | # file. This includes Django's development server, if the WSGI_APPLICATION 22 | # setting points here. 23 | from django.core.wsgi import get_wsgi_application 24 | application = get_wsgi_application() 25 | 26 | # Apply WSGI middleware here. 27 | # from helloworld.wsgi import HelloWorldApplication 28 | # application = HelloWorldApplication(application) 29 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djobs.settings") 7 | 8 | from django.core.management import execute_from_command_line 9 | 10 | execute_from_command_line(sys.argv) 11 | -------------------------------------------------------------------------------- /simpleblog/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gusibi/sblog/45f92e574878dabd1d92d0f3bd5eb85144344313/simpleblog/__init__.py -------------------------------------------------------------------------------- /simpleblog/admin.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | from django.contrib import admin 5 | from simpleblog.models import Author, Blog, Tag, Weibo 6 | 7 | 8 | class AuthorAdmin(admin.ModelAdmin): 9 | """docstring for AuthorAdmin""" 10 | list_display = ('name', 'email', 'website') 11 | search_fields = ('name',) 12 | 13 | 14 | class BlogAdmin(admin.ModelAdmin): 15 | """docstring for BlogAdmin""" 16 | list_display = ('caption', 'id', 'author', 'publish_time') 17 | list_filter = ('publish_time',) 18 | date_hierarchy = 'publish_time' 19 | ordering = ('-publish_time',) 20 | filter_horizontal = ('tags',) 21 | raw_id_fields = ('author',) # 它是一个包含外键字段名称的元组,它包含的字段将被展现成`` 文本框`` ,而不再是`` 下拉框`` 。 22 | 23 | 24 | admin.site.register(Author, AuthorAdmin) 25 | admin.site.register(Blog, BlogAdmin) 26 | admin.site.register(Tag) 27 | admin.site.register(Weibo) 28 | -------------------------------------------------------------------------------- /simpleblog/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | 4 | class BlogForm(forms.Form): 5 | """docstring for BlogForm""" 6 | caption = forms.CharField(label='title', max_length=100) 7 | content = forms.CharField(widget=forms.Textarea) 8 | 9 | 10 | class TagForm(forms.Form): 11 | """docstring for TagForm""" 12 | tag_name = forms.CharField() 13 | 14 | 15 | class WeiboForm(forms.Form): 16 | """docstring for WeiboForm""" 17 | massage = forms.CharField(widget=forms.Textarea) 18 | -------------------------------------------------------------------------------- /simpleblog/models.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | from django.db import models 5 | 6 | 7 | class Tag(models.Model): 8 | """docstring for Tags""" 9 | tag_name = models.CharField(max_length=20) 10 | create_time = models.DateTimeField(auto_now_add=True) 11 | 12 | def __unicode__(self): 13 | return self.tag_name 14 | 15 | 16 | class Author(models.Model): 17 | """docstring for Author""" 18 | name = models.CharField(max_length=30) 19 | email = models.EmailField(blank=True) 20 | website = models.URLField(blank=True) 21 | 22 | def __unicode__(self): 23 | return u'%s' % (self.name) 24 | 25 | 26 | class BlogManager(models.Manager): 27 | """docstring for BlogManager""" 28 | def title_count(self, keyword): 29 | return self.filter(caption__icontains=keyword).count() 30 | 31 | def tag_count(self, keyword): 32 | return self.filter(tags__icontains=keyword).count() 33 | 34 | def author_count(self, keyword): 35 | return self.filter(author__icontains=keyword).count() 36 | 37 | 38 | class Blog(models.Model): 39 | """docstring for Blogs""" 40 | caption = models.CharField(max_length=50) 41 | author = models.ForeignKey(Author) 42 | tags = models.ManyToManyField(Tag, blank=True) 43 | content = models.TextField() 44 | publish_time = models.DateTimeField(auto_now_add=True) 45 | update_time = models.DateTimeField(auto_now=True) 46 | 47 | objects = models.Manager() 48 | count_objects = BlogManager() 49 | taglist = [] 50 | 51 | def save(self, *args, **kwargs): 52 | super(Blog, self).save() 53 | for i in self.taglist: 54 | p, created = Tag.objects.get_or_create(tag_name=i) 55 | self.tags.add(p) 56 | 57 | def __unicode__(self): 58 | return u'%s %s %s' % (self.caption, self.author, self.publish_time) 59 | 60 | 61 | class Weibo(models.Model): 62 | massage = models.CharField(max_length=200) 63 | author = models.ForeignKey(Author) 64 | publish_time = models.DateTimeField(auto_now_add=True) 65 | 66 | def __unicode__(self): 67 | return self.massage 68 | -------------------------------------------------------------------------------- /simpleblog/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gusibi/sblog/45f92e574878dabd1d92d0f3bd5eb85144344313/simpleblog/templatetags/__init__.py -------------------------------------------------------------------------------- /simpleblog/templatetags/filterlib.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | from django.template.defaultfilters import stringfilter 3 | 4 | from django.conf import settings 5 | 6 | register = template.Library() 7 | 8 | @register.filter(name='markdown') 9 | @stringfilter 10 | def markdown(value, arg=''): 11 | """ 12 | Filter to create HTML out of Markdown, using custom extensions. 13 | 14 | The diffrence between this filter and the django-internal markdown 15 | filter (located in ``django/contrib/markup/templatetags/markup.py``) 16 | is that this filter enables extensions to be load. 17 | 18 | Usage:: 19 | 20 | {{ object.text|markdown }} 21 | {{ object.text|markdown:"save" }} 22 | {{ object.text|markdown:"codehilite" }} 23 | {{ object.text|markdown:"save,codehilite" }} 24 | 25 | This code is taken from 26 | http://www.freewisdom.org/projects/python-markdown/Django 27 | """ 28 | try: 29 | import markdown 30 | except ImportError: 31 | if settings.DEBUG: 32 | raise (template.TemplateSyntaxError, 33 | "Error in {% markdown %} filter: " 34 | + "The markdown library isn't installed.") 35 | else : 36 | from django.utils.html import escape, linebreaks 37 | return linebreaks(escape(value)) 38 | else: 39 | extensions=arg.split(",") 40 | if len(extensions) > 0 and extensions[0] == "safe" : 41 | extensions = extensions[1:] 42 | safe_mode = True 43 | else : 44 | safe_mode = False 45 | return markdown.markdown(value, extensions, safe_mode=safe_mode) -------------------------------------------------------------------------------- /simpleblog/templatetags/gravatar.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ### gravatar.py ############### 3 | ### place inside a 'templatetags' directory inside the top level of a Django app (not project, must be inside an app) 4 | ### at the top of your page template include this: 5 | ### {% load gravatar %} 6 | ### and to use the url do this: 7 | ### 8 | ### or 9 | ### 10 | ### just make sure to update the "default" image path below 11 | 12 | from django import template 13 | import urllib 14 | import hashlib 15 | 16 | register = template.Library() 17 | 18 | 19 | class GravatarUrlNode(template.Node): 20 | def __init__(self, email): 21 | self.email = template.Variable(email) 22 | 23 | def render(self, context): 24 | try: 25 | email = self.email.resolve(context) 26 | except template.VariableDoesNotExist: 27 | return '' 28 | 29 | default = "http://127.0.0.1:8000/static/img/defaultavatar.png" 30 | size = 40 31 | 32 | gravatar_url = "http://www.gravatar.com/avatar/" + hashlib.md5(email.lower()).hexdigest() + "?" 33 | gravatar_url += urllib.urlencode({'d': default, 's': str(size)}) 34 | 35 | return gravatar_url 36 | 37 | 38 | @register.tag 39 | def gravatar_url(parser, token): 40 | try: 41 | tag_name, email = token.split_contents() 42 | 43 | except ValueError: 44 | raise template.TemplateSyntaxError, "%r tag requires a single argument" % token.contents.split()[0] 45 | 46 | return GravatarUrlNode(email) 47 | -------------------------------------------------------------------------------- /simpleblog/urls.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | from django.conf.urls import * 5 | 6 | 7 | urlpatterns = patterns(('simpleblog.views'), 8 | url(r'^bloglist/$', 'blog_list', name='bloglist'), 9 | url(r'^blog/tag/(?P\d+)/$', 'blog_filter', name='filtrblog'), 10 | url(r'^blog/search/$', 'blog_search', name='searchblog'), 11 | url(r'^blog/(?P\d+)/$', 'blog_show', name='detailblog'), 12 | url(r'^blog/(?P\w+)/del/$', 'blog_del', name='delblog'), 13 | url(r'^blog/(?P\w+)/update/$', 'blog_update', name='updateblog'), 14 | url(r'^blog/add/$', 'blog_add', name='addblog'), 15 | url(r'^blog/addmassage/$', 'add_weibo', name='addmassage'), 16 | url(r'^blog/showweibo/$', 'show_weibo', name='showweibo'), 17 | url(r'^blog/(?P\d+)/commentshow/$', 'blog_show_comment', name='showcomment'), 18 | ) 19 | -------------------------------------------------------------------------------- /simpleblog/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render_to_response 2 | from django.http import Http404 3 | from django.http import HttpResponse 4 | from django.http import HttpResponseRedirect 5 | from django.template import RequestContext 6 | # from django.views.decorators.csrf import csrf_protect 7 | from django.core.context_processors import csrf 8 | from simpleblog.forms import BlogForm 9 | from simpleblog.forms import TagForm 10 | from simpleblog.models import Blog 11 | from simpleblog.models import Author 12 | from simpleblog.models import Tag 13 | from simpleblog.models import Weibo 14 | 15 | 16 | def blog_list(request): 17 | blogs = Blog.objects.order_by('-id') 18 | tags = Tag.objects.all() 19 | weibos = Weibo.objects.order_by('-publish_time')[:5] 20 | return render_to_response("blog_list.html", 21 | {"blogs": blogs, "tags": tags, "weibos": weibos}, 22 | context_instance=RequestContext(request)) 23 | 24 | 25 | def blog_filter(request, id=''): 26 | tags = Tag.objects.all() 27 | tag = Tag.objects.get(id=id) 28 | blogs = tag.blog_set.all() 29 | return render_to_response("blog_filter.html", 30 | {"blogs": blogs, "tag": tag, "tags": tags}) 31 | 32 | 33 | def blog_search(request): 34 | tags = Tag.objects.all() 35 | if 'search' in request.GET: 36 | search = request.GET['search'] 37 | blogs = Blog.objects.filter(caption__icontains=search) 38 | return render_to_response('blog_filter.html', 39 | {"blogs": blogs, "tags": tags}, context_instance=RequestContext(request)) 40 | else: 41 | blogs = Blog.objects.order_by('-id') 42 | return render_to_response("blog_list.html", {"blogs": blogs, "tags": tags}, 43 | context_instance=RequestContext(request)) 44 | 45 | 46 | def blog_show(request, id=''): 47 | try: 48 | blog = Blog.objects.get(id=id) 49 | tags = Tag.objects.all() 50 | except Blog.DoesNotExist: 51 | raise Http404 52 | return render_to_response("blog_show.html", 53 | {"blog": blog, "tags": tags}, 54 | context_instance=RequestContext(request)) 55 | 56 | 57 | def blog_show_comment(request, id=''): 58 | blog = Blog.objects.get(id=id) 59 | return render_to_response('blog_comments_show.html', {"blog": blog}) 60 | 61 | 62 | def blog_del(request, id=""): 63 | try: 64 | blog = Blog.objects.get(id=id) 65 | except Exception: 66 | raise Http404 67 | if blog: 68 | blog.delete() 69 | return HttpResponseRedirect("/simpleblog/bloglist/") 70 | blogs = Blog.objects.all() 71 | return render_to_response("blog_list.html", {"blogs": blogs}) 72 | 73 | 74 | def blog_add(request): 75 | if request.method == 'POST': 76 | form = BlogForm(request.POST) 77 | tag = TagForm(request.POST) 78 | if form.is_valid() and tag.is_valid(): 79 | cd = form.cleaned_data 80 | cdtag = tag.cleaned_data 81 | tagname = cdtag['tag_name'] 82 | for taglist in tagname.split(): 83 | Tag.objects.get_or_create(tag_name=taglist.strip()) 84 | title = cd['caption'] 85 | author = Author.objects.get(id=1) 86 | content = cd['content'] 87 | blog = Blog(caption=title, author=author, content=content) 88 | blog.save() 89 | for taglist in tagname.split(): 90 | blog.tags.add(Tag.objects.get(tag_name=taglist.strip())) 91 | blog.save() 92 | id = Blog.objects.order_by('-id')[0].id 93 | return HttpResponseRedirect('/simpleblog/blog/%s' % id) 94 | else: 95 | form = BlogForm() 96 | tag = TagForm() 97 | return render_to_response('blog_add.html', 98 | {'form': form, 'tag': tag}, context_instance=RequestContext(request)) 99 | 100 | 101 | def show_weibo(request): 102 | weibos = Weibo.objects.order_by('-publish_time')[:5] 103 | return render_to_response("blog_twitter.html", {"weibos": weibos}) 104 | 105 | 106 | def add_weibo(request): 107 | c = {} 108 | c.update(csrf(request)) 109 | if request.method == 'POST': 110 | massage = request.POST['twitter'] 111 | author = Author.objects.get(id=1) 112 | massage = Weibo(massage=massage, author=author) 113 | massage.save() 114 | weibos = Weibo.objects.order_by('-publish_time')[:5] 115 | return render_to_response("blog_twitter.html", 116 | {"weibos": weibos}, 117 | context_instance=RequestContext(request)) 118 | else: 119 | return HttpResponse('dddd') 120 | # blogs = Blog.objects.order_by('-id') 121 | # tags = Tag.objects.all() 122 | # return render_to_response("blog_list.html", 123 | # {"blogs": blogs, "tags": tags}, 124 | # context_instance=RequestContext(request)) 125 | 126 | 127 | def blog_update(request, id=""): 128 | id = id 129 | if request.method == 'POST': 130 | form = BlogForm(request.POST) 131 | tag = TagForm(request.POST) 132 | if form.is_valid() and tag.is_valid(): 133 | cd = form.cleaned_data 134 | cdtag = tag.cleaned_data 135 | tagname = cdtag['tag_name'] 136 | tagnamelist = tagname.split() 137 | for taglist in tagnamelist: 138 | Tag.objects.get_or_create(tag_name=taglist.strip()) 139 | title = cd['caption'] 140 | content = cd['content'] 141 | blog = Blog.objects.get(id=id) 142 | if blog: 143 | blog.caption = title 144 | blog.content = content 145 | blog.save() 146 | for taglist in tagnamelist: 147 | blog.tags.add(Tag.objects.get(tag_name=taglist.strip())) 148 | blog.save() 149 | tags = blog.tags.all() 150 | for tagname in tags: 151 | tagname = unicode(str(tagname), "utf-8") 152 | if tagname not in tagnamelist: 153 | notag = blog.tags.get(tag_name=tagname) 154 | blog.tags.remove(notag) 155 | else: 156 | blog = Blog(caption=blog.caption, content=blog.content) 157 | blog.save() 158 | return HttpResponseRedirect('/simpleblog/blog/%s' % id) 159 | else: 160 | try: 161 | blog = Blog.objects.get(id=id) 162 | except Exception: 163 | raise Http404 164 | form = BlogForm(initial={'caption': blog.caption, 'content': blog.content}, auto_id=False) 165 | tags = blog.tags.all() 166 | if tags: 167 | taginit = '' 168 | for x in tags: 169 | taginit += str(x) + ' ' 170 | tag = TagForm(initial={'tag_name': taginit}) 171 | else: 172 | tag = TagForm() 173 | return render_to_response('blog_add.html', 174 | {'blog': blog, 'form': form, 'id': id, 'tag': tag}, 175 | context_instance=RequestContext(request)) 176 | -------------------------------------------------------------------------------- /static/css/bootstrap-responsive.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Responsive v2.1.1 3 | * 4 | * Copyright 2012 Twitter, Inc 5 | * Licensed under the Apache License v2.0 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Designed and built with all the love in the world @twitter by @mdo and @fat. 9 | */ 10 | 11 | .clearfix { 12 | *zoom: 1; 13 | } 14 | 15 | .clearfix:before, 16 | .clearfix:after { 17 | display: table; 18 | line-height: 0; 19 | content: ""; 20 | } 21 | 22 | .clearfix:after { 23 | clear: both; 24 | } 25 | 26 | .hide-text { 27 | font: 0/0 a; 28 | color: transparent; 29 | text-shadow: none; 30 | background-color: transparent; 31 | border: 0; 32 | } 33 | 34 | .input-block-level { 35 | display: block; 36 | width: 100%; 37 | min-height: 30px; 38 | -webkit-box-sizing: border-box; 39 | -moz-box-sizing: border-box; 40 | box-sizing: border-box; 41 | } 42 | 43 | .hidden { 44 | display: none; 45 | visibility: hidden; 46 | } 47 | 48 | .visible-phone { 49 | display: none !important; 50 | } 51 | 52 | .visible-tablet { 53 | display: none !important; 54 | } 55 | 56 | .hidden-desktop { 57 | display: none !important; 58 | } 59 | 60 | .visible-desktop { 61 | display: inherit !important; 62 | } 63 | 64 | @media (min-width: 768px) and (max-width: 979px) { 65 | .hidden-desktop { 66 | display: inherit !important; 67 | } 68 | .visible-desktop { 69 | display: none !important ; 70 | } 71 | .visible-tablet { 72 | display: inherit !important; 73 | } 74 | .hidden-tablet { 75 | display: none !important; 76 | } 77 | } 78 | 79 | @media (max-width: 767px) { 80 | .hidden-desktop { 81 | display: inherit !important; 82 | } 83 | .visible-desktop { 84 | display: none !important; 85 | } 86 | .visible-phone { 87 | display: inherit !important; 88 | } 89 | .hidden-phone { 90 | display: none !important; 91 | } 92 | } 93 | 94 | @media (min-width: 1200px) { 95 | .row { 96 | margin-left: -30px; 97 | *zoom: 1; 98 | } 99 | .row:before, 100 | .row:after { 101 | display: table; 102 | line-height: 0; 103 | content: ""; 104 | } 105 | .row:after { 106 | clear: both; 107 | } 108 | [class*="span"] { 109 | float: left; 110 | min-height: 1px; 111 | margin-left: 30px; 112 | } 113 | .container, 114 | .navbar-static-top .container, 115 | .navbar-fixed-top .container, 116 | .navbar-fixed-bottom .container { 117 | width: 1170px; 118 | } 119 | .span12 { 120 | width: 1170px; 121 | } 122 | .span11 { 123 | width: 1070px; 124 | } 125 | .span10 { 126 | width: 970px; 127 | } 128 | .span9 { 129 | width: 870px; 130 | } 131 | .span8 { 132 | width: 770px; 133 | } 134 | .span7 { 135 | width: 670px; 136 | } 137 | .span6 { 138 | width: 570px; 139 | } 140 | .span5 { 141 | width: 470px; 142 | } 143 | .span4 { 144 | width: 370px; 145 | } 146 | .span3 { 147 | width: 270px; 148 | } 149 | .span2 { 150 | width: 170px; 151 | } 152 | .span1 { 153 | width: 70px; 154 | } 155 | .offset12 { 156 | margin-left: 1230px; 157 | } 158 | .offset11 { 159 | margin-left: 1130px; 160 | } 161 | .offset10 { 162 | margin-left: 1030px; 163 | } 164 | .offset9 { 165 | margin-left: 930px; 166 | } 167 | .offset8 { 168 | margin-left: 830px; 169 | } 170 | .offset7 { 171 | margin-left: 730px; 172 | } 173 | .offset6 { 174 | margin-left: 630px; 175 | } 176 | .offset5 { 177 | margin-left: 530px; 178 | } 179 | .offset4 { 180 | margin-left: 430px; 181 | } 182 | .offset3 { 183 | margin-left: 330px; 184 | } 185 | .offset2 { 186 | margin-left: 230px; 187 | } 188 | .offset1 { 189 | margin-left: 130px; 190 | } 191 | .row-fluid { 192 | width: 100%; 193 | *zoom: 1; 194 | } 195 | .row-fluid:before, 196 | .row-fluid:after { 197 | display: table; 198 | line-height: 0; 199 | content: ""; 200 | } 201 | .row-fluid:after { 202 | clear: both; 203 | } 204 | .row-fluid [class*="span"] { 205 | display: block; 206 | float: left; 207 | width: 100%; 208 | min-height: 30px; 209 | margin-left: 2.564102564102564%; 210 | *margin-left: 2.5109110747408616%; 211 | -webkit-box-sizing: border-box; 212 | -moz-box-sizing: border-box; 213 | box-sizing: border-box; 214 | } 215 | .row-fluid [class*="span"]:first-child { 216 | margin-left: 0; 217 | } 218 | .row-fluid .span12 { 219 | width: 100%; 220 | *width: 99.94680851063829%; 221 | } 222 | .row-fluid .span11 { 223 | width: 91.45299145299145%; 224 | *width: 91.39979996362975%; 225 | } 226 | .row-fluid .span10 { 227 | width: 82.90598290598291%; 228 | *width: 82.8527914166212%; 229 | } 230 | .row-fluid .span9 { 231 | width: 74.35897435897436%; 232 | *width: 74.30578286961266%; 233 | } 234 | .row-fluid .span8 { 235 | width: 65.81196581196582%; 236 | *width: 65.75877432260411%; 237 | } 238 | .row-fluid .span7 { 239 | width: 57.26495726495726%; 240 | *width: 57.21176577559556%; 241 | } 242 | .row-fluid .span6 { 243 | width: 48.717948717948715%; 244 | *width: 48.664757228587014%; 245 | } 246 | .row-fluid .span5 { 247 | width: 40.17094017094017%; 248 | *width: 40.11774868157847%; 249 | } 250 | .row-fluid .span4 { 251 | width: 31.623931623931625%; 252 | *width: 31.570740134569924%; 253 | } 254 | .row-fluid .span3 { 255 | width: 23.076923076923077%; 256 | *width: 23.023731587561375%; 257 | } 258 | .row-fluid .span2 { 259 | width: 14.52991452991453%; 260 | *width: 14.476723040552828%; 261 | } 262 | .row-fluid .span1 { 263 | width: 5.982905982905983%; 264 | *width: 5.929714493544281%; 265 | } 266 | .row-fluid .offset12 { 267 | margin-left: 105.12820512820512%; 268 | *margin-left: 105.02182214948171%; 269 | } 270 | .row-fluid .offset12:first-child { 271 | margin-left: 102.56410256410257%; 272 | *margin-left: 102.45771958537915%; 273 | } 274 | .row-fluid .offset11 { 275 | margin-left: 96.58119658119658%; 276 | *margin-left: 96.47481360247316%; 277 | } 278 | .row-fluid .offset11:first-child { 279 | margin-left: 94.01709401709402%; 280 | *margin-left: 93.91071103837061%; 281 | } 282 | .row-fluid .offset10 { 283 | margin-left: 88.03418803418803%; 284 | *margin-left: 87.92780505546462%; 285 | } 286 | .row-fluid .offset10:first-child { 287 | margin-left: 85.47008547008548%; 288 | *margin-left: 85.36370249136206%; 289 | } 290 | .row-fluid .offset9 { 291 | margin-left: 79.48717948717949%; 292 | *margin-left: 79.38079650845607%; 293 | } 294 | .row-fluid .offset9:first-child { 295 | margin-left: 76.92307692307693%; 296 | *margin-left: 76.81669394435352%; 297 | } 298 | .row-fluid .offset8 { 299 | margin-left: 70.94017094017094%; 300 | *margin-left: 70.83378796144753%; 301 | } 302 | .row-fluid .offset8:first-child { 303 | margin-left: 68.37606837606839%; 304 | *margin-left: 68.26968539734497%; 305 | } 306 | .row-fluid .offset7 { 307 | margin-left: 62.393162393162385%; 308 | *margin-left: 62.28677941443899%; 309 | } 310 | .row-fluid .offset7:first-child { 311 | margin-left: 59.82905982905982%; 312 | *margin-left: 59.72267685033642%; 313 | } 314 | .row-fluid .offset6 { 315 | margin-left: 53.84615384615384%; 316 | *margin-left: 53.739770867430444%; 317 | } 318 | .row-fluid .offset6:first-child { 319 | margin-left: 51.28205128205128%; 320 | *margin-left: 51.175668303327875%; 321 | } 322 | .row-fluid .offset5 { 323 | margin-left: 45.299145299145295%; 324 | *margin-left: 45.1927623204219%; 325 | } 326 | .row-fluid .offset5:first-child { 327 | margin-left: 42.73504273504273%; 328 | *margin-left: 42.62865975631933%; 329 | } 330 | .row-fluid .offset4 { 331 | margin-left: 36.75213675213675%; 332 | *margin-left: 36.645753773413354%; 333 | } 334 | .row-fluid .offset4:first-child { 335 | margin-left: 34.18803418803419%; 336 | *margin-left: 34.081651209310785%; 337 | } 338 | .row-fluid .offset3 { 339 | margin-left: 28.205128205128204%; 340 | *margin-left: 28.0987452264048%; 341 | } 342 | .row-fluid .offset3:first-child { 343 | margin-left: 25.641025641025642%; 344 | *margin-left: 25.53464266230224%; 345 | } 346 | .row-fluid .offset2 { 347 | margin-left: 19.65811965811966%; 348 | *margin-left: 19.551736679396257%; 349 | } 350 | .row-fluid .offset2:first-child { 351 | margin-left: 17.094017094017094%; 352 | *margin-left: 16.98763411529369%; 353 | } 354 | .row-fluid .offset1 { 355 | margin-left: 11.11111111111111%; 356 | *margin-left: 11.004728132387708%; 357 | } 358 | .row-fluid .offset1:first-child { 359 | margin-left: 8.547008547008547%; 360 | *margin-left: 8.440625568285142%; 361 | } 362 | input, 363 | textarea, 364 | .uneditable-input { 365 | margin-left: 0; 366 | } 367 | .controls-row [class*="span"] + [class*="span"] { 368 | margin-left: 30px; 369 | } 370 | input.span12, 371 | textarea.span12, 372 | .uneditable-input.span12 { 373 | width: 1156px; 374 | } 375 | input.span11, 376 | textarea.span11, 377 | .uneditable-input.span11 { 378 | width: 1056px; 379 | } 380 | input.span10, 381 | textarea.span10, 382 | .uneditable-input.span10 { 383 | width: 956px; 384 | } 385 | input.span9, 386 | textarea.span9, 387 | .uneditable-input.span9 { 388 | width: 856px; 389 | } 390 | input.span8, 391 | textarea.span8, 392 | .uneditable-input.span8 { 393 | width: 756px; 394 | } 395 | input.span7, 396 | textarea.span7, 397 | .uneditable-input.span7 { 398 | width: 656px; 399 | } 400 | input.span6, 401 | textarea.span6, 402 | .uneditable-input.span6 { 403 | width: 556px; 404 | } 405 | input.span5, 406 | textarea.span5, 407 | .uneditable-input.span5 { 408 | width: 456px; 409 | } 410 | input.span4, 411 | textarea.span4, 412 | .uneditable-input.span4 { 413 | width: 356px; 414 | } 415 | input.span3, 416 | textarea.span3, 417 | .uneditable-input.span3 { 418 | width: 256px; 419 | } 420 | input.span2, 421 | textarea.span2, 422 | .uneditable-input.span2 { 423 | width: 156px; 424 | } 425 | input.span1, 426 | textarea.span1, 427 | .uneditable-input.span1 { 428 | width: 56px; 429 | } 430 | .thumbnails { 431 | margin-left: -30px; 432 | } 433 | .thumbnails > li { 434 | margin-left: 30px; 435 | } 436 | .row-fluid .thumbnails { 437 | margin-left: 0; 438 | } 439 | } 440 | 441 | @media (min-width: 768px) and (max-width: 979px) { 442 | .row { 443 | margin-left: -20px; 444 | *zoom: 1; 445 | } 446 | .row:before, 447 | .row:after { 448 | display: table; 449 | line-height: 0; 450 | content: ""; 451 | } 452 | .row:after { 453 | clear: both; 454 | } 455 | [class*="span"] { 456 | float: left; 457 | min-height: 1px; 458 | margin-left: 20px; 459 | } 460 | .container, 461 | .navbar-static-top .container, 462 | .navbar-fixed-top .container, 463 | .navbar-fixed-bottom .container { 464 | width: 724px; 465 | } 466 | .span12 { 467 | width: 724px; 468 | } 469 | .span11 { 470 | width: 662px; 471 | } 472 | .span10 { 473 | width: 600px; 474 | } 475 | .span9 { 476 | width: 538px; 477 | } 478 | .span8 { 479 | width: 476px; 480 | } 481 | .span7 { 482 | width: 414px; 483 | } 484 | .span6 { 485 | width: 352px; 486 | } 487 | .span5 { 488 | width: 290px; 489 | } 490 | .span4 { 491 | width: 228px; 492 | } 493 | .span3 { 494 | width: 166px; 495 | } 496 | .span2 { 497 | width: 104px; 498 | } 499 | .span1 { 500 | width: 42px; 501 | } 502 | .offset12 { 503 | margin-left: 764px; 504 | } 505 | .offset11 { 506 | margin-left: 702px; 507 | } 508 | .offset10 { 509 | margin-left: 640px; 510 | } 511 | .offset9 { 512 | margin-left: 578px; 513 | } 514 | .offset8 { 515 | margin-left: 516px; 516 | } 517 | .offset7 { 518 | margin-left: 454px; 519 | } 520 | .offset6 { 521 | margin-left: 392px; 522 | } 523 | .offset5 { 524 | margin-left: 330px; 525 | } 526 | .offset4 { 527 | margin-left: 268px; 528 | } 529 | .offset3 { 530 | margin-left: 206px; 531 | } 532 | .offset2 { 533 | margin-left: 144px; 534 | } 535 | .offset1 { 536 | margin-left: 82px; 537 | } 538 | .row-fluid { 539 | width: 100%; 540 | *zoom: 1; 541 | } 542 | .row-fluid:before, 543 | .row-fluid:after { 544 | display: table; 545 | line-height: 0; 546 | content: ""; 547 | } 548 | .row-fluid:after { 549 | clear: both; 550 | } 551 | .row-fluid [class*="span"] { 552 | display: block; 553 | float: left; 554 | width: 100%; 555 | min-height: 30px; 556 | margin-left: 2.7624309392265194%; 557 | *margin-left: 2.709239449864817%; 558 | -webkit-box-sizing: border-box; 559 | -moz-box-sizing: border-box; 560 | box-sizing: border-box; 561 | } 562 | .row-fluid [class*="span"]:first-child { 563 | margin-left: 0; 564 | } 565 | .row-fluid .span12 { 566 | width: 100%; 567 | *width: 99.94680851063829%; 568 | } 569 | .row-fluid .span11 { 570 | width: 91.43646408839778%; 571 | *width: 91.38327259903608%; 572 | } 573 | .row-fluid .span10 { 574 | width: 82.87292817679558%; 575 | *width: 82.81973668743387%; 576 | } 577 | .row-fluid .span9 { 578 | width: 74.30939226519337%; 579 | *width: 74.25620077583166%; 580 | } 581 | .row-fluid .span8 { 582 | width: 65.74585635359117%; 583 | *width: 65.69266486422946%; 584 | } 585 | .row-fluid .span7 { 586 | width: 57.18232044198895%; 587 | *width: 57.12912895262725%; 588 | } 589 | .row-fluid .span6 { 590 | width: 48.61878453038674%; 591 | *width: 48.56559304102504%; 592 | } 593 | .row-fluid .span5 { 594 | width: 40.05524861878453%; 595 | *width: 40.00205712942283%; 596 | } 597 | .row-fluid .span4 { 598 | width: 31.491712707182323%; 599 | *width: 31.43852121782062%; 600 | } 601 | .row-fluid .span3 { 602 | width: 22.92817679558011%; 603 | *width: 22.87498530621841%; 604 | } 605 | .row-fluid .span2 { 606 | width: 14.3646408839779%; 607 | *width: 14.311449394616199%; 608 | } 609 | .row-fluid .span1 { 610 | width: 5.801104972375691%; 611 | *width: 5.747913483013988%; 612 | } 613 | .row-fluid .offset12 { 614 | margin-left: 105.52486187845304%; 615 | *margin-left: 105.41847889972962%; 616 | } 617 | .row-fluid .offset12:first-child { 618 | margin-left: 102.76243093922652%; 619 | *margin-left: 102.6560479605031%; 620 | } 621 | .row-fluid .offset11 { 622 | margin-left: 96.96132596685082%; 623 | *margin-left: 96.8549429881274%; 624 | } 625 | .row-fluid .offset11:first-child { 626 | margin-left: 94.1988950276243%; 627 | *margin-left: 94.09251204890089%; 628 | } 629 | .row-fluid .offset10 { 630 | margin-left: 88.39779005524862%; 631 | *margin-left: 88.2914070765252%; 632 | } 633 | .row-fluid .offset10:first-child { 634 | margin-left: 85.6353591160221%; 635 | *margin-left: 85.52897613729868%; 636 | } 637 | .row-fluid .offset9 { 638 | margin-left: 79.8342541436464%; 639 | *margin-left: 79.72787116492299%; 640 | } 641 | .row-fluid .offset9:first-child { 642 | margin-left: 77.07182320441989%; 643 | *margin-left: 76.96544022569647%; 644 | } 645 | .row-fluid .offset8 { 646 | margin-left: 71.2707182320442%; 647 | *margin-left: 71.16433525332079%; 648 | } 649 | .row-fluid .offset8:first-child { 650 | margin-left: 68.50828729281768%; 651 | *margin-left: 68.40190431409427%; 652 | } 653 | .row-fluid .offset7 { 654 | margin-left: 62.70718232044199%; 655 | *margin-left: 62.600799341718584%; 656 | } 657 | .row-fluid .offset7:first-child { 658 | margin-left: 59.94475138121547%; 659 | *margin-left: 59.838368402492065%; 660 | } 661 | .row-fluid .offset6 { 662 | margin-left: 54.14364640883978%; 663 | *margin-left: 54.037263430116376%; 664 | } 665 | .row-fluid .offset6:first-child { 666 | margin-left: 51.38121546961326%; 667 | *margin-left: 51.27483249088986%; 668 | } 669 | .row-fluid .offset5 { 670 | margin-left: 45.58011049723757%; 671 | *margin-left: 45.47372751851417%; 672 | } 673 | .row-fluid .offset5:first-child { 674 | margin-left: 42.81767955801105%; 675 | *margin-left: 42.71129657928765%; 676 | } 677 | .row-fluid .offset4 { 678 | margin-left: 37.01657458563536%; 679 | *margin-left: 36.91019160691196%; 680 | } 681 | .row-fluid .offset4:first-child { 682 | margin-left: 34.25414364640884%; 683 | *margin-left: 34.14776066768544%; 684 | } 685 | .row-fluid .offset3 { 686 | margin-left: 28.45303867403315%; 687 | *margin-left: 28.346655695309746%; 688 | } 689 | .row-fluid .offset3:first-child { 690 | margin-left: 25.69060773480663%; 691 | *margin-left: 25.584224756083227%; 692 | } 693 | .row-fluid .offset2 { 694 | margin-left: 19.88950276243094%; 695 | *margin-left: 19.783119783707537%; 696 | } 697 | .row-fluid .offset2:first-child { 698 | margin-left: 17.12707182320442%; 699 | *margin-left: 17.02068884448102%; 700 | } 701 | .row-fluid .offset1 { 702 | margin-left: 11.32596685082873%; 703 | *margin-left: 11.219583872105325%; 704 | } 705 | .row-fluid .offset1:first-child { 706 | margin-left: 8.56353591160221%; 707 | *margin-left: 8.457152932878806%; 708 | } 709 | input, 710 | textarea, 711 | .uneditable-input { 712 | margin-left: 0; 713 | } 714 | .controls-row [class*="span"] + [class*="span"] { 715 | margin-left: 20px; 716 | } 717 | input.span12, 718 | textarea.span12, 719 | .uneditable-input.span12 { 720 | width: 710px; 721 | } 722 | input.span11, 723 | textarea.span11, 724 | .uneditable-input.span11 { 725 | width: 648px; 726 | } 727 | input.span10, 728 | textarea.span10, 729 | .uneditable-input.span10 { 730 | width: 586px; 731 | } 732 | input.span9, 733 | textarea.span9, 734 | .uneditable-input.span9 { 735 | width: 524px; 736 | } 737 | input.span8, 738 | textarea.span8, 739 | .uneditable-input.span8 { 740 | width: 462px; 741 | } 742 | input.span7, 743 | textarea.span7, 744 | .uneditable-input.span7 { 745 | width: 400px; 746 | } 747 | input.span6, 748 | textarea.span6, 749 | .uneditable-input.span6 { 750 | width: 338px; 751 | } 752 | input.span5, 753 | textarea.span5, 754 | .uneditable-input.span5 { 755 | width: 276px; 756 | } 757 | input.span4, 758 | textarea.span4, 759 | .uneditable-input.span4 { 760 | width: 214px; 761 | } 762 | input.span3, 763 | textarea.span3, 764 | .uneditable-input.span3 { 765 | width: 152px; 766 | } 767 | input.span2, 768 | textarea.span2, 769 | .uneditable-input.span2 { 770 | width: 90px; 771 | } 772 | input.span1, 773 | textarea.span1, 774 | .uneditable-input.span1 { 775 | width: 28px; 776 | } 777 | } 778 | 779 | @media (max-width: 767px) { 780 | body { 781 | padding-right: 20px; 782 | padding-left: 20px; 783 | } 784 | .navbar-fixed-top, 785 | .navbar-fixed-bottom, 786 | .navbar-static-top { 787 | margin-right: -20px; 788 | margin-left: -20px; 789 | } 790 | .container-fluid { 791 | padding: 0; 792 | } 793 | .dl-horizontal dt { 794 | float: none; 795 | width: auto; 796 | clear: none; 797 | text-align: left; 798 | } 799 | .dl-horizontal dd { 800 | margin-left: 0; 801 | } 802 | .container { 803 | width: auto; 804 | } 805 | .row-fluid { 806 | width: 100%; 807 | } 808 | .row, 809 | .thumbnails { 810 | margin-left: 0; 811 | } 812 | .thumbnails > li { 813 | float: none; 814 | margin-left: 0; 815 | } 816 | [class*="span"], 817 | .row-fluid [class*="span"] { 818 | display: block; 819 | float: none; 820 | width: 100%; 821 | margin-left: 0; 822 | -webkit-box-sizing: border-box; 823 | -moz-box-sizing: border-box; 824 | box-sizing: border-box; 825 | } 826 | .span12, 827 | .row-fluid .span12 { 828 | width: 100%; 829 | -webkit-box-sizing: border-box; 830 | -moz-box-sizing: border-box; 831 | box-sizing: border-box; 832 | } 833 | .input-large, 834 | .input-xlarge, 835 | .input-xxlarge, 836 | input[class*="span"], 837 | select[class*="span"], 838 | textarea[class*="span"], 839 | .uneditable-input { 840 | display: block; 841 | width: 100%; 842 | min-height: 30px; 843 | -webkit-box-sizing: border-box; 844 | -moz-box-sizing: border-box; 845 | box-sizing: border-box; 846 | } 847 | .input-prepend input, 848 | .input-append input, 849 | .input-prepend input[class*="span"], 850 | .input-append input[class*="span"] { 851 | display: inline-block; 852 | width: auto; 853 | } 854 | .controls-row [class*="span"] + [class*="span"] { 855 | margin-left: 0; 856 | } 857 | .modal { 858 | position: fixed; 859 | top: 20px; 860 | right: 20px; 861 | left: 20px; 862 | width: auto; 863 | margin: 0; 864 | } 865 | .modal.fade.in { 866 | top: auto; 867 | } 868 | } 869 | 870 | @media (max-width: 480px) { 871 | .nav-collapse { 872 | -webkit-transform: translate3d(0, 0, 0); 873 | } 874 | .page-header h1 small { 875 | display: block; 876 | line-height: 20px; 877 | } 878 | input[type="checkbox"], 879 | input[type="radio"] { 880 | border: 1px solid #ccc; 881 | } 882 | .form-horizontal .control-label { 883 | float: none; 884 | width: auto; 885 | padding-top: 0; 886 | text-align: left; 887 | } 888 | .form-horizontal .controls { 889 | margin-left: 0; 890 | } 891 | .form-horizontal .control-list { 892 | padding-top: 0; 893 | } 894 | .form-horizontal .form-actions { 895 | padding-right: 10px; 896 | padding-left: 10px; 897 | } 898 | .modal { 899 | top: 10px; 900 | right: 10px; 901 | left: 10px; 902 | } 903 | .modal-header .close { 904 | padding: 10px; 905 | margin: -10px; 906 | } 907 | .carousel-caption { 908 | position: static; 909 | } 910 | } 911 | 912 | @media (max-width: 979px) { 913 | body { 914 | padding-top: 0; 915 | } 916 | .navbar-fixed-top, 917 | .navbar-fixed-bottom { 918 | position: static; 919 | } 920 | .navbar-fixed-top { 921 | margin-bottom: 20px; 922 | } 923 | .navbar-fixed-bottom { 924 | margin-top: 20px; 925 | } 926 | .navbar-fixed-top .navbar-inner, 927 | .navbar-fixed-bottom .navbar-inner { 928 | padding: 5px; 929 | } 930 | .navbar .container { 931 | width: auto; 932 | padding: 0; 933 | } 934 | .navbar .brand { 935 | padding-right: 10px; 936 | padding-left: 10px; 937 | margin: 0 0 0 -5px; 938 | } 939 | .nav-collapse { 940 | clear: both; 941 | } 942 | .nav-collapse .nav { 943 | float: none; 944 | margin: 0 0 10px; 945 | } 946 | .nav-collapse .nav > li { 947 | float: none; 948 | } 949 | .nav-collapse .nav > li > a { 950 | margin-bottom: 2px; 951 | } 952 | .nav-collapse .nav > .divider-vertical { 953 | display: none; 954 | } 955 | .nav-collapse .nav .nav-header { 956 | color: #777777; 957 | text-shadow: none; 958 | } 959 | .nav-collapse .nav > li > a, 960 | .nav-collapse .dropdown-menu a { 961 | padding: 9px 15px; 962 | font-weight: bold; 963 | color: #777777; 964 | -webkit-border-radius: 3px; 965 | -moz-border-radius: 3px; 966 | border-radius: 3px; 967 | } 968 | .nav-collapse .btn { 969 | padding: 4px 10px 4px; 970 | font-weight: normal; 971 | -webkit-border-radius: 4px; 972 | -moz-border-radius: 4px; 973 | border-radius: 4px; 974 | } 975 | .nav-collapse .dropdown-menu li + li a { 976 | margin-bottom: 2px; 977 | } 978 | .nav-collapse .nav > li > a:hover, 979 | .nav-collapse .dropdown-menu a:hover { 980 | background-color: #f2f2f2; 981 | } 982 | .navbar-inverse .nav-collapse .nav > li > a:hover, 983 | .navbar-inverse .nav-collapse .dropdown-menu a:hover { 984 | background-color: #111111; 985 | } 986 | .nav-collapse.in .btn-group { 987 | padding: 0; 988 | margin-top: 5px; 989 | } 990 | .nav-collapse .dropdown-menu { 991 | position: static; 992 | top: auto; 993 | left: auto; 994 | display: block; 995 | float: none; 996 | max-width: none; 997 | padding: 0; 998 | margin: 0 15px; 999 | background-color: transparent; 1000 | border: none; 1001 | -webkit-border-radius: 0; 1002 | -moz-border-radius: 0; 1003 | border-radius: 0; 1004 | -webkit-box-shadow: none; 1005 | -moz-box-shadow: none; 1006 | box-shadow: none; 1007 | } 1008 | .nav-collapse .dropdown-menu:before, 1009 | .nav-collapse .dropdown-menu:after { 1010 | display: none; 1011 | } 1012 | .nav-collapse .dropdown-menu .divider { 1013 | display: none; 1014 | } 1015 | .nav-collapse .nav > li > .dropdown-menu:before, 1016 | .nav-collapse .nav > li > .dropdown-menu:after { 1017 | display: none; 1018 | } 1019 | .nav-collapse .navbar-form, 1020 | .nav-collapse .navbar-search { 1021 | float: none; 1022 | padding: 10px 15px; 1023 | margin: 10px 0; 1024 | border-top: 1px solid #f2f2f2; 1025 | border-bottom: 1px solid #f2f2f2; 1026 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); 1027 | -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); 1028 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); 1029 | } 1030 | .navbar-inverse .nav-collapse .navbar-form, 1031 | .navbar-inverse .nav-collapse .navbar-search { 1032 | border-top-color: #111111; 1033 | border-bottom-color: #111111; 1034 | } 1035 | .navbar .nav-collapse .nav.pull-right { 1036 | float: none; 1037 | margin-left: 0; 1038 | } 1039 | .nav-collapse, 1040 | .nav-collapse.collapse { 1041 | height: 0; 1042 | overflow: hidden; 1043 | } 1044 | .navbar .btn-navbar { 1045 | display: block; 1046 | } 1047 | .navbar-static .navbar-inner { 1048 | padding-right: 10px; 1049 | padding-left: 10px; 1050 | } 1051 | } 1052 | 1053 | @media (min-width: 980px) { 1054 | .nav-collapse.collapse { 1055 | height: auto !important; 1056 | overflow: visible !important; 1057 | } 1058 | } 1059 | -------------------------------------------------------------------------------- /static/css/bootstrap-responsive.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Responsive v2.1.1 3 | * 4 | * Copyright 2012 Twitter, Inc 5 | * Licensed under the Apache License v2.0 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Designed and built with all the love in the world @twitter by @mdo and @fat. 9 | */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%}.row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:30px}input.span12,textarea.span12,.uneditable-input.span12{width:1156px}input.span11,textarea.span11,.uneditable-input.span11{width:1056px}input.span10,textarea.span10,.uneditable-input.span10{width:956px}input.span9,textarea.span9,.uneditable-input.span9{width:856px}input.span8,textarea.span8,.uneditable-input.span8{width:756px}input.span7,textarea.span7,.uneditable-input.span7{width:656px}input.span6,textarea.span6,.uneditable-input.span6{width:556px}input.span5,textarea.span5,.uneditable-input.span5{width:456px}input.span4,textarea.span4,.uneditable-input.span4{width:356px}input.span3,textarea.span3,.uneditable-input.span3{width:256px}input.span2,textarea.span2,.uneditable-input.span2{width:156px}input.span1,textarea.span1,.uneditable-input.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%}.row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%}.row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%}.row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%}.row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%}.row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:710px}input.span11,textarea.span11,.uneditable-input.span11{width:648px}input.span10,textarea.span10,.uneditable-input.span10{width:586px}input.span9,textarea.span9,.uneditable-input.span9{width:524px}input.span8,textarea.span8,.uneditable-input.span8{width:462px}input.span7,textarea.span7,.uneditable-input.span7{width:400px}input.span6,textarea.span6,.uneditable-input.span6{width:338px}input.span5,textarea.span5,.uneditable-input.span5{width:276px}input.span4,textarea.span4,.uneditable-input.span4{width:214px}input.span3,textarea.span3,.uneditable-input.span3{width:152px}input.span2,textarea.span2,.uneditable-input.span2{width:90px}input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}.controls-row [class*="span"]+[class*="span"]{margin-left:0}.modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.modal.fade.in{top:auto}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.modal{top:10px;right:10px;left:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#777;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .dropdown-menu a:hover{background-color:#f2f2f2}.navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:hover{background-color:#111}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:block;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}} 10 | -------------------------------------------------------------------------------- /static/css/code.css: -------------------------------------------------------------------------------- 1 | .codehilite .hll { background-color: #ffffcc } 2 | .codehilite { background: #f8f8f8; } 3 | .codehilite .c { color: #408080; font-style: italic } /* Comment */ 4 | .codehilite .err { border: 1px solid #FF0000 } /* Error */ 5 | .codehilite .k { color: #008000; font-weight: bold } /* Keyword */ 6 | .codehilite .o { color: #666666 } /* Operator */ 7 | .codehilite .cm { color: #408080; font-style: italic } /* Comment.Multiline */ 8 | .codehilite .cp { color: #BC7A00 } /* Comment.Preproc */ 9 | .codehilite .c1 { color: #408080; font-style: italic } /* Comment.Single */ 10 | .codehilite .cs { color: #408080; font-style: italic } /* Comment.Special */ 11 | .codehilite .gd { color: #A00000 } /* Generic.Deleted */ 12 | .codehilite .ge { font-style: italic } /* Generic.Emph */ 13 | .codehilite .gr { color: #FF0000 } /* Generic.Error */ 14 | .codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 15 | .codehilite .gi { color: #00A000 } /* Generic.Inserted */ 16 | .codehilite .go { color: #808080 } /* Generic.Output */ 17 | .codehilite .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ 18 | .codehilite .gs { font-weight: bold } /* Generic.Strong */ 19 | .codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 20 | .codehilite .gt { color: #0040D0 } /* Generic.Traceback */ 21 | .codehilite .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ 22 | .codehilite .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ 23 | .codehilite .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ 24 | .codehilite .kp { color: #008000 } /* Keyword.Pseudo */ 25 | .codehilite .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ 26 | .codehilite .kt { color: #B00040 } /* Keyword.Type */ 27 | .codehilite .m { color: #666666 } /* Literal.Number */ 28 | .codehilite .s { color: #BA2121 } /* Literal.String */ 29 | .codehilite .na { color: #7D9029 } /* Name.Attribute */ 30 | .codehilite .nb { color: #008000 } /* Name.Builtin */ 31 | .codehilite .nc { color: #0000FF; font-weight: bold } /* Name.Class */ 32 | .codehilite .no { color: #880000 } /* Name.Constant */ 33 | .codehilite .nd { color: #AA22FF } /* Name.Decorator */ 34 | .codehilite .ni { color: #999999; font-weight: bold } /* Name.Entity */ 35 | .codehilite .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ 36 | .codehilite .nf { color: #0000FF } /* Name.Function */ 37 | .codehilite .nl { color: #A0A000 } /* Name.Label */ 38 | .codehilite .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ 39 | .codehilite .nt { color: #008000; font-weight: bold } /* Name.Tag */ 40 | .codehilite .nv { color: #19177C } /* Name.Variable */ 41 | .codehilite .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ 42 | .codehilite .w { color: #bbbbbb } /* Text.Whitespace */ 43 | .codehilite .mf { color: #666666 } /* Literal.Number.Float */ 44 | .codehilite .mh { color: #666666 } /* Literal.Number.Hex */ 45 | .codehilite .mi { color: #666666 } /* Literal.Number.Integer */ 46 | .codehilite .mo { color: #666666 } /* Literal.Number.Oct */ 47 | .codehilite .sb { color: #BA2121 } /* Literal.String.Backtick */ 48 | .codehilite .sc { color: #BA2121 } /* Literal.String.Char */ 49 | .codehilite .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ 50 | .codehilite .s2 { color: #BA2121 } /* Literal.String.Double */ 51 | .codehilite .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ 52 | .codehilite .sh { color: #BA2121 } /* Literal.String.Heredoc */ 53 | .codehilite .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ 54 | .codehilite .sx { color: #008000 } /* Literal.String.Other */ 55 | .codehilite .sr { color: #BB6688 } /* Literal.String.Regex */ 56 | .codehilite .s1 { color: #BA2121 } /* Literal.String.Single */ 57 | .codehilite .ss { color: #19177C } /* Literal.String.Symbol */ 58 | .codehilite .bp { color: #008000 } /* Name.Builtin.Pseudo */ 59 | .codehilite .vc { color: #19177C } /* Name.Variable.Class */ 60 | .codehilite .vg { color: #19177C } /* Name.Variable.Global */ 61 | .codehilite .vi { color: #19177C } /* Name.Variable.Instance */ 62 | .codehilite .il { color: #666666 } /* Literal.Number.Integer.Long */ 63 | -------------------------------------------------------------------------------- /static/css/reset.css: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | /** 3 | * Author:airenLiao 4 | * Blog: http://www.w3cplus.com 5 | */ 6 | body,ul,ol,dd{ 7 | margin:0; 8 | padding:0; 9 | } 10 | a:hover { 11 | text-decoration: none; 12 | } 13 | table { 14 | border-collapse:collapse; 15 | border-spacing:0; 16 | } 17 | article ol, article ul { 18 | padding-left: 20px; 19 | } 20 | ol.errorlist, ul.errorlist { 21 | list-style: none outside none; 22 | } 23 | 24 | article, aside, dialog, figure, footer, header,hgroup, nav, section { 25 | display:block; 26 | } 27 | -------------------------------------------------------------------------------- /static/css/style.css: -------------------------------------------------------------------------------- 1 | /*header*/ 2 | .nav .new-wrapper { 3 | position: relative; 4 | float: left; 5 | } 6 | 7 | i { 8 | display: inline-block; 9 | zoom: 1; 10 | vertical-align: text-top; 11 | background-image: url(../img/twitter_web_sprite_icons.png); 12 | background-position: 0 0; 13 | background-repeat: no-repeat; 14 | } 15 | .nav i { 16 | float: left; 17 | margin: -1px 6px 0 0; 18 | } 19 | 20 | .nav-home, .nav-topics, .nav-people, .nav-me, .nav-tweet { 21 | height: 22px; 22 | } 23 | 24 | .nav .active .nav-new{ 25 | display: block; 26 | } 27 | .nav-new { 28 | background-position: -200px -80px; 29 | width: 24px; 30 | height: 3px; 31 | } 32 | .nav-home { 33 | background-position: 0 -50px; 34 | width: 21px; 35 | } 36 | a:hover .nav-home { 37 | background-position: 0 -80px; 38 | } 39 | .active .nav-home, 40 | .active a:hover .nav-home { 41 | background-position: 0 -110px; 42 | } 43 | .nav-people { 44 | background-position: -80px -50px; 45 | width: 21px; 46 | } 47 | a:hover .nav-people { 48 | background-position: -80px -80px; 49 | } 50 | .active .nav-people, 51 | .active a:hover .nav-people { 52 | background-position: -80px -110px; 53 | } 54 | .nav-me { 55 | background-position: -120px -50px; 56 | width: 21px; 57 | } 58 | a:hover .nav-me { 59 | background-position: -120px -80px; 60 | } 61 | .active .nav-me, 62 | .active a:hover .nav-me { 63 | background-position: -120px -110px; 64 | } 65 | .nav .nav-new { 66 | position: absolute; 67 | top: 26px; 68 | left: 50%; 69 | display: none; 70 | height: 3px; 71 | margin-left: -14px; 72 | line-height: 1; 73 | text-align: center; 74 | } 75 | 76 | .sbrand{ 77 | position: absolute; 78 | top: 0; 79 | font-size: 20px; 80 | padding-top:10px; 81 | left: 45%; 82 | color: #000; 83 | font-weight: bold; 84 | } 85 | 86 | .nav-session { 87 | background-position: -160px -50px; 88 | width: 20px; 89 | height: 21px; 90 | } 91 | .nav-tweet { 92 | background-position: -200px -50px; 93 | width: 22px; 94 | height: 18px; 95 | } 96 | 97 | #myModal{ 98 | display: none; 99 | } 100 | 101 | hr.soften { 102 | clear: both; 103 | float: none; 104 | width: 100%; 105 | height: 1px; 106 | line-height: 1px; 107 | font-size: 0; 108 | border: none 0; 109 | margin: 5px 0; 110 | border: none; 111 | background: #ddd; 112 | background-image: -webkit-gradient(linear,left bottom,right bottom,color-stop(0, rgb(255,255,255)), color-stop(0.1, rgb(221,221,221)),color-stop(0.9, rgb(221,221,221)),color-stop(1, rgb(255,255,255))); 113 | background-image: -webkit-linear-gradient(left center,rgb(255,255,255) 0%,rgb(221,221,221) 10%,rgb(221,221,221) 90%,rgb(255,255,255) 100%); 114 | background-image: -moz-linear-gradient(left center,rgb(255,255,255) 0%,rgb(221,221,221) 10%,rgb(221,221,221) 90%,rgb(255,255,255) 100%); 115 | background-image: -o-linear-gradient(left center,rgb(255,255,255) 0%,rgb(221,221,221) 10%,rgb(221,221,221) 90%,rgb(255,255,255) 100%); 116 | } 117 | 118 | #cmt p{ 119 | margin: 2px 0; 120 | } 121 | 122 | .none-padding{ 123 | padding-left: 0; 124 | } 125 | 126 | .gravatar{ 127 | width: 40px; 128 | height: 40px 129 | } 130 | 131 | h1, h2, h3, h4, h5, h6{ 132 | margin: 5px 0; 133 | } 134 | #cmt h2{ 135 | font-size: 16px; 136 | line-height: 20px; 137 | } 138 | .comtop{ 139 | margin-top: 20px; 140 | } 141 | .post-info{ 142 | padding: 0; 143 | } 144 | .blog-content{ 145 | margin: 20px 0; 146 | } 147 | form fieldset label { 148 | width: 100px; 149 | margin: 4px 0 5px 0; 150 | font-weight: bold; 151 | } 152 | .alert-error{ 153 | width: 65%; 154 | } 155 | 156 | form textarea{ 157 | display: block; 158 | width: 95%; 159 | height: 400px; 160 | padding: 5px; 161 | font-size: 14px; 162 | resize: vertical; 163 | } 164 | 165 | /*add blog form*/ 166 | .field label{ 167 | display: block; 168 | margin: 0 0 5px 0; 169 | font-weight: bold; 170 | } 171 | .field input{ 172 | width: 70%; 173 | } 174 | /* end add blog*/ 175 | 176 | .btn-tweet { 177 | padding: 3px 4px 5px 10px; 178 | } 179 | 180 | textarea.twitter{ 181 | width: 512px; 182 | height: 64px; 183 | overflow: hidden; 184 | padding-bottom: 5px; 185 | resize: vertical; 186 | } 187 | 188 | .twitter-modal-header{ 189 | border: none; 190 | } 191 | .twitter-modal-header h3{ 192 | font-size: 18px; 193 | line-height: 24px; 194 | font-weight: bold; 195 | } 196 | .twitter-modal-body{ 197 | padding: 0 15px; 198 | } 199 | 200 | .twitter-modal-footer{ 201 | border: none; 202 | padding-top: 10px; 203 | } 204 | 205 | textarea.comment{ 206 | height: 160px; 207 | width: 70%; 208 | } -------------------------------------------------------------------------------- /static/img/defaultavatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gusibi/sblog/45f92e574878dabd1d92d0f3bd5eb85144344313/static/img/defaultavatar.png -------------------------------------------------------------------------------- /static/img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gusibi/sblog/45f92e574878dabd1d92d0f3bd5eb85144344313/static/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /static/img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gusibi/sblog/45f92e574878dabd1d92d0f3bd5eb85144344313/static/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /static/img/twitter_web_sprite_icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gusibi/sblog/45f92e574878dabd1d92d0f3bd5eb85144344313/static/img/twitter_web_sprite_icons.png -------------------------------------------------------------------------------- /static/js/ajaxpost.js: -------------------------------------------------------------------------------- 1 | $(document).ajaxSend(function(event, xhr, settings) { 2 | function getCookie(name) { 3 | var cookieValue = null; 4 | if (document.cookie && document.cookie != '') { 5 | var cookies = document.cookie.split(';'); 6 | for (var i = 0; i < cookies.length; i++) { 7 | var cookie = jQuery.trim(cookies[i]); 8 | // Does this cookie string begin with the name we want? 9 | if (cookie.substring(0, name.length + 1) == (name + '=')) { 10 | cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); 11 | break; 12 | } 13 | } 14 | } 15 | return cookieValue; 16 | } 17 | function sameOrigin(url) { 18 | // url could be relative or scheme relative or absolute 19 | var host = document.location.host; // host + port 20 | var protocol = document.location.protocol; 21 | var sr_origin = '//' + host; 22 | var origin = protocol + sr_origin; 23 | // Allow absolute or scheme relative URLs to same origin 24 | return (url == origin || url.slice(0, origin.length + 1) == origin + '/') || 25 | (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') || 26 | // or any other URL that isn't scheme relative or absolute i.e relative. 27 | !(/^(\/\/|http:|https:).*/.test(url)); 28 | } 29 | function safeMethod(method) { 30 | return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); 31 | } 32 | 33 | if (!safeMethod(settings.type) && sameOrigin(settings.url)) { 34 | xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken')); 35 | } 36 | }); -------------------------------------------------------------------------------- /static/js/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap.js by @fat & @mdo 3 | * Copyright 2012 Twitter, Inc. 4 | * http://www.apache.org/licenses/LICENSE-2.0.txt 5 | */ 6 | !function(e){e(function(){"use strict";e.support.transition=function(){var e=function(){var e=document.createElement("bootstrap"),t={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},n;for(n in t)if(e.style[n]!==undefined)return t[n]}();return e&&{end:e}}()})}(window.jQuery),!function(e){"use strict";var t='[data-dismiss="alert"]',n=function(n){e(n).on("click",t,this.close)};n.prototype.close=function(t){function s(){i.trigger("closed").remove()}var n=e(this),r=n.attr("data-target"),i;r||(r=n.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,"")),i=e(r),t&&t.preventDefault(),i.length||(i=n.hasClass("alert")?n:n.parent()),i.trigger(t=e.Event("close"));if(t.isDefaultPrevented())return;i.removeClass("in"),e.support.transition&&i.hasClass("fade")?i.on(e.support.transition.end,s):s()},e.fn.alert=function(t){return this.each(function(){var r=e(this),i=r.data("alert");i||r.data("alert",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.alert.Constructor=n,e(function(){e("body").on("click.alert.data-api",t,n.prototype.close)})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.button.defaults,n)};t.prototype.setState=function(e){var t="disabled",n=this.$element,r=n.data(),i=n.is("input")?"val":"html";e+="Text",r.resetText||n.data("resetText",n[i]()),n[i](r[e]||this.options[e]),setTimeout(function(){e=="loadingText"?n.addClass(t).attr(t,t):n.removeClass(t).removeAttr(t)},0)},t.prototype.toggle=function(){var e=this.$element.closest('[data-toggle="buttons-radio"]');e&&e.find(".active").removeClass("active"),this.$element.toggleClass("active")},e.fn.button=function(n){return this.each(function(){var r=e(this),i=r.data("button"),s=typeof n=="object"&&n;i||r.data("button",i=new t(this,s)),n=="toggle"?i.toggle():n&&i.setState(n)})},e.fn.button.defaults={loadingText:"loading..."},e.fn.button.Constructor=t,e(function(){e("body").on("click.button.data-api","[data-toggle^=button]",function(t){var n=e(t.target);n.hasClass("btn")||(n=n.closest(".btn")),n.button("toggle")})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=n,this.options.slide&&this.slide(this.options.slide),this.options.pause=="hover"&&this.$element.on("mouseenter",e.proxy(this.pause,this)).on("mouseleave",e.proxy(this.cycle,this))};t.prototype={cycle:function(t){return t||(this.paused=!1),this.options.interval&&!this.paused&&(this.interval=setInterval(e.proxy(this.next,this),this.options.interval)),this},to:function(t){var n=this.$element.find(".item.active"),r=n.parent().children(),i=r.index(n),s=this;if(t>r.length-1||t<0)return;return this.sliding?this.$element.one("slid",function(){s.to(t)}):i==t?this.pause().cycle():this.slide(t>i?"next":"prev",e(r[t]))},pause:function(t){return t||(this.paused=!0),this.$element.find(".next, .prev").length&&e.support.transition.end&&(this.$element.trigger(e.support.transition.end),this.cycle()),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(t,n){var r=this.$element.find(".item.active"),i=n||r[t](),s=this.interval,o=t=="next"?"left":"right",u=t=="next"?"first":"last",a=this,f=e.Event("slide",{relatedTarget:i[0]});this.sliding=!0,s&&this.pause(),i=i.length?i:this.$element.find(".item")[u]();if(i.hasClass("active"))return;if(e.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(f);if(f.isDefaultPrevented())return;i.addClass(t),i[0].offsetWidth,r.addClass(o),i.addClass(o),this.$element.one(e.support.transition.end,function(){i.removeClass([t,o].join(" ")).addClass("active"),r.removeClass(["active",o].join(" ")),a.sliding=!1,setTimeout(function(){a.$element.trigger("slid")},0)})}else{this.$element.trigger(f);if(f.isDefaultPrevented())return;r.removeClass("active"),i.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return s&&this.cycle(),this}},e.fn.carousel=function(n){return this.each(function(){var r=e(this),i=r.data("carousel"),s=e.extend({},e.fn.carousel.defaults,typeof n=="object"&&n),o=typeof n=="string"?n:s.slide;i||r.data("carousel",i=new t(this,s)),typeof n=="number"?i.to(n):o?i[o]():s.interval&&i.cycle()})},e.fn.carousel.defaults={interval:5e3,pause:"hover"},e.fn.carousel.Constructor=t,e(function(){e("body").on("click.carousel.data-api","[data-slide]",function(t){var n=e(this),r,i=e(n.attr("data-target")||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,"")),s=!i.data("modal")&&e.extend({},i.data(),n.data());i.carousel(s),t.preventDefault()})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.collapse.defaults,n),this.options.parent&&(this.$parent=e(this.options.parent)),this.options.toggle&&this.toggle()};t.prototype={constructor:t,dimension:function(){var e=this.$element.hasClass("width");return e?"width":"height"},show:function(){var t,n,r,i;if(this.transitioning)return;t=this.dimension(),n=e.camelCase(["scroll",t].join("-")),r=this.$parent&&this.$parent.find("> .accordion-group > .in");if(r&&r.length){i=r.data("collapse");if(i&&i.transitioning)return;r.collapse("hide"),i||r.data("collapse",null)}this.$element[t](0),this.transition("addClass",e.Event("show"),"shown"),e.support.transition&&this.$element[t](this.$element[0][n])},hide:function(){var t;if(this.transitioning)return;t=this.dimension(),this.reset(this.$element[t]()),this.transition("removeClass",e.Event("hide"),"hidden"),this.$element[t](0)},reset:function(e){var t=this.dimension();return this.$element.removeClass("collapse")[t](e||"auto")[0].offsetWidth,this.$element[e!==null?"addClass":"removeClass"]("collapse"),this},transition:function(t,n,r){var i=this,s=function(){n.type=="show"&&i.reset(),i.transitioning=0,i.$element.trigger(r)};this.$element.trigger(n);if(n.isDefaultPrevented())return;this.transitioning=1,this.$element[t]("in"),e.support.transition&&this.$element.hasClass("collapse")?this.$element.one(e.support.transition.end,s):s()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}},e.fn.collapse=function(n){return this.each(function(){var r=e(this),i=r.data("collapse"),s=typeof n=="object"&&n;i||r.data("collapse",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.collapse.defaults={toggle:!0},e.fn.collapse.Constructor=t,e(function(){e("body").on("click.collapse.data-api","[data-toggle=collapse]",function(t){var n=e(this),r,i=n.attr("data-target")||t.preventDefault()||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,""),s=e(i).data("collapse")?"toggle":n.data();n[e(i).hasClass("in")?"addClass":"removeClass"]("collapsed"),e(i).collapse(s)})})}(window.jQuery),!function(e){"use strict";function r(){i(e(t)).removeClass("open")}function i(t){var n=t.attr("data-target"),r;return n||(n=t.attr("href"),n=n&&/#/.test(n)&&n.replace(/.*(?=#[^\s]*$)/,"")),r=e(n),r.length||(r=t.parent()),r}var t="[data-toggle=dropdown]",n=function(t){var n=e(t).on("click.dropdown.data-api",this.toggle);e("html").on("click.dropdown.data-api",function(){n.parent().removeClass("open")})};n.prototype={constructor:n,toggle:function(t){var n=e(this),s,o;if(n.is(".disabled, :disabled"))return;return s=i(n),o=s.hasClass("open"),r(),o||(s.toggleClass("open"),n.focus()),!1},keydown:function(t){var n,r,s,o,u,a;if(!/(38|40|27)/.test(t.keyCode))return;n=e(this),t.preventDefault(),t.stopPropagation();if(n.is(".disabled, :disabled"))return;o=i(n),u=o.hasClass("open");if(!u||u&&t.keyCode==27)return n.click();r=e("[role=menu] li:not(.divider) a",o);if(!r.length)return;a=r.index(r.filter(":focus")),t.keyCode==38&&a>0&&a--,t.keyCode==40&&a').appendTo(document.body),this.options.backdrop!="static"&&this.$backdrop.click(e.proxy(this.hide,this)),i&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),i?this.$backdrop.one(e.support.transition.end,t):t()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),e.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(e.support.transition.end,e.proxy(this.removeBackdrop,this)):this.removeBackdrop()):t&&t()}},e.fn.modal=function(n){return this.each(function(){var r=e(this),i=r.data("modal"),s=e.extend({},e.fn.modal.defaults,r.data(),typeof n=="object"&&n);i||r.data("modal",i=new t(this,s)),typeof n=="string"?i[n]():s.show&&i.show()})},e.fn.modal.defaults={backdrop:!0,keyboard:!0,show:!0},e.fn.modal.Constructor=t,e(function(){e("body").on("click.modal.data-api",'[data-toggle="modal"]',function(t){var n=e(this),r=n.attr("href"),i=e(n.attr("data-target")||r&&r.replace(/.*(?=#[^\s]+$)/,"")),s=i.data("modal")?"toggle":e.extend({remote:!/#/.test(r)&&r},i.data(),n.data());t.preventDefault(),i.modal(s).one("hide",function(){n.focus()})})})}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("tooltip",e,t)};t.prototype={constructor:t,init:function(t,n,r){var i,s;this.type=t,this.$element=e(n),this.options=this.getOptions(r),this.enabled=!0,this.options.trigger=="click"?this.$element.on("click."+this.type,this.options.selector,e.proxy(this.toggle,this)):this.options.trigger!="manual"&&(i=this.options.trigger=="hover"?"mouseenter":"focus",s=this.options.trigger=="hover"?"mouseleave":"blur",this.$element.on(i+"."+this.type,this.options.selector,e.proxy(this.enter,this)),this.$element.on(s+"."+this.type,this.options.selector,e.proxy(this.leave,this))),this.options.selector?this._options=e.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(t){return t=e.extend({},e.fn[this.type].defaults,t,this.$element.data()),t.delay&&typeof t.delay=="number"&&(t.delay={show:t.delay,hide:t.delay}),t},enter:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);if(!n.options.delay||!n.options.delay.show)return n.show();clearTimeout(this.timeout),n.hoverState="in",this.timeout=setTimeout(function(){n.hoverState=="in"&&n.show()},n.options.delay.show)},leave:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);this.timeout&&clearTimeout(this.timeout);if(!n.options.delay||!n.options.delay.hide)return n.hide();n.hoverState="out",this.timeout=setTimeout(function(){n.hoverState=="out"&&n.hide()},n.options.delay.hide)},show:function(){var e,t,n,r,i,s,o;if(this.hasContent()&&this.enabled){e=this.tip(),this.setContent(),this.options.animation&&e.addClass("fade"),s=typeof this.options.placement=="function"?this.options.placement.call(this,e[0],this.$element[0]):this.options.placement,t=/in/.test(s),e.remove().css({top:0,left:0,display:"block"}).appendTo(t?this.$element:document.body),n=this.getPosition(t),r=e[0].offsetWidth,i=e[0].offsetHeight;switch(t?s.split(" ")[1]:s){case"bottom":o={top:n.top+n.height,left:n.left+n.width/2-r/2};break;case"top":o={top:n.top-i,left:n.left+n.width/2-r/2};break;case"left":o={top:n.top+n.height/2-i/2,left:n.left-r};break;case"right":o={top:n.top+n.height/2-i/2,left:n.left+n.width}}e.css(o).addClass(s).addClass("in")}},setContent:function(){var e=this.tip(),t=this.getTitle();e.find(".tooltip-inner")[this.options.html?"html":"text"](t),e.removeClass("fade in top bottom left right")},hide:function(){function r(){var t=setTimeout(function(){n.off(e.support.transition.end).remove()},500);n.one(e.support.transition.end,function(){clearTimeout(t),n.remove()})}var t=this,n=this.tip();return n.removeClass("in"),e.support.transition&&this.$tip.hasClass("fade")?r():n.remove(),this},fixTitle:function(){var e=this.$element;(e.attr("title")||typeof e.attr("data-original-title")!="string")&&e.attr("data-original-title",e.attr("title")||"").removeAttr("title")},hasContent:function(){return this.getTitle()},getPosition:function(t){return e.extend({},t?{top:0,left:0}:this.$element.offset(),{width:this.$element[0].offsetWidth,height:this.$element[0].offsetHeight})},getTitle:function(){var e,t=this.$element,n=this.options;return e=t.attr("data-original-title")||(typeof n.title=="function"?n.title.call(t[0]):n.title),e},tip:function(){return this.$tip=this.$tip||e(this.options.template)},validate:function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(){this[this.tip().hasClass("in")?"hide":"show"]()},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}},e.fn.tooltip=function(n){return this.each(function(){var r=e(this),i=r.data("tooltip"),s=typeof n=="object"&&n;i||r.data("tooltip",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.tooltip.Constructor=t,e.fn.tooltip.defaults={animation:!0,placement:"top",selector:!1,template:'
',trigger:"hover",title:"",delay:0,html:!0}}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("popover",e,t)};t.prototype=e.extend({},e.fn.tooltip.Constructor.prototype,{constructor:t,setContent:function(){var e=this.tip(),t=this.getTitle(),n=this.getContent();e.find(".popover-title")[this.options.html?"html":"text"](t),e.find(".popover-content > *")[this.options.html?"html":"text"](n),e.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var e,t=this.$element,n=this.options;return e=t.attr("data-content")||(typeof n.content=="function"?n.content.call(t[0]):n.content),e},tip:function(){return this.$tip||(this.$tip=e(this.options.template)),this.$tip},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}}),e.fn.popover=function(n){return this.each(function(){var r=e(this),i=r.data("popover"),s=typeof n=="object"&&n;i||r.data("popover",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.popover.Constructor=t,e.fn.popover.defaults=e.extend({},e.fn.tooltip.defaults,{placement:"right",trigger:"click",content:"",template:'

'})}(window.jQuery),!function(e){"use strict";function t(t,n){var r=e.proxy(this.process,this),i=e(t).is("body")?e(window):e(t),s;this.options=e.extend({},e.fn.scrollspy.defaults,n),this.$scrollElement=i.on("scroll.scroll-spy.data-api",r),this.selector=(this.options.target||(s=e(t).attr("href"))&&s.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.$body=e("body"),this.refresh(),this.process()}t.prototype={constructor:t,refresh:function(){var t=this,n;this.offsets=e([]),this.targets=e([]),n=this.$body.find(this.selector).map(function(){var t=e(this),n=t.data("target")||t.attr("href"),r=/^#\w/.test(n)&&e(n);return r&&r.length&&[[r.position().top,n]]||null}).sort(function(e,t){return e[0]-t[0]}).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},process:function(){var e=this.$scrollElement.scrollTop()+this.options.offset,t=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,n=t-this.$scrollElement.height(),r=this.offsets,i=this.targets,s=this.activeTarget,o;if(e>=n)return s!=(o=i.last()[0])&&this.activate(o);for(o=r.length;o--;)s!=i[o]&&e>=r[o]&&(!r[o+1]||e<=r[o+1])&&this.activate(i[o])},activate:function(t){var n,r;this.activeTarget=t,e(this.selector).parent(".active").removeClass("active"),r=this.selector+'[data-target="'+t+'"],'+this.selector+'[href="'+t+'"]',n=e(r).parent("li").addClass("active"),n.parent(".dropdown-menu").length&&(n=n.closest("li.dropdown").addClass("active")),n.trigger("activate")}},e.fn.scrollspy=function(n){return this.each(function(){var r=e(this),i=r.data("scrollspy"),s=typeof n=="object"&&n;i||r.data("scrollspy",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.scrollspy.Constructor=t,e.fn.scrollspy.defaults={offset:10},e(window).on("load",function(){e('[data-spy="scroll"]').each(function(){var t=e(this);t.scrollspy(t.data())})})}(window.jQuery),!function(e){"use strict";var t=function(t){this.element=e(t)};t.prototype={constructor:t,show:function(){var t=this.element,n=t.closest("ul:not(.dropdown-menu)"),r=t.attr("data-target"),i,s,o;r||(r=t.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,""));if(t.parent("li").hasClass("active"))return;i=n.find(".active a").last()[0],o=e.Event("show",{relatedTarget:i}),t.trigger(o);if(o.isDefaultPrevented())return;s=e(r),this.activate(t.parent("li"),n),this.activate(s,s.parent(),function(){t.trigger({type:"shown",relatedTarget:i})})},activate:function(t,n,r){function o(){i.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),t.addClass("active"),s?(t[0].offsetWidth,t.addClass("in")):t.removeClass("fade"),t.parent(".dropdown-menu")&&t.closest("li.dropdown").addClass("active"),r&&r()}var i=n.find("> .active"),s=r&&e.support.transition&&i.hasClass("fade");s?i.one(e.support.transition.end,o):o(),i.removeClass("in")}},e.fn.tab=function(n){return this.each(function(){var r=e(this),i=r.data("tab");i||r.data("tab",i=new t(this)),typeof n=="string"&&i[n]()})},e.fn.tab.Constructor=t,e(function(){e("body").on("click.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(t){t.preventDefault(),e(this).tab("show")})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.typeahead.defaults,n),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.$menu=e(this.options.menu).appendTo("body"),this.source=this.options.source,this.shown=!1,this.listen()};t.prototype={constructor:t,select:function(){var e=this.$menu.find(".active").attr("data-value");return this.$element.val(this.updater(e)).change(),this.hide()},updater:function(e){return e},show:function(){var t=e.extend({},this.$element.offset(),{height:this.$element[0].offsetHeight});return this.$menu.css({top:t.top+t.height,left:t.left}),this.$menu.show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(t){var n;return this.query=this.$element.val(),!this.query||this.query.length"+t+""})},render:function(t){var n=this;return t=e(t).map(function(t,r){return t=e(n.options.item).attr("data-value",r),t.find("a").html(n.highlighter(r)),t[0]}),t.first().addClass("active"),this.$menu.html(t),this},next:function(t){var n=this.$menu.find(".active").removeClass("active"),r=n.next();r.length||(r=e(this.$menu.find("li")[0])),r.addClass("active")},prev:function(e){var t=this.$menu.find(".active").removeClass("active"),n=t.prev();n.length||(n=this.$menu.find("li").last()),n.addClass("active")},listen:function(){this.$element.on("blur",e.proxy(this.blur,this)).on("keypress",e.proxy(this.keypress,this)).on("keyup",e.proxy(this.keyup,this)),(e.browser.chrome||e.browser.webkit||e.browser.msie)&&this.$element.on("keydown",e.proxy(this.keydown,this)),this.$menu.on("click",e.proxy(this.click,this)).on("mouseenter","li",e.proxy(this.mouseenter,this))},move:function(e){if(!this.shown)return;switch(e.keyCode){case 9:case 13:case 27:e.preventDefault();break;case 38:e.preventDefault(),this.prev();break;case 40:e.preventDefault(),this.next()}e.stopPropagation()},keydown:function(t){this.suppressKeyPressRepeat=!~e.inArray(t.keyCode,[40,38,9,13,27]),this.move(t)},keypress:function(e){if(this.suppressKeyPressRepeat)return;this.move(e)},keyup:function(e){switch(e.keyCode){case 40:case 38:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}e.stopPropagation(),e.preventDefault()},blur:function(e){var t=this;setTimeout(function(){t.hide()},150)},click:function(e){e.stopPropagation(),e.preventDefault(),this.select()},mouseenter:function(t){this.$menu.find(".active").removeClass("active"),e(t.currentTarget).addClass("active")}},e.fn.typeahead=function(n){return this.each(function(){var r=e(this),i=r.data("typeahead"),s=typeof n=="object"&&n;i||r.data("typeahead",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.typeahead.defaults={source:[],items:8,menu:'',item:'
  • ',minLength:1},e.fn.typeahead.Constructor=t,e(function(){e("body").on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(t){var n=e(this);if(n.data("typeahead"))return;t.preventDefault(),n.typeahead(n.data())})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=e.extend({},e.fn.affix.defaults,n),this.$window=e(window).on("scroll.affix.data-api",e.proxy(this.checkPosition,this)),this.$element=e(t),this.checkPosition()};t.prototype.checkPosition=function(){if(!this.$element.is(":visible"))return;var t=e(document).height(),n=this.$window.scrollTop(),r=this.$element.offset(),i=this.options.offset,s=i.bottom,o=i.top,u="affix affix-top affix-bottom",a;typeof i!="object"&&(s=o=i),typeof o=="function"&&(o=i.top()),typeof s=="function"&&(s=i.bottom()),a=this.unpin!=null&&n+this.unpin<=r.top?!1:s!=null&&r.top+this.$element.height()>=t-s?"bottom":o!=null&&n<=o?"top":!1;if(this.affixed===a)return;this.affixed=a,this.unpin=a=="bottom"?r.top-n:null,this.$element.removeClass(u).addClass("affix"+(a?"-"+a:""))},e.fn.affix=function(n){return this.each(function(){var r=e(this),i=r.data("affix"),s=typeof n=="object"&&n;i||r.data("affix",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.affix.Constructor=t,e.fn.affix.defaults={offset:0},e(window).on("load",function(){e('[data-spy="affix"]').each(function(){var t=e(this),n=t.data();n.offset=n.offset||{},n.offsetBottom&&(n.offset.bottom=n.offsetBottom),n.offsetTop&&(n.offset.top=n.offsetTop),t.affix(n)})})}(window.jQuery); -------------------------------------------------------------------------------- /static/js/modernizr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author goodspeedcheng 3 | */ 4 | 5 | /*! 6 | * Modernizr v2.0.6 7 | * http://www.modernizr.com 8 | * 9 | * Copyright (c) 2009-2011 Faruk Ates, Paul Irish, Alex Sexton 10 | * Dual-licensed under the BSD or MIT licenses: www.modernizr.com/license/ 11 | */ 12 | 13 | /* 14 | * Modernizr tests which native CSS3 and HTML5 features are available in 15 | * the current UA and makes the results available to you in two ways: 16 | * as properties on a global Modernizr object, and as classes on the 17 | * element. This information allows you to progressively enhance 18 | * your pages with a granular level of control over the experience. 19 | * 20 | * Modernizr has an optional (not included) conditional resource loader 21 | * called Modernizr.load(), based on Yepnope.js (yepnopejs.com). 22 | * To get a build that includes Modernizr.load(), as well as choosing 23 | * which tests to include, go to www.modernizr.com/download/ 24 | * 25 | * Authors Faruk Ates, Paul Irish, Alex Sexton, 26 | * Contributors Ryan Seddon, Ben Alman 27 | */ 28 | 29 | window.Modernizr = (function( window, document, undefined ) { 30 | 31 | var version = '2.0.6', 32 | 33 | Modernizr = {}, 34 | 35 | // option for enabling the HTML classes to be added 36 | enableClasses = true, 37 | 38 | docElement = document.documentElement, 39 | docHead = document.head || document.getElementsByTagName('head')[0], 40 | 41 | /** 42 | * Create our "modernizr" element that we do most feature tests on. 43 | */ 44 | mod = 'modernizr', 45 | modElem = document.createElement(mod), 46 | mStyle = modElem.style, 47 | 48 | /** 49 | * Create the input element for various Web Forms feature tests. 50 | */ 51 | inputElem = document.createElement('input'), 52 | 53 | smile = ':)', 54 | 55 | toString = Object.prototype.toString, 56 | 57 | // List of property values to set for css tests. See ticket #21 58 | prefixes = ' -webkit- -moz- -o- -ms- -khtml- '.split(' '), 59 | 60 | // Following spec is to expose vendor-specific style properties as: 61 | // elem.style.WebkitBorderRadius 62 | // and the following would be incorrect: 63 | // elem.style.webkitBorderRadius 64 | 65 | // Webkit ghosts their properties in lowercase but Opera & Moz do not. 66 | // Microsoft foregoes prefixes entirely <= IE8, but appears to 67 | // use a lowercase `ms` instead of the correct `Ms` in IE9 68 | 69 | // More here: http://github.com/Modernizr/Modernizr/issues/issue/21 70 | domPrefixes = 'Webkit Moz O ms Khtml'.split(' '), 71 | 72 | ns = {'svg': 'http://www.w3.org/2000/svg'}, 73 | 74 | tests = {}, 75 | inputs = {}, 76 | attrs = {}, 77 | 78 | classes = [], 79 | 80 | featureName, // used in testing loop 81 | 82 | 83 | // Inject element with style element and some CSS rules 84 | injectElementWithStyles = function( rule, callback, nodes, testnames ) { 85 | 86 | var style, ret, node, 87 | div = document.createElement('div'); 88 | 89 | if ( parseInt(nodes, 10) ) { 90 | // In order not to give false positives we create a node for each test 91 | // This also allows the method to scale for unspecified uses 92 | while ( nodes-- ) { 93 | node = document.createElement('div'); 94 | node.id = testnames ? testnames[nodes] : mod + (nodes + 1); 95 | div.appendChild(node); 96 | } 97 | } 98 | 99 | // '].join(''); 104 | div.id = mod; 105 | div.innerHTML += style; 106 | docElement.appendChild(div); 107 | 108 | ret = callback(div, rule); 109 | div.parentNode.removeChild(div); 110 | 111 | return !!ret; 112 | 113 | }, 114 | 115 | 116 | // adapted from matchMedia polyfill 117 | // by Scott Jehl and Paul Irish 118 | // gist.github.com/786768 119 | testMediaQuery = function( mq ) { 120 | 121 | if ( window.matchMedia ) { 122 | return matchMedia(mq).matches; 123 | } 124 | 125 | var bool; 126 | 127 | injectElementWithStyles('@media ' + mq + ' { #' + mod + ' { position: absolute; } }', function( node ) { 128 | bool = (window.getComputedStyle ? 129 | getComputedStyle(node, null) : 130 | node.currentStyle)['position'] == 'absolute'; 131 | }); 132 | 133 | return bool; 134 | 135 | }, 136 | 137 | 138 | /** 139 | * isEventSupported determines if a given element supports the given event 140 | * function from http://yura.thinkweb2.com/isEventSupported/ 141 | */ 142 | isEventSupported = (function() { 143 | 144 | var TAGNAMES = { 145 | 'select': 'input', 'change': 'input', 146 | 'submit': 'form', 'reset': 'form', 147 | 'error': 'img', 'load': 'img', 'abort': 'img' 148 | }; 149 | 150 | function isEventSupported( eventName, element ) { 151 | 152 | element = element || document.createElement(TAGNAMES[eventName] || 'div'); 153 | eventName = 'on' + eventName; 154 | 155 | // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those 156 | var isSupported = eventName in element; 157 | 158 | if ( !isSupported ) { 159 | // If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element 160 | if ( !element.setAttribute ) { 161 | element = document.createElement('div'); 162 | } 163 | if ( element.setAttribute && element.removeAttribute ) { 164 | element.setAttribute(eventName, ''); 165 | isSupported = is(element[eventName], 'function'); 166 | 167 | // If property was created, "remove it" (by setting value to `undefined`) 168 | if ( !is(element[eventName], undefined) ) { 169 | element[eventName] = undefined; 170 | } 171 | element.removeAttribute(eventName); 172 | } 173 | } 174 | 175 | element = null; 176 | return isSupported; 177 | } 178 | return isEventSupported; 179 | })(); 180 | 181 | // hasOwnProperty shim by kangax needed for Safari 2.0 support 182 | var _hasOwnProperty = ({}).hasOwnProperty, hasOwnProperty; 183 | if ( !is(_hasOwnProperty, undefined) && !is(_hasOwnProperty.call, undefined) ) { 184 | hasOwnProperty = function (object, property) { 185 | return _hasOwnProperty.call(object, property); 186 | }; 187 | } 188 | else { 189 | hasOwnProperty = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */ 190 | return ((property in object) && is(object.constructor.prototype[property], undefined)); 191 | }; 192 | } 193 | 194 | /** 195 | * setCss applies given styles to the Modernizr DOM node. 196 | */ 197 | function setCss( str ) { 198 | mStyle.cssText = str; 199 | } 200 | 201 | /** 202 | * setCssAll extrapolates all vendor-specific css strings. 203 | */ 204 | function setCssAll( str1, str2 ) { 205 | return setCss(prefixes.join(str1 + ';') + ( str2 || '' )); 206 | } 207 | 208 | /** 209 | * is returns a boolean for if typeof obj is exactly type. 210 | */ 211 | function is( obj, type ) { 212 | return typeof obj === type; 213 | } 214 | 215 | /** 216 | * contains returns a boolean for if substr is found within str. 217 | */ 218 | function contains( str, substr ) { 219 | return !!~('' + str).indexOf(substr); 220 | } 221 | 222 | /** 223 | * testProps is a generic CSS / DOM property test; if a browser supports 224 | * a certain property, it won't return undefined for it. 225 | * A supported CSS property returns empty string when its not yet set. 226 | */ 227 | function testProps( props, prefixed ) { 228 | for ( var i in props ) { 229 | if ( mStyle[ props[i] ] !== undefined ) { 230 | return prefixed == 'pfx' ? props[i] : true; 231 | } 232 | } 233 | return false; 234 | } 235 | 236 | /** 237 | * testPropsAll tests a list of DOM properties we want to check against. 238 | * We specify literally ALL possible (known and/or likely) properties on 239 | * the element including the non-vendor prefixed one, for forward- 240 | * compatibility. 241 | */ 242 | function testPropsAll( prop, prefixed ) { 243 | 244 | var ucProp = prop.charAt(0).toUpperCase() + prop.substr(1), 245 | props = (prop + ' ' + domPrefixes.join(ucProp + ' ') + ucProp).split(' '); 246 | 247 | return testProps(props, prefixed); 248 | } 249 | 250 | /** 251 | * testBundle tests a list of CSS features that require element and style injection. 252 | * By bundling them together we can reduce the need to touch the DOM multiple times. 253 | */ 254 | /*>>testBundle*/ 255 | var testBundle = (function( styles, tests ) { 256 | var style = styles.join(''), 257 | len = tests.length; 258 | 259 | injectElementWithStyles(style, function( node, rule ) { 260 | var style = document.styleSheets[document.styleSheets.length - 1], 261 | // IE8 will bork if you create a custom build that excludes both fontface and generatedcontent tests. 262 | // So we check for cssRules and that there is a rule available 263 | // More here: https://github.com/Modernizr/Modernizr/issues/288 & https://github.com/Modernizr/Modernizr/issues/293 264 | cssText = style.cssRules && style.cssRules[0] ? style.cssRules[0].cssText : style.cssText || "", 265 | children = node.childNodes, hash = {}; 266 | 267 | while ( len-- ) { 268 | hash[children[len].id] = children[len]; 269 | } 270 | 271 | /*>>touch*/ Modernizr['touch'] = ('ontouchstart' in window) || hash['touch'].offsetTop === 9; /*>>touch*/ 272 | /*>>csstransforms3d*/ Modernizr['csstransforms3d'] = hash['csstransforms3d'].offsetLeft === 9; /*>>csstransforms3d*/ 273 | /*>>generatedcontent*/Modernizr['generatedcontent'] = hash['generatedcontent'].offsetHeight >= 1; /*>>generatedcontent*/ 274 | /*>>fontface*/ Modernizr['fontface'] = /src/i.test(cssText) && 275 | cssText.indexOf(rule.split(' ')[0]) === 0; /*>>fontface*/ 276 | }, len, tests); 277 | 278 | })([ 279 | // Pass in styles to be injected into document 280 | /*>>fontface*/ '@font-face {font-family:"font";src:url("https://")}' /*>>fontface*/ 281 | 282 | /*>>touch*/ ,['@media (',prefixes.join('touch-enabled),('),mod,')', 283 | '{#touch{top:9px;position:absolute}}'].join('') /*>>touch*/ 284 | 285 | /*>>csstransforms3d*/ ,['@media (',prefixes.join('transform-3d),('),mod,')', 286 | '{#csstransforms3d{left:9px;position:absolute}}'].join('')/*>>csstransforms3d*/ 287 | 288 | /*>>generatedcontent*/,['#generatedcontent:after{content:"',smile,'";visibility:hidden}'].join('') /*>>generatedcontent*/ 289 | ], 290 | [ 291 | /*>>fontface*/ 'fontface' /*>>fontface*/ 292 | /*>>touch*/ ,'touch' /*>>touch*/ 293 | /*>>csstransforms3d*/ ,'csstransforms3d' /*>>csstransforms3d*/ 294 | /*>>generatedcontent*/,'generatedcontent' /*>>generatedcontent*/ 295 | 296 | ]);/*>>testBundle*/ 297 | 298 | 299 | /** 300 | * Tests 301 | * ----- 302 | */ 303 | 304 | tests['flexbox'] = function() { 305 | /** 306 | * setPrefixedValueCSS sets the property of a specified element 307 | * adding vendor prefixes to the VALUE of the property. 308 | * @param {Element} element 309 | * @param {string} property The property name. This will not be prefixed. 310 | * @param {string} value The value of the property. This WILL be prefixed. 311 | * @param {string=} extra Additional CSS to append unmodified to the end of 312 | * the CSS string. 313 | */ 314 | function setPrefixedValueCSS( element, property, value, extra ) { 315 | property += ':'; 316 | element.style.cssText = (property + prefixes.join(value + ';' + property)).slice(0, -property.length) + (extra || ''); 317 | } 318 | 319 | /** 320 | * setPrefixedPropertyCSS sets the property of a specified element 321 | * adding vendor prefixes to the NAME of the property. 322 | * @param {Element} element 323 | * @param {string} property The property name. This WILL be prefixed. 324 | * @param {string} value The value of the property. This will not be prefixed. 325 | * @param {string=} extra Additional CSS to append unmodified to the end of 326 | * the CSS string. 327 | */ 328 | function setPrefixedPropertyCSS( element, property, value, extra ) { 329 | element.style.cssText = prefixes.join(property + ':' + value + ';') + (extra || ''); 330 | } 331 | 332 | var c = document.createElement('div'), 333 | elem = document.createElement('div'); 334 | 335 | setPrefixedValueCSS(c, 'display', 'box', 'width:42px;padding:0;'); 336 | setPrefixedPropertyCSS(elem, 'box-flex', '1', 'width:10px;'); 337 | 338 | c.appendChild(elem); 339 | docElement.appendChild(c); 340 | 341 | var ret = elem.offsetWidth === 42; 342 | 343 | c.removeChild(elem); 344 | docElement.removeChild(c); 345 | 346 | return ret; 347 | }; 348 | 349 | // On the S60 and BB Storm, getContext exists, but always returns undefined 350 | // http://github.com/Modernizr/Modernizr/issues/issue/97/ 351 | 352 | tests['canvas'] = function() { 353 | var elem = document.createElement('canvas'); 354 | return !!(elem.getContext && elem.getContext('2d')); 355 | }; 356 | 357 | tests['canvastext'] = function() { 358 | return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function')); 359 | }; 360 | 361 | // This WebGL test may false positive. 362 | // But really it's quite impossible to know whether webgl will succeed until after you create the context. 363 | // You might have hardware that can support a 100x100 webgl canvas, but will not support a 1000x1000 webgl 364 | // canvas. So this feature inference is weak, but intentionally so. 365 | 366 | // It is known to false positive in FF4 with certain hardware and the iPad 2. 367 | 368 | tests['webgl'] = function() { 369 | return !!window.WebGLRenderingContext; 370 | }; 371 | 372 | /* 373 | * The Modernizr.touch test only indicates if the browser supports 374 | * touch events, which does not necessarily reflect a touchscreen 375 | * device, as evidenced by tablets running Windows 7 or, alas, 376 | * the Palm Pre / WebOS (touch) phones. 377 | * 378 | * Additionally, Chrome (desktop) used to lie about its support on this, 379 | * but that has since been rectified: http://crbug.com/36415 380 | * 381 | * We also test for Firefox 4 Multitouch Support. 382 | * 383 | * For more info, see: http://modernizr.github.com/Modernizr/touch.html 384 | */ 385 | 386 | tests['touch'] = function() { 387 | return Modernizr['touch']; 388 | }; 389 | 390 | /** 391 | * geolocation tests for the new Geolocation API specification. 392 | * This test is a standards compliant-only test; for more complete 393 | * testing, including a Google Gears fallback, please see: 394 | * http://code.google.com/p/geo-location-javascript/ 395 | * or view a fallback solution using google's geo API: 396 | * http://gist.github.com/366184 397 | */ 398 | tests['geolocation'] = function() { 399 | return !!navigator.geolocation; 400 | }; 401 | 402 | // Per 1.6: 403 | // This used to be Modernizr.crosswindowmessaging but the longer 404 | // name has been deprecated in favor of a shorter and property-matching one. 405 | // The old API is still available in 1.6, but as of 2.0 will throw a warning, 406 | // and in the first release thereafter disappear entirely. 407 | tests['postmessage'] = function() { 408 | return !!window.postMessage; 409 | }; 410 | 411 | // Web SQL database detection is tricky: 412 | 413 | // In chrome incognito mode, openDatabase is truthy, but using it will 414 | // throw an exception: http://crbug.com/42380 415 | // We can create a dummy database, but there is no way to delete it afterwards. 416 | 417 | // Meanwhile, Safari users can get prompted on any database creation. 418 | // If they do, any page with Modernizr will give them a prompt: 419 | // http://github.com/Modernizr/Modernizr/issues/closed#issue/113 420 | 421 | // We have chosen to allow the Chrome incognito false positive, so that Modernizr 422 | // doesn't litter the web with these test databases. As a developer, you'll have 423 | // to account for this gotcha yourself. 424 | tests['websqldatabase'] = function() { 425 | var result = !!window.openDatabase; 426 | /* if (result){ 427 | try { 428 | result = !!openDatabase( mod + "testdb", "1.0", mod + "testdb", 2e4); 429 | } catch(e) { 430 | } 431 | } */ 432 | return result; 433 | }; 434 | 435 | // Vendors had inconsistent prefixing with the experimental Indexed DB: 436 | // - Webkit's implementation is accessible through webkitIndexedDB 437 | // - Firefox shipped moz_indexedDB before FF4b9, but since then has been mozIndexedDB 438 | // For speed, we don't test the legacy (and beta-only) indexedDB 439 | tests['indexedDB'] = function() { 440 | for ( var i = -1, len = domPrefixes.length; ++i < len; ){ 441 | if ( window[domPrefixes[i].toLowerCase() + 'IndexedDB'] ){ 442 | return true; 443 | } 444 | } 445 | return !!window.indexedDB; 446 | }; 447 | 448 | // documentMode logic from YUI to filter out IE8 Compat Mode 449 | // which false positives. 450 | tests['hashchange'] = function() { 451 | return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7); 452 | }; 453 | 454 | // Per 1.6: 455 | // This used to be Modernizr.historymanagement but the longer 456 | // name has been deprecated in favor of a shorter and property-matching one. 457 | // The old API is still available in 1.6, but as of 2.0 will throw a warning, 458 | // and in the first release thereafter disappear entirely. 459 | tests['history'] = function() { 460 | return !!(window.history && history.pushState); 461 | }; 462 | 463 | tests['draganddrop'] = function() { 464 | return isEventSupported('dragstart') && isEventSupported('drop'); 465 | }; 466 | 467 | // Mozilla is targeting to land MozWebSocket for FF6 468 | // bugzil.la/659324 469 | tests['websockets'] = function() { 470 | for ( var i = -1, len = domPrefixes.length; ++i < len; ){ 471 | if ( window[domPrefixes[i] + 'WebSocket'] ){ 472 | return true; 473 | } 474 | } 475 | return 'WebSocket' in window; 476 | }; 477 | 478 | 479 | // http://css-tricks.com/rgba-browser-support/ 480 | tests['rgba'] = function() { 481 | // Set an rgba() color and check the returned value 482 | 483 | setCss('background-color:rgba(150,255,150,.5)'); 484 | 485 | return contains(mStyle.backgroundColor, 'rgba'); 486 | }; 487 | 488 | tests['hsla'] = function() { 489 | // Same as rgba(), in fact, browsers re-map hsla() to rgba() internally, 490 | // except IE9 who retains it as hsla 491 | 492 | setCss('background-color:hsla(120,40%,100%,.5)'); 493 | 494 | return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla'); 495 | }; 496 | 497 | tests['multiplebgs'] = function() { 498 | // Setting multiple images AND a color on the background shorthand property 499 | // and then querying the style.background property value for the number of 500 | // occurrences of "url(" is a reliable method for detecting ACTUAL support for this! 501 | 502 | setCss('background:url(https://),url(https://),red url(https://)'); 503 | 504 | // If the UA supports multiple backgrounds, there should be three occurrences 505 | // of the string "url(" in the return value for elemStyle.background 506 | 507 | return /(url\s*\(.*?){3}/.test(mStyle.background); 508 | }; 509 | 510 | 511 | // In testing support for a given CSS property, it's legit to test: 512 | // `elem.style[styleName] !== undefined` 513 | // If the property is supported it will return an empty string, 514 | // if unsupported it will return undefined. 515 | 516 | // We'll take advantage of this quick test and skip setting a style 517 | // on our modernizr element, but instead just testing undefined vs 518 | // empty string. 519 | 520 | 521 | tests['backgroundsize'] = function() { 522 | return testPropsAll('backgroundSize'); 523 | }; 524 | 525 | tests['borderimage'] = function() { 526 | return testPropsAll('borderImage'); 527 | }; 528 | 529 | 530 | // Super comprehensive table about all the unique implementations of 531 | // border-radius: http://muddledramblings.com/table-of-css3-border-radius-compliance 532 | 533 | tests['borderradius'] = function() { 534 | return testPropsAll('borderRadius'); 535 | }; 536 | 537 | // WebOS unfortunately false positives on this test. 538 | tests['boxshadow'] = function() { 539 | return testPropsAll('boxShadow'); 540 | }; 541 | 542 | // FF3.0 will false positive on this test 543 | tests['textshadow'] = function() { 544 | return document.createElement('div').style.textShadow === ''; 545 | }; 546 | 547 | 548 | tests['opacity'] = function() { 549 | // Browsers that actually have CSS Opacity implemented have done so 550 | // according to spec, which means their return values are within the 551 | // range of [0.0,1.0] - including the leading zero. 552 | 553 | setCssAll('opacity:.55'); 554 | 555 | // The non-literal . in this regex is intentional: 556 | // German Chrome returns this value as 0,55 557 | // https://github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632 558 | return /^0.55$/.test(mStyle.opacity); 559 | }; 560 | 561 | 562 | tests['cssanimations'] = function() { 563 | return testPropsAll('animationName'); 564 | }; 565 | 566 | 567 | tests['csscolumns'] = function() { 568 | return testPropsAll('columnCount'); 569 | }; 570 | 571 | 572 | tests['cssgradients'] = function() { 573 | /** 574 | * For CSS Gradients syntax, please see: 575 | * http://webkit.org/blog/175/introducing-css-gradients/ 576 | * https://developer.mozilla.org/en/CSS/-moz-linear-gradient 577 | * https://developer.mozilla.org/en/CSS/-moz-radial-gradient 578 | * http://dev.w3.org/csswg/css3-images/#gradients- 579 | */ 580 | 581 | var str1 = 'background-image:', 582 | str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));', 583 | str3 = 'linear-gradient(left top,#9f9, white);'; 584 | 585 | setCss( 586 | (str1 + prefixes.join(str2 + str1) + prefixes.join(str3 + str1)).slice(0, -str1.length) 587 | ); 588 | 589 | return contains(mStyle.backgroundImage, 'gradient'); 590 | }; 591 | 592 | 593 | tests['cssreflections'] = function() { 594 | return testPropsAll('boxReflect'); 595 | }; 596 | 597 | 598 | tests['csstransforms'] = function() { 599 | return !!testProps(['transformProperty', 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform']); 600 | }; 601 | 602 | 603 | tests['csstransforms3d'] = function() { 604 | 605 | var ret = !!testProps(['perspectiveProperty', 'WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective']); 606 | 607 | // Webkit鈥檚 3D transforms are passed off to the browser's own graphics renderer. 608 | // It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in 609 | // some conditions. As a result, Webkit typically recognizes the syntax but 610 | // will sometimes throw a false positive, thus we must do a more thorough check: 611 | if ( ret && 'webkitPerspective' in docElement.style ) { 612 | 613 | // Webkit allows this media query to succeed only if the feature is enabled. 614 | // `@media (transform-3d),(-o-transform-3d),(-moz-transform-3d),(-ms-transform-3d),(-webkit-transform-3d),(modernizr){ ... }` 615 | ret = Modernizr['csstransforms3d']; 616 | } 617 | return ret; 618 | }; 619 | 620 | 621 | tests['csstransitions'] = function() { 622 | return testPropsAll('transitionProperty'); 623 | }; 624 | 625 | 626 | /*>>fontface*/ 627 | // @font-face detection routine by Diego Perini 628 | // http://javascript.nwbox.com/CSSSupport/ 629 | tests['fontface'] = function() { 630 | return Modernizr['fontface']; 631 | }; 632 | /*>>fontface*/ 633 | 634 | // CSS generated content detection 635 | tests['generatedcontent'] = function() { 636 | return Modernizr['generatedcontent']; 637 | }; 638 | 639 | 640 | 641 | // These tests evaluate support of the video/audio elements, as well as 642 | // testing what types of content they support. 643 | // 644 | // We're using the Boolean constructor here, so that we can extend the value 645 | // e.g. Modernizr.video // true 646 | // Modernizr.video.ogg // 'probably' 647 | // 648 | // Codec values from : http://github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845 649 | // thx to NielsLeenheer and zcorpan 650 | 651 | // Note: in FF 3.5.1 and 3.5.0, "no" was a return value instead of empty string. 652 | // Modernizr does not normalize for that. 653 | 654 | tests['video'] = function() { 655 | var elem = document.createElement('video'), 656 | bool = false; 657 | 658 | // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224 659 | try { 660 | if ( bool = !!elem.canPlayType ) { 661 | bool = new Boolean(bool); 662 | bool.ogg = elem.canPlayType('video/ogg; codecs="theora"'); 663 | 664 | // Workaround required for IE9, which doesn't report video support without audio codec specified. 665 | // bug 599718 @ msft connect 666 | var h264 = 'video/mp4; codecs="avc1.42E01E'; 667 | bool.h264 = elem.canPlayType(h264 + '"') || elem.canPlayType(h264 + ', mp4a.40.2"'); 668 | 669 | bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"'); 670 | } 671 | 672 | } catch(e) { } 673 | 674 | return bool; 675 | }; 676 | 677 | tests['audio'] = function() { 678 | var elem = document.createElement('audio'), 679 | bool = false; 680 | 681 | try { 682 | if ( bool = !!elem.canPlayType ) { 683 | bool = new Boolean(bool); 684 | bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"'); 685 | bool.mp3 = elem.canPlayType('audio/mpeg;'); 686 | 687 | // Mimetypes accepted: 688 | // https://developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements 689 | // http://bit.ly/iphoneoscodecs 690 | bool.wav = elem.canPlayType('audio/wav; codecs="1"'); 691 | bool.m4a = elem.canPlayType('audio/x-m4a;') || elem.canPlayType('audio/aac;'); 692 | } 693 | } catch(e) { } 694 | 695 | return bool; 696 | }; 697 | 698 | 699 | // Firefox has made these tests rather unfun. 700 | 701 | // In FF4, if disabled, window.localStorage should === null. 702 | 703 | // Normally, we could not test that directly and need to do a 704 | // `('localStorage' in window) && ` test first because otherwise Firefox will 705 | // throw http://bugzil.la/365772 if cookies are disabled 706 | 707 | // However, in Firefox 4 betas, if dom.storage.enabled == false, just mentioning 708 | // the property will throw an exception. http://bugzil.la/599479 709 | // This looks to be fixed for FF4 Final. 710 | 711 | // Because we are forced to try/catch this, we'll go aggressive. 712 | 713 | // FWIW: IE8 Compat mode supports these features completely: 714 | // http://www.quirksmode.org/dom/html5.html 715 | // But IE8 doesn't support either with local files 716 | 717 | tests['localstorage'] = function() { 718 | try { 719 | return !!localStorage.getItem; 720 | } catch(e) { 721 | return false; 722 | } 723 | }; 724 | 725 | tests['sessionstorage'] = function() { 726 | try { 727 | return !!sessionStorage.getItem; 728 | } catch(e){ 729 | return false; 730 | } 731 | }; 732 | 733 | 734 | tests['webworkers'] = function() { 735 | return !!window.Worker; 736 | }; 737 | 738 | 739 | tests['applicationcache'] = function() { 740 | return !!window.applicationCache; 741 | }; 742 | 743 | 744 | // Thanks to Erik Dahlstrom 745 | tests['svg'] = function() { 746 | return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect; 747 | }; 748 | 749 | // specifically for SVG inline in HTML, not within XHTML 750 | // test page: paulirish.com/demo/inline-svg 751 | tests['inlinesvg'] = function() { 752 | var div = document.createElement('div'); 753 | div.innerHTML = ''; 754 | return (div.firstChild && div.firstChild.namespaceURI) == ns.svg; 755 | }; 756 | 757 | // Thanks to F1lt3r and lucideer, ticket #35 758 | tests['smil'] = function() { 759 | return !!document.createElementNS && /SVG/.test(toString.call(document.createElementNS(ns.svg, 'animate'))); 760 | }; 761 | 762 | tests['svgclippaths'] = function() { 763 | // Possibly returns a false positive in Safari 3.2? 764 | return !!document.createElementNS && /SVG/.test(toString.call(document.createElementNS(ns.svg, 'clipPath'))); 765 | }; 766 | 767 | // input features and input types go directly onto the ret object, bypassing the tests loop. 768 | // Hold this guy to execute in a moment. 769 | function webforms() { 770 | // Run through HTML5's new input attributes to see if the UA understands any. 771 | // We're using f which is the element created early on 772 | // Mike Taylr has created a comprehensive resource for testing these attributes 773 | // when applied to all input types: 774 | // http://miketaylr.com/code/input-type-attr.html 775 | // spec: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary 776 | 777 | // Only input placeholder is tested while textarea's placeholder is not. 778 | // Currently Safari 4 and Opera 11 have support only for the input placeholder 779 | // Both tests are available in feature-detects/forms-placeholder.js 780 | Modernizr['input'] = (function( props ) { 781 | for ( var i = 0, len = props.length; i < len; i++ ) { 782 | attrs[ props[i] ] = !!(props[i] in inputElem); 783 | } 784 | return attrs; 785 | })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' ')); 786 | 787 | // Run through HTML5's new input types to see if the UA understands any. 788 | // This is put behind the tests runloop because it doesn't return a 789 | // true/false like all the other tests; instead, it returns an object 790 | // containing each input type with its corresponding true/false value 791 | 792 | // Big thanks to @miketaylr for the html5 forms expertise. http://miketaylr.com/ 793 | Modernizr['inputtypes'] = (function(props) { 794 | 795 | for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) { 796 | 797 | inputElem.setAttribute('type', inputElemType = props[i]); 798 | bool = inputElem.type !== 'text'; 799 | 800 | // We first check to see if the type we give it sticks.. 801 | // If the type does, we feed it a textual value, which shouldn't be valid. 802 | // If the value doesn't stick, we know there's input sanitization which infers a custom UI 803 | if ( bool ) { 804 | 805 | inputElem.value = smile; 806 | inputElem.style.cssText = 'position:absolute;visibility:hidden;'; 807 | 808 | if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) { 809 | 810 | docElement.appendChild(inputElem); 811 | defaultView = document.defaultView; 812 | 813 | // Safari 2-4 allows the smiley as a value, despite making a slider 814 | bool = defaultView.getComputedStyle && 815 | defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' && 816 | // Mobile android web browser has false positive, so must 817 | // check the height to see if the widget is actually there. 818 | (inputElem.offsetHeight !== 0); 819 | 820 | docElement.removeChild(inputElem); 821 | 822 | } else if ( /^(search|tel)$/.test(inputElemType) ){ 823 | // Spec doesnt define any special parsing or detectable UI 824 | // behaviors so we pass these through as true 825 | 826 | // Interestingly, opera fails the earlier test, so it doesn't 827 | // even make it here. 828 | 829 | } else if ( /^(url|email)$/.test(inputElemType) ) { 830 | // Real url and email support comes with prebaked validation. 831 | bool = inputElem.checkValidity && inputElem.checkValidity() === false; 832 | 833 | } else if ( /^color$/.test(inputElemType) ) { 834 | // chuck into DOM and force reflow for Opera bug in 11.00 835 | // github.com/Modernizr/Modernizr/issues#issue/159 836 | docElement.appendChild(inputElem); 837 | docElement.offsetWidth; 838 | bool = inputElem.value != smile; 839 | docElement.removeChild(inputElem); 840 | 841 | } else { 842 | // If the upgraded input compontent rejects the :) text, we got a winner 843 | bool = inputElem.value != smile; 844 | } 845 | } 846 | 847 | inputs[ props[i] ] = !!bool; 848 | } 849 | return inputs; 850 | })('search tel url email datetime date month week time datetime-local number range color'.split(' ')); 851 | } 852 | 853 | 854 | // End of test definitions 855 | // ----------------------- 856 | 857 | 858 | 859 | // Run through all tests and detect their support in the current UA. 860 | // todo: hypothetically we could be doing an array of tests and use a basic loop here. 861 | for ( var feature in tests ) { 862 | if ( hasOwnProperty(tests, feature) ) { 863 | // run the test, throw the return value into the Modernizr, 864 | // then based on that boolean, define an appropriate className 865 | // and push it into an array of classes we'll join later. 866 | featureName = feature.toLowerCase(); 867 | Modernizr[featureName] = tests[feature](); 868 | 869 | classes.push((Modernizr[featureName] ? '' : 'no-') + featureName); 870 | } 871 | } 872 | 873 | // input tests need to run. 874 | Modernizr.input || webforms(); 875 | 876 | 877 | /** 878 | * addTest allows the user to define their own feature tests 879 | * the result will be added onto the Modernizr object, 880 | * as well as an appropriate className set on the html element 881 | * 882 | * @param feature - String naming the feature 883 | * @param test - Function returning true if feature is supported, false if not 884 | */ 885 | Modernizr.addTest = function ( feature, test ) { 886 | if ( typeof feature == "object" ) { 887 | for ( var key in feature ) { 888 | if ( hasOwnProperty( feature, key ) ) { 889 | Modernizr.addTest( key, feature[ key ] ); 890 | } 891 | } 892 | } else { 893 | 894 | feature = feature.toLowerCase(); 895 | 896 | if ( Modernizr[feature] !== undefined ) { 897 | // we're going to quit if you're trying to overwrite an existing test 898 | // if we were to allow it, we'd do this: 899 | // var re = new RegExp("\\b(no-)?" + feature + "\\b"); 900 | // docElement.className = docElement.className.replace( re, '' ); 901 | // but, no rly, stuff 'em. 902 | return; 903 | } 904 | 905 | test = typeof test == "boolean" ? test : !!test(); 906 | 907 | docElement.className += ' ' + (test ? '' : 'no-') + feature; 908 | Modernizr[feature] = test; 909 | 910 | } 911 | 912 | return Modernizr; // allow chaining. 913 | }; 914 | 915 | 916 | // Reset modElem.cssText to nothing to reduce memory footprint. 917 | setCss(''); 918 | modElem = inputElem = null; 919 | 920 | //>>BEGIN IEPP 921 | // Enable HTML 5 elements for styling (and printing) in IE. 922 | if ( window.attachEvent && (function(){ var elem = document.createElement('div'); 923 | elem.innerHTML = ''; 924 | return elem.childNodes.length !== 1; })() ) { 925 | 926 | // iepp v2 by @jon_neal & afarkas : github.com/aFarkas/iepp/ 927 | (function(win, doc) { 928 | win.iepp = win.iepp || {}; 929 | var iepp = win.iepp, 930 | elems = iepp.html5elements || 'abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video', 931 | elemsArr = elems.split('|'), 932 | elemsArrLen = elemsArr.length, 933 | elemRegExp = new RegExp('(^|\\s)('+elems+')', 'gi'), 934 | tagRegExp = new RegExp('<(\/*)('+elems+')', 'gi'), 935 | filterReg = /^\s*[\{\}]\s*$/, 936 | ruleRegExp = new RegExp('(^|[^\\n]*?\\s)('+elems+')([^\\n]*)({[\\n\\w\\W]*?})', 'gi'), 937 | docFrag = doc.createDocumentFragment(), 938 | html = doc.documentElement, 939 | head = html.firstChild, 940 | bodyElem = doc.createElement('body'), 941 | styleElem = doc.createElement('style'), 942 | printMedias = /print|all/, 943 | body; 944 | function shim(doc) { 945 | var a = -1; 946 | while (++a < elemsArrLen) 947 | // Use createElement so IE allows HTML5-named elements in a document 948 | doc.createElement(elemsArr[a]); 949 | } 950 | 951 | iepp.getCSS = function(styleSheetList, mediaType) { 952 | if(styleSheetList+'' === undefined){return '';} 953 | var a = -1, 954 | len = styleSheetList.length, 955 | styleSheet, 956 | cssTextArr = []; 957 | while (++a < len) { 958 | styleSheet = styleSheetList[a]; 959 | //currently no test for disabled/alternate stylesheets 960 | if(styleSheet.disabled){continue;} 961 | mediaType = styleSheet.media || mediaType; 962 | // Get css from all non-screen stylesheets and their imports 963 | if (printMedias.test(mediaType)) cssTextArr.push(iepp.getCSS(styleSheet.imports, mediaType), styleSheet.cssText); 964 | //reset mediaType to all with every new *not imported* stylesheet 965 | mediaType = 'all'; 966 | } 967 | return cssTextArr.join(''); 968 | }; 969 | 970 | iepp.parseCSS = function(cssText) { 971 | var cssTextArr = [], 972 | rule; 973 | while ((rule = ruleRegExp.exec(cssText)) != null){ 974 | // Replace all html5 element references with iepp substitute classnames 975 | cssTextArr.push(( (filterReg.exec(rule[1]) ? '\n' : rule[1]) +rule[2]+rule[3]).replace(elemRegExp, '$1.iepp_$2')+rule[4]); 976 | } 977 | return cssTextArr.join('\n'); 978 | }; 979 | 980 | iepp.writeHTML = function() { 981 | var a = -1; 982 | body = body || doc.body; 983 | while (++a < elemsArrLen) { 984 | var nodeList = doc.getElementsByTagName(elemsArr[a]), 985 | nodeListLen = nodeList.length, 986 | b = -1; 987 | while (++b < nodeListLen) 988 | if (nodeList[b].className.indexOf('iepp_') < 0) 989 | // Append iepp substitute classnames to all html5 elements 990 | nodeList[b].className += ' iepp_'+elemsArr[a]; 991 | } 992 | docFrag.appendChild(body); 993 | html.appendChild(bodyElem); 994 | // Write iepp substitute print-safe document 995 | bodyElem.className = body.className; 996 | bodyElem.id = body.id; 997 | // Replace HTML5 elements with which is print-safe and shouldn't conflict since it isn't part of html5 998 | bodyElem.innerHTML = body.innerHTML.replace(tagRegExp, '<$1font'); 999 | }; 1000 | 1001 | 1002 | iepp._beforePrint = function() { 1003 | // Write iepp custom print CSS 1004 | styleElem.styleSheet.cssText = iepp.parseCSS(iepp.getCSS(doc.styleSheets, 'all')); 1005 | iepp.writeHTML(); 1006 | }; 1007 | 1008 | iepp.restoreHTML = function(){ 1009 | // Undo everything done in onbeforeprint 1010 | bodyElem.innerHTML = ''; 1011 | html.removeChild(bodyElem); 1012 | html.appendChild(body); 1013 | }; 1014 | 1015 | iepp._afterPrint = function(){ 1016 | // Undo everything done in onbeforeprint 1017 | iepp.restoreHTML(); 1018 | styleElem.styleSheet.cssText = ''; 1019 | }; 1020 | 1021 | 1022 | 1023 | // Shim the document and iepp fragment 1024 | shim(doc); 1025 | shim(docFrag); 1026 | 1027 | // 1028 | if(iepp.disablePP){return;} 1029 | 1030 | // Add iepp custom print style element 1031 | head.insertBefore(styleElem, head.firstChild); 1032 | styleElem.media = 'print'; 1033 | styleElem.className = 'iepp-printshim'; 1034 | win.attachEvent( 1035 | 'onbeforeprint', 1036 | iepp._beforePrint 1037 | ); 1038 | win.attachEvent( 1039 | 'onafterprint', 1040 | iepp._afterPrint 1041 | ); 1042 | })(window, document); 1043 | } 1044 | //>>END IEPP 1045 | 1046 | // Assign private properties to the return object with prefix 1047 | Modernizr._version = version; 1048 | 1049 | // expose these for the plugin API. Look in the source for how to join() them against your input 1050 | Modernizr._prefixes = prefixes; 1051 | Modernizr._domPrefixes = domPrefixes; 1052 | 1053 | // Modernizr.mq tests a given media query, live against the current state of the window 1054 | // A few important notes: 1055 | // * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false 1056 | // * A max-width or orientation query will be evaluated against the current state, which may change later. 1057 | // * You must specify values. Eg. If you are testing support for the min-width media query use: 1058 | // Modernizr.mq('(min-width:0)') 1059 | // usage: 1060 | // Modernizr.mq('only screen and (max-width:768)') 1061 | Modernizr.mq = testMediaQuery; 1062 | 1063 | // Modernizr.hasEvent() detects support for a given event, with an optional element to test on 1064 | // Modernizr.hasEvent('gesturestart', elem) 1065 | Modernizr.hasEvent = isEventSupported; 1066 | 1067 | // Modernizr.testProp() investigates whether a given style property is recognized 1068 | // Note that the property names must be provided in the camelCase variant. 1069 | // Modernizr.testProp('pointerEvents') 1070 | Modernizr.testProp = function(prop){ 1071 | return testProps([prop]); 1072 | }; 1073 | 1074 | // Modernizr.testAllProps() investigates whether a given style property, 1075 | // or any of its vendor-prefixed variants, is recognized 1076 | // Note that the property names must be provided in the camelCase variant. 1077 | // Modernizr.testAllProps('boxSizing') 1078 | Modernizr.testAllProps = testPropsAll; 1079 | 1080 | 1081 | 1082 | // Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards 1083 | // Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... }) 1084 | Modernizr.testStyles = injectElementWithStyles; 1085 | 1086 | 1087 | // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input 1088 | // Modernizr.prefixed('boxSizing') // 'MozBoxSizing' 1089 | 1090 | // Properties must be passed as dom-style camelcase, rather than `box-sizing` hypentated style. 1091 | // Return values will also be the camelCase variant, if you need to translate that to hypenated style use: 1092 | // 1093 | // str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-'); 1094 | 1095 | // If you're trying to ascertain which transition end event to bind to, you might do something like... 1096 | // 1097 | // var transEndEventNames = { 1098 | // 'WebkitTransition' : 'webkitTransitionEnd', 1099 | // 'MozTransition' : 'transitionend', 1100 | // 'OTransition' : 'oTransitionEnd', 1101 | // 'msTransition' : 'msTransitionEnd', // maybe? 1102 | // 'transition' : 'transitionEnd' 1103 | // }, 1104 | // transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ]; 1105 | 1106 | Modernizr.prefixed = function(prop){ 1107 | return testPropsAll(prop, 'pfx'); 1108 | }; 1109 | 1110 | 1111 | 1112 | // Remove "no-js" class from element, if it exists: 1113 | docElement.className = docElement.className.replace(/\bno-js\b/, '') 1114 | 1115 | // Add the new classes to the element. 1116 | + (enableClasses ? ' js ' + classes.join(' ') : ''); 1117 | 1118 | return Modernizr; 1119 | 1120 | })(this, this.document); -------------------------------------------------------------------------------- /templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {% block title %}{% endblock %} 7 | 8 | 9 | 10 | 11 | 12 | {# #} 13 | 14 | 15 | {% block extra_head %} 16 | {% comment %} 17 | 我认为这是个非常有用的区块, 很多人已经以某种方式在使用了. 很多页面经常需要在 HTML 文档头添加些信息, 比如 RSS 源, Javascript, CSS, 以及别的应该放在文档头的信息. 你可以, 也很可能将会, 定义另外专门的区块 (比如前面的 title 区块) 来添加文档头的其它部分的信息. 18 | {% endcomment %} 19 | {% endblock %} 20 | 21 | 22 | 23 | {% block body %} 24 | {% block header %} 25 | {# 任何每个页面都可能修改的文本区域的页面 #} 26 | {% block menu %} 27 | {# 你的菜单 (导航栏) 应该包含在这个区块中. 它是针对站点级的导航, 不是 每个页面专属的导航菜单. #} 28 | {% endblock %} 29 | {% endblock %} 30 | 31 |
    32 | {% block content %} 33 | {# 这个区块用来放置页面正文内容. 任何页面正文内容都可能不一样. 它不 包含任何站点导航, 信息头, 页脚, 或其它任何属于 base 模板的东东. #} 34 | 35 |
    36 |
    37 |
    38 | {% block article %} 39 | {% block article_title %} 40 | {% comment %} 41 | 用来指定 content 区块的 "title". 比如 blog 的标题. 42 | 也可以用来 包含 content 内的导航 (译注: 比如提纲), 或其它类似的东东. 43 | 大致都是些 页面中并非主要内容的东东. 44 | 我不知道这个区块是否应该放到 content tag 内, 并且对应于前面建议的 content tag, 45 | 是不是还需要一个 main_content 区块. 46 | {% block [section]_menu %} {% block page_menu %} 47 | 这是对应于之前建议的 menu 区块. 用来导航一个章节或页面. 48 | {% endcomment %} 49 | {% endblock %} 50 | {% block article_content %}{% endblock %} 51 | {% endblock %} 52 | 53 | {% block article_menu %} {% endblock %} 54 | {% block comments %} {% endblock %} 55 |
    56 |
    57 | {% block aside %} 58 | {% block addblog %}{% endblock %} 59 | {% block search %}{% endblock %} 60 | {% block tags %}{% endblock %} 61 | {% endblock %} 62 |
    63 |
    64 |
    65 | {% endblock %} 66 | {% block footer %} 67 | {# 任何每个页面都可能修改的文本区域的页脚 #} 68 |

    Thanks for visiting my site!

    69 | {% endblock %} 70 | {% endblock %} 71 |
    72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /templates/simpleblog/blog_add.html: -------------------------------------------------------------------------------- 1 | {% extends "blog_base.html" %} 2 | 3 | {% block title %} 发布文字 {% endblock %} 4 | {% block otherscript %} 5 | 10 | {% endblock %} 11 | 12 | {% block article %} 13 | {% comment %} 14 | {% if form.errors %} 15 |
    16 | Please correct the error {{ form.errors|pluralize }} below. 17 |
    18 | {% endif %} 19 | {% endcomment %} 20 | 21 |
    22 | {% csrf_token %} 23 |
    24 | 25 | {% if form.caption.errors %} 26 |
    27 | {{ form.caption.errors }} 28 |
    29 | {% endif %} 30 | {{ form.caption }} 31 |
    32 |
    33 | 34 | {% if form.content.errors %} 35 |
    36 | {{ form.content.errors }} 37 |
    38 | {% endif %} 39 | {{ form.content }} 40 |
    41 |
    42 | 43 | {% if tag.tag_name.errors %} 44 |
    45 | {{ tag.tag_name.errors }} 46 |
    47 | {% endif %} 48 | {{ tag.tag_name }} 49 |
    50 |
    51 | 52 | Save as Draft 53 |
    54 |
    55 | {% endblock %} 56 | 57 | {% block aside %} 58 |
    59 |
    60 |

    markdown syntax

    61 |
    62 |
    63 | 123 |
    124 |
    125 |
    126 | 131 |
    132 |
    133 | Anim pariatur cliche... 134 |
    135 |
    136 |
    137 |
    138 |
    139 | {% endblock %} 140 | -------------------------------------------------------------------------------- /templates/simpleblog/blog_add_comments.html: -------------------------------------------------------------------------------- 1 | {% load comments %} 2 | {% get_comment_form for blog as blog_form %} 3 |
    4 |
    5 |
    6 | {% csrf_token %} 7 | {{ blog_form.object_pk }} 8 | {{ blog_form.content_type }} 9 | {{ blog_form.timestamp }} 10 | {{ blog_form.site }} 11 | {{ blog_form.submit_date }} 12 | {{ blog_form.security_hash }} 13 |
    14 | 15 |
    16 | 17 |
    18 |
    19 |
    20 | 21 |
    22 | 23 |
    24 |
    25 |
    26 | 27 |
    28 | 29 |
    30 |
    31 |

    32 |
    33 | 34 | {# #} 35 | 36 |
    37 |
    38 |
    39 |
    -------------------------------------------------------------------------------- /templates/simpleblog/blog_add_weibo.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/simpleblog/blog_base.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% load filterlib %} 3 | 4 | {% block extra_head %} 5 | 18 | {% block script %} 19 | 44 | {% endblock %} 45 | {% block showblogscript %}{% endblock %} 46 | {% block otherscript %}{% endblock %} 47 | {% endblock %} 48 | 49 | {% block header %} 50 | {% block menu %} 51 | 121 | 136 | {% endblock %} 137 | {% endblock %} 138 | -------------------------------------------------------------------------------- /templates/simpleblog/blog_comments_show.html: -------------------------------------------------------------------------------- 1 | {% load comments %} 2 | {% load gravatar %} 3 | {% load markup %} 4 |
    5 | {% get_comment_count for blog as comment_count %} 6 |

    {{ comment_count }} Comments

    7 |
    8 | {% get_comment_list for blog as blog_com %} 9 | {% for comment in blog_com %} 10 |
    11 |
    12 |
    13 | 14 |
    15 |
    16 |

    {{ comment.user }}{{ comment.submit_date|date:"F,j,Y" }}

    17 | {{ comment.comment|markdown:'safe,codehilite' }} 18 |
    19 |
    20 |
    21 |
    22 | {% endfor %} 23 |
    -------------------------------------------------------------------------------- /templates/simpleblog/blog_filter.html: -------------------------------------------------------------------------------- 1 | {% extends "blog_base.html" %} 2 | {% load comments %} 3 | 4 | {% block title %} tag: {{ tag.tag_name }} {% endblock %} 5 | 6 | {% block article %} 7 |
    8 | {% for blog in blogs %} 9 |

    {{ blog.caption }}

    10 |
    11 |
    12 |

    {{ blog.publish_time }}

    13 |
    14 |
    15 | 16 | 17 | {% get_comment_count for blog as comment_count %} 18 | {{ comment_count }} 19 |
    20 |
    21 |
    22 | {% empty %} 23 |

    no result!!

    24 | {% endfor %} 25 |
    26 | {% endblock %} 27 | 28 | {% block aside %} 29 | {% block tags %} 30 |
    31 | {% for tag in tags %} 32 | {{ tag }} 33 | {% endfor %} 34 |
    35 | {% endblock %} 36 | {% endblock %} -------------------------------------------------------------------------------- /templates/simpleblog/blog_list.html: -------------------------------------------------------------------------------- 1 | {% extends "blog_base.html" %} 2 | {% load comments %} 3 | 4 | {% block title %} blog list {% endblock %} 5 | 6 | {% block article %} 7 |
    8 | {% for blog in blogs %} 9 |

    {{ blog.caption }}

    10 |

    11 | {% for tag in blog.tags.all %} 12 | {{ tag }} 13 | {% endfor %} 14 |

    15 | {% load markup %} 16 |
    {{ blog.content|markdown:'codehilite' }}
    17 | 18 |
    19 |
    20 |

    {{ blog.publish_time }}

    21 |
    22 |
    23 | 24 | 25 | {% get_comment_count for blog as comment_count %} 26 | {{ comment_count }} 27 |
    28 |
    29 |
    30 | {% endfor %} 31 |
    32 | {% endblock %} 33 | 34 | {% block aside %} 35 | {% block twitter %} 36 |
    37 | {% for weibo in weibos %} 38 |

    {{ weibo }}

    39 |

    {{ weibo.publish_time }}

    40 |
    41 | {% endfor %} 42 |
    43 | {% endblock %} 44 | {% block tags %} 45 |
    46 | {% for tag in tags %} 47 | {{ tag }} 48 | {% endfor %} 49 |
    50 | {% endblock %} 51 | {% endblock %} -------------------------------------------------------------------------------- /templates/simpleblog/blog_show.html: -------------------------------------------------------------------------------- 1 | {% extends "blog_base.html" %} 2 | {% load comments %} 3 | {% load gravatar %} 4 | 5 | {% block title %} {{ blog.caption }} {% endblock %} 6 | {% block showblogscript %} 7 | 33 | {% endblock %} 34 | 35 | 36 | {% block article %} 37 |
    38 | {% block article_title %} 39 |

    {{ blog.caption }}

    40 | {% endblock %} 41 |

    42 | {{ blog.author }} 43 | {{ blog.publish_time }} 44 |

    45 |
    46 |
    47 |
    48 | {% load markup %} 49 | {% block article_content %} 50 | {{ blog.content|markdown:"safe,codehilite" }} 51 | {% endblock %} 52 |
    53 |
    54 |
    55 | 71 |
    72 |
    73 |
    74 | 75 | {% endblock %} 76 | 77 | {% block comments %} 78 |
    79 | {% get_comment_count for blog as comment_count %} 80 |

    {{ comment_count }} Comments

    81 |
    82 | {% get_comment_list for blog as blog_com %} 83 | {% for comment in blog_com %} 84 |
    85 |
    86 |
    87 | 88 |
    89 |
    90 |

    {{ comment.user }}{{ comment.submit_date|date:"F,j,Y" }}

    91 | {{ comment.comment|markdown:'safe,codehilite' }} 92 |
    93 |
    94 |
    95 |
    96 | {% endfor %} 97 |
    98 | 99 |
    100 | {% get_comment_form for blog as blog_form %} 101 |
    102 |

    New Comments

    103 |
    104 |
    105 | {% csrf_token %} 106 | {{ blog_form.object_pk }} 107 | {{ blog_form.content_type }} 108 | {{ blog_form.timestamp }} 109 | {{ blog_form.site }} 110 | {{ blog_form.submit_date }} 111 | {{ blog_form.security_hash }} 112 |
    113 | 114 |
    115 | 116 |
    117 |
    118 |
    119 | 120 |
    121 | 122 |
    123 |
    124 |
    125 | 126 |
    127 | 128 |
    129 |
    130 |

    131 |
    132 | 133 | {# #} 134 | 135 |
    136 |
    137 |
    138 |
    139 |
    140 | {% endblock %} -------------------------------------------------------------------------------- /templates/simpleblog/blog_twitter.html: -------------------------------------------------------------------------------- 1 | {% block twitter %} 2 |
    3 | {% for weibo in weibos %} 4 |

    {{ weibo }}

    5 |

    {{ weibo.publish_time }}

    6 |
    7 | {% endfor %} 8 |
    9 | {% endblock %} -------------------------------------------------------------------------------- /templates/simpleblog/share.html: -------------------------------------------------------------------------------- 1 | 推荐到豆瓣 2 | 3 | 4 | 5 | 6 | 18 | 19 | 分享到饭否 --------------------------------------------------------------------------------