├── .gitignore ├── article ├── __init__.py ├── admin.py ├── forms.py ├── models.py ├── static │ └── images.jpg ├── templates │ ├── article.html │ └── articles.html ├── tests.py ├── urls.py └── views.py ├── firstapp ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py ├── loginsys ├── __init__.py ├── admin.py ├── models.py ├── templates │ ├── login.html │ └── register.html ├── tests.py ├── urls.py └── views.py ├── manage.py ├── static ├── css │ ├── foundation.css │ ├── foundation.min.css │ └── normalize.css ├── img │ └── .gitkeep └── js │ ├── foundation.min.js │ ├── foundation │ ├── foundation.abide.js │ ├── foundation.accordion.js │ ├── foundation.alert.js │ ├── foundation.clearing.js │ ├── foundation.dropdown.js │ ├── foundation.equalizer.js │ ├── foundation.interchange.js │ ├── foundation.joyride.js │ ├── foundation.js │ ├── foundation.magellan.js │ ├── foundation.offcanvas.js │ ├── foundation.orbit.js │ ├── foundation.reveal.js │ ├── foundation.tab.js │ ├── foundation.tooltip.js │ └── foundation.topbar.js │ └── vendor │ ├── fastclick.js │ ├── jquery.cookie.js │ ├── jquery.js │ ├── modernizr.js │ └── placeholder.js └── templates ├── main.html └── myview.html /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.pot 3 | *.pyc 4 | *.sqlite3 5 | *.iml 6 | .idea 7 | .DS_Store 8 | local_settings.py -------------------------------------------------------------------------------- /article/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shadrus/Python-Django-12/252ca7dccfcd224ec69d6ac2b44c300fac94e97b/article/__init__.py -------------------------------------------------------------------------------- /article/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from article.models import Article, Comments 3 | 4 | 5 | # Register your models here. 6 | class ArticleInline(admin.StackedInline): 7 | model = Comments 8 | extra = 2 9 | 10 | 11 | class ArticleAdmin(admin.ModelAdmin): 12 | fields = ['article_title', 'article_text', 'article_date'] 13 | inlines = [ArticleInline] 14 | list_filter = ['article_date'] 15 | 16 | 17 | admin.site.register(Article, ArticleAdmin) 18 | -------------------------------------------------------------------------------- /article/forms.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | __author__ = 'macpro' 3 | 4 | from django.forms import ModelForm 5 | from models import Comments 6 | 7 | class CommentForm(ModelForm): 8 | class Meta: 9 | model = Comments 10 | fields = ['comments_text'] 11 | -------------------------------------------------------------------------------- /article/models.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from django.db import models 4 | 5 | 6 | # Create your models here. 7 | class Article(models.Model): 8 | class Meta(): 9 | db_table = 'article' 10 | 11 | article_title = models.CharField(max_length=200) 12 | article_text = models.TextField() 13 | article_date = models.DateTimeField() 14 | article_likes = models.IntegerField(default=0) 15 | 16 | 17 | class Comments(models.Model): 18 | class Meta(): 19 | db_table = 'comments' 20 | 21 | comments_text = models.TextField(verbose_name="Текст комментария") 22 | comments_article = models.ForeignKey(Article) 23 | -------------------------------------------------------------------------------- /article/static/images.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shadrus/Python-Django-12/252ca7dccfcd224ec69d6ac2b44c300fac94e97b/article/static/images.jpg -------------------------------------------------------------------------------- /article/templates/article.html: -------------------------------------------------------------------------------- 1 | {% extends 'main.html' %} 2 | 3 | {% block article %} 4 |

{{ article.article_date }}

5 |

{{ article.article_title }}

6 |

{{ article.article_text }}

7 |
8 |
Комментарии:

10 | {% for comment in comments %} 11 |

{{ comment.comments_text }}

12 | {% endfor %} 13 | {% if username %} 14 |
15 | {% csrf_token %} 16 | {{ form }} 17 | 18 |
19 | {% endif %} 20 | 21 |
22 | {% endblock %} 23 | -------------------------------------------------------------------------------- /article/templates/articles.html: -------------------------------------------------------------------------------- 1 | {% extends 'main.html' %} 2 | {% load staticfiles %} 3 | 4 | {% block article %} 5 |
6 | {% for article in articles %} 7 |
Дата публикации:{{ article.article_date }}
8 |

{{ article.article_title }}

9 |

{{ article.article_text }}

10 |

{{ article.article_likes }}

11 |
12 | {% endfor %} 13 |
14 |
15 |
16 | 35 |
36 |
37 | {% endblock %} 38 | -------------------------------------------------------------------------------- /article/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /article/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import patterns, include, url 2 | 3 | urlpatterns = patterns('', 4 | # Examples: 5 | # url(r'^$', 'firstapp.views.home', name='home'), 6 | # url(r'^blog/', include('blog.urls')), 7 | 8 | url(r'^1/', 'article.views.basic_one'), 9 | url(r'^2/', 'article.views.template_two'), 10 | url(r'^3/', 'article.views.template_three_simple'), 11 | url(r'^articles/all/$', 'article.views.articles'), 12 | url(r'^articles/get/(?P\d+)/$', 'article.views.article'), 13 | url(r'^articles/addlike/(?P\d+)/$', 'article.views.addlike'), 14 | url(r'^articles/addcomment/(?P\d+)/$', 'article.views.addcomment'), 15 | url(r'^page/(\d+)/$', 'article.views.articles'), 16 | url(r'^', 'article.views.articles'), 17 | 18 | ) 19 | -------------------------------------------------------------------------------- /article/views.py: -------------------------------------------------------------------------------- 1 | from django.http.response import HttpResponse, Http404 2 | from django.template.loader import get_template 3 | from django.template import Context 4 | from django.shortcuts import render_to_response, redirect 5 | from article.models import Article, Comments 6 | from django.core.exceptions import ObjectDoesNotExist 7 | from forms import CommentForm 8 | from django.core.context_processors import csrf 9 | from django.core.paginator import Paginator 10 | from django.contrib import auth 11 | 12 | 13 | # Create your views here. 14 | 15 | def basic_one(request): 16 | view = "basic_one" 17 | html = "This is %s view" % view 18 | return HttpResponse(html) 19 | 20 | def template_two(request): 21 | view = "template_two" 22 | t = get_template('myview.html') 23 | html = t.render(Context({'name': view})) 24 | return HttpResponse(html) 25 | 26 | def template_three_simple(request): 27 | view = "template_three" 28 | return render_to_response('myview.html', {'name': view}) 29 | 30 | def articles(request, page_number=1): 31 | all_articles = Article.objects.all() 32 | current_page = Paginator(all_articles, 2) 33 | return render_to_response('articles.html', {'articles': current_page.page(page_number), 'username': auth.get_user(request).username}) 34 | 35 | def article(request, article_id=1): 36 | comment_form = CommentForm 37 | args = {} 38 | args.update(csrf(request)) 39 | args['article'] = Article.objects.get(id=article_id) 40 | args['comments'] = Comments.objects.filter(comments_article_id=article_id) 41 | args['form'] = comment_form 42 | args['username'] = auth.get_user(request).username 43 | return render_to_response('article.html', args) 44 | 45 | def addlike(request, article_id): 46 | try: 47 | if article_id in request.COOKIES: 48 | redirect('/') 49 | else: 50 | article = Article.objects.get(id=article_id) 51 | article.article_likes += 1 52 | article.save() 53 | response = redirect('/') 54 | response.set_cookie(article_id, "test") 55 | return response 56 | except ObjectDoesNotExist: 57 | raise Http404 58 | return redirect('/') 59 | 60 | 61 | def addcomment(request, article_id): 62 | if request.POST and ("pause" not in request.session): 63 | form = CommentForm(request.POST) 64 | if form.is_valid(): 65 | comment = form.save(commit=False) 66 | comment.comments_article = Article.objects.get(id=article_id) 67 | form.save() 68 | request.session.set_expiry(60) 69 | request.session['pause'] = True 70 | return redirect('/articles/get/%s/' % article_id) 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /firstapp/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shadrus/Python-Django-12/252ca7dccfcd224ec69d6ac2b44c300fac94e97b/firstapp/__init__.py -------------------------------------------------------------------------------- /firstapp/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for firstapp project. 3 | 4 | For more information on this file, see 5 | https://docs.djangoproject.com/en/1.6/topics/settings/ 6 | 7 | For the full list of settings and their values, see 8 | https://docs.djangoproject.com/en/1.6/ref/settings/ 9 | """ 10 | 11 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 12 | import os 13 | BASE_DIR = os.path.dirname(os.path.dirname(__file__)) 14 | 15 | 16 | # Quick-start development settings - unsuitable for production 17 | # See https://docs.djangoproject.com/en/1.6/howto/deployment/checklist/ 18 | 19 | # SECURITY WARNING: keep the secret key used in production secret! 20 | SECRET_KEY = 'ic(xlly-d!qu4unkj@p3aw_%3xd@$#r1!05n@3+t5us=kg4db+' 21 | 22 | # SECURITY WARNING: don't run with debug turned on in production! 23 | DEBUG = True 24 | 25 | TEMPLATE_DEBUG = True 26 | 27 | ALLOWED_HOSTS = [] 28 | 29 | TEMPLATE_DIRS = ( 30 | '/Users/macpro/djangoenv/bin/firstapp/templates', 31 | '/Users/macpro/djangoenv/bin/firstapp/article/templates', 32 | '/Users/macpro/djangoenv/bin/firstapp/loginsys/templates', 33 | ) 34 | 35 | 36 | # Application definition 37 | 38 | INSTALLED_APPS = ( 39 | 'django.contrib.admin', 40 | 'django.contrib.auth', 41 | 'django.contrib.contenttypes', 42 | 'django.contrib.sessions', 43 | 'django.contrib.messages', 44 | 'django.contrib.staticfiles', 45 | 'article', 46 | 'loginsys', 47 | ) 48 | 49 | MIDDLEWARE_CLASSES = ( 50 | 'django.contrib.sessions.middleware.SessionMiddleware', 51 | 'django.middleware.common.CommonMiddleware', 52 | 'django.middleware.csrf.CsrfViewMiddleware', 53 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 54 | 'django.contrib.messages.middleware.MessageMiddleware', 55 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 56 | ) 57 | 58 | ROOT_URLCONF = 'firstapp.urls' 59 | 60 | WSGI_APPLICATION = 'firstapp.wsgi.application' 61 | 62 | 63 | # Database 64 | # https://docs.djangoproject.com/en/1.6/ref/settings/#databases 65 | 66 | DATABASES = { 67 | 'default': { 68 | 'ENGINE': 'django.db.backends.sqlite3', 69 | 'NAME': os.path.join(BASE_DIR, 'our_db.sqlite3'), 70 | } 71 | } 72 | 73 | # Internationalization 74 | # https://docs.djangoproject.com/en/1.6/topics/i18n/ 75 | 76 | LANGUAGE_CODE = 'ru-RU' 77 | 78 | TIME_ZONE = 'UTC' 79 | 80 | USE_I18N = True 81 | 82 | USE_L10N = True 83 | 84 | USE_TZ = True 85 | 86 | 87 | # Static files (CSS, JavaScript, Images) 88 | # https://docs.djangoproject.com/en/1.6/howto/static-files/ 89 | 90 | STATIC_URL = '/static/' 91 | 92 | STATICFILES_DIRS = ( 93 | ('static', '/Users/macpro/djangoenv/bin/firstapp/static'), 94 | ) 95 | -------------------------------------------------------------------------------- /firstapp/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import patterns, include, url 2 | 3 | from django.contrib import admin 4 | 5 | admin.autodiscover() 6 | 7 | urlpatterns = patterns('', 8 | # Examples: 9 | # url(r'^$', 'firstapp.views.home', name='home'), 10 | # url(r'^blog/', include('blog.urls')), 11 | 12 | url(r'^admin/', include(admin.site.urls)), 13 | url(r'^basicview/', include('article.urls')), 14 | url(r'^auth/', include('loginsys.urls')), 15 | url(r'^', include('article.urls')), 16 | 17 | ) 18 | -------------------------------------------------------------------------------- /firstapp/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for firstapp project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.6/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "firstapp.settings") 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | application = get_wsgi_application() 15 | -------------------------------------------------------------------------------- /loginsys/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shadrus/Python-Django-12/252ca7dccfcd224ec69d6ac2b44c300fac94e97b/loginsys/__init__.py -------------------------------------------------------------------------------- /loginsys/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /loginsys/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /loginsys/templates/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'main.html' %} 2 | 3 | {% block login %} 4 |
5 |
6 | {% csrf_token %} 7 | 8 | 9 | 10 | 11 | {% if login_error %} 12 | 13 | {% endif %} 14 | 15 | 16 |
17 |
18 | {% endblock %} -------------------------------------------------------------------------------- /loginsys/templates/register.html: -------------------------------------------------------------------------------- 1 | {% extends 'main.html' %} 2 | 3 | 4 | {% block login %} 5 |
6 |
7 | {% csrf_token %} 8 | {{ form }} 9 | 10 | 11 |
12 |
13 | {% endblock %} -------------------------------------------------------------------------------- /loginsys/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /loginsys/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import patterns, url 2 | 3 | urlpatterns = patterns('', 4 | # Examples: 5 | # url(r'^$', 'firstapp.views.home', name='home'), 6 | # url(r'^blog/', include('blog.urls')), 7 | 8 | url(r'^login/$', 'loginsys.views.login'), 9 | url(r'^logout/$', 'loginsys.views.logout'), 10 | url(r'^register/$', 'loginsys.views.register'), 11 | 12 | ) 13 | -------------------------------------------------------------------------------- /loginsys/views.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from django.shortcuts import render_to_response, redirect 4 | from django.contrib import auth 5 | from django.contrib.auth.forms import UserCreationForm 6 | from django.core.context_processors import csrf 7 | 8 | def login(request): 9 | args = {} 10 | args.update(csrf(request)) 11 | print "test" 12 | if request.POST: 13 | username = request.POST.get('username', '') 14 | password = request.POST.get('password', '') 15 | user = auth.authenticate(username=username, password=password) 16 | if user is not None: 17 | auth.login(request, user) 18 | return redirect('/') 19 | else: 20 | args['login_error'] = "Пользователь не найден" 21 | return render_to_response('login.html', args) 22 | 23 | else: 24 | return render_to_response('login.html', args) 25 | 26 | 27 | def logout(request): 28 | auth.logout(request) 29 | return redirect("/") 30 | 31 | def register(request): 32 | args = {} 33 | args.update(csrf(request)) 34 | args['form'] = UserCreationForm() 35 | if request.POST: 36 | newuser_form = UserCreationForm(request.POST) 37 | if newuser_form.is_valid(): 38 | newuser_form.save() 39 | newuser = auth.authenticate(username=newuser_form.cleaned_data['username'], password=newuser_form.cleaned_data['password2']) 40 | auth.login(request, newuser) 41 | return redirect('/') 42 | else: 43 | args['form'] = newuser_form 44 | return render_to_response('register.html', args) -------------------------------------------------------------------------------- /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", "firstapp.settings") 7 | 8 | from django.core.management import execute_from_command_line 9 | 10 | execute_from_command_line(sys.argv) 11 | -------------------------------------------------------------------------------- /static/css/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v2.1.2 | MIT License | git.io/normalize */ 2 | 3 | /* ========================================================================== 4 | HTML5 display definitions 5 | ========================================================================== */ 6 | 7 | /** 8 | * Correct `block` display not defined in IE 8/9. 9 | */ 10 | 11 | article, 12 | aside, 13 | details, 14 | figcaption, 15 | figure, 16 | footer, 17 | header, 18 | hgroup, 19 | main, 20 | nav, 21 | section, 22 | summary { 23 | display: block; 24 | } 25 | 26 | /** 27 | * Correct `inline-block` display not defined in IE 8/9. 28 | */ 29 | 30 | audio, 31 | canvas, 32 | video { 33 | display: inline-block; 34 | } 35 | 36 | /** 37 | * Prevent modern browsers from displaying `audio` without controls. 38 | * Remove excess height in iOS 5 devices. 39 | */ 40 | 41 | audio:not([controls]) { 42 | display: none; 43 | height: 0; 44 | } 45 | 46 | /** 47 | * Address `[hidden]` styling not present in IE 8/9. 48 | * Hide the `template` element in IE, Safari, and Firefox < 22. 49 | */ 50 | 51 | [hidden], 52 | template { 53 | display: none; 54 | } 55 | 56 | script { 57 | display: none !important; 58 | } 59 | 60 | /* ========================================================================== 61 | Base 62 | ========================================================================== */ 63 | 64 | /** 65 | * 1. Set default font family to sans-serif. 66 | * 2. Prevent iOS text size adjust after orientation change, without disabling 67 | * user zoom. 68 | */ 69 | 70 | html { 71 | font-family: sans-serif; /* 1 */ 72 | -ms-text-size-adjust: 100%; /* 2 */ 73 | -webkit-text-size-adjust: 100%; /* 2 */ 74 | } 75 | 76 | /** 77 | * Remove default margin. 78 | */ 79 | 80 | body { 81 | margin: 0; 82 | } 83 | 84 | /* ========================================================================== 85 | Links 86 | ========================================================================== */ 87 | 88 | /** 89 | * Remove the gray background color from active links in IE 10. 90 | */ 91 | 92 | a { 93 | background: transparent; 94 | } 95 | 96 | /** 97 | * Address `outline` inconsistency between Chrome and other browsers. 98 | */ 99 | 100 | a:focus { 101 | outline: thin dotted; 102 | } 103 | 104 | /** 105 | * Improve readability when focused and also mouse hovered in all browsers. 106 | */ 107 | 108 | a:active, 109 | a:hover { 110 | outline: 0; 111 | } 112 | 113 | /* ========================================================================== 114 | Typography 115 | ========================================================================== */ 116 | 117 | /** 118 | * Address variable `h1` font-size and margin within `section` and `article` 119 | * contexts in Firefox 4+, Safari 5, and Chrome. 120 | */ 121 | 122 | h1 { 123 | font-size: 2em; 124 | margin: 0.67em 0; 125 | } 126 | 127 | /** 128 | * Address styling not present in IE 8/9, Safari 5, and Chrome. 129 | */ 130 | 131 | abbr[title] { 132 | border-bottom: 1px dotted; 133 | } 134 | 135 | /** 136 | * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. 137 | */ 138 | 139 | b, 140 | strong { 141 | font-weight: bold; 142 | } 143 | 144 | /** 145 | * Address styling not present in Safari 5 and Chrome. 146 | */ 147 | 148 | dfn { 149 | font-style: italic; 150 | } 151 | 152 | /** 153 | * Address differences between Firefox and other browsers. 154 | */ 155 | 156 | hr { 157 | -moz-box-sizing: content-box; 158 | box-sizing: content-box; 159 | height: 0; 160 | } 161 | 162 | /** 163 | * Address styling not present in IE 8/9. 164 | */ 165 | 166 | mark { 167 | background: #ff0; 168 | color: #000; 169 | } 170 | 171 | /** 172 | * Correct font family set oddly in Safari 5 and Chrome. 173 | */ 174 | 175 | code, 176 | kbd, 177 | pre, 178 | samp { 179 | font-family: monospace, serif; 180 | font-size: 1em; 181 | } 182 | 183 | /** 184 | * Improve readability of pre-formatted text in all browsers. 185 | */ 186 | 187 | pre { 188 | white-space: pre-wrap; 189 | } 190 | 191 | /** 192 | * Set consistent quote types. 193 | */ 194 | 195 | q { 196 | quotes: "\201C" "\201D" "\2018" "\2019"; 197 | } 198 | 199 | /** 200 | * Address inconsistent and variable font size in all browsers. 201 | */ 202 | 203 | small { 204 | font-size: 80%; 205 | } 206 | 207 | /** 208 | * Prevent `sub` and `sup` affecting `line-height` in all browsers. 209 | */ 210 | 211 | sub, 212 | sup { 213 | font-size: 75%; 214 | line-height: 0; 215 | position: relative; 216 | vertical-align: baseline; 217 | } 218 | 219 | sup { 220 | top: -0.5em; 221 | } 222 | 223 | sub { 224 | bottom: -0.25em; 225 | } 226 | 227 | /* ========================================================================== 228 | Embedded content 229 | ========================================================================== */ 230 | 231 | /** 232 | * Remove border when inside `a` element in IE 8/9. 233 | */ 234 | 235 | img { 236 | border: 0; 237 | } 238 | 239 | /** 240 | * Correct overflow displayed oddly in IE 9. 241 | */ 242 | 243 | svg:not(:root) { 244 | overflow: hidden; 245 | } 246 | 247 | /* ========================================================================== 248 | Figures 249 | ========================================================================== */ 250 | 251 | /** 252 | * Address margin not present in IE 8/9 and Safari 5. 253 | */ 254 | 255 | figure { 256 | margin: 0; 257 | } 258 | 259 | /* ========================================================================== 260 | Forms 261 | ========================================================================== */ 262 | 263 | /** 264 | * Define consistent border, margin, and padding. 265 | */ 266 | 267 | fieldset { 268 | border: 1px solid #c0c0c0; 269 | margin: 0 2px; 270 | padding: 0.35em 0.625em 0.75em; 271 | } 272 | 273 | /** 274 | * 1. Correct `color` not being inherited in IE 8/9. 275 | * 2. Remove padding so people aren't caught out if they zero out fieldsets. 276 | */ 277 | 278 | legend { 279 | border: 0; /* 1 */ 280 | padding: 0; /* 2 */ 281 | } 282 | 283 | /** 284 | * 1. Correct font family not being inherited in all browsers. 285 | * 2. Correct font size not being inherited in all browsers. 286 | * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. 287 | */ 288 | 289 | button, 290 | input, 291 | select, 292 | textarea { 293 | font-family: inherit; /* 1 */ 294 | font-size: 100%; /* 2 */ 295 | margin: 0; /* 3 */ 296 | } 297 | 298 | /** 299 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in 300 | * the UA stylesheet. 301 | */ 302 | 303 | button, 304 | input { 305 | line-height: normal; 306 | } 307 | 308 | /** 309 | * Address inconsistent `text-transform` inheritance for `button` and `select`. 310 | * All other form control elements do not inherit `text-transform` values. 311 | * Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. 312 | * Correct `select` style inheritance in Firefox 4+ and Opera. 313 | */ 314 | 315 | button, 316 | select { 317 | text-transform: none; 318 | } 319 | 320 | /** 321 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` 322 | * and `video` controls. 323 | * 2. Correct inability to style clickable `input` types in iOS. 324 | * 3. Improve usability and consistency of cursor style between image-type 325 | * `input` and others. 326 | */ 327 | 328 | button, 329 | html input[type="button"], /* 1 */ 330 | input[type="reset"], 331 | input[type="submit"] { 332 | -webkit-appearance: button; /* 2 */ 333 | cursor: pointer; /* 3 */ 334 | } 335 | 336 | /** 337 | * Re-set default cursor for disabled elements. 338 | */ 339 | 340 | button[disabled], 341 | html input[disabled] { 342 | cursor: default; 343 | } 344 | 345 | /** 346 | * 1. Address box sizing set to `content-box` in IE 8/9. 347 | * 2. Remove excess padding in IE 8/9. 348 | */ 349 | 350 | input[type="checkbox"], 351 | input[type="radio"] { 352 | box-sizing: border-box; /* 1 */ 353 | padding: 0; /* 2 */ 354 | } 355 | 356 | /** 357 | * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. 358 | * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome 359 | * (include `-moz` to future-proof). 360 | */ 361 | 362 | input[type="search"] { 363 | -webkit-appearance: textfield; /* 1 */ 364 | -moz-box-sizing: content-box; 365 | -webkit-box-sizing: content-box; /* 2 */ 366 | box-sizing: content-box; 367 | } 368 | 369 | /** 370 | * Remove inner padding and search cancel button in Safari 5 and Chrome 371 | * on OS X. 372 | */ 373 | 374 | input[type="search"]::-webkit-search-cancel-button, 375 | input[type="search"]::-webkit-search-decoration { 376 | -webkit-appearance: none; 377 | } 378 | 379 | /** 380 | * Remove inner padding and border in Firefox 4+. 381 | */ 382 | 383 | button::-moz-focus-inner, 384 | input::-moz-focus-inner { 385 | border: 0; 386 | padding: 0; 387 | } 388 | 389 | /** 390 | * 1. Remove default vertical scrollbar in IE 8/9. 391 | * 2. Improve readability and alignment in all browsers. 392 | */ 393 | 394 | textarea { 395 | overflow: auto; /* 1 */ 396 | vertical-align: top; /* 2 */ 397 | } 398 | 399 | /* ========================================================================== 400 | Tables 401 | ========================================================================== */ 402 | 403 | /** 404 | * Remove most spacing between table cells. 405 | */ 406 | 407 | table { 408 | border-collapse: collapse; 409 | border-spacing: 0; 410 | } 411 | -------------------------------------------------------------------------------- /static/img/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/js/foundation/foundation.abide.js: -------------------------------------------------------------------------------- 1 | ;(function ($, window, document, undefined) { 2 | 'use strict'; 3 | 4 | Foundation.libs.abide = { 5 | name : 'abide', 6 | 7 | version : '5.1.0', 8 | 9 | settings : { 10 | live_validate : true, 11 | focus_on_invalid : true, 12 | error_labels: true, // labels with a for="inputId" will recieve an `error` class 13 | timeout : 1000, 14 | patterns : { 15 | alpha: /^[a-zA-Z]+$/, 16 | alpha_numeric : /^[a-zA-Z0-9]+$/, 17 | integer: /^\d+$/, 18 | number: /-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?/, 19 | 20 | // generic password: upper-case, lower-case, number/special character, and min 8 characters 21 | password : /(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/, 22 | 23 | // amex, visa, diners 24 | card : /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/, 25 | cvv : /^([0-9]){3,4}$/, 26 | 27 | // http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#valid-e-mail-address 28 | email : /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/, 29 | 30 | url: /(https?|ftp|file|ssh):\/\/(((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?/, 31 | // abc.de 32 | domain: /^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$/, 33 | 34 | datetime: /([0-2][0-9]{3})\-([0-1][0-9])\-([0-3][0-9])T([0-5][0-9])\:([0-5][0-9])\:([0-5][0-9])(Z|([\-\+]([0-1][0-9])\:00))/, 35 | // YYYY-MM-DD 36 | date: /(?:19|20)[0-9]{2}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9])|(?:(?!02)(?:0[1-9]|1[0-2])-(?:30))|(?:(?:0[13578]|1[02])-31))/, 37 | // HH:MM:SS 38 | time : /(0[0-9]|1[0-9]|2[0-3])(:[0-5][0-9]){2}/, 39 | dateISO: /\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/, 40 | // MM/DD/YYYY 41 | month_day_year : /(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.](19|20)\d\d/, 42 | 43 | // #FFF or #FFFFFF 44 | color: /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/ 45 | } 46 | }, 47 | 48 | timer : null, 49 | 50 | init : function (scope, method, options) { 51 | this.bindings(method, options); 52 | }, 53 | 54 | events : function (scope) { 55 | var self = this, 56 | form = self.S(scope).attr('novalidate', 'novalidate'), 57 | settings = form.data(this.attr_name(true) + '-init'); 58 | 59 | this.invalid_attr = this.add_namespace('data-invalid'); 60 | 61 | form 62 | .off('.abide') 63 | .on('submit.fndtn.abide validate.fndtn.abide', function (e) { 64 | var is_ajax = /ajax/i.test(self.S(this).attr(self.attr_name())); 65 | return self.validate(self.S(this).find('input, textarea, select').get(), e, is_ajax); 66 | }) 67 | .on('reset', function() { 68 | return self.reset($(this)); 69 | }) 70 | .find('input, textarea, select') 71 | .off('.abide') 72 | .on('blur.fndtn.abide change.fndtn.abide', function (e) { 73 | self.validate([this], e); 74 | }) 75 | .on('keydown.fndtn.abide', function (e) { 76 | var settings = $(this).closest('form').data('abide-init'); 77 | if (settings.live_validate === true) { 78 | clearTimeout(self.timer); 79 | self.timer = setTimeout(function () { 80 | self.validate([this], e); 81 | }.bind(this), settings.timeout); 82 | } 83 | }); 84 | }, 85 | 86 | reset : function (form) { 87 | form.removeAttr(this.invalid_attr); 88 | $(this.invalid_attr, form).removeAttr(this.invalid_attr); 89 | $('.error', form).not('small').removeClass('error'); 90 | }, 91 | 92 | validate : function (els, e, is_ajax) { 93 | var validations = this.parse_patterns(els), 94 | validation_count = validations.length, 95 | form = this.S(els[0]).closest('form'), 96 | submit_event = /submit/.test(e.type); 97 | 98 | // Has to count up to make sure the focus gets applied to the top error 99 | for (var i=0; i < validation_count; i++) { 100 | if (!validations[i] && (submit_event || is_ajax)) { 101 | if (this.settings.focus_on_invalid) els[i].focus(); 102 | form.trigger('invalid'); 103 | this.S(els[i]).closest('form').attr(this.invalid_attr, ''); 104 | return false; 105 | } 106 | } 107 | 108 | if (submit_event || is_ajax) { 109 | form.trigger('valid'); 110 | } 111 | 112 | form.removeAttr(this.invalid_attr); 113 | 114 | if (is_ajax) return false; 115 | 116 | return true; 117 | }, 118 | 119 | parse_patterns : function (els) { 120 | var i = els.length, 121 | el_patterns = []; 122 | 123 | while (i--) { 124 | el_patterns.push(this.pattern(els[i])); 125 | } 126 | 127 | return this.check_validation_and_apply_styles(el_patterns); 128 | }, 129 | 130 | pattern : function (el) { 131 | var type = el.getAttribute('type'), 132 | required = typeof el.getAttribute('required') === 'string'; 133 | 134 | var pattern = el.getAttribute('pattern') || ''; 135 | 136 | if (this.settings.patterns.hasOwnProperty(pattern) && pattern.length > 0) { 137 | return [el, this.settings.patterns[pattern], required]; 138 | } else if (pattern.length > 0) { 139 | return [el, new RegExp(pattern), required]; 140 | } 141 | 142 | if (this.settings.patterns.hasOwnProperty(type)) { 143 | return [el, this.settings.patterns[type], required]; 144 | } 145 | 146 | pattern = /.*/; 147 | 148 | return [el, pattern, required]; 149 | }, 150 | 151 | check_validation_and_apply_styles : function (el_patterns) { 152 | var i = el_patterns.length, 153 | validations = []; 154 | 155 | while (i--) { 156 | var el = el_patterns[i][0], 157 | required = el_patterns[i][2], 158 | value = el.value, 159 | direct_parent = this.S(el).parent(), 160 | is_equal = el.getAttribute(this.add_namespace('data-equalto')), 161 | is_radio = el.type === "radio", 162 | is_checkbox = el.type === "checkbox", 163 | label = this.S('label[for="' + el.getAttribute('id') + '"]'), 164 | valid_length = (required) ? (el.value.length > 0) : true; 165 | 166 | var parent; 167 | 168 | if (!direct_parent.is('label')) { 169 | parent = direct_parent; 170 | } else { 171 | parent = direct_parent.parent(); 172 | } 173 | 174 | if (is_radio && required) { 175 | validations.push(this.valid_radio(el, required)); 176 | } else if (is_checkbox && required) { 177 | validations.push(this.valid_checkbox(el, required)); 178 | } else if (is_equal && required) { 179 | validations.push(this.valid_equal(el, required, parent)); 180 | } else { 181 | 182 | if (el_patterns[i][1].test(value) && valid_length || 183 | !required && el.value.length < 1) { 184 | this.S(el).removeAttr(this.invalid_attr); 185 | parent.removeClass('error'); 186 | if (label.length > 0 && this.settings.error_labels) label.removeClass('error'); 187 | 188 | validations.push(true); 189 | $(el).triggerHandler('valid'); 190 | } else { 191 | this.S(el).attr(this.invalid_attr, ''); 192 | parent.addClass('error'); 193 | if (label.length > 0 && this.settings.error_labels) label.addClass('error'); 194 | 195 | validations.push(false); 196 | $(el).triggerHandler('invalid'); 197 | } 198 | } 199 | } 200 | 201 | return validations; 202 | }, 203 | 204 | valid_checkbox : function(el, required) { 205 | var el = this.S(el), 206 | valid = (el.is(':checked') || !required); 207 | 208 | if (valid) { 209 | el.removeAttr(this.invalid_attr).parent().removeClass('error'); 210 | } else { 211 | el.attr(this.invalid_attr, '').parent().addClass('error'); 212 | } 213 | 214 | return valid; 215 | }, 216 | 217 | valid_radio : function (el, required) { 218 | var name = el.getAttribute('name'), 219 | group = document.getElementsByName(name), 220 | count = group.length, 221 | valid = false; 222 | 223 | // Has to count up to make sure the focus gets applied to the top error 224 | for (var i=0; i < count; i++) { 225 | if (group[i].checked) valid = true; 226 | } 227 | 228 | // Has to count up to make sure the focus gets applied to the top error 229 | for (var i=0; i < count; i++) { 230 | if (valid) { 231 | this.S(group[i]).removeAttr(this.invalid_attr).parent().removeClass('error'); 232 | } else { 233 | this.S(group[i]).attr(this.invalid_attr, '').parent().addClass('error'); 234 | } 235 | } 236 | 237 | return valid; 238 | }, 239 | 240 | valid_equal: function(el, required, parent) { 241 | var from = document.getElementById(el.getAttribute(this.add_namespace('data-equalto'))).value, 242 | to = el.value, 243 | valid = (from === to); 244 | 245 | if (valid) { 246 | this.S(el).removeAttr(this.invalid_attr); 247 | parent.removeClass('error'); 248 | } else { 249 | this.S(el).attr(this.invalid_attr, ''); 250 | parent.addClass('error'); 251 | } 252 | 253 | return valid; 254 | } 255 | }; 256 | }(jQuery, this, this.document)); 257 | -------------------------------------------------------------------------------- /static/js/foundation/foundation.accordion.js: -------------------------------------------------------------------------------- 1 | ;(function ($, window, document, undefined) { 2 | 'use strict'; 3 | 4 | Foundation.libs.accordion = { 5 | name : 'accordion', 6 | 7 | version : '5.1.0', 8 | 9 | settings : { 10 | active_class: 'active', 11 | toggleable: true 12 | }, 13 | 14 | init : function (scope, method, options) { 15 | this.bindings(method, options); 16 | }, 17 | 18 | events : function () { 19 | var self = this; 20 | var S = this.S; 21 | S(this.scope) 22 | .off('.fndtn.accordion') 23 | .on('click.fndtn.accordion', '[' + this.attr_name() + '] > dd > a', function (e) { 24 | var accordion = S(this).closest('[' + self.attr_name() + ']'), 25 | target = S('#' + this.href.split('#')[1]), 26 | siblings = S('dd > .content', accordion), 27 | aunts = $('> dd', accordion), 28 | settings = accordion.data(self.attr_name(true) + '-init'), 29 | active_content = S('dd > .content.' + settings.active_class, accordion), 30 | active_parent = S('dd.' + settings.active_class, accordion); 31 | 32 | e.preventDefault(); 33 | 34 | if (active_content[0] == target[0] && settings.toggleable) { 35 | active_parent.toggleClass(settings.active_class, false); 36 | return target.toggleClass(settings.active_class, false); 37 | } 38 | 39 | siblings.removeClass(settings.active_class); 40 | aunts.removeClass(settings.active_class); 41 | target.addClass(settings.active_class).parent().addClass(settings.active_class); 42 | }); 43 | }, 44 | 45 | off : function () {}, 46 | 47 | reflow : function () {} 48 | }; 49 | }(jQuery, this, this.document)); 50 | -------------------------------------------------------------------------------- /static/js/foundation/foundation.alert.js: -------------------------------------------------------------------------------- 1 | ;(function ($, window, document, undefined) { 2 | 'use strict'; 3 | 4 | Foundation.libs.alert = { 5 | name : 'alert', 6 | 7 | version : '5.1.0', 8 | 9 | settings : { 10 | animation: 'fadeOut', 11 | speed: 300, // fade out speed 12 | callback: function (){} 13 | }, 14 | 15 | init : function (scope, method, options) { 16 | this.bindings(method, options); 17 | }, 18 | 19 | events : function () { 20 | var self = this, 21 | S = this.S; 22 | 23 | $(this.scope).off('.alert').on('click.fndtn.alert', '[' + this.attr_name() + '] a.close', function (e) { 24 | var alertBox = S(this).closest('[' + self.attr_name() + ']'), 25 | settings = alertBox.data(self.attr_name(true) + '-init') || self.settings; 26 | 27 | e.preventDefault(); 28 | alertBox[settings.animation](settings.speed, function () { 29 | S(this).trigger('closed').remove(); 30 | settings.callback(); 31 | }); 32 | }); 33 | }, 34 | 35 | reflow : function () {} 36 | }; 37 | }(jQuery, this, this.document)); 38 | -------------------------------------------------------------------------------- /static/js/foundation/foundation.clearing.js: -------------------------------------------------------------------------------- 1 | ;(function ($, window, document, undefined) { 2 | 'use strict'; 3 | 4 | Foundation.libs.clearing = { 5 | name : 'clearing', 6 | 7 | version: '5.1.0', 8 | 9 | settings : { 10 | templates : { 11 | viewing : '×' + 12 | '' 15 | }, 16 | 17 | // comma delimited list of selectors that, on click, will close clearing, 18 | // add 'div.clearing-blackout, div.visible-img' to close on background click 19 | close_selectors : '.clearing-close', 20 | 21 | touch_label : '← Swipe to Advance →', 22 | 23 | // event initializers and locks 24 | init : false, 25 | locked : false 26 | }, 27 | 28 | init : function (scope, method, options) { 29 | var self = this; 30 | Foundation.inherit(this, 'throttle image_loaded'); 31 | 32 | this.bindings(method, options); 33 | 34 | if (self.S(this.scope).is('[' + this.attr_name() + ']')) { 35 | this.assemble(self.S('li', this.scope)); 36 | } else { 37 | self.S('[' + this.attr_name() + ']', this.scope).each(function () { 38 | self.assemble(self.S('li', this)); 39 | }); 40 | } 41 | }, 42 | 43 | events : function (scope) { 44 | var self = this, 45 | S = self.S; 46 | 47 | S(this.scope) 48 | .off('.clearing') 49 | .on('click.fndtn.clearing', 'ul[' + this.attr_name() + '] li', 50 | function (e, current, target) { 51 | var current = current || S(this), 52 | target = target || current, 53 | next = current.next('li'), 54 | settings = current.closest('[' + self.attr_name() + ']').data(self.attr_name(true) + '-init'), 55 | image = S(e.target); 56 | 57 | e.preventDefault(); 58 | 59 | if (!settings) { 60 | self.init(); 61 | settings = current.closest('[' + self.attr_name() + ']').data(self.attr_name(true) + '-init'); 62 | } 63 | 64 | // if clearing is open and the current image is 65 | // clicked, go to the next image in sequence 66 | if (target.hasClass('visible') && 67 | current[0] === target[0] && 68 | next.length > 0 && self.is_open(current)) { 69 | target = next; 70 | image = S('img', target); 71 | } 72 | 73 | // set current and target to the clicked li if not otherwise defined. 74 | self.open(image, current, target); 75 | self.update_paddles(target); 76 | }) 77 | 78 | .on('click.fndtn.clearing', '.clearing-main-next', 79 | function (e) { self.nav(e, 'next') }) 80 | .on('click.fndtn.clearing', '.clearing-main-prev', 81 | function (e) { self.nav(e, 'prev') }) 82 | .on('click.fndtn.clearing', this.settings.close_selectors, 83 | function (e) { Foundation.libs.clearing.close(e, this) }) 84 | .on('keydown.fndtn.clearing', 85 | function (e) { self.keydown(e) }); 86 | 87 | S(window).off('.clearing').on('resize.fndtn.clearing', 88 | function () { self.resize() }); 89 | 90 | this.swipe_events(scope); 91 | }, 92 | 93 | swipe_events : function (scope) { 94 | var self = this, 95 | S = self.S; 96 | 97 | S(this.scope) 98 | .on('touchstart.fndtn.clearing', '.visible-img', function(e) { 99 | if (!e.touches) { e = e.originalEvent; } 100 | var data = { 101 | start_page_x: e.touches[0].pageX, 102 | start_page_y: e.touches[0].pageY, 103 | start_time: (new Date()).getTime(), 104 | delta_x: 0, 105 | is_scrolling: undefined 106 | }; 107 | 108 | S(this).data('swipe-transition', data); 109 | e.stopPropagation(); 110 | }) 111 | .on('touchmove.fndtn.clearing', '.visible-img', function(e) { 112 | if (!e.touches) { e = e.originalEvent; } 113 | // Ignore pinch/zoom events 114 | if(e.touches.length > 1 || e.scale && e.scale !== 1) return; 115 | 116 | var data = S(this).data('swipe-transition'); 117 | 118 | if (typeof data === 'undefined') { 119 | data = {}; 120 | } 121 | 122 | data.delta_x = e.touches[0].pageX - data.start_page_x; 123 | 124 | if ( typeof data.is_scrolling === 'undefined') { 125 | data.is_scrolling = !!( data.is_scrolling || Math.abs(data.delta_x) < Math.abs(e.touches[0].pageY - data.start_page_y) ); 126 | } 127 | 128 | if (!data.is_scrolling && !data.active) { 129 | e.preventDefault(); 130 | var direction = (data.delta_x < 0) ? 'next' : 'prev'; 131 | data.active = true; 132 | self.nav(e, direction); 133 | } 134 | }) 135 | .on('touchend.fndtn.clearing', '.visible-img', function(e) { 136 | S(this).data('swipe-transition', {}); 137 | e.stopPropagation(); 138 | }); 139 | }, 140 | 141 | assemble : function ($li) { 142 | var $el = $li.parent(); 143 | 144 | if ($el.parent().hasClass('carousel')) return; 145 | $el.after('
'); 146 | 147 | var holder = this.S('#foundationClearingHolder'), 148 | settings = $el.data(this.attr_name(true) + '-init'), 149 | grid = $el.detach(), 150 | data = { 151 | grid: '', 152 | viewing: settings.templates.viewing 153 | }, 154 | wrapper = '
' + data.viewing + 155 | data.grid + '
', 156 | touch_label = this.settings.touch_label; 157 | 158 | if (Modernizr.touch) { 159 | wrapper = $(wrapper).find('.clearing-touch-label').html(touch_label).end(); 160 | } 161 | 162 | holder.after(wrapper).remove(); 163 | }, 164 | 165 | open : function ($image, current, target) { 166 | var self = this, 167 | root = target.closest('.clearing-assembled'), 168 | container = self.S('div', root).first(), 169 | visible_image = self.S('.visible-img', container), 170 | image = self.S('img', visible_image).not($image), 171 | label = self.S('.clearing-touch-label', container); 172 | 173 | if (!this.locked()) { 174 | // set the image to the selected thumbnail 175 | image 176 | .attr('src', this.load($image)) 177 | .css('visibility', 'hidden'); 178 | 179 | this.image_loaded(image, function () { 180 | image.css('visibility', 'visible'); 181 | // toggle the gallery 182 | root.addClass('clearing-blackout'); 183 | container.addClass('clearing-container'); 184 | visible_image.show(); 185 | this.fix_height(target) 186 | .caption(self.S('.clearing-caption', visible_image), $image) 187 | .center_and_label(image,label) 188 | .shift(current, target, function () { 189 | target.siblings().removeClass('visible'); 190 | target.addClass('visible'); 191 | }); 192 | }.bind(this)); 193 | } 194 | }, 195 | 196 | close : function (e, el) { 197 | e.preventDefault(); 198 | 199 | var root = (function (target) { 200 | if (/blackout/.test(target.selector)) { 201 | return target; 202 | } else { 203 | return target.closest('.clearing-blackout'); 204 | } 205 | }($(el))), container, visible_image; 206 | 207 | if (el === e.target && root) { 208 | container = $('div', root).first(); 209 | visible_image = $('.visible-img', container); 210 | this.settings.prev_index = 0; 211 | $('ul[' + this.attr_name() + ']', root) 212 | .attr('style', '').closest('.clearing-blackout') 213 | .removeClass('clearing-blackout'); 214 | container.removeClass('clearing-container'); 215 | visible_image.hide(); 216 | } 217 | 218 | return false; 219 | }, 220 | 221 | is_open : function (current) { 222 | return current.parent().prop('style').length > 0; 223 | }, 224 | 225 | keydown : function (e) { 226 | var clearing = $('ul[' + this.attr_name() + ']', '.clearing-blackout'), 227 | NEXT_KEY = this.rtl ? 37 : 39, 228 | PREV_KEY = this.rtl ? 39 : 37, 229 | ESC_KEY = 27; 230 | 231 | if (e.which === NEXT_KEY) this.go(clearing, 'next'); 232 | if (e.which === PREV_KEY) this.go(clearing, 'prev'); 233 | if (e.which === ESC_KEY) this.S('a.clearing-close').trigger('click'); 234 | }, 235 | 236 | nav : function (e, direction) { 237 | var clearing = $('ul[' + this.attr_name() + ']', '.clearing-blackout'); 238 | 239 | e.preventDefault(); 240 | this.go(clearing, direction); 241 | }, 242 | 243 | resize : function () { 244 | var image = $('img', '.clearing-blackout .visible-img'), 245 | label = $('.clearing-touch-label', '.clearing-blackout'); 246 | 247 | if (image.length) { 248 | this.center_and_label(image, label); 249 | } 250 | }, 251 | 252 | // visual adjustments 253 | fix_height : function (target) { 254 | var lis = target.parent().children(), 255 | self = this; 256 | 257 | lis.each(function () { 258 | var li = self.S(this), 259 | image = li.find('img'); 260 | 261 | if (li.height() > image.outerHeight()) { 262 | li.addClass('fix-height'); 263 | } 264 | }) 265 | .closest('ul') 266 | .width(lis.length * 100 + '%'); 267 | 268 | return this; 269 | }, 270 | 271 | update_paddles : function (target) { 272 | var visible_image = target 273 | .closest('.carousel') 274 | .siblings('.visible-img'); 275 | 276 | if (target.next().length > 0) { 277 | this.S('.clearing-main-next', visible_image) 278 | .removeClass('disabled'); 279 | } else { 280 | this.S('.clearing-main-next', visible_image) 281 | .addClass('disabled'); 282 | } 283 | 284 | if (target.prev().length > 0) { 285 | this.S('.clearing-main-prev', visible_image) 286 | .removeClass('disabled'); 287 | } else { 288 | this.S('.clearing-main-prev', visible_image) 289 | .addClass('disabled'); 290 | } 291 | }, 292 | 293 | center_and_label : function (target, label) { 294 | if (!this.rtl) { 295 | target.css({ 296 | marginLeft : -(target.outerWidth() / 2), 297 | marginTop : -(target.outerHeight() / 2) 298 | }); 299 | label.css({ 300 | marginLeft : -(label.outerWidth() / 2), 301 | marginTop : -(target.outerHeight() / 2)-label.outerHeight()-10 302 | }); 303 | } else { 304 | target.css({ 305 | marginRight : -(target.outerWidth() / 2), 306 | marginTop : -(target.outerHeight() / 2), 307 | left: 'auto', 308 | right: '50%' 309 | }); 310 | label.css({ 311 | marginRight : -(label.outerWidth() / 2), 312 | marginTop : -(target.outerHeight() / 2)-label.outerHeight()-10, 313 | left: 'auto', 314 | right: '50%' 315 | }); 316 | } 317 | return this; 318 | }, 319 | 320 | // image loading and preloading 321 | 322 | load : function ($image) { 323 | if ($image[0].nodeName === "A") { 324 | var href = $image.attr('href'); 325 | } else { 326 | var href = $image.parent().attr('href'); 327 | } 328 | 329 | this.preload($image); 330 | 331 | if (href) return href; 332 | return $image.attr('src'); 333 | }, 334 | 335 | preload : function ($image) { 336 | this 337 | .img($image.closest('li').next()) 338 | .img($image.closest('li').prev()); 339 | }, 340 | 341 | img : function (img) { 342 | if (img.length) { 343 | var new_img = new Image(), 344 | new_a = this.S('a', img); 345 | 346 | if (new_a.length) { 347 | new_img.src = new_a.attr('href'); 348 | } else { 349 | new_img.src = this.S('img', img).attr('src'); 350 | } 351 | } 352 | return this; 353 | }, 354 | 355 | // image caption 356 | 357 | caption : function (container, $image) { 358 | var caption = $image.data('caption'); 359 | 360 | if (caption) { 361 | container 362 | .html(caption) 363 | .show(); 364 | } else { 365 | container 366 | .text('') 367 | .hide(); 368 | } 369 | return this; 370 | }, 371 | 372 | // directional methods 373 | 374 | go : function ($ul, direction) { 375 | var current = this.S('.visible', $ul), 376 | target = current[direction](); 377 | 378 | if (target.length) { 379 | this.S('img', target) 380 | .trigger('click', [current, target]); 381 | } 382 | }, 383 | 384 | shift : function (current, target, callback) { 385 | var clearing = target.parent(), 386 | old_index = this.settings.prev_index || target.index(), 387 | direction = this.direction(clearing, current, target), 388 | dir = this.rtl ? 'right' : 'left', 389 | left = parseInt(clearing.css('left'), 10), 390 | width = target.outerWidth(), 391 | skip_shift; 392 | 393 | var dir_obj = {}; 394 | 395 | // we use jQuery animate instead of CSS transitions because we 396 | // need a callback to unlock the next animation 397 | // needs support for RTL ** 398 | if (target.index() !== old_index && !/skip/.test(direction)){ 399 | if (/left/.test(direction)) { 400 | this.lock(); 401 | dir_obj[dir] = left + width; 402 | clearing.animate(dir_obj, 300, this.unlock()); 403 | } else if (/right/.test(direction)) { 404 | this.lock(); 405 | dir_obj[dir] = left - width; 406 | clearing.animate(dir_obj, 300, this.unlock()); 407 | } 408 | } else if (/skip/.test(direction)) { 409 | // the target image is not adjacent to the current image, so 410 | // do we scroll right or not 411 | skip_shift = target.index() - this.settings.up_count; 412 | this.lock(); 413 | 414 | if (skip_shift > 0) { 415 | dir_obj[dir] = -(skip_shift * width); 416 | clearing.animate(dir_obj, 300, this.unlock()); 417 | } else { 418 | dir_obj[dir] = 0; 419 | clearing.animate(dir_obj, 300, this.unlock()); 420 | } 421 | } 422 | 423 | callback(); 424 | }, 425 | 426 | direction : function ($el, current, target) { 427 | var lis = this.S('li', $el), 428 | li_width = lis.outerWidth() + (lis.outerWidth() / 4), 429 | up_count = Math.floor(this.S('.clearing-container').outerWidth() / li_width) - 1, 430 | target_index = lis.index(target), 431 | response; 432 | 433 | this.settings.up_count = up_count; 434 | 435 | if (this.adjacent(this.settings.prev_index, target_index)) { 436 | if ((target_index > up_count) 437 | && target_index > this.settings.prev_index) { 438 | response = 'right'; 439 | } else if ((target_index > up_count - 1) 440 | && target_index <= this.settings.prev_index) { 441 | response = 'left'; 442 | } else { 443 | response = false; 444 | } 445 | } else { 446 | response = 'skip'; 447 | } 448 | 449 | this.settings.prev_index = target_index; 450 | 451 | return response; 452 | }, 453 | 454 | adjacent : function (current_index, target_index) { 455 | for (var i = target_index + 1; i >= target_index - 1; i--) { 456 | if (i === current_index) return true; 457 | } 458 | return false; 459 | }, 460 | 461 | // lock management 462 | 463 | lock : function () { 464 | this.settings.locked = true; 465 | }, 466 | 467 | unlock : function () { 468 | this.settings.locked = false; 469 | }, 470 | 471 | locked : function () { 472 | return this.settings.locked; 473 | }, 474 | 475 | off : function () { 476 | this.S(this.scope).off('.fndtn.clearing'); 477 | this.S(window).off('.fndtn.clearing'); 478 | }, 479 | 480 | reflow : function () { 481 | this.init(); 482 | } 483 | }; 484 | 485 | }(jQuery, this, this.document)); 486 | -------------------------------------------------------------------------------- /static/js/foundation/foundation.dropdown.js: -------------------------------------------------------------------------------- 1 | ;(function ($, window, document, undefined) { 2 | 'use strict'; 3 | 4 | Foundation.libs.dropdown = { 5 | name : 'dropdown', 6 | 7 | version : '5.1.0', 8 | 9 | settings : { 10 | active_class: 'open', 11 | is_hover: false, 12 | opened: function(){}, 13 | closed: function(){} 14 | }, 15 | 16 | init : function (scope, method, options) { 17 | Foundation.inherit(this, 'throttle'); 18 | 19 | this.bindings(method, options); 20 | }, 21 | 22 | events : function (scope) { 23 | var self = this, 24 | S = self.S; 25 | 26 | S(this.scope) 27 | .off('.dropdown') 28 | .on('click.fndtn.dropdown', '[' + this.attr_name() + ']', function (e) { 29 | var settings = S(this).data(self.attr_name(true) + '-init') || self.settings; 30 | e.preventDefault(); 31 | if (!settings.is_hover || Modernizr.touch) self.toggle(S(this)); 32 | }) 33 | .on('mouseenter.fndtn.dropdown', '[' + this.attr_name() + '], [' + this.attr_name() + '-content]', function (e) { 34 | var $this = S(this); 35 | clearTimeout(self.timeout); 36 | 37 | if ($this.data(self.data_attr())) { 38 | var dropdown = S('#' + $this.data(self.data_attr())), 39 | target = $this; 40 | } else { 41 | var dropdown = $this; 42 | target = S("[" + self.attr_name() + "='" + dropdown.attr('id') + "']"); 43 | } 44 | 45 | var settings = target.data(self.attr_name(true) + '-init') || self.settings; 46 | 47 | if(S(e.target).data(self.data_attr()) && settings.is_hover) { 48 | self.closeall.call(self); 49 | } 50 | 51 | if (settings.is_hover) self.open.apply(self, [dropdown, target]); 52 | }) 53 | .on('mouseleave.fndtn.dropdown', '[' + this.attr_name() + '], [' + this.attr_name() + '-content]', function (e) { 54 | var $this = S(this); 55 | self.timeout = setTimeout(function () { 56 | if ($this.data(self.data_attr())) { 57 | var settings = $this.data(self.data_attr(true) + '-init') || self.settings; 58 | if (settings.is_hover) self.close.call(self, S('#' + $this.data(self.data_attr()))); 59 | } else { 60 | var target = S('[' + self.attr_name() + '="' + S(this).attr('id') + '"]'), 61 | settings = target.data(self.attr_name(true) + '-init') || self.settings; 62 | if (settings.is_hover) self.close.call(self, $this); 63 | } 64 | }.bind(this), 150); 65 | }) 66 | .on('click.fndtn.dropdown', function (e) { 67 | var parent = S(e.target).closest('[' + self.attr_name() + '-content]'); 68 | 69 | if (S(e.target).data(self.data_attr()) || S(e.target).parent().data(self.data_attr())) { 70 | return; 71 | } 72 | if (!(S(e.target).data('revealId')) && 73 | (parent.length > 0 && (S(e.target).is('[' + self.attr_name() + '-content]') || 74 | $.contains(parent.first()[0], e.target)))) { 75 | e.stopPropagation(); 76 | return; 77 | } 78 | 79 | self.close.call(self, S('[' + self.attr_name() + '-content]')); 80 | }) 81 | .on('opened.fndtn.dropdown', '[' + self.attr_name() + '-content]', function () { 82 | self.settings.opened.call(this); 83 | }) 84 | .on('closed.fndtn.dropdown', '[' + self.attr_name() + '-content]', function () { 85 | self.settings.closed.call(this); 86 | }); 87 | 88 | S(window) 89 | .off('.dropdown') 90 | .on('resize.fndtn.dropdown', self.throttle(function () { 91 | self.resize.call(self); 92 | }, 50)).trigger('resize'); 93 | }, 94 | 95 | close: function (dropdown) { 96 | var self = this; 97 | dropdown.each(function () { 98 | if (self.S(this).hasClass(self.settings.active_class)) { 99 | self.S(this) 100 | .css(Foundation.rtl ? 'right':'left', '-99999px') 101 | .removeClass(self.settings.active_class); 102 | self.S(this).trigger('closed'); 103 | } 104 | }); 105 | }, 106 | 107 | closeall: function() { 108 | var self = this; 109 | $.each(self.S('[' + this.attr_name() + '-content]'), function() { 110 | self.close.call(self, self.S(this)) 111 | }); 112 | }, 113 | 114 | open: function (dropdown, target) { 115 | this 116 | .css(dropdown 117 | .addClass(this.settings.active_class), target); 118 | dropdown.trigger('opened'); 119 | }, 120 | 121 | data_attr: function () { 122 | if (this.namespace.length > 0) { 123 | return this.namespace + '-' + this.name; 124 | } 125 | 126 | return this.name; 127 | }, 128 | 129 | toggle : function (target) { 130 | var dropdown = this.S('#' + target.data(this.data_attr())); 131 | if (dropdown.length === 0) { 132 | // No dropdown found, not continuing 133 | return; 134 | } 135 | 136 | this.close.call(this, this.S('[' + this.attr_name() + '-content]').not(dropdown)); 137 | 138 | if (dropdown.hasClass(this.settings.active_class)) { 139 | this.close.call(this, dropdown); 140 | } else { 141 | this.close.call(this, this.S('[' + this.attr_name() + '-content]')) 142 | this.open.call(this, dropdown, target); 143 | } 144 | }, 145 | 146 | resize : function () { 147 | var dropdown = this.S('[' + this.attr_name() + '-content].open'), 148 | target = this.S("[" + this.attr_name() + "='" + dropdown.attr('id') + "']"); 149 | 150 | if (dropdown.length && target.length) { 151 | this.css(dropdown, target); 152 | } 153 | }, 154 | 155 | css : function (dropdown, target) { 156 | var offset_parent = dropdown.offsetParent(), 157 | position = target.offset(); 158 | 159 | position.top -= offset_parent.offset().top; 160 | position.left -= offset_parent.offset().left; 161 | 162 | if (this.small()) { 163 | dropdown.css({ 164 | position : 'absolute', 165 | width: '95%', 166 | 'max-width': 'none', 167 | top: position.top + target.outerHeight() 168 | }); 169 | dropdown.css(Foundation.rtl ? 'right':'left', '2.5%'); 170 | } else { 171 | if (!Foundation.rtl && this.S(window).width() > dropdown.outerWidth() + target.offset().left) { 172 | var left = position.left; 173 | if (dropdown.hasClass('right')) { 174 | dropdown.removeClass('right'); 175 | } 176 | } else { 177 | if (!dropdown.hasClass('right')) { 178 | dropdown.addClass('right'); 179 | } 180 | var left = position.left - (dropdown.outerWidth() - target.outerWidth()); 181 | } 182 | 183 | dropdown.attr('style', '').css({ 184 | position : 'absolute', 185 | top: position.top + target.outerHeight(), 186 | left: left 187 | }); 188 | } 189 | 190 | return dropdown; 191 | }, 192 | 193 | small : function () { 194 | return matchMedia(Foundation.media_queries.small).matches && 195 | !matchMedia(Foundation.media_queries.medium).matches; 196 | }, 197 | 198 | off: function () { 199 | this.S(this.scope).off('.fndtn.dropdown'); 200 | this.S('html, body').off('.fndtn.dropdown'); 201 | this.S(window).off('.fndtn.dropdown'); 202 | this.S('[data-dropdown-content]').off('.fndtn.dropdown'); 203 | this.settings.init = false; 204 | }, 205 | 206 | reflow : function () {} 207 | }; 208 | }(jQuery, this, this.document)); 209 | -------------------------------------------------------------------------------- /static/js/foundation/foundation.equalizer.js: -------------------------------------------------------------------------------- 1 | ;(function ($, window, document, undefined) { 2 | 'use strict'; 3 | 4 | Foundation.libs.equalizer = { 5 | name : 'equalizer', 6 | 7 | version : '5.1.0', 8 | 9 | settings : { 10 | use_tallest: true, 11 | before_height_change: $.noop, 12 | after_height_change: $.noop 13 | }, 14 | 15 | init : function (scope, method, options) { 16 | this.bindings(method, options); 17 | }, 18 | 19 | events : function () { 20 | this.S(window).off('.equalizer').on('resize.fndtn.equalizer', function(e){ 21 | this.reflow(); 22 | }.bind(this)); 23 | }, 24 | 25 | equalize: function(equalizer) { 26 | var isStacked = false, 27 | vals = equalizer.find('[' + this.attr_name() + '-watch]'), 28 | firstTopOffset = vals.first().offset().top, 29 | settings = equalizer.data(this.attr_name(true)+'-init'); 30 | 31 | if (vals.length === 0) return; 32 | settings.before_height_change(); 33 | equalizer.trigger('before-height-change'); 34 | vals.height('inherit'); 35 | vals.each(function(){ 36 | var el = $(this); 37 | if (el.offset().top !== firstTopOffset) { 38 | isStacked = true; 39 | } 40 | }); 41 | if (isStacked) return; 42 | 43 | var heights = vals.map(function(){ return $(this).outerHeight() }); 44 | if (settings.use_tallest) { 45 | var max = Math.max.apply(null, heights); 46 | vals.height(max); 47 | } else { 48 | var min = Math.min.apply(null, heights); 49 | vals.height(min); 50 | } 51 | settings.after_height_change(); 52 | equalizer.trigger('after-height-change'); 53 | }, 54 | 55 | reflow : function () { 56 | var self = this; 57 | 58 | this.S('[' + this.attr_name() + ']', this.scope).each(function(){ 59 | self.equalize($(this)); 60 | }); 61 | } 62 | }; 63 | }(jQuery, this, this.document)); 64 | -------------------------------------------------------------------------------- /static/js/foundation/foundation.interchange.js: -------------------------------------------------------------------------------- 1 | ;(function ($, window, document, undefined) { 2 | 'use strict'; 3 | 4 | Foundation.libs.interchange = { 5 | name : 'interchange', 6 | 7 | version : '5.1.0', 8 | 9 | cache : {}, 10 | 11 | images_loaded : false, 12 | nodes_loaded : false, 13 | 14 | settings : { 15 | load_attr : 'interchange', 16 | 17 | named_queries : { 18 | 'default' : 'only screen', 19 | small : Foundation.media_queries.small, 20 | medium : Foundation.media_queries.medium, 21 | large : Foundation.media_queries.large, 22 | xlarge : Foundation.media_queries.xlarge, 23 | xxlarge: Foundation.media_queries.xxlarge, 24 | landscape : 'only screen and (orientation: landscape)', 25 | portrait : 'only screen and (orientation: portrait)', 26 | retina : 'only screen and (-webkit-min-device-pixel-ratio: 2),' + 27 | 'only screen and (min--moz-device-pixel-ratio: 2),' + 28 | 'only screen and (-o-min-device-pixel-ratio: 2/1),' + 29 | 'only screen and (min-device-pixel-ratio: 2),' + 30 | 'only screen and (min-resolution: 192dpi),' + 31 | 'only screen and (min-resolution: 2dppx)' 32 | }, 33 | 34 | directives : { 35 | replace: function (el, path, trigger) { 36 | // The trigger argument, if called within the directive, fires 37 | // an event named after the directive on the element, passing 38 | // any parameters along to the event that you pass to trigger. 39 | // 40 | // ex. trigger(), trigger([a, b, c]), or trigger(a, b, c) 41 | // 42 | // This allows you to bind a callback like so: 43 | // $('#interchangeContainer').on('replace', function (e, a, b, c) { 44 | // console.log($(this).html(), a, b, c); 45 | // }); 46 | 47 | if (/IMG/.test(el[0].nodeName)) { 48 | var orig_path = el[0].src; 49 | 50 | if (new RegExp(path, 'i').test(orig_path)) return; 51 | 52 | el[0].src = path; 53 | 54 | return trigger(el[0].src); 55 | } 56 | var last_path = el.data(this.data_attr + '-last-path'); 57 | 58 | if (last_path == path) return; 59 | 60 | return $.get(path, function (response) { 61 | el.html(response); 62 | el.data(this.data_attr + '-last-path', path); 63 | trigger(); 64 | }); 65 | 66 | } 67 | } 68 | }, 69 | 70 | init : function (scope, method, options) { 71 | Foundation.inherit(this, 'throttle random_str'); 72 | 73 | this.data_attr = this.set_data_attr(); 74 | $.extend(true, this.settings, method, options); 75 | 76 | this.bindings(method, options); 77 | this.load('images'); 78 | this.load('nodes'); 79 | }, 80 | 81 | events : function () { 82 | var self = this; 83 | 84 | $(window) 85 | .off('.interchange') 86 | .on('resize.fndtn.interchange', self.throttle(function () { 87 | self.resize(); 88 | }, 50)); 89 | 90 | return this; 91 | }, 92 | 93 | resize : function () { 94 | var cache = this.cache; 95 | 96 | if(!this.images_loaded || !this.nodes_loaded) { 97 | setTimeout($.proxy(this.resize, this), 50); 98 | return; 99 | } 100 | 101 | for (var uuid in cache) { 102 | if (cache.hasOwnProperty(uuid)) { 103 | var passed = this.results(uuid, cache[uuid]); 104 | 105 | if (passed) { 106 | this.settings.directives[passed 107 | .scenario[1]].call(this, passed.el, passed.scenario[0], function () { 108 | if (arguments[0] instanceof Array) { 109 | var args = arguments[0]; 110 | } else { 111 | var args = Array.prototype.slice.call(arguments, 0); 112 | } 113 | 114 | passed.el.trigger(passed.scenario[1], args); 115 | }); 116 | } 117 | } 118 | } 119 | 120 | }, 121 | 122 | results : function (uuid, scenarios) { 123 | var count = scenarios.length; 124 | 125 | if (count > 0) { 126 | var el = this.S('[' + this.add_namespace('data-uuid') + '="' + uuid + '"]'); 127 | 128 | while (count--) { 129 | var mq, rule = scenarios[count][2]; 130 | if (this.settings.named_queries.hasOwnProperty(rule)) { 131 | mq = matchMedia(this.settings.named_queries[rule]); 132 | } else { 133 | mq = matchMedia(rule); 134 | } 135 | if (mq.matches) { 136 | return {el: el, scenario: scenarios[count]}; 137 | } 138 | } 139 | } 140 | 141 | return false; 142 | }, 143 | 144 | load : function (type, force_update) { 145 | if (typeof this['cached_' + type] === 'undefined' || force_update) { 146 | this['update_' + type](); 147 | } 148 | 149 | return this['cached_' + type]; 150 | }, 151 | 152 | update_images : function () { 153 | var images = this.S('img[' + this.data_attr + ']'), 154 | count = images.length, 155 | i = count, 156 | loaded_count = 0, 157 | data_attr = this.data_attr; 158 | 159 | this.cache = {}; 160 | this.cached_images = []; 161 | this.images_loaded = (count === 0); 162 | 163 | while (i--) { 164 | loaded_count++; 165 | if (images[i]) { 166 | var str = images[i].getAttribute(data_attr) || ''; 167 | 168 | if (str.length > 0) { 169 | this.cached_images.push(images[i]); 170 | } 171 | } 172 | 173 | if (loaded_count === count) { 174 | this.images_loaded = true; 175 | this.enhance('images'); 176 | } 177 | } 178 | 179 | return this; 180 | }, 181 | 182 | update_nodes : function () { 183 | var nodes = this.S('[' + this.data_attr + ']').not('img'), 184 | count = nodes.length, 185 | i = count, 186 | loaded_count = 0, 187 | data_attr = this.data_attr; 188 | 189 | this.cached_nodes = []; 190 | // Set nodes_loaded to true if there are no nodes 191 | // this.nodes_loaded = false; 192 | this.nodes_loaded = (count === 0); 193 | 194 | 195 | while (i--) { 196 | loaded_count++; 197 | var str = nodes[i].getAttribute(data_attr) || ''; 198 | 199 | if (str.length > 0) { 200 | this.cached_nodes.push(nodes[i]); 201 | } 202 | 203 | if(loaded_count === count) { 204 | this.nodes_loaded = true; 205 | this.enhance('nodes'); 206 | } 207 | } 208 | 209 | return this; 210 | }, 211 | 212 | enhance : function (type) { 213 | var i = this['cached_' + type].length; 214 | 215 | while (i--) { 216 | this.object($(this['cached_' + type][i])); 217 | } 218 | 219 | return $(window).trigger('resize'); 220 | }, 221 | 222 | parse_params : function (path, directive, mq) { 223 | return [this.trim(path), this.convert_directive(directive), this.trim(mq)]; 224 | }, 225 | 226 | convert_directive : function (directive) { 227 | var trimmed = this.trim(directive); 228 | 229 | if (trimmed.length > 0) { 230 | return trimmed; 231 | } 232 | 233 | return 'replace'; 234 | }, 235 | 236 | object : function(el) { 237 | var raw_arr = this.parse_data_attr(el), 238 | scenarios = [], 239 | i = raw_arr.length; 240 | 241 | if (i > 0) { 242 | while (i--) { 243 | var split = raw_arr[i].split(/\((.*?)(\))$/); 244 | 245 | if (split.length > 1) { 246 | var cached_split = split[0].split(','), 247 | params = this.parse_params(cached_split[0], 248 | cached_split[1], split[1]); 249 | 250 | scenarios.push(params); 251 | } 252 | } 253 | } 254 | 255 | return this.store(el, scenarios); 256 | }, 257 | 258 | uuid : function (separator) { 259 | var delim = separator || "-", 260 | self = this; 261 | 262 | function S4() { 263 | return self.random_str(6); 264 | } 265 | 266 | return (S4() + S4() + delim + S4() + delim + S4() 267 | + delim + S4() + delim + S4() + S4() + S4()); 268 | }, 269 | 270 | store : function (el, scenarios) { 271 | var uuid = this.uuid(), 272 | current_uuid = el.data(this.add_namespace('uuid', true)); 273 | 274 | if (this.cache[current_uuid]) return this.cache[current_uuid]; 275 | 276 | el.attr(this.add_namespace('data-uuid'), uuid); 277 | 278 | return this.cache[uuid] = scenarios; 279 | }, 280 | 281 | trim : function(str) { 282 | if (typeof str === 'string') { 283 | return $.trim(str); 284 | } 285 | 286 | return str; 287 | }, 288 | 289 | set_data_attr: function (init) { 290 | if (init) { 291 | if (this.namespace.length > 0) { 292 | return this.namespace + '-' + this.settings.load_attr; 293 | } 294 | 295 | return this.settings.load_attr; 296 | } 297 | 298 | if (this.namespace.length > 0) { 299 | return 'data-' + this.namespace + '-' + this.settings.load_attr; 300 | } 301 | 302 | return 'data-' + this.settings.load_attr; 303 | }, 304 | 305 | parse_data_attr : function (el) { 306 | var raw = el.attr(this.attr_name()).split(/\[(.*?)\]/), 307 | i = raw.length, 308 | output = []; 309 | 310 | while (i--) { 311 | if (raw[i].replace(/[\W\d]+/, '').length > 4) { 312 | output.push(raw[i]); 313 | } 314 | } 315 | 316 | return output; 317 | }, 318 | 319 | reflow : function () { 320 | this.load('images', true); 321 | this.load('nodes', true); 322 | } 323 | 324 | }; 325 | 326 | }(jQuery, this, this.document)); 327 | -------------------------------------------------------------------------------- /static/js/foundation/foundation.joyride.js: -------------------------------------------------------------------------------- 1 | ;(function ($, window, document, undefined) { 2 | 'use strict'; 3 | 4 | var Modernizr = Modernizr || false; 5 | 6 | Foundation.libs.joyride = { 7 | name : 'joyride', 8 | 9 | version : '5.1.0', 10 | 11 | defaults : { 12 | expose : false, // turn on or off the expose feature 13 | modal : true, // Whether to cover page with modal during the tour 14 | tip_location : 'bottom', // 'top' or 'bottom' in relation to parent 15 | nub_position : 'auto', // override on a per tooltip bases 16 | scroll_speed : 1500, // Page scrolling speed in milliseconds, 0 = no scroll animation 17 | scroll_animation : 'linear', // supports 'swing' and 'linear', extend with jQuery UI. 18 | timer : 0, // 0 = no timer , all other numbers = timer in milliseconds 19 | start_timer_on_click : true, // true or false - true requires clicking the first button start the timer 20 | start_offset : 0, // the index of the tooltip you want to start on (index of the li) 21 | next_button : true, // true or false to control whether a next button is used 22 | tip_animation : 'fade', // 'pop' or 'fade' in each tip 23 | pause_after : [], // array of indexes where to pause the tour after 24 | exposed : [], // array of expose elements 25 | tip_animation_fade_speed : 300, // when tipAnimation = 'fade' this is speed in milliseconds for the transition 26 | cookie_monster : false, // true or false to control whether cookies are used 27 | cookie_name : 'joyride', // Name the cookie you'll use 28 | cookie_domain : false, // Will this cookie be attached to a domain, ie. '.notableapp.com' 29 | cookie_expires : 365, // set when you would like the cookie to expire. 30 | tip_container : 'body', // Where will the tip be attached 31 | tip_location_patterns : { 32 | top: ['bottom'], 33 | bottom: [], // bottom should not need to be repositioned 34 | left: ['right', 'top', 'bottom'], 35 | right: ['left', 'top', 'bottom'] 36 | }, 37 | post_ride_callback : function (){}, // A method to call once the tour closes (canceled or complete) 38 | post_step_callback : function (){}, // A method to call after each step 39 | pre_step_callback : function (){}, // A method to call before each step 40 | pre_ride_callback : function (){}, // A method to call before the tour starts (passed index, tip, and cloned exposed element) 41 | post_expose_callback : function (){}, // A method to call after an element has been exposed 42 | template : { // HTML segments for tip layout 43 | link : '×', 44 | timer : '
', 45 | tip : '
', 46 | wrapper : '
', 47 | button : '', 48 | modal : '
', 49 | expose : '
', 50 | expose_cover: '
' 51 | }, 52 | expose_add_class : '' // One or more space-separated class names to be added to exposed element 53 | }, 54 | 55 | init : function (scope, method, options) { 56 | Foundation.inherit(this, 'throttle random_str'); 57 | 58 | this.settings = this.defaults; 59 | 60 | this.bindings(method, options) 61 | }, 62 | 63 | events : function () { 64 | var self = this; 65 | 66 | $(this.scope) 67 | .off('.joyride') 68 | .on('click.fndtn.joyride', '.joyride-next-tip, .joyride-modal-bg', function (e) { 69 | e.preventDefault(); 70 | 71 | if (this.settings.$li.next().length < 1) { 72 | this.end(); 73 | } else if (this.settings.timer > 0) { 74 | clearTimeout(this.settings.automate); 75 | this.hide(); 76 | this.show(); 77 | this.startTimer(); 78 | } else { 79 | this.hide(); 80 | this.show(); 81 | } 82 | 83 | }.bind(this)) 84 | 85 | .on('click.fndtn.joyride', '.joyride-close-tip', function (e) { 86 | e.preventDefault(); 87 | this.end(); 88 | }.bind(this)); 89 | 90 | $(window) 91 | .off('.joyride') 92 | .on('resize.fndtn.joyride', self.throttle(function () { 93 | if ($('[' + self.attr_name() + ']').length > 0 && self.settings.$next_tip) { 94 | if (self.settings.exposed.length > 0) { 95 | var $els = $(self.settings.exposed); 96 | 97 | $els.each(function () { 98 | var $this = $(this); 99 | self.un_expose($this); 100 | self.expose($this); 101 | }); 102 | } 103 | 104 | if (self.is_phone()) { 105 | self.pos_phone(); 106 | } else { 107 | self.pos_default(false, true); 108 | } 109 | } 110 | }, 100)); 111 | }, 112 | 113 | start : function () { 114 | var self = this, 115 | $this = $('[' + this.attr_name() + ']', this.scope), 116 | integer_settings = ['timer', 'scrollSpeed', 'startOffset', 'tipAnimationFadeSpeed', 'cookieExpires'], 117 | int_settings_count = integer_settings.length; 118 | 119 | if (!$this.length > 0) return; 120 | 121 | if (!this.settings.init) this.events(); 122 | 123 | this.settings = $this.data(this.attr_name(true) + '-init'); 124 | 125 | // non configureable settings 126 | this.settings.$content_el = $this; 127 | this.settings.$body = $(this.settings.tip_container); 128 | this.settings.body_offset = $(this.settings.tip_container).position(); 129 | this.settings.$tip_content = this.settings.$content_el.find('> li'); 130 | this.settings.paused = false; 131 | this.settings.attempts = 0; 132 | 133 | // can we create cookies? 134 | if (typeof $.cookie !== 'function') { 135 | this.settings.cookie_monster = false; 136 | } 137 | 138 | // generate the tips and insert into dom. 139 | if (!this.settings.cookie_monster || this.settings.cookie_monster && !$.cookie(this.settings.cookie_name)) { 140 | this.settings.$tip_content.each(function (index) { 141 | var $this = $(this); 142 | this.settings = $.extend({}, self.defaults, self.data_options($this)) 143 | 144 | // Make sure that settings parsed from data_options are integers where necessary 145 | var i = int_settings_count; 146 | while (i--) { 147 | self.settings[integer_settings[i]] = parseInt(self.settings[integer_settings[i]], 10); 148 | } 149 | self.create({$li : $this, index : index}); 150 | }); 151 | 152 | // show first tip 153 | if (!this.settings.start_timer_on_click && this.settings.timer > 0) { 154 | this.show('init'); 155 | this.startTimer(); 156 | } else { 157 | this.show('init'); 158 | } 159 | 160 | } 161 | }, 162 | 163 | resume : function () { 164 | this.set_li(); 165 | this.show(); 166 | }, 167 | 168 | tip_template : function (opts) { 169 | var $blank, content; 170 | 171 | opts.tip_class = opts.tip_class || ''; 172 | 173 | $blank = $(this.settings.template.tip).addClass(opts.tip_class); 174 | content = $.trim($(opts.li).html()) + 175 | this.button_text(opts.button_text) + 176 | this.settings.template.link + 177 | this.timer_instance(opts.index); 178 | 179 | $blank.append($(this.settings.template.wrapper)); 180 | $blank.first().attr(this.add_namespace('data-index'), opts.index); 181 | $('.joyride-content-wrapper', $blank).append(content); 182 | 183 | return $blank[0]; 184 | }, 185 | 186 | timer_instance : function (index) { 187 | var txt; 188 | 189 | if ((index === 0 && this.settings.start_timer_on_click && this.settings.timer > 0) || this.settings.timer === 0) { 190 | txt = ''; 191 | } else { 192 | txt = $(this.settings.template.timer)[0].outerHTML; 193 | } 194 | return txt; 195 | }, 196 | 197 | button_text : function (txt) { 198 | if (this.settings.next_button) { 199 | txt = $.trim(txt) || 'Next'; 200 | txt = $(this.settings.template.button).append(txt)[0].outerHTML; 201 | } else { 202 | txt = ''; 203 | } 204 | return txt; 205 | }, 206 | 207 | create : function (opts) { 208 | console.log(opts.$li) 209 | var buttonText = opts.$li.attr(this.add_namespace('data-button')) 210 | || opts.$li.attr(this.add_namespace('data-text')), 211 | tipClass = opts.$li.attr('class'), 212 | $tip_content = $(this.tip_template({ 213 | tip_class : tipClass, 214 | index : opts.index, 215 | button_text : buttonText, 216 | li : opts.$li 217 | })); 218 | 219 | $(this.settings.tip_container).append($tip_content); 220 | }, 221 | 222 | show : function (init) { 223 | var $timer = null; 224 | 225 | // are we paused? 226 | if (this.settings.$li === undefined 227 | || ($.inArray(this.settings.$li.index(), this.settings.pause_after) === -1)) { 228 | 229 | // don't go to the next li if the tour was paused 230 | if (this.settings.paused) { 231 | this.settings.paused = false; 232 | } else { 233 | this.set_li(init); 234 | } 235 | 236 | this.settings.attempts = 0; 237 | 238 | if (this.settings.$li.length && this.settings.$target.length > 0) { 239 | if (init) { //run when we first start 240 | this.settings.pre_ride_callback(this.settings.$li.index(), this.settings.$next_tip); 241 | if (this.settings.modal) { 242 | this.show_modal(); 243 | } 244 | } 245 | 246 | this.settings.pre_step_callback(this.settings.$li.index(), this.settings.$next_tip); 247 | 248 | if (this.settings.modal && this.settings.expose) { 249 | this.expose(); 250 | } 251 | 252 | this.settings.tip_settings = $.extend({}, this.settings, this.data_options(this.settings.$li)); 253 | 254 | this.settings.timer = parseInt(this.settings.timer, 10); 255 | 256 | this.settings.tip_settings.tip_location_pattern = this.settings.tip_location_patterns[this.settings.tip_settings.tip_location]; 257 | 258 | // scroll if not modal 259 | if (!/body/i.test(this.settings.$target.selector)) { 260 | this.scroll_to(); 261 | } 262 | 263 | if (this.is_phone()) { 264 | this.pos_phone(true); 265 | } else { 266 | this.pos_default(true); 267 | } 268 | 269 | $timer = this.settings.$next_tip.find('.joyride-timer-indicator'); 270 | 271 | if (/pop/i.test(this.settings.tip_animation)) { 272 | 273 | $timer.width(0); 274 | 275 | if (this.settings.timer > 0) { 276 | 277 | this.settings.$next_tip.show(); 278 | 279 | setTimeout(function () { 280 | $timer.animate({ 281 | width: $timer.parent().width() 282 | }, this.settings.timer, 'linear'); 283 | }.bind(this), this.settings.tip_animation_fade_speed); 284 | 285 | } else { 286 | this.settings.$next_tip.show(); 287 | 288 | } 289 | 290 | 291 | } else if (/fade/i.test(this.settings.tip_animation)) { 292 | 293 | $timer.width(0); 294 | 295 | if (this.settings.timer > 0) { 296 | 297 | this.settings.$next_tip 298 | .fadeIn(this.settings.tip_animation_fade_speed) 299 | .show(); 300 | 301 | setTimeout(function () { 302 | $timer.animate({ 303 | width: $timer.parent().width() 304 | }, this.settings.timer, 'linear'); 305 | }.bind(this), this.settings.tip_animation_fadeSpeed); 306 | 307 | } else { 308 | this.settings.$next_tip.fadeIn(this.settings.tip_animation_fade_speed); 309 | } 310 | } 311 | 312 | this.settings.$current_tip = this.settings.$next_tip; 313 | 314 | // skip non-existant targets 315 | } else if (this.settings.$li && this.settings.$target.length < 1) { 316 | 317 | this.show(); 318 | 319 | } else { 320 | 321 | this.end(); 322 | 323 | } 324 | } else { 325 | 326 | this.settings.paused = true; 327 | 328 | } 329 | 330 | }, 331 | 332 | is_phone : function () { 333 | return matchMedia(Foundation.media_queries.small).matches && 334 | !matchMedia(Foundation.media_queries.medium).matches; 335 | }, 336 | 337 | hide : function () { 338 | if (this.settings.modal && this.settings.expose) { 339 | this.un_expose(); 340 | } 341 | 342 | if (!this.settings.modal) { 343 | $('.joyride-modal-bg').hide(); 344 | } 345 | 346 | // Prevent scroll bouncing...wait to remove from layout 347 | this.settings.$current_tip.css('visibility', 'hidden'); 348 | setTimeout($.proxy(function() { 349 | this.hide(); 350 | this.css('visibility', 'visible'); 351 | }, this.settings.$current_tip), 0); 352 | this.settings.post_step_callback(this.settings.$li.index(), 353 | this.settings.$current_tip); 354 | }, 355 | 356 | set_li : function (init) { 357 | if (init) { 358 | this.settings.$li = this.settings.$tip_content.eq(this.settings.start_offset); 359 | this.set_next_tip(); 360 | this.settings.$current_tip = this.settings.$next_tip; 361 | } else { 362 | this.settings.$li = this.settings.$li.next(); 363 | this.set_next_tip(); 364 | } 365 | 366 | this.set_target(); 367 | }, 368 | 369 | set_next_tip : function () { 370 | this.settings.$next_tip = $(".joyride-tip-guide").eq(this.settings.$li.index()); 371 | this.settings.$next_tip.data('closed', ''); 372 | }, 373 | 374 | set_target : function () { 375 | console.log(this.add_namespace('data-class')) 376 | var cl = this.settings.$li.attr(this.add_namespace('data-class')), 377 | id = this.settings.$li.attr(this.add_namespace('data-id')), 378 | $sel = function () { 379 | if (id) { 380 | return $(document.getElementById(id)); 381 | } else if (cl) { 382 | return $('.' + cl).first(); 383 | } else { 384 | return $('body'); 385 | } 386 | }; 387 | 388 | console.log(cl, id) 389 | 390 | this.settings.$target = $sel(); 391 | }, 392 | 393 | scroll_to : function () { 394 | var window_half, tipOffset; 395 | 396 | window_half = $(window).height() / 2; 397 | tipOffset = Math.ceil(this.settings.$target.offset().top - window_half + this.settings.$next_tip.outerHeight()); 398 | 399 | if (tipOffset != 0) { 400 | $('html, body').animate({ 401 | scrollTop: tipOffset 402 | }, this.settings.scroll_speed, 'swing'); 403 | } 404 | }, 405 | 406 | paused : function () { 407 | return ($.inArray((this.settings.$li.index() + 1), this.settings.pause_after) === -1); 408 | }, 409 | 410 | restart : function () { 411 | this.hide(); 412 | this.settings.$li = undefined; 413 | this.show('init'); 414 | }, 415 | 416 | pos_default : function (init, resizing) { 417 | var half_fold = Math.ceil($(window).height() / 2), 418 | tip_position = this.settings.$next_tip.offset(), 419 | $nub = this.settings.$next_tip.find('.joyride-nub'), 420 | nub_width = Math.ceil($nub.outerWidth() / 2), 421 | nub_height = Math.ceil($nub.outerHeight() / 2), 422 | toggle = init || false; 423 | 424 | // tip must not be "display: none" to calculate position 425 | if (toggle) { 426 | this.settings.$next_tip.css('visibility', 'hidden'); 427 | this.settings.$next_tip.show(); 428 | } 429 | 430 | if (typeof resizing === 'undefined') { 431 | resizing = false; 432 | } 433 | 434 | if (!/body/i.test(this.settings.$target.selector)) { 435 | if (this.bottom()) { 436 | if (this.rtl) { 437 | this.settings.$next_tip.css({ 438 | top: (this.settings.$target.offset().top + nub_height + this.settings.$target.outerHeight()), 439 | left: this.settings.$target.offset().left + this.settings.$target.outerWidth() - this.settings.$next_tip.outerWidth()}); 440 | } else { 441 | this.settings.$next_tip.css({ 442 | top: (this.settings.$target.offset().top + nub_height + this.settings.$target.outerHeight()), 443 | left: this.settings.$target.offset().left}); 444 | } 445 | 446 | this.nub_position($nub, this.settings.tip_settings.nub_position, 'top'); 447 | 448 | } else if (this.top()) { 449 | if (this.rtl) { 450 | this.settings.$next_tip.css({ 451 | top: (this.settings.$target.offset().top - this.settings.$next_tip.outerHeight() - nub_height), 452 | left: this.settings.$target.offset().left + this.settings.$target.outerWidth() - this.settings.$next_tip.outerWidth()}); 453 | } else { 454 | this.settings.$next_tip.css({ 455 | top: (this.settings.$target.offset().top - this.settings.$next_tip.outerHeight() - nub_height), 456 | left: this.settings.$target.offset().left}); 457 | } 458 | 459 | this.nub_position($nub, this.settings.tip_settings.nub_position, 'bottom'); 460 | 461 | } else if (this.right()) { 462 | 463 | this.settings.$next_tip.css({ 464 | top: this.settings.$target.offset().top, 465 | left: (this.outerWidth(this.settings.$target) + this.settings.$target.offset().left + nub_width)}); 466 | 467 | this.nub_position($nub, this.settings.tip_settings.nub_position, 'left'); 468 | 469 | } else if (this.left()) { 470 | 471 | this.settings.$next_tip.css({ 472 | top: this.settings.$target.offset().top, 473 | left: (this.settings.$target.offset().left - this.outerWidth(this.settings.$next_tip) - nub_width)}); 474 | 475 | this.nub_position($nub, this.settings.tip_settings.nub_position, 'right'); 476 | 477 | } 478 | 479 | if (!this.visible(this.corners(this.settings.$next_tip)) && this.settings.attempts < this.settings.tip_settings.tip_location_pattern.length) { 480 | 481 | $nub.removeClass('bottom') 482 | .removeClass('top') 483 | .removeClass('right') 484 | .removeClass('left'); 485 | 486 | this.settings.tip_settings.tip_location = this.settings.tip_settings.tip_location_pattern[this.settings.attempts]; 487 | 488 | this.settings.attempts++; 489 | 490 | this.pos_default(); 491 | 492 | } 493 | 494 | } else if (this.settings.$li.length) { 495 | 496 | this.pos_modal($nub); 497 | 498 | } 499 | 500 | if (toggle) { 501 | this.settings.$next_tip.hide(); 502 | this.settings.$next_tip.css('visibility', 'visible'); 503 | } 504 | 505 | }, 506 | 507 | pos_phone : function (init) { 508 | var tip_height = this.settings.$next_tip.outerHeight(), 509 | tip_offset = this.settings.$next_tip.offset(), 510 | target_height = this.settings.$target.outerHeight(), 511 | $nub = $('.joyride-nub', this.settings.$next_tip), 512 | nub_height = Math.ceil($nub.outerHeight() / 2), 513 | toggle = init || false; 514 | 515 | $nub.removeClass('bottom') 516 | .removeClass('top') 517 | .removeClass('right') 518 | .removeClass('left'); 519 | 520 | if (toggle) { 521 | this.settings.$next_tip.css('visibility', 'hidden'); 522 | this.settings.$next_tip.show(); 523 | } 524 | 525 | if (!/body/i.test(this.settings.$target.selector)) { 526 | 527 | if (this.top()) { 528 | 529 | this.settings.$next_tip.offset({top: this.settings.$target.offset().top - tip_height - nub_height}); 530 | $nub.addClass('bottom'); 531 | 532 | } else { 533 | 534 | this.settings.$next_tip.offset({top: this.settings.$target.offset().top + target_height + nub_height}); 535 | $nub.addClass('top'); 536 | 537 | } 538 | 539 | } else if (this.settings.$li.length) { 540 | this.pos_modal($nub); 541 | } 542 | 543 | if (toggle) { 544 | this.settings.$next_tip.hide(); 545 | this.settings.$next_tip.css('visibility', 'visible'); 546 | } 547 | }, 548 | 549 | pos_modal : function ($nub) { 550 | this.center(); 551 | $nub.hide(); 552 | 553 | this.show_modal(); 554 | }, 555 | 556 | show_modal : function () { 557 | if (!this.settings.$next_tip.data('closed')) { 558 | var joyridemodalbg = $('.joyride-modal-bg'); 559 | if (joyridemodalbg.length < 1) { 560 | $('body').append(this.settings.template.modal).show(); 561 | } 562 | 563 | if (/pop/i.test(this.settings.tip_animation)) { 564 | joyridemodalbg.show(); 565 | } else { 566 | joyridemodalbg.fadeIn(this.settings.tip_animation_fade_speed); 567 | } 568 | } 569 | }, 570 | 571 | expose : function () { 572 | var expose, 573 | exposeCover, 574 | el, 575 | origCSS, 576 | origClasses, 577 | randId = 'expose-' + this.random_str(6); 578 | 579 | if (arguments.length > 0 && arguments[0] instanceof $) { 580 | el = arguments[0]; 581 | } else if(this.settings.$target && !/body/i.test(this.settings.$target.selector)){ 582 | el = this.settings.$target; 583 | } else { 584 | return false; 585 | } 586 | 587 | if(el.length < 1){ 588 | if(window.console){ 589 | console.error('element not valid', el); 590 | } 591 | return false; 592 | } 593 | 594 | expose = $(this.settings.template.expose); 595 | this.settings.$body.append(expose); 596 | expose.css({ 597 | top: el.offset().top, 598 | left: el.offset().left, 599 | width: el.outerWidth(true), 600 | height: el.outerHeight(true) 601 | }); 602 | 603 | exposeCover = $(this.settings.template.expose_cover); 604 | 605 | origCSS = { 606 | zIndex: el.css('z-index'), 607 | position: el.css('position') 608 | }; 609 | 610 | origClasses = el.attr('class') == null ? '' : el.attr('class'); 611 | 612 | el.css('z-index',parseInt(expose.css('z-index'))+1); 613 | 614 | if (origCSS.position == 'static') { 615 | el.css('position','relative'); 616 | } 617 | 618 | el.data('expose-css',origCSS); 619 | el.data('orig-class', origClasses); 620 | el.attr('class', origClasses + ' ' + this.settings.expose_add_class); 621 | 622 | exposeCover.css({ 623 | top: el.offset().top, 624 | left: el.offset().left, 625 | width: el.outerWidth(true), 626 | height: el.outerHeight(true) 627 | }); 628 | 629 | if (this.settings.modal) this.show_modal(); 630 | 631 | this.settings.$body.append(exposeCover); 632 | expose.addClass(randId); 633 | exposeCover.addClass(randId); 634 | el.data('expose', randId); 635 | this.settings.post_expose_callback(this.settings.$li.index(), this.settings.$next_tip, el); 636 | this.add_exposed(el); 637 | }, 638 | 639 | un_expose : function () { 640 | var exposeId, 641 | el, 642 | expose , 643 | origCSS, 644 | origClasses, 645 | clearAll = false; 646 | 647 | if (arguments.length > 0 && arguments[0] instanceof $) { 648 | el = arguments[0]; 649 | } else if(this.settings.$target && !/body/i.test(this.settings.$target.selector)){ 650 | el = this.settings.$target; 651 | } else { 652 | return false; 653 | } 654 | 655 | if(el.length < 1){ 656 | if (window.console) { 657 | console.error('element not valid', el); 658 | } 659 | return false; 660 | } 661 | 662 | exposeId = el.data('expose'); 663 | expose = $('.' + exposeId); 664 | 665 | if (arguments.length > 1) { 666 | clearAll = arguments[1]; 667 | } 668 | 669 | if (clearAll === true) { 670 | $('.joyride-expose-wrapper,.joyride-expose-cover').remove(); 671 | } else { 672 | expose.remove(); 673 | } 674 | 675 | origCSS = el.data('expose-css'); 676 | 677 | if (origCSS.zIndex == 'auto') { 678 | el.css('z-index', ''); 679 | } else { 680 | el.css('z-index', origCSS.zIndex); 681 | } 682 | 683 | if (origCSS.position != el.css('position')) { 684 | if(origCSS.position == 'static') {// this is default, no need to set it. 685 | el.css('position', ''); 686 | } else { 687 | el.css('position', origCSS.position); 688 | } 689 | } 690 | 691 | origClasses = el.data('orig-class'); 692 | el.attr('class', origClasses); 693 | el.removeData('orig-classes'); 694 | 695 | el.removeData('expose'); 696 | el.removeData('expose-z-index'); 697 | this.remove_exposed(el); 698 | }, 699 | 700 | add_exposed: function(el){ 701 | this.settings.exposed = this.settings.exposed || []; 702 | if (el instanceof $ || typeof el === 'object') { 703 | this.settings.exposed.push(el[0]); 704 | } else if (typeof el == 'string') { 705 | this.settings.exposed.push(el); 706 | } 707 | }, 708 | 709 | remove_exposed: function(el){ 710 | var search, i; 711 | if (el instanceof $) { 712 | search = el[0] 713 | } else if (typeof el == 'string'){ 714 | search = el; 715 | } 716 | 717 | this.settings.exposed = this.settings.exposed || []; 718 | i = this.settings.exposed.length; 719 | 720 | while (i--) { 721 | if (this.settings.exposed[i] == search) { 722 | this.settings.exposed.splice(i, 1); 723 | return; 724 | } 725 | } 726 | }, 727 | 728 | center : function () { 729 | var $w = $(window); 730 | 731 | this.settings.$next_tip.css({ 732 | top : ((($w.height() - this.settings.$next_tip.outerHeight()) / 2) + $w.scrollTop()), 733 | left : ((($w.width() - this.settings.$next_tip.outerWidth()) / 2) + $w.scrollLeft()) 734 | }); 735 | 736 | return true; 737 | }, 738 | 739 | bottom : function () { 740 | return /bottom/i.test(this.settings.tip_settings.tip_location); 741 | }, 742 | 743 | top : function () { 744 | return /top/i.test(this.settings.tip_settings.tip_location); 745 | }, 746 | 747 | right : function () { 748 | return /right/i.test(this.settings.tip_settings.tip_location); 749 | }, 750 | 751 | left : function () { 752 | return /left/i.test(this.settings.tip_settings.tip_location); 753 | }, 754 | 755 | corners : function (el) { 756 | var w = $(window), 757 | window_half = w.height() / 2, 758 | //using this to calculate since scroll may not have finished yet. 759 | tipOffset = Math.ceil(this.settings.$target.offset().top - window_half + this.settings.$next_tip.outerHeight()), 760 | right = w.width() + w.scrollLeft(), 761 | offsetBottom = w.height() + tipOffset, 762 | bottom = w.height() + w.scrollTop(), 763 | top = w.scrollTop(); 764 | 765 | if (tipOffset < top) { 766 | if (tipOffset < 0) { 767 | top = 0; 768 | } else { 769 | top = tipOffset; 770 | } 771 | } 772 | 773 | if (offsetBottom > bottom) { 774 | bottom = offsetBottom; 775 | } 776 | 777 | return [ 778 | el.offset().top < top, 779 | right < el.offset().left + el.outerWidth(), 780 | bottom < el.offset().top + el.outerHeight(), 781 | w.scrollLeft() > el.offset().left 782 | ]; 783 | }, 784 | 785 | visible : function (hidden_corners) { 786 | var i = hidden_corners.length; 787 | 788 | while (i--) { 789 | if (hidden_corners[i]) return false; 790 | } 791 | 792 | return true; 793 | }, 794 | 795 | nub_position : function (nub, pos, def) { 796 | if (pos === 'auto') { 797 | nub.addClass(def); 798 | } else { 799 | nub.addClass(pos); 800 | } 801 | }, 802 | 803 | startTimer : function () { 804 | if (this.settings.$li.length) { 805 | this.settings.automate = setTimeout(function () { 806 | this.hide(); 807 | this.show(); 808 | this.startTimer(); 809 | }.bind(this), this.settings.timer); 810 | } else { 811 | clearTimeout(this.settings.automate); 812 | } 813 | }, 814 | 815 | end : function () { 816 | if (this.settings.cookie_monster) { 817 | $.cookie(this.settings.cookie_name, 'ridden', { expires: this.settings.cookie_expires, domain: this.settings.cookie_domain }); 818 | } 819 | 820 | if (this.settings.timer > 0) { 821 | clearTimeout(this.settings.automate); 822 | } 823 | 824 | if (this.settings.modal && this.settings.expose) { 825 | this.un_expose(); 826 | } 827 | 828 | this.settings.$next_tip.data('closed', true); 829 | 830 | $('.joyride-modal-bg').hide(); 831 | this.settings.$current_tip.hide(); 832 | this.settings.post_step_callback(this.settings.$li.index(), this.settings.$current_tip); 833 | this.settings.post_ride_callback(this.settings.$li.index(), this.settings.$current_tip); 834 | $('.joyride-tip-guide').remove(); 835 | }, 836 | 837 | off : function () { 838 | $(this.scope).off('.joyride'); 839 | $(window).off('.joyride'); 840 | $('.joyride-close-tip, .joyride-next-tip, .joyride-modal-bg').off('.joyride'); 841 | $('.joyride-tip-guide, .joyride-modal-bg').remove(); 842 | clearTimeout(this.settings.automate); 843 | this.settings = {}; 844 | }, 845 | 846 | reflow : function () {} 847 | }; 848 | }(jQuery, this, this.document)); 849 | -------------------------------------------------------------------------------- /static/js/foundation/foundation.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Foundation Responsive Library 3 | * http://foundation.zurb.com 4 | * Copyright 2014, ZURB 5 | * Free to use under the MIT license. 6 | * http://www.opensource.org/licenses/mit-license.php 7 | */ 8 | 9 | (function ($, window, document, undefined) { 10 | 'use strict'; 11 | 12 | var header_helpers = function (class_array) { 13 | var i = class_array.length; 14 | 15 | while (i--) { 16 | if($('head').has('.' + class_array[i]).length === 0) { 17 | $('head').append(''); 18 | } 19 | } 20 | }; 21 | 22 | header_helpers([ 23 | 'foundation-mq-small', 24 | 'foundation-mq-medium', 25 | 'foundation-mq-large', 26 | 'foundation-mq-xlarge', 27 | 'foundation-mq-xxlarge', 28 | 'foundation-data-attribute-namespace']); 29 | 30 | // Enable FastClick if present 31 | 32 | $(function() { 33 | if(typeof FastClick !== 'undefined') { 34 | // Don't attach to body if undefined 35 | if (typeof document.body !== 'undefined') { 36 | FastClick.attach(document.body); 37 | } 38 | } 39 | }); 40 | 41 | // private Fast Selector wrapper, 42 | // returns jQuery object. Only use where 43 | // getElementById is not available. 44 | var S = function (selector, context) { 45 | if (typeof selector === 'string') { 46 | if (context) { 47 | var cont; 48 | if (context.jquery) { 49 | cont = context[0]; 50 | } else { 51 | cont = context; 52 | } 53 | return $(cont.querySelectorAll(selector)); 54 | } 55 | 56 | return $(document.querySelectorAll(selector)); 57 | } 58 | 59 | return $(selector, context); 60 | }; 61 | 62 | // Namespace functions. 63 | 64 | var attr_name = function (init) { 65 | var arr = []; 66 | if (!init) arr.push('data'); 67 | if (this.namespace.length > 0) arr.push(this.namespace); 68 | arr.push(this.name); 69 | 70 | return arr.join('-'); 71 | }; 72 | 73 | var header_helpers = function (class_array) { 74 | var i = class_array.length; 75 | 76 | while (i--) { 77 | if($('head').has('.' + class_array[i]).length === 0) { 78 | $('head').append(''); 79 | } 80 | } 81 | }; 82 | 83 | var add_namespace = function (str) { 84 | var parts = str.split('-'), 85 | i = parts.length, 86 | arr = []; 87 | 88 | while(i--) { 89 | if (i !== 0) { 90 | arr.push(parts[i]); 91 | } else { 92 | if (this.namespace.length > 0) { 93 | arr.push(this.namespace, parts[i]); 94 | } else { 95 | arr.push(parts[i]); 96 | } 97 | } 98 | } 99 | 100 | return arr.reverse().join('-'); 101 | }; 102 | 103 | // Event binding and data-options updating. 104 | 105 | var bindings = function (method, options) { 106 | var self = this, 107 | should_bind_events = !S(this).data(this.attr_name(true)); 108 | 109 | if (typeof method === 'string') { 110 | return this[method].call(this, options); 111 | } 112 | 113 | if (S(this.scope).is('[' + this.attr_name() +']')) { 114 | S(this.scope).data(this.attr_name(true) + '-init', $.extend({}, this.settings, (options || method), this.data_options(S(this.scope)))); 115 | 116 | if (should_bind_events) { 117 | this.events(this.scope); 118 | } 119 | 120 | } else { 121 | S('[' + this.attr_name() +']', this.scope).each(function () { 122 | var should_bind_events = !S(this).data(self.attr_name(true) + '-init'); 123 | 124 | S(this).data(self.attr_name(true) + '-init', $.extend({}, self.settings, (options || method), self.data_options(S(this)))); 125 | 126 | if (should_bind_events) { 127 | self.events(this); 128 | } 129 | }); 130 | } 131 | }; 132 | 133 | var single_image_loaded = function (image, callback) { 134 | function loaded () { 135 | callback(image[0]); 136 | } 137 | 138 | function bindLoad () { 139 | this.one('load', loaded); 140 | 141 | if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) { 142 | var src = this.attr( 'src' ), 143 | param = src.match( /\?/ ) ? '&' : '?'; 144 | 145 | param += 'random=' + (new Date()).getTime(); 146 | this.attr('src', src + param); 147 | } 148 | } 149 | 150 | if (!image.attr('src')) { 151 | loaded(); 152 | return; 153 | } 154 | 155 | if (image[0].complete || image[0].readyState === 4) { 156 | loaded(); 157 | } else { 158 | bindLoad.call(image); 159 | } 160 | } 161 | 162 | /* 163 | https://github.com/paulirish/matchMedia.js 164 | */ 165 | 166 | window.matchMedia = window.matchMedia || (function( doc, undefined ) { 167 | 168 | "use strict"; 169 | 170 | var bool, 171 | docElem = doc.documentElement, 172 | refNode = docElem.firstElementChild || docElem.firstChild, 173 | // fakeBody required for 174 | fakeBody = doc.createElement( "body" ), 175 | div = doc.createElement( "div" ); 176 | 177 | div.id = "mq-test-1"; 178 | div.style.cssText = "position:absolute;top:-100em"; 179 | fakeBody.style.background = "none"; 180 | fakeBody.appendChild(div); 181 | 182 | return function(q){ 183 | 184 | div.innerHTML = "­"; 185 | 186 | docElem.insertBefore( fakeBody, refNode ); 187 | bool = div.offsetWidth === 42; 188 | docElem.removeChild( fakeBody ); 189 | 190 | return { 191 | matches: bool, 192 | media: q 193 | }; 194 | 195 | }; 196 | 197 | }( document )); 198 | 199 | /* 200 | * jquery.requestAnimationFrame 201 | * https://github.com/gnarf37/jquery-requestAnimationFrame 202 | * Requires jQuery 1.8+ 203 | * 204 | * Copyright (c) 2012 Corey Frang 205 | * Licensed under the MIT license. 206 | */ 207 | 208 | (function( $ ) { 209 | 210 | // requestAnimationFrame polyfill adapted from Erik Möller 211 | // fixes from Paul Irish and Tino Zijdel 212 | // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 213 | // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating 214 | 215 | 216 | var animating, 217 | lastTime = 0, 218 | vendors = ['webkit', 'moz'], 219 | requestAnimationFrame = window.requestAnimationFrame, 220 | cancelAnimationFrame = window.cancelAnimationFrame; 221 | 222 | for(; lastTime < vendors.length && !requestAnimationFrame; lastTime++) { 223 | requestAnimationFrame = window[ vendors[lastTime] + "RequestAnimationFrame" ]; 224 | cancelAnimationFrame = cancelAnimationFrame || 225 | window[ vendors[lastTime] + "CancelAnimationFrame" ] || 226 | window[ vendors[lastTime] + "CancelRequestAnimationFrame" ]; 227 | } 228 | 229 | function raf() { 230 | if ( animating ) { 231 | requestAnimationFrame( raf ); 232 | jQuery.fx.tick(); 233 | } 234 | } 235 | 236 | if ( requestAnimationFrame ) { 237 | // use rAF 238 | window.requestAnimationFrame = requestAnimationFrame; 239 | window.cancelAnimationFrame = cancelAnimationFrame; 240 | jQuery.fx.timer = function( timer ) { 241 | if ( timer() && jQuery.timers.push( timer ) && !animating ) { 242 | animating = true; 243 | raf(); 244 | } 245 | }; 246 | 247 | jQuery.fx.stop = function() { 248 | animating = false; 249 | }; 250 | } else { 251 | // polyfill 252 | window.requestAnimationFrame = function( callback, element ) { 253 | var currTime = new Date().getTime(), 254 | timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) ), 255 | id = window.setTimeout( function() { 256 | callback( currTime + timeToCall ); 257 | }, timeToCall ); 258 | lastTime = currTime + timeToCall; 259 | return id; 260 | }; 261 | 262 | window.cancelAnimationFrame = function(id) { 263 | clearTimeout(id); 264 | }; 265 | 266 | } 267 | 268 | }( jQuery )); 269 | 270 | 271 | function removeQuotes (string) { 272 | if (typeof string === 'string' || string instanceof String) { 273 | string = string.replace(/^['\\/"]+|(;\s?})+|['\\/"]+$/g, ''); 274 | } 275 | 276 | return string; 277 | } 278 | 279 | window.Foundation = { 280 | name : 'Foundation', 281 | 282 | version : '5.1.0', 283 | 284 | media_queries : { 285 | small : S('.foundation-mq-small').css('font-family').replace(/^[\/\\'"]+|(;\s?})+|[\/\\'"]+$/g, ''), 286 | medium : S('.foundation-mq-medium').css('font-family').replace(/^[\/\\'"]+|(;\s?})+|[\/\\'"]+$/g, ''), 287 | large : S('.foundation-mq-large').css('font-family').replace(/^[\/\\'"]+|(;\s?})+|[\/\\'"]+$/g, ''), 288 | xlarge: S('.foundation-mq-xlarge').css('font-family').replace(/^[\/\\'"]+|(;\s?})+|[\/\\'"]+$/g, ''), 289 | xxlarge: S('.foundation-mq-xxlarge').css('font-family').replace(/^[\/\\'"]+|(;\s?})+|[\/\\'"]+$/g, '') 290 | }, 291 | 292 | stylesheet : $('').appendTo('head')[0].sheet, 293 | 294 | global: { 295 | namespace: '' 296 | }, 297 | 298 | init : function (scope, libraries, method, options, response) { 299 | var library_arr, 300 | args = [scope, method, options, response], 301 | responses = []; 302 | 303 | // check RTL 304 | this.rtl = /rtl/i.test(S('html').attr('dir')); 305 | 306 | // set foundation global scope 307 | this.scope = scope || this.scope; 308 | 309 | this.set_namespace(); 310 | 311 | if (libraries && typeof libraries === 'string' && !/reflow/i.test(libraries)) { 312 | if (this.libs.hasOwnProperty(libraries)) { 313 | responses.push(this.init_lib(libraries, args)); 314 | } 315 | } else { 316 | for (var lib in this.libs) { 317 | responses.push(this.init_lib(lib, libraries)); 318 | } 319 | } 320 | 321 | return scope; 322 | }, 323 | 324 | init_lib : function (lib, args) { 325 | if (this.libs.hasOwnProperty(lib)) { 326 | this.patch(this.libs[lib]); 327 | 328 | if (args && args.hasOwnProperty(lib)) { 329 | return this.libs[lib].init.apply(this.libs[lib], [this.scope, args[lib]]); 330 | } 331 | 332 | args = args instanceof Array ? args : Array(args); // PATCH: added this line 333 | return this.libs[lib].init.apply(this.libs[lib], args); 334 | } 335 | 336 | return function () {}; 337 | }, 338 | 339 | patch : function (lib) { 340 | lib.scope = this.scope; 341 | lib.namespace = this.global.namespace; 342 | lib.rtl = this.rtl; 343 | lib['data_options'] = this.utils.data_options; 344 | lib['attr_name'] = attr_name; 345 | lib['add_namespace'] = add_namespace; 346 | lib['bindings'] = bindings; 347 | lib['S'] = this.utils.S; 348 | }, 349 | 350 | inherit : function (scope, methods) { 351 | var methods_arr = methods.split(' '), 352 | i = methods_arr.length; 353 | 354 | while (i--) { 355 | if (this.utils.hasOwnProperty(methods_arr[i])) { 356 | scope[methods_arr[i]] = this.utils[methods_arr[i]]; 357 | } 358 | } 359 | }, 360 | 361 | set_namespace: function () { 362 | var namespace = $('.foundation-data-attribute-namespace').css('font-family'); 363 | 364 | if (/false/i.test(namespace)) return; 365 | 366 | this.global.namespace = namespace; 367 | }, 368 | 369 | libs : {}, 370 | 371 | // methods that can be inherited in libraries 372 | utils : { 373 | 374 | // Description: 375 | // Fast Selector wrapper returns jQuery object. Only use where getElementById 376 | // is not available. 377 | // 378 | // Arguments: 379 | // Selector (String): CSS selector describing the element(s) to be 380 | // returned as a jQuery object. 381 | // 382 | // Scope (String): CSS selector describing the area to be searched. Default 383 | // is document. 384 | // 385 | // Returns: 386 | // Element (jQuery Object): jQuery object containing elements matching the 387 | // selector within the scope. 388 | S : S, 389 | 390 | // Description: 391 | // Executes a function a max of once every n milliseconds 392 | // 393 | // Arguments: 394 | // Func (Function): Function to be throttled. 395 | // 396 | // Delay (Integer): Function execution threshold in milliseconds. 397 | // 398 | // Returns: 399 | // Lazy_function (Function): Function with throttling applied. 400 | throttle : function(func, delay) { 401 | var timer = null; 402 | 403 | return function () { 404 | var context = this, args = arguments; 405 | 406 | clearTimeout(timer); 407 | timer = setTimeout(function () { 408 | func.apply(context, args); 409 | }, delay); 410 | }; 411 | }, 412 | 413 | // Description: 414 | // Executes a function when it stops being invoked for n seconds 415 | // Modified version of _.debounce() http://underscorejs.org 416 | // 417 | // Arguments: 418 | // Func (Function): Function to be debounced. 419 | // 420 | // Delay (Integer): Function execution threshold in milliseconds. 421 | // 422 | // Immediate (Bool): Whether the function should be called at the beginning 423 | // of the delay instead of the end. Default is false. 424 | // 425 | // Returns: 426 | // Lazy_function (Function): Function with debouncing applied. 427 | debounce : function(func, delay, immediate) { 428 | var timeout, result; 429 | return function() { 430 | var context = this, args = arguments; 431 | var later = function() { 432 | timeout = null; 433 | if (!immediate) result = func.apply(context, args); 434 | }; 435 | var callNow = immediate && !timeout; 436 | clearTimeout(timeout); 437 | timeout = setTimeout(later, delay); 438 | if (callNow) result = func.apply(context, args); 439 | return result; 440 | }; 441 | }, 442 | 443 | // Description: 444 | // Parses data-options attribute 445 | // 446 | // Arguments: 447 | // El (jQuery Object): Element to be parsed. 448 | // 449 | // Returns: 450 | // Options (Javascript Object): Contents of the element's data-options 451 | // attribute. 452 | data_options : function (el) { 453 | var opts = {}, ii, p, opts_arr, 454 | data_options = function (el) { 455 | var namespace = Foundation.global.namespace; 456 | 457 | if (namespace.length > 0) { 458 | return el.data(namespace + '-options'); 459 | } 460 | 461 | return el.data('options'); 462 | }; 463 | 464 | var cached_options = data_options(el); 465 | 466 | if (typeof cached_options === 'object') { 467 | return cached_options; 468 | } 469 | 470 | opts_arr = (cached_options || ':').split(';'), 471 | ii = opts_arr.length; 472 | 473 | function isNumber (o) { 474 | return ! isNaN (o-0) && o !== null && o !== "" && o !== false && o !== true; 475 | } 476 | 477 | function trim(str) { 478 | if (typeof str === 'string') return $.trim(str); 479 | return str; 480 | } 481 | 482 | while (ii--) { 483 | p = opts_arr[ii].split(':'); 484 | 485 | if (/true/i.test(p[1])) p[1] = true; 486 | if (/false/i.test(p[1])) p[1] = false; 487 | if (isNumber(p[1])) p[1] = parseInt(p[1], 10); 488 | 489 | if (p.length === 2 && p[0].length > 0) { 490 | opts[trim(p[0])] = trim(p[1]); 491 | } 492 | } 493 | 494 | return opts; 495 | }, 496 | 497 | // Description: 498 | // Adds JS-recognizable media queries 499 | // 500 | // Arguments: 501 | // Media (String): Key string for the media query to be stored as in 502 | // Foundation.media_queries 503 | // 504 | // Class (String): Class name for the generated tag 505 | register_media : function(media, media_class) { 506 | if(Foundation.media_queries[media] === undefined) { 507 | $('head').append(''); 508 | Foundation.media_queries[media] = removeQuotes($('.' + media_class).css('font-family')); 509 | } 510 | }, 511 | 512 | // Description: 513 | // Add custom CSS within a JS-defined media query 514 | // 515 | // Arguments: 516 | // Rule (String): CSS rule to be appended to the document. 517 | // 518 | // Media (String): Optional media query string for the CSS rule to be 519 | // nested under. 520 | add_custom_rule : function(rule, media) { 521 | if(media === undefined) { 522 | Foundation.stylesheet.insertRule(rule, Foundation.stylesheet.cssRules.length); 523 | } else { 524 | var query = Foundation.media_queries[media]; 525 | if(query !== undefined) { 526 | Foundation.stylesheet.insertRule('@media ' + 527 | Foundation.media_queries[media] + '{ ' + rule + ' }'); 528 | } 529 | } 530 | }, 531 | 532 | // Description: 533 | // Performs a callback function when an image is fully loaded 534 | // 535 | // Arguments: 536 | // Image (jQuery Object): Image(s) to check if loaded. 537 | // 538 | // Callback (Function): Fundation to execute when image is fully loaded. 539 | image_loaded : function (images, callback) { 540 | var self = this, 541 | unloaded = images.length; 542 | 543 | images.each(function(){ 544 | single_image_loaded(self.S(this),function(){ 545 | unloaded -= 1; 546 | if(unloaded == 0){ 547 | callback(images); 548 | } 549 | }); 550 | }); 551 | }, 552 | 553 | // Description: 554 | // Returns a random, alphanumeric string 555 | // 556 | // Arguments: 557 | // Length (Integer): Length of string to be generated. Defaults to random 558 | // integer. 559 | // 560 | // Returns: 561 | // Rand (String): Pseudo-random, alphanumeric string. 562 | random_str : function (length) { 563 | var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''); 564 | 565 | if (!length) { 566 | length = Math.floor(Math.random() * chars.length); 567 | } 568 | 569 | var str = ''; 570 | while (length--) { 571 | str += chars[Math.floor(Math.random() * chars.length)]; 572 | } 573 | return str; 574 | } 575 | } 576 | }; 577 | 578 | $.fn.foundation = function () { 579 | var args = Array.prototype.slice.call(arguments, 0); 580 | 581 | return this.each(function () { 582 | Foundation.init.apply(Foundation, [this].concat(args)); 583 | return this; 584 | }); 585 | }; 586 | 587 | }(jQuery, this, this.document)); 588 | -------------------------------------------------------------------------------- /static/js/foundation/foundation.magellan.js: -------------------------------------------------------------------------------- 1 | ;(function ($, window, document, undefined) { 2 | 'use strict'; 3 | 4 | Foundation.libs['magellan-expedition'] = { 5 | name : 'magellan-expedition', 6 | 7 | version : '5.1.0', 8 | 9 | settings : { 10 | active_class: 'active', 11 | threshold: 0, // pixels from the top of the expedition for it to become fixes 12 | destination_threshold: 20, // pixels from the top of destination for it to be considered active 13 | throttle_delay: 30 // calculation throttling to increase framerate 14 | }, 15 | 16 | init : function (scope, method, options) { 17 | Foundation.inherit(this, 'throttle'); 18 | this.bindings(method, options); 19 | }, 20 | 21 | events : function () { 22 | var self = this, 23 | S = self.S, 24 | settings = self.settings; 25 | 26 | // initialize expedition offset 27 | self.set_expedition_position(); 28 | 29 | 30 | S(self.scope) 31 | .off('.magellan') 32 | .on('click.fndtn.magellan', '[data-magellan-arrival] a[href^="#"]', function (e) { 33 | e.preventDefault(); 34 | var expedition = $(this).closest('[data-magellan-expedition]'), 35 | settings = expedition.data('magellan-expedition-init'); 36 | 37 | var hash = this.hash.split('#').join(''), 38 | target = $('a[name='+hash+']'); 39 | if (target.length === 0) target = $('#'+hash); 40 | 41 | // Account for expedition height if fixed position 42 | var scroll_top = target.offset().top; 43 | if (expedition.css('position') === 'fixed') { 44 | scroll_top = scroll_top - expedition.outerHeight(); 45 | } 46 | 47 | $('html, body').stop().animate({ 48 | 'scrollTop': scroll_top 49 | }, 700, 'swing', function () { 50 | window.location.hash = '#'+hash; 51 | }); 52 | }) 53 | .on('scroll.fndtn.magellan', self.throttle(this.check_for_arrivals.bind(this), settings.throttle_delay)) 54 | .on('resize.fndtn.magellan', self.throttle(this.set_expedition_position.bind(this), settings.throttle_delay)); 55 | }, 56 | 57 | check_for_arrivals : function() { 58 | var self = this; 59 | self.update_arrivals(); 60 | self.update_expedition_positions(); 61 | }, 62 | 63 | set_expedition_position : function() { 64 | var self = this; 65 | $('[' + this.attr_name() + '=fixed]', self.scope).each(function(idx, el) { 66 | var expedition = $(this), 67 | styles = expedition.attr('styles'), // save styles 68 | top_offset; 69 | 70 | expedition.attr('style', ''); 71 | top_offset = expedition.offset().top; 72 | 73 | expedition.data(self.data_attr('magellan-top-offset'), top_offset); 74 | expedition.attr('style', styles); 75 | }); 76 | }, 77 | 78 | update_expedition_positions : function() { 79 | var self = this, 80 | window_top_offset = $(window).scrollTop(); 81 | 82 | $('[' + this.attr_name() + '=fixed]', self.scope).each(function() { 83 | var expedition = $(this), 84 | top_offset = expedition.data('magellan-top-offset'); 85 | 86 | if (window_top_offset >= top_offset) { 87 | // Placeholder allows height calculations to be consistent even when 88 | // appearing to switch between fixed/non-fixed placement 89 | var placeholder = expedition.prev('[data-magellan-expedition-clone]'); 90 | if (placeholder.length === 0) { 91 | placeholder = expedition.clone(); 92 | placeholder.removeAttr('data-magellan-expedition'); 93 | placeholder.attr('data-magellan-expedition-clone',''); 94 | expedition.before(placeholder); 95 | } 96 | expedition.css({position:'fixed', top: 0}); 97 | } else { 98 | expedition.prev('[data-magellan-expedition-clone]').remove(); 99 | expedition.attr('style',''); 100 | } 101 | }); 102 | }, 103 | 104 | update_arrivals : function() { 105 | var self = this, 106 | window_top_offset = $(window).scrollTop(); 107 | 108 | $('[' + this.attr_name() + ']', self.scope).each(function() { 109 | var expedition = $(this), 110 | settings = settings = expedition.data(self.attr_name(true) + '-init'), 111 | offsets = self.offsets(expedition, window_top_offset), 112 | arrivals = expedition.find('[' + self.add_namespace('data-magellan-arrival') + ']'), 113 | active_item = false; 114 | offsets.each(function(idx, item) { 115 | if (item.viewport_offset >= item.top_offset) { 116 | var arrivals = expedition.find('[' + self.add_namespace('data-magellan-arrival') + ']'); 117 | arrivals.not(item.arrival).removeClass(settings.active_class); 118 | item.arrival.addClass(settings.active_class); 119 | active_item = true; 120 | return true; 121 | } 122 | }); 123 | 124 | if (!active_item) arrivals.removeClass(settings.active_class); 125 | }); 126 | }, 127 | 128 | offsets : function(expedition, window_offset) { 129 | var self = this, 130 | settings = expedition.data(self.attr_name(true) + '-init'), 131 | viewport_offset = (window_offset + settings.destination_threshold); 132 | 133 | return expedition.find('[' + self.add_namespace('data-magellan-arrival') + ']').map(function(idx, el) { 134 | var name = $(this).data(self.data_attr('magellan-arrival')), 135 | dest = $('[' + self.add_namespace('data-magellan-destination') + '=' + name + ']'); 136 | if (dest.length > 0) { 137 | var top_offset = dest.offset().top; 138 | return { 139 | destination : dest, 140 | arrival : $(this), 141 | top_offset : top_offset, 142 | viewport_offset : viewport_offset 143 | } 144 | } 145 | }).sort(function(a, b) { 146 | if (a.top_offset < b.top_offset) return -1; 147 | if (a.top_offset > b.top_offset) return 1; 148 | return 0; 149 | }); 150 | }, 151 | 152 | data_attr: function (str) { 153 | if (this.namespace.length > 0) { 154 | return this.namespace + '-' + str; 155 | } 156 | 157 | return str; 158 | }, 159 | 160 | off : function () { 161 | this.S(this.scope).off('.magellan'); 162 | this.S(window).off('.magellan'); 163 | }, 164 | 165 | reflow : function () { 166 | var self = this; 167 | // remove placeholder expeditions used for height calculation purposes 168 | $('[data-magellan-expedition-clone]', self.scope).remove(); 169 | } 170 | }; 171 | }(jQuery, this, this.document)); 172 | -------------------------------------------------------------------------------- /static/js/foundation/foundation.offcanvas.js: -------------------------------------------------------------------------------- 1 | ;(function ($, window, document, undefined) { 2 | 'use strict'; 3 | 4 | Foundation.libs.offcanvas = { 5 | name : 'offcanvas', 6 | 7 | version : '5.1.0', 8 | 9 | settings : {}, 10 | 11 | init : function (scope, method, options) { 12 | this.events(); 13 | }, 14 | 15 | events : function () { 16 | var S = this.S; 17 | 18 | S(this.scope).off('.offcanvas') 19 | .on('click.fndtn.offcanvas', '.left-off-canvas-toggle', function (e) { 20 | e.preventDefault(); 21 | S(this).closest('.off-canvas-wrap').toggleClass('move-right'); 22 | }) 23 | .on('click.fndtn.offcanvas', '.exit-off-canvas', function (e) { 24 | e.preventDefault(); 25 | S(".off-canvas-wrap").removeClass("move-right"); 26 | }) 27 | .on('click.fndtn.offcanvas', '.right-off-canvas-toggle', function (e) { 28 | e.preventDefault(); 29 | S(this).closest(".off-canvas-wrap").toggleClass("move-left"); 30 | }) 31 | .on('click.fndtn.offcanvas', '.exit-off-canvas', function (e) { 32 | e.preventDefault(); 33 | S(".off-canvas-wrap").removeClass("move-left"); 34 | }); 35 | }, 36 | 37 | reflow : function () {} 38 | }; 39 | }(jQuery, this, this.document)); 40 | -------------------------------------------------------------------------------- /static/js/foundation/foundation.orbit.js: -------------------------------------------------------------------------------- 1 | ;(function ($, window, document, undefined) { 2 | 'use strict'; 3 | 4 | var noop = function() {}; 5 | 6 | var Orbit = function(el, settings) { 7 | // Don't reinitialize plugin 8 | if (el.hasClass(settings.slides_container_class)) { 9 | return this; 10 | } 11 | 12 | var self = this, 13 | container, 14 | slides_container = el, 15 | number_container, 16 | bullets_container, 17 | timer_container, 18 | idx = 0, 19 | animate, 20 | timer, 21 | locked = false, 22 | adjust_height_after = false; 23 | 24 | 25 | self.slides = function() { 26 | return slides_container.children(settings.slide_selector); 27 | }; 28 | 29 | self.slides().first().addClass(settings.active_slide_class); 30 | 31 | self.update_slide_number = function(index) { 32 | if (settings.slide_number) { 33 | number_container.find('span:first').text(parseInt(index)+1); 34 | number_container.find('span:last').text(self.slides().length); 35 | } 36 | if (settings.bullets) { 37 | bullets_container.children().removeClass(settings.bullets_active_class); 38 | $(bullets_container.children().get(index)).addClass(settings.bullets_active_class); 39 | } 40 | }; 41 | 42 | self.update_active_link = function(index) { 43 | var link = $('a[data-orbit-link="'+self.slides().eq(index).attr('data-orbit-slide')+'"]'); 44 | link.siblings().removeClass(settings.bullets_active_class); 45 | link.addClass(settings.bullets_active_class); 46 | }; 47 | 48 | self.build_markup = function() { 49 | slides_container.wrap('
'); 50 | container = slides_container.parent(); 51 | slides_container.addClass(settings.slides_container_class); 52 | 53 | if (settings.navigation_arrows) { 54 | container.append($('').addClass(settings.prev_class)); 55 | container.append($('').addClass(settings.next_class)); 56 | } 57 | 58 | if (settings.timer) { 59 | timer_container = $('
').addClass(settings.timer_container_class); 60 | timer_container.append(''); 61 | timer_container.append($('
').addClass(settings.timer_progress_class)); 62 | timer_container.addClass(settings.timer_paused_class); 63 | container.append(timer_container); 64 | } 65 | 66 | if (settings.slide_number) { 67 | number_container = $('
').addClass(settings.slide_number_class); 68 | number_container.append(' ' + settings.slide_number_text + ' '); 69 | container.append(number_container); 70 | } 71 | 72 | if (settings.bullets) { 73 | bullets_container = $('
    ').addClass(settings.bullets_container_class); 74 | container.append(bullets_container); 75 | bullets_container.wrap('
    '); 76 | self.slides().each(function(idx, el) { 77 | var bullet = $('
  1. ').attr('data-orbit-slide', idx); 78 | bullets_container.append(bullet); 79 | }); 80 | } 81 | 82 | if (settings.stack_on_small) { 83 | container.addClass(settings.stack_on_small_class); 84 | } 85 | }; 86 | 87 | self._goto = function(next_idx, start_timer) { 88 | // if (locked) {return false;} 89 | if (next_idx === idx) {return false;} 90 | if (typeof timer === 'object') {timer.restart();} 91 | var slides = self.slides(); 92 | 93 | var dir = 'next'; 94 | locked = true; 95 | if (next_idx < idx) {dir = 'prev';} 96 | if (next_idx >= slides.length) { 97 | if (!settings.circular) return false; 98 | next_idx = 0; 99 | } else if (next_idx < 0) { 100 | if (!settings.circular) return false; 101 | next_idx = slides.length - 1; 102 | } 103 | 104 | var current = $(slides.get(idx)); 105 | var next = $(slides.get(next_idx)); 106 | 107 | current.css('zIndex', 2); 108 | current.removeClass(settings.active_slide_class); 109 | next.css('zIndex', 4).addClass(settings.active_slide_class); 110 | 111 | slides_container.trigger('before-slide-change.fndtn.orbit'); 112 | settings.before_slide_change(); 113 | self.update_active_link(next_idx); 114 | 115 | var callback = function() { 116 | var unlock = function() { 117 | idx = next_idx; 118 | locked = false; 119 | if (start_timer === true) {timer = self.create_timer(); timer.start();} 120 | self.update_slide_number(idx); 121 | slides_container.trigger('after-slide-change.fndtn.orbit',[{slide_number: idx, total_slides: slides.length}]); 122 | settings.after_slide_change(idx, slides.length); 123 | }; 124 | if (slides_container.height() != next.height() && settings.variable_height) { 125 | slides_container.animate({'height': next.height()}, 250, 'linear', unlock); 126 | } else { 127 | unlock(); 128 | } 129 | }; 130 | 131 | if (slides.length === 1) {callback(); return false;} 132 | 133 | var start_animation = function() { 134 | if (dir === 'next') {animate.next(current, next, callback);} 135 | if (dir === 'prev') {animate.prev(current, next, callback);} 136 | }; 137 | 138 | if (next.height() > slides_container.height() && settings.variable_height) { 139 | slides_container.animate({'height': next.height()}, 250, 'linear', start_animation); 140 | } else { 141 | start_animation(); 142 | } 143 | }; 144 | 145 | self.next = function(e) { 146 | e.stopImmediatePropagation(); 147 | e.preventDefault(); 148 | self._goto(idx + 1); 149 | }; 150 | 151 | self.prev = function(e) { 152 | e.stopImmediatePropagation(); 153 | e.preventDefault(); 154 | self._goto(idx - 1); 155 | }; 156 | 157 | self.link_custom = function(e) { 158 | e.preventDefault(); 159 | var link = $(this).attr('data-orbit-link'); 160 | if ((typeof link === 'string') && (link = $.trim(link)) != "") { 161 | var slide = container.find('[data-orbit-slide='+link+']'); 162 | if (slide.index() != -1) {self._goto(slide.index());} 163 | } 164 | }; 165 | 166 | self.link_bullet = function(e) { 167 | var index = $(this).attr('data-orbit-slide'); 168 | if ((typeof index === 'string') && (index = $.trim(index)) != "") { 169 | if(isNaN(parseInt(index))) 170 | { 171 | var slide = container.find('[data-orbit-slide='+index+']'); 172 | if (slide.index() != -1) {self._goto(slide.index() + 1);} 173 | } 174 | else 175 | { 176 | self._goto(parseInt(index)); 177 | } 178 | } 179 | 180 | } 181 | 182 | self.timer_callback = function() { 183 | self._goto(idx + 1, true); 184 | } 185 | 186 | self.compute_dimensions = function() { 187 | var current = $(self.slides().get(idx)); 188 | var h = current.height(); 189 | if (!settings.variable_height) { 190 | self.slides().each(function(){ 191 | if ($(this).height() > h) { h = $(this).height(); } 192 | }); 193 | } 194 | slides_container.height(h); 195 | }; 196 | 197 | self.create_timer = function() { 198 | var t = new Timer( 199 | container.find('.'+settings.timer_container_class), 200 | settings, 201 | self.timer_callback 202 | ); 203 | return t; 204 | }; 205 | 206 | self.stop_timer = function() { 207 | if (typeof timer === 'object') timer.stop(); 208 | }; 209 | 210 | self.toggle_timer = function() { 211 | var t = container.find('.'+settings.timer_container_class); 212 | if (t.hasClass(settings.timer_paused_class)) { 213 | if (typeof timer === 'undefined') {timer = self.create_timer();} 214 | timer.start(); 215 | } 216 | else { 217 | if (typeof timer === 'object') {timer.stop();} 218 | } 219 | }; 220 | 221 | self.init = function() { 222 | self.build_markup(); 223 | if (settings.timer) { 224 | timer = self.create_timer(); 225 | Foundation.utils.image_loaded(this.slides().children('img'), timer.start); 226 | } 227 | animate = new FadeAnimation(settings, slides_container); 228 | if (settings.animation === 'slide') 229 | animate = new SlideAnimation(settings, slides_container); 230 | container.on('click', '.'+settings.next_class, self.next); 231 | container.on('click', '.'+settings.prev_class, self.prev); 232 | container.on('click', '[data-orbit-slide]', self.link_bullet); 233 | container.on('click', self.toggle_timer); 234 | if (settings.swipe) { 235 | container.on('touchstart.fndtn.orbit', function(e) { 236 | if (!e.touches) {e = e.originalEvent;} 237 | var data = { 238 | start_page_x: e.touches[0].pageX, 239 | start_page_y: e.touches[0].pageY, 240 | start_time: (new Date()).getTime(), 241 | delta_x: 0, 242 | is_scrolling: undefined 243 | }; 244 | container.data('swipe-transition', data); 245 | e.stopPropagation(); 246 | }) 247 | .on('touchmove.fndtn.orbit', function(e) { 248 | if (!e.touches) { e = e.originalEvent; } 249 | // Ignore pinch/zoom events 250 | if(e.touches.length > 1 || e.scale && e.scale !== 1) return; 251 | 252 | var data = container.data('swipe-transition'); 253 | if (typeof data === 'undefined') {data = {};} 254 | 255 | data.delta_x = e.touches[0].pageX - data.start_page_x; 256 | 257 | if ( typeof data.is_scrolling === 'undefined') { 258 | data.is_scrolling = !!( data.is_scrolling || Math.abs(data.delta_x) < Math.abs(e.touches[0].pageY - data.start_page_y) ); 259 | } 260 | 261 | if (!data.is_scrolling && !data.active) { 262 | e.preventDefault(); 263 | var direction = (data.delta_x < 0) ? (idx+1) : (idx-1); 264 | data.active = true; 265 | self._goto(direction); 266 | } 267 | }) 268 | .on('touchend.fndtn.orbit', function(e) { 269 | container.data('swipe-transition', {}); 270 | e.stopPropagation(); 271 | }) 272 | } 273 | container.on('mouseenter.fndtn.orbit', function(e) { 274 | if (settings.timer && settings.pause_on_hover) { 275 | self.stop_timer(); 276 | } 277 | }) 278 | .on('mouseleave.fndtn.orbit', function(e) { 279 | if (settings.timer && settings.resume_on_mouseout) { 280 | timer.start(); 281 | } 282 | }); 283 | 284 | $(document).on('click', '[data-orbit-link]', self.link_custom); 285 | $(window).on('resize', self.compute_dimensions); 286 | Foundation.utils.image_loaded(this.slides().children('img'), self.compute_dimensions); 287 | Foundation.utils.image_loaded(this.slides().children('img'), function() { 288 | container.prev('.preloader').css('display', 'none'); 289 | self.update_slide_number(0); 290 | self.update_active_link(0); 291 | slides_container.trigger('ready.fndtn.orbit'); 292 | }); 293 | }; 294 | 295 | self.init(); 296 | }; 297 | 298 | var Timer = function(el, settings, callback) { 299 | var self = this, 300 | duration = settings.timer_speed, 301 | progress = el.find('.'+settings.timer_progress_class), 302 | start, 303 | timeout, 304 | left = -1; 305 | 306 | this.update_progress = function(w) { 307 | var new_progress = progress.clone(); 308 | new_progress.attr('style', ''); 309 | new_progress.css('width', w+'%'); 310 | progress.replaceWith(new_progress); 311 | progress = new_progress; 312 | }; 313 | 314 | this.restart = function() { 315 | clearTimeout(timeout); 316 | el.addClass(settings.timer_paused_class); 317 | left = -1; 318 | self.update_progress(0); 319 | }; 320 | 321 | this.start = function() { 322 | if (!el.hasClass(settings.timer_paused_class)) {return true;} 323 | left = (left === -1) ? duration : left; 324 | el.removeClass(settings.timer_paused_class); 325 | start = new Date().getTime(); 326 | progress.animate({'width': '100%'}, left, 'linear'); 327 | timeout = setTimeout(function() { 328 | self.restart(); 329 | callback(); 330 | }, left); 331 | el.trigger('timer-started.fndtn.orbit') 332 | }; 333 | 334 | this.stop = function() { 335 | if (el.hasClass(settings.timer_paused_class)) {return true;} 336 | clearTimeout(timeout); 337 | el.addClass(settings.timer_paused_class); 338 | var end = new Date().getTime(); 339 | left = left - (end - start); 340 | var w = 100 - ((left / duration) * 100); 341 | self.update_progress(w); 342 | el.trigger('timer-stopped.fndtn.orbit'); 343 | }; 344 | }; 345 | 346 | var SlideAnimation = function(settings, container) { 347 | var duration = settings.animation_speed; 348 | var is_rtl = ($('html[dir=rtl]').length === 1); 349 | var margin = is_rtl ? 'marginRight' : 'marginLeft'; 350 | var animMargin = {}; 351 | animMargin[margin] = '0%'; 352 | 353 | this.next = function(current, next, callback) { 354 | current.animate({marginLeft:'-100%'}, duration); 355 | next.animate(animMargin, duration, function() { 356 | current.css(margin, '100%'); 357 | callback(); 358 | }); 359 | }; 360 | 361 | this.prev = function(current, prev, callback) { 362 | current.animate({marginLeft:'100%'}, duration); 363 | prev.css(margin, '-100%'); 364 | prev.animate(animMargin, duration, function() { 365 | current.css(margin, '100%'); 366 | callback(); 367 | }); 368 | }; 369 | }; 370 | 371 | var FadeAnimation = function(settings, container) { 372 | var duration = settings.animation_speed; 373 | var is_rtl = ($('html[dir=rtl]').length === 1); 374 | var margin = is_rtl ? 'marginRight' : 'marginLeft'; 375 | 376 | this.next = function(current, next, callback) { 377 | next.css({'margin':'0%', 'opacity':'0.01'}); 378 | next.animate({'opacity':'1'}, duration, 'linear', function() { 379 | current.css('margin', '100%'); 380 | callback(); 381 | }); 382 | }; 383 | 384 | this.prev = function(current, prev, callback) { 385 | prev.css({'margin':'0%', 'opacity':'0.01'}); 386 | prev.animate({'opacity':'1'}, duration, 'linear', function() { 387 | current.css('margin', '100%'); 388 | callback(); 389 | }); 390 | }; 391 | }; 392 | 393 | 394 | Foundation.libs = Foundation.libs || {}; 395 | 396 | Foundation.libs.orbit = { 397 | name: 'orbit', 398 | 399 | version: '5.1.0', 400 | 401 | settings: { 402 | animation: 'slide', 403 | timer_speed: 10000, 404 | pause_on_hover: true, 405 | resume_on_mouseout: false, 406 | animation_speed: 500, 407 | stack_on_small: false, 408 | navigation_arrows: true, 409 | slide_number: true, 410 | slide_number_text: 'of', 411 | container_class: 'orbit-container', 412 | stack_on_small_class: 'orbit-stack-on-small', 413 | next_class: 'orbit-next', 414 | prev_class: 'orbit-prev', 415 | timer_container_class: 'orbit-timer', 416 | timer_paused_class: 'paused', 417 | timer_progress_class: 'orbit-progress', 418 | slides_container_class: 'orbit-slides-container', 419 | slide_selector: '*', 420 | bullets_container_class: 'orbit-bullets', 421 | bullets_active_class: 'active', 422 | slide_number_class: 'orbit-slide-number', 423 | caption_class: 'orbit-caption', 424 | active_slide_class: 'active', 425 | orbit_transition_class: 'orbit-transitioning', 426 | bullets: true, 427 | circular: true, 428 | timer: true, 429 | variable_height: false, 430 | swipe: true, 431 | before_slide_change: noop, 432 | after_slide_change: noop 433 | }, 434 | 435 | init : function (scope, method, options) { 436 | var self = this; 437 | this.bindings(method, options); 438 | }, 439 | 440 | events : function (instance) { 441 | var orbit_instance = new Orbit(this.S(instance), this.S(instance).data('orbit-init')); 442 | this.S(instance).data(self.name + '-instance', orbit_instance); 443 | }, 444 | 445 | reflow : function () { 446 | var self = this; 447 | 448 | if (self.S(self.scope).is('[data-orbit]')) { 449 | var $el = self.S(self.scope); 450 | var instance = $el.data(self.name + '-instance'); 451 | instance.compute_dimensions(); 452 | } else { 453 | self.S('[data-orbit]', self.scope).each(function(idx, el) { 454 | var $el = self.S(el); 455 | var opts = self.data_options($el); 456 | var instance = $el.data(self.name + '-instance'); 457 | instance.compute_dimensions(); 458 | }); 459 | } 460 | } 461 | }; 462 | 463 | 464 | }(jQuery, this, this.document)); 465 | -------------------------------------------------------------------------------- /static/js/foundation/foundation.reveal.js: -------------------------------------------------------------------------------- 1 | ;(function ($, window, document, undefined) { 2 | 'use strict'; 3 | 4 | Foundation.libs.reveal = { 5 | name : 'reveal', 6 | 7 | version : '5.1.0', 8 | 9 | locked : false, 10 | 11 | settings : { 12 | animation: 'fadeAndPop', 13 | animation_speed: 250, 14 | close_on_background_click: true, 15 | close_on_esc: true, 16 | dismiss_modal_class: 'close-reveal-modal', 17 | bg_class: 'reveal-modal-bg', 18 | open: function(){}, 19 | opened: function(){}, 20 | close: function(){}, 21 | closed: function(){}, 22 | bg : $('.reveal-modal-bg'), 23 | css : { 24 | open : { 25 | 'opacity': 0, 26 | 'visibility': 'visible', 27 | 'display' : 'block' 28 | }, 29 | close : { 30 | 'opacity': 1, 31 | 'visibility': 'hidden', 32 | 'display': 'none' 33 | } 34 | } 35 | }, 36 | 37 | init : function (scope, method, options) { 38 | $.extend(true, this.settings, method, options); 39 | this.bindings(method, options); 40 | }, 41 | 42 | events : function (scope) { 43 | var self = this, 44 | S = self.S; 45 | 46 | S(this.scope) 47 | .off('.reveal') 48 | .on('click.fndtn.reveal', '[' + this.add_namespace('data-reveal-id') + ']', function (e) { 49 | e.preventDefault(); 50 | 51 | if (!self.locked) { 52 | var element = S(this), 53 | ajax = element.data(self.data_attr('reveal-ajax')); 54 | 55 | self.locked = true; 56 | 57 | if (typeof ajax === 'undefined') { 58 | self.open.call(self, element); 59 | } else { 60 | var url = ajax === true ? element.attr('href') : ajax; 61 | 62 | self.open.call(self, element, {url: url}); 63 | } 64 | } 65 | }); 66 | 67 | S(document) 68 | .on('click.fndtn.reveal', this.close_targets(), function (e) { 69 | 70 | e.preventDefault(); 71 | 72 | if (!self.locked) { 73 | var settings = S('[' + self.attr_name() + '].open').data(self.attr_name(true) + '-init'), 74 | bg_clicked = S(e.target)[0] === S('.' + settings.bg_class)[0]; 75 | 76 | if (bg_clicked && !settings.close_on_background_click) { 77 | return; 78 | } 79 | 80 | self.locked = true; 81 | self.close.call(self, bg_clicked ? S('[' + self.attr_name() + '].open') : S(this).closest('[' + self.attr_name() + ']')); 82 | } 83 | }); 84 | 85 | if(S('[' + self.attr_name() + ']', this.scope).length > 0) { 86 | S(this.scope) 87 | // .off('.reveal') 88 | .on('open.fndtn.reveal', this.settings.open) 89 | .on('opened.fndtn.reveal', this.settings.opened) 90 | .on('opened.fndtn.reveal', this.open_video) 91 | .on('close.fndtn.reveal', this.settings.close) 92 | .on('closed.fndtn.reveal', this.settings.closed) 93 | .on('closed.fndtn.reveal', this.close_video); 94 | } else { 95 | S(this.scope) 96 | // .off('.reveal') 97 | .on('open.fndtn.reveal', '[' + self.attr_name() + ']', this.settings.open) 98 | .on('opened.fndtn.reveal', '[' + self.attr_name() + ']', this.settings.opened) 99 | .on('opened.fndtn.reveal', '[' + self.attr_name() + ']', this.open_video) 100 | .on('close.fndtn.reveal', '[' + self.attr_name() + ']', this.settings.close) 101 | .on('closed.fndtn.reveal', '[' + self.attr_name() + ']', this.settings.closed) 102 | .on('closed.fndtn.reveal', '[' + self.attr_name() + ']', this.close_video); 103 | } 104 | 105 | return true; 106 | }, 107 | 108 | // PATCH #3: turning on key up capture only when a reveal window is open 109 | key_up_on : function (scope) { 110 | var self = this; 111 | 112 | // PATCH #1: fixing multiple keyup event trigger from single key press 113 | self.S('body').off('keyup.fndtn.reveal').on('keyup.fndtn.reveal', function ( event ) { 114 | var open_modal = self.S('[' + self.attr_name() + '].open'), 115 | settings = open_modal.data(self.attr_name(true) + '-init'); 116 | // PATCH #2: making sure that the close event can be called only while unlocked, 117 | // so that multiple keyup.fndtn.reveal events don't prevent clean closing of the reveal window. 118 | if ( settings && event.which === 27 && settings.close_on_esc && !self.locked) { // 27 is the keycode for the Escape key 119 | self.close.call(self, open_modal); 120 | } 121 | }); 122 | 123 | return true; 124 | }, 125 | 126 | // PATCH #3: turning on key up capture only when a reveal window is open 127 | key_up_off : function (scope) { 128 | this.S('body').off('keyup.fndtn.reveal'); 129 | return true; 130 | }, 131 | 132 | open : function (target, ajax_settings) { 133 | var self = this; 134 | if (target) { 135 | if (typeof target.selector !== 'undefined') { 136 | var modal = self.S('#' + target.data(self.data_attr('reveal-id'))); 137 | } else { 138 | var modal = self.S(this.scope); 139 | 140 | ajax_settings = target; 141 | } 142 | } else { 143 | var modal = self.S(this.scope); 144 | } 145 | 146 | var settings = modal.data(self.attr_name(true) + '-init'); 147 | 148 | if (!modal.hasClass('open')) { 149 | var open_modal = self.S('[' + self.attr_name() + '].open'); 150 | 151 | if (typeof modal.data('css-top') === 'undefined') { 152 | modal.data('css-top', parseInt(modal.css('top'), 10)) 153 | .data('offset', this.cache_offset(modal)); 154 | } 155 | 156 | this.key_up_on(modal); // PATCH #3: turning on key up capture only when a reveal window is open 157 | modal.trigger('open'); 158 | 159 | if (open_modal.length < 1) { 160 | this.toggle_bg(modal); 161 | } 162 | 163 | if (typeof ajax_settings === 'string') { 164 | ajax_settings = { 165 | url: ajax_settings 166 | }; 167 | } 168 | 169 | if (typeof ajax_settings === 'undefined' || !ajax_settings.url) { 170 | if (open_modal.length > 0) { 171 | var open_modal_settings = open_modal.data(self.attr_name(true) + '-init'); 172 | this.hide(open_modal, open_modal_settings.css.close); 173 | } 174 | 175 | this.show(modal, settings.css.open); 176 | } else { 177 | var old_success = typeof ajax_settings.success !== 'undefined' ? ajax_settings.success : null; 178 | 179 | $.extend(ajax_settings, { 180 | success: function (data, textStatus, jqXHR) { 181 | if ( $.isFunction(old_success) ) { 182 | old_success(data, textStatus, jqXHR); 183 | } 184 | 185 | modal.html(data); 186 | self.S(modal).foundation('section', 'reflow'); 187 | 188 | if (open_modal.length > 0) { 189 | var open_modal_settings = open_modal.data(self.attr_name(true)); 190 | self.hide(open_modal, open_modal_settings.css.close); 191 | } 192 | self.show(modal, settings.css.open); 193 | } 194 | }); 195 | 196 | $.ajax(ajax_settings); 197 | } 198 | } 199 | }, 200 | 201 | close : function (modal) { 202 | var modal = modal && modal.length ? modal : this.S(this.scope), 203 | open_modals = this.S('[' + this.attr_name() + '].open'), 204 | settings = modal.data(this.attr_name(true) + '-init'); 205 | 206 | if (open_modals.length > 0) { 207 | this.locked = true; 208 | this.key_up_off(modal); // PATCH #3: turning on key up capture only when a reveal window is open 209 | modal.trigger('close'); 210 | this.toggle_bg(modal); 211 | this.hide(open_modals, settings.css.close, settings); 212 | } 213 | }, 214 | 215 | close_targets : function () { 216 | var base = '.' + this.settings.dismiss_modal_class; 217 | 218 | if (this.settings.close_on_background_click) { 219 | return base + ', .' + this.settings.bg_class; 220 | } 221 | 222 | return base; 223 | }, 224 | 225 | toggle_bg : function (modal) { 226 | var settings = modal.data(this.attr_name(true)); 227 | 228 | if (this.S('.' + this.settings.bg_class).length === 0) { 229 | this.settings.bg = $('
    ', {'class': this.settings.bg_class}) 230 | .appendTo('body'); 231 | } 232 | 233 | if (this.settings.bg.filter(':visible').length > 0) { 234 | this.hide(this.settings.bg); 235 | } else { 236 | this.show(this.settings.bg); 237 | } 238 | }, 239 | 240 | show : function (el, css) { 241 | // is modal 242 | if (css) { 243 | var settings = el.data(this.attr_name(true) + '-init'); 244 | if (el.parent('body').length === 0) { 245 | var placeholder = el.wrap('
    ').parent(), 246 | rootElement = this.settings.rootElement || 'body'; 247 | 248 | el.on('closed.fndtn.reveal.wrapped', function() { 249 | el.detach().appendTo(placeholder); 250 | el.unwrap().unbind('closed.fndtn.reveal.wrapped'); 251 | }); 252 | 253 | el.detach().appendTo(rootElement); 254 | } 255 | 256 | if (/pop/i.test(settings.animation)) { 257 | css.top = $(window).scrollTop() - el.data('offset') + 'px'; 258 | var end_css = { 259 | top: $(window).scrollTop() + el.data('css-top') + 'px', 260 | opacity: 1 261 | }; 262 | 263 | return setTimeout(function () { 264 | return el 265 | .css(css) 266 | .animate(end_css, settings.animation_speed, 'linear', function () { 267 | this.locked = false; 268 | el.trigger('opened'); 269 | }.bind(this)) 270 | .addClass('open'); 271 | }.bind(this), settings.animation_speed / 2); 272 | } 273 | 274 | if (/fade/i.test(settings.animation)) { 275 | var end_css = {opacity: 1}; 276 | 277 | return setTimeout(function () { 278 | return el 279 | .css(css) 280 | .animate(end_css, settings.animation_speed, 'linear', function () { 281 | this.locked = false; 282 | el.trigger('opened'); 283 | }.bind(this)) 284 | .addClass('open'); 285 | }.bind(this), settings.animation_speed / 2); 286 | } 287 | 288 | return el.css(css).show().css({opacity: 1}).addClass('open').trigger('opened'); 289 | } 290 | 291 | var settings = this.settings; 292 | 293 | // should we animate the background? 294 | if (/fade/i.test(settings.animation)) { 295 | return el.fadeIn(settings.animation_speed / 2); 296 | } 297 | 298 | this.locked = false; 299 | 300 | return el.show(); 301 | }, 302 | 303 | hide : function (el, css) { 304 | // is modal 305 | if (css) { 306 | var settings = el.data(this.attr_name(true) + '-init'); 307 | if (/pop/i.test(settings.animation)) { 308 | var end_css = { 309 | top: - $(window).scrollTop() - el.data('offset') + 'px', 310 | opacity: 0 311 | }; 312 | 313 | return setTimeout(function () { 314 | return el 315 | .animate(end_css, settings.animation_speed, 'linear', function () { 316 | this.locked = false; 317 | el.css(css).trigger('closed'); 318 | }.bind(this)) 319 | .removeClass('open'); 320 | }.bind(this), settings.animation_speed / 2); 321 | } 322 | 323 | if (/fade/i.test(settings.animation)) { 324 | var end_css = {opacity: 0}; 325 | 326 | return setTimeout(function () { 327 | return el 328 | .animate(end_css, settings.animation_speed, 'linear', function () { 329 | this.locked = false; 330 | el.css(css).trigger('closed'); 331 | }.bind(this)) 332 | .removeClass('open'); 333 | }.bind(this), settings.animation_speed / 2); 334 | } 335 | 336 | return el.hide().css(css).removeClass('open').trigger('closed'); 337 | } 338 | 339 | var settings = this.settings; 340 | 341 | // should we animate the background? 342 | if (/fade/i.test(settings.animation)) { 343 | return el.fadeOut(settings.animation_speed / 2); 344 | } 345 | 346 | return el.hide(); 347 | }, 348 | 349 | close_video : function (e) { 350 | var video = $('.flex-video', e.target), 351 | iframe = $('iframe', video); 352 | 353 | if (iframe.length > 0) { 354 | iframe.attr('data-src', iframe[0].src); 355 | iframe.attr('src', 'about:blank'); 356 | video.hide(); 357 | } 358 | }, 359 | 360 | open_video : function (e) { 361 | var video = $('.flex-video', e.target), 362 | iframe = video.find('iframe'); 363 | 364 | if (iframe.length > 0) { 365 | var data_src = iframe.attr('data-src'); 366 | if (typeof data_src === 'string') { 367 | iframe[0].src = iframe.attr('data-src'); 368 | } else { 369 | var src = iframe[0].src; 370 | iframe[0].src = undefined; 371 | iframe[0].src = src; 372 | } 373 | video.show(); 374 | } 375 | }, 376 | 377 | data_attr: function (str) { 378 | if (this.namespace.length > 0) { 379 | return this.namespace + '-' + str; 380 | } 381 | 382 | return str; 383 | }, 384 | 385 | cache_offset : function (modal) { 386 | var offset = modal.show().height() + parseInt(modal.css('top'), 10); 387 | 388 | modal.hide(); 389 | 390 | return offset; 391 | }, 392 | 393 | off : function () { 394 | $(this.scope).off('.fndtn.reveal'); 395 | }, 396 | 397 | reflow : function () {} 398 | }; 399 | }(jQuery, this, this.document)); 400 | -------------------------------------------------------------------------------- /static/js/foundation/foundation.tab.js: -------------------------------------------------------------------------------- 1 | /*jslint unparam: true, browser: true, indent: 2 */ 2 | ;(function ($, window, document, undefined) { 3 | 'use strict'; 4 | 5 | Foundation.libs.tab = { 6 | name : 'tab', 7 | 8 | version : '5.1.0', 9 | 10 | settings : { 11 | active_class: 'active', 12 | callback : function () {} 13 | }, 14 | 15 | init : function (scope, method, options) { 16 | this.bindings(method, options); 17 | }, 18 | 19 | events : function () { 20 | var self = this, 21 | S = this.S; 22 | 23 | S(this.scope).off('.tab').on('click.fndtn.tab', '[' + this.attr_name() + '] > dd > a', function (e) { 24 | e.preventDefault(); 25 | e.stopPropagation(); 26 | 27 | var tab = S(this).parent(), 28 | tabs = tab.closest('[' + self.attr_name() + ']'), 29 | target = S('#' + this.href.split('#')[1]), 30 | siblings = tab.siblings(), 31 | settings = tabs.data(self.attr_name(true) + '-init'); 32 | 33 | // allow usage of data-tab-content attribute instead of href 34 | if (S(this).data(self.data_attr('tab-content'))) { 35 | target = S('#' + S(this).data(self.data_attr('tab-content')).split('#')[1]); 36 | } 37 | 38 | tab.addClass(settings.active_class).triggerHandler('opened'); 39 | siblings.removeClass(settings.active_class); 40 | target.siblings().removeClass(settings.active_class).end().addClass(settings.active_class); 41 | settings.callback(tab); 42 | tabs.triggerHandler('toggled', [tab]); 43 | }); 44 | }, 45 | 46 | data_attr: function (str) { 47 | if (this.namespace.length > 0) { 48 | return this.namespace + '-' + str; 49 | } 50 | 51 | return str; 52 | }, 53 | 54 | off : function () {}, 55 | 56 | reflow : function () {} 57 | }; 58 | }(jQuery, this, this.document)); 59 | -------------------------------------------------------------------------------- /static/js/foundation/foundation.tooltip.js: -------------------------------------------------------------------------------- 1 | ;(function ($, window, document, undefined) { 2 | 'use strict'; 3 | 4 | Foundation.libs.tooltip = { 5 | name : 'tooltip', 6 | 7 | version : '5.1.0', 8 | 9 | settings : { 10 | additional_inheritable_classes : [], 11 | tooltip_class : '.tooltip', 12 | append_to: 'body', 13 | touch_close_text: 'Tap To Close', 14 | disable_for_touch: false, 15 | hover_delay: 200, 16 | tip_template : function (selector, content) { 17 | return '' + content + ''; 20 | } 21 | }, 22 | 23 | cache : {}, 24 | 25 | init : function (scope, method, options) { 26 | Foundation.inherit(this, 'random_str'); 27 | this.bindings(method, options); 28 | }, 29 | 30 | events : function () { 31 | var self = this, 32 | S = self.S; 33 | 34 | if (Modernizr.touch) { 35 | S(document) 36 | .off('.tooltip') 37 | .on('click.fndtn.tooltip touchstart.fndtn.tooltip touchend.fndtn.tooltip', 38 | '[' + this.attr_name() + ']:not(a)', function (e) { 39 | var settings = $.extend({}, self.settings, self.data_options(S(this))); 40 | if (!settings.disable_for_touch) { 41 | e.preventDefault(); 42 | S(settings.tooltip_class).hide(); 43 | self.showOrCreateTip(S(this)); 44 | } 45 | }) 46 | .on('click.fndtn.tooltip touchstart.fndtn.tooltip touchend.fndtn.tooltip', 47 | this.settings.tooltip_class, function (e) { 48 | e.preventDefault(); 49 | S(this).fadeOut(150); 50 | }); 51 | } else { 52 | S(document) 53 | .off('.tooltip') 54 | .on('mouseenter.fndtn.tooltip mouseleave.fndtn.tooltip', 55 | '[' + this.attr_name() + ']', function (e) { 56 | var $this = S(this); 57 | 58 | if (/enter|over/i.test(e.type)) { 59 | this.timer = setTimeout(function () { 60 | var tip = self.showOrCreateTip($this); 61 | }.bind(this), self.settings.hover_delay); 62 | } else if (e.type === 'mouseout' || e.type === 'mouseleave') { 63 | clearTimeout(this.timer); 64 | self.hide($this); 65 | } 66 | }); 67 | } 68 | }, 69 | 70 | showOrCreateTip : function ($target) { 71 | var $tip = this.getTip($target); 72 | 73 | if ($tip && $tip.length > 0) { 74 | return this.show($target); 75 | } 76 | 77 | return this.create($target); 78 | }, 79 | 80 | getTip : function ($target) { 81 | var selector = this.selector($target), 82 | tip = null; 83 | 84 | if (selector) { 85 | tip = this.S('span[data-selector="' + selector + '"]' + this.settings.tooltip_class); 86 | } 87 | 88 | return (typeof tip === 'object') ? tip : false; 89 | }, 90 | 91 | selector : function ($target) { 92 | var id = $target.attr('id'), 93 | dataSelector = $target.attr(this.attr_name()) || $target.attr('data-selector'); 94 | 95 | if ((id && id.length < 1 || !id) && typeof dataSelector != 'string') { 96 | dataSelector = 'tooltip' + this.random_str(6); 97 | $target.attr('data-selector', dataSelector); 98 | } 99 | 100 | return (id && id.length > 0) ? id : dataSelector; 101 | }, 102 | 103 | create : function ($target) { 104 | var $tip = $(this.settings.tip_template(this.selector($target), $('
    ').html($target.attr('title')).html())), 105 | classes = this.inheritable_classes($target); 106 | 107 | $tip.addClass(classes).appendTo(this.settings.append_to); 108 | if (Modernizr.touch) { 109 | $tip.append(''+this.settings.touch_close_text+''); 110 | } 111 | $target.removeAttr('title').attr('title',''); 112 | this.show($target); 113 | }, 114 | 115 | reposition : function (target, tip, classes) { 116 | var width, nub, nubHeight, nubWidth, column, objPos; 117 | 118 | tip.css('visibility', 'hidden').show(); 119 | 120 | width = target.data('width'); 121 | nub = tip.children('.nub'); 122 | nubHeight = nub.outerHeight(); 123 | nubWidth = nub.outerHeight(); 124 | 125 | if(this.small()) { 126 | tip.css({'width' : '100%' }); 127 | } else { 128 | tip.css({'width' : (width) ? width : 'auto'}); 129 | } 130 | 131 | objPos = function (obj, top, right, bottom, left, width) { 132 | return obj.css({ 133 | 'top' : (top) ? top : 'auto', 134 | 'bottom' : (bottom) ? bottom : 'auto', 135 | 'left' : (left) ? left : 'auto', 136 | 'right' : (right) ? right : 'auto' 137 | }).end(); 138 | }; 139 | 140 | objPos(tip, (target.offset().top + target.outerHeight() + 10), 'auto', 'auto', target.offset().left); 141 | 142 | if (this.small()) { 143 | objPos(tip, (target.offset().top + target.outerHeight() + 10), 'auto', 'auto', 12.5, this.S(this.scope).width()); 144 | tip.addClass('tip-override'); 145 | objPos(nub, -nubHeight, 'auto', 'auto', target.offset().left + 10); 146 | } else { 147 | var left = target.offset().left; 148 | if (Foundation.rtl) { 149 | left = target.offset().left + target.outerWidth() - tip.outerWidth(); 150 | } 151 | 152 | objPos(tip, (target.offset().top + target.outerHeight() + 10), 'auto', 'auto', left); 153 | tip.removeClass('tip-override'); 154 | nub.removeAttr( 'style' ); 155 | if (classes && classes.indexOf('tip-top') > -1) { 156 | objPos(tip, (target.offset().top - tip.outerHeight() - 10), 'auto', 'auto', left) 157 | .removeClass('tip-override'); 158 | } else if (classes && classes.indexOf('tip-left') > -1) { 159 | objPos(tip, (target.offset().top + (target.outerHeight() / 2) - (tip.outerHeight() / 2)), 'auto', 'auto', (target.offset().left - tip.outerWidth() - nubHeight)) 160 | .removeClass('tip-override'); 161 | } else if (classes && classes.indexOf('tip-right') > -1) { 162 | objPos(tip, (target.offset().top + (target.outerHeight() / 2) - (tip.outerHeight() / 2)), 'auto', 'auto', (target.offset().left + target.outerWidth() + nubHeight)) 163 | .removeClass('tip-override'); 164 | } 165 | } 166 | 167 | tip.css('visibility', 'visible').hide(); 168 | }, 169 | 170 | small : function () { 171 | return matchMedia(Foundation.media_queries.small).matches; 172 | }, 173 | 174 | inheritable_classes : function (target) { 175 | var inheritables = ['tip-top', 'tip-left', 'tip-bottom', 'tip-right', 'radius', 'round'].concat(this.settings.additional_inheritable_classes), 176 | classes = target.attr('class'), 177 | filtered = classes ? $.map(classes.split(' '), function (el, i) { 178 | if ($.inArray(el, inheritables) !== -1) { 179 | return el; 180 | } 181 | }).join(' ') : ''; 182 | 183 | return $.trim(filtered); 184 | }, 185 | 186 | show : function ($target) { 187 | var $tip = this.getTip($target); 188 | 189 | this.reposition($target, $tip, $target.attr('class')); 190 | return $tip.fadeIn(150); 191 | }, 192 | 193 | hide : function ($target) { 194 | var $tip = this.getTip($target); 195 | 196 | return $tip.fadeOut(150); 197 | }, 198 | 199 | // deprecate reload 200 | reload : function () { 201 | var $self = $(this); 202 | 203 | return ($self.data('fndtn-tooltips')) ? $self.foundationTooltips('destroy').foundationTooltips('init') : $self.foundationTooltips('init'); 204 | }, 205 | 206 | off : function () { 207 | this.S(this.scope).off('.fndtn.tooltip'); 208 | this.S(this.settings.tooltip_class).each(function (i) { 209 | $('[' + this.attr_name() + ']').get(i).attr('title', $(this).text()); 210 | }).remove(); 211 | }, 212 | 213 | reflow : function () {} 214 | }; 215 | }(jQuery, this, this.document)); 216 | -------------------------------------------------------------------------------- /static/js/foundation/foundation.topbar.js: -------------------------------------------------------------------------------- 1 | ;(function ($, window, document, undefined) { 2 | 'use strict'; 3 | 4 | Foundation.libs.topbar = { 5 | name : 'topbar', 6 | 7 | version: '5.1.0', 8 | 9 | settings : { 10 | index : 0, 11 | sticky_class : 'sticky', 12 | custom_back_text: true, 13 | back_text: 'Back', 14 | is_hover: true, 15 | mobile_show_parent_link: false, 16 | scrolltop : true // jump to top when sticky nav menu toggle is clicked 17 | }, 18 | 19 | init : function (section, method, options) { 20 | Foundation.inherit(this, 'add_custom_rule register_media throttle'); 21 | var self = this; 22 | 23 | self.register_media('topbar', 'foundation-mq-topbar'); 24 | 25 | this.bindings(method, options); 26 | 27 | self.S('[' + this.attr_name() + ']', this.scope).each(function () { 28 | var topbar = self.S(this), 29 | settings = topbar.data(self.attr_name(true) + '-init'), 30 | section = self.S('section', this), 31 | titlebar = $('> ul', this).first(); 32 | 33 | topbar.data('index', 0); 34 | 35 | var topbarContainer = topbar.parent(); 36 | if(topbarContainer.hasClass('fixed') || topbarContainer.hasClass(settings.sticky_class)) { 37 | self.settings.sticky_class = settings.sticky_class; 38 | self.settings.sticky_topbar = topbar; 39 | topbar.data('height', topbarContainer.outerHeight()); 40 | topbar.data('stickyoffset', topbarContainer.offset().top); 41 | } else { 42 | topbar.data('height', topbar.outerHeight()); 43 | } 44 | 45 | if (!settings.assembled) self.assemble(topbar); 46 | 47 | if (settings.is_hover) { 48 | self.S('.has-dropdown', topbar).addClass('not-click'); 49 | } else { 50 | self.S('.has-dropdown', topbar).removeClass('not-click'); 51 | } 52 | 53 | // Pad body when sticky (scrolled) or fixed. 54 | self.add_custom_rule('.f-topbar-fixed { padding-top: ' + topbar.data('height') + 'px }'); 55 | 56 | if (topbarContainer.hasClass('fixed')) { 57 | self.S('body').addClass('f-topbar-fixed'); 58 | } 59 | }); 60 | 61 | }, 62 | 63 | toggle: function (toggleEl) { 64 | var self = this; 65 | 66 | if (toggleEl) { 67 | var topbar = self.S(toggleEl).closest('[' + this.attr_name() + ']'); 68 | } else { 69 | var topbar = self.S('[' + this.attr_name() + ']'); 70 | } 71 | 72 | var settings = topbar.data(this.attr_name(true) + '-init'); 73 | 74 | var section = self.S('section, .section', topbar); 75 | 76 | if (self.breakpoint()) { 77 | if (!self.rtl) { 78 | section.css({left: '0%'}); 79 | $('>.name', section).css({left: '100%'}); 80 | } else { 81 | section.css({right: '0%'}); 82 | $('>.name', section).css({right: '100%'}); 83 | } 84 | 85 | self.S('li.moved', section).removeClass('moved'); 86 | topbar.data('index', 0); 87 | 88 | topbar 89 | .toggleClass('expanded') 90 | .css('height', ''); 91 | } 92 | 93 | if (settings.scrolltop) { 94 | if (!topbar.hasClass('expanded')) { 95 | if (topbar.hasClass('fixed')) { 96 | topbar.parent().addClass('fixed'); 97 | topbar.removeClass('fixed'); 98 | self.S('body').addClass('f-topbar-fixed'); 99 | } 100 | } else if (topbar.parent().hasClass('fixed')) { 101 | if (settings.scrolltop) { 102 | topbar.parent().removeClass('fixed'); 103 | topbar.addClass('fixed'); 104 | self.S('body').removeClass('f-topbar-fixed'); 105 | 106 | window.scrollTo(0,0); 107 | } else { 108 | topbar.parent().removeClass('expanded'); 109 | } 110 | } 111 | } else { 112 | if(topbar.parent().hasClass(self.settings.sticky_class)) { 113 | topbar.parent().addClass('fixed'); 114 | } 115 | 116 | if(topbar.parent().hasClass('fixed')) { 117 | if (!topbar.hasClass('expanded')) { 118 | topbar.removeClass('fixed'); 119 | topbar.parent().removeClass('expanded'); 120 | self.update_sticky_positioning(); 121 | } else { 122 | topbar.addClass('fixed'); 123 | topbar.parent().addClass('expanded'); 124 | self.S('body').addClass('f-topbar-fixed'); 125 | } 126 | } 127 | } 128 | }, 129 | 130 | timer : null, 131 | 132 | events : function (bar) { 133 | var self = this, 134 | S = this.S; 135 | 136 | S(this.scope) 137 | .off('.topbar') 138 | .on('click.fndtn.topbar', '[' + this.attr_name() + '] .toggle-topbar', function (e) { 139 | e.preventDefault(); 140 | self.toggle(this); 141 | }) 142 | .on('click.fndtn.topbar', '[' + this.attr_name() + '] li.has-dropdown', function (e) { 143 | var li = S(this), 144 | target = S(e.target), 145 | topbar = li.closest('[' + self.attr_name() + ']'), 146 | settings = topbar.data(self.attr_name(true) + '-init'); 147 | 148 | if(target.data('revealId')) { 149 | self.toggle(); 150 | return; 151 | } 152 | 153 | if (self.breakpoint()) return; 154 | if (settings.is_hover && !Modernizr.touch) return; 155 | 156 | e.stopImmediatePropagation(); 157 | 158 | if (li.hasClass('hover')) { 159 | li 160 | .removeClass('hover') 161 | .find('li') 162 | .removeClass('hover'); 163 | 164 | li.parents('li.hover') 165 | .removeClass('hover'); 166 | } else { 167 | li.addClass('hover'); 168 | 169 | if (target[0].nodeName === 'A' && target.parent().hasClass('has-dropdown')) { 170 | e.preventDefault(); 171 | } 172 | } 173 | }) 174 | .on('click.fndtn.topbar', '[' + this.attr_name() + '] .has-dropdown>a', function (e) { 175 | if (self.breakpoint()) { 176 | 177 | e.preventDefault(); 178 | 179 | var $this = S(this), 180 | topbar = $this.closest('[' + self.attr_name() + ']'), 181 | section = topbar.find('section, .section'), 182 | dropdownHeight = $this.next('.dropdown').outerHeight(), 183 | $selectedLi = $this.closest('li'); 184 | 185 | topbar.data('index', topbar.data('index') + 1); 186 | $selectedLi.addClass('moved'); 187 | 188 | if (!self.rtl) { 189 | section.css({left: -(100 * topbar.data('index')) + '%'}); 190 | section.find('>.name').css({left: 100 * topbar.data('index') + '%'}); 191 | } else { 192 | section.css({right: -(100 * topbar.data('index')) + '%'}); 193 | section.find('>.name').css({right: 100 * topbar.data('index') + '%'}); 194 | } 195 | 196 | topbar.css('height', $this.siblings('ul').outerHeight(true) + topbar.data('height')); 197 | } 198 | }); 199 | 200 | S(window).off('.topbar').on('resize.fndtn.topbar', self.throttle(function () { 201 | self.resize.call(self); 202 | }, 50)).trigger('resize'); 203 | 204 | S('body').off('.topbar').on('click.fndtn.topbar touchstart.fndtn.topbar', function (e) { 205 | var parent = S(e.target).closest('li').closest('li.hover'); 206 | 207 | if (parent.length > 0) { 208 | return; 209 | } 210 | 211 | S('[' + self.attr_name() + '] li').removeClass('hover'); 212 | }); 213 | 214 | // Go up a level on Click 215 | S(this.scope).on('click.fndtn.topbar', '[' + this.attr_name() + '] .has-dropdown .back', function (e) { 216 | e.preventDefault(); 217 | 218 | var $this = S(this), 219 | topbar = $this.closest('[' + self.attr_name() + ']'), 220 | section = topbar.find('section, .section'), 221 | settings = topbar.data(self.attr_name(true) + '-init'), 222 | $movedLi = $this.closest('li.moved'), 223 | $previousLevelUl = $movedLi.parent(); 224 | 225 | topbar.data('index', topbar.data('index') - 1); 226 | 227 | if (!self.rtl) { 228 | section.css({left: -(100 * topbar.data('index')) + '%'}); 229 | section.find('>.name').css({left: 100 * topbar.data('index') + '%'}); 230 | } else { 231 | section.css({right: -(100 * topbar.data('index')) + '%'}); 232 | section.find('>.name').css({right: 100 * topbar.data('index') + '%'}); 233 | } 234 | 235 | if (topbar.data('index') === 0) { 236 | topbar.css('height', ''); 237 | } else { 238 | topbar.css('height', $previousLevelUl.outerHeight(true) + topbar.data('height')); 239 | } 240 | 241 | setTimeout(function () { 242 | $movedLi.removeClass('moved'); 243 | }, 300); 244 | }); 245 | }, 246 | 247 | resize : function () { 248 | var self = this; 249 | self.S('[' + this.attr_name() + ']').each(function () { 250 | var topbar = self.S(this), 251 | settings = topbar.data(self.attr_name(true) + '-init'); 252 | 253 | var stickyContainer = topbar.parent('.' + self.settings.sticky_class); 254 | var stickyOffset; 255 | 256 | if (!self.breakpoint()) { 257 | var doToggle = topbar.hasClass('expanded'); 258 | topbar 259 | .css('height', '') 260 | .removeClass('expanded') 261 | .find('li') 262 | .removeClass('hover'); 263 | 264 | if(doToggle) { 265 | self.toggle(topbar); 266 | } 267 | } 268 | 269 | if(stickyContainer.length > 0) { 270 | if(stickyContainer.hasClass('fixed')) { 271 | // Remove the fixed to allow for correct calculation of the offset. 272 | stickyContainer.removeClass('fixed'); 273 | 274 | stickyOffset = stickyContainer.offset().top; 275 | if(self.S(document.body).hasClass('f-topbar-fixed')) { 276 | stickyOffset -= topbar.data('height'); 277 | } 278 | 279 | topbar.data('stickyoffset', stickyOffset); 280 | stickyContainer.addClass('fixed'); 281 | } else { 282 | stickyOffset = stickyContainer.offset().top; 283 | topbar.data('stickyoffset', stickyOffset); 284 | } 285 | } 286 | 287 | }); 288 | }, 289 | 290 | breakpoint : function () { 291 | return !matchMedia(Foundation.media_queries['topbar']).matches; 292 | }, 293 | 294 | assemble : function (topbar) { 295 | var self = this, 296 | settings = topbar.data(this.attr_name(true) + '-init'), 297 | section = self.S('section', topbar), 298 | titlebar = $('> ul', topbar).first(); 299 | 300 | // Pull element out of the DOM for manipulation 301 | section.detach(); 302 | 303 | self.S('.has-dropdown>a', section).each(function () { 304 | var $link = self.S(this), 305 | $dropdown = $link.siblings('.dropdown'), 306 | url = $link.attr('href'); 307 | 308 | if (!$dropdown.find('.title.back').length) { 309 | if (settings.mobile_show_parent_link && url && url.length > 1) { 310 | var $titleLi = $('
  2. ' + $link.text() +'
  3. '); 311 | } else { 312 | var $titleLi = $('
  4. '); 313 | } 314 | 315 | // Copy link to subnav 316 | if (settings.custom_back_text == true) { 317 | $('h5>a', $titleLi).html(settings.back_text); 318 | } else { 319 | $('h5>a', $titleLi).html('« ' + $link.html()); 320 | } 321 | $dropdown.prepend($titleLi); 322 | } 323 | }); 324 | 325 | // Put element back in the DOM 326 | section.appendTo(topbar); 327 | 328 | // check for sticky 329 | this.sticky(); 330 | 331 | this.assembled(topbar); 332 | }, 333 | 334 | assembled : function (topbar) { 335 | topbar.data(this.attr_name(true), $.extend({}, topbar.data(this.attr_name(true)), {assembled: true})); 336 | }, 337 | 338 | height : function (ul) { 339 | var total = 0, 340 | self = this; 341 | 342 | $('> li', ul).each(function () { total += self.S(this).outerHeight(true); }); 343 | 344 | return total; 345 | }, 346 | 347 | sticky : function () { 348 | var $window = this.S(window), 349 | self = this; 350 | 351 | this.S(window).on('scroll', function() { 352 | self.update_sticky_positioning(); 353 | }); 354 | }, 355 | 356 | update_sticky_positioning: function() { 357 | var klass = '.' + this.settings.sticky_class, 358 | $window = this.S(window), 359 | self = this; 360 | 361 | 362 | if (self.S(klass).length > 0) { 363 | var distance = this.settings.sticky_topbar.data('stickyoffset'); 364 | if (!self.S(klass).hasClass('expanded')) { 365 | if ($window.scrollTop() > (distance)) { 366 | if (!self.S(klass).hasClass('fixed')) { 367 | self.S(klass).addClass('fixed'); 368 | self.S('body').addClass('f-topbar-fixed'); 369 | } 370 | } else if ($window.scrollTop() <= distance) { 371 | if (self.S(klass).hasClass('fixed')) { 372 | self.S(klass).removeClass('fixed'); 373 | self.S('body').removeClass('f-topbar-fixed'); 374 | } 375 | } 376 | } 377 | } 378 | }, 379 | 380 | off : function () { 381 | this.S(this.scope).off('.fndtn.topbar'); 382 | this.S(window).off('.fndtn.topbar'); 383 | }, 384 | 385 | reflow : function () {} 386 | }; 387 | }(jQuery, this, this.document)); 388 | -------------------------------------------------------------------------------- /static/js/vendor/fastclick.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve FastClick: polyfill to remove click delays on browsers with touch UIs. 3 | * 4 | * @version 0.6.11 5 | * @codingstandard ftlabs-jsv2 6 | * @copyright The Financial Times Limited [All Rights Reserved] 7 | * @license MIT License (see LICENSE.txt) 8 | */ 9 | function FastClick(a){"use strict";var b,c=this;if(this.trackingClick=!1,this.trackingClickStart=0,this.targetElement=null,this.touchStartX=0,this.touchStartY=0,this.lastTouchIdentifier=0,this.touchBoundary=10,this.layer=a,!a||!a.nodeType)throw new TypeError("Layer must be a document node");this.onClick=function(){return FastClick.prototype.onClick.apply(c,arguments)},this.onMouse=function(){return FastClick.prototype.onMouse.apply(c,arguments)},this.onTouchStart=function(){return FastClick.prototype.onTouchStart.apply(c,arguments)},this.onTouchMove=function(){return FastClick.prototype.onTouchMove.apply(c,arguments)},this.onTouchEnd=function(){return FastClick.prototype.onTouchEnd.apply(c,arguments)},this.onTouchCancel=function(){return FastClick.prototype.onTouchCancel.apply(c,arguments)},FastClick.notNeeded(a)||(this.deviceIsAndroid&&(a.addEventListener("mouseover",this.onMouse,!0),a.addEventListener("mousedown",this.onMouse,!0),a.addEventListener("mouseup",this.onMouse,!0)),a.addEventListener("click",this.onClick,!0),a.addEventListener("touchstart",this.onTouchStart,!1),a.addEventListener("touchmove",this.onTouchMove,!1),a.addEventListener("touchend",this.onTouchEnd,!1),a.addEventListener("touchcancel",this.onTouchCancel,!1),Event.prototype.stopImmediatePropagation||(a.removeEventListener=function(b,c,d){var e=Node.prototype.removeEventListener;"click"===b?e.call(a,b,c.hijacked||c,d):e.call(a,b,c,d)},a.addEventListener=function(b,c,d){var e=Node.prototype.addEventListener;"click"===b?e.call(a,b,c.hijacked||(c.hijacked=function(a){a.propagationStopped||c(a)}),d):e.call(a,b,c,d)}),"function"==typeof a.onclick&&(b=a.onclick,a.addEventListener("click",function(a){b(a)},!1),a.onclick=null))}FastClick.prototype.deviceIsAndroid=navigator.userAgent.indexOf("Android")>0,FastClick.prototype.deviceIsIOS=/iP(ad|hone|od)/.test(navigator.userAgent),FastClick.prototype.deviceIsIOS4=FastClick.prototype.deviceIsIOS&&/OS 4_\d(_\d)?/.test(navigator.userAgent),FastClick.prototype.deviceIsIOSWithBadTarget=FastClick.prototype.deviceIsIOS&&/OS ([6-9]|\d{2})_\d/.test(navigator.userAgent),FastClick.prototype.needsClick=function(a){"use strict";switch(a.nodeName.toLowerCase()){case"button":case"select":case"textarea":if(a.disabled)return!0;break;case"input":if(this.deviceIsIOS&&"file"===a.type||a.disabled)return!0;break;case"label":case"video":return!0}return/\bneedsclick\b/.test(a.className)},FastClick.prototype.needsFocus=function(a){"use strict";switch(a.nodeName.toLowerCase()){case"textarea":return!0;case"select":return!this.deviceIsAndroid;case"input":switch(a.type){case"button":case"checkbox":case"file":case"image":case"radio":case"submit":return!1}return!a.disabled&&!a.readOnly;default:return/\bneedsfocus\b/.test(a.className)}},FastClick.prototype.sendClick=function(a,b){"use strict";var c,d;document.activeElement&&document.activeElement!==a&&document.activeElement.blur(),d=b.changedTouches[0],c=document.createEvent("MouseEvents"),c.initMouseEvent(this.determineEventType(a),!0,!0,window,1,d.screenX,d.screenY,d.clientX,d.clientY,!1,!1,!1,!1,0,null),c.forwardedTouchEvent=!0,a.dispatchEvent(c)},FastClick.prototype.determineEventType=function(a){"use strict";return this.deviceIsAndroid&&"select"===a.tagName.toLowerCase()?"mousedown":"click"},FastClick.prototype.focus=function(a){"use strict";var b;this.deviceIsIOS&&a.setSelectionRange&&0!==a.type.indexOf("date")&&"time"!==a.type?(b=a.value.length,a.setSelectionRange(b,b)):a.focus()},FastClick.prototype.updateScrollParent=function(a){"use strict";var b,c;if(b=a.fastClickScrollParent,!b||!b.contains(a)){c=a;do{if(c.scrollHeight>c.offsetHeight){b=c,a.fastClickScrollParent=c;break}c=c.parentElement}while(c)}b&&(b.fastClickLastScrollTop=b.scrollTop)},FastClick.prototype.getTargetElementFromEventTarget=function(a){"use strict";return a.nodeType===Node.TEXT_NODE?a.parentNode:a},FastClick.prototype.onTouchStart=function(a){"use strict";var b,c,d;if(a.targetTouches.length>1)return!0;if(b=this.getTargetElementFromEventTarget(a.target),c=a.targetTouches[0],this.deviceIsIOS){if(d=window.getSelection(),d.rangeCount&&!d.isCollapsed)return!0;if(!this.deviceIsIOS4){if(c.identifier===this.lastTouchIdentifier)return a.preventDefault(),!1;this.lastTouchIdentifier=c.identifier,this.updateScrollParent(b)}}return this.trackingClick=!0,this.trackingClickStart=a.timeStamp,this.targetElement=b,this.touchStartX=c.pageX,this.touchStartY=c.pageY,a.timeStamp-this.lastClickTime<200&&a.preventDefault(),!0},FastClick.prototype.touchHasMoved=function(a){"use strict";var b=a.changedTouches[0],c=this.touchBoundary;return Math.abs(b.pageX-this.touchStartX)>c||Math.abs(b.pageY-this.touchStartY)>c?!0:!1},FastClick.prototype.onTouchMove=function(a){"use strict";return this.trackingClick?((this.targetElement!==this.getTargetElementFromEventTarget(a.target)||this.touchHasMoved(a))&&(this.trackingClick=!1,this.targetElement=null),!0):!0},FastClick.prototype.findControl=function(a){"use strict";return void 0!==a.control?a.control:a.htmlFor?document.getElementById(a.htmlFor):a.querySelector("button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea")},FastClick.prototype.onTouchEnd=function(a){"use strict";var b,c,d,e,f,g=this.targetElement;if(!this.trackingClick)return!0;if(a.timeStamp-this.lastClickTime<200)return this.cancelNextClick=!0,!0;if(this.cancelNextClick=!1,this.lastClickTime=a.timeStamp,c=this.trackingClickStart,this.trackingClick=!1,this.trackingClickStart=0,this.deviceIsIOSWithBadTarget&&(f=a.changedTouches[0],g=document.elementFromPoint(f.pageX-window.pageXOffset,f.pageY-window.pageYOffset)||g,g.fastClickScrollParent=this.targetElement.fastClickScrollParent),d=g.tagName.toLowerCase(),"label"===d){if(b=this.findControl(g)){if(this.focus(g),this.deviceIsAndroid)return!1;g=b}}else if(this.needsFocus(g))return a.timeStamp-c>100||this.deviceIsIOS&&window.top!==window&&"input"===d?(this.targetElement=null,!1):(this.focus(g),this.deviceIsIOS4&&"select"===d||(this.targetElement=null,a.preventDefault()),!1);return this.deviceIsIOS&&!this.deviceIsIOS4&&(e=g.fastClickScrollParent,e&&e.fastClickLastScrollTop!==e.scrollTop)?!0:(this.needsClick(g)||(a.preventDefault(),this.sendClick(g,a)),!1)},FastClick.prototype.onTouchCancel=function(){"use strict";this.trackingClick=!1,this.targetElement=null},FastClick.prototype.onMouse=function(a){"use strict";return this.targetElement?a.forwardedTouchEvent?!0:a.cancelable?!this.needsClick(this.targetElement)||this.cancelNextClick?(a.stopImmediatePropagation?a.stopImmediatePropagation():a.propagationStopped=!0,a.stopPropagation(),a.preventDefault(),!1):!0:!0:!0},FastClick.prototype.onClick=function(a){"use strict";var b;return this.trackingClick?(this.targetElement=null,this.trackingClick=!1,!0):"submit"===a.target.type&&0===a.detail?!0:(b=this.onMouse(a),b||(this.targetElement=null),b)},FastClick.prototype.destroy=function(){"use strict";var a=this.layer;this.deviceIsAndroid&&(a.removeEventListener("mouseover",this.onMouse,!0),a.removeEventListener("mousedown",this.onMouse,!0),a.removeEventListener("mouseup",this.onMouse,!0)),a.removeEventListener("click",this.onClick,!0),a.removeEventListener("touchstart",this.onTouchStart,!1),a.removeEventListener("touchmove",this.onTouchMove,!1),a.removeEventListener("touchend",this.onTouchEnd,!1),a.removeEventListener("touchcancel",this.onTouchCancel,!1)},FastClick.notNeeded=function(a){"use strict";var b,c;if("undefined"==typeof window.ontouchstart)return!0;if(c=+(/Chrome\/([0-9]+)/.exec(navigator.userAgent)||[,0])[1]){if(!FastClick.prototype.deviceIsAndroid)return!0;if(b=document.querySelector("meta[name=viewport]")){if(-1!==b.content.indexOf("user-scalable=no"))return!0;if(c>31&&window.innerWidth<=window.screen.width)return!0}}return"none"===a.style.msTouchAction?!0:!1},FastClick.attach=function(a){"use strict";return new FastClick(a)},"undefined"!=typeof define&&define.amd?define(function(){"use strict";return FastClick}):"undefined"!=typeof module&&module.exports?(module.exports=FastClick.attach,module.exports.FastClick=FastClick):window.FastClick=FastClick; 10 | -------------------------------------------------------------------------------- /static/js/vendor/jquery.cookie.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery Cookie Plugin v1.4.0 3 | * https://github.com/carhartl/jquery-cookie 4 | * 5 | * Copyright 2013 Klaus Hartl 6 | * Released under the MIT license 7 | */ 8 | !function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a(jQuery)}(function(a){function b(a){return h.raw?a:encodeURIComponent(a)}function c(a){return h.raw?a:decodeURIComponent(a)}function d(a){return b(h.json?JSON.stringify(a):String(a))}function e(a){0===a.indexOf('"')&&(a=a.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\"));try{a=decodeURIComponent(a.replace(g," "))}catch(b){return}try{return h.json?JSON.parse(a):a}catch(b){}}function f(b,c){var d=h.raw?b:e(b);return a.isFunction(c)?c(d):d}var g=/\+/g,h=a.cookie=function(e,g,i){if(void 0!==g&&!a.isFunction(g)){if(i=a.extend({},h.defaults,i),"number"==typeof i.expires){var j=i.expires,k=i.expires=new Date;k.setDate(k.getDate()+j)}return document.cookie=[b(e),"=",d(g),i.expires?"; expires="+i.expires.toUTCString():"",i.path?"; path="+i.path:"",i.domain?"; domain="+i.domain:"",i.secure?"; secure":""].join("")}for(var l=e?void 0:{},m=document.cookie?document.cookie.split("; "):[],n=0,o=m.length;o>n;n++){var p=m[n].split("="),q=c(p.shift()),r=p.join("=");if(e&&e===q){l=f(r,g);break}e||void 0===(r=f(r))||(l[q]=r)}return l};h.defaults={},a.removeCookie=function(b,c){return void 0!==a.cookie(b)?(a.cookie(b,"",a.extend({},c,{expires:-1})),!0):!1}}); 9 | -------------------------------------------------------------------------------- /static/js/vendor/modernizr.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Modernizr v2.7.1 3 | * www.modernizr.com 4 | * 5 | * Copyright (c) Faruk Ates, Paul Irish, Alex Sexton 6 | * Available under the BSD and MIT licenses: www.modernizr.com/license/ 7 | */ 8 | window.Modernizr=function(a,b,c){function d(a){t.cssText=a}function e(a,b){return d(x.join(a+";")+(b||""))}function f(a,b){return typeof a===b}function g(a,b){return!!~(""+a).indexOf(b)}function h(a,b){for(var d in a){var e=a[d];if(!g(e,"-")&&t[e]!==c)return"pfx"==b?e:!0}return!1}function i(a,b,d){for(var e in a){var g=b[a[e]];if(g!==c)return d===!1?a[e]:f(g,"function")?g.bind(d||b):g}return!1}function j(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+z.join(d+" ")+d).split(" ");return f(b,"string")||f(b,"undefined")?h(e,b):(e=(a+" "+A.join(d+" ")+d).split(" "),i(e,b,c))}function k(){o.input=function(c){for(var d=0,e=c.length;e>d;d++)E[c[d]]=!!(c[d]in u);return E.list&&(E.list=!(!b.createElement("datalist")||!a.HTMLDataListElement)),E}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" ")),o.inputtypes=function(a){for(var d,e,f,g=0,h=a.length;h>g;g++)u.setAttribute("type",e=a[g]),d="text"!==u.type,d&&(u.value=v,u.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(e)&&u.style.WebkitAppearance!==c?(q.appendChild(u),f=b.defaultView,d=f.getComputedStyle&&"textfield"!==f.getComputedStyle(u,null).WebkitAppearance&&0!==u.offsetHeight,q.removeChild(u)):/^(search|tel)$/.test(e)||(d=/^(url|email)$/.test(e)?u.checkValidity&&u.checkValidity()===!1:u.value!=v)),D[a[g]]=!!d;return D}("search tel url email datetime date month week time datetime-local number range color".split(" "))}var l,m,n="2.7.1",o={},p=!0,q=b.documentElement,r="modernizr",s=b.createElement(r),t=s.style,u=b.createElement("input"),v=":)",w={}.toString,x=" -webkit- -moz- -o- -ms- ".split(" "),y="Webkit Moz O ms",z=y.split(" "),A=y.toLowerCase().split(" "),B={svg:"http://www.w3.org/2000/svg"},C={},D={},E={},F=[],G=F.slice,H=function(a,c,d,e){var f,g,h,i,j=b.createElement("div"),k=b.body,l=k||b.createElement("body");if(parseInt(d,10))for(;d--;)h=b.createElement("div"),h.id=e?e[d]:r+(d+1),j.appendChild(h);return f=["­",'"].join(""),j.id=r,(k?j:l).innerHTML+=f,l.appendChild(j),k||(l.style.background="",l.style.overflow="hidden",i=q.style.overflow,q.style.overflow="hidden",q.appendChild(l)),g=c(j,a),k?j.parentNode.removeChild(j):(l.parentNode.removeChild(l),q.style.overflow=i),!!g},I=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return H("@media "+b+" { #"+r+" { position: absolute; } }",function(b){d="absolute"==(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle).position}),d},J=function(){function a(a,e){e=e||b.createElement(d[a]||"div"),a="on"+a;var g=a in e;return g||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(a,""),g=f(e[a],"function"),f(e[a],"undefined")||(e[a]=c),e.removeAttribute(a))),e=null,g}var d={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return a}(),K={}.hasOwnProperty;m=f(K,"undefined")||f(K.call,"undefined")?function(a,b){return b in a&&f(a.constructor.prototype[b],"undefined")}:function(a,b){return K.call(a,b)},Function.prototype.bind||(Function.prototype.bind=function(a){var b=this;if("function"!=typeof b)throw new TypeError;var c=G.call(arguments,1),d=function(){if(this instanceof d){var e=function(){};e.prototype=b.prototype;var f=new e,g=b.apply(f,c.concat(G.call(arguments)));return Object(g)===g?g:f}return b.apply(a,c.concat(G.call(arguments)))};return d}),C.flexbox=function(){return j("flexWrap")},C.flexboxlegacy=function(){return j("boxDirection")},C.canvas=function(){var a=b.createElement("canvas");return!(!a.getContext||!a.getContext("2d"))},C.canvastext=function(){return!(!o.canvas||!f(b.createElement("canvas").getContext("2d").fillText,"function"))},C.webgl=function(){return!!a.WebGLRenderingContext},C.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:H(["@media (",x.join("touch-enabled),("),r,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=9===a.offsetTop}),c},C.geolocation=function(){return"geolocation"in navigator},C.postmessage=function(){return!!a.postMessage},C.websqldatabase=function(){return!!a.openDatabase},C.indexedDB=function(){return!!j("indexedDB",a)},C.hashchange=function(){return J("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},C.history=function(){return!(!a.history||!history.pushState)},C.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},C.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},C.rgba=function(){return d("background-color:rgba(150,255,150,.5)"),g(t.backgroundColor,"rgba")},C.hsla=function(){return d("background-color:hsla(120,40%,100%,.5)"),g(t.backgroundColor,"rgba")||g(t.backgroundColor,"hsla")},C.multiplebgs=function(){return d("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(t.background)},C.backgroundsize=function(){return j("backgroundSize")},C.borderimage=function(){return j("borderImage")},C.borderradius=function(){return j("borderRadius")},C.boxshadow=function(){return j("boxShadow")},C.textshadow=function(){return""===b.createElement("div").style.textShadow},C.opacity=function(){return e("opacity:.55"),/^0.55$/.test(t.opacity)},C.cssanimations=function(){return j("animationName")},C.csscolumns=function(){return j("columnCount")},C.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return d((a+"-webkit- ".split(" ").join(b+a)+x.join(c+a)).slice(0,-a.length)),g(t.backgroundImage,"gradient")},C.cssreflections=function(){return j("boxReflect")},C.csstransforms=function(){return!!j("transform")},C.csstransforms3d=function(){var a=!!j("perspective");return a&&"webkitPerspective"in q.style&&H("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b){a=9===b.offsetLeft&&3===b.offsetHeight}),a},C.csstransitions=function(){return j("transition")},C.fontface=function(){var a;return H('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&0===g.indexOf(d.split(" ")[0])}),a},C.generatedcontent=function(){var a;return H(["#",r,"{font:0/0 a}#",r,':after{content:"',v,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},C.video=function(){var a=b.createElement("video"),c=!1;try{(c=!!a.canPlayType)&&(c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,""))}catch(d){}return c},C.audio=function(){var a=b.createElement("audio"),c=!1;try{(c=!!a.canPlayType)&&(c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,""))}catch(d){}return c},C.localstorage=function(){try{return localStorage.setItem(r,r),localStorage.removeItem(r),!0}catch(a){return!1}},C.sessionstorage=function(){try{return sessionStorage.setItem(r,r),sessionStorage.removeItem(r),!0}catch(a){return!1}},C.webworkers=function(){return!!a.Worker},C.applicationcache=function(){return!!a.applicationCache},C.svg=function(){return!!b.createElementNS&&!!b.createElementNS(B.svg,"svg").createSVGRect},C.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="",(a.firstChild&&a.firstChild.namespaceURI)==B.svg},C.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(w.call(b.createElementNS(B.svg,"animate")))},C.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(w.call(b.createElementNS(B.svg,"clipPath")))};for(var L in C)m(C,L)&&(l=L.toLowerCase(),o[l]=C[L](),F.push((o[l]?"":"no-")+l));return o.input||k(),o.addTest=function(a,b){if("object"==typeof a)for(var d in a)m(a,d)&&o.addTest(d,a[d]);else{if(a=a.toLowerCase(),o[a]!==c)return o;b="function"==typeof b?b():b,"undefined"!=typeof p&&p&&(q.className+=" "+(b?"":"no-")+a),o[a]=b}return o},d(""),s=u=null,function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=s.elements;return"string"==typeof a?a.split(" "):a}function e(a){var b=r[a[p]];return b||(b={},q++,a[p]=q,r[q]=b),b}function f(a,c,d){if(c||(c=b),k)return c.createElement(a);d||(d=e(c));var f;return f=d.cache[a]?d.cache[a].cloneNode():o.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!f.canHaveChildren||n.test(a)||f.tagUrn?f:d.frag.appendChild(f)}function g(a,c){if(a||(a=b),k)return a.createDocumentFragment();c=c||e(a);for(var f=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)f.createElement(h[g]);return f}function h(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return s.shivMethods?f(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(s,b.frag)}function i(a){a||(a=b);var d=e(a);return!s.shivCSS||j||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),k||h(a,d),a}var j,k,l="3.7.0",m=a.html5||{},n=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,o=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,p="_html5shiv",q=0,r={};!function(){try{var a=b.createElement("a");a.innerHTML="",j="hidden"in a,k=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){j=!0,k=!0}}();var s={elements:m.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:l,shivCSS:m.shivCSS!==!1,supportsUnknownElements:k,shivMethods:m.shivMethods!==!1,type:"default",shivDocument:i,createElement:f,createDocumentFragment:g};a.html5=s,i(b)}(this,b),o._version=n,o._prefixes=x,o._domPrefixes=A,o._cssomPrefixes=z,o.mq=I,o.hasEvent=J,o.testProp=function(a){return h([a])},o.testAllProps=j,o.testStyles=H,o.prefixed=function(a,b,c){return b?j(a,b,c):j(a,"pfx")},q.className=q.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(p?" js "+F.join(" "):""),o}(this,this.document); 9 | -------------------------------------------------------------------------------- /static/js/vendor/placeholder.js: -------------------------------------------------------------------------------- 1 | /*! http://mths.be/placeholder v2.0.7 by @mathias */ 2 | !function(a,b,c){function d(a){var b={},d=/^jQuery\d+$/;return c.each(a.attributes,function(a,c){c.specified&&!d.test(c.name)&&(b[c.name]=c.value)}),b}function e(a,d){var e=this,f=c(e);if(e.value==f.attr("placeholder")&&f.hasClass("placeholder"))if(f.data("placeholder-password")){if(f=f.hide().next().show().attr("id",f.removeAttr("id").data("placeholder-id")),a===!0)return f[0].value=d;f.focus()}else e.value="",f.removeClass("placeholder"),e==b.activeElement&&e.select()}function f(){var a,b=this,f=c(b),g=this.id;if(""==b.value){if("password"==b.type){if(!f.data("placeholder-textinput")){try{a=f.clone().attr({type:"text"})}catch(h){a=c("").attr(c.extend(d(this),{type:"text"}))}a.removeAttr("name").data({"placeholder-password":!0,"placeholder-id":g}).bind("focus.placeholder",e),f.data({"placeholder-textinput":a,"placeholder-id":g}).before(a)}f=f.removeAttr("id").hide().prev().attr("id",g).show()}f.addClass("placeholder"),f[0].value=f.attr("placeholder")}else f.removeClass("placeholder")}var g,h,i="placeholder"in b.createElement("input"),j="placeholder"in b.createElement("textarea"),k=c.fn,l=c.valHooks;i&&j?(h=k.placeholder=function(){return this},h.input=h.textarea=!0):(h=k.placeholder=function(){var a=this;return a.filter((i?"textarea":":input")+"[placeholder]").not(".placeholder").bind({"focus.placeholder":e,"blur.placeholder":f}).data("placeholder-enabled",!0).trigger("blur.placeholder"),a},h.input=i,h.textarea=j,g={get:function(a){var b=c(a);return b.data("placeholder-enabled")&&b.hasClass("placeholder")?"":a.value},set:function(a,d){var g=c(a);return g.data("placeholder-enabled")?(""==d?(a.value=d,a!=b.activeElement&&f.call(a)):g.hasClass("placeholder")?e.call(a,!0,d)||(a.value=d):a.value=d,g):a.value=d}},i||(l.input=g),j||(l.textarea=g),c(function(){c(b).delegate("form","submit.placeholder",function(){var a=c(".placeholder",this).each(e);setTimeout(function(){a.each(f)},10)})}),c(a).bind("beforeunload.placeholder",function(){c(".placeholder").each(function(){this.value=""})}))}(this,document,jQuery); 3 | -------------------------------------------------------------------------------- /templates/main.html: -------------------------------------------------------------------------------- 1 | {% load staticfiles %} 2 | 3 | 4 | 5 | Django 6 | 7 | 8 | 9 |
    10 |
    11 | 18 |
    19 |
    20 |

    Мой блог

    21 |
    22 | {% block article %}{% endblock %} 23 | {% block login %}{% endblock %} 24 |
    25 | 26 | -------------------------------------------------------------------------------- /templates/myview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | This is {{ name }} view 5 | 6 | --------------------------------------------------------------------------------