Created
April 9, 2013 17:41
-
-
Save Ollo/5347746 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Avoid `console` errors in browsers that lack a console. | |
if (!(window.console && console.log)) { | |
(function() { | |
var noop = function() {}; | |
var methods = ['assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error', 'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log', 'markTimeline', 'profile', 'profileEnd', 'markTimeline', 'table', 'time', 'timeEnd', 'timeStamp', 'trace', 'warn']; | |
var length = methods.length; | |
var console = window.console = {}; | |
while (length--) { | |
console[methods[length]] = noop; | |
} | |
}()); | |
} | |
/*! | |
* jQuery Cookie Plugin v1.3.1 | |
* https://github.com/carhartl/jquery-cookie | |
* | |
* Copyright 2013 Klaus Hartl | |
* Released under the MIT license | |
*/ | |
(function (factory) { | |
if (typeof define === 'function' && define.amd) { | |
// AMD. Register as anonymous module. | |
define(['jquery'], factory); | |
} else { | |
// Browser globals. | |
factory(jQuery); | |
} | |
}(function ($) { | |
var pluses = /\+/g; | |
function raw(s) { | |
return s; | |
} | |
function decoded(s) { | |
return decodeURIComponent(s.replace(pluses, ' ')); | |
} | |
function converted(s) { | |
if (s.indexOf('"') === 0) { | |
// This is a quoted cookie as according to RFC2068, unescape | |
s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\'); | |
} | |
try { | |
return config.json ? JSON.parse(s) : s; | |
} catch(er) {} | |
} | |
var config = $.cookie = function (key, value, options) { | |
// write | |
if (value !== undefined) { | |
options = $.extend({}, config.defaults, options); | |
if (typeof options.expires === 'number') { | |
var days = options.expires, t = options.expires = new Date(); | |
t.setDate(t.getDate() + days); | |
} | |
value = config.json ? JSON.stringify(value) : String(value); | |
return (document.cookie = [ | |
config.raw ? key : encodeURIComponent(key), | |
'=', | |
config.raw ? value : encodeURIComponent(value), | |
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE | |
options.path ? '; path=' + options.path : '', | |
options.domain ? '; domain=' + options.domain : '', | |
options.secure ? '; secure' : '' | |
].join('')); | |
} | |
// read | |
var decode = config.raw ? raw : decoded; | |
var cookies = document.cookie.split('; '); | |
var result = key ? undefined : {}; | |
for (var i = 0, l = cookies.length; i < l; i++) { | |
var parts = cookies[i].split('='); | |
var name = decode(parts.shift()); | |
var cookie = decode(parts.join('=')); | |
if (key && key === name) { | |
result = converted(cookie); | |
break; | |
} | |
if (!key) { | |
result[name] = converted(cookie); | |
} | |
} | |
return result; | |
}; | |
config.defaults = {}; | |
$.removeCookie = function (key, options) { | |
if ($.cookie(key) !== undefined) { | |
$.cookie(key, '', $.extend(options, { expires: -1 })); | |
return true; | |
} | |
return false; | |
}; | |
})); | |
/*! jQuery Mustache - v0.2.7 - 2013-01-30 | |
* https://github.com/jonnyreeves/jquery-Mustache | |
* Copyright (c) 2013 Jonny Reeves; Licensed MIT */ | |
/*global jQuery, window */ | |
(function ($, window) { | |
'use strict'; | |
var templateMap = {}, | |
instance = null, | |
options = { | |
// Should an error be thrown if an attempt is made to render a non-existent template. If false, the | |
// operation will fail silently. | |
warnOnMissingTemplates: false, | |
// Should an error be thrown if an attempt is made to overwrite a template which has already been added. | |
// If true the original template will be overwritten with the new value. | |
allowOverwrite: true, | |
// The 'type' attribute which you use to denoate a Mustache Template in the DOM; eg: | |
// `<script type="text/html" id="my-template"></script>` | |
domTemplateType: 'text/html', | |
// Specifies the `dataType` attribute used when external templates are loaded. | |
externalTemplateDataType: 'text' | |
}; | |
function getMustache() { | |
// Lazily retrieve Mustache from the window global if it hasn't been defined by | |
// the User. | |
if (instance === null) { | |
instance = window.Mustache; | |
if (instance === void 0) { | |
$.error("Failed to locate Mustache instance, are you sure it has been loaded?"); | |
} | |
} | |
return instance; | |
} | |
/** | |
* Returns true if the supplied templateName has been added. | |
*/ | |
function has(templateName) { | |
return templateMap[templateName] !== void 0; | |
} | |
/** | |
* Registers a template so that it can be used by $.Mustache. | |
* | |
* @param templateName A name which uniquely identifies this template. | |
* @param templateHtml The HTML which makes us the template; this will be rendered by Mustache when render() | |
* is invoked. | |
* @throws If options.allowOverwrite is false and the templateName has already been registered. | |
*/ | |
function add(templateName, templateHtml) { | |
if (!options.allowOverwrite && has(templateName)) { | |
$.error('TemplateName: ' + templateName + ' is already mapped.'); | |
return; | |
} | |
templateMap[templateName] = $.trim(templateHtml); | |
} | |
/** | |
* Adds one or more tempaltes from the DOM using either the supplied templateElementIds or by retrieving all script | |
* tags of the 'domTemplateType'. Templates added in this fashion will be registered with their elementId value. | |
* | |
* @param [...templateElementIds] List of element id's present on the DOM which contain templates to be added; | |
* if none are supplied all script tags that are of the same type as the | |
* `options.domTemplateType` configuration value will be added. | |
*/ | |
function addFromDom() { | |
var templateElementIds; | |
// If no args are supplied, all script blocks will be read from the document. | |
if (arguments.length === 0) { | |
templateElementIds = $('script[type="' + options.domTemplateType + '"]').map(function () { | |
return this.id; | |
}); | |
} | |
else { | |
templateElementIds = $.makeArray(arguments); | |
} | |
$.each(templateElementIds, function() { | |
var templateElement = document.getElementById(this); | |
if (templateElement === null) { | |
$.error('No such elementId: #' + this); | |
} | |
else { | |
add(this, $(templateElement).html()); | |
} | |
}); | |
} | |
/** | |
* Removes a template, the contents of the removed Template will be returned. | |
* | |
* @param templateName The name of the previously registered Mustache template that you wish to remove. | |
* @returns String which represents the raw content of the template. | |
*/ | |
function remove(templateName) { | |
var result = templateMap[templateName]; | |
delete templateMap[templateName]; | |
return result; | |
} | |
/** | |
* Removes all templates and tells Mustache to flush its cache. | |
*/ | |
function clear() { | |
templateMap = {}; | |
getMustache().clearCache(); | |
} | |
/** | |
* Renders a previously added Mustache template using the supplied templateData object. Note if the supplied | |
* templateName doesn't exist an empty String will be returned. | |
*/ | |
function render(templateName, templateData) { | |
if (!has(templateName)) { | |
if (options.warnOnMissingTemplates) { | |
$.error('No template registered for: ' + templateName); | |
} | |
return ''; | |
} | |
return getMustache().to_html(templateMap[templateName], templateData, templateMap); | |
} | |
/** | |
* Loads the external Mustache templates located at the supplied URL and registers them for later use. This method | |
* returns a jQuery Promise and also support an `onComplete` callback. | |
* | |
* @param url URL of the external Mustache template file to load. | |
* @param onComplete Optional callback function which will be invoked when the templates from the supplied URL | |
* have been loaded and are ready for use. | |
* @returns jQuery deferred promise which will complete when the templates have been loaded and are | |
* ready for use. | |
*/ | |
function load(url, onComplete) { | |
return $.ajax({ | |
url: url, | |
dataType: options.externalTemplateDataType | |
}).done(function (templates) { | |
$(templates).filter('script').each(function (i, el) { | |
add(el.id, $(el).html()); | |
}); | |
if ($.isFunction(onComplete)) { | |
onComplete(); | |
} | |
}); | |
} | |
/** | |
* Returns an Array of templateNames which have been registered and can be retrieved via | |
* $.Mustache.render() or $(element).mustache(). | |
*/ | |
function templates() { | |
return $.map(templateMap, function (value, key) { | |
return key; | |
}); | |
} | |
// Expose the public methods on jQuery.Mustache | |
$.Mustache = { | |
options: options, | |
load: load, | |
add: add, | |
addFromDom: addFromDom, | |
remove: remove, | |
clear: clear, | |
render: render, | |
templates: templates, | |
instance: instance | |
}; | |
/** | |
* Renders one or more viewModels into the current jQuery element. | |
* | |
* @param templateName The name of the Mustache template you wish to render, Note that the | |
* template must have been previously loaded and / or added. | |
* @param templateData One or more JavaScript objects which will be used to render the Mustache | |
* template. | |
* @param options.method jQuery method to use when rendering, defaults to 'append'. | |
*/ | |
$.fn.mustache = function (templateName, templateData, options) { | |
var settings = $.extend({ | |
method: 'append' | |
}, options); | |
var renderTemplate = function (obj, viewModel) { | |
$(obj)[settings.method](render(templateName, viewModel)); | |
}; | |
return this.each(function () { | |
var element = this; | |
// Render a collection of viewModels. | |
if ($.isArray(templateData)) { | |
$.each(templateData, function () { | |
renderTemplate(element, this); | |
}); | |
} | |
// Render a single viewModel. | |
else { | |
renderTemplate(element, templateData); | |
} | |
}); | |
}; | |
}(jQuery, window)); | |
/*! | |
* mustache.js - Logic-less {{mustache}} templates with JavaScript | |
* http://github.com/janl/mustache.js | |
*/ | |
/*global define: false*/ | |
(function (root, factory) { | |
if (typeof exports === "object" && exports) { | |
module.exports = factory; // CommonJS | |
} else if (typeof define === "function" && define.amd) { | |
define(factory); // AMD | |
} else { | |
root.Mustache = factory; // <script> | |
} | |
}(this, (function () { | |
var exports = {}; | |
exports.name = "mustache.js"; | |
exports.version = "0.7.2"; | |
exports.tags = ["{{", "}}"]; | |
exports.Scanner = Scanner; | |
exports.Context = Context; | |
exports.Writer = Writer; | |
var whiteRe = /\s*/; | |
var spaceRe = /\s+/; | |
var nonSpaceRe = /\S/; | |
var eqRe = /\s*=/; | |
var curlyRe = /\s*\}/; | |
var tagRe = /#|\^|\/|>|\{|&|=|!/; | |
var _test = RegExp.prototype.test; | |
var _toString = Object.prototype.toString; | |
// Workaround for https://issues.apache.org/jira/browse/COUCHDB-577 | |
// See https://github.com/janl/mustache.js/issues/189 | |
function testRe(re, string) { | |
return _test.call(re, string); | |
} | |
function isWhitespace(string) { | |
return !testRe(nonSpaceRe, string); | |
} | |
var isArray = Array.isArray || function (obj) { | |
return _toString.call(obj) === '[object Array]'; | |
}; | |
function escapeRe(string) { | |
return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"); | |
} | |
var entityMap = { | |
"&": "&", | |
"<": "<", | |
">": ">", | |
'"': '"', | |
"'": ''', | |
"/": '/' | |
}; | |
function escapeHtml(string) { | |
return String(string).replace(/[&<>"'\/]/g, function (s) { | |
return entityMap[s]; | |
}); | |
} | |
// Export the escaping function so that the user may override it. | |
// See https://github.com/janl/mustache.js/issues/244 | |
exports.escape = escapeHtml; | |
function Scanner(string) { | |
this.string = string; | |
this.tail = string; | |
this.pos = 0; | |
} | |
/** | |
* Returns `true` if the tail is empty (end of string). | |
*/ | |
Scanner.prototype.eos = function () { | |
return this.tail === ""; | |
}; | |
/** | |
* Tries to match the given regular expression at the current position. | |
* Returns the matched text if it can match, the empty string otherwise. | |
*/ | |
Scanner.prototype.scan = function (re) { | |
var match = this.tail.match(re); | |
if (match && match.index === 0) { | |
this.tail = this.tail.substring(match[0].length); | |
this.pos += match[0].length; | |
return match[0]; | |
} | |
return ""; | |
}; | |
/** | |
* Skips all text until the given regular expression can be matched. Returns | |
* the skipped string, which is the entire tail if no match can be made. | |
*/ | |
Scanner.prototype.scanUntil = function (re) { | |
var match, pos = this.tail.search(re); | |
switch (pos) { | |
case -1: | |
match = this.tail; | |
this.pos += this.tail.length; | |
this.tail = ""; | |
break; | |
case 0: | |
match = ""; | |
break; | |
default: | |
match = this.tail.substring(0, pos); | |
this.tail = this.tail.substring(pos); | |
this.pos += pos; | |
} | |
return match; | |
}; | |
function Context(view, parent) { | |
this.view = view; | |
this.parent = parent; | |
this._cache = {}; | |
} | |
Context.make = function (view) { | |
return (view instanceof Context) ? view : new Context(view); | |
}; | |
Context.prototype.push = function (view) { | |
return new Context(view, this); | |
}; | |
Context.prototype.lookup = function (name) { | |
var value = this._cache[name]; | |
if (!value) { | |
if (name == '.') { | |
value = this.view; | |
} else { | |
var context = this; | |
while (context) { | |
if (name.indexOf('.') > 0) { | |
value = context.view; | |
var names = name.split('.'), i = 0; | |
while (value && i < names.length) { | |
value = value[names[i++]]; | |
} | |
} else { | |
value = context.view[name]; | |
} | |
if (value != null) break; | |
context = context.parent; | |
} | |
} | |
this._cache[name] = value; | |
} | |
if (typeof value === 'function') value = value.call(this.view); | |
return value; | |
}; | |
function Writer() { | |
this.clearCache(); | |
} | |
Writer.prototype.clearCache = function () { | |
this._cache = {}; | |
this._partialCache = {}; | |
}; | |
Writer.prototype.compile = function (template, tags) { | |
var fn = this._cache[template]; | |
if (!fn) { | |
var tokens = exports.parse(template, tags); | |
fn = this._cache[template] = this.compileTokens(tokens, template); | |
} | |
return fn; | |
}; | |
Writer.prototype.compilePartial = function (name, template, tags) { | |
var fn = this.compile(template, tags); | |
this._partialCache[name] = fn; | |
return fn; | |
}; | |
Writer.prototype.getPartial = function (name) { | |
if (!(name in this._partialCache) && this._loadPartial) { | |
this.compilePartial(name, this._loadPartial(name)); | |
} | |
return this._partialCache[name]; | |
}; | |
Writer.prototype.compileTokens = function (tokens, template) { | |
var self = this; | |
return function (view, partials) { | |
if (partials) { | |
if (typeof partials === 'function') { | |
self._loadPartial = partials; | |
} else { | |
for (var name in partials) { | |
self.compilePartial(name, partials[name]); | |
} | |
} | |
} | |
return renderTokens(tokens, self, Context.make(view), template); | |
}; | |
}; | |
Writer.prototype.render = function (template, view, partials) { | |
return this.compile(template)(view, partials); | |
}; | |
/** | |
* Low-level function that renders the given `tokens` using the given `writer` | |
* and `context`. The `template` string is only needed for templates that use | |
* higher-order sections to extract the portion of the original template that | |
* was contained in that section. | |
*/ | |
function renderTokens(tokens, writer, context, template) { | |
var buffer = ''; | |
var token, tokenValue, value; | |
for (var i = 0, len = tokens.length; i < len; ++i) { | |
token = tokens[i]; | |
tokenValue = token[1]; | |
switch (token[0]) { | |
case '#': | |
value = context.lookup(tokenValue); | |
if (typeof value === 'object') { | |
if (isArray(value)) { | |
for (var j = 0, jlen = value.length; j < jlen; ++j) { | |
buffer += renderTokens(token[4], writer, context.push(value[j]), template); | |
} | |
} else if (value) { | |
buffer += renderTokens(token[4], writer, context.push(value), template); | |
} | |
} else if (typeof value === 'function') { | |
var text = template == null ? null : template.slice(token[3], token[5]); | |
value = value.call(context.view, text, function (template) { | |
return writer.render(template, context); | |
}); | |
if (value != null) buffer += value; | |
} else if (value) { | |
buffer += renderTokens(token[4], writer, context, template); | |
} | |
break; | |
case '^': | |
value = context.lookup(tokenValue); | |
// Use JavaScript's definition of falsy. Include empty arrays. | |
// See https://github.com/janl/mustache.js/issues/186 | |
if (!value || (isArray(value) && value.length === 0)) { | |
buffer += renderTokens(token[4], writer, context, template); | |
} | |
break; | |
case '>': | |
value = writer.getPartial(tokenValue); | |
if (typeof value === 'function') buffer += value(context); | |
break; | |
case '&': | |
value = context.lookup(tokenValue); | |
if (value != null) buffer += value; | |
break; | |
case 'name': | |
value = context.lookup(tokenValue); | |
if (value != null) buffer += exports.escape(value); | |
break; | |
case 'text': | |
buffer += tokenValue; | |
break; | |
} | |
} | |
return buffer; | |
} | |
/** | |
* Forms the given array of `tokens` into a nested tree structure where | |
* tokens that represent a section have two additional items: 1) an array of | |
* all tokens that appear in that section and 2) the index in the original | |
* template that represents the end of that section. | |
*/ | |
function nestTokens(tokens) { | |
var tree = []; | |
var collector = tree; | |
var sections = []; | |
var token; | |
for (var i = 0, len = tokens.length; i < len; ++i) { | |
token = tokens[i]; | |
switch (token[0]) { | |
case '#': | |
case '^': | |
sections.push(token); | |
collector.push(token); | |
collector = token[4] = []; | |
break; | |
case '/': | |
var section = sections.pop(); | |
section[5] = token[2]; | |
collector = sections.length > 0 ? sections[sections.length - 1][4] : tree; | |
break; | |
default: | |
collector.push(token); | |
} | |
} | |
return tree; | |
} | |
/** | |
* Combines the values of consecutive text tokens in the given `tokens` array | |
* to a single token. | |
*/ | |
function squashTokens(tokens) { | |
var squashedTokens = []; | |
var token, lastToken; | |
for (var i = 0, len = tokens.length; i < len; ++i) { | |
token = tokens[i]; | |
if (token) { | |
if (token[0] === 'text' && lastToken && lastToken[0] === 'text') { | |
lastToken[1] += token[1]; | |
lastToken[3] = token[3]; | |
} else { | |
lastToken = token; | |
squashedTokens.push(token); | |
} | |
} | |
} | |
return squashedTokens; | |
} | |
function escapeTags(tags) { | |
return [ | |
new RegExp(escapeRe(tags[0]) + "\\s*"), | |
new RegExp("\\s*" + escapeRe(tags[1])) | |
]; | |
} | |
/** | |
* Breaks up the given `template` string into a tree of token objects. If | |
* `tags` is given here it must be an array with two string values: the | |
* opening and closing tags used in the template (e.g. ["<%", "%>"]). Of | |
* course, the default is to use mustaches (i.e. Mustache.tags). | |
*/ | |
exports.parse = function (template, tags) { | |
template = template || ''; | |
tags = tags || exports.tags; | |
if (typeof tags === 'string') tags = tags.split(spaceRe); | |
if (tags.length !== 2) throw new Error('Invalid tags: ' + tags.join(', ')); | |
var tagRes = escapeTags(tags); | |
var scanner = new Scanner(template); | |
var sections = []; // Stack to hold section tokens | |
var tokens = []; // Buffer to hold the tokens | |
var spaces = []; // Indices of whitespace tokens on the current line | |
var hasTag = false; // Is there a {{tag}} on the current line? | |
var nonSpace = false; // Is there a non-space char on the current line? | |
// Strips all whitespace tokens array for the current line | |
// if there was a {{#tag}} on it and otherwise only space. | |
function stripSpace() { | |
if (hasTag && !nonSpace) { | |
while (spaces.length) { | |
delete tokens[spaces.pop()]; | |
} | |
} else { | |
spaces = []; | |
} | |
hasTag = false; | |
nonSpace = false; | |
} | |
var start, type, value, chr, token; | |
while (!scanner.eos()) { | |
start = scanner.pos; | |
// Match any text between tags. | |
value = scanner.scanUntil(tagRes[0]); | |
if (value) { | |
for (var i = 0, len = value.length; i < len; ++i) { | |
chr = value.charAt(i); | |
if (isWhitespace(chr)) { | |
spaces.push(tokens.length); | |
} else { | |
nonSpace = true; | |
} | |
tokens.push(['text', chr, start, start + 1]); | |
start += 1; | |
// Check for whitespace on the current line. | |
if (chr == '\n') stripSpace(); | |
} | |
} | |
// Match the opening tag. | |
if (!scanner.scan(tagRes[0])) break; | |
hasTag = true; | |
// Get the tag type. | |
type = scanner.scan(tagRe) || 'name'; | |
scanner.scan(whiteRe); | |
// Get the tag value. | |
if (type === '=') { | |
value = scanner.scanUntil(eqRe); | |
scanner.scan(eqRe); | |
scanner.scanUntil(tagRes[1]); | |
} else if (type === '{') { | |
value = scanner.scanUntil(new RegExp('\\s*' + escapeRe('}' + tags[1]))); | |
scanner.scan(curlyRe); | |
scanner.scanUntil(tagRes[1]); | |
type = '&'; | |
} else { | |
value = scanner.scanUntil(tagRes[1]); | |
} | |
// Match the closing tag. | |
if (!scanner.scan(tagRes[1])) throw new Error('Unclosed tag at ' + scanner.pos); | |
token = [type, value, start, scanner.pos]; | |
tokens.push(token); | |
if (type === '#' || type === '^') { | |
sections.push(token); | |
} else if (type === '/') { | |
// Check section nesting. | |
if (sections.length === 0) throw new Error('Unopened section "' + value + '" at ' + start); | |
var openSection = sections.pop(); | |
if (openSection[1] !== value) throw new Error('Unclosed section "' + openSection[1] + '" at ' + start); | |
} else if (type === 'name' || type === '{' || type === '&') { | |
nonSpace = true; | |
} else if (type === '=') { | |
// Set the tags for the next time around. | |
tags = value.split(spaceRe); | |
if (tags.length !== 2) throw new Error('Invalid tags at ' + start + ': ' + tags.join(', ')); | |
tagRes = escapeTags(tags); | |
} | |
} | |
// Make sure there are no open sections when we're done. | |
var openSection = sections.pop(); | |
if (openSection) throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos); | |
tokens = squashTokens(tokens); | |
return nestTokens(tokens); | |
}; | |
// All Mustache.* functions use this writer. | |
var _writer = new Writer(); | |
/** | |
* Clears all cached templates and partials in the default writer. | |
*/ | |
exports.clearCache = function () { | |
return _writer.clearCache(); | |
}; | |
/** | |
* Compiles the given `template` to a reusable function using the default | |
* writer. | |
*/ | |
exports.compile = function (template, tags) { | |
return _writer.compile(template, tags); | |
}; | |
/** | |
* Compiles the partial with the given `name` and `template` to a reusable | |
* function using the default writer. | |
*/ | |
exports.compilePartial = function (name, template, tags) { | |
return _writer.compilePartial(name, template, tags); | |
}; | |
/** | |
* Compiles the given array of tokens (the output of a parse) to a reusable | |
* function using the default writer. | |
*/ | |
exports.compileTokens = function (tokens, template) { | |
return _writer.compileTokens(tokens, template); | |
}; | |
/** | |
* Renders the `template` with the given `view` and `partials` using the | |
* default writer. | |
*/ | |
exports.render = function (template, view, partials) { | |
return _writer.render(template, view, partials); | |
}; | |
// This is here for backwards compatibility with 0.4.x. | |
exports.to_html = function (template, view, partials, send) { | |
var result = exports.render(template, view, partials); | |
if (typeof send === "function") { | |
send(result); | |
} else { | |
return result; | |
} | |
}; | |
return exports; | |
}()))); | |
/*! jQuery Validation Plugin - v1.11.0 - 2/4/2013 | |
* https://github.com/jzaefferer/jquery-validation | |
* Copyright (c) 2013 Jörn Zaefferer; Licensed MIT */ | |
(function(e){e.extend(e.fn,{validate:function(t){if(!this.length){t&&t.debug&&window.console&&console.warn("Nothing selected, can't validate, returning nothing.");return}var n=e.data(this[0],"validator");return n?n:(this.attr("novalidate","novalidate"),n=new e.validator(t,this[0]),e.data(this[0],"validator",n),n.settings.onsubmit&&(this.validateDelegate(":submit","click",function(t){n.settings.submitHandler&&(n.submitButton=t.target),e(t.target).hasClass("cancel")&&(n.cancelSubmit=!0)}),this.submit(function(t){function r(){var r;return n.settings.submitHandler?(n.submitButton&&(r=e("<input type='hidden'/>").attr("name",n.submitButton.name).val(n.submitButton.value).appendTo(n.currentForm)),n.settings.submitHandler.call(n,n.currentForm,t),n.submitButton&&r.remove(),!1):!0}return n.settings.debug&&t.preventDefault(),n.cancelSubmit?(n.cancelSubmit=!1,r()):n.form()?n.pendingRequest?(n.formSubmitted=!0,!1):r():(n.focusInvalid(),!1)})),n)},valid:function(){if(e(this[0]).is("form"))return this.validate().form();var t=!0,n=e(this[0].form).validate();return this.each(function(){t&=n.element(this)}),t},removeAttrs:function(t){var n={},r=this;return e.each(t.split(/\s/),function(e,t){n[t]=r.attr(t),r.removeAttr(t)}),n},rules:function(t,n){var r=this[0];if(t){var i=e.data(r.form,"validator").settings,s=i.rules,o=e.validator.staticRules(r);switch(t){case"add":e.extend(o,e.validator.normalizeRule(n)),s[r.name]=o,n.messages&&(i.messages[r.name]=e.extend(i.messages[r.name],n.messages));break;case"remove":if(!n)return delete s[r.name],o;var u={};return e.each(n.split(/\s/),function(e,t){u[t]=o[t],delete o[t]}),u}}var a=e.validator.normalizeRules(e.extend({},e.validator.classRules(r),e.validator.attributeRules(r),e.validator.dataRules(r),e.validator.staticRules(r)),r);if(a.required){var f=a.required;delete a.required,a=e.extend({required:f},a)}return a}}),e.extend(e.expr[":"],{blank:function(t){return!e.trim(""+t.value)},filled:function(t){return!!e.trim(""+t.value)},unchecked:function(e){return!e.checked}}),e.validator=function(t,n){this.settings=e.extend(!0,{},e.validator.defaults,t),this.currentForm=n,this.init()},e.validator.format=function(t,n){return arguments.length===1?function(){var n=e.makeArray(arguments);return n.unshift(t),e.validator.format.apply(this,n)}:(arguments.length>2&&n.constructor!==Array&&(n=e.makeArray(arguments).slice(1)),n.constructor!==Array&&(n=[n]),e.each(n,function(e,n){t=t.replace(new RegExp("\\{"+e+"\\}","g"),function(){return n})}),t)},e.extend(e.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",validClass:"valid",errorElement:"label",focusInvalid:!0,errorContainer:e([]),errorLabelContainer:e([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(e,t){this.lastActive=e,this.settings.focusCleanup&&!this.blockFocusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,e,this.settings.errorClass,this.settings.validClass),this.addWrapper(this.errorsFor(e)).hide())},onfocusout:function(e,t){!this.checkable(e)&&(e.name in this.submitted||!this.optional(e))&&this.element(e)},onkeyup:function(e,t){if(t.which===9&&this.elementValue(e)==="")return;(e.name in this.submitted||e===this.lastElement)&&this.element(e)},onclick:function(e,t){e.name in this.submitted?this.element(e):e.parentNode.name in this.submitted&&this.element(e.parentNode)},highlight:function(t,n,r){t.type==="radio"?this.findByName(t.name).addClass(n).removeClass(r):e(t).addClass(n).removeClass(r)},unhighlight:function(t,n,r){t.type==="radio"?this.findByName(t.name).removeClass(n).addClass(r):e(t).removeClass(n).addClass(r)}},setDefaults:function(t){e.extend(e.validator.defaults,t)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",creditcard:"Please enter a valid credit card number.",equalTo:"Please enter the same value again.",maxlength:e.validator.format("Please enter no more than {0} characters."),minlength:e.validator.format("Please enter at least {0} characters."),rangelength:e.validator.format("Please enter a value between {0} and {1} characters long."),range:e.validator.format("Please enter a value between {0} and {1}."),max:e.validator.format("Please enter a value less than or equal to {0}."),min:e.validator.format("Please enter a value greater than or equal to {0}.")},autoCreateRanges:!1,prototype:{init:function(){function r(t){var n=e.data(this[0].form,"validator"),r="on"+t.type.replace(/^validate/,"");n.settings[r]&&n.settings[r].call(n,this[0],t)}this.labelContainer=e(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||e(this.currentForm),this.containers=e(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var t=this.groups={};e.each(this.settings.groups,function(n,r){typeof r=="string"&&(r=r.split(/\s/)),e.each(r,function(e,r){t[r]=n})});var n=this.settings.rules;e.each(n,function(t,r){n[t]=e.validator.normalizeRule(r)}),e(this.currentForm).validateDelegate(":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'] ,[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'] ","focusin focusout keyup",r).validateDelegate("[type='radio'], [type='checkbox'], select, option","click",r),this.settings.invalidHandler&&e(this.currentForm).bind("invalid-form.validate",this.settings.invalidHandler)},form:function(){return this.checkForm(),e.extend(this.submitted,this.errorMap),this.invalid=e.extend({},this.errorMap),this.valid()||e(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var e=0,t=this.currentElements=this.elements();t[e];e++)this.check(t[e]);return this.valid()},element:function(t){t=this.validationTargetFor(this.clean(t)),this.lastElement=t,this.prepareElement(t),this.currentElements=e(t);var n=this.check(t)!==!1;return n?delete this.invalid[t.name]:this.invalid[t.name]=!0,this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),n},showErrors:function(t){if(t){e.extend(this.errorMap,t),this.errorList=[];for(var n in t)this.errorList.push({message:t[n],element:this.findByName(n)[0]});this.successList=e.grep(this.successList,function(e){return!(e.name in t)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){e.fn.resetForm&&e(this.currentForm).resetForm(),this.submitted={},this.lastElement=null,this.prepareForm(),this.hideErrors(),this.elements().removeClass(this.settings.errorClass).removeData("previousValue")},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(e){var t=0;for(var n in e)t++;return t},hideErrors:function(){this.addWrapper(this.toHide).hide()},valid:function(){return this.size()===0},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{e(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin")}catch(t){}},findLastActive:function(){var t=this.lastActive;return t&&e.grep(this.errorList,function(e){return e.element.name===t.name}).length===1&&t},elements:function(){var t=this,n={};return e(this.currentForm).find("input, select, textarea").not(":submit, :reset, :image, [disabled]").not(this.settings.ignore).filter(function(){return!this.name&&t.settings.debug&&window.console&&console.error("%o has no name assigned",this),this.name in n||!t.objectLength(e(this).rules())?!1:(n[this.name]=!0,!0)})},clean:function(t){return e(t)[0]},errors:function(){var t=this.settings.errorClass.replace(" ",".");return e(this.settings.errorElement+"."+t,this.errorContext)},reset:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=e([]),this.toHide=e([]),this.currentElements=e([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(e){this.reset(),this.toHide=this.errorsFor(e)},elementValue:function(t){var n=e(t).attr("type"),r=e(t).val();return n==="radio"||n==="checkbox"?e("input[name='"+e(t).attr("name")+"']:checked").val():typeof r=="string"?r.replace(/\r/g,""):r},check:function(t){t=this.validationTargetFor(this.clean(t));var n=e(t).rules(),r=!1,i=this.elementValue(t),s;for(var o in n){var u={method:o,parameters:n[o]};try{s=e.validator.methods[o].call(this,i,t,u.parameters);if(s==="dependency-mismatch"){r=!0;continue}r=!1;if(s==="pending"){this.toHide=this.toHide.not(this.errorsFor(t));return}if(!s)return this.formatAndAdd(t,u),!1}catch(a){throw this.settings.debug&&window.console&&console.log("Exception occured when checking element "+t.id+", check the '"+u.method+"' method.",a),a}}if(r)return;return this.objectLength(n)&&this.successList.push(t),!0},customDataMessage:function(t,n){return e(t).data("msg-"+n.toLowerCase())||t.attributes&&e(t).attr("data-msg-"+n.toLowerCase())},customMessage:function(e,t){var n=this.settings.messages[e];return n&&(n.constructor===String?n:n[t])},findDefined:function(){for(var e=0;e<arguments.length;e++)if(arguments[e]!==undefined)return arguments[e];return undefined},defaultMessage:function(t,n){return this.findDefined(this.customMessage(t.name,n),this.customDataMessage(t,n),!this.settings.ignoreTitle&&t.title||undefined,e.validator.messages[n],"<strong>Warning: No message defined for "+t.name+"</strong>")},formatAndAdd:function(t,n){var r=this.defaultMessage(t,n.method),i=/\$?\{(\d+)\}/g;typeof r=="function"?r=r.call(this,n.parameters,t):i.test(r)&&(r=e.validator.format(r.replace(i,"{$1}"),n.parameters)),this.errorList.push({message:r,element:t}),this.errorMap[t.name]=r,this.submitted[t.name]=r},addWrapper:function(e){return this.settings.wrapper&&(e=e.add(e.parent(this.settings.wrapper))),e},defaultShowErrors:function(){var e,t;for(e=0;this.errorList[e];e++){var n=this.errorList[e];this.settings.highlight&&this.settings.highlight.call(this,n.element,this.settings.errorClass,this.settings.validClass),this.showLabel(n.element,n.message)}this.errorList.length&&(this.toShow=this.toShow.add(this.containers));if(this.settings.success)for(e=0;this.successList[e];e++)this.showLabel(this.successList[e]);if(this.settings.unhighlight)for(e=0,t=this.validElements();t[e];e++)this.settings.unhighlight.call(this,t[e],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return e(this.errorList).map(function(){return this.element})},showLabel:function(t,n){var r=this.errorsFor(t);r.length?(r.removeClass(this.settings.validClass).addClass(this.settings.errorClass),r.html(n)):(r=e("<"+this.settings.errorElement+">").attr("for",this.idOrName(t)).addClass(this.settings.errorClass).html(n||""),this.settings.wrapper&&(r=r.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.append(r).length||(this.settings.errorPlacement?this.settings.errorPlacement(r,e(t)):r.insertAfter(t))),!n&&this.settings.success&&(r.text(""),typeof this.settings.success=="string"?r.addClass(this.settings.success):this.settings.success(r,t)),this.toShow=this.toShow.add(r)},errorsFor:function(t){var n=this.idOrName(t);return this.errors().filter(function(){return e(this).attr("for")===n})},idOrName:function(e){return this.groups[e.name]||(this.checkable(e)?e.name:e.id||e.name)},validationTargetFor:function(e){return this.checkable(e)&&(e=this.findByName(e.name).not(this.settings.ignore)[0]),e},checkable:function(e){return/radio|checkbox/i.test(e.type)},findByName:function(t){return e(this.currentForm).find("[name='"+t+"']")},getLength:function(t,n){switch(n.nodeName.toLowerCase()){case"select":return e("option:selected",n).length;case"input":if(this.checkable(n))return this.findByName(n.name).filter(":checked").length}return t.length},depend:function(e,t){return this.dependTypes[typeof e]?this.dependTypes[typeof e](e,t):!0},dependTypes:{"boolean":function(e,t){return e},string:function(t,n){return!!e(t,n.form).length},"function":function(e,t){return e(t)}},optional:function(t){var n=this.elementValue(t);return!e.validator.methods.required.call(this,n,t)&&"dependency-mismatch"},startRequest:function(e){this.pending[e.name]||(this.pendingRequest++,this.pending[e.name]=!0)},stopRequest:function(t,n){this.pendingRequest--,this.pendingRequest<0&&(this.pendingRequest=0),delete this.pending[t.name],n&&this.pendingRequest===0&&this.formSubmitted&&this.form()?(e(this.currentForm).submit(),this.formSubmitted=!1):!n&&this.pendingRequest===0&&this.formSubmitted&&(e(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(t){return e.data(t,"previousValue")||e.data(t,"previousValue",{old:null,valid:!0,message:this.defaultMessage(t,"remote")})}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(t,n){t.constructor===String?this.classRuleSettings[t]=n:e.extend(this.classRuleSettings,t)},classRules:function(t){var n={},r=e(t).attr("class");return r&&e.each(r.split(" "),function(){this in e.validator.classRuleSettings&&e.extend(n,e.validator.classRuleSettings[this])}),n},attributeRules:function(t){var n={},r=e(t);for(var i in e.validator.methods){var s;i==="required"?(s=r.get(0).getAttribute(i),s===""&&(s=!0),s=!!s):s=r.attr(i),s?n[i]=s:r[0].getAttribute("type")===i&&(n[i]=!0)}return n.maxlength&&/-1|2147483647|524288/.test(n.maxlength)&&delete n.maxlength,n},dataRules:function(t){var n,r,i={},s=e(t);for(n in e.validator.methods)r=s.data("rule-"+n.toLowerCase()),r!==undefined&&(i[n]=r);return i},staticRules:function(t){var n={},r=e.data(t.form,"validator");return r.settings.rules&&(n=e.validator.normalizeRule(r.settings.rules[t.name])||{}),n},normalizeRules:function(t,n){return e.each(t,function(r,i){if(i===!1){delete t[r];return}if(i.param||i.depends){var s=!0;switch(typeof i.depends){case"string":s=!!e(i.depends,n.form).length;break;case"function":s=i.depends.call(n,n)}s?t[r]=i.param!==undefined?i.param:!0:delete t[r]}}),e.each(t,function(r,i){t[r]=e.isFunction(i)?i(n):i}),e.each(["minlength","maxlength"],function(){t[this]&&(t[this]=Number(t[this]))}),e.each(["rangelength"],function(){var n;t[this]&&(e.isArray(t[this])?t[this]=[Number(t[this][0]),Number(t[this][1])]:typeof t[this]=="string"&&(n=t[this].split(/[\s,]+/),t[this]=[Number(n[0]),Number(n[1])]))}),e.validator.autoCreateRanges&&(t.min&&t.max&&(t.range=[t.min,t.max],delete t.min,delete t.max),t.minlength&&t.maxlength&&(t.rangelength=[t.minlength,t.maxlength],delete t.minlength,delete t.maxlength)),t},normalizeRule:function(t){if(typeof t=="string"){var n={};e.each(t.split(/\s/),function(){n[this]=!0}),t=n}return t},addMethod:function(t,n,r){e.validator.methods[t]=n,e.validator.messages[t]=r!==undefined?r:e.validator.messages[t],n.length<3&&e.validator.addClassRules(t,e.validator.normalizeRule(t))},methods:{required:function(t,n,r){if(!this.depend(r,n))return"dependency-mismatch";if(n.nodeName.toLowerCase()==="select"){var i=e(n).val();return i&&i.length>0}return this.checkable(n)?this.getLength(t,n)>0:e.trim(t).length>0},remote:function(t,n,r){if(this.optional(n))return"dependency-mismatch";var i=this.previousValue(n);this.settings.messages[n.name]||(this.settings.messages[n.name]={}),i.originalMessage=this.settings.messages[n.name].remote,this.settings.messages[n.name].remote=i.message,r=typeof r=="string"&&{url:r}||r;if(i.old===t)return i.valid;i.old=t;var s=this;this.startRequest(n);var o={};return o[n.name]=t,e.ajax(e.extend(!0,{url:r,mode:"abort",port:"validate"+n.name,dataType:"json",data:o,success:function(r){s.settings.messages[n.name].remote=i.originalMessage;var o=r===!0||r==="true";if(o){var u=s.formSubmitted;s.prepareElement(n),s.formSubmitted=u,s.successList.push(n),delete s.invalid[n.name],s.showErrors()}else{var a={},f=r||s.defaultMessage(n,"remote");a[n.name]=i.message=e.isFunction(f)?f(t):f,s.invalid[n.name]=!0,s.showErrors(a)}i.valid=o,s.stopRequest(n,o)}},r)),"pending"},minlength:function(t,n,r){var i=e.isArray(t)?t.length:this.getLength(e.trim(t),n);return this.optional(n)||i>=r},maxlength:function(t,n,r){var i=e.isArray(t)?t.length:this.getLength(e.trim(t),n);return this.optional(n)||i<=r},rangelength:function(t,n,r){var i=e.isArray(t)?t.length:this.getLength(e.trim(t),n);return this.optional(n)||i>=r[0]&&i<=r[1]},min:function(e,t,n){return this.optional(t)||e>=n},max:function(e,t,n){return this.optional(t)||e<=n},range:function(e,t,n){return this.optional(t)||e>=n[0]&&e<=n[1]},email:function(e,t){return this.optional(t)||/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i.test(e)},url:function(e,t){return this.optional(t)||/^(https?|s?ftp):\/\/(((([a-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-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(e)},date:function(e,t){return this.optional(t)||!/Invalid|NaN/.test((new Date(e)).toString())},dateISO:function(e,t){return this.optional(t)||/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/.test(e)},number:function(e,t){return this.optional(t)||/^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(e)},digits:function(e,t){return this.optional(t)||/^\d+$/.test(e)},creditcard:function(e,t){if(this.optional(t))return"dependency-mismatch";if(/[^0-9 \-]+/.test(e))return!1;var n=0,r=0,i=!1;e=e.replace(/\D/g,"");for(var s=e.length-1;s>=0;s--){var o=e.charAt(s);r=parseInt(o,10),i&&(r*=2)>9&&(r-=9),n+=r,i=!i}return n%10===0},equalTo:function(t,n,r){var i=e(r);return this.settings.onfocusout&&i.unbind(".validate-equalTo").bind("blur.validate-equalTo",function(){e(n).valid()}),t===i.val()}}}),e.format=e.validator.format})(jQuery),function(e){var t={};if(e.ajaxPrefilter)e.ajaxPrefilter(function(e,n,r){var i=e.port;e.mode==="abort"&&(t[i]&&t[i].abort(),t[i]=r)});else{var n=e.ajax;e.ajax=function(r){var i=("mode"in r?r:e.ajaxSettings).mode,s=("port"in r?r:e.ajaxSettings).port;return i==="abort"?(t[s]&&t[s].abort(),t[s]=n.apply(this,arguments)):n.apply(this,arguments)}}}(jQuery),function(e){e.extend(e.fn,{validateDelegate:function(t,n,r){return this.bind(n,function(n){var i=e(n.target);if(i.is(t))return r.apply(i,arguments)})}})}(jQuery); | |
/* | |
Breakpoints.js | |
version 1.0 | |
Creates handy events for your responsive design breakpoints | |
Copyright 2011 XOXCO, Inc | |
http://xoxco.com/ | |
Documentation for this plugin lives here: | |
http://xoxco.com/projects/code/breakpoints | |
Licensed under the MIT license: | |
http://www.opensource.org/licenses/mit-license.php | |
*/ | |
(function($) { | |
var lastSize = 0; | |
var interval = null; | |
$.fn.resetBreakpoints = function() { | |
$(window).unbind('resize'); | |
if (interval) { | |
clearInterval(interval); | |
} | |
lastSize = 0; | |
}; | |
$.fn.setBreakpoints = function(settings) { | |
var options = jQuery.extend({ | |
distinct: true, | |
breakpoints: new Array(320,480,768,1024) | |
},settings); | |
interval = setInterval(function() { | |
var w = $(window).width(); | |
var done = false; | |
for (var bp in options.breakpoints.sort(function(a,b) { return (b-a) })) { | |
// fire onEnter when a browser expands into a new breakpoint | |
// if in distinct mode, remove all other breakpoints first. | |
if (!done && w >= options.breakpoints[bp] && lastSize < options.breakpoints[bp]) { | |
if (options.distinct) { | |
for (var x in options.breakpoints.sort(function(a,b) { return (b-a) })) { | |
if ($('body').hasClass('breakpoint-' + options.breakpoints[x])) { | |
$('body').removeClass('breakpoint-' + options.breakpoints[x]); | |
$(window).trigger('exitBreakpoint' + options.breakpoints[x]); | |
} | |
} | |
done = true; | |
} | |
$('body').addClass('breakpoint-' + options.breakpoints[bp]); | |
$(window).trigger('enterBreakpoint' + options.breakpoints[bp]); | |
} | |
// fire onExit when browser contracts out of a larger breakpoint | |
if (w < options.breakpoints[bp] && lastSize >= options.breakpoints[bp]) { | |
$('body').removeClass('breakpoint-' + options.breakpoints[bp]); | |
$(window).trigger('exitBreakpoint' + options.breakpoints[bp]); | |
} | |
// if in distinct mode, fire onEnter when browser contracts into a smaller breakpoint | |
if ( | |
options.distinct && // only one breakpoint at a time | |
w >= options.breakpoints[bp] && // and we are in this one | |
w < options.breakpoints[bp-1] && // and smaller than the bigger one | |
lastSize > w && // and we contracted | |
lastSize >0 && // and this is not the first time | |
!$('body').hasClass('breakpoint-' + options.breakpoints[bp]) // and we aren't already in this breakpoint | |
) { | |
$('body').addClass('breakpoint-' + options.breakpoints[bp]); | |
$(window).trigger('enterBreakpoint' + options.breakpoints[bp]); | |
} | |
} | |
// set up for next call | |
if (lastSize != w) { | |
lastSize = w; | |
} | |
},250); | |
}; | |
})(jQuery); | |
// Place any jQuery/helper plugins in here. | |
/*! | |
* jQuery Transit - CSS3 transitions and transformations | |
* (c) 2011-2012 Rico Sta. Cruz <[email protected]> | |
* MIT Licensed. | |
* | |
* http://ricostacruz.com/jquery.transit | |
* http://github.com/rstacruz/jquery.transit | |
*/ | |
(function(k){k.transit={version:"0.9.9",propertyMap:{marginLeft:"margin",marginRight:"margin",marginBottom:"margin",marginTop:"margin",paddingLeft:"padding",paddingRight:"padding",paddingBottom:"padding",paddingTop:"padding"},enabled:true,useTransitionEnd:false};var d=document.createElement("div");var q={};function b(v){if(v in d.style){return v}var u=["Moz","Webkit","O","ms"];var r=v.charAt(0).toUpperCase()+v.substr(1);if(v in d.style){return v}for(var t=0;t<u.length;++t){var s=u[t]+r;if(s in d.style){return s}}}function e(){d.style[q.transform]="";d.style[q.transform]="rotateY(90deg)";return d.style[q.transform]!==""}var a=navigator.userAgent.toLowerCase().indexOf("chrome")>-1;q.transition=b("transition");q.transitionDelay=b("transitionDelay");q.transform=b("transform");q.transformOrigin=b("transformOrigin");q.transform3d=e();var i={transition:"transitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",WebkitTransition:"webkitTransitionEnd",msTransition:"MSTransitionEnd"};var f=q.transitionEnd=i[q.transition]||null;for(var p in q){if(q.hasOwnProperty(p)&&typeof k.support[p]==="undefined"){k.support[p]=q[p]}}d=null;k.cssEase={_default:"ease","in":"ease-in",out:"ease-out","in-out":"ease-in-out",snap:"cubic-bezier(0,1,.5,1)",easeOutCubic:"cubic-bezier(.215,.61,.355,1)",easeInOutCubic:"cubic-bezier(.645,.045,.355,1)",easeInCirc:"cubic-bezier(.6,.04,.98,.335)",easeOutCirc:"cubic-bezier(.075,.82,.165,1)",easeInOutCirc:"cubic-bezier(.785,.135,.15,.86)",easeInExpo:"cubic-bezier(.95,.05,.795,.035)",easeOutExpo:"cubic-bezier(.19,1,.22,1)",easeInOutExpo:"cubic-bezier(1,0,0,1)",easeInQuad:"cubic-bezier(.55,.085,.68,.53)",easeOutQuad:"cubic-bezier(.25,.46,.45,.94)",easeInOutQuad:"cubic-bezier(.455,.03,.515,.955)",easeInQuart:"cubic-bezier(.895,.03,.685,.22)",easeOutQuart:"cubic-bezier(.165,.84,.44,1)",easeInOutQuart:"cubic-bezier(.77,0,.175,1)",easeInQuint:"cubic-bezier(.755,.05,.855,.06)",easeOutQuint:"cubic-bezier(.23,1,.32,1)",easeInOutQuint:"cubic-bezier(.86,0,.07,1)",easeInSine:"cubic-bezier(.47,0,.745,.715)",easeOutSine:"cubic-bezier(.39,.575,.565,1)",easeInOutSine:"cubic-bezier(.445,.05,.55,.95)",easeInBack:"cubic-bezier(.6,-.28,.735,.045)",easeOutBack:"cubic-bezier(.175, .885,.32,1.275)",easeInOutBack:"cubic-bezier(.68,-.55,.265,1.55)"};k.cssHooks["transit:transform"]={get:function(r){return k(r).data("transform")||new j()},set:function(s,r){var t=r;if(!(t instanceof j)){t=new j(t)}if(q.transform==="WebkitTransform"&&!a){s.style[q.transform]=t.toString(true)}else{s.style[q.transform]=t.toString()}k(s).data("transform",t)}};k.cssHooks.transform={set:k.cssHooks["transit:transform"].set};if(k.fn.jquery<"1.8"){k.cssHooks.transformOrigin={get:function(r){return r.style[q.transformOrigin]},set:function(r,s){r.style[q.transformOrigin]=s}};k.cssHooks.transition={get:function(r){return r.style[q.transition]},set:function(r,s){r.style[q.transition]=s}}}n("scale");n("translate");n("rotate");n("rotateX");n("rotateY");n("rotate3d");n("perspective");n("skewX");n("skewY");n("x",true);n("y",true);function j(r){if(typeof r==="string"){this.parse(r)}return this}j.prototype={setFromString:function(t,s){var r=(typeof s==="string")?s.split(","):(s.constructor===Array)?s:[s];r.unshift(t);j.prototype.set.apply(this,r)},set:function(s){var r=Array.prototype.slice.apply(arguments,[1]);if(this.setter[s]){this.setter[s].apply(this,r)}else{this[s]=r.join(",")}},get:function(r){if(this.getter[r]){return this.getter[r].apply(this)}else{return this[r]||0}},setter:{rotate:function(r){this.rotate=o(r,"deg")},rotateX:function(r){this.rotateX=o(r,"deg")},rotateY:function(r){this.rotateY=o(r,"deg")},scale:function(r,s){if(s===undefined){s=r}this.scale=r+","+s},skewX:function(r){this.skewX=o(r,"deg")},skewY:function(r){this.skewY=o(r,"deg")},perspective:function(r){this.perspective=o(r,"px")},x:function(r){this.set("translate",r,null)},y:function(r){this.set("translate",null,r)},translate:function(r,s){if(this._translateX===undefined){this._translateX=0}if(this._translateY===undefined){this._translateY=0}if(r!==null&&r!==undefined){this._translateX=o(r,"px")}if(s!==null&&s!==undefined){this._translateY=o(s,"px")}this.translate=this._translateX+","+this._translateY}},getter:{x:function(){return this._translateX||0},y:function(){return this._translateY||0},scale:function(){var r=(this.scale||"1,1").split(",");if(r[0]){r[0]=parseFloat(r[0])}if(r[1]){r[1]=parseFloat(r[1])}return(r[0]===r[1])?r[0]:r},rotate3d:function(){var t=(this.rotate3d||"0,0,0,0deg").split(",");for(var r=0;r<=3;++r){if(t[r]){t[r]=parseFloat(t[r])}}if(t[3]){t[3]=o(t[3],"deg")}return t}},parse:function(s){var r=this;s.replace(/([a-zA-Z0-9]+)\((.*?)\)/g,function(t,v,u){r.setFromString(v,u)})},toString:function(t){var s=[];for(var r in this){if(this.hasOwnProperty(r)){if((!q.transform3d)&&((r==="rotateX")||(r==="rotateY")||(r==="perspective")||(r==="transformOrigin"))){continue}if(r[0]!=="_"){if(t&&(r==="scale")){s.push(r+"3d("+this[r]+",1)")}else{if(t&&(r==="translate")){s.push(r+"3d("+this[r]+",0)")}else{s.push(r+"("+this[r]+")")}}}}}return s.join(" ")}};function m(s,r,t){if(r===true){s.queue(t)}else{if(r){s.queue(r,t)}else{t()}}}function h(s){var r=[];k.each(s,function(t){t=k.camelCase(t);t=k.transit.propertyMap[t]||k.cssProps[t]||t;t=c(t);if(k.inArray(t,r)===-1){r.push(t)}});return r}function g(s,v,x,r){var t=h(s);if(k.cssEase[x]){x=k.cssEase[x]}var w=""+l(v)+" "+x;if(parseInt(r,10)>0){w+=" "+l(r)}var u=[];k.each(t,function(z,y){u.push(y+" "+w)});return u.join(", ")}k.fn.transition=k.fn.transit=function(z,s,y,C){var D=this;var u=0;var w=true;if(typeof s==="function"){C=s;s=undefined}if(typeof y==="function"){C=y;y=undefined}if(typeof z.easing!=="undefined"){y=z.easing;delete z.easing}if(typeof z.duration!=="undefined"){s=z.duration;delete z.duration}if(typeof z.complete!=="undefined"){C=z.complete;delete z.complete}if(typeof z.queue!=="undefined"){w=z.queue;delete z.queue}if(typeof z.delay!=="undefined"){u=z.delay;delete z.delay}if(typeof s==="undefined"){s=k.fx.speeds._default}if(typeof y==="undefined"){y=k.cssEase._default}s=l(s);var E=g(z,s,y,u);var B=k.transit.enabled&&q.transition;var t=B?(parseInt(s,10)+parseInt(u,10)):0;if(t===0){var A=function(F){D.css(z);if(C){C.apply(D)}if(F){F()}};m(D,w,A);return D}var x={};var r=function(H){var G=false;var F=function(){if(G){D.unbind(f,F)}if(t>0){D.each(function(){this.style[q.transition]=(x[this]||null)})}if(typeof C==="function"){C.apply(D)}if(typeof H==="function"){H()}};if((t>0)&&(f)&&(k.transit.useTransitionEnd)){G=true;D.bind(f,F)}else{window.setTimeout(F,t)}D.each(function(){if(t>0){this.style[q.transition]=E}k(this).css(z)})};var v=function(F){this.offsetWidth;r(F)};m(D,w,v);return this};function n(s,r){if(!r){k.cssNumber[s]=true}k.transit.propertyMap[s]=q.transform;k.cssHooks[s]={get:function(v){var u=k(v).css("transit:transform");return u.get(s)},set:function(v,w){var u=k(v).css("transit:transform");u.setFromString(s,w);k(v).css({"transit:transform":u})}}}function c(r){return r.replace(/([A-Z])/g,function(s){return"-"+s.toLowerCase()})}function o(s,r){if((typeof s==="string")&&(!s.match(/^[\-0-9\.]+$/))){return s}else{return""+s+r}}function l(s){var r=s;if(k.fx.speeds[r]){r=k.fx.speeds[r]}return o(r,"ms")}k.transit.getTransitionValue=g})(jQuery); | |
// Place any jQuery/helper plugins in here. | |
/* MOBILE COLLAPSE MENU */ | |
(function($) { | |
$.fn.collapsable = function(options) { | |
// iterate and reformat each matched element | |
return this.each(function() { | |
// cache this: | |
var obj = $(this); | |
var tree = obj.next('ul#top-nav'); | |
obj.click(function(){ | |
if( obj.is(':visible') ){tree.toggle();} | |
$(this).toggleClass('active'); | |
}); | |
$(window).resize(function(){ | |
if ( $(window).width() <= 480 ){tree.attr('style','');}; | |
}); | |
}); | |
}; | |
})(jQuery); | |
(function(a){"use strict";a.fn.fitVids=function(b){var c={customSelector:null},d=document.createElement("div"),e=document.getElementsByTagName("base")[0]||document.getElementsByTagName("script")[0];return d.className="fit-vids-style",d.innerHTML="­<style> .fluid-width-video-wrapper { width: 100%; position: relative; padding: 0; } .fluid-width-video-wrapper iframe, .fluid-width-video-wrapper object, .fluid-width-video-wrapper embed { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } </style>",e.parentNode.insertBefore(d,e),b&&a.extend(c,b),this.each(function(){var b=["iframe[src*='player.vimeo.com']","iframe[src*='www.youtube.com']","iframe[src*='www.youtube-nocookie.com']","iframe[src*='www.kickstarter.com']","object","embed"];c.customSelector&&b.push(c.customSelector);var d=a(this).find(b.join(","));d.each(function(){var b=a(this);if(!("embed"===this.tagName.toLowerCase()&&b.parent("object").length||b.parent(".fluid-width-video-wrapper").length)){var c="object"===this.tagName.toLowerCase()||b.attr("height")&&!isNaN(parseInt(b.attr("height"),10))?parseInt(b.attr("height"),10):b.height(),d=isNaN(parseInt(b.attr("width"),10))?b.width():parseInt(b.attr("width"),10),e=c/d;if(!b.attr("id")){var f="fitvid"+Math.floor(999999*Math.random());b.attr("id",f)}b.wrap('<div class="fluid-width-video-wrapper"></div>').parent(".fluid-width-video-wrapper").css("padding-top",100*e+"%"),b.removeAttr("height").removeAttr("width")}})})}})(jQuery); | |
// jquery.event.move | |
// | |
// 1.3.1 | |
// | |
// Stephen Band | |
// | |
// Triggers 'movestart', 'move' and 'moveend' events after | |
// mousemoves following a mousedown cross a distance threshold, | |
// similar to the native 'dragstart', 'drag' and 'dragend' events. | |
// Move events are throttled to animation frames. Move event objects | |
// have the properties: | |
// | |
// pageX: | |
// pageY: Page coordinates of pointer. | |
// startX: | |
// startY: Page coordinates of pointer at movestart. | |
// distX: | |
// distY: Distance the pointer has moved since movestart. | |
// deltaX: | |
// deltaY: Distance the finger has moved since last event. | |
// velocityX: | |
// velocityY: Average velocity over last few events. | |
(function (module) { | |
if (typeof define === 'function' && define.amd) { | |
// AMD. Register as an anonymous module. | |
define(['jquery'], module); | |
} else { | |
// Browser globals | |
module(jQuery); | |
} | |
})(function(jQuery, undefined){ | |
var // Number of pixels a pressed pointer travels before movestart | |
// event is fired. | |
threshold = 6, | |
add = jQuery.event.add, | |
remove = jQuery.event.remove, | |
// Just sugar, so we can have arguments in the same order as | |
// add and remove. | |
trigger = function(node, type, data) { | |
jQuery.event.trigger(type, data, node); | |
}, | |
// Shim for requestAnimationFrame, falling back to timer. See: | |
// see http://paulirish.com/2011/requestanimationframe-for-smart-animating/ | |
requestFrame = (function(){ | |
return ( | |
window.requestAnimationFrame || | |
window.webkitRequestAnimationFrame || | |
window.mozRequestAnimationFrame || | |
window.oRequestAnimationFrame || | |
window.msRequestAnimationFrame || | |
function(fn, element){ | |
return window.setTimeout(function(){ | |
fn(); | |
}, 25); | |
} | |
); | |
})(), | |
ignoreTags = { | |
textarea: true, | |
input: true, | |
select: true, | |
button: true | |
}, | |
mouseevents = { | |
move: 'mousemove', | |
cancel: 'mouseup dragstart', | |
end: 'mouseup' | |
}, | |
touchevents = { | |
move: 'touchmove', | |
cancel: 'touchend', | |
end: 'touchend' | |
}; | |
// Constructors | |
function Timer(fn){ | |
var callback = fn, | |
active = false, | |
running = false; | |
function trigger(time) { | |
if (active){ | |
callback(); | |
requestFrame(trigger); | |
running = true; | |
active = false; | |
} | |
else { | |
running = false; | |
} | |
} | |
this.kick = function(fn) { | |
active = true; | |
if (!running) { trigger(); } | |
}; | |
this.end = function(fn) { | |
var cb = callback; | |
if (!fn) { return; } | |
// If the timer is not running, simply call the end callback. | |
if (!running) { | |
fn(); | |
} | |
// If the timer is running, and has been kicked lately, then | |
// queue up the current callback and the end callback, otherwise | |
// just the end callback. | |
else { | |
callback = active ? | |
function(){ cb(); fn(); } : | |
fn ; | |
active = true; | |
} | |
}; | |
} | |
// Functions | |
function returnTrue() { | |
return true; | |
} | |
function returnFalse() { | |
return false; | |
} | |
function preventDefault(e) { | |
e.preventDefault(); | |
} | |
function preventIgnoreTags(e) { | |
// Don't prevent interaction with form elements. | |
if (ignoreTags[ e.target.tagName.toLowerCase() ]) { return; } | |
e.preventDefault(); | |
} | |
function isLeftButton(e) { | |
// Ignore mousedowns on any button other than the left (or primary) | |
// mouse button, or when a modifier key is pressed. | |
return (e.which === 1 && !e.ctrlKey && !e.altKey); | |
} | |
function identifiedTouch(touchList, id) { | |
var i, l; | |
if (touchList.identifiedTouch) { | |
return touchList.identifiedTouch(id); | |
} | |
// touchList.identifiedTouch() does not exist in | |
// webkit yet… we must do the search ourselves... | |
i = -1; | |
l = touchList.length; | |
while (++i < l) { | |
if (touchList[i].identifier === id) { | |
return touchList[i]; | |
} | |
} | |
} | |
function changedTouch(e, event) { | |
var touch = identifiedTouch(e.changedTouches, event.identifier); | |
// This isn't the touch you're looking for. | |
if (!touch) { return; } | |
// Chrome Android (at least) includes touches that have not | |
// changed in e.changedTouches. That's a bit annoying. Check | |
// that this touch has changed. | |
if (touch.pageX === event.pageX && touch.pageY === event.pageY) { return; } | |
return touch; | |
} | |
// Handlers that decide when the first movestart is triggered | |
function mousedown(e){ | |
var data; | |
if (!isLeftButton(e)) { return; } | |
data = { | |
target: e.target, | |
startX: e.pageX, | |
startY: e.pageY, | |
timeStamp: e.timeStamp | |
}; | |
add(document, mouseevents.move, mousemove, data); | |
add(document, mouseevents.cancel, mouseend, data); | |
} | |
function mousemove(e){ | |
var data = e.data; | |
checkThreshold(e, data, e, removeMouse); | |
} | |
function mouseend(e) { | |
removeMouse(); | |
} | |
function removeMouse() { | |
remove(document, mouseevents.move, mousemove); | |
remove(document, mouseevents.cancel, mouseend); | |
} | |
function touchstart(e) { | |
var touch, template; | |
// Don't get in the way of interaction with form elements. | |
if (ignoreTags[ e.target.tagName.toLowerCase() ]) { return; } | |
touch = e.changedTouches[0]; | |
// iOS live updates the touch objects whereas Android gives us copies. | |
// That means we can't trust the touchstart object to stay the same, | |
// so we must copy the data. This object acts as a template for | |
// movestart, move and moveend event objects. | |
template = { | |
target: touch.target, | |
startX: touch.pageX, | |
startY: touch.pageY, | |
timeStamp: e.timeStamp, | |
identifier: touch.identifier | |
}; | |
// Use the touch identifier as a namespace, so that we can later | |
// remove handlers pertaining only to this touch. | |
add(document, touchevents.move + '.' + touch.identifier, touchmove, template); | |
add(document, touchevents.cancel + '.' + touch.identifier, touchend, template); | |
} | |
function touchmove(e){ | |
var data = e.data, | |
touch = changedTouch(e, data); | |
if (!touch) { return; } | |
checkThreshold(e, data, touch, removeTouch); | |
} | |
function touchend(e) { | |
var template = e.data, | |
touch = identifiedTouch(e.changedTouches, template.identifier); | |
if (!touch) { return; } | |
removeTouch(template.identifier); | |
} | |
function removeTouch(identifier) { | |
remove(document, '.' + identifier, touchmove); | |
remove(document, '.' + identifier, touchend); | |
} | |
// Logic for deciding when to trigger a movestart. | |
function checkThreshold(e, template, touch, fn) { | |
var distX = touch.pageX - template.startX, | |
distY = touch.pageY - template.startY; | |
// Do nothing if the threshold has not been crossed. | |
if ((distX * distX) + (distY * distY) < (threshold * threshold)) { return; } | |
triggerStart(e, template, touch, distX, distY, fn); | |
} | |
function handled() { | |
// this._handled should return false once, and after return true. | |
this._handled = returnTrue; | |
return false; | |
} | |
function flagAsHandled(e) { | |
e._handled(); | |
} | |
function triggerStart(e, template, touch, distX, distY, fn) { | |
var node = template.target, | |
touches, time; | |
touches = e.targetTouches; | |
time = e.timeStamp - template.timeStamp; | |
// Create a movestart object with some special properties that | |
// are passed only to the movestart handlers. | |
template.type = 'movestart'; | |
template.distX = distX; | |
template.distY = distY; | |
template.deltaX = distX; | |
template.deltaY = distY; | |
template.pageX = touch.pageX; | |
template.pageY = touch.pageY; | |
template.velocityX = distX / time; | |
template.velocityY = distY / time; | |
template.targetTouches = touches; | |
template.finger = touches ? | |
touches.length : | |
1 ; | |
// The _handled method is fired to tell the default movestart | |
// handler that one of the move events is bound. | |
template._handled = handled; | |
// Pass the touchmove event so it can be prevented if or when | |
// movestart is handled. | |
template._preventTouchmoveDefault = function() { | |
e.preventDefault(); | |
}; | |
// Trigger the movestart event. | |
trigger(template.target, template); | |
// Unbind handlers that tracked the touch or mouse up till now. | |
fn(template.identifier); | |
} | |
// Handlers that control what happens following a movestart | |
function activeMousemove(e) { | |
var event = e.data.event, | |
timer = e.data.timer; | |
updateEvent(event, e, e.timeStamp, timer); | |
} | |
function activeMouseend(e) { | |
var event = e.data.event, | |
timer = e.data.timer; | |
removeActiveMouse(); | |
endEvent(event, timer, function() { | |
// Unbind the click suppressor, waiting until after mouseup | |
// has been handled. | |
setTimeout(function(){ | |
remove(event.target, 'click', returnFalse); | |
}, 0); | |
}); | |
} | |
function removeActiveMouse(event) { | |
remove(document, mouseevents.move, activeMousemove); | |
remove(document, mouseevents.end, activeMouseend); | |
} | |
function activeTouchmove(e) { | |
var event = e.data.event, | |
timer = e.data.timer, | |
touch = changedTouch(e, event); | |
if (!touch) { return; } | |
// Stop the interface from gesturing | |
e.preventDefault(); | |
event.targetTouches = e.targetTouches; | |
updateEvent(event, touch, e.timeStamp, timer); | |
} | |
function activeTouchend(e) { | |
var event = e.data.event, | |
timer = e.data.timer, | |
touch = identifiedTouch(e.changedTouches, event.identifier); | |
// This isn't the touch you're looking for. | |
if (!touch) { return; } | |
removeActiveTouch(event); | |
endEvent(event, timer); | |
} | |
function removeActiveTouch(event) { | |
remove(document, '.' + event.identifier, activeTouchmove); | |
remove(document, '.' + event.identifier, activeTouchend); | |
} | |
// Logic for triggering move and moveend events | |
function updateEvent(event, touch, timeStamp, timer) { | |
var time = timeStamp - event.timeStamp; | |
event.type = 'move'; | |
event.distX = touch.pageX - event.startX; | |
event.distY = touch.pageY - event.startY; | |
event.deltaX = touch.pageX - event.pageX; | |
event.deltaY = touch.pageY - event.pageY; | |
// Average the velocity of the last few events using a decay | |
// curve to even out spurious jumps in values. | |
event.velocityX = 0.3 * event.velocityX + 0.7 * event.deltaX / time; | |
event.velocityY = 0.3 * event.velocityY + 0.7 * event.deltaY / time; | |
event.pageX = touch.pageX; | |
event.pageY = touch.pageY; | |
timer.kick(); | |
} | |
function endEvent(event, timer, fn) { | |
timer.end(function(){ | |
event.type = 'moveend'; | |
trigger(event.target, event); | |
return fn && fn(); | |
}); | |
} | |
// jQuery special event definition | |
function setup(data, namespaces, eventHandle) { | |
// Stop the node from being dragged | |
//add(this, 'dragstart.move drag.move', preventDefault); | |
// Prevent text selection and touch interface scrolling | |
//add(this, 'mousedown.move', preventIgnoreTags); | |
// Tell movestart default handler that we've handled this | |
add(this, 'movestart.move', flagAsHandled); | |
// Don't bind to the DOM. For speed. | |
return true; | |
} | |
function teardown(namespaces) { | |
remove(this, 'dragstart drag', preventDefault); | |
remove(this, 'mousedown touchstart', preventIgnoreTags); | |
remove(this, 'movestart', flagAsHandled); | |
// Don't bind to the DOM. For speed. | |
return true; | |
} | |
function addMethod(handleObj) { | |
// We're not interested in preventing defaults for handlers that | |
// come from internal move or moveend bindings | |
if (handleObj.namespace === "move" || handleObj.namespace === "moveend") { | |
return; | |
} | |
// Stop the node from being dragged | |
add(this, 'dragstart.' + handleObj.guid + ' drag.' + handleObj.guid, preventDefault, undefined, handleObj.selector); | |
// Prevent text selection and touch interface scrolling | |
add(this, 'mousedown.' + handleObj.guid, preventIgnoreTags, undefined, handleObj.selector); | |
} | |
function removeMethod(handleObj) { | |
if (handleObj.namespace === "move" || handleObj.namespace === "moveend") { | |
return; | |
} | |
remove(this, 'dragstart.' + handleObj.guid + ' drag.' + handleObj.guid); | |
remove(this, 'mousedown.' + handleObj.guid); | |
} | |
jQuery.event.special.movestart = { | |
setup: setup, | |
teardown: teardown, | |
add: addMethod, | |
remove: removeMethod, | |
_default: function(e) { | |
var template, data; | |
// If no move events were bound to any ancestors of this | |
// target, high tail it out of here. | |
if (!e._handled()) { return; } | |
template = { | |
target: e.target, | |
startX: e.startX, | |
startY: e.startY, | |
pageX: e.pageX, | |
pageY: e.pageY, | |
distX: e.distX, | |
distY: e.distY, | |
deltaX: e.deltaX, | |
deltaY: e.deltaY, | |
velocityX: e.velocityX, | |
velocityY: e.velocityY, | |
timeStamp: e.timeStamp, | |
identifier: e.identifier, | |
targetTouches: e.targetTouches, | |
finger: e.finger | |
}; | |
data = { | |
event: template, | |
timer: new Timer(function(time){ | |
trigger(e.target, template); | |
}) | |
}; | |
if (e.identifier === undefined) { | |
// We're dealing with a mouse | |
// Stop clicks from propagating during a move | |
add(e.target, 'click', returnFalse); | |
add(document, mouseevents.move, activeMousemove, data); | |
add(document, mouseevents.end, activeMouseend, data); | |
} | |
else { | |
// We're dealing with a touch. Stop touchmove doing | |
// anything defaulty. | |
e._preventTouchmoveDefault(); | |
add(document, touchevents.move + '.' + e.identifier, activeTouchmove, data); | |
add(document, touchevents.end + '.' + e.identifier, activeTouchend, data); | |
} | |
} | |
}; | |
jQuery.event.special.move = { | |
setup: function() { | |
// Bind a noop to movestart. Why? It's the movestart | |
// setup that decides whether other move events are fired. | |
add(this, 'movestart.move', jQuery.noop); | |
}, | |
teardown: function() { | |
remove(this, 'movestart.move', jQuery.noop); | |
} | |
}; | |
jQuery.event.special.moveend = { | |
setup: function() { | |
// Bind a noop to movestart. Why? It's the movestart | |
// setup that decides whether other move events are fired. | |
add(this, 'movestart.moveend', jQuery.noop); | |
}, | |
teardown: function() { | |
remove(this, 'movestart.moveend', jQuery.noop); | |
} | |
}; | |
add(document, 'mousedown.move', mousedown); | |
add(document, 'touchstart.move', touchstart); | |
// Make jQuery copy touch event properties over to the jQuery event | |
// object, if they are not already listed. But only do the ones we | |
// really need. IE7/8 do not have Array#indexOf(), but nor do they | |
// have touch events, so let's assume we can ignore them. | |
if (typeof Array.prototype.indexOf === 'function') { | |
(function(jQuery, undefined){ | |
var props = ["changedTouches", "targetTouches"], | |
l = props.length; | |
while (l--) { | |
if (jQuery.event.props.indexOf(props[l]) === -1) { | |
jQuery.event.props.push(props[l]); | |
} | |
} | |
})(jQuery); | |
}; | |
}); | |
// jQuery.event.swipe | |
// 0.5 | |
// Stephen Band | |
// Dependencies | |
// jQuery.event.move 1.2 | |
// One of swipeleft, swiperight, swipeup or swipedown is triggered on | |
// moveend, when the move has covered a threshold ratio of the dimension | |
// of the target node, or has gone really fast. Threshold and velocity | |
// sensitivity changed with: | |
// | |
// jQuery.event.special.swipe.settings.threshold | |
// jQuery.event.special.swipe.settings.sensitivity | |
(function (module) { | |
if (typeof define === 'function' && define.amd) { | |
// AMD. Register as an anonymous module. | |
define(['jquery'], module); | |
} else { | |
// Browser globals | |
module(jQuery); | |
} | |
})(function(jQuery, undefined){ | |
var add = jQuery.event.add, | |
remove = jQuery.event.remove, | |
// Just sugar, so we can have arguments in the same order as | |
// add and remove. | |
trigger = function(node, type, data) { | |
jQuery.event.trigger(type, data, node); | |
}, | |
settings = { | |
// Ratio of distance over target finger must travel to be | |
// considered a swipe. | |
threshold: 0.4, | |
// Faster fingers can travel shorter distances to be considered | |
// swipes. 'sensitivity' controls how much. Bigger is shorter. | |
sensitivity: 6 | |
}; | |
function moveend(e) { | |
var w, h, event; | |
w = e.target.offsetWidth; | |
h = e.target.offsetHeight; | |
// Copy over some useful properties from the move event | |
event = { | |
distX: e.distX, | |
distY: e.distY, | |
velocityX: e.velocityX, | |
velocityY: e.velocityY, | |
finger: e.finger | |
}; | |
// Find out which of the four directions was swiped | |
if (e.distX > e.distY) { | |
if (e.distX > -e.distY) { | |
if (e.distX/w > settings.threshold || e.velocityX * e.distX/w * settings.sensitivity > 1) { | |
event.type = 'swiperight'; | |
trigger(e.currentTarget, event); | |
} | |
} | |
else { | |
if (-e.distY/h > settings.threshold || e.velocityY * e.distY/w * settings.sensitivity > 1) { | |
event.type = 'swipeup'; | |
trigger(e.currentTarget, event); | |
} | |
} | |
} | |
else { | |
if (e.distX > -e.distY) { | |
if (e.distY/h > settings.threshold || e.velocityY * e.distY/w * settings.sensitivity > 1) { | |
event.type = 'swipedown'; | |
trigger(e.currentTarget, event); | |
} | |
} | |
else { | |
if (-e.distX/w > settings.threshold || e.velocityX * e.distX/w * settings.sensitivity > 1) { | |
event.type = 'swipeleft'; | |
trigger(e.currentTarget, event); | |
} | |
} | |
} | |
} | |
function getData(node) { | |
var data = jQuery.data(node, 'event_swipe'); | |
if (!data) { | |
data = { count: 0 }; | |
jQuery.data(node, 'event_swipe', data); | |
} | |
return data; | |
} | |
jQuery.event.special.swipe = | |
jQuery.event.special.swipeleft = | |
jQuery.event.special.swiperight = | |
jQuery.event.special.swipeup = | |
jQuery.event.special.swipedown = { | |
setup: function( data, namespaces, eventHandle ) { | |
var data = getData(this); | |
// If another swipe event is already setup, don't setup again. | |
if (data.count++ > 0) { return; } | |
add(this, 'moveend', moveend); | |
return true; | |
}, | |
teardown: function() { | |
var data = getData(this); | |
// If another swipe event is still setup, don't teardown. | |
if (--data.count > 0) { return; } | |
remove(this, 'moveend', moveend); | |
return true; | |
}, | |
settings: settings | |
}; | |
}); | |
/* | |
* hoverFlow - A Solution to Animation Queue Buildup in jQuery | |
* Version 1.00 | |
* | |
* Copyright (c) 2009 Ralf Stoltze, http://www.2meter3.de/code/hoverFlow/ | |
* Dual-licensed under the MIT and GPL licenses. | |
* http://www.opensource.org/licenses/mit-license.php | |
* http://www.gnu.org/licenses/gpl.html | |
*/ | |
(function($){$.fn.hoverFlow=function(c,d,e,f,g){if($.inArray(c,['mouseover','mouseenter','mouseout','mouseleave'])==-1){return this}var h=typeof e==='object'?e:{complete:g||!g&&f||$.isFunction(e)&&e,duration:e,easing:g&&f||f&&!$.isFunction(f)&&f};h.queue=false;var i=h.complete;h.complete=function(){$(this).dequeue();if($.isFunction(i)){i.call(this)}};return this.each(function(){var b=$(this);if(c=='mouseover'||c=='mouseenter'){b.data('jQuery.hoverFlow',true)}else{b.removeData('jQuery.hoverFlow')}b.queue(function(){var a=(c=='mouseover'||c=='mouseenter')?b.data('jQuery.hoverFlow')!==undefined:b.data('jQuery.hoverFlow')===undefined;if(a){b.animate(d,h)}else{b.queue([])}})})}})(jQuery); | |
/*! | |
* hoverIntent r7 // 2013.03.11 // jQuery 1.9.1+ | |
* http://cherne.net/brian/resources/jquery.hoverIntent.html | |
* | |
* You may use hoverIntent under the terms of the MIT license. | |
* Copyright 2007, 2013 Brian Cherne | |
*/ | |
(function(e){e.fn.hoverIntent=function(t,n,r){var i={interval:100,sensitivity:7,timeout:0};if(typeof t==="object"){i=e.extend(i,t)}else if(e.isFunction(n)){i=e.extend(i,{over:t,out:n,selector:r})}else{i=e.extend(i,{over:t,out:t,selector:n})}var s,o,u,a;var f=function(e){s=e.pageX;o=e.pageY};var l=function(t,n){n.hoverIntent_t=clearTimeout(n.hoverIntent_t);if(Math.abs(u-s)+Math.abs(a-o)<i.sensitivity){e(n).off("mousemove.hoverIntent",f);n.hoverIntent_s=1;return i.over.apply(n,[t])}else{u=s;a=o;n.hoverIntent_t=setTimeout(function(){l(t,n)},i.interval)}};var c=function(e,t){t.hoverIntent_t=clearTimeout(t.hoverIntent_t);t.hoverIntent_s=0;return i.out.apply(t,[e])};var h=function(t){var n=jQuery.extend({},t);var r=this;if(r.hoverIntent_t){r.hoverIntent_t=clearTimeout(r.hoverIntent_t)}if(t.type=="mouseenter"){u=n.pageX;a=n.pageY;e(r).on("mousemove.hoverIntent",f);if(r.hoverIntent_s!=1){r.hoverIntent_t=setTimeout(function(){l(n,r)},i.interval)}}else{e(r).off("mousemove.hoverIntent",f);if(r.hoverIntent_s==1){r.hoverIntent_t=setTimeout(function(){c(n,r)},i.timeout)}}};return this.on({"mouseenter.hoverIntent":h,"mouseleave.hoverIntent":h},i.selector)}})(jQuery) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment