{I" class:ETI"BundledAsset;�FI"logical_path;�TI"spina/admin/application.js;�TI" pathname;�TI"M/Users/bram/apps/spina/app/assets/javascripts/spina/admin/application.js;�FI"content_type;�TI"application/javascript;�TI" mtime;�Tl+ 6UI"length;�Ti��I"digest;�TI"%1d500462e4b84c2fafd15b7c2d18ece2;�FI"source;�TI"��/*! * jQuery JavaScript Library v1.11.2 * http://jquery.com/ * * Includes Sizzle.js * http://sizzlejs.com/ * * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors * Released under the MIT license * http://jquery.org/license * * Date: 2014-12-17T15:27Z */ (function( global, factory ) { if ( typeof module === "object" && typeof module.exports === "object" ) { // For CommonJS and CommonJS-like environments where a proper window is present, // execute the factory and get jQuery // For environments that do not inherently posses a window with a document // (such as Node.js), expose a jQuery-making factory as module.exports // This accentuates the need for the creation of a real window // e.g. var jQuery = require("jquery")(window); // See ticket #14549 for more info module.exports = global.document ? factory( global, true ) : function( w ) { if ( !w.document ) { throw new Error( "jQuery requires a window with a document" ); } return factory( w ); }; } else { factory( global ); } // Pass this if window is not defined yet }(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { // Can't do this because several apps including ASP.NET trace // the stack via arguments.caller.callee and Firefox dies if // you try to trace through "use strict" call chains. (#13335) // Support: Firefox 18+ // var deletedIds = []; var slice = deletedIds.slice; var concat = deletedIds.concat; var push = deletedIds.push; var indexOf = deletedIds.indexOf; var class2type = {}; var toString = class2type.toString; var hasOwn = class2type.hasOwnProperty; var support = {}; var version = "1.11.2", // Define a local copy of jQuery jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' // Need init if jQuery is called (just allow error to be thrown if not included) return new jQuery.fn.init( selector, context ); }, // Support: Android<4.1, IE<9 // Make sure we trim BOM and NBSP rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, // Matches dashed string for camelizing rmsPrefix = /^-ms-/, rdashAlpha = /-([\da-z])/gi, // Used by jQuery.camelCase as callback to replace() fcamelCase = function( all, letter ) { return letter.toUpperCase(); }; jQuery.fn = jQuery.prototype = { // The current version of jQuery being used jquery: version, constructor: jQuery, // Start with an empty selector selector: "", // The default length of a jQuery object is 0 length: 0, toArray: function() { return slice.call( this ); }, // Get the Nth element in the matched element set OR // Get the whole matched element set as a clean array get: function( num ) { return num != null ? // Return just the one element from the set ( num < 0 ? this[ num + this.length ] : this[ num ] ) : // Return all the elements in a clean array slice.call( this ); }, // Take an array of elements and push it onto the stack // (returning the new matched element set) pushStack: function( elems ) { // Build a new jQuery matched element set var ret = jQuery.merge( this.constructor(), elems ); // Add the old object onto the stack (as a reference) ret.prevObject = this; ret.context = this.context; // Return the newly-formed element set return ret; }, // Execute a callback for every element in the matched set. // (You can seed the arguments with an array of args, but this is // only used internally.) each: function( callback, args ) { return jQuery.each( this, callback, args ); }, map: function( callback ) { return this.pushStack( jQuery.map(this, function( elem, i ) { return callback.call( elem, i, elem ); })); }, slice: function() { return this.pushStack( slice.apply( this, arguments ) ); }, first: function() { return this.eq( 0 ); }, last: function() { return this.eq( -1 ); }, eq: function( i ) { var len = this.length, j = +i + ( i < 0 ? len : 0 ); return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); }, end: function() { return this.prevObject || this.constructor(null); }, // For internal use only. // Behaves like an Array's method, not like a jQuery method. push: push, sort: deletedIds.sort, splice: deletedIds.splice }; jQuery.extend = jQuery.fn.extend = function() { var src, copyIsArray, copy, name, options, clone, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; // skip the boolean and the target target = arguments[ i ] || {}; i++; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !jQuery.isFunction(target) ) { target = {}; } // extend jQuery itself if only one argument is passed if ( i === length ) { target = this; i--; } for ( ; i < length; i++ ) { // Only deal with non-null/undefined values if ( (options = arguments[ i ]) != null ) { // Extend the base object for ( name in options ) { src = target[ name ]; copy = options[ name ]; // Prevent never-ending loop if ( target === copy ) { continue; } // Recurse if we're merging plain objects or arrays if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { if ( copyIsArray ) { copyIsArray = false; clone = src && jQuery.isArray(src) ? src : []; } else { clone = src && jQuery.isPlainObject(src) ? src : {}; } // Never move original objects, clone them target[ name ] = jQuery.extend( deep, clone, copy ); // Don't bring in undefined values } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // Return the modified object return target; }; jQuery.extend({ // Unique for each copy of jQuery on the page expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), // Assume jQuery is ready without the ready module isReady: true, error: function( msg ) { throw new Error( msg ); }, noop: function() {}, // See test/unit/core.js for details concerning isFunction. // Since version 1.3, DOM methods and functions like alert // aren't supported. They return false on IE (#2968). isFunction: function( obj ) { return jQuery.type(obj) === "function"; }, isArray: Array.isArray || function( obj ) { return jQuery.type(obj) === "array"; }, isWindow: function( obj ) { /* jshint eqeqeq: false */ return obj != null && obj == obj.window; }, isNumeric: function( obj ) { // parseFloat NaNs numeric-cast false positives (null|true|false|"") // ...but misinterprets leading-number strings, particularly hex literals ("0x...") // subtraction forces infinities to NaN // adding 1 corrects loss of precision from parseFloat (#15100) return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0; }, isEmptyObject: function( obj ) { var name; for ( name in obj ) { return false; } return true; }, isPlainObject: function( obj ) { var key; // Must be an Object. // Because of IE, we also have to check the presence of the constructor property. // Make sure that DOM nodes and window objects don't pass through, as well if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { return false; } try { // Not own constructor property must be Object if ( obj.constructor && !hasOwn.call(obj, "constructor") && !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { return false; } } catch ( e ) { // IE8,9 Will throw exceptions on certain host objects #9897 return false; } // Support: IE<9 // Handle iteration over inherited properties before own properties. if ( support.ownLast ) { for ( key in obj ) { return hasOwn.call( obj, key ); } } // Own properties are enumerated firstly, so to speed up, // if last one is own, then all properties are own. for ( key in obj ) {} return key === undefined || hasOwn.call( obj, key ); }, type: function( obj ) { if ( obj == null ) { return obj + ""; } return typeof obj === "object" || typeof obj === "function" ? class2type[ toString.call(obj) ] || "object" : typeof obj; }, // Evaluates a script in a global context // Workarounds based on findings by Jim Driscoll // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context globalEval: function( data ) { if ( data && jQuery.trim( data ) ) { // We use execScript on Internet Explorer // We use an anonymous function so that context is window // rather than jQuery in Firefox ( window.execScript || function( data ) { window[ "eval" ].call( window, data ); } )( data ); } }, // Convert dashed to camelCase; used by the css and data modules // Microsoft forgot to hump their vendor prefix (#9572) camelCase: function( string ) { return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); }, nodeName: function( elem, name ) { return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); }, // args is for internal usage only each: function( obj, callback, args ) { var value, i = 0, length = obj.length, isArray = isArraylike( obj ); if ( args ) { if ( isArray ) { for ( ; i < length; i++ ) { value = callback.apply( obj[ i ], args ); if ( value === false ) { break; } } } else { for ( i in obj ) { value = callback.apply( obj[ i ], args ); if ( value === false ) { break; } } } // A special, fast, case for the most common use of each } else { if ( isArray ) { for ( ; i < length; i++ ) { value = callback.call( obj[ i ], i, obj[ i ] ); if ( value === false ) { break; } } } else { for ( i in obj ) { value = callback.call( obj[ i ], i, obj[ i ] ); if ( value === false ) { break; } } } } return obj; }, // Support: Android<4.1, IE<9 trim: function( text ) { return text == null ? "" : ( text + "" ).replace( rtrim, "" ); }, // results is for internal usage only makeArray: function( arr, results ) { var ret = results || []; if ( arr != null ) { if ( isArraylike( Object(arr) ) ) { jQuery.merge( ret, typeof arr === "string" ? [ arr ] : arr ); } else { push.call( ret, arr ); } } return ret; }, inArray: function( elem, arr, i ) { var len; if ( arr ) { if ( indexOf ) { return indexOf.call( arr, elem, i ); } len = arr.length; i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; for ( ; i < len; i++ ) { // Skip accessing in sparse arrays if ( i in arr && arr[ i ] === elem ) { return i; } } } return -1; }, merge: function( first, second ) { var len = +second.length, j = 0, i = first.length; while ( j < len ) { first[ i++ ] = second[ j++ ]; } // Support: IE<9 // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists) if ( len !== len ) { while ( second[j] !== undefined ) { first[ i++ ] = second[ j++ ]; } } first.length = i; return first; }, grep: function( elems, callback, invert ) { var callbackInverse, matches = [], i = 0, length = elems.length, callbackExpect = !invert; // Go through the array, only saving the items // that pass the validator function for ( ; i < length; i++ ) { callbackInverse = !callback( elems[ i ], i ); if ( callbackInverse !== callbackExpect ) { matches.push( elems[ i ] ); } } return matches; }, // arg is for internal usage only map: function( elems, callback, arg ) { var value, i = 0, length = elems.length, isArray = isArraylike( elems ), ret = []; // Go through the array, translating each of the items to their new values if ( isArray ) { for ( ; i < length; i++ ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret.push( value ); } } // Go through every key on the object, } else { for ( i in elems ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret.push( value ); } } } // Flatten any nested arrays return concat.apply( [], ret ); }, // A global GUID counter for objects guid: 1, // Bind a function to a context, optionally partially applying any // arguments. proxy: function( fn, context ) { var args, proxy, tmp; if ( typeof context === "string" ) { tmp = fn[ context ]; context = fn; fn = tmp; } // Quick check to determine if target is callable, in the spec // this throws a TypeError, but we will just return undefined. if ( !jQuery.isFunction( fn ) ) { return undefined; } // Simulated bind args = slice.call( arguments, 2 ); proxy = function() { return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); }; // Set the guid of unique handler to the same of original handler, so it can be removed proxy.guid = fn.guid = fn.guid || jQuery.guid++; return proxy; }, now: function() { return +( new Date() ); }, // jQuery.support is not used in Core but other projects attach their // properties to it so it needs to exist. support: support }); // Populate the class2type map jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { class2type[ "[object " + name + "]" ] = name.toLowerCase(); }); function isArraylike( obj ) { var length = obj.length, type = jQuery.type( obj ); if ( type === "function" || jQuery.isWindow( obj ) ) { return false; } if ( obj.nodeType === 1 && length ) { return true; } return type === "array" || length === 0 || typeof length === "number" && length > 0 && ( length - 1 ) in obj; } var Sizzle = /*! * Sizzle CSS Selector Engine v2.2.0-pre * http://sizzlejs.com/ * * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors * Released under the MIT license * http://jquery.org/license * * Date: 2014-12-16 */ (function( window ) { var i, support, Expr, getText, isXML, tokenize, compile, select, outermostContext, sortInput, hasDuplicate, // Local document vars setDocument, document, docElem, documentIsHTML, rbuggyQSA, rbuggyMatches, matches, contains, // Instance-specific data expando = "sizzle" + 1 * new Date(), preferredDoc = window.document, dirruns = 0, done = 0, classCache = createCache(), tokenCache = createCache(), compilerCache = createCache(), sortOrder = function( a, b ) { if ( a === b ) { hasDuplicate = true; } return 0; }, // General-purpose constants MAX_NEGATIVE = 1 << 31, // Instance methods hasOwn = ({}).hasOwnProperty, arr = [], pop = arr.pop, push_native = arr.push, push = arr.push, slice = arr.slice, // Use a stripped-down indexOf as it's faster than native // http://jsperf.com/thor-indexof-vs-for/5 indexOf = function( list, elem ) { var i = 0, len = list.length; for ( ; i < len; i++ ) { if ( list[i] === elem ) { return i; } } return -1; }, booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", // Regular expressions // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace whitespace = "[\\x20\\t\\r\\n\\f]", // http://www.w3.org/TR/css3-syntax/#characters characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", // Loosely modeled on CSS identifier characters // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier identifier = characterEncoding.replace( "w", "w#" ), // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace + // Operator (capture 2) "*([*^$|!~]?=)" + whitespace + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + "*\\]", pseudos = ":(" + characterEncoding + ")(?:\\((" + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: // 1. quoted (capture 3; capture 4 or capture 5) "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + // 2. simple (capture 6) "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + // 3. anything else (capture 2) ".*" + ")\\)|)", // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter rwhitespace = new RegExp( whitespace + "+", "g" ), rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), rpseudo = new RegExp( pseudos ), ridentifier = new RegExp( "^" + identifier + "$" ), matchExpr = { "ID": new RegExp( "^#(" + characterEncoding + ")" ), "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), "ATTR": new RegExp( "^" + attributes ), "PSEUDO": new RegExp( "^" + pseudos ), "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), // For use in libraries implementing .is() // We use this for POS matching in `select` "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) }, rinputs = /^(?:input|select|textarea|button)$/i, rheader = /^h\d$/i, rnative = /^[^{]+\{\s*\[native \w/, // Easily-parseable/retrievable ID or TAG or CLASS selectors rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, rsibling = /[+~]/, rescape = /'|\\/g, // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), funescape = function( _, escaped, escapedWhitespace ) { var high = "0x" + escaped - 0x10000; // NaN means non-codepoint // Support: Firefox<24 // Workaround erroneous numeric interpretation of +"0x" return high !== high || escapedWhitespace ? escaped : high < 0 ? // BMP codepoint String.fromCharCode( high + 0x10000 ) : // Supplemental Plane codepoint (surrogate pair) String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); }, // Used for iframes // See setDocument() // Removing the function wrapper causes a "Permission Denied" // error in IE unloadHandler = function() { setDocument(); }; // Optimize for push.apply( _, NodeList ) try { push.apply( (arr = slice.call( preferredDoc.childNodes )), preferredDoc.childNodes ); // Support: Android<4.0 // Detect silently failing push.apply arr[ preferredDoc.childNodes.length ].nodeType; } catch ( e ) { push = { apply: arr.length ? // Leverage slice if possible function( target, els ) { push_native.apply( target, slice.call(els) ); } : // Support: IE<9 // Otherwise append directly function( target, els ) { var j = target.length, i = 0; // Can't trust NodeList.length while ( (target[j++] = els[i++]) ) {} target.length = j - 1; } }; } function Sizzle( selector, context, results, seed ) { var match, elem, m, nodeType, // QSA vars i, groups, old, nid, newContext, newSelector; if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { setDocument( context ); } context = context || document; results = results || []; nodeType = context.nodeType; if ( typeof selector !== "string" || !selector || nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { return results; } if ( !seed && documentIsHTML ) { // Try to shortcut find operations when possible (e.g., not under DocumentFragment) if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { // Speed-up: Sizzle("#ID") if ( (m = match[1]) ) { if ( nodeType === 9 ) { elem = context.getElementById( m ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document (jQuery #6963) if ( elem && elem.parentNode ) { // Handle the case where IE, Opera, and Webkit return items // by name instead of ID if ( elem.id === m ) { results.push( elem ); return results; } } else { return results; } } else { // Context is not a document if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && contains( context, elem ) && elem.id === m ) { results.push( elem ); return results; } } // Speed-up: Sizzle("TAG") } else if ( match[2] ) { push.apply( results, context.getElementsByTagName( selector ) ); return results; // Speed-up: Sizzle(".CLASS") } else if ( (m = match[3]) && support.getElementsByClassName ) { push.apply( results, context.getElementsByClassName( m ) ); return results; } } // QSA path if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { nid = old = expando; newContext = context; newSelector = nodeType !== 1 && selector; // qSA works strangely on Element-rooted queries // We can work around this by specifying an extra ID on the root // and working up from there (Thanks to Andrew Dupont for the technique) // IE 8 doesn't work on object elements if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { groups = tokenize( selector ); if ( (old = context.getAttribute("id")) ) { nid = old.replace( rescape, "\\$&" ); } else { context.setAttribute( "id", nid ); } nid = "[id='" + nid + "'] "; i = groups.length; while ( i-- ) { groups[i] = nid + toSelector( groups[i] ); } newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; newSelector = groups.join(","); } if ( newSelector ) { try { push.apply( results, newContext.querySelectorAll( newSelector ) ); return results; } catch(qsaError) { } finally { if ( !old ) { context.removeAttribute("id"); } } } } } // All others return select( selector.replace( rtrim, "$1" ), context, results, seed ); } /** * Create key-value caches of limited size * @returns {Function(string, Object)} Returns the Object data after storing it on itself with * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) * deleting the oldest entry */ function createCache() { var keys = []; function cache( key, value ) { // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) if ( keys.push( key + " " ) > Expr.cacheLength ) { // Only keep the most recent entries delete cache[ keys.shift() ]; } return (cache[ key + " " ] = value); } return cache; } /** * Mark a function for special use by Sizzle * @param {Function} fn The function to mark */ function markFunction( fn ) { fn[ expando ] = true; return fn; } /** * Support testing using an element * @param {Function} fn Passed the created div and expects a boolean result */ function assert( fn ) { var div = document.createElement("div"); try { return !!fn( div ); } catch (e) { return false; } finally { // Remove from its parent by default if ( div.parentNode ) { div.parentNode.removeChild( div ); } // release memory in IE div = null; } } /** * Adds the same handler for all of the specified attrs * @param {String} attrs Pipe-separated list of attributes * @param {Function} handler The method that will be applied */ function addHandle( attrs, handler ) { var arr = attrs.split("|"), i = attrs.length; while ( i-- ) { Expr.attrHandle[ arr[i] ] = handler; } } /** * Checks document order of two siblings * @param {Element} a * @param {Element} b * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b */ function siblingCheck( a, b ) { var cur = b && a, diff = cur && a.nodeType === 1 && b.nodeType === 1 && ( ~b.sourceIndex || MAX_NEGATIVE ) - ( ~a.sourceIndex || MAX_NEGATIVE ); // Use IE sourceIndex if available on both nodes if ( diff ) { return diff; } // Check if b follows a if ( cur ) { while ( (cur = cur.nextSibling) ) { if ( cur === b ) { return -1; } } } return a ? 1 : -1; } /** * Returns a function to use in pseudos for input types * @param {String} type */ function createInputPseudo( type ) { return function( elem ) { var name = elem.nodeName.toLowerCase(); return name === "input" && elem.type === type; }; } /** * Returns a function to use in pseudos for buttons * @param {String} type */ function createButtonPseudo( type ) { return function( elem ) { var name = elem.nodeName.toLowerCase(); return (name === "input" || name === "button") && elem.type === type; }; } /** * Returns a function to use in pseudos for positionals * @param {Function} fn */ function createPositionalPseudo( fn ) { return markFunction(function( argument ) { argument = +argument; return markFunction(function( seed, matches ) { var j, matchIndexes = fn( [], seed.length, argument ), i = matchIndexes.length; // Match elements found at the specified indexes while ( i-- ) { if ( seed[ (j = matchIndexes[i]) ] ) { seed[j] = !(matches[j] = seed[j]); } } }); }); } /** * Checks a node for validity as a Sizzle context * @param {Element|Object=} context * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value */ function testContext( context ) { return context && typeof context.getElementsByTagName !== "undefined" && context; } // Expose support vars for convenience support = Sizzle.support = {}; /** * Detects XML nodes * @param {Element|Object} elem An element or a document * @returns {Boolean} True iff elem is a non-HTML XML node */ isXML = Sizzle.isXML = function( elem ) { // documentElement is verified for cases where it doesn't yet exist // (such as loading iframes in IE - #4833) var documentElement = elem && (elem.ownerDocument || elem).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; }; /** * Sets document-related variables once based on the current document * @param {Element|Object} [doc] An element or document object to use to set the document * @returns {Object} Returns the current document */ setDocument = Sizzle.setDocument = function( node ) { var hasCompare, parent, doc = node ? node.ownerDocument || node : preferredDoc; // If no document and documentElement is available, return if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { return document; } // Set our document document = doc; docElem = doc.documentElement; parent = doc.defaultView; // Support: IE>8 // If iframe document is assigned to "document" variable and if iframe has been reloaded, // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 // IE6-8 do not support the defaultView property so parent will be undefined if ( parent && parent !== parent.top ) { // IE11 does not have attachEvent, so all must suffer if ( parent.addEventListener ) { parent.addEventListener( "unload", unloadHandler, false ); } else if ( parent.attachEvent ) { parent.attachEvent( "onunload", unloadHandler ); } } /* Support tests ---------------------------------------------------------------------- */ documentIsHTML = !isXML( doc ); /* Attributes ---------------------------------------------------------------------- */ // Support: IE<8 // Verify that getAttribute really returns attributes and not properties // (excepting IE8 booleans) support.attributes = assert(function( div ) { div.className = "i"; return !div.getAttribute("className"); }); /* getElement(s)By* ---------------------------------------------------------------------- */ // Check if getElementsByTagName("*") returns only elements support.getElementsByTagName = assert(function( div ) { div.appendChild( doc.createComment("") ); return !div.getElementsByTagName("*").length; }); // Support: IE<9 support.getElementsByClassName = rnative.test( doc.getElementsByClassName ); // Support: IE<10 // Check if getElementById returns elements by name // The broken getElementById methods don't pick up programatically-set names, // so use a roundabout getElementsByName test support.getById = assert(function( div ) { docElem.appendChild( div ).id = expando; return !doc.getElementsByName || !doc.getElementsByName( expando ).length; }); // ID find and filter if ( support.getById ) { Expr.find["ID"] = function( id, context ) { if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { var m = context.getElementById( id ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 return m && m.parentNode ? [ m ] : []; } }; Expr.filter["ID"] = function( id ) { var attrId = id.replace( runescape, funescape ); return function( elem ) { return elem.getAttribute("id") === attrId; }; }; } else { // Support: IE6/7 // getElementById is not reliable as a find shortcut delete Expr.find["ID"]; Expr.filter["ID"] = function( id ) { var attrId = id.replace( runescape, funescape ); return function( elem ) { var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); return node && node.value === attrId; }; }; } // Tag Expr.find["TAG"] = support.getElementsByTagName ? function( tag, context ) { if ( typeof context.getElementsByTagName !== "undefined" ) { return context.getElementsByTagName( tag ); // DocumentFragment nodes don't have gEBTN } else if ( support.qsa ) { return context.querySelectorAll( tag ); } } : function( tag, context ) { var elem, tmp = [], i = 0, // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too results = context.getElementsByTagName( tag ); // Filter out possible comments if ( tag === "*" ) { while ( (elem = results[i++]) ) { if ( elem.nodeType === 1 ) { tmp.push( elem ); } } return tmp; } return results; }; // Class Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { if ( documentIsHTML ) { return context.getElementsByClassName( className ); } }; /* QSA/matchesSelector ---------------------------------------------------------------------- */ // QSA and matchesSelector support // matchesSelector(:active) reports false when true (IE9/Opera 11.5) rbuggyMatches = []; // qSa(:focus) reports false when true (Chrome 21) // We allow this because of a bug in IE8/9 that throws an error // whenever `document.activeElement` is accessed on an iframe // So, we allow :focus to pass through QSA all the time to avoid the IE error // See http://bugs.jquery.com/ticket/13378 rbuggyQSA = []; if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { // Build QSA regex // Regex strategy adopted from Diego Perini assert(function( div ) { // Select is set to empty string on purpose // This is to test IE's treatment of not explicitly // setting a boolean content attribute, // since its presence should be enough // http://bugs.jquery.com/ticket/12359 docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" + "<select id='" + expando + "-\f]' msallowcapture=''>" + "<option selected=''></option></select>"; // Support: IE8, Opera 11-12.16 // Nothing should be selected when empty strings follow ^= or $= or *= // The test attribute must be unknown in Opera but "safe" for WinRT // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section if ( div.querySelectorAll("[msallowcapture^='']").length ) { rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); } // Support: IE8 // Boolean attributes and "value" are not treated correctly if ( !div.querySelectorAll("[selected]").length ) { rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); } // Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+ if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) { rbuggyQSA.push("~="); } // Webkit/Opera - :checked should return selected option elements // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked // IE8 throws error here and will not see later tests if ( !div.querySelectorAll(":checked").length ) { rbuggyQSA.push(":checked"); } // Support: Safari 8+, iOS 8+ // https://bugs.webkit.org/show_bug.cgi?id=136851 // In-page `selector#id sibing-combinator selector` fails if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) { rbuggyQSA.push(".#.+[+~]"); } }); assert(function( div ) { // Support: Windows 8 Native Apps // The type and name attributes are restricted during .innerHTML assignment var input = doc.createElement("input"); input.setAttribute( "type", "hidden" ); div.appendChild( input ).setAttribute( "name", "D" ); // Support: IE8 // Enforce case-sensitivity of name attribute if ( div.querySelectorAll("[name=d]").length ) { rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); } // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) // IE8 throws error here and will not see later tests if ( !div.querySelectorAll(":enabled").length ) { rbuggyQSA.push( ":enabled", ":disabled" ); } // Opera 10-11 does not throw on post-comma invalid pseudos div.querySelectorAll("*,:x"); rbuggyQSA.push(",.*:"); }); } if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || docElem.webkitMatchesSelector || docElem.mozMatchesSelector || docElem.oMatchesSelector || docElem.msMatchesSelector) )) ) { assert(function( div ) { // Check to see if it's possible to do matchesSelector // on a disconnected node (IE 9) support.disconnectedMatch = matches.call( div, "div" ); // This should fail with an exception // Gecko does not error, returns false instead matches.call( div, "[s!='']:x" ); rbuggyMatches.push( "!=", pseudos ); }); } rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); /* Contains ---------------------------------------------------------------------- */ hasCompare = rnative.test( docElem.compareDocumentPosition ); // Element contains another // Purposefully does not implement inclusive descendent // As in, an element does not contain itself contains = hasCompare || rnative.test( docElem.contains ) ? function( a, b ) { var adown = a.nodeType === 9 ? a.documentElement : a, bup = b && b.parentNode; return a === bup || !!( bup && bup.nodeType === 1 && ( adown.contains ? adown.contains( bup ) : a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 )); } : function( a, b ) { if ( b ) { while ( (b = b.parentNode) ) { if ( b === a ) { return true; } } } return false; }; /* Sorting ---------------------------------------------------------------------- */ // Document order sorting sortOrder = hasCompare ? function( a, b ) { // Flag for duplicate removal if ( a === b ) { hasDuplicate = true; return 0; } // Sort on method existence if only one input has compareDocumentPosition var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; if ( compare ) { return compare; } // Calculate position if both inputs belong to the same document compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? a.compareDocumentPosition( b ) : // Otherwise we know they are disconnected 1; // Disconnected nodes if ( compare & 1 || (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { // Choose the first element that is related to our preferred document if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { return -1; } if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { return 1; } // Maintain original order return sortInput ? ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : 0; } return compare & 4 ? -1 : 1; } : function( a, b ) { // Exit early if the nodes are identical if ( a === b ) { hasDuplicate = true; return 0; } var cur, i = 0, aup = a.parentNode, bup = b.parentNode, ap = [ a ], bp = [ b ]; // Parentless nodes are either documents or disconnected if ( !aup || !bup ) { return a === doc ? -1 : b === doc ? 1 : aup ? -1 : bup ? 1 : sortInput ? ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : 0; // If the nodes are siblings, we can do a quick check } else if ( aup === bup ) { return siblingCheck( a, b ); } // Otherwise we need full lists of their ancestors for comparison cur = a; while ( (cur = cur.parentNode) ) { ap.unshift( cur ); } cur = b; while ( (cur = cur.parentNode) ) { bp.unshift( cur ); } // Walk down the tree looking for a discrepancy while ( ap[i] === bp[i] ) { i++; } return i ? // Do a sibling check if the nodes have a common ancestor siblingCheck( ap[i], bp[i] ) : // Otherwise nodes in our document sort first ap[i] === preferredDoc ? -1 : bp[i] === preferredDoc ? 1 : 0; }; return doc; }; Sizzle.matches = function( expr, elements ) { return Sizzle( expr, null, null, elements ); }; Sizzle.matchesSelector = function( elem, expr ) { // Set document vars if needed if ( ( elem.ownerDocument || elem ) !== document ) { setDocument( elem ); } // Make sure that attribute selectors are quoted expr = expr.replace( rattributeQuotes, "='$1']" ); if ( support.matchesSelector && documentIsHTML && ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { try { var ret = matches.call( elem, expr ); // IE 9's matchesSelector returns false on disconnected nodes if ( ret || support.disconnectedMatch || // As well, disconnected nodes are said to be in a document // fragment in IE 9 elem.document && elem.document.nodeType !== 11 ) { return ret; } } catch (e) {} } return Sizzle( expr, document, null, [ elem ] ).length > 0; }; Sizzle.contains = function( context, elem ) { // Set document vars if needed if ( ( context.ownerDocument || context ) !== document ) { setDocument( context ); } return contains( context, elem ); }; Sizzle.attr = function( elem, name ) { // Set document vars if needed if ( ( elem.ownerDocument || elem ) !== document ) { setDocument( elem ); } var fn = Expr.attrHandle[ name.toLowerCase() ], // Don't get fooled by Object.prototype properties (jQuery #13807) val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? fn( elem, name, !documentIsHTML ) : undefined; return val !== undefined ? val : support.attributes || !documentIsHTML ? elem.getAttribute( name ) : (val = elem.getAttributeNode(name)) && val.specified ? val.value : null; }; Sizzle.error = function( msg ) { throw new Error( "Syntax error, unrecognized expression: " + msg ); }; /** * Document sorting and removing duplicates * @param {ArrayLike} results */ Sizzle.uniqueSort = function( results ) { var elem, duplicates = [], j = 0, i = 0; // Unless we *know* we can detect duplicates, assume their presence hasDuplicate = !support.detectDuplicates; sortInput = !support.sortStable && results.slice( 0 ); results.sort( sortOrder ); if ( hasDuplicate ) { while ( (elem = results[i++]) ) { if ( elem === results[ i ] ) { j = duplicates.push( i ); } } while ( j-- ) { results.splice( duplicates[ j ], 1 ); } } // Clear input after sorting to release objects // See https://github.com/jquery/sizzle/pull/225 sortInput = null; return results; }; /** * Utility function for retrieving the text value of an array of DOM nodes * @param {Array|Element} elem */ getText = Sizzle.getText = function( elem ) { var node, ret = "", i = 0, nodeType = elem.nodeType; if ( !nodeType ) { // If no nodeType, this is expected to be an array while ( (node = elem[i++]) ) { // Do not traverse comment nodes ret += getText( node ); } } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { // Use textContent for elements // innerText usage removed for consistency of new lines (jQuery #11153) if ( typeof elem.textContent === "string" ) { return elem.textContent; } else { // Traverse its children for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { ret += getText( elem ); } } } else if ( nodeType === 3 || nodeType === 4 ) { return elem.nodeValue; } // Do not include comment or processing instruction nodes return ret; }; Expr = Sizzle.selectors = { // Can be adjusted by the user cacheLength: 50, createPseudo: markFunction, match: matchExpr, attrHandle: {}, find: {}, relative: { ">": { dir: "parentNode", first: true }, " ": { dir: "parentNode" }, "+": { dir: "previousSibling", first: true }, "~": { dir: "previousSibling" } }, preFilter: { "ATTR": function( match ) { match[1] = match[1].replace( runescape, funescape ); // Move the given value to match[3] whether quoted or unquoted match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); if ( match[2] === "~=" ) { match[3] = " " + match[3] + " "; } return match.slice( 0, 4 ); }, "CHILD": function( match ) { /* matches from matchExpr["CHILD"] 1 type (only|nth|...) 2 what (child|of-type) 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) 4 xn-component of xn+y argument ([+-]?\d*n|) 5 sign of xn-component 6 x of xn-component 7 sign of y-component 8 y of y-component */ match[1] = match[1].toLowerCase(); if ( match[1].slice( 0, 3 ) === "nth" ) { // nth-* requires argument if ( !match[3] ) { Sizzle.error( match[0] ); } // numeric x and y parameters for Expr.filter.CHILD // remember that false/true cast respectively to 0/1 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); // other types prohibit arguments } else if ( match[3] ) { Sizzle.error( match[0] ); } return match; }, "PSEUDO": function( match ) { var excess, unquoted = !match[6] && match[2]; if ( matchExpr["CHILD"].test( match[0] ) ) { return null; } // Accept quoted arguments as-is if ( match[3] ) { match[2] = match[4] || match[5] || ""; // Strip excess characters from unquoted arguments } else if ( unquoted && rpseudo.test( unquoted ) && // Get excess from tokenize (recursively) (excess = tokenize( unquoted, true )) && // advance to the next closing parenthesis (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { // excess is a negative index match[0] = match[0].slice( 0, excess ); match[2] = unquoted.slice( 0, excess ); } // Return only captures needed by the pseudo filter method (type and argument) return match.slice( 0, 3 ); } }, filter: { "TAG": function( nodeNameSelector ) { var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); return nodeNameSelector === "*" ? function() { return true; } : function( elem ) { return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; }; }, "CLASS": function( className ) { var pattern = classCache[ className + " " ]; return pattern || (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && classCache( className, function( elem ) { return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); }); }, "ATTR": function( name, operator, check ) { return function( elem ) { var result = Sizzle.attr( elem, name ); if ( result == null ) { return operator === "!="; } if ( !operator ) { return true; } result += ""; return operator === "=" ? result === check : operator === "!=" ? result !== check : operator === "^=" ? check && result.indexOf( check ) === 0 : operator === "*=" ? check && result.indexOf( check ) > -1 : operator === "$=" ? check && result.slice( -check.length ) === check : operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : false; }; }, "CHILD": function( type, what, argument, first, last ) { var simple = type.slice( 0, 3 ) !== "nth", forward = type.slice( -4 ) !== "last", ofType = what === "of-type"; return first === 1 && last === 0 ? // Shortcut for :nth-*(n) function( elem ) { return !!elem.parentNode; } : function( elem, context, xml ) { var cache, outerCache, node, diff, nodeIndex, start, dir = simple !== forward ? "nextSibling" : "previousSibling", parent = elem.parentNode, name = ofType && elem.nodeName.toLowerCase(), useCache = !xml && !ofType; if ( parent ) { // :(first|last|only)-(child|of-type) if ( simple ) { while ( dir ) { node = elem; while ( (node = node[ dir ]) ) { if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { return false; } } // Reverse direction for :only-* (if we haven't yet done so) start = dir = type === "only" && !start && "nextSibling"; } return true; } start = [ forward ? parent.firstChild : parent.lastChild ]; // non-xml :nth-child(...) stores cache data on `parent` if ( forward && useCache ) { // Seek `elem` from a previously-cached index outerCache = parent[ expando ] || (parent[ expando ] = {}); cache = outerCache[ type ] || []; nodeIndex = cache[0] === dirruns && cache[1]; diff = cache[0] === dirruns && cache[2]; node = nodeIndex && parent.childNodes[ nodeIndex ]; while ( (node = ++nodeIndex && node && node[ dir ] || // Fallback to seeking `elem` from the start (diff = nodeIndex = 0) || start.pop()) ) { // When found, cache indexes on `parent` and break if ( node.nodeType === 1 && ++diff && node === elem ) { outerCache[ type ] = [ dirruns, nodeIndex, diff ]; break; } } // Use previously-cached element index if available } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { diff = cache[1]; // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) } else { // Use the same loop as above to seek `elem` from the start while ( (node = ++nodeIndex && node && node[ dir ] || (diff = nodeIndex = 0) || start.pop()) ) { if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { // Cache the index of each encountered element if ( useCache ) { (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; } if ( node === elem ) { break; } } } } // Incorporate the offset, then check against cycle size diff -= last; return diff === first || ( diff % first === 0 && diff / first >= 0 ); } }; }, "PSEUDO": function( pseudo, argument ) { // pseudo-class names are case-insensitive // http://www.w3.org/TR/selectors/#pseudo-classes // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters // Remember that setFilters inherits from pseudos var args, fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || Sizzle.error( "unsupported pseudo: " + pseudo ); // The user may use createPseudo to indicate that // arguments are needed to create the filter function // just as Sizzle does if ( fn[ expando ] ) { return fn( argument ); } // But maintain support for old signatures if ( fn.length > 1 ) { args = [ pseudo, pseudo, "", argument ]; return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? markFunction(function( seed, matches ) { var idx, matched = fn( seed, argument ), i = matched.length; while ( i-- ) { idx = indexOf( seed, matched[i] ); seed[ idx ] = !( matches[ idx ] = matched[i] ); } }) : function( elem ) { return fn( elem, 0, args ); }; } return fn; } }, pseudos: { // Potentially complex pseudos "not": markFunction(function( selector ) { // Trim the selector passed to compile // to avoid treating leading and trailing // spaces as combinators var input = [], results = [], matcher = compile( selector.replace( rtrim, "$1" ) ); return matcher[ expando ] ? markFunction(function( seed, matches, context, xml ) { var elem, unmatched = matcher( seed, null, xml, [] ), i = seed.length; // Match elements unmatched by `matcher` while ( i-- ) { if ( (elem = unmatched[i]) ) { seed[i] = !(matches[i] = elem); } } }) : function( elem, context, xml ) { input[0] = elem; matcher( input, null, xml, results ); // Don't keep the element (issue #299) input[0] = null; return !results.pop(); }; }), "has": markFunction(function( selector ) { return function( elem ) { return Sizzle( selector, elem ).length > 0; }; }), "contains": markFunction(function( text ) { text = text.replace( runescape, funescape ); return function( elem ) { return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; }; }), // "Whether an element is represented by a :lang() selector // is based solely on the element's language value // being equal to the identifier C, // or beginning with the identifier C immediately followed by "-". // The matching of C against the element's language value is performed case-insensitively. // The identifier C does not have to be a valid language name." // http://www.w3.org/TR/selectors/#lang-pseudo "lang": markFunction( function( lang ) { // lang value must be a valid identifier if ( !ridentifier.test(lang || "") ) { Sizzle.error( "unsupported lang: " + lang ); } lang = lang.replace( runescape, funescape ).toLowerCase(); return function( elem ) { var elemLang; do { if ( (elemLang = documentIsHTML ? elem.lang : elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { elemLang = elemLang.toLowerCase(); return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; } } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); return false; }; }), // Miscellaneous "target": function( elem ) { var hash = window.location && window.location.hash; return hash && hash.slice( 1 ) === elem.id; }, "root": function( elem ) { return elem === docElem; }, "focus": function( elem ) { return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); }, // Boolean properties "enabled": function( elem ) { return elem.disabled === false; }, "disabled": function( elem ) { return elem.disabled === true; }, "checked": function( elem ) { // In CSS3, :checked should return both checked and selected elements // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked var nodeName = elem.nodeName.toLowerCase(); return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); }, "selected": function( elem ) { // Accessing this property makes selected-by-default // options in Safari work properly if ( elem.parentNode ) { elem.parentNode.selectedIndex; } return elem.selected === true; }, // Contents "empty": function( elem ) { // http://www.w3.org/TR/selectors/#empty-pseudo // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), // but not by others (comment: 8; processing instruction: 7; etc.) // nodeType < 6 works because attributes (2) do not appear as children for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { if ( elem.nodeType < 6 ) { return false; } } return true; }, "parent": function( elem ) { return !Expr.pseudos["empty"]( elem ); }, // Element/input types "header": function( elem ) { return rheader.test( elem.nodeName ); }, "input": function( elem ) { return rinputs.test( elem.nodeName ); }, "button": function( elem ) { var name = elem.nodeName.toLowerCase(); return name === "input" && elem.type === "button" || name === "button"; }, "text": function( elem ) { var attr; return elem.nodeName.toLowerCase() === "input" && elem.type === "text" && // Support: IE<8 // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); }, // Position-in-collection "first": createPositionalPseudo(function() { return [ 0 ]; }), "last": createPositionalPseudo(function( matchIndexes, length ) { return [ length - 1 ]; }), "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { return [ argument < 0 ? argument + length : argument ]; }), "even": createPositionalPseudo(function( matchIndexes, length ) { var i = 0; for ( ; i < length; i += 2 ) { matchIndexes.push( i ); } return matchIndexes; }), "odd": createPositionalPseudo(function( matchIndexes, length ) { var i = 1; for ( ; i < length; i += 2 ) { matchIndexes.push( i ); } return matchIndexes; }), "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { var i = argument < 0 ? argument + length : argument; for ( ; --i >= 0; ) { matchIndexes.push( i ); } return matchIndexes; }), "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { var i = argument < 0 ? argument + length : argument; for ( ; ++i < length; ) { matchIndexes.push( i ); } return matchIndexes; }) } }; Expr.pseudos["nth"] = Expr.pseudos["eq"]; // Add button/input type pseudos for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { Expr.pseudos[ i ] = createInputPseudo( i ); } for ( i in { submit: true, reset: true } ) { Expr.pseudos[ i ] = createButtonPseudo( i ); } // Easy API for creating new setFilters function setFilters() {} setFilters.prototype = Expr.filters = Expr.pseudos; Expr.setFilters = new setFilters(); tokenize = Sizzle.tokenize = function( selector, parseOnly ) { var matched, match, tokens, type, soFar, groups, preFilters, cached = tokenCache[ selector + " " ]; if ( cached ) { return parseOnly ? 0 : cached.slice( 0 ); } soFar = selector; groups = []; preFilters = Expr.preFilter; while ( soFar ) { // Comma and first run if ( !matched || (match = rcomma.exec( soFar )) ) { if ( match ) { // Don't consume trailing commas as valid soFar = soFar.slice( match[0].length ) || soFar; } groups.push( (tokens = []) ); } matched = false; // Combinators if ( (match = rcombinators.exec( soFar )) ) { matched = match.shift(); tokens.push({ value: matched, // Cast descendant combinators to space type: match[0].replace( rtrim, " " ) }); soFar = soFar.slice( matched.length ); } // Filters for ( type in Expr.filter ) { if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || (match = preFilters[ type ]( match ))) ) { matched = match.shift(); tokens.push({ value: matched, type: type, matches: match }); soFar = soFar.slice( matched.length ); } } if ( !matched ) { break; } } // Return the length of the invalid excess // if we're just parsing // Otherwise, throw an error or return tokens return parseOnly ? soFar.length : soFar ? Sizzle.error( selector ) : // Cache the tokens tokenCache( selector, groups ).slice( 0 ); }; function toSelector( tokens ) { var i = 0, len = tokens.length, selector = ""; for ( ; i < len; i++ ) { selector += tokens[i].value; } return selector; } function addCombinator( matcher, combinator, base ) { var dir = combinator.dir, checkNonElements = base && dir === "parentNode", doneName = done++; return combinator.first ? // Check against closest ancestor/preceding element function( elem, context, xml ) { while ( (elem = elem[ dir ]) ) { if ( elem.nodeType === 1 || checkNonElements ) { return matcher( elem, context, xml ); } } } : // Check against all ancestor/preceding elements function( elem, context, xml ) { var oldCache, outerCache, newCache = [ dirruns, doneName ]; // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching if ( xml ) { while ( (elem = elem[ dir ]) ) { if ( elem.nodeType === 1 || checkNonElements ) { if ( matcher( elem, context, xml ) ) { return true; } } } } else { while ( (elem = elem[ dir ]) ) { if ( elem.nodeType === 1 || checkNonElements ) { outerCache = elem[ expando ] || (elem[ expando ] = {}); if ( (oldCache = outerCache[ dir ]) && oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { // Assign to newCache so results back-propagate to previous elements return (newCache[ 2 ] = oldCache[ 2 ]); } else { // Reuse newcache so results back-propagate to previous elements outerCache[ dir ] = newCache; // A match means we're done; a fail means we have to keep checking if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { return true; } } } } } }; } function elementMatcher( matchers ) { return matchers.length > 1 ? function( elem, context, xml ) { var i = matchers.length; while ( i-- ) { if ( !matchers[i]( elem, context, xml ) ) { return false; } } return true; } : matchers[0]; } function multipleContexts( selector, contexts, results ) { var i = 0, len = contexts.length; for ( ; i < len; i++ ) { Sizzle( selector, contexts[i], results ); } return results; } function condense( unmatched, map, filter, context, xml ) { var elem, newUnmatched = [], i = 0, len = unmatched.length, mapped = map != null; for ( ; i < len; i++ ) { if ( (elem = unmatched[i]) ) { if ( !filter || filter( elem, context, xml ) ) { newUnmatched.push( elem ); if ( mapped ) { map.push( i ); } } } } return newUnmatched; } function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { if ( postFilter && !postFilter[ expando ] ) { postFilter = setMatcher( postFilter ); } if ( postFinder && !postFinder[ expando ] ) { postFinder = setMatcher( postFinder, postSelector ); } return markFunction(function( seed, results, context, xml ) { var temp, i, elem, preMap = [], postMap = [], preexisting = results.length, // Get initial elements from seed or context elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), // Prefilter to get matcher input, preserving a map for seed-results synchronization matcherIn = preFilter && ( seed || !selector ) ? condense( elems, preMap, preFilter, context, xml ) : elems, matcherOut = matcher ? // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, postFinder || ( seed ? preFilter : preexisting || postFilter ) ? // ...intermediate processing is necessary [] : // ...otherwise use results directly results : matcherIn; // Find primary matches if ( matcher ) { matcher( matcherIn, matcherOut, context, xml ); } // Apply postFilter if ( postFilter ) { temp = condense( matcherOut, postMap ); postFilter( temp, [], context, xml ); // Un-match failing elements by moving them back to matcherIn i = temp.length; while ( i-- ) { if ( (elem = temp[i]) ) { matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); } } } if ( seed ) { if ( postFinder || preFilter ) { if ( postFinder ) { // Get the final matcherOut by condensing this intermediate into postFinder contexts temp = []; i = matcherOut.length; while ( i-- ) { if ( (elem = matcherOut[i]) ) { // Restore matcherIn since elem is not yet a final match temp.push( (matcherIn[i] = elem) ); } } postFinder( null, (matcherOut = []), temp, xml ); } // Move matched elements from seed to results to keep them synchronized i = matcherOut.length; while ( i-- ) { if ( (elem = matcherOut[i]) && (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { seed[temp] = !(results[temp] = elem); } } } // Add elements to results, through postFinder if defined } else { matcherOut = condense( matcherOut === results ? matcherOut.splice( preexisting, matcherOut.length ) : matcherOut ); if ( postFinder ) { postFinder( null, results, matcherOut, xml ); } else { push.apply( results, matcherOut ); } } }); } function matcherFromTokens( tokens ) { var checkContext, matcher, j, len = tokens.length, leadingRelative = Expr.relative[ tokens[0].type ], implicitRelative = leadingRelative || Expr.relative[" "], i = leadingRelative ? 1 : 0, // The foundational matcher ensures that elements are reachable from top-level context(s) matchContext = addCombinator( function( elem ) { return elem === checkContext; }, implicitRelative, true ), matchAnyContext = addCombinator( function( elem ) { return indexOf( checkContext, elem ) > -1; }, implicitRelative, true ), matchers = [ function( elem, context, xml ) { var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( (checkContext = context).nodeType ? matchContext( elem, context, xml ) : matchAnyContext( elem, context, xml ) ); // Avoid hanging onto element (issue #299) checkContext = null; return ret; } ]; for ( ; i < len; i++ ) { if ( (matcher = Expr.relative[ tokens[i].type ]) ) { matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; } else { matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); // Return special upon seeing a positional matcher if ( matcher[ expando ] ) { // Find the next relative operator (if any) for proper handling j = ++i; for ( ; j < len; j++ ) { if ( Expr.relative[ tokens[j].type ] ) { break; } } return setMatcher( i > 1 && elementMatcher( matchers ), i > 1 && toSelector( // If the preceding token was a descendant combinator, insert an implicit any-element `*` tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) ).replace( rtrim, "$1" ), matcher, i < j && matcherFromTokens( tokens.slice( i, j ) ), j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), j < len && toSelector( tokens ) ); } matchers.push( matcher ); } } return elementMatcher( matchers ); } function matcherFromGroupMatchers( elementMatchers, setMatchers ) { var bySet = setMatchers.length > 0, byElement = elementMatchers.length > 0, superMatcher = function( seed, context, xml, results, outermost ) { var elem, j, matcher, matchedCount = 0, i = "0", unmatched = seed && [], setMatched = [], contextBackup = outermostContext, // We must always have either seed elements or outermost context elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), // Use integer dirruns iff this is the outermost matcher dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), len = elems.length; if ( outermost ) { outermostContext = context !== document && context; } // Add elements passing elementMatchers directly to results // Keep `i` a string if there are no elements so `matchedCount` will be "00" below // Support: IE<9, Safari // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id for ( ; i !== len && (elem = elems[i]) != null; i++ ) { if ( byElement && elem ) { j = 0; while ( (matcher = elementMatchers[j++]) ) { if ( matcher( elem, context, xml ) ) { results.push( elem ); break; } } if ( outermost ) { dirruns = dirrunsUnique; } } // Track unmatched elements for set filters if ( bySet ) { // They will have gone through all possible matchers if ( (elem = !matcher && elem) ) { matchedCount--; } // Lengthen the array for every element, matched or not if ( seed ) { unmatched.push( elem ); } } } // Apply set filters to unmatched elements matchedCount += i; if ( bySet && i !== matchedCount ) { j = 0; while ( (matcher = setMatchers[j++]) ) { matcher( unmatched, setMatched, context, xml ); } if ( seed ) { // Reintegrate element matches to eliminate the need for sorting if ( matchedCount > 0 ) { while ( i-- ) { if ( !(unmatched[i] || setMatched[i]) ) { setMatched[i] = pop.call( results ); } } } // Discard index placeholder values to get only actual matches setMatched = condense( setMatched ); } // Add matches to results push.apply( results, setMatched ); // Seedless set matches succeeding multiple successful matchers stipulate sorting if ( outermost && !seed && setMatched.length > 0 && ( matchedCount + setMatchers.length ) > 1 ) { Sizzle.uniqueSort( results ); } } // Override manipulation of globals by nested matchers if ( outermost ) { dirruns = dirrunsUnique; outermostContext = contextBackup; } return unmatched; }; return bySet ? markFunction( superMatcher ) : superMatcher; } compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { var i, setMatchers = [], elementMatchers = [], cached = compilerCache[ selector + " " ]; if ( !cached ) { // Generate a function of recursive functions that can be used to check each element if ( !match ) { match = tokenize( selector ); } i = match.length; while ( i-- ) { cached = matcherFromTokens( match[i] ); if ( cached[ expando ] ) { setMatchers.push( cached ); } else { elementMatchers.push( cached ); } } // Cache the compiled function cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); // Save selector and tokenization cached.selector = selector; } return cached; }; /** * A low-level selection function that works with Sizzle's compiled * selector functions * @param {String|Function} selector A selector or a pre-compiled * selector function built with Sizzle.compile * @param {Element} context * @param {Array} [results] * @param {Array} [seed] A set of elements to match against */ select = Sizzle.select = function( selector, context, results, seed ) { var i, tokens, token, type, find, compiled = typeof selector === "function" && selector, match = !seed && tokenize( (selector = compiled.selector || selector) ); results = results || []; // Try to minimize operations if there is no seed and only one group if ( match.length === 1 ) { // Take a shortcut and set the context if the root selector is an ID tokens = match[0] = match[0].slice( 0 ); if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && support.getById && context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; if ( !context ) { return results; // Precompiled matchers will still verify ancestry, so step up a level } else if ( compiled ) { context = context.parentNode; } selector = selector.slice( tokens.shift().value.length ); } // Fetch a seed set for right-to-left matching i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; while ( i-- ) { token = tokens[i]; // Abort if we hit a combinator if ( Expr.relative[ (type = token.type) ] ) { break; } if ( (find = Expr.find[ type ]) ) { // Search, expanding context for leading sibling combinators if ( (seed = find( token.matches[0].replace( runescape, funescape ), rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context )) ) { // If seed is empty or no tokens remain, we can return early tokens.splice( i, 1 ); selector = seed.length && toSelector( tokens ); if ( !selector ) { push.apply( results, seed ); return results; } break; } } } } // Compile and execute a filtering function if one is not provided // Provide `match` to avoid retokenization if we modified the selector above ( compiled || compile( selector, match ) )( seed, context, !documentIsHTML, results, rsibling.test( selector ) && testContext( context.parentNode ) || context ); return results; }; // One-time assignments // Sort stability support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; // Support: Chrome 14-35+ // Always assume duplicates if they aren't passed to the comparison function support.detectDuplicates = !!hasDuplicate; // Initialize against the default document setDocument(); // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) // Detached nodes confoundingly follow *each other* support.sortDetached = assert(function( div1 ) { // Should return 1, but returns 4 (following) return div1.compareDocumentPosition( document.createElement("div") ) & 1; }); // Support: IE<8 // Prevent attribute/property "interpolation" // http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx if ( !assert(function( div ) { div.innerHTML = "<a href='#'></a>"; return div.firstChild.getAttribute("href") === "#" ; }) ) { addHandle( "type|href|height|width", function( elem, name, isXML ) { if ( !isXML ) { return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); } }); } // Support: IE<9 // Use defaultValue in place of getAttribute("value") if ( !support.attributes || !assert(function( div ) { div.innerHTML = "<input/>"; div.firstChild.setAttribute( "value", "" ); return div.firstChild.getAttribute( "value" ) === ""; }) ) { addHandle( "value", function( elem, name, isXML ) { if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { return elem.defaultValue; } }); } // Support: IE<9 // Use getAttributeNode to fetch booleans when getAttribute lies if ( !assert(function( div ) { return div.getAttribute("disabled") == null; }) ) { addHandle( booleans, function( elem, name, isXML ) { var val; if ( !isXML ) { return elem[ name ] === true ? name.toLowerCase() : (val = elem.getAttributeNode( name )) && val.specified ? val.value : null; } }); } return Sizzle; })( window ); jQuery.find = Sizzle; jQuery.expr = Sizzle.selectors; jQuery.expr[":"] = jQuery.expr.pseudos; jQuery.unique = Sizzle.uniqueSort; jQuery.text = Sizzle.getText; jQuery.isXMLDoc = Sizzle.isXML; jQuery.contains = Sizzle.contains; var rneedsContext = jQuery.expr.match.needsContext; var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/); var risSimple = /^.[^:#\[\.,]*$/; // Implement the identical functionality for filter and not function winnow( elements, qualifier, not ) { if ( jQuery.isFunction( qualifier ) ) { return jQuery.grep( elements, function( elem, i ) { /* jshint -W018 */ return !!qualifier.call( elem, i, elem ) !== not; }); } if ( qualifier.nodeType ) { return jQuery.grep( elements, function( elem ) { return ( elem === qualifier ) !== not; }); } if ( typeof qualifier === "string" ) { if ( risSimple.test( qualifier ) ) { return jQuery.filter( qualifier, elements, not ); } qualifier = jQuery.filter( qualifier, elements ); } return jQuery.grep( elements, function( elem ) { return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not; }); } jQuery.filter = function( expr, elems, not ) { var elem = elems[ 0 ]; if ( not ) { expr = ":not(" + expr + ")"; } return elems.length === 1 && elem.nodeType === 1 ? jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { return elem.nodeType === 1; })); }; jQuery.fn.extend({ find: function( selector ) { var i, ret = [], self = this, len = self.length; if ( typeof selector !== "string" ) { return this.pushStack( jQuery( selector ).filter(function() { for ( i = 0; i < len; i++ ) { if ( jQuery.contains( self[ i ], this ) ) { return true; } } }) ); } for ( i = 0; i < len; i++ ) { jQuery.find( selector, self[ i ], ret ); } // Needed because $( selector, context ) becomes $( context ).find( selector ) ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); ret.selector = this.selector ? this.selector + " " + selector : selector; return ret; }, filter: function( selector ) { return this.pushStack( winnow(this, selector || [], false) ); }, not: function( selector ) { return this.pushStack( winnow(this, selector || [], true) ); }, is: function( selector ) { return !!winnow( this, // If this is a positional/relative selector, check membership in the returned set // so $("p:first").is("p:last") won't return true for a doc with two "p". typeof selector === "string" && rneedsContext.test( selector ) ? jQuery( selector ) : selector || [], false ).length; } }); // Initialize a jQuery object // A central reference to the root jQuery(document) var rootjQuery, // Use the correct document accordingly with window argument (sandbox) document = window.document, // A simple way to check for HTML strings // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) // Strict HTML recognition (#11290: must start with <) rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, init = jQuery.fn.init = function( selector, context ) { var match, elem; // HANDLE: $(""), $(null), $(undefined), $(false) if ( !selector ) { return this; } // Handle HTML strings if ( typeof selector === "string" ) { if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [ null, selector, null ]; } else { match = rquickExpr.exec( selector ); } // Match html or make sure no context is specified for #id if ( match && (match[1] || !context) ) { // HANDLE: $(html) -> $(array) if ( match[1] ) { context = context instanceof jQuery ? context[0] : context; // scripts is true for back-compat // Intentionally let the error be thrown if parseHTML is not present jQuery.merge( this, jQuery.parseHTML( match[1], context && context.nodeType ? context.ownerDocument || context : document, true ) ); // HANDLE: $(html, props) if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { for ( match in context ) { // Properties of context are called as methods if possible if ( jQuery.isFunction( this[ match ] ) ) { this[ match ]( context[ match ] ); // ...and otherwise set as attributes } else { this.attr( match, context[ match ] ); } } } return this; // HANDLE: $(#id) } else { elem = document.getElementById( match[2] ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 if ( elem && elem.parentNode ) { // Handle the case where IE and Opera return items // by name instead of ID if ( elem.id !== match[2] ) { return rootjQuery.find( selector ); } // Otherwise, we inject the element directly into the jQuery object this.length = 1; this[0] = elem; } this.context = document; this.selector = selector; return this; } // HANDLE: $(expr, $(...)) } else if ( !context || context.jquery ) { return ( context || rootjQuery ).find( selector ); // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { return this.constructor( context ).find( selector ); } // HANDLE: $(DOMElement) } else if ( selector.nodeType ) { this.context = this[0] = selector; this.length = 1; return this; // HANDLE: $(function) // Shortcut for document ready } else if ( jQuery.isFunction( selector ) ) { return typeof rootjQuery.ready !== "undefined" ? rootjQuery.ready( selector ) : // Execute immediately if ready is not present selector( jQuery ); } if ( selector.selector !== undefined ) { this.selector = selector.selector; this.context = selector.context; } return jQuery.makeArray( selector, this ); }; // Give the init function the jQuery prototype for later instantiation init.prototype = jQuery.fn; // Initialize central reference rootjQuery = jQuery( document ); var rparentsprev = /^(?:parents|prev(?:Until|All))/, // methods guaranteed to produce a unique set when starting from a unique set guaranteedUnique = { children: true, contents: true, next: true, prev: true }; jQuery.extend({ dir: function( elem, dir, until ) { var matched = [], cur = elem[ dir ]; while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { if ( cur.nodeType === 1 ) { matched.push( cur ); } cur = cur[dir]; } return matched; }, sibling: function( n, elem ) { var r = []; for ( ; n; n = n.nextSibling ) { if ( n.nodeType === 1 && n !== elem ) { r.push( n ); } } return r; } }); jQuery.fn.extend({ has: function( target ) { var i, targets = jQuery( target, this ), len = targets.length; return this.filter(function() { for ( i = 0; i < len; i++ ) { if ( jQuery.contains( this, targets[i] ) ) { return true; } } }); }, closest: function( selectors, context ) { var cur, i = 0, l = this.length, matched = [], pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? jQuery( selectors, context || this.context ) : 0; for ( ; i < l; i++ ) { for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { // Always skip document fragments if ( cur.nodeType < 11 && (pos ? pos.index(cur) > -1 : // Don't pass non-elements to Sizzle cur.nodeType === 1 && jQuery.find.matchesSelector(cur, selectors)) ) { matched.push( cur ); break; } } } return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched ); }, // Determine the position of an element within // the matched set of elements index: function( elem ) { // No argument, return index in parent if ( !elem ) { return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; } // index in selector if ( typeof elem === "string" ) { return jQuery.inArray( this[0], jQuery( elem ) ); } // Locate the position of the desired element return jQuery.inArray( // If it receives a jQuery object, the first element is used elem.jquery ? elem[0] : elem, this ); }, add: function( selector, context ) { return this.pushStack( jQuery.unique( jQuery.merge( this.get(), jQuery( selector, context ) ) ) ); }, addBack: function( selector ) { return this.add( selector == null ? this.prevObject : this.prevObject.filter(selector) ); } }); function sibling( cur, dir ) { do { cur = cur[ dir ]; } while ( cur && cur.nodeType !== 1 ); return cur; } jQuery.each({ parent: function( elem ) { var parent = elem.parentNode; return parent && parent.nodeType !== 11 ? parent : null; }, parents: function( elem ) { return jQuery.dir( elem, "parentNode" ); }, parentsUntil: function( elem, i, until ) { return jQuery.dir( elem, "parentNode", until ); }, next: function( elem ) { return sibling( elem, "nextSibling" ); }, prev: function( elem ) { return sibling( elem, "previousSibling" ); }, nextAll: function( elem ) { return jQuery.dir( elem, "nextSibling" ); }, prevAll: function( elem ) { return jQuery.dir( elem, "previousSibling" ); }, nextUntil: function( elem, i, until ) { return jQuery.dir( elem, "nextSibling", until ); }, prevUntil: function( elem, i, until ) { return jQuery.dir( elem, "previousSibling", until ); }, siblings: function( elem ) { return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); }, children: function( elem ) { return jQuery.sibling( elem.firstChild ); }, contents: function( elem ) { return jQuery.nodeName( elem, "iframe" ) ? elem.contentDocument || elem.contentWindow.document : jQuery.merge( [], elem.childNodes ); } }, function( name, fn ) { jQuery.fn[ name ] = function( until, selector ) { var ret = jQuery.map( this, fn, until ); if ( name.slice( -5 ) !== "Until" ) { selector = until; } if ( selector && typeof selector === "string" ) { ret = jQuery.filter( selector, ret ); } if ( this.length > 1 ) { // Remove duplicates if ( !guaranteedUnique[ name ] ) { ret = jQuery.unique( ret ); } // Reverse order for parents* and prev-derivatives if ( rparentsprev.test( name ) ) { ret = ret.reverse(); } } return this.pushStack( ret ); }; }); var rnotwhite = (/\S+/g); // String to Object options format cache var optionsCache = {}; // Convert String-formatted options into Object-formatted ones and store in cache function createOptions( options ) { var object = optionsCache[ options ] = {}; jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { object[ flag ] = true; }); return object; } /* * Create a callback list using the following parameters: * * options: an optional list of space-separated options that will change how * the callback list behaves or a more traditional option object * * By default a callback list will act like an event callback list and can be * "fired" multiple times. * * Possible options: * * once: will ensure the callback list can only be fired once (like a Deferred) * * memory: will keep track of previous values and will call any callback added * after the list has been fired right away with the latest "memorized" * values (like a Deferred) * * unique: will ensure a callback can only be added once (no duplicate in the list) * * stopOnFalse: interrupt callings when a callback returns false * */ jQuery.Callbacks = function( options ) { // Convert options from String-formatted to Object-formatted if needed // (we check in cache first) options = typeof options === "string" ? ( optionsCache[ options ] || createOptions( options ) ) : jQuery.extend( {}, options ); var // Flag to know if list is currently firing firing, // Last fire value (for non-forgettable lists) memory, // Flag to know if list was already fired fired, // End of the loop when firing firingLength, // Index of currently firing callback (modified by remove if needed) firingIndex, // First callback to fire (used internally by add and fireWith) firingStart, // Actual callback list list = [], // Stack of fire calls for repeatable lists stack = !options.once && [], // Fire callbacks fire = function( data ) { memory = options.memory && data; fired = true; firingIndex = firingStart || 0; firingStart = 0; firingLength = list.length; firing = true; for ( ; list && firingIndex < firingLength; firingIndex++ ) { if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { memory = false; // To prevent further calls using add break; } } firing = false; if ( list ) { if ( stack ) { if ( stack.length ) { fire( stack.shift() ); } } else if ( memory ) { list = []; } else { self.disable(); } } }, // Actual Callbacks object self = { // Add a callback or a collection of callbacks to the list add: function() { if ( list ) { // First, we save the current length var start = list.length; (function add( args ) { jQuery.each( args, function( _, arg ) { var type = jQuery.type( arg ); if ( type === "function" ) { if ( !options.unique || !self.has( arg ) ) { list.push( arg ); } } else if ( arg && arg.length && type !== "string" ) { // Inspect recursively add( arg ); } }); })( arguments ); // Do we need to add the callbacks to the // current firing batch? if ( firing ) { firingLength = list.length; // With memory, if we're not firing then // we should call right away } else if ( memory ) { firingStart = start; fire( memory ); } } return this; }, // Remove a callback from the list remove: function() { if ( list ) { jQuery.each( arguments, function( _, arg ) { var index; while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { list.splice( index, 1 ); // Handle firing indexes if ( firing ) { if ( index <= firingLength ) { firingLength--; } if ( index <= firingIndex ) { firingIndex--; } } } }); } return this; }, // Check if a given callback is in the list. // If no argument is given, return whether or not list has callbacks attached. has: function( fn ) { return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); }, // Remove all callbacks from the list empty: function() { list = []; firingLength = 0; return this; }, // Have the list do nothing anymore disable: function() { list = stack = memory = undefined; return this; }, // Is it disabled? disabled: function() { return !list; }, // Lock the list in its current state lock: function() { stack = undefined; if ( !memory ) { self.disable(); } return this; }, // Is it locked? locked: function() { return !stack; }, // Call all callbacks with the given context and arguments fireWith: function( context, args ) { if ( list && ( !fired || stack ) ) { args = args || []; args = [ context, args.slice ? args.slice() : args ]; if ( firing ) { stack.push( args ); } else { fire( args ); } } return this; }, // Call all the callbacks with the given arguments fire: function() { self.fireWith( this, arguments ); return this; }, // To know if the callbacks have already been called at least once fired: function() { return !!fired; } }; return self; }; jQuery.extend({ Deferred: function( func ) { var tuples = [ // action, add listener, listener list, final state [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], [ "notify", "progress", jQuery.Callbacks("memory") ] ], state = "pending", promise = { state: function() { return state; }, always: function() { deferred.done( arguments ).fail( arguments ); return this; }, then: function( /* fnDone, fnFail, fnProgress */ ) { var fns = arguments; return jQuery.Deferred(function( newDefer ) { jQuery.each( tuples, function( i, tuple ) { var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; // deferred[ done | fail | progress ] for forwarding actions to newDefer deferred[ tuple[1] ](function() { var returned = fn && fn.apply( this, arguments ); if ( returned && jQuery.isFunction( returned.promise ) ) { returned.promise() .done( newDefer.resolve ) .fail( newDefer.reject ) .progress( newDefer.notify ); } else { newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); } }); }); fns = null; }).promise(); }, // Get a promise for this deferred // If obj is provided, the promise aspect is added to the object promise: function( obj ) { return obj != null ? jQuery.extend( obj, promise ) : promise; } }, deferred = {}; // Keep pipe for back-compat promise.pipe = promise.then; // Add list-specific methods jQuery.each( tuples, function( i, tuple ) { var list = tuple[ 2 ], stateString = tuple[ 3 ]; // promise[ done | fail | progress ] = list.add promise[ tuple[1] ] = list.add; // Handle state if ( stateString ) { list.add(function() { // state = [ resolved | rejected ] state = stateString; // [ reject_list | resolve_list ].disable; progress_list.lock }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); } // deferred[ resolve | reject | notify ] deferred[ tuple[0] ] = function() { deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); return this; }; deferred[ tuple[0] + "With" ] = list.fireWith; }); // Make the deferred a promise promise.promise( deferred ); // Call given func if any if ( func ) { func.call( deferred, deferred ); } // All done! return deferred; }, // Deferred helper when: function( subordinate /* , ..., subordinateN */ ) { var i = 0, resolveValues = slice.call( arguments ), length = resolveValues.length, // the count of uncompleted subordinates remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, // the master Deferred. If resolveValues consist of only a single Deferred, just use that. deferred = remaining === 1 ? subordinate : jQuery.Deferred(), // Update function for both resolve and progress values updateFunc = function( i, contexts, values ) { return function( value ) { contexts[ i ] = this; values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; if ( values === progressValues ) { deferred.notifyWith( contexts, values ); } else if ( !(--remaining) ) { deferred.resolveWith( contexts, values ); } }; }, progressValues, progressContexts, resolveContexts; // add listeners to Deferred subordinates; treat others as resolved if ( length > 1 ) { progressValues = new Array( length ); progressContexts = new Array( length ); resolveContexts = new Array( length ); for ( ; i < length; i++ ) { if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { resolveValues[ i ].promise() .done( updateFunc( i, resolveContexts, resolveValues ) ) .fail( deferred.reject ) .progress( updateFunc( i, progressContexts, progressValues ) ); } else { --remaining; } } } // if we're not waiting on anything, resolve the master if ( !remaining ) { deferred.resolveWith( resolveContexts, resolveValues ); } return deferred.promise(); } }); // The deferred used on DOM ready var readyList; jQuery.fn.ready = function( fn ) { // Add the callback jQuery.ready.promise().done( fn ); return this; }; jQuery.extend({ // Is the DOM ready to be used? Set to true once it occurs. isReady: false, // A counter to track how many items to wait for before // the ready event fires. See #6781 readyWait: 1, // Hold (or release) the ready event holdReady: function( hold ) { if ( hold ) { jQuery.readyWait++; } else { jQuery.ready( true ); } }, // Handle when the DOM is ready ready: function( wait ) { // Abort if there are pending holds or we're already ready if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { return; } // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). if ( !document.body ) { return setTimeout( jQuery.ready ); } // Remember that the DOM is ready jQuery.isReady = true; // If a normal DOM Ready event fired, decrement, and wait if need be if ( wait !== true && --jQuery.readyWait > 0 ) { return; } // If there are functions bound, to execute readyList.resolveWith( document, [ jQuery ] ); // Trigger any bound ready events if ( jQuery.fn.triggerHandler ) { jQuery( document ).triggerHandler( "ready" ); jQuery( document ).off( "ready" ); } } }); /** * Clean-up method for dom ready events */ function detach() { if ( document.addEventListener ) { document.removeEventListener( "DOMContentLoaded", completed, false ); window.removeEventListener( "load", completed, false ); } else { document.detachEvent( "onreadystatechange", completed ); window.detachEvent( "onload", completed ); } } /** * The ready event handler and self cleanup method */ function completed() { // readyState === "complete" is good enough for us to call the dom ready in oldIE if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { detach(); jQuery.ready(); } } jQuery.ready.promise = function( obj ) { if ( !readyList ) { readyList = jQuery.Deferred(); // Catch cases where $(document).ready() is called after the browser event has already occurred. // we once tried to use readyState "interactive" here, but it caused issues like the one // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 if ( document.readyState === "complete" ) { // Handle it asynchronously to allow scripts the opportunity to delay ready setTimeout( jQuery.ready ); // Standards-based browsers support DOMContentLoaded } else if ( document.addEventListener ) { // Use the handy event callback document.addEventListener( "DOMContentLoaded", completed, false ); // A fallback to window.onload, that will always work window.addEventListener( "load", completed, false ); // If IE event model is used } else { // Ensure firing before onload, maybe late but safe also for iframes document.attachEvent( "onreadystatechange", completed ); // A fallback to window.onload, that will always work window.attachEvent( "onload", completed ); // If IE and not a frame // continually check to see if the document is ready var top = false; try { top = window.frameElement == null && document.documentElement; } catch(e) {} if ( top && top.doScroll ) { (function doScrollCheck() { if ( !jQuery.isReady ) { try { // Use the trick by Diego Perini // http://javascript.nwbox.com/IEContentLoaded/ top.doScroll("left"); } catch(e) { return setTimeout( doScrollCheck, 50 ); } // detach all dom ready events detach(); // and execute any waiting functions jQuery.ready(); } })(); } } } return readyList.promise( obj ); }; var strundefined = typeof undefined; // Support: IE<9 // Iteration over object's inherited properties before its own var i; for ( i in jQuery( support ) ) { break; } support.ownLast = i !== "0"; // Note: most support tests are defined in their respective modules. // false until the test is run support.inlineBlockNeedsLayout = false; // Execute ASAP in case we need to set body.style.zoom jQuery(function() { // Minified: var a,b,c,d var val, div, body, container; body = document.getElementsByTagName( "body" )[ 0 ]; if ( !body || !body.style ) { // Return for frameset docs that don't have a body return; } // Setup div = document.createElement( "div" ); container = document.createElement( "div" ); container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px"; body.appendChild( container ).appendChild( div ); if ( typeof div.style.zoom !== strundefined ) { // Support: IE<8 // Check if natively block-level elements act like inline-block // elements when setting their display to 'inline' and giving // them layout div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1"; support.inlineBlockNeedsLayout = val = div.offsetWidth === 3; if ( val ) { // Prevent IE 6 from affecting layout for positioned elements #11048 // Prevent IE from shrinking the body in IE 7 mode #12869 // Support: IE<8 body.style.zoom = 1; } } body.removeChild( container ); }); (function() { var div = document.createElement( "div" ); // Execute the test only if not already executed in another module. if (support.deleteExpando == null) { // Support: IE<9 support.deleteExpando = true; try { delete div.test; } catch( e ) { support.deleteExpando = false; } } // Null elements to avoid leaks in IE. div = null; })(); /** * Determines whether an object can have data */ jQuery.acceptData = function( elem ) { var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ], nodeType = +elem.nodeType || 1; // Do not set data on non-element DOM nodes because it will not be cleared (#8335). return nodeType !== 1 && nodeType !== 9 ? false : // Nodes accept data unless otherwise specified; rejection can be conditional !noData || noData !== true && elem.getAttribute("classid") === noData; }; var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, rmultiDash = /([A-Z])/g; function dataAttr( elem, key, data ) { // If nothing was found internally, try to fetch any // data from the HTML5 data-* attribute if ( data === undefined && elem.nodeType === 1 ) { var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); data = elem.getAttribute( name ); if ( typeof data === "string" ) { try { data = data === "true" ? true : data === "false" ? false : data === "null" ? null : // Only convert to a number if it doesn't change the string +data + "" === data ? +data : rbrace.test( data ) ? jQuery.parseJSON( data ) : data; } catch( e ) {} // Make sure we set the data so it isn't changed later jQuery.data( elem, key, data ); } else { data = undefined; } } return data; } // checks a cache object for emptiness function isEmptyDataObject( obj ) { var name; for ( name in obj ) { // if the public data object is empty, the private is still empty if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { continue; } if ( name !== "toJSON" ) { return false; } } return true; } function internalData( elem, name, data, pvt /* Internal Use Only */ ) { if ( !jQuery.acceptData( elem ) ) { return; } var ret, thisCache, internalKey = jQuery.expando, // We have to handle DOM nodes and JS objects differently because IE6-7 // can't GC object references properly across the DOM-JS boundary isNode = elem.nodeType, // Only DOM nodes need the global jQuery cache; JS object data is // attached directly to the object so GC can occur automatically cache = isNode ? jQuery.cache : elem, // Only defining an ID for JS objects if its cache already exists allows // the code to shortcut on the same path as a DOM node with no cache id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; // Avoid doing any more work than we need to when trying to get data on an // object that has no data at all if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) { return; } if ( !id ) { // Only DOM nodes need a new unique ID for each element since their data // ends up in the global cache if ( isNode ) { id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++; } else { id = internalKey; } } if ( !cache[ id ] ) { // Avoid exposing jQuery metadata on plain JS objects when the object // is serialized using JSON.stringify cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; } // An object can be passed to jQuery.data instead of a key/value pair; this gets // shallow copied over onto the existing cache if ( typeof name === "object" || typeof name === "function" ) { if ( pvt ) { cache[ id ] = jQuery.extend( cache[ id ], name ); } else { cache[ id ].data = jQuery.extend( cache[ id ].data, name ); } } thisCache = cache[ id ]; // jQuery data() is stored in a separate object inside the object's internal data // cache in order to avoid key collisions between internal data and user-defined // data. if ( !pvt ) { if ( !thisCache.data ) { thisCache.data = {}; } thisCache = thisCache.data; } if ( data !== undefined ) { thisCache[ jQuery.camelCase( name ) ] = data; } // Check for both converted-to-camel and non-converted data property names // If a data property was specified if ( typeof name === "string" ) { // First Try to find as-is property data ret = thisCache[ name ]; // Test for null|undefined property data if ( ret == null ) { // Try to find the camelCased property ret = thisCache[ jQuery.camelCase( name ) ]; } } else { ret = thisCache; } return ret; } function internalRemoveData( elem, name, pvt ) { if ( !jQuery.acceptData( elem ) ) { return; } var thisCache, i, isNode = elem.nodeType, // See jQuery.data for more information cache = isNode ? jQuery.cache : elem, id = isNode ? elem[ jQuery.expando ] : jQuery.expando; // If there is already no cache entry for this object, there is no // purpose in continuing if ( !cache[ id ] ) { return; } if ( name ) { thisCache = pvt ? cache[ id ] : cache[ id ].data; if ( thisCache ) { // Support array or space separated string names for data keys if ( !jQuery.isArray( name ) ) { // try the string as a key before any manipulation if ( name in thisCache ) { name = [ name ]; } else { // split the camel cased version by spaces unless a key with the spaces exists name = jQuery.camelCase( name ); if ( name in thisCache ) { name = [ name ]; } else { name = name.split(" "); } } } else { // If "name" is an array of keys... // When data is initially created, via ("key", "val") signature, // keys will be converted to camelCase. // Since there is no way to tell _how_ a key was added, remove // both plain key and camelCase key. #12786 // This will only penalize the array argument path. name = name.concat( jQuery.map( name, jQuery.camelCase ) ); } i = name.length; while ( i-- ) { delete thisCache[ name[i] ]; } // If there is no data left in the cache, we want to continue // and let the cache object itself get destroyed if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) { return; } } } // See jQuery.data for more information if ( !pvt ) { delete cache[ id ].data; // Don't destroy the parent cache unless the internal data object // had been the only thing left in it if ( !isEmptyDataObject( cache[ id ] ) ) { return; } } // Destroy the cache if ( isNode ) { jQuery.cleanData( [ elem ], true ); // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) /* jshint eqeqeq: false */ } else if ( support.deleteExpando || cache != cache.window ) { /* jshint eqeqeq: true */ delete cache[ id ]; // When all else fails, null } else { cache[ id ] = null; } } jQuery.extend({ cache: {}, // The following elements (space-suffixed to avoid Object.prototype collisions) // throw uncatchable exceptions if you attempt to set expando properties noData: { "applet ": true, "embed ": true, // ...but Flash objects (which have this classid) *can* handle expandos "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" }, hasData: function( elem ) { elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; return !!elem && !isEmptyDataObject( elem ); }, data: function( elem, name, data ) { return internalData( elem, name, data ); }, removeData: function( elem, name ) { return internalRemoveData( elem, name ); }, // For internal use only. _data: function( elem, name, data ) { return internalData( elem, name, data, true ); }, _removeData: function( elem, name ) { return internalRemoveData( elem, name, true ); } }); jQuery.fn.extend({ data: function( key, value ) { var i, name, data, elem = this[0], attrs = elem && elem.attributes; // Special expections of .data basically thwart jQuery.access, // so implement the relevant behavior ourselves // Gets all values if ( key === undefined ) { if ( this.length ) { data = jQuery.data( elem ); if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { i = attrs.length; while ( i-- ) { // Support: IE11+ // The attrs elements can be null (#14894) if ( attrs[ i ] ) { name = attrs[ i ].name; if ( name.indexOf( "data-" ) === 0 ) { name = jQuery.camelCase( name.slice(5) ); dataAttr( elem, name, data[ name ] ); } } } jQuery._data( elem, "parsedAttrs", true ); } } return data; } // Sets multiple values if ( typeof key === "object" ) { return this.each(function() { jQuery.data( this, key ); }); } return arguments.length > 1 ? // Sets one value this.each(function() { jQuery.data( this, key, value ); }) : // Gets one value // Try to fetch any internally stored data first elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined; }, removeData: function( key ) { return this.each(function() { jQuery.removeData( this, key ); }); } }); jQuery.extend({ queue: function( elem, type, data ) { var queue; if ( elem ) { type = ( type || "fx" ) + "queue"; queue = jQuery._data( elem, type ); // Speed up dequeue by getting out quickly if this is just a lookup if ( data ) { if ( !queue || jQuery.isArray(data) ) { queue = jQuery._data( elem, type, jQuery.makeArray(data) ); } else { queue.push( data ); } } return queue || []; } }, dequeue: function( elem, type ) { type = type || "fx"; var queue = jQuery.queue( elem, type ), startLength = queue.length, fn = queue.shift(), hooks = jQuery._queueHooks( elem, type ), next = function() { jQuery.dequeue( elem, type ); }; // If the fx queue is dequeued, always remove the progress sentinel if ( fn === "inprogress" ) { fn = queue.shift(); startLength--; } if ( fn ) { // Add a progress sentinel to prevent the fx queue from being // automatically dequeued if ( type === "fx" ) { queue.unshift( "inprogress" ); } // clear up the last queue stop function delete hooks.stop; fn.call( elem, next, hooks ); } if ( !startLength && hooks ) { hooks.empty.fire(); } }, // not intended for public consumption - generates a queueHooks object, or returns the current one _queueHooks: function( elem, type ) { var key = type + "queueHooks"; return jQuery._data( elem, key ) || jQuery._data( elem, key, { empty: jQuery.Callbacks("once memory").add(function() { jQuery._removeData( elem, type + "queue" ); jQuery._removeData( elem, key ); }) }); } }); jQuery.fn.extend({ queue: function( type, data ) { var setter = 2; if ( typeof type !== "string" ) { data = type; type = "fx"; setter--; } if ( arguments.length < setter ) { return jQuery.queue( this[0], type ); } return data === undefined ? this : this.each(function() { var queue = jQuery.queue( this, type, data ); // ensure a hooks for this queue jQuery._queueHooks( this, type ); if ( type === "fx" && queue[0] !== "inprogress" ) { jQuery.dequeue( this, type ); } }); }, dequeue: function( type ) { return this.each(function() { jQuery.dequeue( this, type ); }); }, clearQueue: function( type ) { return this.queue( type || "fx", [] ); }, // Get a promise resolved when queues of a certain type // are emptied (fx is the type by default) promise: function( type, obj ) { var tmp, count = 1, defer = jQuery.Deferred(), elements = this, i = this.length, resolve = function() { if ( !( --count ) ) { defer.resolveWith( elements, [ elements ] ); } }; if ( typeof type !== "string" ) { obj = type; type = undefined; } type = type || "fx"; while ( i-- ) { tmp = jQuery._data( elements[ i ], type + "queueHooks" ); if ( tmp && tmp.empty ) { count++; tmp.empty.add( resolve ); } } resolve(); return defer.promise( obj ); } }); var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source; var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; var isHidden = function( elem, el ) { // isHidden might be called from jQuery#filter function; // in that case, element will be second argument elem = el || elem; return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); }; // Multifunctional method to get and set values of a collection // The value/s can optionally be executed if it's a function var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) { var i = 0, length = elems.length, bulk = key == null; // Sets many values if ( jQuery.type( key ) === "object" ) { chainable = true; for ( i in key ) { jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); } // Sets one value } else if ( value !== undefined ) { chainable = true; if ( !jQuery.isFunction( value ) ) { raw = true; } if ( bulk ) { // Bulk operations run against the entire set if ( raw ) { fn.call( elems, value ); fn = null; // ...except when executing function values } else { bulk = fn; fn = function( elem, key, value ) { return bulk.call( jQuery( elem ), value ); }; } } if ( fn ) { for ( ; i < length; i++ ) { fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); } } } return chainable ? elems : // Gets bulk ? fn.call( elems ) : length ? fn( elems[0], key ) : emptyGet; }; var rcheckableType = (/^(?:checkbox|radio)$/i); (function() { // Minified: var a,b,c var input = document.createElement( "input" ), div = document.createElement( "div" ), fragment = document.createDocumentFragment(); // Setup div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>"; // IE strips leading whitespace when .innerHTML is used support.leadingWhitespace = div.firstChild.nodeType === 3; // Make sure that tbody elements aren't automatically inserted // IE will insert them into empty tables support.tbody = !div.getElementsByTagName( "tbody" ).length; // Make sure that link elements get serialized correctly by innerHTML // This requires a wrapper element in IE support.htmlSerialize = !!div.getElementsByTagName( "link" ).length; // Makes sure cloning an html5 element does not cause problems // Where outerHTML is undefined, this still works support.html5Clone = document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav></:nav>"; // Check if a disconnected checkbox will retain its checked // value of true after appended to the DOM (IE6/7) input.type = "checkbox"; input.checked = true; fragment.appendChild( input ); support.appendChecked = input.checked; // Make sure textarea (and checkbox) defaultValue is properly cloned // Support: IE6-IE11+ div.innerHTML = "<textarea>x</textarea>"; support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; // #11217 - WebKit loses check when the name is after the checked attribute fragment.appendChild( div ); div.innerHTML = "<input type='radio' checked='checked' name='t'/>"; // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3 // old WebKit doesn't clone checked state correctly in fragments support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; // Support: IE<9 // Opera does not clone events (and typeof div.attachEvent === undefined). // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() support.noCloneEvent = true; if ( div.attachEvent ) { div.attachEvent( "onclick", function() { support.noCloneEvent = false; }); div.cloneNode( true ).click(); } // Execute the test only if not already executed in another module. if (support.deleteExpando == null) { // Support: IE<9 support.deleteExpando = true; try { delete div.test; } catch( e ) { support.deleteExpando = false; } } })(); (function() { var i, eventName, div = document.createElement( "div" ); // Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event) for ( i in { submit: true, change: true, focusin: true }) { eventName = "on" + i; if ( !(support[ i + "Bubbles" ] = eventName in window) ) { // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) div.setAttribute( eventName, "t" ); support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false; } } // Null elements to avoid leaks in IE. div = null; })(); var rformElems = /^(?:input|select|textarea)$/i, rkeyEvent = /^key/, rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/, rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; function returnTrue() { return true; } function returnFalse() { return false; } function safeActiveElement() { try { return document.activeElement; } catch ( err ) { } } /* * Helper functions for managing events -- not part of the public interface. * Props to Dean Edwards' addEvent library for many of the ideas. */ jQuery.event = { global: {}, add: function( elem, types, handler, data, selector ) { var tmp, events, t, handleObjIn, special, eventHandle, handleObj, handlers, type, namespaces, origType, elemData = jQuery._data( elem ); // Don't attach events to noData or text/comment nodes (but allow plain objects) if ( !elemData ) { return; } // Caller can pass in an object of custom data in lieu of the handler if ( handler.handler ) { handleObjIn = handler; handler = handleObjIn.handler; selector = handleObjIn.selector; } // Make sure that the handler has a unique ID, used to find/remove it later if ( !handler.guid ) { handler.guid = jQuery.guid++; } // Init the element's event structure and main handler, if this is the first if ( !(events = elemData.events) ) { events = elemData.events = {}; } if ( !(eventHandle = elemData.handle) ) { eventHandle = elemData.handle = function( e ) { // Discard the second event of a jQuery.event.trigger() and // when an event is called after a page has unloaded return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ? jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : undefined; }; // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events eventHandle.elem = elem; } // Handle multiple events separated by a space types = ( types || "" ).match( rnotwhite ) || [ "" ]; t = types.length; while ( t-- ) { tmp = rtypenamespace.exec( types[t] ) || []; type = origType = tmp[1]; namespaces = ( tmp[2] || "" ).split( "." ).sort(); // There *must* be a type, no attaching namespace-only handlers if ( !type ) { continue; } // If event changes its type, use the special event handlers for the changed type special = jQuery.event.special[ type ] || {}; // If selector defined, determine special event api type, otherwise given type type = ( selector ? special.delegateType : special.bindType ) || type; // Update special based on newly reset type special = jQuery.event.special[ type ] || {}; // handleObj is passed to all event handlers handleObj = jQuery.extend({ type: type, origType: origType, data: data, handler: handler, guid: handler.guid, selector: selector, needsContext: selector && jQuery.expr.match.needsContext.test( selector ), namespace: namespaces.join(".") }, handleObjIn ); // Init the event handler queue if we're the first if ( !(handlers = events[ type ]) ) { handlers = events[ type ] = []; handlers.delegateCount = 0; // Only use addEventListener/attachEvent if the special events handler returns false if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { // Bind the global event handler to the element if ( elem.addEventListener ) { elem.addEventListener( type, eventHandle, false ); } else if ( elem.attachEvent ) { elem.attachEvent( "on" + type, eventHandle ); } } } if ( special.add ) { special.add.call( elem, handleObj ); if ( !handleObj.handler.guid ) { handleObj.handler.guid = handler.guid; } } // Add to the element's handler list, delegates in front if ( selector ) { handlers.splice( handlers.delegateCount++, 0, handleObj ); } else { handlers.push( handleObj ); } // Keep track of which events have ever been used, for event optimization jQuery.event.global[ type ] = true; } // Nullify elem to prevent memory leaks in IE elem = null; }, // Detach an event or set of events from an element remove: function( elem, types, handler, selector, mappedTypes ) { var j, handleObj, tmp, origCount, t, events, special, handlers, type, namespaces, origType, elemData = jQuery.hasData( elem ) && jQuery._data( elem ); if ( !elemData || !(events = elemData.events) ) { return; } // Once for each type.namespace in types; type may be omitted types = ( types || "" ).match( rnotwhite ) || [ "" ]; t = types.length; while ( t-- ) { tmp = rtypenamespace.exec( types[t] ) || []; type = origType = tmp[1]; namespaces = ( tmp[2] || "" ).split( "." ).sort(); // Unbind all events (on this namespace, if provided) for the element if ( !type ) { for ( type in events ) { jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); } continue; } special = jQuery.event.special[ type ] || {}; type = ( selector ? special.delegateType : special.bindType ) || type; handlers = events[ type ] || []; tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); // Remove matching events origCount = j = handlers.length; while ( j-- ) { handleObj = handlers[ j ]; if ( ( mappedTypes || origType === handleObj.origType ) && ( !handler || handler.guid === handleObj.guid ) && ( !tmp || tmp.test( handleObj.namespace ) ) && ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { handlers.splice( j, 1 ); if ( handleObj.selector ) { handlers.delegateCount--; } if ( special.remove ) { special.remove.call( elem, handleObj ); } } } // Remove generic event handler if we removed something and no more handlers exist // (avoids potential for endless recursion during removal of special event handlers) if ( origCount && !handlers.length ) { if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { jQuery.removeEvent( elem, type, elemData.handle ); } delete events[ type ]; } } // Remove the expando if it's no longer used if ( jQuery.isEmptyObject( events ) ) { delete elemData.handle; // removeData also checks for emptiness and clears the expando if empty // so use it instead of delete jQuery._removeData( elem, "events" ); } }, trigger: function( event, data, elem, onlyHandlers ) { var handle, ontype, cur, bubbleType, special, tmp, i, eventPath = [ elem || document ], type = hasOwn.call( event, "type" ) ? event.type : event, namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; cur = tmp = elem = elem || document; // Don't do events on text and comment nodes if ( elem.nodeType === 3 || elem.nodeType === 8 ) { return; } // focus/blur morphs to focusin/out; ensure we're not firing them right now if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { return; } if ( type.indexOf(".") >= 0 ) { // Namespaced trigger; create a regexp to match event type in handle() namespaces = type.split("."); type = namespaces.shift(); namespaces.sort(); } ontype = type.indexOf(":") < 0 && "on" + type; // Caller can pass in a jQuery.Event object, Object, or just an event type string event = event[ jQuery.expando ] ? event : new jQuery.Event( type, typeof event === "object" && event ); // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) event.isTrigger = onlyHandlers ? 2 : 3; event.namespace = namespaces.join("."); event.namespace_re = event.namespace ? new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : null; // Clean up the event in case it is being reused event.result = undefined; if ( !event.target ) { event.target = elem; } // Clone any incoming data and prepend the event, creating the handler arg list data = data == null ? [ event ] : jQuery.makeArray( data, [ event ] ); // Allow special events to draw outside the lines special = jQuery.event.special[ type ] || {}; if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { return; } // Determine event propagation path in advance, per W3C events spec (#9951) // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { bubbleType = special.delegateType || type; if ( !rfocusMorph.test( bubbleType + type ) ) { cur = cur.parentNode; } for ( ; cur; cur = cur.parentNode ) { eventPath.push( cur ); tmp = cur; } // Only add window if we got to document (e.g., not plain obj or detached DOM) if ( tmp === (elem.ownerDocument || document) ) { eventPath.push( tmp.defaultView || tmp.parentWindow || window ); } } // Fire handlers on the event path i = 0; while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { event.type = i > 1 ? bubbleType : special.bindType || type; // jQuery handler handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); if ( handle ) { handle.apply( cur, data ); } // Native handler handle = ontype && cur[ ontype ]; if ( handle && handle.apply && jQuery.acceptData( cur ) ) { event.result = handle.apply( cur, data ); if ( event.result === false ) { event.preventDefault(); } } } event.type = type; // If nobody prevented the default action, do it now if ( !onlyHandlers && !event.isDefaultPrevented() ) { if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && jQuery.acceptData( elem ) ) { // Call a native DOM method on the target with the same name name as the event. // Can't use an .isFunction() check here because IE6/7 fails that test. // Don't do default actions on window, that's where global variables be (#6170) if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { // Don't re-trigger an onFOO event when we call its FOO() method tmp = elem[ ontype ]; if ( tmp ) { elem[ ontype ] = null; } // Prevent re-triggering of the same event, since we already bubbled it above jQuery.event.triggered = type; try { elem[ type ](); } catch ( e ) { // IE<9 dies on focus/blur to hidden element (#1486,#12518) // only reproducible on winXP IE8 native, not IE9 in IE8 mode } jQuery.event.triggered = undefined; if ( tmp ) { elem[ ontype ] = tmp; } } } } return event.result; }, dispatch: function( event ) { // Make a writable jQuery.Event from the native event object event = jQuery.event.fix( event ); var i, ret, handleObj, matched, j, handlerQueue = [], args = slice.call( arguments ), handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], special = jQuery.event.special[ event.type ] || {}; // Use the fix-ed jQuery.Event rather than the (read-only) native event args[0] = event; event.delegateTarget = this; // Call the preDispatch hook for the mapped type, and let it bail if desired if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { return; } // Determine handlers handlerQueue = jQuery.event.handlers.call( this, event, handlers ); // Run delegates first; they may want to stop propagation beneath us i = 0; while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { event.currentTarget = matched.elem; j = 0; while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { // Triggered event must either 1) have no namespace, or // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { event.handleObj = handleObj; event.data = handleObj.data; ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) .apply( matched.elem, args ); if ( ret !== undefined ) { if ( (event.result = ret) === false ) { event.preventDefault(); event.stopPropagation(); } } } } } // Call the postDispatch hook for the mapped type if ( special.postDispatch ) { special.postDispatch.call( this, event ); } return event.result; }, handlers: function( event, handlers ) { var sel, handleObj, matches, i, handlerQueue = [], delegateCount = handlers.delegateCount, cur = event.target; // Find delegate handlers // Black-hole SVG <use> instance trees (#13180) // Avoid non-left-click bubbling in Firefox (#3861) if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { /* jshint eqeqeq: false */ for ( ; cur != this; cur = cur.parentNode || this ) { /* jshint eqeqeq: true */ // Don't check non-elements (#13208) // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) { matches = []; for ( i = 0; i < delegateCount; i++ ) { handleObj = handlers[ i ]; // Don't conflict with Object.prototype properties (#13203) sel = handleObj.selector + " "; if ( matches[ sel ] === undefined ) { matches[ sel ] = handleObj.needsContext ? jQuery( sel, this ).index( cur ) >= 0 : jQuery.find( sel, this, null, [ cur ] ).length; } if ( matches[ sel ] ) { matches.push( handleObj ); } } if ( matches.length ) { handlerQueue.push({ elem: cur, handlers: matches }); } } } } // Add the remaining (directly-bound) handlers if ( delegateCount < handlers.length ) { handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); } return handlerQueue; }, fix: function( event ) { if ( event[ jQuery.expando ] ) { return event; } // Create a writable copy of the event object and normalize some properties var i, prop, copy, type = event.type, originalEvent = event, fixHook = this.fixHooks[ type ]; if ( !fixHook ) { this.fixHooks[ type ] = fixHook = rmouseEvent.test( type ) ? this.mouseHooks : rkeyEvent.test( type ) ? this.keyHooks : {}; } copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; event = new jQuery.Event( originalEvent ); i = copy.length; while ( i-- ) { prop = copy[ i ]; event[ prop ] = originalEvent[ prop ]; } // Support: IE<9 // Fix target property (#1925) if ( !event.target ) { event.target = originalEvent.srcElement || document; } // Support: Chrome 23+, Safari? // Target should not be a text node (#504, #13143) if ( event.target.nodeType === 3 ) { event.target = event.target.parentNode; } // Support: IE<9 // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) event.metaKey = !!event.metaKey; return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; }, // Includes some event props shared by KeyEvent and MouseEvent props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), fixHooks: {}, keyHooks: { props: "char charCode key keyCode".split(" "), filter: function( event, original ) { // Add which for key events if ( event.which == null ) { event.which = original.charCode != null ? original.charCode : original.keyCode; } return event; } }, mouseHooks: { props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), filter: function( event, original ) { var body, eventDoc, doc, button = original.button, fromElement = original.fromElement; // Calculate pageX/Y if missing and clientX/Y available if ( event.pageX == null && original.clientX != null ) { eventDoc = event.target.ownerDocument || document; doc = eventDoc.documentElement; body = eventDoc.body; event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); } // Add relatedTarget, if necessary if ( !event.relatedTarget && fromElement ) { event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; } // Add which for click: 1 === left; 2 === middle; 3 === right // Note: button is not normalized, so don't use it if ( !event.which && button !== undefined ) { event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); } return event; } }, special: { load: { // Prevent triggered image.load events from bubbling to window.load noBubble: true }, focus: { // Fire native event if possible so blur/focus sequence is correct trigger: function() { if ( this !== safeActiveElement() && this.focus ) { try { this.focus(); return false; } catch ( e ) { // Support: IE<9 // If we error on focus to hidden element (#1486, #12518), // let .trigger() run the handlers } } }, delegateType: "focusin" }, blur: { trigger: function() { if ( this === safeActiveElement() && this.blur ) { this.blur(); return false; } }, delegateType: "focusout" }, click: { // For checkbox, fire native event so checked state will be right trigger: function() { if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { this.click(); return false; } }, // For cross-browser consistency, don't fire native .click() on links _default: function( event ) { return jQuery.nodeName( event.target, "a" ); } }, beforeunload: { postDispatch: function( event ) { // Support: Firefox 20+ // Firefox doesn't alert if the returnValue field is not set. if ( event.result !== undefined && event.originalEvent ) { event.originalEvent.returnValue = event.result; } } } }, simulate: function( type, elem, event, bubble ) { // Piggyback on a donor event to simulate a different one. // Fake originalEvent to avoid donor's stopPropagation, but if the // simulated event prevents default then we do the same on the donor. var e = jQuery.extend( new jQuery.Event(), event, { type: type, isSimulated: true, originalEvent: {} } ); if ( bubble ) { jQuery.event.trigger( e, null, elem ); } else { jQuery.event.dispatch.call( elem, e ); } if ( e.isDefaultPrevented() ) { event.preventDefault(); } } }; jQuery.removeEvent = document.removeEventListener ? function( elem, type, handle ) { if ( elem.removeEventListener ) { elem.removeEventListener( type, handle, false ); } } : function( elem, type, handle ) { var name = "on" + type; if ( elem.detachEvent ) { // #8545, #7054, preventing memory leaks for custom events in IE6-8 // detachEvent needed property on element, by name of that event, to properly expose it to GC if ( typeof elem[ name ] === strundefined ) { elem[ name ] = null; } elem.detachEvent( name, handle ); } }; jQuery.Event = function( src, props ) { // Allow instantiation without the 'new' keyword if ( !(this instanceof jQuery.Event) ) { return new jQuery.Event( src, props ); } // Event object if ( src && src.type ) { this.originalEvent = src; this.type = src.type; // Events bubbling up the document may have been marked as prevented // by a handler lower down the tree; reflect the correct value. this.isDefaultPrevented = src.defaultPrevented || src.defaultPrevented === undefined && // Support: IE < 9, Android < 4.0 src.returnValue === false ? returnTrue : returnFalse; // Event type } else { this.type = src; } // Put explicitly provided properties onto the event object if ( props ) { jQuery.extend( this, props ); } // Create a timestamp if incoming event doesn't have one this.timeStamp = src && src.timeStamp || jQuery.now(); // Mark it as fixed this[ jQuery.expando ] = true; }; // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html jQuery.Event.prototype = { isDefaultPrevented: returnFalse, isPropagationStopped: returnFalse, isImmediatePropagationStopped: returnFalse, preventDefault: function() { var e = this.originalEvent; this.isDefaultPrevented = returnTrue; if ( !e ) { return; } // If preventDefault exists, run it on the original event if ( e.preventDefault ) { e.preventDefault(); // Support: IE // Otherwise set the returnValue property of the original event to false } else { e.returnValue = false; } }, stopPropagation: function() { var e = this.originalEvent; this.isPropagationStopped = returnTrue; if ( !e ) { return; } // If stopPropagation exists, run it on the original event if ( e.stopPropagation ) { e.stopPropagation(); } // Support: IE // Set the cancelBubble property of the original event to true e.cancelBubble = true; }, stopImmediatePropagation: function() { var e = this.originalEvent; this.isImmediatePropagationStopped = returnTrue; if ( e && e.stopImmediatePropagation ) { e.stopImmediatePropagation(); } this.stopPropagation(); } }; // Create mouseenter/leave events using mouseover/out and event-time checks jQuery.each({ mouseenter: "mouseover", mouseleave: "mouseout", pointerenter: "pointerover", pointerleave: "pointerout" }, function( orig, fix ) { jQuery.event.special[ orig ] = { delegateType: fix, bindType: fix, handle: function( event ) { var ret, target = this, related = event.relatedTarget, handleObj = event.handleObj; // For mousenter/leave call the handler if related is outside the target. // NB: No relatedTarget if the mouse left/entered the browser window if ( !related || (related !== target && !jQuery.contains( target, related )) ) { event.type = handleObj.origType; ret = handleObj.handler.apply( this, arguments ); event.type = fix; } return ret; } }; }); // IE submit delegation if ( !support.submitBubbles ) { jQuery.event.special.submit = { setup: function() { // Only need this for delegated form submit events if ( jQuery.nodeName( this, "form" ) ) { return false; } // Lazy-add a submit handler when a descendant form may potentially be submitted jQuery.event.add( this, "click._submit keypress._submit", function( e ) { // Node name check avoids a VML-related crash in IE (#9807) var elem = e.target, form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; if ( form && !jQuery._data( form, "submitBubbles" ) ) { jQuery.event.add( form, "submit._submit", function( event ) { event._submit_bubble = true; }); jQuery._data( form, "submitBubbles", true ); } }); // return undefined since we don't need an event listener }, postDispatch: function( event ) { // If form was submitted by the user, bubble the event up the tree if ( event._submit_bubble ) { delete event._submit_bubble; if ( this.parentNode && !event.isTrigger ) { jQuery.event.simulate( "submit", this.parentNode, event, true ); } } }, teardown: function() { // Only need this for delegated form submit events if ( jQuery.nodeName( this, "form" ) ) { return false; } // Remove delegated handlers; cleanData eventually reaps submit handlers attached above jQuery.event.remove( this, "._submit" ); } }; } // IE change delegation and checkbox/radio fix if ( !support.changeBubbles ) { jQuery.event.special.change = { setup: function() { if ( rformElems.test( this.nodeName ) ) { // IE doesn't fire change on a check/radio until blur; trigger it on click // after a propertychange. Eat the blur-change in special.change.handle. // This still fires onchange a second time for check/radio after blur. if ( this.type === "checkbox" || this.type === "radio" ) { jQuery.event.add( this, "propertychange._change", function( event ) { if ( event.originalEvent.propertyName === "checked" ) { this._just_changed = true; } }); jQuery.event.add( this, "click._change", function( event ) { if ( this._just_changed && !event.isTrigger ) { this._just_changed = false; } // Allow triggered, simulated change events (#11500) jQuery.event.simulate( "change", this, event, true ); }); } return false; } // Delegated event; lazy-add a change handler on descendant inputs jQuery.event.add( this, "beforeactivate._change", function( e ) { var elem = e.target; if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { jQuery.event.add( elem, "change._change", function( event ) { if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { jQuery.event.simulate( "change", this.parentNode, event, true ); } }); jQuery._data( elem, "changeBubbles", true ); } }); }, handle: function( event ) { var elem = event.target; // Swallow native change events from checkbox/radio, we already triggered them above if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { return event.handleObj.handler.apply( this, arguments ); } }, teardown: function() { jQuery.event.remove( this, "._change" ); return !rformElems.test( this.nodeName ); } }; } // Create "bubbling" focus and blur events if ( !support.focusinBubbles ) { jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { // Attach a single capturing handler on the document while someone wants focusin/focusout var handler = function( event ) { jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); }; jQuery.event.special[ fix ] = { setup: function() { var doc = this.ownerDocument || this, attaches = jQuery._data( doc, fix ); if ( !attaches ) { doc.addEventListener( orig, handler, true ); } jQuery._data( doc, fix, ( attaches || 0 ) + 1 ); }, teardown: function() { var doc = this.ownerDocument || this, attaches = jQuery._data( doc, fix ) - 1; if ( !attaches ) { doc.removeEventListener( orig, handler, true ); jQuery._removeData( doc, fix ); } else { jQuery._data( doc, fix, attaches ); } } }; }); } jQuery.fn.extend({ on: function( types, selector, data, fn, /*INTERNAL*/ one ) { var type, origFn; // Types can be a map of types/handlers if ( typeof types === "object" ) { // ( types-Object, selector, data ) if ( typeof selector !== "string" ) { // ( types-Object, data ) data = data || selector; selector = undefined; } for ( type in types ) { this.on( type, selector, data, types[ type ], one ); } return this; } if ( data == null && fn == null ) { // ( types, fn ) fn = selector; data = selector = undefined; } else if ( fn == null ) { if ( typeof selector === "string" ) { // ( types, selector, fn ) fn = data; data = undefined; } else { // ( types, data, fn ) fn = data; data = selector; selector = undefined; } } if ( fn === false ) { fn = returnFalse; } else if ( !fn ) { return this; } if ( one === 1 ) { origFn = fn; fn = function( event ) { // Can use an empty set, since event contains the info jQuery().off( event ); return origFn.apply( this, arguments ); }; // Use same guid so caller can remove using origFn fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); } return this.each( function() { jQuery.event.add( this, types, fn, data, selector ); }); }, one: function( types, selector, data, fn ) { return this.on( types, selector, data, fn, 1 ); }, off: function( types, selector, fn ) { var handleObj, type; if ( types && types.preventDefault && types.handleObj ) { // ( event ) dispatched jQuery.Event handleObj = types.handleObj; jQuery( types.delegateTarget ).off( handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, handleObj.selector, handleObj.handler ); return this; } if ( typeof types === "object" ) { // ( types-object [, selector] ) for ( type in types ) { this.off( type, selector, types[ type ] ); } return this; } if ( selector === false || typeof selector === "function" ) { // ( types [, fn] ) fn = selector; selector = undefined; } if ( fn === false ) { fn = returnFalse; } return this.each(function() { jQuery.event.remove( this, types, fn, selector ); }); }, trigger: function( type, data ) { return this.each(function() { jQuery.event.trigger( type, data, this ); }); }, triggerHandler: function( type, data ) { var elem = this[0]; if ( elem ) { return jQuery.event.trigger( type, data, elem, true ); } } }); function createSafeFragment( document ) { var list = nodeNames.split( "|" ), safeFrag = document.createDocumentFragment(); if ( safeFrag.createElement ) { while ( list.length ) { safeFrag.createElement( list.pop() ); } } return safeFrag; } var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), rleadingWhitespace = /^\s+/, rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, rtagName = /<([\w:]+)/, rtbody = /<tbody/i, rhtml = /<|&#?\w+;/, rnoInnerhtml = /<(?:script|style|link)/i, // checked="checked" or checked rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, rscriptType = /^$|\/(?:java|ecma)script/i, rscriptTypeMasked = /^true\/(.*)/, rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g, // We have to close these tags to support XHTML (#13200) wrapMap = { option: [ 1, "<select multiple='multiple'>", "</select>" ], legend: [ 1, "<fieldset>", "</fieldset>" ], area: [ 1, "<map>", "</map>" ], param: [ 1, "<object>", "</object>" ], thead: [ 1, "<table>", "</table>" ], tr: [ 2, "<table><tbody>", "</tbody></table>" ], col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ], td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, // unless wrapped in a div with non-breaking characters in front of it. _default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>" ] }, safeFragment = createSafeFragment( document ), fragmentDiv = safeFragment.appendChild( document.createElement("div") ); wrapMap.optgroup = wrapMap.option; wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; wrapMap.th = wrapMap.td; function getAll( context, tag ) { var elems, elem, i = 0, found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || "*" ) : typeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || "*" ) : undefined; if ( !found ) { for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { if ( !tag || jQuery.nodeName( elem, tag ) ) { found.push( elem ); } else { jQuery.merge( found, getAll( elem, tag ) ); } } } return tag === undefined || tag && jQuery.nodeName( context, tag ) ? jQuery.merge( [ context ], found ) : found; } // Used in buildFragment, fixes the defaultChecked property function fixDefaultChecked( elem ) { if ( rcheckableType.test( elem.type ) ) { elem.defaultChecked = elem.checked; } } // Support: IE<8 // Manipulating tables requires a tbody function manipulationTarget( elem, content ) { return jQuery.nodeName( elem, "table" ) && jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ? elem.getElementsByTagName("tbody")[0] || elem.appendChild( elem.ownerDocument.createElement("tbody") ) : elem; } // Replace/restore the type attribute of script elements for safe DOM manipulation function disableScript( elem ) { elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type; return elem; } function restoreScript( elem ) { var match = rscriptTypeMasked.exec( elem.type ); if ( match ) { elem.type = match[1]; } else { elem.removeAttribute("type"); } return elem; } // Mark scripts as having already been evaluated function setGlobalEval( elems, refElements ) { var elem, i = 0; for ( ; (elem = elems[i]) != null; i++ ) { jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); } } function cloneCopyEvent( src, dest ) { if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { return; } var type, i, l, oldData = jQuery._data( src ), curData = jQuery._data( dest, oldData ), events = oldData.events; if ( events ) { delete curData.handle; curData.events = {}; for ( type in events ) { for ( i = 0, l = events[ type ].length; i < l; i++ ) { jQuery.event.add( dest, type, events[ type ][ i ] ); } } } // make the cloned public data object a copy from the original if ( curData.data ) { curData.data = jQuery.extend( {}, curData.data ); } } function fixCloneNodeIssues( src, dest ) { var nodeName, e, data; // We do not need to do anything for non-Elements if ( dest.nodeType !== 1 ) { return; } nodeName = dest.nodeName.toLowerCase(); // IE6-8 copies events bound via attachEvent when using cloneNode. if ( !support.noCloneEvent && dest[ jQuery.expando ] ) { data = jQuery._data( dest ); for ( e in data.events ) { jQuery.removeEvent( dest, e, data.handle ); } // Event data gets referenced instead of copied if the expando gets copied too dest.removeAttribute( jQuery.expando ); } // IE blanks contents when cloning scripts, and tries to evaluate newly-set text if ( nodeName === "script" && dest.text !== src.text ) { disableScript( dest ).text = src.text; restoreScript( dest ); // IE6-10 improperly clones children of object elements using classid. // IE10 throws NoModificationAllowedError if parent is null, #12132. } else if ( nodeName === "object" ) { if ( dest.parentNode ) { dest.outerHTML = src.outerHTML; } // This path appears unavoidable for IE9. When cloning an object // element in IE9, the outerHTML strategy above is not sufficient. // If the src has innerHTML and the destination does not, // copy the src.innerHTML into the dest.innerHTML. #10324 if ( support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { dest.innerHTML = src.innerHTML; } } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) { // IE6-8 fails to persist the checked state of a cloned checkbox // or radio button. Worse, IE6-7 fail to give the cloned element // a checked appearance if the defaultChecked value isn't also set dest.defaultChecked = dest.checked = src.checked; // IE6-7 get confused and end up setting the value of a cloned // checkbox/radio button to an empty string instead of "on" if ( dest.value !== src.value ) { dest.value = src.value; } // IE6-8 fails to return the selected option to the default selected // state when cloning options } else if ( nodeName === "option" ) { dest.defaultSelected = dest.selected = src.defaultSelected; // IE6-8 fails to set the defaultValue to the correct value when // cloning other types of input fields } else if ( nodeName === "input" || nodeName === "textarea" ) { dest.defaultValue = src.defaultValue; } } jQuery.extend({ clone: function( elem, dataAndEvents, deepDataAndEvents ) { var destElements, node, clone, i, srcElements, inPage = jQuery.contains( elem.ownerDocument, elem ); if ( support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { clone = elem.cloneNode( true ); // IE<=8 does not properly clone detached, unknown element nodes } else { fragmentDiv.innerHTML = elem.outerHTML; fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); } if ( (!support.noCloneEvent || !support.noCloneChecked) && (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 destElements = getAll( clone ); srcElements = getAll( elem ); // Fix all IE cloning issues for ( i = 0; (node = srcElements[i]) != null; ++i ) { // Ensure that the destination node is not null; Fixes #9587 if ( destElements[i] ) { fixCloneNodeIssues( node, destElements[i] ); } } } // Copy the events from the original to the clone if ( dataAndEvents ) { if ( deepDataAndEvents ) { srcElements = srcElements || getAll( elem ); destElements = destElements || getAll( clone ); for ( i = 0; (node = srcElements[i]) != null; i++ ) { cloneCopyEvent( node, destElements[i] ); } } else { cloneCopyEvent( elem, clone ); } } // Preserve script evaluation history destElements = getAll( clone, "script" ); if ( destElements.length > 0 ) { setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); } destElements = srcElements = node = null; // Return the cloned set return clone; }, buildFragment: function( elems, context, scripts, selection ) { var j, elem, contains, tmp, tag, tbody, wrap, l = elems.length, // Ensure a safe fragment safe = createSafeFragment( context ), nodes = [], i = 0; for ( ; i < l; i++ ) { elem = elems[ i ]; if ( elem || elem === 0 ) { // Add nodes directly if ( jQuery.type( elem ) === "object" ) { jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); // Convert non-html into a text node } else if ( !rhtml.test( elem ) ) { nodes.push( context.createTextNode( elem ) ); // Convert html into DOM nodes } else { tmp = tmp || safe.appendChild( context.createElement("div") ); // Deserialize a standard representation tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase(); wrap = wrapMap[ tag ] || wrapMap._default; tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2]; // Descend through wrappers to the right content j = wrap[0]; while ( j-- ) { tmp = tmp.lastChild; } // Manually add leading whitespace removed by IE if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); } // Remove IE's autoinserted <tbody> from table fragments if ( !support.tbody ) { // String was a <table>, *may* have spurious <tbody> elem = tag === "table" && !rtbody.test( elem ) ? tmp.firstChild : // String was a bare <thead> or <tfoot> wrap[1] === "<table>" && !rtbody.test( elem ) ? tmp : 0; j = elem && elem.childNodes.length; while ( j-- ) { if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { elem.removeChild( tbody ); } } } jQuery.merge( nodes, tmp.childNodes ); // Fix #12392 for WebKit and IE > 9 tmp.textContent = ""; // Fix #12392 for oldIE while ( tmp.firstChild ) { tmp.removeChild( tmp.firstChild ); } // Remember the top-level container for proper cleanup tmp = safe.lastChild; } } } // Fix #11356: Clear elements from fragment if ( tmp ) { safe.removeChild( tmp ); } // Reset defaultChecked for any radios and checkboxes // about to be appended to the DOM in IE 6/7 (#8060) if ( !support.appendChecked ) { jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); } i = 0; while ( (elem = nodes[ i++ ]) ) { // #4087 - If origin and destination elements are the same, and this is // that element, do not do anything if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { continue; } contains = jQuery.contains( elem.ownerDocument, elem ); // Append to fragment tmp = getAll( safe.appendChild( elem ), "script" ); // Preserve script evaluation history if ( contains ) { setGlobalEval( tmp ); } // Capture executables if ( scripts ) { j = 0; while ( (elem = tmp[ j++ ]) ) { if ( rscriptType.test( elem.type || "" ) ) { scripts.push( elem ); } } } } tmp = null; return safe; }, cleanData: function( elems, /* internal */ acceptData ) { var elem, type, id, data, i = 0, internalKey = jQuery.expando, cache = jQuery.cache, deleteExpando = support.deleteExpando, special = jQuery.event.special; for ( ; (elem = elems[i]) != null; i++ ) { if ( acceptData || jQuery.acceptData( elem ) ) { id = elem[ internalKey ]; data = id && cache[ id ]; if ( data ) { if ( data.events ) { for ( type in data.events ) { if ( special[ type ] ) { jQuery.event.remove( elem, type ); // This is a shortcut to avoid jQuery.event.remove's overhead } else { jQuery.removeEvent( elem, type, data.handle ); } } } // Remove cache only if it was not already removed by jQuery.event.remove if ( cache[ id ] ) { delete cache[ id ]; // IE does not allow us to delete expando properties from nodes, // nor does it have a removeAttribute function on Document nodes; // we must handle all of these cases if ( deleteExpando ) { delete elem[ internalKey ]; } else if ( typeof elem.removeAttribute !== strundefined ) { elem.removeAttribute( internalKey ); } else { elem[ internalKey ] = null; } deletedIds.push( id ); } } } } } }); jQuery.fn.extend({ text: function( value ) { return access( this, function( value ) { return value === undefined ? jQuery.text( this ) : this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); }, null, value, arguments.length ); }, append: function() { return this.domManip( arguments, function( elem ) { if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { var target = manipulationTarget( this, elem ); target.appendChild( elem ); } }); }, prepend: function() { return this.domManip( arguments, function( elem ) { if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { var target = manipulationTarget( this, elem ); target.insertBefore( elem, target.firstChild ); } }); }, before: function() { return this.domManip( arguments, function( elem ) { if ( this.parentNode ) { this.parentNode.insertBefore( elem, this ); } }); }, after: function() { return this.domManip( arguments, function( elem ) { if ( this.parentNode ) { this.parentNode.insertBefore( elem, this.nextSibling ); } }); }, remove: function( selector, keepData /* Internal Use Only */ ) { var elem, elems = selector ? jQuery.filter( selector, this ) : this, i = 0; for ( ; (elem = elems[i]) != null; i++ ) { if ( !keepData && elem.nodeType === 1 ) { jQuery.cleanData( getAll( elem ) ); } if ( elem.parentNode ) { if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { setGlobalEval( getAll( elem, "script" ) ); } elem.parentNode.removeChild( elem ); } } return this; }, empty: function() { var elem, i = 0; for ( ; (elem = this[i]) != null; i++ ) { // Remove element nodes and prevent memory leaks if ( elem.nodeType === 1 ) { jQuery.cleanData( getAll( elem, false ) ); } // Remove any remaining nodes while ( elem.firstChild ) { elem.removeChild( elem.firstChild ); } // If this is a select, ensure that it displays empty (#12336) // Support: IE<9 if ( elem.options && jQuery.nodeName( elem, "select" ) ) { elem.options.length = 0; } } return this; }, clone: function( dataAndEvents, deepDataAndEvents ) { dataAndEvents = dataAndEvents == null ? false : dataAndEvents; deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; return this.map(function() { return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); }); }, html: function( value ) { return access( this, function( value ) { var elem = this[ 0 ] || {}, i = 0, l = this.length; if ( value === undefined ) { return elem.nodeType === 1 ? elem.innerHTML.replace( rinlinejQuery, "" ) : undefined; } // See if we can take a shortcut and just use innerHTML if ( typeof value === "string" && !rnoInnerhtml.test( value ) && ( support.htmlSerialize || !rnoshimcache.test( value ) ) && ( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && !wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) { value = value.replace( rxhtmlTag, "<$1></$2>" ); try { for (; i < l; i++ ) { // Remove element nodes and prevent memory leaks elem = this[i] || {}; if ( elem.nodeType === 1 ) { jQuery.cleanData( getAll( elem, false ) ); elem.innerHTML = value; } } elem = 0; // If using innerHTML throws an exception, use the fallback method } catch(e) {} } if ( elem ) { this.empty().append( value ); } }, null, value, arguments.length ); }, replaceWith: function() { var arg = arguments[ 0 ]; // Make the changes, replacing each context element with the new content this.domManip( arguments, function( elem ) { arg = this.parentNode; jQuery.cleanData( getAll( this ) ); if ( arg ) { arg.replaceChild( elem, this ); } }); // Force removal if there was no new content (e.g., from empty arguments) return arg && (arg.length || arg.nodeType) ? this : this.remove(); }, detach: function( selector ) { return this.remove( selector, true ); }, domManip: function( args, callback ) { // Flatten any nested arrays args = concat.apply( [], args ); var first, node, hasScripts, scripts, doc, fragment, i = 0, l = this.length, set = this, iNoClone = l - 1, value = args[0], isFunction = jQuery.isFunction( value ); // We can't cloneNode fragments that contain checked, in WebKit if ( isFunction || ( l > 1 && typeof value === "string" && !support.checkClone && rchecked.test( value ) ) ) { return this.each(function( index ) { var self = set.eq( index ); if ( isFunction ) { args[0] = value.call( this, index, self.html() ); } self.domManip( args, callback ); }); } if ( l ) { fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); first = fragment.firstChild; if ( fragment.childNodes.length === 1 ) { fragment = first; } if ( first ) { scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); hasScripts = scripts.length; // Use the original fragment for the last item instead of the first because it can end up // being emptied incorrectly in certain situations (#8070). for ( ; i < l; i++ ) { node = fragment; if ( i !== iNoClone ) { node = jQuery.clone( node, true, true ); // Keep references to cloned scripts for later restoration if ( hasScripts ) { jQuery.merge( scripts, getAll( node, "script" ) ); } } callback.call( this[i], node, i ); } if ( hasScripts ) { doc = scripts[ scripts.length - 1 ].ownerDocument; // Reenable scripts jQuery.map( scripts, restoreScript ); // Evaluate executable scripts on first document insertion for ( i = 0; i < hasScripts; i++ ) { node = scripts[ i ]; if ( rscriptType.test( node.type || "" ) && !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { if ( node.src ) { // Optional AJAX dependency, but won't run scripts if not present if ( jQuery._evalUrl ) { jQuery._evalUrl( node.src ); } } else { jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); } } } } // Fix #11809: Avoid leaking memory fragment = first = null; } } return this; } }); jQuery.each({ appendTo: "append", prependTo: "prepend", insertBefore: "before", insertAfter: "after", replaceAll: "replaceWith" }, function( name, original ) { jQuery.fn[ name ] = function( selector ) { var elems, i = 0, ret = [], insert = jQuery( selector ), last = insert.length - 1; for ( ; i <= last; i++ ) { elems = i === last ? this : this.clone(true); jQuery( insert[i] )[ original ]( elems ); // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() push.apply( ret, elems.get() ); } return this.pushStack( ret ); }; }); var iframe, elemdisplay = {}; /** * Retrieve the actual display of a element * @param {String} name nodeName of the element * @param {Object} doc Document object */ // Called only from within defaultDisplay function actualDisplay( name, doc ) { var style, elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), // getDefaultComputedStyle might be reliably used only on attached element display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ? // Use of this method is a temporary fix (more like optmization) until something better comes along, // since it was removed from specification and supported only in FF style.display : jQuery.css( elem[ 0 ], "display" ); // We don't have any data stored on the element, // so use "detach" method as fast way to get rid of the element elem.detach(); return display; } /** * Try to determine the default display value of an element * @param {String} nodeName */ function defaultDisplay( nodeName ) { var doc = document, display = elemdisplay[ nodeName ]; if ( !display ) { display = actualDisplay( nodeName, doc ); // If the simple way fails, read from inside an iframe if ( display === "none" || !display ) { // Use the already-created iframe if possible iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement ); // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse doc = ( iframe[ 0 ].contentWindow || iframe[ 0 ].contentDocument ).document; // Support: IE doc.write(); doc.close(); display = actualDisplay( nodeName, doc ); iframe.detach(); } // Store the correct default display elemdisplay[ nodeName ] = display; } return display; } (function() { var shrinkWrapBlocksVal; support.shrinkWrapBlocks = function() { if ( shrinkWrapBlocksVal != null ) { return shrinkWrapBlocksVal; } // Will be changed later if needed. shrinkWrapBlocksVal = false; // Minified: var b,c,d var div, body, container; body = document.getElementsByTagName( "body" )[ 0 ]; if ( !body || !body.style ) { // Test fired too early or in an unsupported environment, exit. return; } // Setup div = document.createElement( "div" ); container = document.createElement( "div" ); container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px"; body.appendChild( container ).appendChild( div ); // Support: IE6 // Check if elements with layout shrink-wrap their children if ( typeof div.style.zoom !== strundefined ) { // Reset CSS: box-sizing; display; margin; border div.style.cssText = // Support: Firefox<29, Android 2.3 // Vendor-prefix box-sizing "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" + "box-sizing:content-box;display:block;margin:0;border:0;" + "padding:1px;width:1px;zoom:1"; div.appendChild( document.createElement( "div" ) ).style.width = "5px"; shrinkWrapBlocksVal = div.offsetWidth !== 3; } body.removeChild( container ); return shrinkWrapBlocksVal; }; })(); var rmargin = (/^margin/); var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); var getStyles, curCSS, rposition = /^(top|right|bottom|left)$/; if ( window.getComputedStyle ) { getStyles = function( elem ) { // Support: IE<=11+, Firefox<=30+ (#15098, #14150) // IE throws on elements created in popups // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" if ( elem.ownerDocument.defaultView.opener ) { return elem.ownerDocument.defaultView.getComputedStyle( elem, null ); } return window.getComputedStyle( elem, null ); }; curCSS = function( elem, name, computed ) { var width, minWidth, maxWidth, ret, style = elem.style; computed = computed || getStyles( elem ); // getPropertyValue is only needed for .css('filter') in IE9, see #12537 ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined; if ( computed ) { if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { ret = jQuery.style( elem, name ); } // A tribute to the "awesome hack by Dean Edwards" // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { // Remember the original values width = style.width; minWidth = style.minWidth; maxWidth = style.maxWidth; // Put in the new values to get a computed value out style.minWidth = style.maxWidth = style.width = ret; ret = computed.width; // Revert the changed values style.width = width; style.minWidth = minWidth; style.maxWidth = maxWidth; } } // Support: IE // IE returns zIndex value as an integer. return ret === undefined ? ret : ret + ""; }; } else if ( document.documentElement.currentStyle ) { getStyles = function( elem ) { return elem.currentStyle; }; curCSS = function( elem, name, computed ) { var left, rs, rsLeft, ret, style = elem.style; computed = computed || getStyles( elem ); ret = computed ? computed[ name ] : undefined; // Avoid setting ret to empty string here // so we don't default to auto if ( ret == null && style && style[ name ] ) { ret = style[ name ]; } // From the awesome hack by Dean Edwards // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 // If we're not dealing with a regular pixel number // but a number that has a weird ending, we need to convert it to pixels // but not position css attributes, as those are proportional to the parent element instead // and we can't measure the parent instead because it might trigger a "stacking dolls" problem if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) { // Remember the original values left = style.left; rs = elem.runtimeStyle; rsLeft = rs && rs.left; // Put in the new values to get a computed value out if ( rsLeft ) { rs.left = elem.currentStyle.left; } style.left = name === "fontSize" ? "1em" : ret; ret = style.pixelLeft + "px"; // Revert the changed values style.left = left; if ( rsLeft ) { rs.left = rsLeft; } } // Support: IE // IE returns zIndex value as an integer. return ret === undefined ? ret : ret + "" || "auto"; }; } function addGetHookIf( conditionFn, hookFn ) { // Define the hook, we'll check on the first run if it's really needed. return { get: function() { var condition = conditionFn(); if ( condition == null ) { // The test was not ready at this point; screw the hook this time // but check again when needed next time. return; } if ( condition ) { // Hook not needed (or it's not possible to use it due to missing dependency), // remove it. // Since there are no other hooks for marginRight, remove the whole object. delete this.get; return; } // Hook needed; redefine it so that the support test is not executed again. return (this.get = hookFn).apply( this, arguments ); } }; } (function() { // Minified: var b,c,d,e,f,g, h,i var div, style, a, pixelPositionVal, boxSizingReliableVal, reliableHiddenOffsetsVal, reliableMarginRightVal; // Setup div = document.createElement( "div" ); div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>"; a = div.getElementsByTagName( "a" )[ 0 ]; style = a && a.style; // Finish early in limited (non-browser) environments if ( !style ) { return; } style.cssText = "float:left;opacity:.5"; // Support: IE<9 // Make sure that element opacity exists (as opposed to filter) support.opacity = style.opacity === "0.5"; // Verify style float existence // (IE uses styleFloat instead of cssFloat) support.cssFloat = !!style.cssFloat; div.style.backgroundClip = "content-box"; div.cloneNode( true ).style.backgroundClip = ""; support.clearCloneStyle = div.style.backgroundClip === "content-box"; // Support: Firefox<29, Android 2.3 // Vendor-prefix box-sizing support.boxSizing = style.boxSizing === "" || style.MozBoxSizing === "" || style.WebkitBoxSizing === ""; jQuery.extend(support, { reliableHiddenOffsets: function() { if ( reliableHiddenOffsetsVal == null ) { computeStyleTests(); } return reliableHiddenOffsetsVal; }, boxSizingReliable: function() { if ( boxSizingReliableVal == null ) { computeStyleTests(); } return boxSizingReliableVal; }, pixelPosition: function() { if ( pixelPositionVal == null ) { computeStyleTests(); } return pixelPositionVal; }, // Support: Android 2.3 reliableMarginRight: function() { if ( reliableMarginRightVal == null ) { computeStyleTests(); } return reliableMarginRightVal; } }); function computeStyleTests() { // Minified: var b,c,d,j var div, body, container, contents; body = document.getElementsByTagName( "body" )[ 0 ]; if ( !body || !body.style ) { // Test fired too early or in an unsupported environment, exit. return; } // Setup div = document.createElement( "div" ); container = document.createElement( "div" ); container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px"; body.appendChild( container ).appendChild( div ); div.style.cssText = // Support: Firefox<29, Android 2.3 // Vendor-prefix box-sizing "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" + "box-sizing:border-box;display:block;margin-top:1%;top:1%;" + "border:1px;padding:1px;width:4px;position:absolute"; // Support: IE<9 // Assume reasonable values in the absence of getComputedStyle pixelPositionVal = boxSizingReliableVal = false; reliableMarginRightVal = true; // Check for getComputedStyle so that this code is not run in IE<9. if ( window.getComputedStyle ) { pixelPositionVal = ( window.getComputedStyle( div, null ) || {} ).top !== "1%"; boxSizingReliableVal = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px"; // Support: Android 2.3 // Div with explicit width and no margin-right incorrectly // gets computed margin-right based on width of container (#3333) // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right contents = div.appendChild( document.createElement( "div" ) ); // Reset CSS: box-sizing; display; margin; border; padding contents.style.cssText = div.style.cssText = // Support: Firefox<29, Android 2.3 // Vendor-prefix box-sizing "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" + "box-sizing:content-box;display:block;margin:0;border:0;padding:0"; contents.style.marginRight = contents.style.width = "0"; div.style.width = "1px"; reliableMarginRightVal = !parseFloat( ( window.getComputedStyle( contents, null ) || {} ).marginRight ); div.removeChild( contents ); } // Support: IE8 // Check if table cells still have offsetWidth/Height when they are set // to display:none and there are still other visible table cells in a // table row; if so, offsetWidth/Height are not reliable for use when // determining if an element has been hidden directly using // display:none (it is still safe to use offsets if a parent element is // hidden; don safety goggles and see bug #4512 for more information). div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>"; contents = div.getElementsByTagName( "td" ); contents[ 0 ].style.cssText = "margin:0;border:0;padding:0;display:none"; reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0; if ( reliableHiddenOffsetsVal ) { contents[ 0 ].style.display = ""; contents[ 1 ].style.display = "none"; reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0; } body.removeChild( container ); } })(); // A method for quickly swapping in/out CSS properties to get correct calculations. jQuery.swap = function( elem, options, callback, args ) { var ret, name, old = {}; // Remember the old values, and insert the new ones for ( name in options ) { old[ name ] = elem.style[ name ]; elem.style[ name ] = options[ name ]; } ret = callback.apply( elem, args || [] ); // Revert the old values for ( name in options ) { elem.style[ name ] = old[ name ]; } return ret; }; var ralpha = /alpha\([^)]*\)/i, ropacity = /opacity\s*=\s*([^)]*)/, // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display rdisplayswap = /^(none|table(?!-c[ea]).+)/, rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ), rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ), cssShow = { position: "absolute", visibility: "hidden", display: "block" }, cssNormalTransform = { letterSpacing: "0", fontWeight: "400" }, cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; // return a css property mapped to a potentially vendor prefixed property function vendorPropName( style, name ) { // shortcut for names that are not vendor prefixed if ( name in style ) { return name; } // check for vendor prefixed names var capName = name.charAt(0).toUpperCase() + name.slice(1), origName = name, i = cssPrefixes.length; while ( i-- ) { name = cssPrefixes[ i ] + capName; if ( name in style ) { return name; } } return origName; } function showHide( elements, show ) { var display, elem, hidden, values = [], index = 0, length = elements.length; for ( ; index < length; index++ ) { elem = elements[ index ]; if ( !elem.style ) { continue; } values[ index ] = jQuery._data( elem, "olddisplay" ); display = elem.style.display; if ( show ) { // Reset the inline display of this element to learn if it is // being hidden by cascaded rules or not if ( !values[ index ] && display === "none" ) { elem.style.display = ""; } // Set elements which have been overridden with display: none // in a stylesheet to whatever the default browser style is // for such an element if ( elem.style.display === "" && isHidden( elem ) ) { values[ index ] = jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) ); } } else { hidden = isHidden( elem ); if ( display && display !== "none" || !hidden ) { jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) ); } } } // Set the display of most of the elements in a second loop // to avoid the constant reflow for ( index = 0; index < length; index++ ) { elem = elements[ index ]; if ( !elem.style ) { continue; } if ( !show || elem.style.display === "none" || elem.style.display === "" ) { elem.style.display = show ? values[ index ] || "" : "none"; } } return elements; } function setPositiveNumber( elem, value, subtract ) { var matches = rnumsplit.exec( value ); return matches ? // Guard against undefined "subtract", e.g., when used as in cssHooks Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : value; } function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { var i = extra === ( isBorderBox ? "border" : "content" ) ? // If we already have the right measurement, avoid augmentation 4 : // Otherwise initialize for horizontal or vertical properties name === "width" ? 1 : 0, val = 0; for ( ; i < 4; i += 2 ) { // both box models exclude margin, so add it if we want it if ( extra === "margin" ) { val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); } if ( isBorderBox ) { // border-box includes padding, so remove it if we want content if ( extra === "content" ) { val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); } // at this point, extra isn't border nor margin, so remove border if ( extra !== "margin" ) { val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); } } else { // at this point, extra isn't content, so add padding val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); // at this point, extra isn't content nor padding, so add border if ( extra !== "padding" ) { val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); } } } return val; } function getWidthOrHeight( elem, name, extra ) { // Start with offset property, which is equivalent to the border-box value var valueIsBorderBox = true, val = name === "width" ? elem.offsetWidth : elem.offsetHeight, styles = getStyles( elem ), isBorderBox = support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; // some non-html elements return undefined for offsetWidth, so check for null/undefined // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 if ( val <= 0 || val == null ) { // Fall back to computed then uncomputed css if necessary val = curCSS( elem, name, styles ); if ( val < 0 || val == null ) { val = elem.style[ name ]; } // Computed unit is not pixels. Stop here and return. if ( rnumnonpx.test(val) ) { return val; } // we need the check for style in case a browser which returns unreliable values // for getComputedStyle silently falls back to the reliable elem.style valueIsBorderBox = isBorderBox && ( support.boxSizingReliable() || val === elem.style[ name ] ); // Normalize "", auto, and prepare for extra val = parseFloat( val ) || 0; } // use the active box-sizing model to add/subtract irrelevant styles return ( val + augmentWidthOrHeight( elem, name, extra || ( isBorderBox ? "border" : "content" ), valueIsBorderBox, styles ) ) + "px"; } jQuery.extend({ // Add in style property hooks for overriding the default // behavior of getting and setting a style property cssHooks: { opacity: { get: function( elem, computed ) { if ( computed ) { // We should always get a number back from opacity var ret = curCSS( elem, "opacity" ); return ret === "" ? "1" : ret; } } } }, // Don't automatically add "px" to these possibly-unitless properties cssNumber: { "columnCount": true, "fillOpacity": true, "flexGrow": true, "flexShrink": true, "fontWeight": true, "lineHeight": true, "opacity": true, "order": true, "orphans": true, "widows": true, "zIndex": true, "zoom": true }, // Add in properties whose names you wish to fix before // setting or getting the value cssProps: { // normalize float css property "float": support.cssFloat ? "cssFloat" : "styleFloat" }, // Get and set the style property on a DOM Node style: function( elem, name, value, extra ) { // Don't set styles on text and comment nodes if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { return; } // Make sure that we're working with the right name var ret, type, hooks, origName = jQuery.camelCase( name ), style = elem.style; name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); // gets hook for the prefixed version // followed by the unprefixed version hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; // Check if we're setting a value if ( value !== undefined ) { type = typeof value; // convert relative number strings (+= or -=) to relative numbers. #7345 if ( type === "string" && (ret = rrelNum.exec( value )) ) { value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); // Fixes bug #9237 type = "number"; } // Make sure that null and NaN values aren't set. See: #7116 if ( value == null || value !== value ) { return; } // If a number was passed in, add 'px' to the (except for certain CSS properties) if ( type === "number" && !jQuery.cssNumber[ origName ] ) { value += "px"; } // Fixes #8908, it can be done more correctly by specifing setters in cssHooks, // but it would mean to define eight (for every problematic property) identical functions if ( !support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) { style[ name ] = "inherit"; } // If a hook was provided, use that value, otherwise just set the specified value if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { // Support: IE // Swallow errors from 'invalid' CSS values (#5509) try { style[ name ] = value; } catch(e) {} } } else { // If a hook was provided get the non-computed value from there if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { return ret; } // Otherwise just get the value from the style object return style[ name ]; } }, css: function( elem, name, extra, styles ) { var num, val, hooks, origName = jQuery.camelCase( name ); // Make sure that we're working with the right name name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); // gets hook for the prefixed version // followed by the unprefixed version hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; // If a hook was provided get the computed value from there if ( hooks && "get" in hooks ) { val = hooks.get( elem, true, extra ); } // Otherwise, if a way to get the computed value exists, use that if ( val === undefined ) { val = curCSS( elem, name, styles ); } //convert "normal" to computed value if ( val === "normal" && name in cssNormalTransform ) { val = cssNormalTransform[ name ]; } // Return, converting to number if forced or a qualifier was provided and val looks numeric if ( extra === "" || extra ) { num = parseFloat( val ); return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; } return val; } }); jQuery.each([ "height", "width" ], function( i, name ) { jQuery.cssHooks[ name ] = { get: function( elem, computed, extra ) { if ( computed ) { // certain elements can have dimension info if we invisibly show them // however, it must have a current display style that would benefit from this return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ? jQuery.swap( elem, cssShow, function() { return getWidthOrHeight( elem, name, extra ); }) : getWidthOrHeight( elem, name, extra ); } }, set: function( elem, value, extra ) { var styles = extra && getStyles( elem ); return setPositiveNumber( elem, value, extra ? augmentWidthOrHeight( elem, name, extra, support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box", styles ) : 0 ); } }; }); if ( !support.opacity ) { jQuery.cssHooks.opacity = { get: function( elem, computed ) { // IE uses filters for opacity return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ? ( 0.01 * parseFloat( RegExp.$1 ) ) + "" : computed ? "1" : ""; }, set: function( elem, value ) { var style = elem.style, currentStyle = elem.currentStyle, opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "", filter = currentStyle && currentStyle.filter || style.filter || ""; // IE has trouble with opacity if it does not have layout // Force it by setting the zoom level style.zoom = 1; // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652 // if value === "", then remove inline opacity #12685 if ( ( value >= 1 || value === "" ) && jQuery.trim( filter.replace( ralpha, "" ) ) === "" && style.removeAttribute ) { // Setting style.filter to null, "" & " " still leave "filter:" in the cssText // if "filter:" is present at all, clearType is disabled, we want to avoid this // style.removeAttribute is IE Only, but so apparently is this code path... style.removeAttribute( "filter" ); // if there is no filter style applied in a css rule or unset inline opacity, we are done if ( value === "" || currentStyle && !currentStyle.filter ) { return; } } // otherwise, set new filter values style.filter = ralpha.test( filter ) ? filter.replace( ralpha, opacity ) : filter + " " + opacity; } }; } jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight, function( elem, computed ) { if ( computed ) { // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right // Work around by temporarily setting element display to inline-block return jQuery.swap( elem, { "display": "inline-block" }, curCSS, [ elem, "marginRight" ] ); } } ); // These hooks are used by animate to expand properties jQuery.each({ margin: "", padding: "", border: "Width" }, function( prefix, suffix ) { jQuery.cssHooks[ prefix + suffix ] = { expand: function( value ) { var i = 0, expanded = {}, // assumes a single number if not a string parts = typeof value === "string" ? value.split(" ") : [ value ]; for ( ; i < 4; i++ ) { expanded[ prefix + cssExpand[ i ] + suffix ] = parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; } return expanded; } }; if ( !rmargin.test( prefix ) ) { jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; } }); jQuery.fn.extend({ css: function( name, value ) { return access( this, function( elem, name, value ) { var styles, len, map = {}, i = 0; if ( jQuery.isArray( name ) ) { styles = getStyles( elem ); len = name.length; for ( ; i < len; i++ ) { map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); } return map; } return value !== undefined ? jQuery.style( elem, name, value ) : jQuery.css( elem, name ); }, name, value, arguments.length > 1 ); }, show: function() { return showHide( this, true ); }, hide: function() { return showHide( this ); }, toggle: function( state ) { if ( typeof state === "boolean" ) { return state ? this.show() : this.hide(); } return this.each(function() { if ( isHidden( this ) ) { jQuery( this ).show(); } else { jQuery( this ).hide(); } }); } }); function Tween( elem, options, prop, end, easing ) { return new Tween.prototype.init( elem, options, prop, end, easing ); } jQuery.Tween = Tween; Tween.prototype = { constructor: Tween, init: function( elem, options, prop, end, easing, unit ) { this.elem = elem; this.prop = prop; this.easing = easing || "swing"; this.options = options; this.start = this.now = this.cur(); this.end = end; this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); }, cur: function() { var hooks = Tween.propHooks[ this.prop ]; return hooks && hooks.get ? hooks.get( this ) : Tween.propHooks._default.get( this ); }, run: function( percent ) { var eased, hooks = Tween.propHooks[ this.prop ]; if ( this.options.duration ) { this.pos = eased = jQuery.easing[ this.easing ]( percent, this.options.duration * percent, 0, 1, this.options.duration ); } else { this.pos = eased = percent; } this.now = ( this.end - this.start ) * eased + this.start; if ( this.options.step ) { this.options.step.call( this.elem, this.now, this ); } if ( hooks && hooks.set ) { hooks.set( this ); } else { Tween.propHooks._default.set( this ); } return this; } }; Tween.prototype.init.prototype = Tween.prototype; Tween.propHooks = { _default: { get: function( tween ) { var result; if ( tween.elem[ tween.prop ] != null && (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) { return tween.elem[ tween.prop ]; } // passing an empty string as a 3rd parameter to .css will automatically // attempt a parseFloat and fallback to a string if the parse fails // so, simple values such as "10px" are parsed to Float. // complex values such as "rotate(1rad)" are returned as is. result = jQuery.css( tween.elem, tween.prop, "" ); // Empty strings, null, undefined and "auto" are converted to 0. return !result || result === "auto" ? 0 : result; }, set: function( tween ) { // use step hook for back compat - use cssHook if its there - use .style if its // available and use plain properties where available if ( jQuery.fx.step[ tween.prop ] ) { jQuery.fx.step[ tween.prop ]( tween ); } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) { jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); } else { tween.elem[ tween.prop ] = tween.now; } } } }; // Support: IE <=9 // Panic based approach to setting things on disconnected nodes Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { set: function( tween ) { if ( tween.elem.nodeType && tween.elem.parentNode ) { tween.elem[ tween.prop ] = tween.now; } } }; jQuery.easing = { linear: function( p ) { return p; }, swing: function( p ) { return 0.5 - Math.cos( p * Math.PI ) / 2; } }; jQuery.fx = Tween.prototype.init; // Back Compat <1.8 extension point jQuery.fx.step = {}; var fxNow, timerId, rfxtypes = /^(?:toggle|show|hide)$/, rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ), rrun = /queueHooks$/, animationPrefilters = [ defaultPrefilter ], tweeners = { "*": [ function( prop, value ) { var tween = this.createTween( prop, value ), target = tween.cur(), parts = rfxnum.exec( value ), unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), // Starting value computation is required for potential unit mismatches start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) && rfxnum.exec( jQuery.css( tween.elem, prop ) ), scale = 1, maxIterations = 20; if ( start && start[ 3 ] !== unit ) { // Trust units reported by jQuery.css unit = unit || start[ 3 ]; // Make sure we update the tween properties later on parts = parts || []; // Iteratively approximate from a nonzero starting point start = +target || 1; do { // If previous iteration zeroed out, double until we get *something* // Use a string for doubling factor so we don't accidentally see scale as unchanged below scale = scale || ".5"; // Adjust and apply start = start / scale; jQuery.style( tween.elem, prop, start + unit ); // Update scale, tolerating zero or NaN from tween.cur() // And breaking the loop if scale is unchanged or perfect, or if we've just had enough } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations ); } // Update tween properties if ( parts ) { start = tween.start = +start || +target || 0; tween.unit = unit; // If a +=/-= token was provided, we're doing a relative animation tween.end = parts[ 1 ] ? start + ( parts[ 1 ] + 1 ) * parts[ 2 ] : +parts[ 2 ]; } return tween; } ] }; // Animations created synchronously will run synchronously function createFxNow() { setTimeout(function() { fxNow = undefined; }); return ( fxNow = jQuery.now() ); } // Generate parameters to create a standard animation function genFx( type, includeWidth ) { var which, attrs = { height: type }, i = 0; // if we include width, step value is 1 to do all cssExpand values, // if we don't include width, step value is 2 to skip over Left and Right includeWidth = includeWidth ? 1 : 0; for ( ; i < 4 ; i += 2 - includeWidth ) { which = cssExpand[ i ]; attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; } if ( includeWidth ) { attrs.opacity = attrs.width = type; } return attrs; } function createTween( value, prop, animation ) { var tween, collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ), index = 0, length = collection.length; for ( ; index < length; index++ ) { if ( (tween = collection[ index ].call( animation, prop, value )) ) { // we're done with this property return tween; } } } function defaultPrefilter( elem, props, opts ) { /* jshint validthis: true */ var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay, anim = this, orig = {}, style = elem.style, hidden = elem.nodeType && isHidden( elem ), dataShow = jQuery._data( elem, "fxshow" ); // handle queue: false promises if ( !opts.queue ) { hooks = jQuery._queueHooks( elem, "fx" ); if ( hooks.unqueued == null ) { hooks.unqueued = 0; oldfire = hooks.empty.fire; hooks.empty.fire = function() { if ( !hooks.unqueued ) { oldfire(); } }; } hooks.unqueued++; anim.always(function() { // doing this makes sure that the complete handler will be called // before this completes anim.always(function() { hooks.unqueued--; if ( !jQuery.queue( elem, "fx" ).length ) { hooks.empty.fire(); } }); }); } // height/width overflow pass if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) { // Make sure that nothing sneaks out // Record all 3 overflow attributes because IE does not // change the overflow attribute when overflowX and // overflowY are set to the same value opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; // Set display property to inline-block for height/width // animations on inline elements that are having width/height animated display = jQuery.css( elem, "display" ); // Test default display if display is currently "none" checkDisplay = display === "none" ? jQuery._data( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display; if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) { // inline-level elements accept inline-block; // block-level elements need to be inline with layout if ( !support.inlineBlockNeedsLayout || defaultDisplay( elem.nodeName ) === "inline" ) { style.display = "inline-block"; } else { style.zoom = 1; } } } if ( opts.overflow ) { style.overflow = "hidden"; if ( !support.shrinkWrapBlocks() ) { anim.always(function() { style.overflow = opts.overflow[ 0 ]; style.overflowX = opts.overflow[ 1 ]; style.overflowY = opts.overflow[ 2 ]; }); } } // show/hide pass for ( prop in props ) { value = props[ prop ]; if ( rfxtypes.exec( value ) ) { delete props[ prop ]; toggle = toggle || value === "toggle"; if ( value === ( hidden ? "hide" : "show" ) ) { // If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { hidden = true; } else { continue; } } orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); // Any non-fx value stops us from restoring the original display value } else { display = undefined; } } if ( !jQuery.isEmptyObject( orig ) ) { if ( dataShow ) { if ( "hidden" in dataShow ) { hidden = dataShow.hidden; } } else { dataShow = jQuery._data( elem, "fxshow", {} ); } // store state if its toggle - enables .stop().toggle() to "reverse" if ( toggle ) { dataShow.hidden = !hidden; } if ( hidden ) { jQuery( elem ).show(); } else { anim.done(function() { jQuery( elem ).hide(); }); } anim.done(function() { var prop; jQuery._removeData( elem, "fxshow" ); for ( prop in orig ) { jQuery.style( elem, prop, orig[ prop ] ); } }); for ( prop in orig ) { tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); if ( !( prop in dataShow ) ) { dataShow[ prop ] = tween.start; if ( hidden ) { tween.end = tween.start; tween.start = prop === "width" || prop === "height" ? 1 : 0; } } } // If this is a noop like .hide().hide(), restore an overwritten display value } else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) { style.display = display; } } function propFilter( props, specialEasing ) { var index, name, easing, value, hooks; // camelCase, specialEasing and expand cssHook pass for ( index in props ) { name = jQuery.camelCase( index ); easing = specialEasing[ name ]; value = props[ index ]; if ( jQuery.isArray( value ) ) { easing = value[ 1 ]; value = props[ index ] = value[ 0 ]; } if ( index !== name ) { props[ name ] = value; delete props[ index ]; } hooks = jQuery.cssHooks[ name ]; if ( hooks && "expand" in hooks ) { value = hooks.expand( value ); delete props[ name ]; // not quite $.extend, this wont overwrite keys already present. // also - reusing 'index' from above because we have the correct "name" for ( index in value ) { if ( !( index in props ) ) { props[ index ] = value[ index ]; specialEasing[ index ] = easing; } } } else { specialEasing[ name ] = easing; } } } function Animation( elem, properties, options ) { var result, stopped, index = 0, length = animationPrefilters.length, deferred = jQuery.Deferred().always( function() { // don't match elem in the :animated selector delete tick.elem; }), tick = function() { if ( stopped ) { return false; } var currentTime = fxNow || createFxNow(), remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497) temp = remaining / animation.duration || 0, percent = 1 - temp, index = 0, length = animation.tweens.length; for ( ; index < length ; index++ ) { animation.tweens[ index ].run( percent ); } deferred.notifyWith( elem, [ animation, percent, remaining ]); if ( percent < 1 && length ) { return remaining; } else { deferred.resolveWith( elem, [ animation ] ); return false; } }, animation = deferred.promise({ elem: elem, props: jQuery.extend( {}, properties ), opts: jQuery.extend( true, { specialEasing: {} }, options ), originalProperties: properties, originalOptions: options, startTime: fxNow || createFxNow(), duration: options.duration, tweens: [], createTween: function( prop, end ) { var tween = jQuery.Tween( elem, animation.opts, prop, end, animation.opts.specialEasing[ prop ] || animation.opts.easing ); animation.tweens.push( tween ); return tween; }, stop: function( gotoEnd ) { var index = 0, // if we are going to the end, we want to run all the tweens // otherwise we skip this part length = gotoEnd ? animation.tweens.length : 0; if ( stopped ) { return this; } stopped = true; for ( ; index < length ; index++ ) { animation.tweens[ index ].run( 1 ); } // resolve when we played the last frame // otherwise, reject if ( gotoEnd ) { deferred.resolveWith( elem, [ animation, gotoEnd ] ); } else { deferred.rejectWith( elem, [ animation, gotoEnd ] ); } return this; } }), props = animation.props; propFilter( props, animation.opts.specialEasing ); for ( ; index < length ; index++ ) { result = animationPrefilters[ index ].call( animation, elem, props, animation.opts ); if ( result ) { return result; } } jQuery.map( props, createTween, animation ); if ( jQuery.isFunction( animation.opts.start ) ) { animation.opts.start.call( elem, animation ); } jQuery.fx.timer( jQuery.extend( tick, { elem: elem, anim: animation, queue: animation.opts.queue }) ); // attach callbacks from options return animation.progress( animation.opts.progress ) .done( animation.opts.done, animation.opts.complete ) .fail( animation.opts.fail ) .always( animation.opts.always ); } jQuery.Animation = jQuery.extend( Animation, { tweener: function( props, callback ) { if ( jQuery.isFunction( props ) ) { callback = props; props = [ "*" ]; } else { props = props.split(" "); } var prop, index = 0, length = props.length; for ( ; index < length ; index++ ) { prop = props[ index ]; tweeners[ prop ] = tweeners[ prop ] || []; tweeners[ prop ].unshift( callback ); } }, prefilter: function( callback, prepend ) { if ( prepend ) { animationPrefilters.unshift( callback ); } else { animationPrefilters.push( callback ); } } }); jQuery.speed = function( speed, easing, fn ) { var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { complete: fn || !fn && easing || jQuery.isFunction( speed ) && speed, duration: speed, easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing }; opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default; // normalize opt.queue - true/undefined/null -> "fx" if ( opt.queue == null || opt.queue === true ) { opt.queue = "fx"; } // Queueing opt.old = opt.complete; opt.complete = function() { if ( jQuery.isFunction( opt.old ) ) { opt.old.call( this ); } if ( opt.queue ) { jQuery.dequeue( this, opt.queue ); } }; return opt; }; jQuery.fn.extend({ fadeTo: function( speed, to, easing, callback ) { // show any hidden elements after setting opacity to 0 return this.filter( isHidden ).css( "opacity", 0 ).show() // animate to the value specified .end().animate({ opacity: to }, speed, easing, callback ); }, animate: function( prop, speed, easing, callback ) { var empty = jQuery.isEmptyObject( prop ), optall = jQuery.speed( speed, easing, callback ), doAnimation = function() { // Operate on a copy of prop so per-property easing won't be lost var anim = Animation( this, jQuery.extend( {}, prop ), optall ); // Empty animations, or finishing resolves immediately if ( empty || jQuery._data( this, "finish" ) ) { anim.stop( true ); } }; doAnimation.finish = doAnimation; return empty || optall.queue === false ? this.each( doAnimation ) : this.queue( optall.queue, doAnimation ); }, stop: function( type, clearQueue, gotoEnd ) { var stopQueue = function( hooks ) { var stop = hooks.stop; delete hooks.stop; stop( gotoEnd ); }; if ( typeof type !== "string" ) { gotoEnd = clearQueue; clearQueue = type; type = undefined; } if ( clearQueue && type !== false ) { this.queue( type || "fx", [] ); } return this.each(function() { var dequeue = true, index = type != null && type + "queueHooks", timers = jQuery.timers, data = jQuery._data( this ); if ( index ) { if ( data[ index ] && data[ index ].stop ) { stopQueue( data[ index ] ); } } else { for ( index in data ) { if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { stopQueue( data[ index ] ); } } } for ( index = timers.length; index--; ) { if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) { timers[ index ].anim.stop( gotoEnd ); dequeue = false; timers.splice( index, 1 ); } } // start the next in the queue if the last step wasn't forced // timers currently will call their complete callbacks, which will dequeue // but only if they were gotoEnd if ( dequeue || !gotoEnd ) { jQuery.dequeue( this, type ); } }); }, finish: function( type ) { if ( type !== false ) { type = type || "fx"; } return this.each(function() { var index, data = jQuery._data( this ), queue = data[ type + "queue" ], hooks = data[ type + "queueHooks" ], timers = jQuery.timers, length = queue ? queue.length : 0; // enable finishing flag on private data data.finish = true; // empty the queue first jQuery.queue( this, type, [] ); if ( hooks && hooks.stop ) { hooks.stop.call( this, true ); } // look for any active animations, and finish them for ( index = timers.length; index--; ) { if ( timers[ index ].elem === this && timers[ index ].queue === type ) { timers[ index ].anim.stop( true ); timers.splice( index, 1 ); } } // look for any animations in the old queue and finish them for ( index = 0; index < length; index++ ) { if ( queue[ index ] && queue[ index ].finish ) { queue[ index ].finish.call( this ); } } // turn off finishing flag delete data.finish; }); } }); jQuery.each([ "toggle", "show", "hide" ], function( i, name ) { var cssFn = jQuery.fn[ name ]; jQuery.fn[ name ] = function( speed, easing, callback ) { return speed == null || typeof speed === "boolean" ? cssFn.apply( this, arguments ) : this.animate( genFx( name, true ), speed, easing, callback ); }; }); // Generate shortcuts for custom animations jQuery.each({ slideDown: genFx("show"), slideUp: genFx("hide"), slideToggle: genFx("toggle"), fadeIn: { opacity: "show" }, fadeOut: { opacity: "hide" }, fadeToggle: { opacity: "toggle" } }, function( name, props ) { jQuery.fn[ name ] = function( speed, easing, callback ) { return this.animate( props, speed, easing, callback ); }; }); jQuery.timers = []; jQuery.fx.tick = function() { var timer, timers = jQuery.timers, i = 0; fxNow = jQuery.now(); for ( ; i < timers.length; i++ ) { timer = timers[ i ]; // Checks the timer has not already been removed if ( !timer() && timers[ i ] === timer ) { timers.splice( i--, 1 ); } } if ( !timers.length ) { jQuery.fx.stop(); } fxNow = undefined; }; jQuery.fx.timer = function( timer ) { jQuery.timers.push( timer ); if ( timer() ) { jQuery.fx.start(); } else { jQuery.timers.pop(); } }; jQuery.fx.interval = 13; jQuery.fx.start = function() { if ( !timerId ) { timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval ); } }; jQuery.fx.stop = function() { clearInterval( timerId ); timerId = null; }; jQuery.fx.speeds = { slow: 600, fast: 200, // Default speed _default: 400 }; // Based off of the plugin by Clint Helfers, with permission. // http://blindsignals.com/index.php/2009/07/jquery-delay/ jQuery.fn.delay = function( time, type ) { time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; type = type || "fx"; return this.queue( type, function( next, hooks ) { var timeout = setTimeout( next, time ); hooks.stop = function() { clearTimeout( timeout ); }; }); }; (function() { // Minified: var a,b,c,d,e var input, div, select, a, opt; // Setup div = document.createElement( "div" ); div.setAttribute( "className", "t" ); div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>"; a = div.getElementsByTagName("a")[ 0 ]; // First batch of tests. select = document.createElement("select"); opt = select.appendChild( document.createElement("option") ); input = div.getElementsByTagName("input")[ 0 ]; a.style.cssText = "top:1px"; // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) support.getSetAttribute = div.className !== "t"; // Get the style information from getAttribute // (IE uses .cssText instead) support.style = /top/.test( a.getAttribute("style") ); // Make sure that URLs aren't manipulated // (IE normalizes it by default) support.hrefNormalized = a.getAttribute("href") === "/a"; // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere) support.checkOn = !!input.value; // Make sure that a selected-by-default option has a working selected property. // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) support.optSelected = opt.selected; // Tests for enctype support on a form (#6743) support.enctype = !!document.createElement("form").enctype; // Make sure that the options inside disabled selects aren't marked as disabled // (WebKit marks them as disabled) select.disabled = true; support.optDisabled = !opt.disabled; // Support: IE8 only // Check if we can trust getAttribute("value") input = document.createElement( "input" ); input.setAttribute( "value", "" ); support.input = input.getAttribute( "value" ) === ""; // Check if an input maintains its value after becoming a radio input.value = "t"; input.setAttribute( "type", "radio" ); support.radioValue = input.value === "t"; })(); var rreturn = /\r/g; jQuery.fn.extend({ val: function( value ) { var hooks, ret, isFunction, elem = this[0]; if ( !arguments.length ) { if ( elem ) { hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { return ret; } ret = elem.value; return typeof ret === "string" ? // handle most common string cases ret.replace(rreturn, "") : // handle cases where value is null/undef or number ret == null ? "" : ret; } return; } isFunction = jQuery.isFunction( value ); return this.each(function( i ) { var val; if ( this.nodeType !== 1 ) { return; } if ( isFunction ) { val = value.call( this, i, jQuery( this ).val() ); } else { val = value; } // Treat null/undefined as ""; convert numbers to string if ( val == null ) { val = ""; } else if ( typeof val === "number" ) { val += ""; } else if ( jQuery.isArray( val ) ) { val = jQuery.map( val, function( value ) { return value == null ? "" : value + ""; }); } hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; // If set returns undefined, fall back to normal setting if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { this.value = val; } }); } }); jQuery.extend({ valHooks: { option: { get: function( elem ) { var val = jQuery.find.attr( elem, "value" ); return val != null ? val : // Support: IE10-11+ // option.text throws exceptions (#14686, #14858) jQuery.trim( jQuery.text( elem ) ); } }, select: { get: function( elem ) { var value, option, options = elem.options, index = elem.selectedIndex, one = elem.type === "select-one" || index < 0, values = one ? null : [], max = one ? index + 1 : options.length, i = index < 0 ? max : one ? index : 0; // Loop through all the selected options for ( ; i < max; i++ ) { option = options[ i ]; // oldIE doesn't update selected after form reset (#2551) if ( ( option.selected || i === index ) && // Don't return options that are disabled or in a disabled optgroup ( support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { // Get the specific value for the option value = jQuery( option ).val(); // We don't need an array for one selects if ( one ) { return value; } // Multi-Selects return an array values.push( value ); } } return values; }, set: function( elem, value ) { var optionSet, option, options = elem.options, values = jQuery.makeArray( value ), i = options.length; while ( i-- ) { option = options[ i ]; if ( jQuery.inArray( jQuery.valHooks.option.get( option ), values ) >= 0 ) { // Support: IE6 // When new option element is added to select box we need to // force reflow of newly added node in order to workaround delay // of initialization properties try { option.selected = optionSet = true; } catch ( _ ) { // Will be executed only in IE6 option.scrollHeight; } } else { option.selected = false; } } // Force browsers to behave consistently when non-matching value is set if ( !optionSet ) { elem.selectedIndex = -1; } return options; } } } }); // Radios and checkboxes getter/setter jQuery.each([ "radio", "checkbox" ], function() { jQuery.valHooks[ this ] = { set: function( elem, value ) { if ( jQuery.isArray( value ) ) { return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); } } }; if ( !support.checkOn ) { jQuery.valHooks[ this ].get = function( elem ) { // Support: Webkit // "" is returned instead of "on" if a value isn't specified return elem.getAttribute("value") === null ? "on" : elem.value; }; } }); var nodeHook, boolHook, attrHandle = jQuery.expr.attrHandle, ruseDefault = /^(?:checked|selected)$/i, getSetAttribute = support.getSetAttribute, getSetInput = support.input; jQuery.fn.extend({ attr: function( name, value ) { return access( this, jQuery.attr, name, value, arguments.length > 1 ); }, removeAttr: function( name ) { return this.each(function() { jQuery.removeAttr( this, name ); }); } }); jQuery.extend({ attr: function( elem, name, value ) { var hooks, ret, nType = elem.nodeType; // don't get/set attributes on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return; } // Fallback to prop when attributes are not supported if ( typeof elem.getAttribute === strundefined ) { return jQuery.prop( elem, name, value ); } // All attributes are lowercase // Grab necessary hook if one is defined if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { name = name.toLowerCase(); hooks = jQuery.attrHooks[ name ] || ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook ); } if ( value !== undefined ) { if ( value === null ) { jQuery.removeAttr( elem, name ); } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { return ret; } else { elem.setAttribute( name, value + "" ); return value; } } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { return ret; } else { ret = jQuery.find.attr( elem, name ); // Non-existent attributes return null, we normalize to undefined return ret == null ? undefined : ret; } }, removeAttr: function( elem, value ) { var name, propName, i = 0, attrNames = value && value.match( rnotwhite ); if ( attrNames && elem.nodeType === 1 ) { while ( (name = attrNames[i++]) ) { propName = jQuery.propFix[ name ] || name; // Boolean attributes get special treatment (#10870) if ( jQuery.expr.match.bool.test( name ) ) { // Set corresponding property to false if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { elem[ propName ] = false; // Support: IE<9 // Also clear defaultChecked/defaultSelected (if appropriate) } else { elem[ jQuery.camelCase( "default-" + name ) ] = elem[ propName ] = false; } // See #9699 for explanation of this approach (setting first, then removal) } else { jQuery.attr( elem, name, "" ); } elem.removeAttribute( getSetAttribute ? name : propName ); } } }, attrHooks: { type: { set: function( elem, value ) { if ( !support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { // Setting the type on a radio button after the value resets the value in IE6-9 // Reset value to default in case type is set after value during creation var val = elem.value; elem.setAttribute( "type", value ); if ( val ) { elem.value = val; } return value; } } } } }); // Hook for boolean attributes boolHook = { set: function( elem, value, name ) { if ( value === false ) { // Remove boolean attributes when set to false jQuery.removeAttr( elem, name ); } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { // IE<8 needs the *property* name elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name ); // Use defaultChecked and defaultSelected for oldIE } else { elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true; } return name; } }; // Retrieve booleans specially jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { var getter = attrHandle[ name ] || jQuery.find.attr; attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ? function( elem, name, isXML ) { var ret, handle; if ( !isXML ) { // Avoid an infinite loop by temporarily removing this function from the getter handle = attrHandle[ name ]; attrHandle[ name ] = ret; ret = getter( elem, name, isXML ) != null ? name.toLowerCase() : null; attrHandle[ name ] = handle; } return ret; } : function( elem, name, isXML ) { if ( !isXML ) { return elem[ jQuery.camelCase( "default-" + name ) ] ? name.toLowerCase() : null; } }; }); // fix oldIE attroperties if ( !getSetInput || !getSetAttribute ) { jQuery.attrHooks.value = { set: function( elem, value, name ) { if ( jQuery.nodeName( elem, "input" ) ) { // Does not return so that setAttribute is also used elem.defaultValue = value; } else { // Use nodeHook if defined (#1954); otherwise setAttribute is fine return nodeHook && nodeHook.set( elem, value, name ); } } }; } // IE6/7 do not support getting/setting some attributes with get/setAttribute if ( !getSetAttribute ) { // Use this for any attribute in IE6/7 // This fixes almost every IE6/7 issue nodeHook = { set: function( elem, value, name ) { // Set the existing or create a new attribute node var ret = elem.getAttributeNode( name ); if ( !ret ) { elem.setAttributeNode( (ret = elem.ownerDocument.createAttribute( name )) ); } ret.value = value += ""; // Break association with cloned elements by also using setAttribute (#9646) if ( name === "value" || value === elem.getAttribute( name ) ) { return value; } } }; // Some attributes are constructed with empty-string values when not defined attrHandle.id = attrHandle.name = attrHandle.coords = function( elem, name, isXML ) { var ret; if ( !isXML ) { return (ret = elem.getAttributeNode( name )) && ret.value !== "" ? ret.value : null; } }; // Fixing value retrieval on a button requires this module jQuery.valHooks.button = { get: function( elem, name ) { var ret = elem.getAttributeNode( name ); if ( ret && ret.specified ) { return ret.value; } }, set: nodeHook.set }; // Set contenteditable to false on removals(#10429) // Setting to empty string throws an error as an invalid value jQuery.attrHooks.contenteditable = { set: function( elem, value, name ) { nodeHook.set( elem, value === "" ? false : value, name ); } }; // Set width and height to auto instead of 0 on empty string( Bug #8150 ) // This is for removals jQuery.each([ "width", "height" ], function( i, name ) { jQuery.attrHooks[ name ] = { set: function( elem, value ) { if ( value === "" ) { elem.setAttribute( name, "auto" ); return value; } } }; }); } if ( !support.style ) { jQuery.attrHooks.style = { get: function( elem ) { // Return undefined in the case of empty string // Note: IE uppercases css property names, but if we were to .toLowerCase() // .cssText, that would destroy case senstitivity in URL's, like in "background" return elem.style.cssText || undefined; }, set: function( elem, value ) { return ( elem.style.cssText = value + "" ); } }; } var rfocusable = /^(?:input|select|textarea|button|object)$/i, rclickable = /^(?:a|area)$/i; jQuery.fn.extend({ prop: function( name, value ) { return access( this, jQuery.prop, name, value, arguments.length > 1 ); }, removeProp: function( name ) { name = jQuery.propFix[ name ] || name; return this.each(function() { // try/catch handles cases where IE balks (such as removing a property on window) try { this[ name ] = undefined; delete this[ name ]; } catch( e ) {} }); } }); jQuery.extend({ propFix: { "for": "htmlFor", "class": "className" }, prop: function( elem, name, value ) { var ret, hooks, notxml, nType = elem.nodeType; // don't get/set properties on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return; } notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); if ( notxml ) { // Fix name and attach hooks name = jQuery.propFix[ name ] || name; hooks = jQuery.propHooks[ name ]; } if ( value !== undefined ) { return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ? ret : ( elem[ name ] = value ); } else { return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ? ret : elem[ name ]; } }, propHooks: { tabIndex: { get: function( elem ) { // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ // Use proper attribute retrieval(#12072) var tabindex = jQuery.find.attr( elem, "tabindex" ); return tabindex ? parseInt( tabindex, 10 ) : rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? 0 : -1; } } } }); // Some attributes require a special call on IE // http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx if ( !support.hrefNormalized ) { // href/src property should get the full normalized URL (#10299/#12915) jQuery.each([ "href", "src" ], function( i, name ) { jQuery.propHooks[ name ] = { get: function( elem ) { return elem.getAttribute( name, 4 ); } }; }); } // Support: Safari, IE9+ // mis-reports the default selected property of an option // Accessing the parent's selectedIndex property fixes it if ( !support.optSelected ) { jQuery.propHooks.selected = { get: function( elem ) { var parent = elem.parentNode; if ( parent ) { parent.selectedIndex; // Make sure that it also works with optgroups, see #5701 if ( parent.parentNode ) { parent.parentNode.selectedIndex; } } return null; } }; } jQuery.each([ "tabIndex", "readOnly", "maxLength", "cellSpacing", "cellPadding", "rowSpan", "colSpan", "useMap", "frameBorder", "contentEditable" ], function() { jQuery.propFix[ this.toLowerCase() ] = this; }); // IE6/7 call enctype encoding if ( !support.enctype ) { jQuery.propFix.enctype = "encoding"; } var rclass = /[\t\r\n\f]/g; jQuery.fn.extend({ addClass: function( value ) { var classes, elem, cur, clazz, j, finalValue, i = 0, len = this.length, proceed = typeof value === "string" && value; if ( jQuery.isFunction( value ) ) { return this.each(function( j ) { jQuery( this ).addClass( value.call( this, j, this.className ) ); }); } if ( proceed ) { // The disjunction here is for better compressibility (see removeClass) classes = ( value || "" ).match( rnotwhite ) || []; for ( ; i < len; i++ ) { elem = this[ i ]; cur = elem.nodeType === 1 && ( elem.className ? ( " " + elem.className + " " ).replace( rclass, " " ) : " " ); if ( cur ) { j = 0; while ( (clazz = classes[j++]) ) { if ( cur.indexOf( " " + clazz + " " ) < 0 ) { cur += clazz + " "; } } // only assign if different to avoid unneeded rendering. finalValue = jQuery.trim( cur ); if ( elem.className !== finalValue ) { elem.className = finalValue; } } } } return this; }, removeClass: function( value ) { var classes, elem, cur, clazz, j, finalValue, i = 0, len = this.length, proceed = arguments.length === 0 || typeof value === "string" && value; if ( jQuery.isFunction( value ) ) { return this.each(function( j ) { jQuery( this ).removeClass( value.call( this, j, this.className ) ); }); } if ( proceed ) { classes = ( value || "" ).match( rnotwhite ) || []; for ( ; i < len; i++ ) { elem = this[ i ]; // This expression is here for better compressibility (see addClass) cur = elem.nodeType === 1 && ( elem.className ? ( " " + elem.className + " " ).replace( rclass, " " ) : "" ); if ( cur ) { j = 0; while ( (clazz = classes[j++]) ) { // Remove *all* instances while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { cur = cur.replace( " " + clazz + " ", " " ); } } // only assign if different to avoid unneeded rendering. finalValue = value ? jQuery.trim( cur ) : ""; if ( elem.className !== finalValue ) { elem.className = finalValue; } } } } return this; }, toggleClass: function( value, stateVal ) { var type = typeof value; if ( typeof stateVal === "boolean" && type === "string" ) { return stateVal ? this.addClass( value ) : this.removeClass( value ); } if ( jQuery.isFunction( value ) ) { return this.each(function( i ) { jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); }); } return this.each(function() { if ( type === "string" ) { // toggle individual class names var className, i = 0, self = jQuery( this ), classNames = value.match( rnotwhite ) || []; while ( (className = classNames[ i++ ]) ) { // check each className given, space separated list if ( self.hasClass( className ) ) { self.removeClass( className ); } else { self.addClass( className ); } } // Toggle whole class name } else if ( type === strundefined || type === "boolean" ) { if ( this.className ) { // store className if set jQuery._data( this, "__className__", this.className ); } // If the element has a class name or if we're passed "false", // then remove the whole classname (if there was one, the above saved it). // Otherwise bring back whatever was previously saved (if anything), // falling back to the empty string if nothing was stored. this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; } }); }, hasClass: function( selector ) { var className = " " + selector + " ", i = 0, l = this.length; for ( ; i < l; i++ ) { if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { return true; } } return false; } }); // Return jQuery for attributes-only inclusion jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { // Handle event binding jQuery.fn[ name ] = function( data, fn ) { return arguments.length > 0 ? this.on( name, null, data, fn ) : this.trigger( name ); }; }); jQuery.fn.extend({ hover: function( fnOver, fnOut ) { return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); }, bind: function( types, data, fn ) { return this.on( types, null, data, fn ); }, unbind: function( types, fn ) { return this.off( types, null, fn ); }, delegate: function( selector, types, data, fn ) { return this.on( types, selector, data, fn ); }, undelegate: function( selector, types, fn ) { // ( namespace ) or ( selector, types [, fn] ) return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn ); } }); var nonce = jQuery.now(); var rquery = (/\?/); var rvalidtokens = /(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g; jQuery.parseJSON = function( data ) { // Attempt to parse using the native JSON parser first if ( window.JSON && window.JSON.parse ) { // Support: Android 2.3 // Workaround failure to string-cast null input return window.JSON.parse( data + "" ); } var requireNonComma, depth = null, str = jQuery.trim( data + "" ); // Guard against invalid (and possibly dangerous) input by ensuring that nothing remains // after removing valid tokens return str && !jQuery.trim( str.replace( rvalidtokens, function( token, comma, open, close ) { // Force termination if we see a misplaced comma if ( requireNonComma && comma ) { depth = 0; } // Perform no more replacements after returning to outermost depth if ( depth === 0 ) { return token; } // Commas must not follow "[", "{", or "," requireNonComma = open || comma; // Determine new depth // array/object open ("[" or "{"): depth += true - false (increment) // array/object close ("]" or "}"): depth += false - true (decrement) // other cases ("," or primitive): depth += true - true (numeric cast) depth += !close - !open; // Remove this token return ""; }) ) ? ( Function( "return " + str ) )() : jQuery.error( "Invalid JSON: " + data ); }; // Cross-browser xml parsing jQuery.parseXML = function( data ) { var xml, tmp; if ( !data || typeof data !== "string" ) { return null; } try { if ( window.DOMParser ) { // Standard tmp = new DOMParser(); xml = tmp.parseFromString( data, "text/xml" ); } else { // IE xml = new ActiveXObject( "Microsoft.XMLDOM" ); xml.async = "false"; xml.loadXML( data ); } } catch( e ) { xml = undefined; } if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { jQuery.error( "Invalid XML: " + data ); } return xml; }; var // Document location ajaxLocParts, ajaxLocation, rhash = /#.*$/, rts = /([?&])_=[^&]*/, rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL // #7653, #8125, #8152: local protocol detection rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, rnoContent = /^(?:GET|HEAD)$/, rprotocol = /^\/\//, rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/, /* Prefilters * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) * 2) These are called: * - BEFORE asking for a transport * - AFTER param serialization (s.data is a string if s.processData is true) * 3) key is the dataType * 4) the catchall symbol "*" can be used * 5) execution will start with transport dataType and THEN continue down to "*" if needed */ prefilters = {}, /* Transports bindings * 1) key is the dataType * 2) the catchall symbol "*" can be used * 3) selection will start with transport dataType and THEN go to "*" if needed */ transports = {}, // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression allTypes = "*/".concat("*"); // #8138, IE may throw an exception when accessing // a field from window.location if document.domain has been set try { ajaxLocation = location.href; } catch( e ) { // Use the href attribute of an A element // since IE will modify it given document.location ajaxLocation = document.createElement( "a" ); ajaxLocation.href = ""; ajaxLocation = ajaxLocation.href; } // Segment location into parts ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || []; // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport function addToPrefiltersOrTransports( structure ) { // dataTypeExpression is optional and defaults to "*" return function( dataTypeExpression, func ) { if ( typeof dataTypeExpression !== "string" ) { func = dataTypeExpression; dataTypeExpression = "*"; } var dataType, i = 0, dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || []; if ( jQuery.isFunction( func ) ) { // For each dataType in the dataTypeExpression while ( (dataType = dataTypes[i++]) ) { // Prepend if requested if ( dataType.charAt( 0 ) === "+" ) { dataType = dataType.slice( 1 ) || "*"; (structure[ dataType ] = structure[ dataType ] || []).unshift( func ); // Otherwise append } else { (structure[ dataType ] = structure[ dataType ] || []).push( func ); } } } }; } // Base inspection function for prefilters and transports function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { var inspected = {}, seekingTransport = ( structure === transports ); function inspect( dataType ) { var selected; inspected[ dataType ] = true; jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) { options.dataTypes.unshift( dataTypeOrTransport ); inspect( dataTypeOrTransport ); return false; } else if ( seekingTransport ) { return !( selected = dataTypeOrTransport ); } }); return selected; } return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); } // A special extend for ajax options // that takes "flat" options (not to be deep extended) // Fixes #9887 function ajaxExtend( target, src ) { var deep, key, flatOptions = jQuery.ajaxSettings.flatOptions || {}; for ( key in src ) { if ( src[ key ] !== undefined ) { ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ]; } } if ( deep ) { jQuery.extend( true, target, deep ); } return target; } /* Handles responses to an ajax request: * - finds the right dataType (mediates between content-type and expected dataType) * - returns the corresponding response */ function ajaxHandleResponses( s, jqXHR, responses ) { var firstDataType, ct, finalDataType, type, contents = s.contents, dataTypes = s.dataTypes; // Remove auto dataType and get content-type in the process while ( dataTypes[ 0 ] === "*" ) { dataTypes.shift(); if ( ct === undefined ) { ct = s.mimeType || jqXHR.getResponseHeader("Content-Type"); } } // Check if we're dealing with a known content-type if ( ct ) { for ( type in contents ) { if ( contents[ type ] && contents[ type ].test( ct ) ) { dataTypes.unshift( type ); break; } } } // Check to see if we have a response for the expected dataType if ( dataTypes[ 0 ] in responses ) { finalDataType = dataTypes[ 0 ]; } else { // Try convertible dataTypes for ( type in responses ) { if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) { finalDataType = type; break; } if ( !firstDataType ) { firstDataType = type; } } // Or just use first one finalDataType = finalDataType || firstDataType; } // If we found a dataType // We add the dataType to the list if needed // and return the corresponding response if ( finalDataType ) { if ( finalDataType !== dataTypes[ 0 ] ) { dataTypes.unshift( finalDataType ); } return responses[ finalDataType ]; } } /* Chain conversions given the request and the original response * Also sets the responseXXX fields on the jqXHR instance */ function ajaxConvert( s, response, jqXHR, isSuccess ) { var conv2, current, conv, tmp, prev, converters = {}, // Work with a copy of dataTypes in case we need to modify it for conversion dataTypes = s.dataTypes.slice(); // Create converters map with lowercased keys if ( dataTypes[ 1 ] ) { for ( conv in s.converters ) { converters[ conv.toLowerCase() ] = s.converters[ conv ]; } } current = dataTypes.shift(); // Convert to each sequential dataType while ( current ) { if ( s.responseFields[ current ] ) { jqXHR[ s.responseFields[ current ] ] = response; } // Apply the dataFilter if provided if ( !prev && isSuccess && s.dataFilter ) { response = s.dataFilter( response, s.dataType ); } prev = current; current = dataTypes.shift(); if ( current ) { // There's only work to do if current dataType is non-auto if ( current === "*" ) { current = prev; // Convert response if prev dataType is non-auto and differs from current } else if ( prev !== "*" && prev !== current ) { // Seek a direct converter conv = converters[ prev + " " + current ] || converters[ "* " + current ]; // If none found, seek a pair if ( !conv ) { for ( conv2 in converters ) { // If conv2 outputs current tmp = conv2.split( " " ); if ( tmp[ 1 ] === current ) { // If prev can be converted to accepted input conv = converters[ prev + " " + tmp[ 0 ] ] || converters[ "* " + tmp[ 0 ] ]; if ( conv ) { // Condense equivalence converters if ( conv === true ) { conv = converters[ conv2 ]; // Otherwise, insert the intermediate dataType } else if ( converters[ conv2 ] !== true ) { current = tmp[ 0 ]; dataTypes.unshift( tmp[ 1 ] ); } break; } } } } // Apply converter (if not an equivalence) if ( conv !== true ) { // Unless errors are allowed to bubble, catch and return them if ( conv && s[ "throws" ] ) { response = conv( response ); } else { try { response = conv( response ); } catch ( e ) { return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current }; } } } } } } return { state: "success", data: response }; } jQuery.extend({ // Counter for holding the number of active queries active: 0, // Last-Modified header cache for next request lastModified: {}, etag: {}, ajaxSettings: { url: ajaxLocation, type: "GET", isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ), global: true, processData: true, async: true, contentType: "application/x-www-form-urlencoded; charset=UTF-8", /* timeout: 0, data: null, dataType: null, username: null, password: null, cache: null, throws: false, traditional: false, headers: {}, */ accepts: { "*": allTypes, text: "text/plain", html: "text/html", xml: "application/xml, text/xml", json: "application/json, text/javascript" }, contents: { xml: /xml/, html: /html/, json: /json/ }, responseFields: { xml: "responseXML", text: "responseText", json: "responseJSON" }, // Data converters // Keys separate source (or catchall "*") and destination types with a single space converters: { // Convert anything to text "* text": String, // Text to html (true = no transformation) "text html": true, // Evaluate text as a json expression "text json": jQuery.parseJSON, // Parse text as xml "text xml": jQuery.parseXML }, // For options that shouldn't be deep extended: // you can add your own custom options here if // and when you create one that shouldn't be // deep extended (see ajaxExtend) flatOptions: { url: true, context: true } }, // Creates a full fledged settings object into target // with both ajaxSettings and settings fields. // If target is omitted, writes into ajaxSettings. ajaxSetup: function( target, settings ) { return settings ? // Building a settings object ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : // Extending ajaxSettings ajaxExtend( jQuery.ajaxSettings, target ); }, ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), ajaxTransport: addToPrefiltersOrTransports( transports ), // Main method ajax: function( url, options ) { // If url is an object, simulate pre-1.5 signature if ( typeof url === "object" ) { options = url; url = undefined; } // Force options to be an object options = options || {}; var // Cross-domain detection vars parts, // Loop variable i, // URL without anti-cache param cacheURL, // Response headers as string responseHeadersString, // timeout handle timeoutTimer, // To know if global events are to be dispatched fireGlobals, transport, // Response headers responseHeaders, // Create the final options object s = jQuery.ajaxSetup( {}, options ), // Callbacks context callbackContext = s.context || s, // Context for global events is callbackContext if it is a DOM node or jQuery collection globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ? jQuery( callbackContext ) : jQuery.event, // Deferreds deferred = jQuery.Deferred(), completeDeferred = jQuery.Callbacks("once memory"), // Status-dependent callbacks statusCode = s.statusCode || {}, // Headers (they are sent all at once) requestHeaders = {}, requestHeadersNames = {}, // The jqXHR state state = 0, // Default abort message strAbort = "canceled", // Fake xhr jqXHR = { readyState: 0, // Builds headers hashtable if needed getResponseHeader: function( key ) { var match; if ( state === 2 ) { if ( !responseHeaders ) { responseHeaders = {}; while ( (match = rheaders.exec( responseHeadersString )) ) { responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; } } match = responseHeaders[ key.toLowerCase() ]; } return match == null ? null : match; }, // Raw string getAllResponseHeaders: function() { return state === 2 ? responseHeadersString : null; }, // Caches the header setRequestHeader: function( name, value ) { var lname = name.toLowerCase(); if ( !state ) { name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; requestHeaders[ name ] = value; } return this; }, // Overrides response content-type header overrideMimeType: function( type ) { if ( !state ) { s.mimeType = type; } return this; }, // Status-dependent callbacks statusCode: function( map ) { var code; if ( map ) { if ( state < 2 ) { for ( code in map ) { // Lazy-add the new callback in a way that preserves old ones statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; } } else { // Execute the appropriate callbacks jqXHR.always( map[ jqXHR.status ] ); } } return this; }, // Cancel the request abort: function( statusText ) { var finalText = statusText || strAbort; if ( transport ) { transport.abort( finalText ); } done( 0, finalText ); return this; } }; // Attach deferreds deferred.promise( jqXHR ).complete = completeDeferred.add; jqXHR.success = jqXHR.done; jqXHR.error = jqXHR.fail; // Remove hash character (#7531: and string promotion) // Add protocol if not provided (#5866: IE7 issue with protocol-less urls) // Handle falsy url in the settings object (#10093: consistency with old signature) // We also use the url parameter if available s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); // Alias method option to type as per ticket #12004 s.type = options.method || options.type || s.method || s.type; // Extract dataTypes list s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ]; // A cross-domain request is in order when we have a protocol:host:port mismatch if ( s.crossDomain == null ) { parts = rurl.exec( s.url.toLowerCase() ); s.crossDomain = !!( parts && ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] || ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !== ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) ) ); } // Convert data if not already a string if ( s.data && s.processData && typeof s.data !== "string" ) { s.data = jQuery.param( s.data, s.traditional ); } // Apply prefilters inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); // If request was aborted inside a prefilter, stop there if ( state === 2 ) { return jqXHR; } // We can fire global events as of now if asked to // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) fireGlobals = jQuery.event && s.global; // Watch for a new set of requests if ( fireGlobals && jQuery.active++ === 0 ) { jQuery.event.trigger("ajaxStart"); } // Uppercase the type s.type = s.type.toUpperCase(); // Determine if request has content s.hasContent = !rnoContent.test( s.type ); // Save the URL in case we're toying with the If-Modified-Since // and/or If-None-Match header later on cacheURL = s.url; // More options handling for requests with no content if ( !s.hasContent ) { // If data is available, append data to url if ( s.data ) { cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data ); // #9682: remove data so that it's not used in an eventual retry delete s.data; } // Add anti-cache in url if needed if ( s.cache === false ) { s.url = rts.test( cacheURL ) ? // If there is already a '_' parameter, set its value cacheURL.replace( rts, "$1_=" + nonce++ ) : // Otherwise add one to the end cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++; } } // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. if ( s.ifModified ) { if ( jQuery.lastModified[ cacheURL ] ) { jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); } if ( jQuery.etag[ cacheURL ] ) { jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); } } // Set the correct header, if data is being sent if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { jqXHR.setRequestHeader( "Content-Type", s.contentType ); } // Set the Accepts header for the server, depending on the dataType jqXHR.setRequestHeader( "Accept", s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : s.accepts[ "*" ] ); // Check for headers option for ( i in s.headers ) { jqXHR.setRequestHeader( i, s.headers[ i ] ); } // Allow custom headers/mimetypes and early abort if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { // Abort if not done already and return return jqXHR.abort(); } // aborting is no longer a cancellation strAbort = "abort"; // Install callbacks on deferreds for ( i in { success: 1, error: 1, complete: 1 } ) { jqXHR[ i ]( s[ i ] ); } // Get transport transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); // If no transport, we auto-abort if ( !transport ) { done( -1, "No Transport" ); } else { jqXHR.readyState = 1; // Send global event if ( fireGlobals ) { globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); } // Timeout if ( s.async && s.timeout > 0 ) { timeoutTimer = setTimeout(function() { jqXHR.abort("timeout"); }, s.timeout ); } try { state = 1; transport.send( requestHeaders, done ); } catch ( e ) { // Propagate exception as error if not done if ( state < 2 ) { done( -1, e ); // Simply rethrow otherwise } else { throw e; } } } // Callback for when everything is done function done( status, nativeStatusText, responses, headers ) { var isSuccess, success, error, response, modified, statusText = nativeStatusText; // Called once if ( state === 2 ) { return; } // State is "done" now state = 2; // Clear timeout if it exists if ( timeoutTimer ) { clearTimeout( timeoutTimer ); } // Dereference transport for early garbage collection // (no matter how long the jqXHR object will be used) transport = undefined; // Cache response headers responseHeadersString = headers || ""; // Set readyState jqXHR.readyState = status > 0 ? 4 : 0; // Determine if successful isSuccess = status >= 200 && status < 300 || status === 304; // Get response data if ( responses ) { response = ajaxHandleResponses( s, jqXHR, responses ); } // Convert no matter what (that way responseXXX fields are always set) response = ajaxConvert( s, response, jqXHR, isSuccess ); // If successful, handle type chaining if ( isSuccess ) { // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. if ( s.ifModified ) { modified = jqXHR.getResponseHeader("Last-Modified"); if ( modified ) { jQuery.lastModified[ cacheURL ] = modified; } modified = jqXHR.getResponseHeader("etag"); if ( modified ) { jQuery.etag[ cacheURL ] = modified; } } // if no content if ( status === 204 || s.type === "HEAD" ) { statusText = "nocontent"; // if not modified } else if ( status === 304 ) { statusText = "notmodified"; // If we have data, let's convert it } else { statusText = response.state; success = response.data; error = response.error; isSuccess = !error; } } else { // We extract error from statusText // then normalize statusText and status for non-aborts error = statusText; if ( status || !statusText ) { statusText = "error"; if ( status < 0 ) { status = 0; } } } // Set data for the fake xhr object jqXHR.status = status; jqXHR.statusText = ( nativeStatusText || statusText ) + ""; // Success/Error if ( isSuccess ) { deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); } else { deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); } // Status-dependent callbacks jqXHR.statusCode( statusCode ); statusCode = undefined; if ( fireGlobals ) { globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", [ jqXHR, s, isSuccess ? success : error ] ); } // Complete completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); if ( fireGlobals ) { globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); // Handle the global AJAX counter if ( !( --jQuery.active ) ) { jQuery.event.trigger("ajaxStop"); } } } return jqXHR; }, getJSON: function( url, data, callback ) { return jQuery.get( url, data, callback, "json" ); }, getScript: function( url, callback ) { return jQuery.get( url, undefined, callback, "script" ); } }); jQuery.each( [ "get", "post" ], function( i, method ) { jQuery[ method ] = function( url, data, callback, type ) { // shift arguments if data argument was omitted if ( jQuery.isFunction( data ) ) { type = type || callback; callback = data; data = undefined; } return jQuery.ajax({ url: url, type: method, dataType: type, data: data, success: callback }); }; }); jQuery._evalUrl = function( url ) { return jQuery.ajax({ url: url, type: "GET", dataType: "script", async: false, global: false, "throws": true }); }; jQuery.fn.extend({ wrapAll: function( html ) { if ( jQuery.isFunction( html ) ) { return this.each(function(i) { jQuery(this).wrapAll( html.call(this, i) ); }); } if ( this[0] ) { // The elements to wrap the target around var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); if ( this[0].parentNode ) { wrap.insertBefore( this[0] ); } wrap.map(function() { var elem = this; while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { elem = elem.firstChild; } return elem; }).append( this ); } return this; }, wrapInner: function( html ) { if ( jQuery.isFunction( html ) ) { return this.each(function(i) { jQuery(this).wrapInner( html.call(this, i) ); }); } return this.each(function() { var self = jQuery( this ), contents = self.contents(); if ( contents.length ) { contents.wrapAll( html ); } else { self.append( html ); } }); }, wrap: function( html ) { var isFunction = jQuery.isFunction( html ); return this.each(function(i) { jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); }); }, unwrap: function() { return this.parent().each(function() { if ( !jQuery.nodeName( this, "body" ) ) { jQuery( this ).replaceWith( this.childNodes ); } }).end(); } }); jQuery.expr.filters.hidden = function( elem ) { // Support: Opera <= 12.12 // Opera reports offsetWidths and offsetHeights less than zero on some elements return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 || (!support.reliableHiddenOffsets() && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none"); }; jQuery.expr.filters.visible = function( elem ) { return !jQuery.expr.filters.hidden( elem ); }; var r20 = /%20/g, rbracket = /\[\]$/, rCRLF = /\r?\n/g, rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, rsubmittable = /^(?:input|select|textarea|keygen)/i; function buildParams( prefix, obj, traditional, add ) { var name; if ( jQuery.isArray( obj ) ) { // Serialize array item. jQuery.each( obj, function( i, v ) { if ( traditional || rbracket.test( prefix ) ) { // Treat each array item as a scalar. add( prefix, v ); } else { // Item is non-scalar (array or object), encode its numeric index. buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add ); } }); } else if ( !traditional && jQuery.type( obj ) === "object" ) { // Serialize object item. for ( name in obj ) { buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); } } else { // Serialize scalar item. add( prefix, obj ); } } // Serialize an array of form elements or a set of // key/values into a query string jQuery.param = function( a, traditional ) { var prefix, s = [], add = function( key, value ) { // If value is a function, invoke it and return its value value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value ); s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value ); }; // Set traditional to true for jQuery <= 1.3.2 behavior. if ( traditional === undefined ) { traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional; } // If an array was passed in, assume that it is an array of form elements. if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { // Serialize the form elements jQuery.each( a, function() { add( this.name, this.value ); }); } else { // If traditional, encode the "old" way (the way 1.3.2 or older // did it), otherwise encode params recursively. for ( prefix in a ) { buildParams( prefix, a[ prefix ], traditional, add ); } } // Return the resulting serialization return s.join( "&" ).replace( r20, "+" ); }; jQuery.fn.extend({ serialize: function() { return jQuery.param( this.serializeArray() ); }, serializeArray: function() { return this.map(function() { // Can add propHook for "elements" to filter or add form elements var elements = jQuery.prop( this, "elements" ); return elements ? jQuery.makeArray( elements ) : this; }) .filter(function() { var type = this.type; // Use .is(":disabled") so that fieldset[disabled] works return this.name && !jQuery( this ).is( ":disabled" ) && rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && ( this.checked || !rcheckableType.test( type ) ); }) .map(function( i, elem ) { var val = jQuery( this ).val(); return val == null ? null : jQuery.isArray( val ) ? jQuery.map( val, function( val ) { return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; }) : { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; }).get(); } }); // Create the request object // (This is still attached to ajaxSettings for backward compatibility) jQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ? // Support: IE6+ function() { // XHR cannot access local files, always use ActiveX for that case return !this.isLocal && // Support: IE7-8 // oldIE XHR does not support non-RFC2616 methods (#13240) // See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx // and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9 // Although this check for six methods instead of eight // since IE also does not support "trace" and "connect" /^(get|post|head|put|delete|options)$/i.test( this.type ) && createStandardXHR() || createActiveXHR(); } : // For all other browsers, use the standard XMLHttpRequest object createStandardXHR; var xhrId = 0, xhrCallbacks = {}, xhrSupported = jQuery.ajaxSettings.xhr(); // Support: IE<10 // Open requests must be manually aborted on unload (#5280) // See https://support.microsoft.com/kb/2856746 for more info if ( window.attachEvent ) { window.attachEvent( "onunload", function() { for ( var key in xhrCallbacks ) { xhrCallbacks[ key ]( undefined, true ); } }); } // Determine support properties support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); xhrSupported = support.ajax = !!xhrSupported; // Create transport if the browser can provide an xhr if ( xhrSupported ) { jQuery.ajaxTransport(function( options ) { // Cross domain only allowed if supported through XMLHttpRequest if ( !options.crossDomain || support.cors ) { var callback; return { send: function( headers, complete ) { var i, xhr = options.xhr(), id = ++xhrId; // Open the socket xhr.open( options.type, options.url, options.async, options.username, options.password ); // Apply custom fields if provided if ( options.xhrFields ) { for ( i in options.xhrFields ) { xhr[ i ] = options.xhrFields[ i ]; } } // Override mime type if needed if ( options.mimeType && xhr.overrideMimeType ) { xhr.overrideMimeType( options.mimeType ); } // X-Requested-With header // For cross-domain requests, seeing as conditions for a preflight are // akin to a jigsaw puzzle, we simply never set it to be sure. // (it can always be set on a per-request basis or even using ajaxSetup) // For same-domain requests, won't change header if already provided. if ( !options.crossDomain && !headers["X-Requested-With"] ) { headers["X-Requested-With"] = "XMLHttpRequest"; } // Set headers for ( i in headers ) { // Support: IE<9 // IE's ActiveXObject throws a 'Type Mismatch' exception when setting // request header to a null-value. // // To keep consistent with other XHR implementations, cast the value // to string and ignore `undefined`. if ( headers[ i ] !== undefined ) { xhr.setRequestHeader( i, headers[ i ] + "" ); } } // Do send the request // This may raise an exception which is actually // handled in jQuery.ajax (so no try/catch here) xhr.send( ( options.hasContent && options.data ) || null ); // Listener callback = function( _, isAbort ) { var status, statusText, responses; // Was never called and is aborted or complete if ( callback && ( isAbort || xhr.readyState === 4 ) ) { // Clean up delete xhrCallbacks[ id ]; callback = undefined; xhr.onreadystatechange = jQuery.noop; // Abort manually if needed if ( isAbort ) { if ( xhr.readyState !== 4 ) { xhr.abort(); } } else { responses = {}; status = xhr.status; // Support: IE<10 // Accessing binary-data responseText throws an exception // (#11426) if ( typeof xhr.responseText === "string" ) { responses.text = xhr.responseText; } // Firefox throws an exception when accessing // statusText for faulty cross-domain requests try { statusText = xhr.statusText; } catch( e ) { // We normalize with Webkit giving an empty statusText statusText = ""; } // Filter status for non standard behaviors // If the request is local and we have data: assume a success // (success with no data won't get notified, that's the best we // can do given current implementations) if ( !status && options.isLocal && !options.crossDomain ) { status = responses.text ? 200 : 404; // IE - #1450: sometimes returns 1223 when it should be 204 } else if ( status === 1223 ) { status = 204; } } } // Call complete if needed if ( responses ) { complete( status, statusText, responses, xhr.getAllResponseHeaders() ); } }; if ( !options.async ) { // if we're in sync mode we fire the callback callback(); } else if ( xhr.readyState === 4 ) { // (IE6 & IE7) if it's in cache and has been // retrieved directly we need to fire the callback setTimeout( callback ); } else { // Add to the list of active xhr callbacks xhr.onreadystatechange = xhrCallbacks[ id ] = callback; } }, abort: function() { if ( callback ) { callback( undefined, true ); } } }; } }); } // Functions to create xhrs function createStandardXHR() { try { return new window.XMLHttpRequest(); } catch( e ) {} } function createActiveXHR() { try { return new window.ActiveXObject( "Microsoft.XMLHTTP" ); } catch( e ) {} } // Install script dataType jQuery.ajaxSetup({ accepts: { script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" }, contents: { script: /(?:java|ecma)script/ }, converters: { "text script": function( text ) { jQuery.globalEval( text ); return text; } } }); // Handle cache's special case and global jQuery.ajaxPrefilter( "script", function( s ) { if ( s.cache === undefined ) { s.cache = false; } if ( s.crossDomain ) { s.type = "GET"; s.global = false; } }); // Bind script tag hack transport jQuery.ajaxTransport( "script", function(s) { // This transport only deals with cross domain requests if ( s.crossDomain ) { var script, head = document.head || jQuery("head")[0] || document.documentElement; return { send: function( _, callback ) { script = document.createElement("script"); script.async = true; if ( s.scriptCharset ) { script.charset = s.scriptCharset; } script.src = s.url; // Attach handlers for all browsers script.onload = script.onreadystatechange = function( _, isAbort ) { if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) { // Handle memory leak in IE script.onload = script.onreadystatechange = null; // Remove the script if ( script.parentNode ) { script.parentNode.removeChild( script ); } // Dereference the script script = null; // Callback if not abort if ( !isAbort ) { callback( 200, "success" ); } } }; // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending // Use native DOM manipulation to avoid our domManip AJAX trickery head.insertBefore( script, head.firstChild ); }, abort: function() { if ( script ) { script.onload( undefined, true ); } } }; } }); var oldCallbacks = [], rjsonp = /(=)\?(?=&|$)|\?\?/; // Default jsonp settings jQuery.ajaxSetup({ jsonp: "callback", jsonpCallback: function() { var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) ); this[ callback ] = true; return callback; } }); // Detect, normalize options and install callbacks for jsonp requests jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { var callbackName, overwritten, responseContainer, jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ? "url" : typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data" ); // Handle iff the expected data type is "jsonp" or we have a parameter to set if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) { // Get callback name, remembering preexisting value associated with it callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback; // Insert callback into url or form data if ( jsonProp ) { s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName ); } else if ( s.jsonp !== false ) { s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; } // Use data converter to retrieve json after script execution s.converters["script json"] = function() { if ( !responseContainer ) { jQuery.error( callbackName + " was not called" ); } return responseContainer[ 0 ]; }; // force json dataType s.dataTypes[ 0 ] = "json"; // Install callback overwritten = window[ callbackName ]; window[ callbackName ] = function() { responseContainer = arguments; }; // Clean-up function (fires after converters) jqXHR.always(function() { // Restore preexisting value window[ callbackName ] = overwritten; // Save back as free if ( s[ callbackName ] ) { // make sure that re-using the options doesn't screw things around s.jsonpCallback = originalSettings.jsonpCallback; // save the callback name for future use oldCallbacks.push( callbackName ); } // Call if it was a function and we have a response if ( responseContainer && jQuery.isFunction( overwritten ) ) { overwritten( responseContainer[ 0 ] ); } responseContainer = overwritten = undefined; }); // Delegate to script return "script"; } }); // data: string of html // context (optional): If specified, the fragment will be created in this context, defaults to document // keepScripts (optional): If true, will include scripts passed in the html string jQuery.parseHTML = function( data, context, keepScripts ) { if ( !data || typeof data !== "string" ) { return null; } if ( typeof context === "boolean" ) { keepScripts = context; context = false; } context = context || document; var parsed = rsingleTag.exec( data ), scripts = !keepScripts && []; // Single tag if ( parsed ) { return [ context.createElement( parsed[1] ) ]; } parsed = jQuery.buildFragment( [ data ], context, scripts ); if ( scripts && scripts.length ) { jQuery( scripts ).remove(); } return jQuery.merge( [], parsed.childNodes ); }; // Keep a copy of the old load method var _load = jQuery.fn.load; /** * Load a url into a page */ jQuery.fn.load = function( url, params, callback ) { if ( typeof url !== "string" && _load ) { return _load.apply( this, arguments ); } var selector, response, type, self = this, off = url.indexOf(" "); if ( off >= 0 ) { selector = jQuery.trim( url.slice( off, url.length ) ); url = url.slice( 0, off ); } // If it's a function if ( jQuery.isFunction( params ) ) { // We assume that it's the callback callback = params; params = undefined; // Otherwise, build a param string } else if ( params && typeof params === "object" ) { type = "POST"; } // If we have elements to modify, make the request if ( self.length > 0 ) { jQuery.ajax({ url: url, // if "type" variable is undefined, then "GET" method will be used type: type, dataType: "html", data: params }).done(function( responseText ) { // Save response for use in complete callback response = arguments; self.html( selector ? // If a selector was specified, locate the right elements in a dummy div // Exclude scripts to avoid IE 'Permission Denied' errors jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) : // Otherwise use the full result responseText ); }).complete( callback && function( jqXHR, status ) { self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] ); }); } return this; }; // Attach a bunch of functions for handling common AJAX events jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) { jQuery.fn[ type ] = function( fn ) { return this.on( type, fn ); }; }); jQuery.expr.filters.animated = function( elem ) { return jQuery.grep(jQuery.timers, function( fn ) { return elem === fn.elem; }).length; }; var docElem = window.document.documentElement; /** * Gets a window from an element */ function getWindow( elem ) { return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 ? elem.defaultView || elem.parentWindow : false; } jQuery.offset = { setOffset: function( elem, options, i ) { var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition, position = jQuery.css( elem, "position" ), curElem = jQuery( elem ), props = {}; // set position first, in-case top/left are set even on static elem if ( position === "static" ) { elem.style.position = "relative"; } curOffset = curElem.offset(); curCSSTop = jQuery.css( elem, "top" ); curCSSLeft = jQuery.css( elem, "left" ); calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [ curCSSTop, curCSSLeft ] ) > -1; // need to be able to calculate position if either top or left is auto and position is either absolute or fixed if ( calculatePosition ) { curPosition = curElem.position(); curTop = curPosition.top; curLeft = curPosition.left; } else { curTop = parseFloat( curCSSTop ) || 0; curLeft = parseFloat( curCSSLeft ) || 0; } if ( jQuery.isFunction( options ) ) { options = options.call( elem, i, curOffset ); } if ( options.top != null ) { props.top = ( options.top - curOffset.top ) + curTop; } if ( options.left != null ) { props.left = ( options.left - curOffset.left ) + curLeft; } if ( "using" in options ) { options.using.call( elem, props ); } else { curElem.css( props ); } } }; jQuery.fn.extend({ offset: function( options ) { if ( arguments.length ) { return options === undefined ? this : this.each(function( i ) { jQuery.offset.setOffset( this, options, i ); }); } var docElem, win, box = { top: 0, left: 0 }, elem = this[ 0 ], doc = elem && elem.ownerDocument; if ( !doc ) { return; } docElem = doc.documentElement; // Make sure it's not a disconnected DOM node if ( !jQuery.contains( docElem, elem ) ) { return box; } // If we don't have gBCR, just use 0,0 rather than error // BlackBerry 5, iOS 3 (original iPhone) if ( typeof elem.getBoundingClientRect !== strundefined ) { box = elem.getBoundingClientRect(); } win = getWindow( doc ); return { top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ), left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 ) }; }, position: function() { if ( !this[ 0 ] ) { return; } var offsetParent, offset, parentOffset = { top: 0, left: 0 }, elem = this[ 0 ]; // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent if ( jQuery.css( elem, "position" ) === "fixed" ) { // we assume that getBoundingClientRect is available when computed position is fixed offset = elem.getBoundingClientRect(); } else { // Get *real* offsetParent offsetParent = this.offsetParent(); // Get correct offsets offset = this.offset(); if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) { parentOffset = offsetParent.offset(); } // Add offsetParent borders parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ); parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true ); } // Subtract parent offsets and element margins // note: when an element has margin: auto the offsetLeft and marginLeft // are the same in Safari causing offset.left to incorrectly be 0 return { top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ), left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true) }; }, offsetParent: function() { return this.map(function() { var offsetParent = this.offsetParent || docElem; while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) { offsetParent = offsetParent.offsetParent; } return offsetParent || docElem; }); } }); // Create scrollLeft and scrollTop methods jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) { var top = /Y/.test( prop ); jQuery.fn[ method ] = function( val ) { return access( this, function( elem, method, val ) { var win = getWindow( elem ); if ( val === undefined ) { return win ? (prop in win) ? win[ prop ] : win.document.documentElement[ method ] : elem[ method ]; } if ( win ) { win.scrollTo( !top ? val : jQuery( win ).scrollLeft(), top ? val : jQuery( win ).scrollTop() ); } else { elem[ method ] = val; } }, method, val, arguments.length, null ); }; }); // Add the top/left cssHooks using jQuery.fn.position // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084 // getComputedStyle returns percent when specified for top/left/bottom/right // rather than make the css module depend on the offset module, we just check for it here jQuery.each( [ "top", "left" ], function( i, prop ) { jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition, function( elem, computed ) { if ( computed ) { computed = curCSS( elem, prop ); // if curCSS returns percentage, fallback to offset return rnumnonpx.test( computed ) ? jQuery( elem ).position()[ prop ] + "px" : computed; } } ); }); // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) { // margin is only for outerHeight, outerWidth jQuery.fn[ funcName ] = function( margin, value ) { var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ), extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" ); return access( this, function( elem, type, value ) { var doc; if ( jQuery.isWindow( elem ) ) { // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there // isn't a whole lot we can do. See pull request at this URL for discussion: // https://github.com/jquery/jquery/pull/764 return elem.document.documentElement[ "client" + name ]; } // Get document width or height if ( elem.nodeType === 9 ) { doc = elem.documentElement; // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it. return Math.max( elem.body[ "scroll" + name ], doc[ "scroll" + name ], elem.body[ "offset" + name ], doc[ "offset" + name ], doc[ "client" + name ] ); } return value === undefined ? // Get width or height on the element, requesting but not forcing parseFloat jQuery.css( elem, type, extra ) : // Set width or height on the element jQuery.style( elem, type, value, extra ); }, type, chainable ? margin : undefined, chainable, null ); }; }); }); // The number of elements contained in the matched element set jQuery.fn.size = function() { return this.length; }; jQuery.fn.andSelf = jQuery.fn.addBack; // Register as a named AMD module, since jQuery can be concatenated with other // files that may use define, but not via a proper concatenation script that // understands anonymous AMD modules. A named AMD is safest and most robust // way to register. Lowercase jquery is used because AMD module names are // derived from file names, and jQuery is normally delivered in a lowercase // file name. Do this after creating the global so that if an AMD module wants // to call noConflict to hide this version of jQuery, it will work. // Note that for maximum portability, libraries that are not jQuery should // declare themselves as anonymous modules, and avoid setting a global if an // AMD loader is present. jQuery is a special case. For more information, see // https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon if ( typeof define === "function" && define.amd ) { define( "jquery", [], function() { return jQuery; }); } var // Map over jQuery in case of overwrite _jQuery = window.jQuery, // Map over the $ in case of overwrite _$ = window.$; jQuery.noConflict = function( deep ) { if ( window.$ === jQuery ) { window.$ = _$; } if ( deep && window.jQuery === jQuery ) { window.jQuery = _jQuery; } return jQuery; }; // Expose jQuery and $ identifiers, even in // AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557) // and CommonJS for browser emulators (#13566) if ( typeof noGlobal === strundefined ) { window.jQuery = window.$ = jQuery; } return jQuery; })); (function($, undefined) { /** * Unobtrusive scripting adapter for jQuery * https://github.com/rails/jquery-ujs * * Requires jQuery 1.8.0 or later. * * Released under the MIT license * */ // Cut down on the number of issues from people inadvertently including jquery_ujs twice // by detecting and raising an error when it happens. if ( $.rails !== undefined ) { $.error('jquery-ujs has already been loaded!'); } // Shorthand to make it a little easier to call public rails functions from within rails.js var rails; var $document = $(document); $.rails = rails = { // Link elements bound by jquery-ujs linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote], a[data-disable-with], a[data-disable]', // Button elements bound by jquery-ujs buttonClickSelector: 'button[data-remote]:not(form button), button[data-confirm]:not(form button)', // Select elements bound by jquery-ujs inputChangeSelector: 'select[data-remote], input[data-remote], textarea[data-remote]', // Form elements bound by jquery-ujs formSubmitSelector: 'form', // Form input elements bound by jquery-ujs formInputClickSelector: 'form input[type=submit], form input[type=image], form button[type=submit], form button:not([type]), input[type=submit][form], input[type=image][form], button[type=submit][form], button[form]:not([type])', // Form input elements disabled during form submission disableSelector: 'input[data-disable-with]:enabled, button[data-disable-with]:enabled, textarea[data-disable-with]:enabled, input[data-disable]:enabled, button[data-disable]:enabled, textarea[data-disable]:enabled', // Form input elements re-enabled after form submission enableSelector: 'input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled, input[data-disable]:disabled, button[data-disable]:disabled, textarea[data-disable]:disabled', // Form required input elements requiredInputSelector: 'input[name][required]:not([disabled]),textarea[name][required]:not([disabled])', // Form file input elements fileInputSelector: 'input[type=file]', // Link onClick disable selector with possible reenable after remote submission linkDisableSelector: 'a[data-disable-with], a[data-disable]', // Button onClick disable selector with possible reenable after remote submission buttonDisableSelector: 'button[data-remote][data-disable-with], button[data-remote][data-disable]', // Make sure that every Ajax request sends the CSRF token CSRFProtection: function(xhr) { var token = $('meta[name="csrf-token"]').attr('content'); if (token) xhr.setRequestHeader('X-CSRF-Token', token); }, // making sure that all forms have actual up-to-date token(cached forms contain old one) refreshCSRFTokens: function(){ var csrfToken = $('meta[name=csrf-token]').attr('content'); var csrfParam = $('meta[name=csrf-param]').attr('content'); $('form input[name="' + csrfParam + '"]').val(csrfToken); }, // Triggers an event on an element and returns false if the event result is false fire: function(obj, name, data) { var event = $.Event(name); obj.trigger(event, data); return event.result !== false; }, // Default confirm dialog, may be overridden with custom confirm dialog in $.rails.confirm confirm: function(message) { return confirm(message); }, // Default ajax function, may be overridden with custom function in $.rails.ajax ajax: function(options) { return $.ajax(options); }, // Default way to get an element's href. May be overridden at $.rails.href. href: function(element) { return element.attr('href'); }, // Submits "remote" forms and links with ajax handleRemote: function(element) { var method, url, data, elCrossDomain, crossDomain, withCredentials, dataType, options; if (rails.fire(element, 'ajax:before')) { elCrossDomain = element.data('cross-domain'); crossDomain = elCrossDomain === undefined ? null : elCrossDomain; withCredentials = element.data('with-credentials') || null; dataType = element.data('type') || ($.ajaxSettings && $.ajaxSettings.dataType); if (element.is('form')) { method = element.attr('method'); url = element.attr('action'); data = element.serializeArray(); // memoized value from clicked submit button var button = element.data('ujs:submit-button'); if (button) { data.push(button); element.data('ujs:submit-button', null); } } else if (element.is(rails.inputChangeSelector)) { method = element.data('method'); url = element.data('url'); data = element.serialize(); if (element.data('params')) data = data + "&" + element.data('params'); } else if (element.is(rails.buttonClickSelector)) { method = element.data('method') || 'get'; url = element.data('url'); data = element.serialize(); if (element.data('params')) data = data + "&" + element.data('params'); } else { method = element.data('method'); url = rails.href(element); data = element.data('params') || null; } options = { type: method || 'GET', data: data, dataType: dataType, // stopping the "ajax:beforeSend" event will cancel the ajax request beforeSend: function(xhr, settings) { if (settings.dataType === undefined) { xhr.setRequestHeader('accept', '*/*;q=0.5, ' + settings.accepts.script); } if (rails.fire(element, 'ajax:beforeSend', [xhr, settings])) { element.trigger('ajax:send', xhr); } else { return false; } }, success: function(data, status, xhr) { element.trigger('ajax:success', [data, status, xhr]); }, complete: function(xhr, status) { element.trigger('ajax:complete', [xhr, status]); }, error: function(xhr, status, error) { element.trigger('ajax:error', [xhr, status, error]); }, crossDomain: crossDomain }; // There is no withCredentials for IE6-8 when // "Enable native XMLHTTP support" is disabled if (withCredentials) { options.xhrFields = { withCredentials: withCredentials }; } // Only pass url to `ajax` options if not blank if (url) { options.url = url; } return rails.ajax(options); } else { return false; } }, // Handles "data-method" on links such as: // <a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a> handleMethod: function(link) { var href = rails.href(link), method = link.data('method'), target = link.attr('target'), csrfToken = $('meta[name=csrf-token]').attr('content'), csrfParam = $('meta[name=csrf-param]').attr('content'), form = $('<form method="post" action="' + href + '"></form>'), metadataInput = '<input name="_method" value="' + method + '" type="hidden" />'; if (csrfParam !== undefined && csrfToken !== undefined) { metadataInput += '<input name="' + csrfParam + '" value="' + csrfToken + '" type="hidden" />'; } if (target) { form.attr('target', target); } form.hide().append(metadataInput).appendTo('body'); form.submit(); }, // Helper function that returns form elements that match the specified CSS selector // If form is actually a "form" element this will return associated elements outside the from that have // the html form attribute set formElements: function(form, selector) { return form.is('form') ? $(form[0].elements).filter(selector) : form.find(selector); }, /* Disables form elements: - Caches element value in 'ujs:enable-with' data store - Replaces element text with value of 'data-disable-with' attribute - Sets disabled property to true */ disableFormElements: function(form) { rails.formElements(form, rails.disableSelector).each(function() { rails.disableFormElement($(this)); }); }, disableFormElement: function(element) { var method, replacement; method = element.is('button') ? 'html' : 'val'; replacement = element.data('disable-with'); element.data('ujs:enable-with', element[method]()); if (replacement !== undefined) { element[method](replacement); } element.prop('disabled', true); }, /* Re-enables disabled form elements: - Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`) - Sets disabled property to false */ enableFormElements: function(form) { rails.formElements(form, rails.enableSelector).each(function() { rails.enableFormElement($(this)); }); }, enableFormElement: function(element) { var method = element.is('button') ? 'html' : 'val'; if (element.data('ujs:enable-with')) element[method](element.data('ujs:enable-with')); element.prop('disabled', false); }, /* For 'data-confirm' attribute: - Fires `confirm` event - Shows the confirmation dialog - Fires the `confirm:complete` event Returns `true` if no function stops the chain and user chose yes; `false` otherwise. Attaching a handler to the element's `confirm` event that returns a `falsy` value cancels the confirmation dialog. Attaching a handler to the element's `confirm:complete` event that returns a `falsy` value makes this function return false. The `confirm:complete` event is fired whether or not the user answered true or false to the dialog. */ allowAction: function(element) { var message = element.data('confirm'), answer = false, callback; if (!message) { return true; } if (rails.fire(element, 'confirm')) { answer = rails.confirm(message); callback = rails.fire(element, 'confirm:complete', [answer]); } return answer && callback; }, // Helper function which checks for blank inputs in a form that match the specified CSS selector blankInputs: function(form, specifiedSelector, nonBlank) { var inputs = $(), input, valueToCheck, selector = specifiedSelector || 'input,textarea', allInputs = form.find(selector); allInputs.each(function() { input = $(this); valueToCheck = input.is('input[type=checkbox],input[type=radio]') ? input.is(':checked') : input.val(); // If nonBlank and valueToCheck are both truthy, or nonBlank and valueToCheck are both falsey if (!valueToCheck === !nonBlank) { // Don't count unchecked required radio if other radio with same name is checked if (input.is('input[type=radio]') && allInputs.filter('input[type=radio]:checked[name="' + input.attr('name') + '"]').length) { return true; // Skip to next input } inputs = inputs.add(input); } }); return inputs.length ? inputs : false; }, // Helper function which checks for non-blank inputs in a form that match the specified CSS selector nonBlankInputs: function(form, specifiedSelector) { return rails.blankInputs(form, specifiedSelector, true); // true specifies nonBlank }, // Helper function, needed to provide consistent behavior in IE stopEverything: function(e) { $(e.target).trigger('ujs:everythingStopped'); e.stopImmediatePropagation(); return false; }, // replace element's html with the 'data-disable-with' after storing original html // and prevent clicking on it disableElement: function(element) { var replacement = element.data('disable-with'); element.data('ujs:enable-with', element.html()); // store enabled state if (replacement !== undefined) { element.html(replacement); } element.bind('click.railsDisable', function(e) { // prevent further clicking return rails.stopEverything(e); }); }, // restore element to its original state which was disabled by 'disableElement' above enableElement: function(element) { if (element.data('ujs:enable-with') !== undefined) { element.html(element.data('ujs:enable-with')); // set to old enabled state element.removeData('ujs:enable-with'); // clean up cache } element.unbind('click.railsDisable'); // enable element } }; if (rails.fire($document, 'rails:attachBindings')) { $.ajaxPrefilter(function(options, originalOptions, xhr){ if ( !options.crossDomain ) { rails.CSRFProtection(xhr); }}); // This event works the same as the load event, except that it fires every // time the page is loaded. // // See https://github.com/rails/jquery-ujs/issues/357 // See https://developer.mozilla.org/en-US/docs/Using_Firefox_1.5_caching $(window).on("pageshow.rails", function () { $($.rails.enableSelector).each(function () { var element = $(this); if (element.data("ujs:enable-with")) { $.rails.enableFormElement(element); } }); $($.rails.linkDisableSelector).each(function () { var element = $(this); if (element.data("ujs:enable-with")) { $.rails.enableElement(element); } }); }); $document.delegate(rails.linkDisableSelector, 'ajax:complete', function() { rails.enableElement($(this)); }); $document.delegate(rails.buttonDisableSelector, 'ajax:complete', function() { rails.enableFormElement($(this)); }); $document.delegate(rails.linkClickSelector, 'click.rails', function(e) { var link = $(this), method = link.data('method'), data = link.data('params'), metaClick = e.metaKey || e.ctrlKey; if (!rails.allowAction(link)) return rails.stopEverything(e); if (!metaClick && link.is(rails.linkDisableSelector)) rails.disableElement(link); if (link.data('remote') !== undefined) { if (metaClick && (!method || method === 'GET') && !data) { return true; } var handleRemote = rails.handleRemote(link); // response from rails.handleRemote() will either be false or a deferred object promise. if (handleRemote === false) { rails.enableElement(link); } else { handleRemote.fail( function() { rails.enableElement(link); } ); } return false; } else if (method) { rails.handleMethod(link); return false; } }); $document.delegate(rails.buttonClickSelector, 'click.rails', function(e) { var button = $(this); if (!rails.allowAction(button)) return rails.stopEverything(e); if (button.is(rails.buttonDisableSelector)) rails.disableFormElement(button); var handleRemote = rails.handleRemote(button); // response from rails.handleRemote() will either be false or a deferred object promise. if (handleRemote === false) { rails.enableFormElement(button); } else { handleRemote.fail( function() { rails.enableFormElement(button); } ); } return false; }); $document.delegate(rails.inputChangeSelector, 'change.rails', function(e) { var link = $(this); if (!rails.allowAction(link)) return rails.stopEverything(e); rails.handleRemote(link); return false; }); $document.delegate(rails.formSubmitSelector, 'submit.rails', function(e) { var form = $(this), remote = form.data('remote') !== undefined, blankRequiredInputs, nonBlankFileInputs; if (!rails.allowAction(form)) return rails.stopEverything(e); // skip other logic when required values are missing or file upload is present if (form.attr('novalidate') == undefined) { blankRequiredInputs = rails.blankInputs(form, rails.requiredInputSelector); if (blankRequiredInputs && rails.fire(form, 'ajax:aborted:required', [blankRequiredInputs])) { return rails.stopEverything(e); } } if (remote) { nonBlankFileInputs = rails.nonBlankInputs(form, rails.fileInputSelector); if (nonBlankFileInputs) { // slight timeout so that the submit button gets properly serialized // (make it easy for event handler to serialize form without disabled values) setTimeout(function(){ rails.disableFormElements(form); }, 13); var aborted = rails.fire(form, 'ajax:aborted:file', [nonBlankFileInputs]); // re-enable form elements if event bindings return false (canceling normal form submission) if (!aborted) { setTimeout(function(){ rails.enableFormElements(form); }, 13); } return aborted; } rails.handleRemote(form); return false; } else { // slight timeout so that the submit button gets properly serialized setTimeout(function(){ rails.disableFormElements(form); }, 13); } }); $document.delegate(rails.formInputClickSelector, 'click.rails', function(event) { var button = $(this); if (!rails.allowAction(button)) return rails.stopEverything(event); // register the pressed submit button var name = button.attr('name'), data = name ? {name:name, value:button.val()} : null; button.closest('form').data('ujs:submit-button', data); }); $document.delegate(rails.formSubmitSelector, 'ajax:send.rails', function(event) { if (this == event.target) rails.disableFormElements($(this)); }); $document.delegate(rails.formSubmitSelector, 'ajax:complete.rails', function(event) { if (this == event.target) rails.enableFormElements($(this)); }); $(function(){ rails.refreshCSRFTokens(); }); } })( jQuery ); (function() { var CSRFToken, Click, ComponentUrl, EVENTS, Link, ProgressBar, browserIsntBuggy, browserSupportsCustomEvents, browserSupportsPushState, browserSupportsTurbolinks, bypassOnLoadPopstate, cacheCurrentPage, cacheSize, changePage, clone, constrainPageCacheTo, createDocument, crossOriginRedirect, currentState, enableProgressBar, enableTransitionCache, executeScriptTags, extractTitleAndBody, fetch, fetchHistory, fetchReplacement, historyStateIsDefined, initializeTurbolinks, installDocumentReadyPageEventTriggers, installHistoryChangeHandler, installJqueryAjaxSuccessPageUpdateTrigger, loadedAssets, manuallyTriggerHashChangeForFirefox, pageCache, pageChangePrevented, pagesCached, popCookie, processResponse, progressBar, recallScrollPosition, ref, referer, reflectNewUrl, reflectRedirectedUrl, rememberCurrentState, rememberCurrentUrl, rememberReferer, removeNoscriptTags, requestMethodIsSafe, resetScrollPosition, setAutofocusElement, transitionCacheEnabled, transitionCacheFor, triggerEvent, visit, xhr, indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty, slice = [].slice, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; pageCache = {}; cacheSize = 10; transitionCacheEnabled = false; progressBar = null; currentState = null; loadedAssets = null; referer = null; xhr = null; EVENTS = { BEFORE_CHANGE: 'page:before-change', FETCH: 'page:fetch', RECEIVE: 'page:receive', CHANGE: 'page:change', UPDATE: 'page:update', LOAD: 'page:load', RESTORE: 'page:restore', BEFORE_UNLOAD: 'page:before-unload', EXPIRE: 'page:expire' }; fetch = function(url) { var cachedPage; url = new ComponentUrl(url); rememberReferer(); cacheCurrentPage(); if (progressBar != null) { progressBar.start(); } if (transitionCacheEnabled && (cachedPage = transitionCacheFor(url.absolute))) { fetchHistory(cachedPage); return fetchReplacement(url, null, false); } else { return fetchReplacement(url, resetScrollPosition); } }; transitionCacheFor = function(url) { var cachedPage; cachedPage = pageCache[url]; if (cachedPage && !cachedPage.transitionCacheDisabled) { return cachedPage; } }; enableTransitionCache = function(enable) { if (enable == null) { enable = true; } return transitionCacheEnabled = enable; }; enableProgressBar = function(enable) { if (enable == null) { enable = true; } if (!browserSupportsTurbolinks) { return; } if (enable) { return progressBar != null ? progressBar : progressBar = new ProgressBar('html'); } else { if (progressBar != null) { progressBar.uninstall(); } return progressBar = null; } }; fetchReplacement = function(url, onLoadFunction, showProgressBar) { if (showProgressBar == null) { showProgressBar = true; } triggerEvent(EVENTS.FETCH, { url: url.absolute }); if (xhr != null) { xhr.abort(); } xhr = new XMLHttpRequest; xhr.open('GET', url.withoutHashForIE10compatibility(), true); xhr.setRequestHeader('Accept', 'text/html, application/xhtml+xml, application/xml'); xhr.setRequestHeader('X-XHR-Referer', referer); xhr.onload = function() { var doc; triggerEvent(EVENTS.RECEIVE, { url: url.absolute }); if (doc = processResponse()) { reflectNewUrl(url); reflectRedirectedUrl(); changePage.apply(null, extractTitleAndBody(doc)); manuallyTriggerHashChangeForFirefox(); if (typeof onLoadFunction === "function") { onLoadFunction(); } return triggerEvent(EVENTS.LOAD); } else { return document.location.href = crossOriginRedirect() || url.absolute; } }; if (progressBar && showProgressBar) { xhr.onprogress = (function(_this) { return function(event) { var percent; percent = event.lengthComputable ? event.loaded / event.total * 100 : progressBar.value + (100 - progressBar.value) / 10; return progressBar.advanceTo(percent); }; })(this); } xhr.onloadend = function() { return xhr = null; }; xhr.onerror = function() { return document.location.href = url.absolute; }; return xhr.send(); }; fetchHistory = function(cachedPage) { if (xhr != null) { xhr.abort(); } changePage(cachedPage.title, cachedPage.body); recallScrollPosition(cachedPage); return triggerEvent(EVENTS.RESTORE); }; cacheCurrentPage = function() { var currentStateUrl; currentStateUrl = new ComponentUrl(currentState.url); pageCache[currentStateUrl.absolute] = { url: currentStateUrl.relative, body: document.body, title: document.title, positionY: window.pageYOffset, positionX: window.pageXOffset, cachedAt: new Date().getTime(), transitionCacheDisabled: document.querySelector('[data-no-transition-cache]') != null }; return constrainPageCacheTo(cacheSize); }; pagesCached = function(size) { if (size == null) { size = cacheSize; } if (/^[\d]+$/.test(size)) { return cacheSize = parseInt(size); } }; constrainPageCacheTo = function(limit) { var cacheTimesRecentFirst, i, key, len, pageCacheKeys, results; pageCacheKeys = Object.keys(pageCache); cacheTimesRecentFirst = pageCacheKeys.map(function(url) { return pageCache[url].cachedAt; }).sort(function(a, b) { return b - a; }); results = []; for (i = 0, len = pageCacheKeys.length; i < len; i++) { key = pageCacheKeys[i]; if (!(pageCache[key].cachedAt <= cacheTimesRecentFirst[limit])) { continue; } triggerEvent(EVENTS.EXPIRE, pageCache[key]); results.push(delete pageCache[key]); } return results; }; changePage = function(title, body, csrfToken, runScripts) { triggerEvent(EVENTS.BEFORE_UNLOAD); document.title = title; document.documentElement.replaceChild(body, document.body); if (csrfToken != null) { CSRFToken.update(csrfToken); } setAutofocusElement(); if (runScripts) { executeScriptTags(); } currentState = window.history.state; if (progressBar != null) { progressBar.done(); } triggerEvent(EVENTS.CHANGE); return triggerEvent(EVENTS.UPDATE); }; executeScriptTags = function() { var attr, copy, i, j, len, len1, nextSibling, parentNode, ref, ref1, script, scripts; scripts = Array.prototype.slice.call(document.body.querySelectorAll('script:not([data-turbolinks-eval="false"])')); for (i = 0, len = scripts.length; i < len; i++) { script = scripts[i]; if (!((ref = script.type) === '' || ref === 'text/javascript')) { continue; } copy = document.createElement('script'); ref1 = script.attributes; for (j = 0, len1 = ref1.length; j < len1; j++) { attr = ref1[j]; copy.setAttribute(attr.name, attr.value); } if (!script.hasAttribute('async')) { copy.async = false; } copy.appendChild(document.createTextNode(script.innerHTML)); parentNode = script.parentNode, nextSibling = script.nextSibling; parentNode.removeChild(script); parentNode.insertBefore(copy, nextSibling); } }; removeNoscriptTags = function(node) { node.innerHTML = node.innerHTML.replace(/<noscript[\S\s]*?<\/noscript>/ig, ''); return node; }; setAutofocusElement = function() { var autofocusElement, list; autofocusElement = (list = document.querySelectorAll('input[autofocus], textarea[autofocus]'))[list.length - 1]; if (autofocusElement && document.activeElement !== autofocusElement) { return autofocusElement.focus(); } }; reflectNewUrl = function(url) { if ((url = new ComponentUrl(url)).absolute !== referer) { return window.history.pushState({ turbolinks: true, url: url.absolute }, '', url.absolute); } }; reflectRedirectedUrl = function() { var location, preservedHash; if (location = xhr.getResponseHeader('X-XHR-Redirected-To')) { location = new ComponentUrl(location); preservedHash = location.hasNoHash() ? document.location.hash : ''; return window.history.replaceState(window.history.state, '', location.href + preservedHash); } }; crossOriginRedirect = function() { var redirect; if (((redirect = xhr.getResponseHeader('Location')) != null) && (new ComponentUrl(redirect)).crossOrigin()) { return redirect; } }; rememberReferer = function() { return referer = document.location.href; }; rememberCurrentUrl = function() { return window.history.replaceState({ turbolinks: true, url: document.location.href }, '', document.location.href); }; rememberCurrentState = function() { return currentState = window.history.state; }; manuallyTriggerHashChangeForFirefox = function() { var url; if (navigator.userAgent.match(/Firefox/) && !(url = new ComponentUrl).hasNoHash()) { window.history.replaceState(currentState, '', url.withoutHash()); return document.location.hash = url.hash; } }; recallScrollPosition = function(page) { return window.scrollTo(page.positionX, page.positionY); }; resetScrollPosition = function() { if (document.location.hash) { return document.location.href = document.location.href; } else { return window.scrollTo(0, 0); } }; clone = function(original) { var copy, key, value; if ((original == null) || typeof original !== 'object') { return original; } copy = new original.constructor(); for (key in original) { value = original[key]; copy[key] = clone(value); } return copy; }; popCookie = function(name) { var ref, value; value = ((ref = document.cookie.match(new RegExp(name + "=(\\w+)"))) != null ? ref[1].toUpperCase() : void 0) || ''; document.cookie = name + '=; expires=Thu, 01-Jan-70 00:00:01 GMT; path=/'; return value; }; triggerEvent = function(name, data) { var event; if (typeof Prototype !== 'undefined') { Event.fire(document, name, data, true); } event = document.createEvent('Events'); if (data) { event.data = data; } event.initEvent(name, true, true); return document.dispatchEvent(event); }; pageChangePrevented = function(url) { return !triggerEvent(EVENTS.BEFORE_CHANGE, { url: url }); }; processResponse = function() { var assetsChanged, clientOrServerError, doc, extractTrackAssets, intersection, validContent; clientOrServerError = function() { var ref; return (400 <= (ref = xhr.status) && ref < 600); }; validContent = function() { var contentType; return ((contentType = xhr.getResponseHeader('Content-Type')) != null) && contentType.match(/^(?:text\/html|application\/xhtml\+xml|application\/xml)(?:;|$)/); }; extractTrackAssets = function(doc) { var i, len, node, ref, results; ref = doc.querySelector('head').childNodes; results = []; for (i = 0, len = ref.length; i < len; i++) { node = ref[i]; if ((typeof node.getAttribute === "function" ? node.getAttribute('data-turbolinks-track') : void 0) != null) { results.push(node.getAttribute('src') || node.getAttribute('href')); } } return results; }; assetsChanged = function(doc) { var fetchedAssets; loadedAssets || (loadedAssets = extractTrackAssets(document)); fetchedAssets = extractTrackAssets(doc); return fetchedAssets.length !== loadedAssets.length || intersection(fetchedAssets, loadedAssets).length !== loadedAssets.length; }; intersection = function(a, b) { var i, len, ref, results, value; if (a.length > b.length) { ref = [b, a], a = ref[0], b = ref[1]; } results = []; for (i = 0, len = a.length; i < len; i++) { value = a[i]; if (indexOf.call(b, value) >= 0) { results.push(value); } } return results; }; if (!clientOrServerError() && validContent()) { doc = createDocument(xhr.responseText); if (doc && !assetsChanged(doc)) { return doc; } } }; extractTitleAndBody = function(doc) { var title; title = doc.querySelector('title'); return [title != null ? title.textContent : void 0, removeNoscriptTags(doc.querySelector('body')), CSRFToken.get(doc).token, 'runScripts']; }; CSRFToken = { get: function(doc) { var tag; if (doc == null) { doc = document; } return { node: tag = doc.querySelector('meta[name="csrf-token"]'), token: tag != null ? typeof tag.getAttribute === "function" ? tag.getAttribute('content') : void 0 : void 0 }; }, update: function(latest) { var current; current = this.get(); if ((current.token != null) && (latest != null) && current.token !== latest) { return current.node.setAttribute('content', latest); } } }; createDocument = function(html) { var doc; doc = document.documentElement.cloneNode(); doc.innerHTML = html; doc.head = doc.querySelector('head'); doc.body = doc.querySelector('body'); return doc; }; ComponentUrl = (function() { function ComponentUrl(original1) { this.original = original1 != null ? original1 : document.location.href; if (this.original.constructor === ComponentUrl) { return this.original; } this._parse(); } ComponentUrl.prototype.withoutHash = function() { return this.href.replace(this.hash, '').replace('#', ''); }; ComponentUrl.prototype.withoutHashForIE10compatibility = function() { return this.withoutHash(); }; ComponentUrl.prototype.hasNoHash = function() { return this.hash.length === 0; }; ComponentUrl.prototype.crossOrigin = function() { return this.origin !== (new ComponentUrl).origin; }; ComponentUrl.prototype._parse = function() { var ref; (this.link != null ? this.link : this.link = document.createElement('a')).href = this.original; ref = this.link, this.href = ref.href, this.protocol = ref.protocol, this.host = ref.host, this.hostname = ref.hostname, this.port = ref.port, this.pathname = ref.pathname, this.search = ref.search, this.hash = ref.hash; this.origin = [this.protocol, '//', this.hostname].join(''); if (this.port.length !== 0) { this.origin += ":" + this.port; } this.relative = [this.pathname, this.search, this.hash].join(''); return this.absolute = this.href; }; return ComponentUrl; })(); Link = (function(superClass) { extend(Link, superClass); Link.HTML_EXTENSIONS = ['html']; Link.allowExtensions = function() { var extension, extensions, i, len; extensions = 1 <= arguments.length ? slice.call(arguments, 0) : []; for (i = 0, len = extensions.length; i < len; i++) { extension = extensions[i]; Link.HTML_EXTENSIONS.push(extension); } return Link.HTML_EXTENSIONS; }; function Link(link1) { this.link = link1; if (this.link.constructor === Link) { return this.link; } this.original = this.link.href; this.originalElement = this.link; this.link = this.link.cloneNode(false); Link.__super__.constructor.apply(this, arguments); } Link.prototype.shouldIgnore = function() { return this.crossOrigin() || this._anchored() || this._nonHtml() || this._optOut() || this._target(); }; Link.prototype._anchored = function() { return (this.hash.length > 0 || this.href.charAt(this.href.length - 1) === '#') && (this.withoutHash() === (new ComponentUrl).withoutHash()); }; Link.prototype._nonHtml = function() { return this.pathname.match(/\.[a-z]+$/g) && !this.pathname.match(new RegExp("\\.(?:" + (Link.HTML_EXTENSIONS.join('|')) + ")?$", 'g')); }; Link.prototype._optOut = function() { var ignore, link; link = this.originalElement; while (!(ignore || link === document)) { ignore = link.getAttribute('data-no-turbolink') != null; link = link.parentNode; } return ignore; }; Link.prototype._target = function() { return this.link.target.length !== 0; }; return Link; })(ComponentUrl); Click = (function() { Click.installHandlerLast = function(event) { if (!event.defaultPrevented) { document.removeEventListener('click', Click.handle, false); return document.addEventListener('click', Click.handle, false); } }; Click.handle = function(event) { return new Click(event); }; function Click(event1) { this.event = event1; if (this.event.defaultPrevented) { return; } this._extractLink(); if (this._validForTurbolinks()) { if (!pageChangePrevented(this.link.absolute)) { visit(this.link.href); } this.event.preventDefault(); } } Click.prototype._extractLink = function() { var link; link = this.event.target; while (!(!link.parentNode || link.nodeName === 'A')) { link = link.parentNode; } if (link.nodeName === 'A' && link.href.length !== 0) { return this.link = new Link(link); } }; Click.prototype._validForTurbolinks = function() { return (this.link != null) && !(this.link.shouldIgnore() || this._nonStandardClick()); }; Click.prototype._nonStandardClick = function() { return this.event.which > 1 || this.event.metaKey || this.event.ctrlKey || this.event.shiftKey || this.event.altKey; }; return Click; })(); ProgressBar = (function() { var className; className = 'turbolinks-progress-bar'; function ProgressBar(elementSelector) { this.elementSelector = elementSelector; this._trickle = bind(this._trickle, this); this.value = 0; this.content = ''; this.speed = 300; this.opacity = 0.99; this.install(); } ProgressBar.prototype.install = function() { this.element = document.querySelector(this.elementSelector); this.element.classList.add(className); this.styleElement = document.createElement('style'); document.head.appendChild(this.styleElement); return this._updateStyle(); }; ProgressBar.prototype.uninstall = function() { this.element.classList.remove(className); return document.head.removeChild(this.styleElement); }; ProgressBar.prototype.start = function() { return this.advanceTo(5); }; ProgressBar.prototype.advanceTo = function(value) { var ref; if ((value > (ref = this.value) && ref <= 100)) { this.value = value; this._updateStyle(); if (this.value === 100) { return this._stopTrickle(); } else if (this.value > 0) { return this._startTrickle(); } } }; ProgressBar.prototype.done = function() { if (this.value > 0) { this.advanceTo(100); return this._reset(); } }; ProgressBar.prototype._reset = function() { var originalOpacity; originalOpacity = this.opacity; setTimeout((function(_this) { return function() { _this.opacity = 0; return _this._updateStyle(); }; })(this), this.speed / 2); return setTimeout((function(_this) { return function() { _this.value = 0; _this.opacity = originalOpacity; return _this._withSpeed(0, function() { return _this._updateStyle(true); }); }; })(this), this.speed); }; ProgressBar.prototype._startTrickle = function() { if (this.trickling) { return; } this.trickling = true; return setTimeout(this._trickle, this.speed); }; ProgressBar.prototype._stopTrickle = function() { return delete this.trickling; }; ProgressBar.prototype._trickle = function() { if (!this.trickling) { return; } this.advanceTo(this.value + Math.random() / 2); return setTimeout(this._trickle, this.speed); }; ProgressBar.prototype._withSpeed = function(speed, fn) { var originalSpeed, result; originalSpeed = this.speed; this.speed = speed; result = fn(); this.speed = originalSpeed; return result; }; ProgressBar.prototype._updateStyle = function(forceRepaint) { if (forceRepaint == null) { forceRepaint = false; } if (forceRepaint) { this._changeContentToForceRepaint(); } return this.styleElement.textContent = this._createCSSRule(); }; ProgressBar.prototype._changeContentToForceRepaint = function() { return this.content = this.content === '' ? ' ' : ''; }; ProgressBar.prototype._createCSSRule = function() { return this.elementSelector + "." + className + "::before {\n content: '" + this.content + "';\n position: fixed;\n top: 0;\n left: 0;\n z-index: 2000;\n background-color: #0076ff;\n height: 3px;\n opacity: " + this.opacity + ";\n width: " + this.value + "%;\n transition: width " + this.speed + "ms ease-out, opacity " + (this.speed / 2) + "ms ease-in;\n transform: translate3d(0,0,0);\n}"; }; return ProgressBar; })(); bypassOnLoadPopstate = function(fn) { return setTimeout(fn, 500); }; installDocumentReadyPageEventTriggers = function() { return document.addEventListener('DOMContentLoaded', (function() { triggerEvent(EVENTS.CHANGE); return triggerEvent(EVENTS.UPDATE); }), true); }; installJqueryAjaxSuccessPageUpdateTrigger = function() { if (typeof jQuery !== 'undefined') { return jQuery(document).on('ajaxSuccess', function(event, xhr, settings) { if (!jQuery.trim(xhr.responseText)) { return; } return triggerEvent(EVENTS.UPDATE); }); } }; installHistoryChangeHandler = function(event) { var cachedPage, ref; if ((ref = event.state) != null ? ref.turbolinks : void 0) { if (cachedPage = pageCache[(new ComponentUrl(event.state.url)).absolute]) { cacheCurrentPage(); return fetchHistory(cachedPage); } else { return visit(event.target.location.href); } } }; initializeTurbolinks = function() { rememberCurrentUrl(); rememberCurrentState(); document.addEventListener('click', Click.installHandlerLast, true); window.addEventListener('hashchange', function(event) { rememberCurrentUrl(); return rememberCurrentState(); }, false); return bypassOnLoadPopstate(function() { return window.addEventListener('popstate', installHistoryChangeHandler, false); }); }; historyStateIsDefined = window.history.state !== void 0 || navigator.userAgent.match(/Firefox\/2[6|7]/); browserSupportsPushState = window.history && window.history.pushState && window.history.replaceState && historyStateIsDefined; browserIsntBuggy = !navigator.userAgent.match(/CriOS\//); requestMethodIsSafe = (ref = popCookie('request_method')) === 'GET' || ref === ''; browserSupportsTurbolinks = browserSupportsPushState && browserIsntBuggy && requestMethodIsSafe; browserSupportsCustomEvents = document.addEventListener && document.createEvent; if (browserSupportsCustomEvents) { installDocumentReadyPageEventTriggers(); installJqueryAjaxSuccessPageUpdateTrigger(); } if (browserSupportsTurbolinks) { visit = fetch; initializeTurbolinks(); } else { visit = function(url) { return document.location.href = url; }; } this.Turbolinks = { visit: visit, pagesCached: pagesCached, enableTransitionCache: enableTransitionCache, enableProgressBar: enableProgressBar, allowLinkExtensions: Link.allowExtensions, supported: browserSupportsTurbolinks, EVENTS: clone(EVENTS) }; }).call(this); /** * @summary DataTables * @description Paginate, search and sort HTML tables * @version 1.9.4 * @file jquery.dataTables.js * @author Allan Jardine (www.sprymedia.co.uk) * @contact www.sprymedia.co.uk/contact * * @copyright Copyright 2008-2012 Allan Jardine, all rights reserved. * * This source file is free software, under either the GPL v2 license or a * BSD style license, available at: * http://datatables.net/license_gpl2 * http://datatables.net/license_bsd * * This source file is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details. * * For details please refer to: http://www.datatables.net */ /*jslint evil: true, undef: true, browser: true */ /*globals $, jQuery,define,_fnExternApiFunc,_fnInitialise,_fnInitComplete,_fnLanguageCompat,_fnAddColumn,_fnColumnOptions,_fnAddData,_fnCreateTr,_fnGatherData,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnServerParams,_fnAddOptionsHtml,_fnFeatureHtmlTable,_fnScrollDraw,_fnAdjustColumnSizing,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnBuildSearchArray,_fnBuildSearchRow,_fnFilterCreateSearch,_fnDataToSearch,_fnSort,_fnSortAttachListener,_fnSortingClasses,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnFeatureHtmlLength,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnNodeToDataIndex,_fnVisbleColumns,_fnCalculateEnd,_fnConvertToWidth,_fnCalculateColumnWidths,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnDetectType,_fnSettingsFromNode,_fnGetDataMaster,_fnGetTrNodes,_fnGetTdNodes,_fnEscapeRegex,_fnDeleteIndex,_fnReOrderIndex,_fnColumnOrdering,_fnLog,_fnClearTable,_fnSaveState,_fnLoadState,_fnCreateCookie,_fnReadCookie,_fnDetectHeader,_fnGetUniqueThs,_fnScrollBarWidth,_fnApplyToChildren,_fnMap,_fnGetRowData,_fnGetCellData,_fnSetCellData,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnApplyColumnDefs,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnJsonString,_fnRender,_fnNodeToColumnIndex,_fnInfoMacros,_fnBrowserDetect,_fnGetColumns*/ (/** @lends <global> */function( window, document, undefined ) { (function( factory ) { "use strict"; // Define as an AMD module if possible if ( typeof define === 'function' && define.amd ) { define( ['jquery'], factory ); } /* Define using browser globals otherwise * Prevent multiple instantiations if the script is loaded twice */ else if ( jQuery && !jQuery.fn.dataTable ) { factory( jQuery ); } } (/** @lends <global> */function( $ ) { "use strict"; /** * DataTables is a plug-in for the jQuery Javascript library. It is a * highly flexible tool, based upon the foundations of progressive * enhancement, which will add advanced interaction controls to any * HTML table. For a full list of features please refer to * <a href="http://datatables.net">DataTables.net</a>. * * Note that the <i>DataTable</i> object is not a global variable but is * aliased to <i>jQuery.fn.DataTable</i> and <i>jQuery.fn.dataTable</i> through which * it may be accessed. * * @class * @param {object} [oInit={}] Configuration object for DataTables. Options * are defined by {@link DataTable.defaults} * @requires jQuery 1.3+ * * @example * // Basic initialisation * $(document).ready( function { * $('#example').dataTable(); * } ); * * @example * // Initialisation with configuration options - in this case, disable * // pagination and sorting. * $(document).ready( function { * $('#example').dataTable( { * "bPaginate": false, * "bSort": false * } ); * } ); */ var DataTable = function( oInit ) { /** * Add a column to the list used for the table with default values * @param {object} oSettings dataTables settings object * @param {node} nTh The th element for this column * @memberof DataTable#oApi */ function _fnAddColumn( oSettings, nTh ) { var oDefaults = DataTable.defaults.columns; var iCol = oSettings.aoColumns.length; var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, { "sSortingClass": oSettings.oClasses.sSortable, "sSortingClassJUI": oSettings.oClasses.sSortJUI, "nTh": nTh ? nTh : document.createElement('th'), "sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '', "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol], "mData": oDefaults.mData ? oDefaults.oDefaults : iCol } ); oSettings.aoColumns.push( oCol ); /* Add a column specific filter */ if ( oSettings.aoPreSearchCols[ iCol ] === undefined || oSettings.aoPreSearchCols[ iCol ] === null ) { oSettings.aoPreSearchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch ); } else { var oPre = oSettings.aoPreSearchCols[ iCol ]; /* Don't require that the user must specify bRegex, bSmart or bCaseInsensitive */ if ( oPre.bRegex === undefined ) { oPre.bRegex = true; } if ( oPre.bSmart === undefined ) { oPre.bSmart = true; } if ( oPre.bCaseInsensitive === undefined ) { oPre.bCaseInsensitive = true; } } /* Use the column options function to initialise classes etc */ _fnColumnOptions( oSettings, iCol, null ); } /** * Apply options for a column * @param {object} oSettings dataTables settings object * @param {int} iCol column index to consider * @param {object} oOptions object with sType, bVisible and bSearchable etc * @memberof DataTable#oApi */ function _fnColumnOptions( oSettings, iCol, oOptions ) { var oCol = oSettings.aoColumns[ iCol ]; /* User specified column options */ if ( oOptions !== undefined && oOptions !== null ) { /* Backwards compatibility for mDataProp */ if ( oOptions.mDataProp && !oOptions.mData ) { oOptions.mData = oOptions.mDataProp; } if ( oOptions.sType !== undefined ) { oCol.sType = oOptions.sType; oCol._bAutoType = false; } $.extend( oCol, oOptions ); _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" ); /* iDataSort to be applied (backwards compatibility), but aDataSort will take * priority if defined */ if ( oOptions.iDataSort !== undefined ) { oCol.aDataSort = [ oOptions.iDataSort ]; } _fnMap( oCol, oOptions, "aDataSort" ); } /* Cache the data get and set functions for speed */ var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null; var mData = _fnGetObjectDataFn( oCol.mData ); oCol.fnGetData = function (oData, sSpecific) { var innerData = mData( oData, sSpecific ); if ( oCol.mRender && (sSpecific && sSpecific !== '') ) { return mRender( innerData, sSpecific, oData ); } return innerData; }; oCol.fnSetData = _fnSetObjectDataFn( oCol.mData ); /* Feature sorting overrides column specific when off */ if ( !oSettings.oFeatures.bSort ) { oCol.bSortable = false; } /* Check that the class assignment is correct for sorting */ if ( !oCol.bSortable || ($.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1) ) { oCol.sSortingClass = oSettings.oClasses.sSortableNone; oCol.sSortingClassJUI = ""; } else if ( $.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1 ) { oCol.sSortingClass = oSettings.oClasses.sSortable; oCol.sSortingClassJUI = oSettings.oClasses.sSortJUI; } else if ( $.inArray('asc', oCol.asSorting) != -1 && $.inArray('desc', oCol.asSorting) == -1 ) { oCol.sSortingClass = oSettings.oClasses.sSortableAsc; oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIAscAllowed; } else if ( $.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) != -1 ) { oCol.sSortingClass = oSettings.oClasses.sSortableDesc; oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIDescAllowed; } } /** * Adjust the table column widths for new data. Note: you would probably want to * do a redraw after calling this function! * @param {object} oSettings dataTables settings object * @memberof DataTable#oApi */ function _fnAdjustColumnSizing ( oSettings ) { /* Not interested in doing column width calculation if auto-width is disabled */ if ( oSettings.oFeatures.bAutoWidth === false ) { return false; } _fnCalculateColumnWidths( oSettings ); for ( var i=0 , iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) { oSettings.aoColumns[i].nTh.style.width = oSettings.aoColumns[i].sWidth; } } /** * Covert the index of a visible column to the index in the data array (take account * of hidden columns) * @param {object} oSettings dataTables settings object * @param {int} iMatch Visible column index to lookup * @returns {int} i the data index * @memberof DataTable#oApi */ function _fnVisibleToColumnIndex( oSettings, iMatch ) { var aiVis = _fnGetColumns( oSettings, 'bVisible' ); return typeof aiVis[iMatch] === 'number' ? aiVis[iMatch] : null; } /** * Covert the index of an index in the data array and convert it to the visible * column index (take account of hidden columns) * @param {int} iMatch Column index to lookup * @param {object} oSettings dataTables settings object * @returns {int} i the data index * @memberof DataTable#oApi */ function _fnColumnIndexToVisible( oSettings, iMatch ) { var aiVis = _fnGetColumns( oSettings, 'bVisible' ); var iPos = $.inArray( iMatch, aiVis ); return iPos !== -1 ? iPos : null; } /** * Get the number of visible columns * @param {object} oSettings dataTables settings object * @returns {int} i the number of visible columns * @memberof DataTable#oApi */ function _fnVisbleColumns( oSettings ) { return _fnGetColumns( oSettings, 'bVisible' ).length; } /** * Get an array of column indexes that match a given property * @param {object} oSettings dataTables settings object * @param {string} sParam Parameter in aoColumns to look for - typically * bVisible or bSearchable * @returns {array} Array of indexes with matched properties * @memberof DataTable#oApi */ function _fnGetColumns( oSettings, sParam ) { var a = []; $.map( oSettings.aoColumns, function(val, i) { if ( val[sParam] ) { a.push( i ); } } ); return a; } /** * Get the sort type based on an input string * @param {string} sData data we wish to know the type of * @returns {string} type (defaults to 'string' if no type can be detected) * @memberof DataTable#oApi */ function _fnDetectType( sData ) { var aTypes = DataTable.ext.aTypes; var iLen = aTypes.length; for ( var i=0 ; i<iLen ; i++ ) { var sType = aTypes[i]( sData ); if ( sType !== null ) { return sType; } } return 'string'; } /** * Figure out how to reorder a display list * @param {object} oSettings dataTables settings object * @returns array {int} aiReturn index list for reordering * @memberof DataTable#oApi */ function _fnReOrderIndex ( oSettings, sColumns ) { var aColumns = sColumns.split(','); var aiReturn = []; for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) { for ( var j=0 ; j<iLen ; j++ ) { if ( oSettings.aoColumns[i].sName == aColumns[j] ) { aiReturn.push( j ); break; } } } return aiReturn; } /** * Get the column ordering that DataTables expects * @param {object} oSettings dataTables settings object * @returns {string} comma separated list of names * @memberof DataTable#oApi */ function _fnColumnOrdering ( oSettings ) { var sNames = ''; for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) { sNames += oSettings.aoColumns[i].sName+','; } if ( sNames.length == iLen ) { return ""; } return sNames.slice(0, -1); } /** * Take the column definitions and static columns arrays and calculate how * they relate to column indexes. The callback function will then apply the * definition found for a column to a suitable configuration object. * @param {object} oSettings dataTables settings object * @param {array} aoColDefs The aoColumnDefs array that is to be applied * @param {array} aoCols The aoColumns array that defines columns individually * @param {function} fn Callback function - takes two parameters, the calculated * column index and the definition for that column. * @memberof DataTable#oApi */ function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn ) { var i, iLen, j, jLen, k, kLen; // Column definitions with aTargets if ( aoColDefs ) { /* Loop over the definitions array - loop in reverse so first instance has priority */ for ( i=aoColDefs.length-1 ; i>=0 ; i-- ) { /* Each definition can target multiple columns, as it is an array */ var aTargets = aoColDefs[i].aTargets; if ( !$.isArray( aTargets ) ) { _fnLog( oSettings, 1, 'aTargets must be an array of targets, not a '+(typeof aTargets) ); } for ( j=0, jLen=aTargets.length ; j<jLen ; j++ ) { if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 ) { /* Add columns that we don't yet know about */ while( oSettings.aoColumns.length <= aTargets[j] ) { _fnAddColumn( oSettings ); } /* Integer, basic index */ fn( aTargets[j], aoColDefs[i] ); } else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 ) { /* Negative integer, right to left column counting */ fn( oSettings.aoColumns.length+aTargets[j], aoColDefs[i] ); } else if ( typeof aTargets[j] === 'string' ) { /* Class name matching on TH element */ for ( k=0, kLen=oSettings.aoColumns.length ; k<kLen ; k++ ) { if ( aTargets[j] == "_all" || $(oSettings.aoColumns[k].nTh).hasClass( aTargets[j] ) ) { fn( k, aoColDefs[i] ); } } } } } } // Statically defined columns array if ( aoCols ) { for ( i=0, iLen=aoCols.length ; i<iLen ; i++ ) { fn( i, aoCols[i] ); } } } /** * Add a data array to the table, creating DOM node etc. This is the parallel to * _fnGatherData, but for adding rows from a Javascript source, rather than a * DOM source. * @param {object} oSettings dataTables settings object * @param {array} aData data array to be added * @returns {int} >=0 if successful (index of new aoData entry), -1 if failed * @memberof DataTable#oApi */ function _fnAddData ( oSettings, aDataSupplied ) { var oCol; /* Take an independent copy of the data source so we can bash it about as we wish */ var aDataIn = ($.isArray(aDataSupplied)) ? aDataSupplied.slice() : $.extend( true, {}, aDataSupplied ); /* Create the object for storing information about this new row */ var iRow = oSettings.aoData.length; var oData = $.extend( true, {}, DataTable.models.oRow ); oData._aData = aDataIn; oSettings.aoData.push( oData ); /* Create the cells */ var nTd, sThisType; for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) { oCol = oSettings.aoColumns[i]; /* Use rendered data for filtering / sorting */ if ( typeof oCol.fnRender === 'function' && oCol.bUseRendered && oCol.mData !== null ) { _fnSetCellData( oSettings, iRow, i, _fnRender(oSettings, iRow, i) ); } else { _fnSetCellData( oSettings, iRow, i, _fnGetCellData( oSettings, iRow, i ) ); } /* See if we should auto-detect the column type */ if ( oCol._bAutoType && oCol.sType != 'string' ) { /* Attempt to auto detect the type - same as _fnGatherData() */ var sVarType = _fnGetCellData( oSettings, iRow, i, 'type' ); if ( sVarType !== null && sVarType !== '' ) { sThisType = _fnDetectType( sVarType ); if ( oCol.sType === null ) { oCol.sType = sThisType; } else if ( oCol.sType != sThisType && oCol.sType != "html" ) { /* String is always the 'fallback' option */ oCol.sType = 'string'; } } } } /* Add to the display array */ oSettings.aiDisplayMaster.push( iRow ); /* Create the DOM information */ if ( !oSettings.oFeatures.bDeferRender ) { _fnCreateTr( oSettings, iRow ); } return iRow; } /** * Read in the data from the target table from the DOM * @param {object} oSettings dataTables settings object * @memberof DataTable#oApi */ function _fnGatherData( oSettings ) { var iLoop, i, iLen, j, jLen, jInner, nTds, nTrs, nTd, nTr, aLocalData, iThisIndex, iRow, iRows, iColumn, iColumns, sNodeName, oCol, oData; /* * Process by row first * Add the data object for the whole table - storing the tr node. Note - no point in getting * DOM based data if we are going to go and replace it with Ajax source data. */ if ( oSettings.bDeferLoading || oSettings.sAjaxSource === null ) { nTr = oSettings.nTBody.firstChild; while ( nTr ) { if ( nTr.nodeName.toUpperCase() == "TR" ) { iThisIndex = oSettings.aoData.length; nTr._DT_RowIndex = iThisIndex; oSettings.aoData.push( $.extend( true, {}, DataTable.models.oRow, { "nTr": nTr } ) ); oSettings.aiDisplayMaster.push( iThisIndex ); nTd = nTr.firstChild; jInner = 0; while ( nTd ) { sNodeName = nTd.nodeName.toUpperCase(); if ( sNodeName == "TD" || sNodeName == "TH" ) { _fnSetCellData( oSettings, iThisIndex, jInner, $.trim(nTd.innerHTML) ); jInner++; } nTd = nTd.nextSibling; } } nTr = nTr.nextSibling; } } /* Gather in the TD elements of the Table - note that this is basically the same as * fnGetTdNodes, but that function takes account of hidden columns, which we haven't yet * setup! */ nTrs = _fnGetTrNodes( oSettings ); nTds = []; for ( i=0, iLen=nTrs.length ; i<iLen ; i++ ) { nTd = nTrs[i].firstChild; while ( nTd ) { sNodeName = nTd.nodeName.toUpperCase(); if ( sNodeName == "TD" || sNodeName == "TH" ) { nTds.push( nTd ); } nTd = nTd.nextSibling; } } /* Now process by column */ for ( iColumn=0, iColumns=oSettings.aoColumns.length ; iColumn<iColumns ; iColumn++ ) { oCol = oSettings.aoColumns[iColumn]; /* Get the title of the column - unless there is a user set one */ if ( oCol.sTitle === null ) { oCol.sTitle = oCol.nTh.innerHTML; } var bAutoType = oCol._bAutoType, bRender = typeof oCol.fnRender === 'function', bClass = oCol.sClass !== null, bVisible = oCol.bVisible, nCell, sThisType, sRendered, sValType; /* A single loop to rule them all (and be more efficient) */ if ( bAutoType || bRender || bClass || !bVisible ) { for ( iRow=0, iRows=oSettings.aoData.length ; iRow<iRows ; iRow++ ) { oData = oSettings.aoData[iRow]; nCell = nTds[ (iRow*iColumns) + iColumn ]; /* Type detection */ if ( bAutoType && oCol.sType != 'string' ) { sValType = _fnGetCellData( oSettings, iRow, iColumn, 'type' ); if ( sValType !== '' ) { sThisType = _fnDetectType( sValType ); if ( oCol.sType === null ) { oCol.sType = sThisType; } else if ( oCol.sType != sThisType && oCol.sType != "html" ) { /* String is always the 'fallback' option */ oCol.sType = 'string'; } } } if ( oCol.mRender ) { // mRender has been defined, so we need to get the value and set it nCell.innerHTML = _fnGetCellData( oSettings, iRow, iColumn, 'display' ); } else if ( oCol.mData !== iColumn ) { // If mData is not the same as the column number, then we need to // get the dev set value. If it is the column, no point in wasting // time setting the value that is already there! nCell.innerHTML = _fnGetCellData( oSettings, iRow, iColumn, 'display' ); } /* Rendering */ if ( bRender ) { sRendered = _fnRender( oSettings, iRow, iColumn ); nCell.innerHTML = sRendered; if ( oCol.bUseRendered ) { /* Use the rendered data for filtering / sorting */ _fnSetCellData( oSettings, iRow, iColumn, sRendered ); } } /* Classes */ if ( bClass ) { nCell.className += ' '+oCol.sClass; } /* Column visibility */ if ( !bVisible ) { oData._anHidden[iColumn] = nCell; nCell.parentNode.removeChild( nCell ); } else { oData._anHidden[iColumn] = null; } if ( oCol.fnCreatedCell ) { oCol.fnCreatedCell.call( oSettings.oInstance, nCell, _fnGetCellData( oSettings, iRow, iColumn, 'display' ), oData._aData, iRow, iColumn ); } } } } /* Row created callbacks */ if ( oSettings.aoRowCreatedCallback.length !== 0 ) { for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ ) { oData = oSettings.aoData[i]; _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [oData.nTr, oData._aData, i] ); } } } /** * Take a TR element and convert it to an index in aoData * @param {object} oSettings dataTables settings object * @param {node} n the TR element to find * @returns {int} index if the node is found, null if not * @memberof DataTable#oApi */ function _fnNodeToDataIndex( oSettings, n ) { return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null; } /** * Take a TD element and convert it into a column data index (not the visible index) * @param {object} oSettings dataTables settings object * @param {int} iRow The row number the TD/TH can be found in * @param {node} n The TD/TH element to find * @returns {int} index if the node is found, -1 if not * @memberof DataTable#oApi */ function _fnNodeToColumnIndex( oSettings, iRow, n ) { var anCells = _fnGetTdNodes( oSettings, iRow ); for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) { if ( anCells[i] === n ) { return i; } } return -1; } /** * Get an array of data for a given row from the internal data cache * @param {object} oSettings dataTables settings object * @param {int} iRow aoData row id * @param {string} sSpecific data get type ('type' 'filter' 'sort') * @param {array} aiColumns Array of column indexes to get data from * @returns {array} Data array * @memberof DataTable#oApi */ function _fnGetRowData( oSettings, iRow, sSpecific, aiColumns ) { var out = []; for ( var i=0, iLen=aiColumns.length ; i<iLen ; i++ ) { out.push( _fnGetCellData( oSettings, iRow, aiColumns[i], sSpecific ) ); } return out; } /** * Get the data for a given cell from the internal cache, taking into account data mapping * @param {object} oSettings dataTables settings object * @param {int} iRow aoData row id * @param {int} iCol Column index * @param {string} sSpecific data get type ('display', 'type' 'filter' 'sort') * @returns {*} Cell data * @memberof DataTable#oApi */ function _fnGetCellData( oSettings, iRow, iCol, sSpecific ) { var sData; var oCol = oSettings.aoColumns[iCol]; var oData = oSettings.aoData[iRow]._aData; if ( (sData=oCol.fnGetData( oData, sSpecific )) === undefined ) { if ( oSettings.iDrawError != oSettings.iDraw && oCol.sDefaultContent === null ) { _fnLog( oSettings, 0, "Requested unknown parameter "+ (typeof oCol.mData=='function' ? '{mData function}' : "'"+oCol.mData+"'")+ " from the data source for row "+iRow ); oSettings.iDrawError = oSettings.iDraw; } return oCol.sDefaultContent; } /* When the data source is null, we can use default column data */ if ( sData === null && oCol.sDefaultContent !== null ) { sData = oCol.sDefaultContent; } else if ( typeof sData === 'function' ) { /* If the data source is a function, then we run it and use the return */ return sData(); } if ( sSpecific == 'display' && sData === null ) { return ''; } return sData; } /** * Set the value for a specific cell, into the internal data cache * @param {object} oSettings dataTables settings object * @param {int} iRow aoData row id * @param {int} iCol Column index * @param {*} val Value to set * @memberof DataTable#oApi */ function _fnSetCellData( oSettings, iRow, iCol, val ) { var oCol = oSettings.aoColumns[iCol]; var oData = oSettings.aoData[iRow]._aData; oCol.fnSetData( oData, val ); } // Private variable that is used to match array syntax in the data property object var __reArray = /\[.*?\]$/; /** * Return a function that can be used to get data from a source object, taking * into account the ability to use nested objects as a source * @param {string|int|function} mSource The data source for the object * @returns {function} Data get function * @memberof DataTable#oApi */ function _fnGetObjectDataFn( mSource ) { if ( mSource === null ) { /* Give an empty string for rendering / sorting etc */ return function (data, type) { return null; }; } else if ( typeof mSource === 'function' ) { return function (data, type, extra) { return mSource( data, type, extra ); }; } else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || mSource.indexOf('[') !== -1) ) { /* If there is a . in the source string then the data source is in a * nested object so we loop over the data for each level to get the next * level down. On each loop we test for undefined, and if found immediately * return. This allows entire objects to be missing and sDefaultContent to * be used if defined, rather than throwing an error */ var fetchData = function (data, type, src) { var a = src.split('.'); var arrayNotation, out, innerSrc; if ( src !== "" ) { for ( var i=0, iLen=a.length ; i<iLen ; i++ ) { // Check if we are dealing with an array notation request arrayNotation = a[i].match(__reArray); if ( arrayNotation ) { a[i] = a[i].replace(__reArray, ''); // Condition allows simply [] to be passed in if ( a[i] !== "" ) { data = data[ a[i] ]; } out = []; // Get the remainder of the nested object to get a.splice( 0, i+1 ); innerSrc = a.join('.'); // Traverse each entry in the array getting the properties requested for ( var j=0, jLen=data.length ; j<jLen ; j++ ) { out.push( fetchData( data[j], type, innerSrc ) ); } // If a string is given in between the array notation indicators, that // is used to join the strings together, otherwise an array is returned var join = arrayNotation[0].substring(1, arrayNotation[0].length-1); data = (join==="") ? out : out.join(join); // The inner call to fetchData has already traversed through the remainder // of the source requested, so we exit from the loop break; } if ( data === null || data[ a[i] ] === undefined ) { return undefined; } data = data[ a[i] ]; } } return data; }; return function (data, type) { return fetchData( data, type, mSource ); }; } else { /* Array or flat object mapping */ return function (data, type) { return data[mSource]; }; } } /** * Return a function that can be used to set data from a source object, taking * into account the ability to use nested objects as a source * @param {string|int|function} mSource The data source for the object * @returns {function} Data set function * @memberof DataTable#oApi */ function _fnSetObjectDataFn( mSource ) { if ( mSource === null ) { /* Nothing to do when the data source is null */ return function (data, val) {}; } else if ( typeof mSource === 'function' ) { return function (data, val) { mSource( data, 'set', val ); }; } else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || mSource.indexOf('[') !== -1) ) { /* Like the get, we need to get data from a nested object */ var setData = function (data, val, src) { var a = src.split('.'), b; var arrayNotation, o, innerSrc; for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ ) { // Check if we are dealing with an array notation request arrayNotation = a[i].match(__reArray); if ( arrayNotation ) { a[i] = a[i].replace(__reArray, ''); data[ a[i] ] = []; // Get the remainder of the nested object to set so we can recurse b = a.slice(); b.splice( 0, i+1 ); innerSrc = b.join('.'); // Traverse each entry in the array setting the properties requested for ( var j=0, jLen=val.length ; j<jLen ; j++ ) { o = {}; setData( o, val[j], innerSrc ); data[ a[i] ].push( o ); } // The inner call to setData has already traversed through the remainder // of the source and has set the data, thus we can exit here return; } // If the nested object doesn't currently exist - since we are // trying to set the value - create it if ( data[ a[i] ] === null || data[ a[i] ] === undefined ) { data[ a[i] ] = {}; } data = data[ a[i] ]; } // If array notation is used, we just want to strip it and use the property name // and assign the value. If it isn't used, then we get the result we want anyway data[ a[a.length-1].replace(__reArray, '') ] = val; }; return function (data, val) { return setData( data, val, mSource ); }; } else { /* Array or flat object mapping */ return function (data, val) { data[mSource] = val; }; } } /** * Return an array with the full table data * @param {object} oSettings dataTables settings object * @returns array {array} aData Master data array * @memberof DataTable#oApi */ function _fnGetDataMaster ( oSettings ) { var aData = []; var iLen = oSettings.aoData.length; for ( var i=0 ; i<iLen; i++ ) { aData.push( oSettings.aoData[i]._aData ); } return aData; } /** * Nuke the table * @param {object} oSettings dataTables settings object * @memberof DataTable#oApi */ function _fnClearTable( oSettings ) { oSettings.aoData.splice( 0, oSettings.aoData.length ); oSettings.aiDisplayMaster.splice( 0, oSettings.aiDisplayMaster.length ); oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length ); _fnCalculateEnd( oSettings ); } /** * Take an array of integers (index array) and remove a target integer (value - not * the key!) * @param {array} a Index array to target * @param {int} iTarget value to find * @memberof DataTable#oApi */ function _fnDeleteIndex( a, iTarget ) { var iTargetIndex = -1; for ( var i=0, iLen=a.length ; i<iLen ; i++ ) { if ( a[i] == iTarget ) { iTargetIndex = i; } else if ( a[i] > iTarget ) { a[i]--; } } if ( iTargetIndex != -1 ) { a.splice( iTargetIndex, 1 ); } } /** * Call the developer defined fnRender function for a given cell (row/column) with * the required parameters and return the result. * @param {object} oSettings dataTables settings object * @param {int} iRow aoData index for the row * @param {int} iCol aoColumns index for the column * @returns {*} Return of the developer's fnRender function * @memberof DataTable#oApi */ function _fnRender( oSettings, iRow, iCol ) { var oCol = oSettings.aoColumns[iCol]; return oCol.fnRender( { "iDataRow": iRow, "iDataColumn": iCol, "oSettings": oSettings, "aData": oSettings.aoData[iRow]._aData, "mDataProp": oCol.mData }, _fnGetCellData(oSettings, iRow, iCol, 'display') ); } /** * Create a new TR element (and it's TD children) for a row * @param {object} oSettings dataTables settings object * @param {int} iRow Row to consider * @memberof DataTable#oApi */ function _fnCreateTr ( oSettings, iRow ) { var oData = oSettings.aoData[iRow]; var nTd; if ( oData.nTr === null ) { oData.nTr = document.createElement('tr'); /* Use a private property on the node to allow reserve mapping from the node * to the aoData array for fast look up */ oData.nTr._DT_RowIndex = iRow; /* Special parameters can be given by the data source to be used on the row */ if ( oData._aData.DT_RowId ) { oData.nTr.id = oData._aData.DT_RowId; } if ( oData._aData.DT_RowClass ) { oData.nTr.className = oData._aData.DT_RowClass; } /* Process each column */ for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) { var oCol = oSettings.aoColumns[i]; nTd = document.createElement( oCol.sCellType ); /* Render if needed - if bUseRendered is true then we already have the rendered * value in the data source - so can just use that */ nTd.innerHTML = (typeof oCol.fnRender === 'function' && (!oCol.bUseRendered || oCol.mData === null)) ? _fnRender( oSettings, iRow, i ) : _fnGetCellData( oSettings, iRow, i, 'display' ); /* Add user defined class */ if ( oCol.sClass !== null ) { nTd.className = oCol.sClass; } if ( oCol.bVisible ) { oData.nTr.appendChild( nTd ); oData._anHidden[i] = null; } else { oData._anHidden[i] = nTd; } if ( oCol.fnCreatedCell ) { oCol.fnCreatedCell.call( oSettings.oInstance, nTd, _fnGetCellData( oSettings, iRow, i, 'display' ), oData._aData, iRow, i ); } } _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [oData.nTr, oData._aData, iRow] ); } } /** * Create the HTML header for the table * @param {object} oSettings dataTables settings object * @memberof DataTable#oApi */ function _fnBuildHead( oSettings ) { var i, nTh, iLen, j, jLen; var iThs = $('th, td', oSettings.nTHead).length; var iCorrector = 0; var jqChildren; /* If there is a header in place - then use it - otherwise it's going to get nuked... */ if ( iThs !== 0 ) { /* We've got a thead from the DOM, so remove hidden columns and apply width to vis cols */ for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) { nTh = oSettings.aoColumns[i].nTh; nTh.setAttribute('role', 'columnheader'); if ( oSettings.aoColumns[i].bSortable ) { nTh.setAttribute('tabindex', oSettings.iTabIndex); nTh.setAttribute('aria-controls', oSettings.sTableId); } if ( oSettings.aoColumns[i].sClass !== null ) { $(nTh).addClass( oSettings.aoColumns[i].sClass ); } /* Set the title of the column if it is user defined (not what was auto detected) */ if ( oSettings.aoColumns[i].sTitle != nTh.innerHTML ) { nTh.innerHTML = oSettings.aoColumns[i].sTitle; } } } else { /* We don't have a header in the DOM - so we are going to have to create one */ var nTr = document.createElement( "tr" ); for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) { nTh = oSettings.aoColumns[i].nTh; nTh.innerHTML = oSettings.aoColumns[i].sTitle; nTh.setAttribute('tabindex', '0'); if ( oSettings.aoColumns[i].sClass !== null ) { $(nTh).addClass( oSettings.aoColumns[i].sClass ); } nTr.appendChild( nTh ); } $(oSettings.nTHead).html( '' )[0].appendChild( nTr ); _fnDetectHeader( oSettings.aoHeader, oSettings.nTHead ); } /* ARIA role for the rows */ $(oSettings.nTHead).children('tr').attr('role', 'row'); /* Add the extra markup needed by jQuery UI's themes */ if ( oSettings.bJUI ) { for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) { nTh = oSettings.aoColumns[i].nTh; var nDiv = document.createElement('div'); nDiv.className = oSettings.oClasses.sSortJUIWrapper; $(nTh).contents().appendTo(nDiv); var nSpan = document.createElement('span'); nSpan.className = oSettings.oClasses.sSortIcon; nDiv.appendChild( nSpan ); nTh.appendChild( nDiv ); } } if ( oSettings.oFeatures.bSort ) { for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) { if ( oSettings.aoColumns[i].bSortable !== false ) { _fnSortAttachListener( oSettings, oSettings.aoColumns[i].nTh, i ); } else { $(oSettings.aoColumns[i].nTh).addClass( oSettings.oClasses.sSortableNone ); } } } /* Deal with the footer - add classes if required */ if ( oSettings.oClasses.sFooterTH !== "" ) { $(oSettings.nTFoot).children('tr').children('th').addClass( oSettings.oClasses.sFooterTH ); } /* Cache the footer elements */ if ( oSettings.nTFoot !== null ) { var anCells = _fnGetUniqueThs( oSettings, null, oSettings.aoFooter ); for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) { if ( anCells[i] ) { oSettings.aoColumns[i].nTf = anCells[i]; if ( oSettings.aoColumns[i].sClass ) { $(anCells[i]).addClass( oSettings.aoColumns[i].sClass ); } } } } } /** * Draw the header (or footer) element based on the column visibility states. The * methodology here is to use the layout array from _fnDetectHeader, modified for * the instantaneous column visibility, to construct the new layout. The grid is * traversed over cell at a time in a rows x columns grid fashion, although each * cell insert can cover multiple elements in the grid - which is tracks using the * aApplied array. Cell inserts in the grid will only occur where there isn't * already a cell in that position. * @param {object} oSettings dataTables settings object * @param array {objects} aoSource Layout array from _fnDetectHeader * @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc, * @memberof DataTable#oApi */ function _fnDrawHead( oSettings, aoSource, bIncludeHidden ) { var i, iLen, j, jLen, k, kLen, n, nLocalTr; var aoLocal = []; var aApplied = []; var iColumns = oSettings.aoColumns.length; var iRowspan, iColspan; if ( bIncludeHidden === undefined ) { bIncludeHidden = false; } /* Make a copy of the master layout array, but without the visible columns in it */ for ( i=0, iLen=aoSource.length ; i<iLen ; i++ ) { aoLocal[i] = aoSource[i].slice(); aoLocal[i].nTr = aoSource[i].nTr; /* Remove any columns which are currently hidden */ for ( j=iColumns-1 ; j>=0 ; j-- ) { if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden ) { aoLocal[i].splice( j, 1 ); } } /* Prep the applied array - it needs an element for each row */ aApplied.push( [] ); } for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ ) { nLocalTr = aoLocal[i].nTr; /* All cells are going to be replaced, so empty out the row */ if ( nLocalTr ) { while( (n = nLocalTr.firstChild) ) { nLocalTr.removeChild( n ); } } for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ ) { iRowspan = 1; iColspan = 1; /* Check to see if there is already a cell (row/colspan) covering our target * insert point. If there is, then there is nothing to do. */ if ( aApplied[i][j] === undefined ) { nLocalTr.appendChild( aoLocal[i][j].cell ); aApplied[i][j] = 1; /* Expand the cell to cover as many rows as needed */ while ( aoLocal[i+iRowspan] !== undefined && aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell ) { aApplied[i+iRowspan][j] = 1; iRowspan++; } /* Expand the cell to cover as many columns as needed */ while ( aoLocal[i][j+iColspan] !== undefined && aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell ) { /* Must update the applied array over the rows for the columns */ for ( k=0 ; k<iRowspan ; k++ ) { aApplied[i+k][j+iColspan] = 1; } iColspan++; } /* Do the actual expansion in the DOM */ aoLocal[i][j].cell.rowSpan = iRowspan; aoLocal[i][j].cell.colSpan = iColspan; } } } } /** * Insert the required TR nodes into the table for display * @param {object} oSettings dataTables settings object * @memberof DataTable#oApi */ function _fnDraw( oSettings ) { /* Provide a pre-callback function which can be used to cancel the draw is false is returned */ var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] ); if ( $.inArray( false, aPreDraw ) !== -1 ) { _fnProcessingDisplay( oSettings, false ); return; } var i, iLen, n; var anRows = []; var iRowCount = 0; var iStripes = oSettings.asStripeClasses.length; var iOpenRows = oSettings.aoOpenRows.length; oSettings.bDrawing = true; /* Check and see if we have an initial draw position from state saving */ if ( oSettings.iInitDisplayStart !== undefined && oSettings.iInitDisplayStart != -1 ) { if ( oSettings.oFeatures.bServerSide ) { oSettings._iDisplayStart = oSettings.iInitDisplayStart; } else { oSettings._iDisplayStart = (oSettings.iInitDisplayStart >= oSettings.fnRecordsDisplay()) ? 0 : oSettings.iInitDisplayStart; } oSettings.iInitDisplayStart = -1; _fnCalculateEnd( oSettings ); } /* Server-side processing draw intercept */ if ( oSettings.bDeferLoading ) { oSettings.bDeferLoading = false; oSettings.iDraw++; } else if ( !oSettings.oFeatures.bServerSide ) { oSettings.iDraw++; } else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) ) { return; } if ( oSettings.aiDisplay.length !== 0 ) { var iStart = oSettings._iDisplayStart; var iEnd = oSettings._iDisplayEnd; if ( oSettings.oFeatures.bServerSide ) { iStart = 0; iEnd = oSettings.aoData.length; } for ( var j=iStart ; j<iEnd ; j++ ) { var aoData = oSettings.aoData[ oSettings.aiDisplay[j] ]; if ( aoData.nTr === null ) { _fnCreateTr( oSettings, oSettings.aiDisplay[j] ); } var nRow = aoData.nTr; /* Remove the old striping classes and then add the new one */ if ( iStripes !== 0 ) { var sStripe = oSettings.asStripeClasses[ iRowCount % iStripes ]; if ( aoData._sRowStripe != sStripe ) { $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe ); aoData._sRowStripe = sStripe; } } /* Row callback functions - might want to manipulate the row */ _fnCallbackFire( oSettings, 'aoRowCallback', null, [nRow, oSettings.aoData[ oSettings.aiDisplay[j] ]._aData, iRowCount, j] ); anRows.push( nRow ); iRowCount++; /* If there is an open row - and it is attached to this parent - attach it on redraw */ if ( iOpenRows !== 0 ) { for ( var k=0 ; k<iOpenRows ; k++ ) { if ( nRow == oSettings.aoOpenRows[k].nParent ) { anRows.push( oSettings.aoOpenRows[k].nTr ); break; } } } } } else { /* Table is empty - create a row with an empty message in it */ anRows[ 0 ] = document.createElement( 'tr' ); if ( oSettings.asStripeClasses[0] ) { anRows[ 0 ].className = oSettings.asStripeClasses[0]; } var oLang = oSettings.oLanguage; var sZero = oLang.sZeroRecords; if ( oSettings.iDraw == 1 && oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide ) { sZero = oLang.sLoadingRecords; } else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 ) { sZero = oLang.sEmptyTable; } var nTd = document.createElement( 'td' ); nTd.setAttribute( 'valign', "top" ); nTd.colSpan = _fnVisbleColumns( oSettings ); nTd.className = oSettings.oClasses.sRowEmpty; nTd.innerHTML = _fnInfoMacros( oSettings, sZero ); anRows[ iRowCount ].appendChild( nTd ); } /* Header and footer callbacks */ _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0], _fnGetDataMaster( oSettings ), oSettings._iDisplayStart, oSettings.fnDisplayEnd(), oSettings.aiDisplay ] ); _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0], _fnGetDataMaster( oSettings ), oSettings._iDisplayStart, oSettings.fnDisplayEnd(), oSettings.aiDisplay ] ); /* * Need to remove any old row from the display - note we can't just empty the tbody using * $().html('') since this will unbind the jQuery event handlers (even although the node * still exists!) - equally we can't use innerHTML, since IE throws an exception. */ var nAddFrag = document.createDocumentFragment(), nRemoveFrag = document.createDocumentFragment(), nBodyPar, nTrs; if ( oSettings.nTBody ) { nBodyPar = oSettings.nTBody.parentNode; nRemoveFrag.appendChild( oSettings.nTBody ); /* When doing infinite scrolling, only remove child rows when sorting, filtering or start * up. When not infinite scroll, always do it. */ if ( !oSettings.oScroll.bInfinite || !oSettings._bInitComplete || oSettings.bSorted || oSettings.bFiltered ) { while( (n = oSettings.nTBody.firstChild) ) { oSettings.nTBody.removeChild( n ); } } /* Put the draw table into the dom */ for ( i=0, iLen=anRows.length ; i<iLen ; i++ ) { nAddFrag.appendChild( anRows[i] ); } oSettings.nTBody.appendChild( nAddFrag ); if ( nBodyPar !== null ) { nBodyPar.appendChild( oSettings.nTBody ); } } /* Call all required callback functions for the end of a draw */ _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] ); /* Draw is complete, sorting and filtering must be as well */ oSettings.bSorted = false; oSettings.bFiltered = false; oSettings.bDrawing = false; if ( oSettings.oFeatures.bServerSide ) { _fnProcessingDisplay( oSettings, false ); if ( !oSettings._bInitComplete ) { _fnInitComplete( oSettings ); } } } /** * Redraw the table - taking account of the various features which are enabled * @param {object} oSettings dataTables settings object * @memberof DataTable#oApi */ function _fnReDraw( oSettings ) { if ( oSettings.oFeatures.bSort ) { /* Sorting will refilter and draw for us */ _fnSort( oSettings, oSettings.oPreviousSearch ); } else if ( oSettings.oFeatures.bFilter ) { /* Filtering will redraw for us */ _fnFilterComplete( oSettings, oSettings.oPreviousSearch ); } else { _fnCalculateEnd( oSettings ); _fnDraw( oSettings ); } } /** * Add the options to the page HTML for the table * @param {object} oSettings dataTables settings object * @memberof DataTable#oApi */ function _fnAddOptionsHtml ( oSettings ) { /* * Create a temporary, empty, div which we can later on replace with what we have generated * we do it this way to rendering the 'options' html offline - speed :-) */ var nHolding = $('<div></div>')[0]; oSettings.nTable.parentNode.insertBefore( nHolding, oSettings.nTable ); /* * All DataTables are wrapped in a div */ oSettings.nTableWrapper = $('<div id="'+oSettings.sTableId+'_wrapper" class="'+oSettings.oClasses.sWrapper+'" role="grid"></div>')[0]; oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling; /* Track where we want to insert the option */ var nInsertNode = oSettings.nTableWrapper; /* Loop over the user set positioning and place the elements as needed */ var aDom = oSettings.sDom.split(''); var nTmp, iPushFeature, cOption, nNewNode, cNext, sAttr, j; for ( var i=0 ; i<aDom.length ; i++ ) { iPushFeature = 0; cOption = aDom[i]; if ( cOption == '<' ) { /* New container div */ nNewNode = $('<div></div>')[0]; /* Check to see if we should append an id and/or a class name to the container */ cNext = aDom[i+1]; if ( cNext == "'" || cNext == '"' ) { sAttr = ""; j = 2; while ( aDom[i+j] != cNext ) { sAttr += aDom[i+j]; j++; } /* Replace jQuery UI constants */ if ( sAttr == "H" ) { sAttr = oSettings.oClasses.sJUIHeader; } else if ( sAttr == "F" ) { sAttr = oSettings.oClasses.sJUIFooter; } /* The attribute can be in the format of "#id.class", "#id" or "class" This logic * breaks the string into parts and applies them as needed */ if ( sAttr.indexOf('.') != -1 ) { var aSplit = sAttr.split('.'); nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1); nNewNode.className = aSplit[1]; } else if ( sAttr.charAt(0) == "#" ) { nNewNode.id = sAttr.substr(1, sAttr.length-1); } else { nNewNode.className = sAttr; } i += j; /* Move along the position array */ } nInsertNode.appendChild( nNewNode ); nInsertNode = nNewNode; } else if ( cOption == '>' ) { /* End container div */ nInsertNode = nInsertNode.parentNode; } else if ( cOption == 'l' && oSettings.oFeatures.bPaginate && oSettings.oFeatures.bLengthChange ) { /* Length */ nTmp = _fnFeatureHtmlLength( oSettings ); iPushFeature = 1; } else if ( cOption == 'f' && oSettings.oFeatures.bFilter ) { /* Filter */ nTmp = _fnFeatureHtmlFilter( oSettings ); iPushFeature = 1; } else if ( cOption == 'r' && oSettings.oFeatures.bProcessing ) { /* pRocessing */ nTmp = _fnFeatureHtmlProcessing( oSettings ); iPushFeature = 1; } else if ( cOption == 't' ) { /* Table */ nTmp = _fnFeatureHtmlTable( oSettings ); iPushFeature = 1; } else if ( cOption == 'i' && oSettings.oFeatures.bInfo ) { /* Info */ nTmp = _fnFeatureHtmlInfo( oSettings ); iPushFeature = 1; } else if ( cOption == 'p' && oSettings.oFeatures.bPaginate ) { /* Pagination */ nTmp = _fnFeatureHtmlPaginate( oSettings ); iPushFeature = 1; } else if ( DataTable.ext.aoFeatures.length !== 0 ) { /* Plug-in features */ var aoFeatures = DataTable.ext.aoFeatures; for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ ) { if ( cOption == aoFeatures[k].cFeature ) { nTmp = aoFeatures[k].fnInit( oSettings ); if ( nTmp ) { iPushFeature = 1; } break; } } } /* Add to the 2D features array */ if ( iPushFeature == 1 && nTmp !== null ) { if ( typeof oSettings.aanFeatures[cOption] !== 'object' ) { oSettings.aanFeatures[cOption] = []; } oSettings.aanFeatures[cOption].push( nTmp ); nInsertNode.appendChild( nTmp ); } } /* Built our DOM structure - replace the holding div with what we want */ nHolding.parentNode.replaceChild( oSettings.nTableWrapper, nHolding ); } /** * Use the DOM source to create up an array of header cells. The idea here is to * create a layout grid (array) of rows x columns, which contains a reference * to the cell that that point in the grid (regardless of col/rowspan), such that * any column / row could be removed and the new grid constructed * @param array {object} aLayout Array to store the calculated layout in * @param {node} nThead The header/footer element for the table * @memberof DataTable#oApi */ function _fnDetectHeader ( aLayout, nThead ) { var nTrs = $(nThead).children('tr'); var nTr, nCell; var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan; var bUnique; var fnShiftCol = function ( a, i, j ) { var k = a[i]; while ( k[j] ) { j++; } return j; }; aLayout.splice( 0, aLayout.length ); /* We know how many rows there are in the layout - so prep it */ for ( i=0, iLen=nTrs.length ; i<iLen ; i++ ) { aLayout.push( [] ); } /* Calculate a layout array */ for ( i=0, iLen=nTrs.length ; i<iLen ; i++ ) { nTr = nTrs[i]; iColumn = 0; /* For every cell in the row... */ nCell = nTr.firstChild; while ( nCell ) { if ( nCell.nodeName.toUpperCase() == "TD" || nCell.nodeName.toUpperCase() == "TH" ) { /* Get the col and rowspan attributes from the DOM and sanitise them */ iColspan = nCell.getAttribute('colspan') * 1; iRowspan = nCell.getAttribute('rowspan') * 1; iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan; iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan; /* There might be colspan cells already in this row, so shift our target * accordingly */ iColShifted = fnShiftCol( aLayout, i, iColumn ); /* Cache calculation for unique columns */ bUnique = iColspan === 1 ? true : false; /* If there is col / rowspan, copy the information into the layout grid */ for ( l=0 ; l<iColspan ; l++ ) { for ( k=0 ; k<iRowspan ; k++ ) { aLayout[i+k][iColShifted+l] = { "cell": nCell, "unique": bUnique }; aLayout[i+k].nTr = nTr; } } } nCell = nCell.nextSibling; } } } /** * Get an array of unique th elements, one for each column * @param {object} oSettings dataTables settings object * @param {node} nHeader automatically detect the layout from this node - optional * @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional * @returns array {node} aReturn list of unique th's * @memberof DataTable#oApi */ function _fnGetUniqueThs ( oSettings, nHeader, aLayout ) { var aReturn = []; if ( !aLayout ) { aLayout = oSettings.aoHeader; if ( nHeader ) { aLayout = []; _fnDetectHeader( aLayout, nHeader ); } } for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ ) { for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ ) { if ( aLayout[i][j].unique && (!aReturn[j] || !oSettings.bSortCellsTop) ) { aReturn[j] = aLayout[i][j].cell; } } } return aReturn; } /** * Update the table using an Ajax call * @param {object} oSettings dataTables settings object * @returns {boolean} Block the table drawing or not * @memberof DataTable#oApi */ function _fnAjaxUpdate( oSettings ) { if ( oSettings.bAjaxDataGet ) { oSettings.iDraw++; _fnProcessingDisplay( oSettings, true ); var iColumns = oSettings.aoColumns.length; var aoData = _fnAjaxParameters( oSettings ); _fnServerParams( oSettings, aoData ); oSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, aoData, function(json) { _fnAjaxUpdateDraw( oSettings, json ); }, oSettings ); return false; } else { return true; } } /** * Build up the parameters in an object needed for a server-side processing request * @param {object} oSettings dataTables settings object * @returns {bool} block the table drawing or not * @memberof DataTable#oApi */ function _fnAjaxParameters( oSettings ) { var iColumns = oSettings.aoColumns.length; var aoData = [], mDataProp, aaSort, aDataSort; var i, j; aoData.push( { "name": "sEcho", "value": oSettings.iDraw } ); aoData.push( { "name": "iColumns", "value": iColumns } ); aoData.push( { "name": "sColumns", "value": _fnColumnOrdering(oSettings) } ); aoData.push( { "name": "iDisplayStart", "value": oSettings._iDisplayStart } ); aoData.push( { "name": "iDisplayLength", "value": oSettings.oFeatures.bPaginate !== false ? oSettings._iDisplayLength : -1 } ); for ( i=0 ; i<iColumns ; i++ ) { mDataProp = oSettings.aoColumns[i].mData; aoData.push( { "name": "mDataProp_"+i, "value": typeof(mDataProp)==="function" ? 'function' : mDataProp } ); } /* Filtering */ if ( oSettings.oFeatures.bFilter !== false ) { aoData.push( { "name": "sSearch", "value": oSettings.oPreviousSearch.sSearch } ); aoData.push( { "name": "bRegex", "value": oSettings.oPreviousSearch.bRegex } ); for ( i=0 ; i<iColumns ; i++ ) { aoData.push( { "name": "sSearch_"+i, "value": oSettings.aoPreSearchCols[i].sSearch } ); aoData.push( { "name": "bRegex_"+i, "value": oSettings.aoPreSearchCols[i].bRegex } ); aoData.push( { "name": "bSearchable_"+i, "value": oSettings.aoColumns[i].bSearchable } ); } } /* Sorting */ if ( oSettings.oFeatures.bSort !== false ) { var iCounter = 0; aaSort = ( oSettings.aaSortingFixed !== null ) ? oSettings.aaSortingFixed.concat( oSettings.aaSorting ) : oSettings.aaSorting.slice(); for ( i=0 ; i<aaSort.length ; i++ ) { aDataSort = oSettings.aoColumns[ aaSort[i][0] ].aDataSort; for ( j=0 ; j<aDataSort.length ; j++ ) { aoData.push( { "name": "iSortCol_"+iCounter, "value": aDataSort[j] } ); aoData.push( { "name": "sSortDir_"+iCounter, "value": aaSort[i][1] } ); iCounter++; } } aoData.push( { "name": "iSortingCols", "value": iCounter } ); for ( i=0 ; i<iColumns ; i++ ) { aoData.push( { "name": "bSortable_"+i, "value": oSettings.aoColumns[i].bSortable } ); } } return aoData; } /** * Add Ajax parameters from plug-ins * @param {object} oSettings dataTables settings object * @param array {objects} aoData name/value pairs to send to the server * @memberof DataTable#oApi */ function _fnServerParams( oSettings, aoData ) { _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [aoData] ); } /** * Data the data from the server (nuking the old) and redraw the table * @param {object} oSettings dataTables settings object * @param {object} json json data return from the server. * @param {string} json.sEcho Tracking flag for DataTables to match requests * @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering * @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering * @param {array} json.aaData The data to display on this page * @param {string} [json.sColumns] Column ordering (sName, comma separated) * @memberof DataTable#oApi */ function _fnAjaxUpdateDraw ( oSettings, json ) { if ( json.sEcho !== undefined ) { /* Protect against old returns over-writing a new one. Possible when you get * very fast interaction, and later queries are completed much faster */ if ( json.sEcho*1 < oSettings.iDraw ) { return; } else { oSettings.iDraw = json.sEcho * 1; } } if ( !oSettings.oScroll.bInfinite || (oSettings.oScroll.bInfinite && (oSettings.bSorted || oSettings.bFiltered)) ) { _fnClearTable( oSettings ); } oSettings._iRecordsTotal = parseInt(json.iTotalRecords, 10); oSettings._iRecordsDisplay = parseInt(json.iTotalDisplayRecords, 10); /* Determine if reordering is required */ var sOrdering = _fnColumnOrdering(oSettings); var bReOrder = (json.sColumns !== undefined && sOrdering !== "" && json.sColumns != sOrdering ); var aiIndex; if ( bReOrder ) { aiIndex = _fnReOrderIndex( oSettings, json.sColumns ); } var aData = _fnGetObjectDataFn( oSettings.sAjaxDataProp )( json ); for ( var i=0, iLen=aData.length ; i<iLen ; i++ ) { if ( bReOrder ) { /* If we need to re-order, then create a new array with the correct order and add it */ var aDataSorted = []; for ( var j=0, jLen=oSettings.aoColumns.length ; j<jLen ; j++ ) { aDataSorted.push( aData[i][ aiIndex[j] ] ); } _fnAddData( oSettings, aDataSorted ); } else { /* No re-order required, sever got it "right" - just straight add */ _fnAddData( oSettings, aData[i] ); } } oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); oSettings.bAjaxDataGet = false; _fnDraw( oSettings ); oSettings.bAjaxDataGet = true; _fnProcessingDisplay( oSettings, false ); } /** * Generate the node required for filtering text * @returns {node} Filter control element * @param {object} oSettings dataTables settings object * @memberof DataTable#oApi */ function _fnFeatureHtmlFilter ( oSettings ) { var oPreviousSearch = oSettings.oPreviousSearch; var sSearchStr = oSettings.oLanguage.sSearch; sSearchStr = (sSearchStr.indexOf('_INPUT_') !== -1) ? sSearchStr.replace('_INPUT_', '<input type="text" />') : sSearchStr==="" ? '<input type="text" />' : sSearchStr+' <input type="text" />'; var nFilter = document.createElement( 'div' ); nFilter.className = oSettings.oClasses.sFilter; nFilter.innerHTML = '<label>'+sSearchStr+'</label>'; if ( !oSettings.aanFeatures.f ) { nFilter.id = oSettings.sTableId+'_filter'; } var jqFilter = $('input[type="text"]', nFilter); // Store a reference to the input element, so other input elements could be // added to the filter wrapper if needed (submit button for example) nFilter._DT_Input = jqFilter[0]; jqFilter.val( oPreviousSearch.sSearch.replace('"','"') ); jqFilter.bind( 'keyup.DT', function(e) { /* Update all other filter input elements for the new display */ var n = oSettings.aanFeatures.f; var val = this.value==="" ? "" : this.value; // mental IE8 fix :-( for ( var i=0, iLen=n.length ; i<iLen ; i++ ) { if ( n[i] != $(this).parents('div.dataTables_filter')[0] ) { $(n[i]._DT_Input).val( val ); } } /* Now do the filter */ if ( val != oPreviousSearch.sSearch ) { _fnFilterComplete( oSettings, { "sSearch": val, "bRegex": oPreviousSearch.bRegex, "bSmart": oPreviousSearch.bSmart , "bCaseInsensitive": oPreviousSearch.bCaseInsensitive } ); } } ); jqFilter .attr('aria-controls', oSettings.sTableId) .bind( 'keypress.DT', function(e) { /* Prevent form submission */ if ( e.keyCode == 13 ) { return false; } } ); return nFilter; } /** * Filter the table using both the global filter and column based filtering * @param {object} oSettings dataTables settings object * @param {object} oSearch search information * @param {int} [iForce] force a research of the master array (1) or not (undefined or 0) * @memberof DataTable#oApi */ function _fnFilterComplete ( oSettings, oInput, iForce ) { var oPrevSearch = oSettings.oPreviousSearch; var aoPrevSearch = oSettings.aoPreSearchCols; var fnSaveFilter = function ( oFilter ) { /* Save the filtering values */ oPrevSearch.sSearch = oFilter.sSearch; oPrevSearch.bRegex = oFilter.bRegex; oPrevSearch.bSmart = oFilter.bSmart; oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive; }; /* In server-side processing all filtering is done by the server, so no point hanging around here */ if ( !oSettings.oFeatures.bServerSide ) { /* Global filter */ _fnFilter( oSettings, oInput.sSearch, iForce, oInput.bRegex, oInput.bSmart, oInput.bCaseInsensitive ); fnSaveFilter( oInput ); /* Now do the individual column filter */ for ( var i=0 ; i<oSettings.aoPreSearchCols.length ; i++ ) { _fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, aoPrevSearch[i].bRegex, aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive ); } /* Custom filtering */ _fnFilterCustom( oSettings ); } else { fnSaveFilter( oInput ); } /* Tell the draw function we have been filtering */ oSettings.bFiltered = true; $(oSettings.oInstance).trigger('filter', oSettings); /* Redraw the table */ oSettings._iDisplayStart = 0; _fnCalculateEnd( oSettings ); _fnDraw( oSettings ); /* Rebuild search array 'offline' */ _fnBuildSearchArray( oSettings, 0 ); } /** * Apply custom filtering functions * @param {object} oSettings dataTables settings object * @memberof DataTable#oApi */ function _fnFilterCustom( oSettings ) { var afnFilters = DataTable.ext.afnFiltering; var aiFilterColumns = _fnGetColumns( oSettings, 'bSearchable' ); for ( var i=0, iLen=afnFilters.length ; i<iLen ; i++ ) { var iCorrector = 0; for ( var j=0, jLen=oSettings.aiDisplay.length ; j<jLen ; j++ ) { var iDisIndex = oSettings.aiDisplay[j-iCorrector]; var bTest = afnFilters[i]( oSettings, _fnGetRowData( oSettings, iDisIndex, 'filter', aiFilterColumns ), iDisIndex ); /* Check if we should use this row based on the filtering function */ if ( !bTest ) { oSettings.aiDisplay.splice( j-iCorrector, 1 ); iCorrector++; } } } } /** * Filter the table on a per-column basis * @param {object} oSettings dataTables settings object * @param {string} sInput string to filter on * @param {int} iColumn column to filter * @param {bool} bRegex treat search string as a regular expression or not * @param {bool} bSmart use smart filtering or not * @param {bool} bCaseInsensitive Do case insenstive matching or not * @memberof DataTable#oApi */ function _fnFilterColumn ( oSettings, sInput, iColumn, bRegex, bSmart, bCaseInsensitive ) { if ( sInput === "" ) { return; } var iIndexCorrector = 0; var rpSearch = _fnFilterCreateSearch( sInput, bRegex, bSmart, bCaseInsensitive ); for ( var i=oSettings.aiDisplay.length-1 ; i>=0 ; i-- ) { var sData = _fnDataToSearch( _fnGetCellData( oSettings, oSettings.aiDisplay[i], iColumn, 'filter' ), oSettings.aoColumns[iColumn].sType ); if ( ! rpSearch.test( sData ) ) { oSettings.aiDisplay.splice( i, 1 ); iIndexCorrector++; } } } /** * Filter the data table based on user input and draw the table * @param {object} oSettings dataTables settings object * @param {string} sInput string to filter on * @param {int} iForce optional - force a research of the master array (1) or not (undefined or 0) * @param {bool} bRegex treat as a regular expression or not * @param {bool} bSmart perform smart filtering or not * @param {bool} bCaseInsensitive Do case insenstive matching or not * @memberof DataTable#oApi */ function _fnFilter( oSettings, sInput, iForce, bRegex, bSmart, bCaseInsensitive ) { var i; var rpSearch = _fnFilterCreateSearch( sInput, bRegex, bSmart, bCaseInsensitive ); var oPrevSearch = oSettings.oPreviousSearch; /* Check if we are forcing or not - optional parameter */ if ( !iForce ) { iForce = 0; } /* Need to take account of custom filtering functions - always filter */ if ( DataTable.ext.afnFiltering.length !== 0 ) { iForce = 1; } /* * If the input is blank - we want the full data set */ if ( sInput.length <= 0 ) { oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length); oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); } else { /* * We are starting a new search or the new search string is smaller * then the old one (i.e. delete). Search from the master array */ if ( oSettings.aiDisplay.length == oSettings.aiDisplayMaster.length || oPrevSearch.sSearch.length > sInput.length || iForce == 1 || sInput.indexOf(oPrevSearch.sSearch) !== 0 ) { /* Nuke the old display array - we are going to rebuild it */ oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length); /* Force a rebuild of the search array */ _fnBuildSearchArray( oSettings, 1 ); /* Search through all records to populate the search array * The the oSettings.aiDisplayMaster and asDataSearch arrays have 1 to 1 * mapping */ for ( i=0 ; i<oSettings.aiDisplayMaster.length ; i++ ) { if ( rpSearch.test(oSettings.asDataSearch[i]) ) { oSettings.aiDisplay.push( oSettings.aiDisplayMaster[i] ); } } } else { /* Using old search array - refine it - do it this way for speed * Don't have to search the whole master array again */ var iIndexCorrector = 0; /* Search the current results */ for ( i=0 ; i<oSettings.asDataSearch.length ; i++ ) { if ( ! rpSearch.test(oSettings.asDataSearch[i]) ) { oSettings.aiDisplay.splice( i-iIndexCorrector, 1 ); iIndexCorrector++; } } } } } /** * Create an array which can be quickly search through * @param {object} oSettings dataTables settings object * @param {int} iMaster use the master data array - optional * @memberof DataTable#oApi */ function _fnBuildSearchArray ( oSettings, iMaster ) { if ( !oSettings.oFeatures.bServerSide ) { /* Clear out the old data */ oSettings.asDataSearch = []; var aiFilterColumns = _fnGetColumns( oSettings, 'bSearchable' ); var aiIndex = (iMaster===1) ? oSettings.aiDisplayMaster : oSettings.aiDisplay; for ( var i=0, iLen=aiIndex.length ; i<iLen ; i++ ) { oSettings.asDataSearch[i] = _fnBuildSearchRow( oSettings, _fnGetRowData( oSettings, aiIndex[i], 'filter', aiFilterColumns ) ); } } } /** * Create a searchable string from a single data row * @param {object} oSettings dataTables settings object * @param {array} aData Row data array to use for the data to search * @memberof DataTable#oApi */ function _fnBuildSearchRow( oSettings, aData ) { var sSearch = aData.join(' '); /* If it looks like there is an HTML entity in the string, attempt to decode it */ if ( sSearch.indexOf('&') !== -1 ) { sSearch = $('<div>').html(sSearch).text(); } // Strip newline characters return sSearch.replace( /[\n\r]/g, " " ); } /** * Build a regular expression object suitable for searching a table * @param {string} sSearch string to search for * @param {bool} bRegex treat as a regular expression or not * @param {bool} bSmart perform smart filtering or not * @param {bool} bCaseInsensitive Do case insensitive matching or not * @returns {RegExp} constructed object * @memberof DataTable#oApi */ function _fnFilterCreateSearch( sSearch, bRegex, bSmart, bCaseInsensitive ) { var asSearch, sRegExpString; if ( bSmart ) { /* Generate the regular expression to use. Something along the lines of: * ^(?=.*?\bone\b)(?=.*?\btwo\b)(?=.*?\bthree\b).*$ */ asSearch = bRegex ? sSearch.split( ' ' ) : _fnEscapeRegex( sSearch ).split( ' ' ); sRegExpString = '^(?=.*?'+asSearch.join( ')(?=.*?' )+').*$'; return new RegExp( sRegExpString, bCaseInsensitive ? "i" : "" ); } else { sSearch = bRegex ? sSearch : _fnEscapeRegex( sSearch ); return new RegExp( sSearch, bCaseInsensitive ? "i" : "" ); } } /** * Convert raw data into something that the user can search on * @param {string} sData data to be modified * @param {string} sType data type * @returns {string} search string * @memberof DataTable#oApi */ function _fnDataToSearch ( sData, sType ) { if ( typeof DataTable.ext.ofnSearch[sType] === "function" ) { return DataTable.ext.ofnSearch[sType]( sData ); } else if ( sData === null ) { return ''; } else if ( sType == "html" ) { return sData.replace(/[\r\n]/g," ").replace( /<.*?>/g, "" ); } else if ( typeof sData === "string" ) { return sData.replace(/[\r\n]/g," "); } return sData; } /** * scape a string such that it can be used in a regular expression * @param {string} sVal string to escape * @returns {string} escaped string * @memberof DataTable#oApi */ function _fnEscapeRegex ( sVal ) { var acEscape = [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ]; var reReplace = new RegExp( '(\\' + acEscape.join('|\\') + ')', 'g' ); return sVal.replace(reReplace, '\\$1'); } /** * Generate the node required for the info display * @param {object} oSettings dataTables settings object * @returns {node} Information element * @memberof DataTable#oApi */ function _fnFeatureHtmlInfo ( oSettings ) { var nInfo = document.createElement( 'div' ); nInfo.className = oSettings.oClasses.sInfo; /* Actions that are to be taken once only for this feature */ if ( !oSettings.aanFeatures.i ) { /* Add draw callback */ oSettings.aoDrawCallback.push( { "fn": _fnUpdateInfo, "sName": "information" } ); /* Add id */ nInfo.id = oSettings.sTableId+'_info'; } oSettings.nTable.setAttribute( 'aria-describedby', oSettings.sTableId+'_info' ); return nInfo; } /** * Update the information elements in the display * @param {object} oSettings dataTables settings object * @memberof DataTable#oApi */ function _fnUpdateInfo ( oSettings ) { /* Show information about the table */ if ( !oSettings.oFeatures.bInfo || oSettings.aanFeatures.i.length === 0 ) { return; } var oLang = oSettings.oLanguage, iStart = oSettings._iDisplayStart+1, iEnd = oSettings.fnDisplayEnd(), iMax = oSettings.fnRecordsTotal(), iTotal = oSettings.fnRecordsDisplay(), sOut; if ( iTotal === 0 ) { /* Empty record set */ sOut = oLang.sInfoEmpty; } else { /* Normal record set */ sOut = oLang.sInfo; } if ( iTotal != iMax ) { /* Record set after filtering */ sOut += ' ' + oLang.sInfoFiltered; } // Convert the macros sOut += oLang.sInfoPostFix; sOut = _fnInfoMacros( oSettings, sOut ); if ( oLang.fnInfoCallback !== null ) { sOut = oLang.fnInfoCallback.call( oSettings.oInstance, oSettings, iStart, iEnd, iMax, iTotal, sOut ); } var n = oSettings.aanFeatures.i; for ( var i=0, iLen=n.length ; i<iLen ; i++ ) { $(n[i]).html( sOut ); } } function _fnInfoMacros ( oSettings, str ) { var iStart = oSettings._iDisplayStart+1, sStart = oSettings.fnFormatNumber( iStart ), iEnd = oSettings.fnDisplayEnd(), sEnd = oSettings.fnFormatNumber( iEnd ), iTotal = oSettings.fnRecordsDisplay(), sTotal = oSettings.fnFormatNumber( iTotal ), iMax = oSettings.fnRecordsTotal(), sMax = oSettings.fnFormatNumber( iMax ); // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only // internally if ( oSettings.oScroll.bInfinite ) { sStart = oSettings.fnFormatNumber( 1 ); } return str. replace(/_START_/g, sStart). replace(/_END_/g, sEnd). replace(/_TOTAL_/g, sTotal). replace(/_MAX_/g, sMax); } /** * Draw the table for the first time, adding all required features * @param {object} oSettings dataTables settings object * @memberof DataTable#oApi */ function _fnInitialise ( oSettings ) { var i, iLen, iAjaxStart=oSettings.iInitDisplayStart; /* Ensure that the table data is fully initialised */ if ( oSettings.bInitialised === false ) { setTimeout( function(){ _fnInitialise( oSettings ); }, 200 ); return; } /* Show the display HTML options */ _fnAddOptionsHtml( oSettings ); /* Build and draw the header / footer for the table */ _fnBuildHead( oSettings ); _fnDrawHead( oSettings, oSettings.aoHeader ); if ( oSettings.nTFoot ) { _fnDrawHead( oSettings, oSettings.aoFooter ); } /* Okay to show that something is going on now */ _fnProcessingDisplay( oSettings, true ); /* Calculate sizes for columns */ if ( oSettings.oFeatures.bAutoWidth ) { _fnCalculateColumnWidths( oSettings ); } for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) { if ( oSettings.aoColumns[i].sWidth !== null ) { oSettings.aoColumns[i].nTh.style.width = _fnStringToCss( oSettings.aoColumns[i].sWidth ); } } /* If there is default sorting required - let's do it. The sort function will do the * drawing for us. Otherwise we draw the table regardless of the Ajax source - this allows * the table to look initialised for Ajax sourcing data (show 'loading' message possibly) */ if ( oSettings.oFeatures.bSort ) { _fnSort( oSettings ); } else if ( oSettings.oFeatures.bFilter ) { _fnFilterComplete( oSettings, oSettings.oPreviousSearch ); } else { oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); _fnCalculateEnd( oSettings ); _fnDraw( oSettings ); } /* if there is an ajax source load the data */ if ( oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide ) { var aoData = []; _fnServerParams( oSettings, aoData ); oSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, aoData, function(json) { var aData = (oSettings.sAjaxDataProp !== "") ? _fnGetObjectDataFn( oSettings.sAjaxDataProp )(json) : json; /* Got the data - add it to the table */ for ( i=0 ; i<aData.length ; i++ ) { _fnAddData( oSettings, aData[i] ); } /* Reset the init display for cookie saving. We've already done a filter, and * therefore cleared it before. So we need to make it appear 'fresh' */ oSettings.iInitDisplayStart = iAjaxStart; if ( oSettings.oFeatures.bSort ) { _fnSort( oSettings ); } else { oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); _fnCalculateEnd( oSettings ); _fnDraw( oSettings ); } _fnProcessingDisplay( oSettings, false ); _fnInitComplete( oSettings, json ); }, oSettings ); return; } /* Server-side processing initialisation complete is done at the end of _fnDraw */ if ( !oSettings.oFeatures.bServerSide ) { _fnProcessingDisplay( oSettings, false ); _fnInitComplete( oSettings ); } } /** * Draw the table for the first time, adding all required features * @param {object} oSettings dataTables settings object * @param {object} [json] JSON from the server that completed the table, if using Ajax source * with client-side processing (optional) * @memberof DataTable#oApi */ function _fnInitComplete ( oSettings, json ) { oSettings._bInitComplete = true; _fnCallbackFire( oSettings, 'aoInitComplete', 'init', [oSettings, json] ); } /** * Language compatibility - when certain options are given, and others aren't, we * need to duplicate the values over, in order to provide backwards compatibility * with older language files. * @param {object} oSettings dataTables settings object * @memberof DataTable#oApi */ function _fnLanguageCompat( oLanguage ) { var oDefaults = DataTable.defaults.oLanguage; /* Backwards compatibility - if there is no sEmptyTable given, then use the same as * sZeroRecords - assuming that is given. */ if ( !oLanguage.sEmptyTable && oLanguage.sZeroRecords && oDefaults.sEmptyTable === "No data available in table" ) { _fnMap( oLanguage, oLanguage, 'sZeroRecords', 'sEmptyTable' ); } /* Likewise with loading records */ if ( !oLanguage.sLoadingRecords && oLanguage.sZeroRecords && oDefaults.sLoadingRecords === "Loading..." ) { _fnMap( oLanguage, oLanguage, 'sZeroRecords', 'sLoadingRecords' ); } } /** * Generate the node required for user display length changing * @param {object} oSettings dataTables settings object * @returns {node} Display length feature node * @memberof DataTable#oApi */ function _fnFeatureHtmlLength ( oSettings ) { if ( oSettings.oScroll.bInfinite ) { return null; } /* This can be overruled by not using the _MENU_ var/macro in the language variable */ var sName = 'name="'+oSettings.sTableId+'_length"'; var sStdMenu = '<select size="1" '+sName+'>'; var i, iLen; var aLengthMenu = oSettings.aLengthMenu; if ( aLengthMenu.length == 2 && typeof aLengthMenu[0] === 'object' && typeof aLengthMenu[1] === 'object' ) { for ( i=0, iLen=aLengthMenu[0].length ; i<iLen ; i++ ) { sStdMenu += '<option value="'+aLengthMenu[0][i]+'">'+aLengthMenu[1][i]+'</option>'; } } else { for ( i=0, iLen=aLengthMenu.length ; i<iLen ; i++ ) { sStdMenu += '<option value="'+aLengthMenu[i]+'">'+aLengthMenu[i]+'</option>'; } } sStdMenu += '</select>'; var nLength = document.createElement( 'div' ); if ( !oSettings.aanFeatures.l ) { nLength.id = oSettings.sTableId+'_length'; } nLength.className = oSettings.oClasses.sLength; nLength.innerHTML = '<label>'+oSettings.oLanguage.sLengthMenu.replace( '_MENU_', sStdMenu )+'</label>'; /* * Set the length to the current display length - thanks to Andrea Pavlovic for this fix, * and Stefan Skopnik for fixing the fix! */ $('select option[value="'+oSettings._iDisplayLength+'"]', nLength).attr("selected", true); $('select', nLength).bind( 'change.DT', function(e) { var iVal = $(this).val(); /* Update all other length options for the new display */ var n = oSettings.aanFeatures.l; for ( i=0, iLen=n.length ; i<iLen ; i++ ) { if ( n[i] != this.parentNode ) { $('select', n[i]).val( iVal ); } } /* Redraw the table */ oSettings._iDisplayLength = parseInt(iVal, 10); _fnCalculateEnd( oSettings ); /* If we have space to show extra rows (backing up from the end point - then do so */ if ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) { oSettings._iDisplayStart = oSettings.fnDisplayEnd() - oSettings._iDisplayLength; if ( oSettings._iDisplayStart < 0 ) { oSettings._iDisplayStart = 0; } } if ( oSettings._iDisplayLength == -1 ) { oSettings._iDisplayStart = 0; } _fnDraw( oSettings ); } ); $('select', nLength).attr('aria-controls', oSettings.sTableId); return nLength; } /** * Recalculate the end point based on the start point * @param {object} oSettings dataTables settings object * @memberof DataTable#oApi */ function _fnCalculateEnd( oSettings ) { if ( oSettings.oFeatures.bPaginate === false ) { oSettings._iDisplayEnd = oSettings.aiDisplay.length; } else { /* Set the end point of the display - based on how many elements there are * still to display */ if ( oSettings._iDisplayStart + oSettings._iDisplayLength > oSettings.aiDisplay.length || oSettings._iDisplayLength == -1 ) { oSettings._iDisplayEnd = oSettings.aiDisplay.length; } else { oSettings._iDisplayEnd = oSettings._iDisplayStart + oSettings._iDisplayLength; } } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Note that most of the paging logic is done in * DataTable.ext.oPagination */ /** * Generate the node required for default pagination * @param {object} oSettings dataTables settings object * @returns {node} Pagination feature node * @memberof DataTable#oApi */ function _fnFeatureHtmlPaginate ( oSettings ) { if ( oSettings.oScroll.bInfinite ) { return null; } var nPaginate = document.createElement( 'div' ); nPaginate.className = oSettings.oClasses.sPaging+oSettings.sPaginationType; DataTable.ext.oPagination[ oSettings.sPaginationType ].fnInit( oSettings, nPaginate, function( oSettings ) { _fnCalculateEnd( oSettings ); _fnDraw( oSettings ); } ); /* Add a draw callback for the pagination on first instance, to update the paging display */ if ( !oSettings.aanFeatures.p ) { oSettings.aoDrawCallback.push( { "fn": function( oSettings ) { DataTable.ext.oPagination[ oSettings.sPaginationType ].fnUpdate( oSettings, function( oSettings ) { _fnCalculateEnd( oSettings ); _fnDraw( oSettings ); } ); }, "sName": "pagination" } ); } return nPaginate; } /** * Alter the display settings to change the page * @param {object} oSettings dataTables settings object * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last" * or page number to jump to (integer) * @returns {bool} true page has changed, false - no change (no effect) eg 'first' on page 1 * @memberof DataTable#oApi */ function _fnPageChange ( oSettings, mAction ) { var iOldStart = oSettings._iDisplayStart; if ( typeof mAction === "number" ) { oSettings._iDisplayStart = mAction * oSettings._iDisplayLength; if ( oSettings._iDisplayStart > oSettings.fnRecordsDisplay() ) { oSettings._iDisplayStart = 0; } } else if ( mAction == "first" ) { oSettings._iDisplayStart = 0; } else if ( mAction == "previous" ) { oSettings._iDisplayStart = oSettings._iDisplayLength>=0 ? oSettings._iDisplayStart - oSettings._iDisplayLength : 0; /* Correct for under-run */ if ( oSettings._iDisplayStart < 0 ) { oSettings._iDisplayStart = 0; } } else if ( mAction == "next" ) { if ( oSettings._iDisplayLength >= 0 ) { /* Make sure we are not over running the display array */ if ( oSettings._iDisplayStart + oSettings._iDisplayLength < oSettings.fnRecordsDisplay() ) { oSettings._iDisplayStart += oSettings._iDisplayLength; } } else { oSettings._iDisplayStart = 0; } } else if ( mAction == "last" ) { if ( oSettings._iDisplayLength >= 0 ) { var iPages = parseInt( (oSettings.fnRecordsDisplay()-1) / oSettings._iDisplayLength, 10 ) + 1; oSettings._iDisplayStart = (iPages-1) * oSettings._iDisplayLength; } else { oSettings._iDisplayStart = 0; } } else { _fnLog( oSettings, 0, "Unknown paging action: "+mAction ); } $(oSettings.oInstance).trigger('page', oSettings); return iOldStart != oSettings._iDisplayStart; } /** * Generate the node required for the processing node * @param {object} oSettings dataTables settings object * @returns {node} Processing element * @memberof DataTable#oApi */ function _fnFeatureHtmlProcessing ( oSettings ) { var nProcessing = document.createElement( 'div' ); if ( !oSettings.aanFeatures.r ) { nProcessing.id = oSettings.sTableId+'_processing'; } nProcessing.innerHTML = oSettings.oLanguage.sProcessing; nProcessing.className = oSettings.oClasses.sProcessing; oSettings.nTable.parentNode.insertBefore( nProcessing, oSettings.nTable ); return nProcessing; } /** * Display or hide the processing indicator * @param {object} oSettings dataTables settings object * @param {bool} bShow Show the processing indicator (true) or not (false) * @memberof DataTable#oApi */ function _fnProcessingDisplay ( oSettings, bShow ) { if ( oSettings.oFeatures.bProcessing ) { var an = oSettings.aanFeatures.r; for ( var i=0, iLen=an.length ; i<iLen ; i++ ) { an[i].style.visibility = bShow ? "visible" : "hidden"; } } $(oSettings.oInstance).trigger('processing', [oSettings, bShow]); } /** * Add any control elements for the table - specifically scrolling * @param {object} oSettings dataTables settings object * @returns {node} Node to add to the DOM * @memberof DataTable#oApi */ function _fnFeatureHtmlTable ( oSettings ) { /* Check if scrolling is enabled or not - if not then leave the DOM unaltered */ if ( oSettings.oScroll.sX === "" && oSettings.oScroll.sY === "" ) { return oSettings.nTable; } /* * The HTML structure that we want to generate in this function is: * div - nScroller * div - nScrollHead * div - nScrollHeadInner * table - nScrollHeadTable * thead - nThead * div - nScrollBody * table - oSettings.nTable * thead - nTheadSize * tbody - nTbody * div - nScrollFoot * div - nScrollFootInner * table - nScrollFootTable * tfoot - nTfoot */ var nScroller = document.createElement('div'), nScrollHead = document.createElement('div'), nScrollHeadInner = document.createElement('div'), nScrollBody = document.createElement('div'), nScrollFoot = document.createElement('div'), nScrollFootInner = document.createElement('div'), nScrollHeadTable = oSettings.nTable.cloneNode(false), nScrollFootTable = oSettings.nTable.cloneNode(false), nThead = oSettings.nTable.getElementsByTagName('thead')[0], nTfoot = oSettings.nTable.getElementsByTagName('tfoot').length === 0 ? null : oSettings.nTable.getElementsByTagName('tfoot')[0], oClasses = oSettings.oClasses; nScrollHead.appendChild( nScrollHeadInner ); nScrollFoot.appendChild( nScrollFootInner ); nScrollBody.appendChild( oSettings.nTable ); nScroller.appendChild( nScrollHead ); nScroller.appendChild( nScrollBody ); nScrollHeadInner.appendChild( nScrollHeadTable ); nScrollHeadTable.appendChild( nThead ); if ( nTfoot !== null ) { nScroller.appendChild( nScrollFoot ); nScrollFootInner.appendChild( nScrollFootTable ); nScrollFootTable.appendChild( nTfoot ); } nScroller.className = oClasses.sScrollWrapper; nScrollHead.className = oClasses.sScrollHead; nScrollHeadInner.className = oClasses.sScrollHeadInner; nScrollBody.className = oClasses.sScrollBody; nScrollFoot.className = oClasses.sScrollFoot; nScrollFootInner.className = oClasses.sScrollFootInner; if ( oSettings.oScroll.bAutoCss ) { nScrollHead.style.overflow = "hidden"; nScrollHead.style.position = "relative"; nScrollFoot.style.overflow = "hidden"; nScrollBody.style.overflow = "auto"; } nScrollHead.style.border = "0"; nScrollHead.style.width = "100%"; nScrollFoot.style.border = "0"; nScrollHeadInner.style.width = oSettings.oScroll.sXInner !== "" ? oSettings.oScroll.sXInner : "100%"; /* will be overwritten */ /* Modify attributes to respect the clones */ nScrollHeadTable.removeAttribute('id'); nScrollHeadTable.style.marginLeft = "0"; oSettings.nTable.style.marginLeft = "0"; if ( nTfoot !== null ) { nScrollFootTable.removeAttribute('id'); nScrollFootTable.style.marginLeft = "0"; } /* Move caption elements from the body to the header, footer or leave where it is * depending on the configuration. Note that the DTD says there can be only one caption */ var nCaption = $(oSettings.nTable).children('caption'); if ( nCaption.length > 0 ) { nCaption = nCaption[0]; if ( nCaption._captionSide === "top" ) { nScrollHeadTable.appendChild( nCaption ); } else if ( nCaption._captionSide === "bottom" && nTfoot ) { nScrollFootTable.appendChild( nCaption ); } } /* * Sizing */ /* When x-scrolling add the width and a scroller to move the header with the body */ if ( oSettings.oScroll.sX !== "" ) { nScrollHead.style.width = _fnStringToCss( oSettings.oScroll.sX ); nScrollBody.style.width = _fnStringToCss( oSettings.oScroll.sX ); if ( nTfoot !== null ) { nScrollFoot.style.width = _fnStringToCss( oSettings.oScroll.sX ); } /* When the body is scrolled, then we also want to scroll the headers */ $(nScrollBody).scroll( function (e) { nScrollHead.scrollLeft = this.scrollLeft; if ( nTfoot !== null ) { nScrollFoot.scrollLeft = this.scrollLeft; } } ); } /* When yscrolling, add the height */ if ( oSettings.oScroll.sY !== "" ) { nScrollBody.style.height = _fnStringToCss( oSettings.oScroll.sY ); } /* Redraw - align columns across the tables */ oSettings.aoDrawCallback.push( { "fn": _fnScrollDraw, "sName": "scrolling" } ); /* Infinite scrolling event handlers */ if ( oSettings.oScroll.bInfinite ) { $(nScrollBody).scroll( function() { /* Use a blocker to stop scrolling from loading more data while other data is still loading */ if ( !oSettings.bDrawing && $(this).scrollTop() !== 0 ) { /* Check if we should load the next data set */ if ( $(this).scrollTop() + $(this).height() > $(oSettings.nTable).height() - oSettings.oScroll.iLoadGap ) { /* Only do the redraw if we have to - we might be at the end of the data */ if ( oSettings.fnDisplayEnd() < oSettings.fnRecordsDisplay() ) { _fnPageChange( oSettings, 'next' ); _fnCalculateEnd( oSettings ); _fnDraw( oSettings ); } } } } ); } oSettings.nScrollHead = nScrollHead; oSettings.nScrollFoot = nScrollFoot; return nScroller; } /** * Update the various tables for resizing. It's a bit of a pig this function, but * basically the idea to: * 1. Re-create the table inside the scrolling div * 2. Take live measurements from the DOM * 3. Apply the measurements * 4. Clean up * @param {object} o dataTables settings object * @returns {node} Node to add to the DOM * @memberof DataTable#oApi */ function _fnScrollDraw ( o ) { var nScrollHeadInner = o.nScrollHead.getElementsByTagName('div')[0], nScrollHeadTable = nScrollHeadInner.getElementsByTagName('table')[0], nScrollBody = o.nTable.parentNode, i, iLen, j, jLen, anHeadToSize, anHeadSizers, anFootSizers, anFootToSize, oStyle, iVis, nTheadSize, nTfootSize, iWidth, aApplied=[], aAppliedFooter=[], iSanityWidth, nScrollFootInner = (o.nTFoot !== null) ? o.nScrollFoot.getElementsByTagName('div')[0] : null, nScrollFootTable = (o.nTFoot !== null) ? nScrollFootInner.getElementsByTagName('table')[0] : null, ie67 = o.oBrowser.bScrollOversize, zeroOut = function(nSizer) { oStyle = nSizer.style; oStyle.paddingTop = "0"; oStyle.paddingBottom = "0"; oStyle.borderTopWidth = "0"; oStyle.borderBottomWidth = "0"; oStyle.height = 0; }; /* * 1. Re-create the table inside the scrolling div */ /* Remove the old minimised thead and tfoot elements in the inner table */ $(o.nTable).children('thead, tfoot').remove(); /* Clone the current header and footer elements and then place it into the inner table */ nTheadSize = $(o.nTHead).clone()[0]; o.nTable.insertBefore( nTheadSize, o.nTable.childNodes[0] ); anHeadToSize = o.nTHead.getElementsByTagName('tr'); anHeadSizers = nTheadSize.getElementsByTagName('tr'); if ( o.nTFoot !== null ) { nTfootSize = $(o.nTFoot).clone()[0]; o.nTable.insertBefore( nTfootSize, o.nTable.childNodes[1] ); anFootToSize = o.nTFoot.getElementsByTagName('tr'); anFootSizers = nTfootSize.getElementsByTagName('tr'); } /* * 2. Take live measurements from the DOM - do not alter the DOM itself! */ /* Remove old sizing and apply the calculated column widths * Get the unique column headers in the newly created (cloned) header. We want to apply the * calculated sizes to this header */ if ( o.oScroll.sX === "" ) { nScrollBody.style.width = '100%'; nScrollHeadInner.parentNode.style.width = '100%'; } var nThs = _fnGetUniqueThs( o, nTheadSize ); for ( i=0, iLen=nThs.length ; i<iLen ; i++ ) { iVis = _fnVisibleToColumnIndex( o, i ); nThs[i].style.width = o.aoColumns[iVis].sWidth; } if ( o.nTFoot !== null ) { _fnApplyToChildren( function(n) { n.style.width = ""; }, anFootSizers ); } // If scroll collapse is enabled, when we put the headers back into the body for sizing, we // will end up forcing the scrollbar to appear, making our measurements wrong for when we // then hide it (end of this function), so add the header height to the body scroller. if ( o.oScroll.bCollapse && o.oScroll.sY !== "" ) { nScrollBody.style.height = (nScrollBody.offsetHeight + o.nTHead.offsetHeight)+"px"; } /* Size the table as a whole */ iSanityWidth = $(o.nTable).outerWidth(); if ( o.oScroll.sX === "" ) { /* No x scrolling */ o.nTable.style.width = "100%"; /* I know this is rubbish - but IE7 will make the width of the table when 100% include * the scrollbar - which is shouldn't. When there is a scrollbar we need to take this * into account. */ if ( ie67 && ($('tbody', nScrollBody).height() > nScrollBody.offsetHeight || $(nScrollBody).css('overflow-y') == "scroll") ) { o.nTable.style.width = _fnStringToCss( $(o.nTable).outerWidth() - o.oScroll.iBarWidth); } } else { if ( o.oScroll.sXInner !== "" ) { /* x scroll inner has been given - use it */ o.nTable.style.width = _fnStringToCss(o.oScroll.sXInner); } else if ( iSanityWidth == $(nScrollBody).width() && $(nScrollBody).height() < $(o.nTable).height() ) { /* There is y-scrolling - try to take account of the y scroll bar */ o.nTable.style.width = _fnStringToCss( iSanityWidth-o.oScroll.iBarWidth ); if ( $(o.nTable).outerWidth() > iSanityWidth-o.oScroll.iBarWidth ) { /* Not possible to take account of it */ o.nTable.style.width = _fnStringToCss( iSanityWidth ); } } else { /* All else fails */ o.nTable.style.width = _fnStringToCss( iSanityWidth ); } } /* Recalculate the sanity width - now that we've applied the required width, before it was * a temporary variable. This is required because the column width calculation is done * before this table DOM is created. */ iSanityWidth = $(o.nTable).outerWidth(); /* We want the hidden header to have zero height, so remove padding and borders. Then * set the width based on the real headers */ // Apply all styles in one pass. Invalidates layout only once because we don't read any // DOM properties. _fnApplyToChildren( zeroOut, anHeadSizers ); // Read all widths in next pass. Forces layout only once because we do not change // any DOM properties. _fnApplyToChildren( function(nSizer) { aApplied.push( _fnStringToCss( $(nSizer).width() ) ); }, anHeadSizers ); // Apply all widths in final pass. Invalidates layout only once because we do not // read any DOM properties. _fnApplyToChildren( function(nToSize, i) { nToSize.style.width = aApplied[i]; }, anHeadToSize ); $(anHeadSizers).height(0); /* Same again with the footer if we have one */ if ( o.nTFoot !== null ) { _fnApplyToChildren( zeroOut, anFootSizers ); _fnApplyToChildren( function(nSizer) { aAppliedFooter.push( _fnStringToCss( $(nSizer).width() ) ); }, anFootSizers ); _fnApplyToChildren( function(nToSize, i) { nToSize.style.width = aAppliedFooter[i]; }, anFootToSize ); $(anFootSizers).height(0); } /* * 3. Apply the measurements */ /* "Hide" the header and footer that we used for the sizing. We want to also fix their width * to what they currently are */ _fnApplyToChildren( function(nSizer, i) { nSizer.innerHTML = ""; nSizer.style.width = aApplied[i]; }, anHeadSizers ); if ( o.nTFoot !== null ) { _fnApplyToChildren( function(nSizer, i) { nSizer.innerHTML = ""; nSizer.style.width = aAppliedFooter[i]; }, anFootSizers ); } /* Sanity check that the table is of a sensible width. If not then we are going to get * misalignment - try to prevent this by not allowing the table to shrink below its min width */ if ( $(o.nTable).outerWidth() < iSanityWidth ) { /* The min width depends upon if we have a vertical scrollbar visible or not */ var iCorrection = ((nScrollBody.scrollHeight > nScrollBody.offsetHeight || $(nScrollBody).css('overflow-y') == "scroll")) ? iSanityWidth+o.oScroll.iBarWidth : iSanityWidth; /* IE6/7 are a law unto themselves... */ if ( ie67 && (nScrollBody.scrollHeight > nScrollBody.offsetHeight || $(nScrollBody).css('overflow-y') == "scroll") ) { o.nTable.style.width = _fnStringToCss( iCorrection-o.oScroll.iBarWidth ); } /* Apply the calculated minimum width to the table wrappers */ nScrollBody.style.width = _fnStringToCss( iCorrection ); o.nScrollHead.style.width = _fnStringToCss( iCorrection ); if ( o.nTFoot !== null ) { o.nScrollFoot.style.width = _fnStringToCss( iCorrection ); } /* And give the user a warning that we've stopped the table getting too small */ if ( o.oScroll.sX === "" ) { _fnLog( o, 1, "The table cannot fit into the current element which will cause column"+ " misalignment. The table has been drawn at its minimum possible width." ); } else if ( o.oScroll.sXInner !== "" ) { _fnLog( o, 1, "The table cannot fit into the current element which will cause column"+ " misalignment. Increase the sScrollXInner value or remove it to allow automatic"+ " calculation" ); } } else { nScrollBody.style.width = _fnStringToCss( '100%' ); o.nScrollHead.style.width = _fnStringToCss( '100%' ); if ( o.nTFoot !== null ) { o.nScrollFoot.style.width = _fnStringToCss( '100%' ); } } /* * 4. Clean up */ if ( o.oScroll.sY === "" ) { /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting * the scrollbar height from the visible display, rather than adding it on. We need to * set the height in order to sort this. Don't want to do it in any other browsers. */ if ( ie67 ) { nScrollBody.style.height = _fnStringToCss( o.nTable.offsetHeight+o.oScroll.iBarWidth ); } } if ( o.oScroll.sY !== "" && o.oScroll.bCollapse ) { nScrollBody.style.height = _fnStringToCss( o.oScroll.sY ); var iExtra = (o.oScroll.sX !== "" && o.nTable.offsetWidth > nScrollBody.offsetWidth) ? o.oScroll.iBarWidth : 0; if ( o.nTable.offsetHeight < nScrollBody.offsetHeight ) { nScrollBody.style.height = _fnStringToCss( o.nTable.offsetHeight+iExtra ); } } /* Finally set the width's of the header and footer tables */ var iOuterWidth = $(o.nTable).outerWidth(); nScrollHeadTable.style.width = _fnStringToCss( iOuterWidth ); nScrollHeadInner.style.width = _fnStringToCss( iOuterWidth ); // Figure out if there are scrollbar present - if so then we need a the header and footer to // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar) var bScrolling = $(o.nTable).height() > nScrollBody.clientHeight || $(nScrollBody).css('overflow-y') == "scroll"; nScrollHeadInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+"px" : "0px"; if ( o.nTFoot !== null ) { nScrollFootTable.style.width = _fnStringToCss( iOuterWidth ); nScrollFootInner.style.width = _fnStringToCss( iOuterWidth ); nScrollFootInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+"px" : "0px"; } /* Adjust the position of the header in case we loose the y-scrollbar */ $(nScrollBody).scroll(); /* If sorting or filtering has occurred, jump the scrolling back to the top */ if ( o.bSorted || o.bFiltered ) { nScrollBody.scrollTop = 0; } } /** * Apply a given function to the display child nodes of an element array (typically * TD children of TR rows * @param {function} fn Method to apply to the objects * @param array {nodes} an1 List of elements to look through for display children * @param array {nodes} an2 Another list (identical structure to the first) - optional * @memberof DataTable#oApi */ function _fnApplyToChildren( fn, an1, an2 ) { var index=0, i=0, iLen=an1.length; var nNode1, nNode2; while ( i < iLen ) { nNode1 = an1[i].firstChild; nNode2 = an2 ? an2[i].firstChild : null; while ( nNode1 ) { if ( nNode1.nodeType === 1 ) { if ( an2 ) { fn( nNode1, nNode2, index ); } else { fn( nNode1, index ); } index++; } nNode1 = nNode1.nextSibling; nNode2 = an2 ? nNode2.nextSibling : null; } i++; } } /** * Convert a CSS unit width to pixels (e.g. 2em) * @param {string} sWidth width to be converted * @param {node} nParent parent to get the with for (required for relative widths) - optional * @returns {int} iWidth width in pixels * @memberof DataTable#oApi */ function _fnConvertToWidth ( sWidth, nParent ) { if ( !sWidth || sWidth === null || sWidth === '' ) { return 0; } if ( !nParent ) { nParent = document.body; } var iWidth; var nTmp = document.createElement( "div" ); nTmp.style.width = _fnStringToCss( sWidth ); nParent.appendChild( nTmp ); iWidth = nTmp.offsetWidth; nParent.removeChild( nTmp ); return ( iWidth ); } /** * Calculate the width of columns for the table * @param {object} oSettings dataTables settings object * @memberof DataTable#oApi */ function _fnCalculateColumnWidths ( oSettings ) { var iTableWidth = oSettings.nTable.offsetWidth; var iUserInputs = 0; var iTmpWidth; var iVisibleColumns = 0; var iColums = oSettings.aoColumns.length; var i, iIndex, iCorrector, iWidth; var oHeaders = $('th', oSettings.nTHead); var widthAttr = oSettings.nTable.getAttribute('width'); var nWrapper = oSettings.nTable.parentNode; /* Convert any user input sizes into pixel sizes */ for ( i=0 ; i<iColums ; i++ ) { if ( oSettings.aoColumns[i].bVisible ) { iVisibleColumns++; if ( oSettings.aoColumns[i].sWidth !== null ) { iTmpWidth = _fnConvertToWidth( oSettings.aoColumns[i].sWidthOrig, nWrapper ); if ( iTmpWidth !== null ) { oSettings.aoColumns[i].sWidth = _fnStringToCss( iTmpWidth ); } iUserInputs++; } } } /* If the number of columns in the DOM equals the number that we have to process in * DataTables, then we can use the offsets that are created by the web-browser. No custom * sizes can be set in order for this to happen, nor scrolling used */ if ( iColums == oHeaders.length && iUserInputs === 0 && iVisibleColumns == iColums && oSettings.oScroll.sX === "" && oSettings.oScroll.sY === "" ) { for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) { iTmpWidth = $(oHeaders[i]).width(); if ( iTmpWidth !== null ) { oSettings.aoColumns[i].sWidth = _fnStringToCss( iTmpWidth ); } } } else { /* Otherwise we are going to have to do some calculations to get the width of each column. * Construct a 1 row table with the widest node in the data, and any user defined widths, * then insert it into the DOM and allow the browser to do all the hard work of * calculating table widths. */ var nCalcTmp = oSettings.nTable.cloneNode( false ), nTheadClone = oSettings.nTHead.cloneNode(true), nBody = document.createElement( 'tbody' ), nTr = document.createElement( 'tr' ), nDivSizing; nCalcTmp.removeAttribute( "id" ); nCalcTmp.appendChild( nTheadClone ); if ( oSettings.nTFoot !== null ) { nCalcTmp.appendChild( oSettings.nTFoot.cloneNode(true) ); _fnApplyToChildren( function(n) { n.style.width = ""; }, nCalcTmp.getElementsByTagName('tr') ); } nCalcTmp.appendChild( nBody ); nBody.appendChild( nTr ); /* Remove any sizing that was previously applied by the styles */ var jqColSizing = $('thead th', nCalcTmp); if ( jqColSizing.length === 0 ) { jqColSizing = $('tbody tr:eq(0)>td', nCalcTmp); } /* Apply custom sizing to the cloned header */ var nThs = _fnGetUniqueThs( oSettings, nTheadClone ); iCorrector = 0; for ( i=0 ; i<iColums ; i++ ) { var oColumn = oSettings.aoColumns[i]; if ( oColumn.bVisible && oColumn.sWidthOrig !== null && oColumn.sWidthOrig !== "" ) { nThs[i-iCorrector].style.width = _fnStringToCss( oColumn.sWidthOrig ); } else if ( oColumn.bVisible ) { nThs[i-iCorrector].style.width = ""; } else { iCorrector++; } } /* Find the biggest td for each column and put it into the table */ for ( i=0 ; i<iColums ; i++ ) { if ( oSettings.aoColumns[i].bVisible ) { var nTd = _fnGetWidestNode( oSettings, i ); if ( nTd !== null ) { nTd = nTd.cloneNode(true); if ( oSettings.aoColumns[i].sContentPadding !== "" ) { nTd.innerHTML += oSettings.aoColumns[i].sContentPadding; } nTr.appendChild( nTd ); } } } /* Build the table and 'display' it */ nWrapper.appendChild( nCalcTmp ); /* When scrolling (X or Y) we want to set the width of the table as appropriate. However, * when not scrolling leave the table width as it is. This results in slightly different, * but I think correct behaviour */ if ( oSettings.oScroll.sX !== "" && oSettings.oScroll.sXInner !== "" ) { nCalcTmp.style.width = _fnStringToCss(oSettings.oScroll.sXInner); } else if ( oSettings.oScroll.sX !== "" ) { nCalcTmp.style.width = ""; if ( $(nCalcTmp).width() < nWrapper.offsetWidth ) { nCalcTmp.style.width = _fnStringToCss( nWrapper.offsetWidth ); } } else if ( oSettings.oScroll.sY !== "" ) { nCalcTmp.style.width = _fnStringToCss( nWrapper.offsetWidth ); } else if ( widthAttr ) { nCalcTmp.style.width = _fnStringToCss( widthAttr ); } nCalcTmp.style.visibility = "hidden"; /* Scrolling considerations */ _fnScrollingWidthAdjust( oSettings, nCalcTmp ); /* Read the width's calculated by the browser and store them for use by the caller. We * first of all try to use the elements in the body, but it is possible that there are * no elements there, under which circumstances we use the header elements */ var oNodes = $("tbody tr:eq(0)", nCalcTmp).children(); if ( oNodes.length === 0 ) { oNodes = _fnGetUniqueThs( oSettings, $('thead', nCalcTmp)[0] ); } /* Browsers need a bit of a hand when a width is assigned to any columns when * x-scrolling as they tend to collapse the table to the min-width, even if * we sent the column widths. So we need to keep track of what the table width * should be by summing the user given values, and the automatic values */ if ( oSettings.oScroll.sX !== "" ) { var iTotal = 0; iCorrector = 0; for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) { if ( oSettings.aoColumns[i].bVisible ) { if ( oSettings.aoColumns[i].sWidthOrig === null ) { iTotal += $(oNodes[iCorrector]).outerWidth(); } else { iTotal += parseInt(oSettings.aoColumns[i].sWidth.replace('px',''), 10) + ($(oNodes[iCorrector]).outerWidth() - $(oNodes[iCorrector]).width()); } iCorrector++; } } nCalcTmp.style.width = _fnStringToCss( iTotal ); oSettings.nTable.style.width = _fnStringToCss( iTotal ); } iCorrector = 0; for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) { if ( oSettings.aoColumns[i].bVisible ) { iWidth = $(oNodes[iCorrector]).width(); if ( iWidth !== null && iWidth > 0 ) { oSettings.aoColumns[i].sWidth = _fnStringToCss( iWidth ); } iCorrector++; } } var cssWidth = $(nCalcTmp).css('width'); oSettings.nTable.style.width = (cssWidth.indexOf('%') !== -1) ? cssWidth : _fnStringToCss( $(nCalcTmp).outerWidth() ); nCalcTmp.parentNode.removeChild( nCalcTmp ); } if ( widthAttr ) { oSettings.nTable.style.width = _fnStringToCss( widthAttr ); } } /** * Adjust a table's width to take account of scrolling * @param {object} oSettings dataTables settings object * @param {node} n table node * @memberof DataTable#oApi */ function _fnScrollingWidthAdjust ( oSettings, n ) { if ( oSettings.oScroll.sX === "" && oSettings.oScroll.sY !== "" ) { /* When y-scrolling only, we want to remove the width of the scroll bar so the table * + scroll bar will fit into the area avaialble. */ var iOrigWidth = $(n).width(); n.style.width = _fnStringToCss( $(n).outerWidth()-oSettings.oScroll.iBarWidth ); } else if ( oSettings.oScroll.sX !== "" ) { /* When x-scrolling both ways, fix the table at it's current size, without adjusting */ n.style.width = _fnStringToCss( $(n).outerWidth() ); } } /** * Get the widest node * @param {object} oSettings dataTables settings object * @param {int} iCol column of interest * @returns {node} widest table node * @memberof DataTable#oApi */ function _fnGetWidestNode( oSettings, iCol ) { var iMaxIndex = _fnGetMaxLenString( oSettings, iCol ); if ( iMaxIndex < 0 ) { return null; } if ( oSettings.aoData[iMaxIndex].nTr === null ) { var n = document.createElement('td'); n.innerHTML = _fnGetCellData( oSettings, iMaxIndex, iCol, '' ); return n; } return _fnGetTdNodes(oSettings, iMaxIndex)[iCol]; } /** * Get the maximum strlen for each data column * @param {object} oSettings dataTables settings object * @param {int} iCol column of interest * @returns {string} max string length for each column * @memberof DataTable#oApi */ function _fnGetMaxLenString( oSettings, iCol ) { var iMax = -1; var iMaxIndex = -1; for ( var i=0 ; i<oSettings.aoData.length ; i++ ) { var s = _fnGetCellData( oSettings, i, iCol, 'display' )+""; s = s.replace( /<.*?>/g, "" ); if ( s.length > iMax ) { iMax = s.length; iMaxIndex = i; } } return iMaxIndex; } /** * Append a CSS unit (only if required) to a string * @param {array} aArray1 first array * @param {array} aArray2 second array * @returns {int} 0 if match, 1 if length is different, 2 if no match * @memberof DataTable#oApi */ function _fnStringToCss( s ) { if ( s === null ) { return "0px"; } if ( typeof s == 'number' ) { if ( s < 0 ) { return "0px"; } return s+"px"; } /* Check if the last character is not 0-9 */ var c = s.charCodeAt( s.length-1 ); if (c < 0x30 || c > 0x39) { return s; } return s+"px"; } /** * Get the width of a scroll bar in this browser being used * @returns {int} width in pixels * @memberof DataTable#oApi */ function _fnScrollBarWidth () { var inner = document.createElement('p'); var style = inner.style; style.width = "100%"; style.height = "200px"; style.padding = "0px"; var outer = document.createElement('div'); style = outer.style; style.position = "absolute"; style.top = "0px"; style.left = "0px"; style.visibility = "hidden"; style.width = "200px"; style.height = "150px"; style.padding = "0px"; style.overflow = "hidden"; outer.appendChild(inner); document.body.appendChild(outer); var w1 = inner.offsetWidth; outer.style.overflow = 'scroll'; var w2 = inner.offsetWidth; if ( w1 == w2 ) { w2 = outer.clientWidth; } document.body.removeChild(outer); return (w1 - w2); } /** * Change the order of the table * @param {object} oSettings dataTables settings object * @param {bool} bApplyClasses optional - should we apply classes or not * @memberof DataTable#oApi */ function _fnSort ( oSettings, bApplyClasses ) { var i, iLen, j, jLen, k, kLen, sDataType, nTh, aaSort = [], aiOrig = [], oSort = DataTable.ext.oSort, aoData = oSettings.aoData, aoColumns = oSettings.aoColumns, oAria = oSettings.oLanguage.oAria; /* No sorting required if server-side or no sorting array */ if ( !oSettings.oFeatures.bServerSide && (oSettings.aaSorting.length !== 0 || oSettings.aaSortingFixed !== null) ) { aaSort = ( oSettings.aaSortingFixed !== null ) ? oSettings.aaSortingFixed.concat( oSettings.aaSorting ) : oSettings.aaSorting.slice(); /* If there is a sorting data type, and a function belonging to it, then we need to * get the data from the developer's function and apply it for this column */ for ( i=0 ; i<aaSort.length ; i++ ) { var iColumn = aaSort[i][0]; var iVisColumn = _fnColumnIndexToVisible( oSettings, iColumn ); sDataType = oSettings.aoColumns[ iColumn ].sSortDataType; if ( DataTable.ext.afnSortData[sDataType] ) { var aData = DataTable.ext.afnSortData[sDataType].call( oSettings.oInstance, oSettings, iColumn, iVisColumn ); if ( aData.length === aoData.length ) { for ( j=0, jLen=aoData.length ; j<jLen ; j++ ) { _fnSetCellData( oSettings, j, iColumn, aData[j] ); } } else { _fnLog( oSettings, 0, "Returned data sort array (col "+iColumn+") is the wrong length" ); } } } /* Create a value - key array of the current row positions such that we can use their * current position during the sort, if values match, in order to perform stable sorting */ for ( i=0, iLen=oSettings.aiDisplayMaster.length ; i<iLen ; i++ ) { aiOrig[ oSettings.aiDisplayMaster[i] ] = i; } /* Build an internal data array which is specific to the sort, so we can get and prep * the data to be sorted only once, rather than needing to do it every time the sorting * function runs. This make the sorting function a very simple comparison */ var iSortLen = aaSort.length; var fnSortFormat, aDataSort; for ( i=0, iLen=aoData.length ; i<iLen ; i++ ) { for ( j=0 ; j<iSortLen ; j++ ) { aDataSort = aoColumns[ aaSort[j][0] ].aDataSort; for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ ) { sDataType = aoColumns[ aDataSort[k] ].sType; fnSortFormat = oSort[ (sDataType ? sDataType : 'string')+"-pre" ]; aoData[i]._aSortData[ aDataSort[k] ] = fnSortFormat ? fnSortFormat( _fnGetCellData( oSettings, i, aDataSort[k], 'sort' ) ) : _fnGetCellData( oSettings, i, aDataSort[k], 'sort' ); } } } /* Do the sort - here we want multi-column sorting based on a given data source (column) * and sorting function (from oSort) in a certain direction. It's reasonably complex to * follow on it's own, but this is what we want (example two column sorting): * fnLocalSorting = function(a,b){ * var iTest; * iTest = oSort['string-asc']('data11', 'data12'); * if (iTest !== 0) * return iTest; * iTest = oSort['numeric-desc']('data21', 'data22'); * if (iTest !== 0) * return iTest; * return oSort['numeric-asc']( aiOrig[a], aiOrig[b] ); * } * Basically we have a test for each sorting column, if the data in that column is equal, * test the next column. If all columns match, then we use a numeric sort on the row * positions in the original data array to provide a stable sort. */ oSettings.aiDisplayMaster.sort( function ( a, b ) { var k, l, lLen, iTest, aDataSort, sDataType; for ( k=0 ; k<iSortLen ; k++ ) { aDataSort = aoColumns[ aaSort[k][0] ].aDataSort; for ( l=0, lLen=aDataSort.length ; l<lLen ; l++ ) { sDataType = aoColumns[ aDataSort[l] ].sType; iTest = oSort[ (sDataType ? sDataType : 'string')+"-"+aaSort[k][1] ]( aoData[a]._aSortData[ aDataSort[l] ], aoData[b]._aSortData[ aDataSort[l] ] ); if ( iTest !== 0 ) { return iTest; } } } return oSort['numeric-asc']( aiOrig[a], aiOrig[b] ); } ); } /* Alter the sorting classes to take account of the changes */ if ( (bApplyClasses === undefined || bApplyClasses) && !oSettings.oFeatures.bDeferRender ) { _fnSortingClasses( oSettings ); } for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) { var sTitle = aoColumns[i].sTitle.replace( /<.*?>/g, "" ); nTh = aoColumns[i].nTh; nTh.removeAttribute('aria-sort'); nTh.removeAttribute('aria-label'); /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */ if ( aoColumns[i].bSortable ) { if ( aaSort.length > 0 && aaSort[0][0] == i ) { nTh.setAttribute('aria-sort', aaSort[0][1]=="asc" ? "ascending" : "descending" ); var nextSort = (aoColumns[i].asSorting[ aaSort[0][2]+1 ]) ? aoColumns[i].asSorting[ aaSort[0][2]+1 ] : aoColumns[i].asSorting[0]; nTh.setAttribute('aria-label', sTitle+ (nextSort=="asc" ? oAria.sSortAscending : oAria.sSortDescending) ); } else { nTh.setAttribute('aria-label', sTitle+ (aoColumns[i].asSorting[0]=="asc" ? oAria.sSortAscending : oAria.sSortDescending) ); } } else { nTh.setAttribute('aria-label', sTitle); } } /* Tell the draw function that we have sorted the data */ oSettings.bSorted = true; $(oSettings.oInstance).trigger('sort', oSettings); /* Copy the master data into the draw array and re-draw */ if ( oSettings.oFeatures.bFilter ) { /* _fnFilter() will redraw the table for us */ _fnFilterComplete( oSettings, oSettings.oPreviousSearch, 1 ); } else { oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); oSettings._iDisplayStart = 0; /* reset display back to page 0 */ _fnCalculateEnd( oSettings ); _fnDraw( oSettings ); } } /** * Attach a sort handler (click) to a node * @param {object} oSettings dataTables settings object * @param {node} nNode node to attach the handler to * @param {int} iDataIndex column sorting index * @param {function} [fnCallback] callback function * @memberof DataTable#oApi */ function _fnSortAttachListener ( oSettings, nNode, iDataIndex, fnCallback ) { _fnBindAction( nNode, {}, function (e) { /* If the column is not sortable - don't to anything */ if ( oSettings.aoColumns[iDataIndex].bSortable === false ) { return; } /* * This is a little bit odd I admit... I declare a temporary function inside the scope of * _fnBuildHead and the click handler in order that the code presented here can be used * twice - once for when bProcessing is enabled, and another time for when it is * disabled, as we need to perform slightly different actions. * Basically the issue here is that the Javascript engine in modern browsers don't * appear to allow the rendering engine to update the display while it is still executing * it's thread (well - it does but only after long intervals). This means that the * 'processing' display doesn't appear for a table sort. To break the js thread up a bit * I force an execution break by using setTimeout - but this breaks the expected * thread continuation for the end-developer's point of view (their code would execute * too early), so we only do it when we absolutely have to. */ var fnInnerSorting = function () { var iColumn, iNextSort; /* If the shift key is pressed then we are multiple column sorting */ if ( e.shiftKey ) { /* Are we already doing some kind of sort on this column? */ var bFound = false; for ( var i=0 ; i<oSettings.aaSorting.length ; i++ ) { if ( oSettings.aaSorting[i][0] == iDataIndex ) { bFound = true; iColumn = oSettings.aaSorting[i][0]; iNextSort = oSettings.aaSorting[i][2]+1; if ( !oSettings.aoColumns[iColumn].asSorting[iNextSort] ) { /* Reached the end of the sorting options, remove from multi-col sort */ oSettings.aaSorting.splice( i, 1 ); } else { /* Move onto next sorting direction */ oSettings.aaSorting[i][1] = oSettings.aoColumns[iColumn].asSorting[iNextSort]; oSettings.aaSorting[i][2] = iNextSort; } break; } } /* No sort yet - add it in */ if ( bFound === false ) { oSettings.aaSorting.push( [ iDataIndex, oSettings.aoColumns[iDataIndex].asSorting[0], 0 ] ); } } else { /* If no shift key then single column sort */ if ( oSettings.aaSorting.length == 1 && oSettings.aaSorting[0][0] == iDataIndex ) { iColumn = oSettings.aaSorting[0][0]; iNextSort = oSettings.aaSorting[0][2]+1; if ( !oSettings.aoColumns[iColumn].asSorting[iNextSort] ) { iNextSort = 0; } oSettings.aaSorting[0][1] = oSettings.aoColumns[iColumn].asSorting[iNextSort]; oSettings.aaSorting[0][2] = iNextSort; } else { oSettings.aaSorting.splice( 0, oSettings.aaSorting.length ); oSettings.aaSorting.push( [ iDataIndex, oSettings.aoColumns[iDataIndex].asSorting[0], 0 ] ); } } /* Run the sort */ _fnSort( oSettings ); }; /* /fnInnerSorting */ if ( !oSettings.oFeatures.bProcessing ) { fnInnerSorting(); } else { _fnProcessingDisplay( oSettings, true ); setTimeout( function() { fnInnerSorting(); if ( !oSettings.oFeatures.bServerSide ) { _fnProcessingDisplay( oSettings, false ); } }, 0 ); } /* Call the user specified callback function - used for async user interaction */ if ( typeof fnCallback == 'function' ) { fnCallback( oSettings ); } } ); } /** * Set the sorting classes on the header, Note: it is safe to call this function * when bSort and bSortClasses are false * @param {object} oSettings dataTables settings object * @memberof DataTable#oApi */ function _fnSortingClasses( oSettings ) { var i, iLen, j, jLen, iFound; var aaSort, sClass; var iColumns = oSettings.aoColumns.length; var oClasses = oSettings.oClasses; for ( i=0 ; i<iColumns ; i++ ) { if ( oSettings.aoColumns[i].bSortable ) { $(oSettings.aoColumns[i].nTh).removeClass( oClasses.sSortAsc +" "+ oClasses.sSortDesc + " "+ oSettings.aoColumns[i].sSortingClass ); } } if ( oSettings.aaSortingFixed !== null ) { aaSort = oSettings.aaSortingFixed.concat( oSettings.aaSorting ); } else { aaSort = oSettings.aaSorting.slice(); } /* Apply the required classes to the header */ for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) { if ( oSettings.aoColumns[i].bSortable ) { sClass = oSettings.aoColumns[i].sSortingClass; iFound = -1; for ( j=0 ; j<aaSort.length ; j++ ) { if ( aaSort[j][0] == i ) { sClass = ( aaSort[j][1] == "asc" ) ? oClasses.sSortAsc : oClasses.sSortDesc; iFound = j; break; } } $(oSettings.aoColumns[i].nTh).addClass( sClass ); if ( oSettings.bJUI ) { /* jQuery UI uses extra markup */ var jqSpan = $("span."+oClasses.sSortIcon, oSettings.aoColumns[i].nTh); jqSpan.removeClass(oClasses.sSortJUIAsc +" "+ oClasses.sSortJUIDesc +" "+ oClasses.sSortJUI +" "+ oClasses.sSortJUIAscAllowed +" "+ oClasses.sSortJUIDescAllowed ); var sSpanClass; if ( iFound == -1 ) { sSpanClass = oSettings.aoColumns[i].sSortingClassJUI; } else if ( aaSort[iFound][1] == "asc" ) { sSpanClass = oClasses.sSortJUIAsc; } else { sSpanClass = oClasses.sSortJUIDesc; } jqSpan.addClass( sSpanClass ); } } else { /* No sorting on this column, so add the base class. This will have been assigned by * _fnAddColumn */ $(oSettings.aoColumns[i].nTh).addClass( oSettings.aoColumns[i].sSortingClass ); } } /* * Apply the required classes to the table body * Note that this is given as a feature switch since it can significantly slow down a sort * on large data sets (adding and removing of classes is always slow at the best of times..) * Further to this, note that this code is admittedly fairly ugly. It could be made a lot * simpler using jQuery selectors and add/removeClass, but that is significantly slower * (on the order of 5 times slower) - hence the direct DOM manipulation here. * Note that for deferred drawing we do use jQuery - the reason being that taking the first * row found to see if the whole column needs processed can miss classes since the first * column might be new. */ sClass = oClasses.sSortColumn; if ( oSettings.oFeatures.bSort && oSettings.oFeatures.bSortClasses ) { var nTds = _fnGetTdNodes( oSettings ); /* Determine what the sorting class for each column should be */ var iClass, iTargetCol; var asClasses = []; for (i = 0; i < iColumns; i++) { asClasses.push(""); } for (i = 0, iClass = 1; i < aaSort.length; i++) { iTargetCol = parseInt( aaSort[i][0], 10 ); asClasses[iTargetCol] = sClass + iClass; if ( iClass < 3 ) { iClass++; } } /* Make changes to the classes for each cell as needed */ var reClass = new RegExp(sClass + "[123]"); var sTmpClass, sCurrentClass, sNewClass; for ( i=0, iLen=nTds.length; i<iLen; i++ ) { /* Determine which column we're looking at */ iTargetCol = i % iColumns; /* What is the full list of classes now */ sCurrentClass = nTds[i].className; /* What sorting class should be applied? */ sNewClass = asClasses[iTargetCol]; /* What would the new full list be if we did a replacement? */ sTmpClass = sCurrentClass.replace(reClass, sNewClass); if ( sTmpClass != sCurrentClass ) { /* We changed something */ nTds[i].className = $.trim( sTmpClass ); } else if ( sNewClass.length > 0 && sCurrentClass.indexOf(sNewClass) == -1 ) { /* We need to add a class */ nTds[i].className = sCurrentClass + " " + sNewClass; } } } } /** * Save the state of a table in a cookie such that the page can be reloaded * @param {object} oSettings dataTables settings object * @memberof DataTable#oApi */ function _fnSaveState ( oSettings ) { if ( !oSettings.oFeatures.bStateSave || oSettings.bDestroying ) { return; } /* Store the interesting variables */ var i, iLen, bInfinite=oSettings.oScroll.bInfinite; var oState = { "iCreate": new Date().getTime(), "iStart": (bInfinite ? 0 : oSettings._iDisplayStart), "iEnd": (bInfinite ? oSettings._iDisplayLength : oSettings._iDisplayEnd), "iLength": oSettings._iDisplayLength, "aaSorting": $.extend( true, [], oSettings.aaSorting ), "oSearch": $.extend( true, {}, oSettings.oPreviousSearch ), "aoSearchCols": $.extend( true, [], oSettings.aoPreSearchCols ), "abVisCols": [] }; for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) { oState.abVisCols.push( oSettings.aoColumns[i].bVisible ); } _fnCallbackFire( oSettings, "aoStateSaveParams", 'stateSaveParams', [oSettings, oState] ); oSettings.fnStateSave.call( oSettings.oInstance, oSettings, oState ); } /** * Attempt to load a saved table state from a cookie * @param {object} oSettings dataTables settings object * @param {object} oInit DataTables init object so we can override settings * @memberof DataTable#oApi */ function _fnLoadState ( oSettings, oInit ) { if ( !oSettings.oFeatures.bStateSave ) { return; } var oData = oSettings.fnStateLoad.call( oSettings.oInstance, oSettings ); if ( !oData ) { return; } /* Allow custom and plug-in manipulation functions to alter the saved data set and * cancelling of loading by returning false */ var abStateLoad = _fnCallbackFire( oSettings, 'aoStateLoadParams', 'stateLoadParams', [oSettings, oData] ); if ( $.inArray( false, abStateLoad ) !== -1 ) { return; } /* Store the saved state so it might be accessed at any time */ oSettings.oLoadedState = $.extend( true, {}, oData ); /* Restore key features */ oSettings._iDisplayStart = oData.iStart; oSettings.iInitDisplayStart = oData.iStart; oSettings._iDisplayEnd = oData.iEnd; oSettings._iDisplayLength = oData.iLength; oSettings.aaSorting = oData.aaSorting.slice(); oSettings.saved_aaSorting = oData.aaSorting.slice(); /* Search filtering */ $.extend( oSettings.oPreviousSearch, oData.oSearch ); $.extend( true, oSettings.aoPreSearchCols, oData.aoSearchCols ); /* Column visibility state * Pass back visibility settings to the init handler, but to do not here override * the init object that the user might have passed in */ oInit.saved_aoColumns = []; for ( var i=0 ; i<oData.abVisCols.length ; i++ ) { oInit.saved_aoColumns[i] = {}; oInit.saved_aoColumns[i].bVisible = oData.abVisCols[i]; } _fnCallbackFire( oSettings, 'aoStateLoaded', 'stateLoaded', [oSettings, oData] ); } /** * Create a new cookie with a value to store the state of a table * @param {string} sName name of the cookie to create * @param {string} sValue the value the cookie should take * @param {int} iSecs duration of the cookie * @param {string} sBaseName sName is made up of the base + file name - this is the base * @param {function} fnCallback User definable function to modify the cookie * @memberof DataTable#oApi */ function _fnCreateCookie ( sName, sValue, iSecs, sBaseName, fnCallback ) { var date = new Date(); date.setTime( date.getTime()+(iSecs*1000) ); /* * Shocking but true - it would appear IE has major issues with having the path not having * a trailing slash on it. We need the cookie to be available based on the path, so we * have to append the file name to the cookie name. Appalling. Thanks to vex for adding the * patch to use at least some of the path */ var aParts = window.location.pathname.split('/'); var sNameFile = sName + '_' + aParts.pop().replace(/[\/:]/g,"").toLowerCase(); var sFullCookie, oData; if ( fnCallback !== null ) { oData = (typeof $.parseJSON === 'function') ? $.parseJSON( sValue ) : eval( '('+sValue+')' ); sFullCookie = fnCallback( sNameFile, oData, date.toGMTString(), aParts.join('/')+"/" ); } else { sFullCookie = sNameFile + "=" + encodeURIComponent(sValue) + "; expires=" + date.toGMTString() +"; path=" + aParts.join('/')+"/"; } /* Are we going to go over the cookie limit of 4KiB? If so, try to delete a cookies * belonging to DataTables. */ var aCookies =document.cookie.split(';'), iNewCookieLen = sFullCookie.split(';')[0].length, aOldCookies = []; if ( iNewCookieLen+document.cookie.length+10 > 4096 ) /* Magic 10 for padding */ { for ( var i=0, iLen=aCookies.length ; i<iLen ; i++ ) { if ( aCookies[i].indexOf( sBaseName ) != -1 ) { /* It's a DataTables cookie, so eval it and check the time stamp */ var aSplitCookie = aCookies[i].split('='); try { oData = eval( '('+decodeURIComponent(aSplitCookie[1])+')' ); if ( oData && oData.iCreate ) { aOldCookies.push( { "name": aSplitCookie[0], "time": oData.iCreate } ); } } catch( e ) {} } } // Make sure we delete the oldest ones first aOldCookies.sort( function (a, b) { return b.time - a.time; } ); // Eliminate as many old DataTables cookies as we need to while ( iNewCookieLen + document.cookie.length + 10 > 4096 ) { if ( aOldCookies.length === 0 ) { // Deleted all DT cookies and still not enough space. Can't state save return; } var old = aOldCookies.pop(); document.cookie = old.name+"=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path="+ aParts.join('/') + "/"; } } document.cookie = sFullCookie; } /** * Read an old cookie to get a cookie with an old table state * @param {string} sName name of the cookie to read * @returns {string} contents of the cookie - or null if no cookie with that name found * @memberof DataTable#oApi */ function _fnReadCookie ( sName ) { var aParts = window.location.pathname.split('/'), sNameEQ = sName + '_' + aParts[aParts.length-1].replace(/[\/:]/g,"").toLowerCase() + '=', sCookieContents = document.cookie.split(';'); for( var i=0 ; i<sCookieContents.length ; i++ ) { var c = sCookieContents[i]; while (c.charAt(0)==' ') { c = c.substring(1,c.length); } if (c.indexOf(sNameEQ) === 0) { return decodeURIComponent( c.substring(sNameEQ.length,c.length) ); } } return null; } /** * Return the settings object for a particular table * @param {node} nTable table we are using as a dataTable * @returns {object} Settings object - or null if not found * @memberof DataTable#oApi */ function _fnSettingsFromNode ( nTable ) { for ( var i=0 ; i<DataTable.settings.length ; i++ ) { if ( DataTable.settings[i].nTable === nTable ) { return DataTable.settings[i]; } } return null; } /** * Return an array with the TR nodes for the table * @param {object} oSettings dataTables settings object * @returns {array} TR array * @memberof DataTable#oApi */ function _fnGetTrNodes ( oSettings ) { var aNodes = []; var aoData = oSettings.aoData; for ( var i=0, iLen=aoData.length ; i<iLen ; i++ ) { if ( aoData[i].nTr !== null ) { aNodes.push( aoData[i].nTr ); } } return aNodes; } /** * Return an flat array with all TD nodes for the table, or row * @param {object} oSettings dataTables settings object * @param {int} [iIndividualRow] aoData index to get the nodes for - optional * if not given then the return array will contain all nodes for the table * @returns {array} TD array * @memberof DataTable#oApi */ function _fnGetTdNodes ( oSettings, iIndividualRow ) { var anReturn = []; var iCorrector; var anTds, nTd; var iRow, iRows=oSettings.aoData.length, iColumn, iColumns, oData, sNodeName, iStart=0, iEnd=iRows; /* Allow the collection to be limited to just one row */ if ( iIndividualRow !== undefined ) { iStart = iIndividualRow; iEnd = iIndividualRow+1; } for ( iRow=iStart ; iRow<iEnd ; iRow++ ) { oData = oSettings.aoData[iRow]; if ( oData.nTr !== null ) { /* get the TD child nodes - taking into account text etc nodes */ anTds = []; nTd = oData.nTr.firstChild; while ( nTd ) { sNodeName = nTd.nodeName.toLowerCase(); if ( sNodeName == 'td' || sNodeName == 'th' ) { anTds.push( nTd ); } nTd = nTd.nextSibling; } iCorrector = 0; for ( iColumn=0, iColumns=oSettings.aoColumns.length ; iColumn<iColumns ; iColumn++ ) { if ( oSettings.aoColumns[iColumn].bVisible ) { anReturn.push( anTds[iColumn-iCorrector] ); } else { anReturn.push( oData._anHidden[iColumn] ); iCorrector++; } } } } return anReturn; } /** * Log an error message * @param {object} oSettings dataTables settings object * @param {int} iLevel log error messages, or display them to the user * @param {string} sMesg error message * @memberof DataTable#oApi */ function _fnLog( oSettings, iLevel, sMesg ) { var sAlert = (oSettings===null) ? "DataTables warning: "+sMesg : "DataTables warning (table id = '"+oSettings.sTableId+"'): "+sMesg; if ( iLevel === 0 ) { if ( DataTable.ext.sErrMode == 'alert' ) { alert( sAlert ); } else { throw new Error(sAlert); } return; } else if ( window.console && console.log ) { console.log( sAlert ); } } /** * See if a property is defined on one object, if so assign it to the other object * @param {object} oRet target object * @param {object} oSrc source object * @param {string} sName property * @param {string} [sMappedName] name to map too - optional, sName used if not given * @memberof DataTable#oApi */ function _fnMap( oRet, oSrc, sName, sMappedName ) { if ( sMappedName === undefined ) { sMappedName = sName; } if ( oSrc[sName] !== undefined ) { oRet[sMappedName] = oSrc[sName]; } } /** * Extend objects - very similar to jQuery.extend, but deep copy objects, and shallow * copy arrays. The reason we need to do this, is that we don't want to deep copy array * init values (such as aaSorting) since the dev wouldn't be able to override them, but * we do want to deep copy arrays. * @param {object} oOut Object to extend * @param {object} oExtender Object from which the properties will be applied to oOut * @returns {object} oOut Reference, just for convenience - oOut === the return. * @memberof DataTable#oApi * @todo This doesn't take account of arrays inside the deep copied objects. */ function _fnExtend( oOut, oExtender ) { var val; for ( var prop in oExtender ) { if ( oExtender.hasOwnProperty(prop) ) { val = oExtender[prop]; if ( typeof oInit[prop] === 'object' && val !== null && $.isArray(val) === false ) { $.extend( true, oOut[prop], val ); } else { oOut[prop] = val; } } } return oOut; } /** * Bind an event handers to allow a click or return key to activate the callback. * This is good for accessibility since a return on the keyboard will have the * same effect as a click, if the element has focus. * @param {element} n Element to bind the action to * @param {object} oData Data object to pass to the triggered function * @param {function} fn Callback function for when the event is triggered * @memberof DataTable#oApi */ function _fnBindAction( n, oData, fn ) { $(n) .bind( 'click.DT', oData, function (e) { n.blur(); // Remove focus outline for mouse users fn(e); } ) .bind( 'keypress.DT', oData, function (e){ if ( e.which === 13 ) { fn(e); } } ) .bind( 'selectstart.DT', function () { /* Take the brutal approach to cancelling text selection */ return false; } ); } /** * Register a callback function. Easily allows a callback function to be added to * an array store of callback functions that can then all be called together. * @param {object} oSettings dataTables settings object * @param {string} sStore Name of the array storage for the callbacks in oSettings * @param {function} fn Function to be called back * @param {string} sName Identifying name for the callback (i.e. a label) * @memberof DataTable#oApi */ function _fnCallbackReg( oSettings, sStore, fn, sName ) { if ( fn ) { oSettings[sStore].push( { "fn": fn, "sName": sName } ); } } /** * Fire callback functions and trigger events. Note that the loop over the callback * array store is done backwards! Further note that you do not want to fire off triggers * in time sensitive applications (for example cell creation) as its slow. * @param {object} oSettings dataTables settings object * @param {string} sStore Name of the array storage for the callbacks in oSettings * @param {string} sTrigger Name of the jQuery custom event to trigger. If null no trigger * is fired * @param {array} aArgs Array of arguments to pass to the callback function / trigger * @memberof DataTable#oApi */ function _fnCallbackFire( oSettings, sStore, sTrigger, aArgs ) { var aoStore = oSettings[sStore]; var aRet =[]; for ( var i=aoStore.length-1 ; i>=0 ; i-- ) { aRet.push( aoStore[i].fn.apply( oSettings.oInstance, aArgs ) ); } if ( sTrigger !== null ) { $(oSettings.oInstance).trigger(sTrigger, aArgs); } return aRet; } /** * JSON stringify. If JSON.stringify it provided by the browser, json2.js or any other * library, then we use that as it is fast, safe and accurate. If the function isn't * available then we need to built it ourselves - the inspiration for this function comes * from Craig Buckler ( http://www.sitepoint.com/javascript-json-serialization/ ). It is * not perfect and absolutely should not be used as a replacement to json2.js - but it does * do what we need, without requiring a dependency for DataTables. * @param {object} o JSON object to be converted * @returns {string} JSON string * @memberof DataTable#oApi */ var _fnJsonString = (window.JSON) ? JSON.stringify : function( o ) { /* Not an object or array */ var sType = typeof o; if (sType !== "object" || o === null) { // simple data type if (sType === "string") { o = '"'+o+'"'; } return o+""; } /* If object or array, need to recurse over it */ var sProp, mValue, json = [], bArr = $.isArray(o); for (sProp in o) { mValue = o[sProp]; sType = typeof mValue; if (sType === "string") { mValue = '"'+mValue+'"'; } else if (sType === "object" && mValue !== null) { mValue = _fnJsonString(mValue); } json.push((bArr ? "" : '"'+sProp+'":') + mValue); } return (bArr ? "[" : "{") + json + (bArr ? "]" : "}"); }; /** * From some browsers (specifically IE6/7) we need special handling to work around browser * bugs - this function is used to detect when these workarounds are needed. * @param {object} oSettings dataTables settings object * @memberof DataTable#oApi */ function _fnBrowserDetect( oSettings ) { /* IE6/7 will oversize a width 100% element inside a scrolling element, to include the * width of the scrollbar, while other browsers ensure the inner element is contained * without forcing scrolling */ var n = $( '<div style="position:absolute; top:0; left:0; height:1px; width:1px; overflow:hidden">'+ '<div style="position:absolute; top:1px; left:1px; width:100px; overflow:scroll;">'+ '<div id="DT_BrowserTest" style="width:100%; height:10px;"></div>'+ '</div>'+ '</div>')[0]; document.body.appendChild( n ); oSettings.oBrowser.bScrollOversize = $('#DT_BrowserTest', n)[0].offsetWidth === 100 ? true : false; document.body.removeChild( n ); } /** * Perform a jQuery selector action on the table's TR elements (from the tbody) and * return the resulting jQuery object. * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on * @param {object} [oOpts] Optional parameters for modifying the rows to be included * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter * criterion ("applied") or all TR elements (i.e. no filter). * @param {string} [oOpts.order=current] Order of the TR elements in the processed array. * Can be either 'current', whereby the current sorting of the table is used, or * 'original' whereby the original order the data was read into the table is used. * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page * ("current") or not ("all"). If 'current' is given, then order is assumed to be * 'current' and filter is 'applied', regardless of what they might be given as. * @returns {object} jQuery object, filtered by the given selector. * @dtopt API * * @example * $(document).ready(function() { * var oTable = $('#example').dataTable(); * * // Highlight every second row * oTable.$('tr:odd').css('backgroundColor', 'blue'); * } ); * * @example * $(document).ready(function() { * var oTable = $('#example').dataTable(); * * // Filter to rows with 'Webkit' in them, add a background colour and then * // remove the filter, thus highlighting the 'Webkit' rows only. * oTable.fnFilter('Webkit'); * oTable.$('tr', {"filter": "applied"}).css('backgroundColor', 'blue'); * oTable.fnFilter(''); * } ); */ this.$ = function ( sSelector, oOpts ) { var i, iLen, a = [], tr; var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); var aoData = oSettings.aoData; var aiDisplay = oSettings.aiDisplay; var aiDisplayMaster = oSettings.aiDisplayMaster; if ( !oOpts ) { oOpts = {}; } oOpts = $.extend( {}, { "filter": "none", // applied "order": "current", // "original" "page": "all" // current }, oOpts ); // Current page implies that order=current and fitler=applied, since it is fairly // senseless otherwise if ( oOpts.page == 'current' ) { for ( i=oSettings._iDisplayStart, iLen=oSettings.fnDisplayEnd() ; i<iLen ; i++ ) { tr = aoData[ aiDisplay[i] ].nTr; if ( tr ) { a.push( tr ); } } } else if ( oOpts.order == "current" && oOpts.filter == "none" ) { for ( i=0, iLen=aiDisplayMaster.length ; i<iLen ; i++ ) { tr = aoData[ aiDisplayMaster[i] ].nTr; if ( tr ) { a.push( tr ); } } } else if ( oOpts.order == "current" && oOpts.filter == "applied" ) { for ( i=0, iLen=aiDisplay.length ; i<iLen ; i++ ) { tr = aoData[ aiDisplay[i] ].nTr; if ( tr ) { a.push( tr ); } } } else if ( oOpts.order == "original" && oOpts.filter == "none" ) { for ( i=0, iLen=aoData.length ; i<iLen ; i++ ) { tr = aoData[ i ].nTr ; if ( tr ) { a.push( tr ); } } } else if ( oOpts.order == "original" && oOpts.filter == "applied" ) { for ( i=0, iLen=aoData.length ; i<iLen ; i++ ) { tr = aoData[ i ].nTr; if ( $.inArray( i, aiDisplay ) !== -1 && tr ) { a.push( tr ); } } } else { _fnLog( oSettings, 1, "Unknown selection options" ); } /* We need to filter on the TR elements and also 'find' in their descendants * to make the selector act like it would in a full table - so we need * to build both results and then combine them together */ var jqA = $(a); var jqTRs = jqA.filter( sSelector ); var jqDescendants = jqA.find( sSelector ); return $( [].concat($.makeArray(jqTRs), $.makeArray(jqDescendants)) ); }; /** * Almost identical to $ in operation, but in this case returns the data for the matched * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes * rather than any descendants, so the data can be obtained for the row/cell. If matching * rows are found, the data returned is the original data array/object that was used to * create the row (or a generated array if from a DOM source). * * This method is often useful in-combination with $ where both functions are given the * same parameters and the array indexes will match identically. * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on * @param {object} [oOpts] Optional parameters for modifying the rows to be included * @param {string} [oOpts.filter=none] Select elements that meet the current filter * criterion ("applied") or all elements (i.e. no filter). * @param {string} [oOpts.order=current] Order of the data in the processed array. * Can be either 'current', whereby the current sorting of the table is used, or * 'original' whereby the original order the data was read into the table is used. * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page * ("current") or not ("all"). If 'current' is given, then order is assumed to be * 'current' and filter is 'applied', regardless of what they might be given as. * @returns {array} Data for the matched elements. If any elements, as a result of the * selector, were not TR, TD or TH elements in the DataTable, they will have a null * entry in the array. * @dtopt API * * @example * $(document).ready(function() { * var oTable = $('#example').dataTable(); * * // Get the data from the first row in the table * var data = oTable._('tr:first'); * * // Do something useful with the data * alert( "First cell is: "+data[0] ); * } ); * * @example * $(document).ready(function() { * var oTable = $('#example').dataTable(); * * // Filter to 'Webkit' and get all data for * oTable.fnFilter('Webkit'); * var data = oTable._('tr', {"filter": "applied"}); * * // Do something with the data * alert( data.length+" rows matched the filter" ); * } ); */ this._ = function ( sSelector, oOpts ) { var aOut = []; var i, iLen, iIndex; var aTrs = this.$( sSelector, oOpts ); for ( i=0, iLen=aTrs.length ; i<iLen ; i++ ) { aOut.push( this.fnGetData(aTrs[i]) ); } return aOut; }; /** * Add a single new row or multiple rows of data to the table. Please note * that this is suitable for client-side processing only - if you are using * server-side processing (i.e. "bServerSide": true), then to add data, you * must add it to the data source, i.e. the server-side, through an Ajax call. * @param {array|object} mData The data to be added to the table. This can be: * <ul> * <li>1D array of data - add a single row with the data provided</li> * <li>2D array of arrays - add multiple rows in a single call</li> * <li>object - data object when using <i>mData</i></li> * <li>array of objects - multiple data objects when using <i>mData</i></li> * </ul> * @param {bool} [bRedraw=true] redraw the table or not * @returns {array} An array of integers, representing the list of indexes in * <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to * the table. * @dtopt API * * @example * // Global var for counter * var giCount = 2; * * $(document).ready(function() { * $('#example').dataTable(); * } ); * * function fnClickAddRow() { * $('#example').dataTable().fnAddData( [ * giCount+".1", * giCount+".2", * giCount+".3", * giCount+".4" ] * ); * * giCount++; * } */ this.fnAddData = function( mData, bRedraw ) { if ( mData.length === 0 ) { return []; } var aiReturn = []; var iTest; /* Find settings from table node */ var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); /* Check if we want to add multiple rows or not */ if ( typeof mData[0] === "object" && mData[0] !== null ) { for ( var i=0 ; i<mData.length ; i++ ) { iTest = _fnAddData( oSettings, mData[i] ); if ( iTest == -1 ) { return aiReturn; } aiReturn.push( iTest ); } } else { iTest = _fnAddData( oSettings, mData ); if ( iTest == -1 ) { return aiReturn; } aiReturn.push( iTest ); } oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); if ( bRedraw === undefined || bRedraw ) { _fnReDraw( oSettings ); } return aiReturn; }; /** * This function will make DataTables recalculate the column sizes, based on the data * contained in the table and the sizes applied to the columns (in the DOM, CSS or * through the sWidth parameter). This can be useful when the width of the table's * parent element changes (for example a window resize). * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to * @dtopt API * * @example * $(document).ready(function() { * var oTable = $('#example').dataTable( { * "sScrollY": "200px", * "bPaginate": false * } ); * * $(window).bind('resize', function () { * oTable.fnAdjustColumnSizing(); * } ); * } ); */ this.fnAdjustColumnSizing = function ( bRedraw ) { var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]); _fnAdjustColumnSizing( oSettings ); if ( bRedraw === undefined || bRedraw ) { this.fnDraw( false ); } else if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" ) { /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */ this.oApi._fnScrollDraw(oSettings); } }; /** * Quickly and simply clear a table * @param {bool} [bRedraw=true] redraw the table or not * @dtopt API * * @example * $(document).ready(function() { * var oTable = $('#example').dataTable(); * * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...) * oTable.fnClearTable(); * } ); */ this.fnClearTable = function( bRedraw ) { /* Find settings from table node */ var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); _fnClearTable( oSettings ); if ( bRedraw === undefined || bRedraw ) { _fnDraw( oSettings ); } }; /** * The exact opposite of 'opening' a row, this function will close any rows which * are currently 'open'. * @param {node} nTr the table row to 'close' * @returns {int} 0 on success, or 1 if failed (can't find the row) * @dtopt API * * @example * $(document).ready(function() { * var oTable; * * // 'open' an information row when a row is clicked on * $('#example tbody tr').click( function () { * if ( oTable.fnIsOpen(this) ) { * oTable.fnClose( this ); * } else { * oTable.fnOpen( this, "Temporary row opened", "info_row" ); * } * } ); * * oTable = $('#example').dataTable(); * } ); */ this.fnClose = function( nTr ) { /* Find settings from table node */ var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); for ( var i=0 ; i<oSettings.aoOpenRows.length ; i++ ) { if ( oSettings.aoOpenRows[i].nParent == nTr ) { var nTrParent = oSettings.aoOpenRows[i].nTr.parentNode; if ( nTrParent ) { /* Remove it if it is currently on display */ nTrParent.removeChild( oSettings.aoOpenRows[i].nTr ); } oSettings.aoOpenRows.splice( i, 1 ); return 0; } } return 1; }; /** * Remove a row for the table * @param {mixed} mTarget The index of the row from aoData to be deleted, or * the TR element you want to delete * @param {function|null} [fnCallBack] Callback function * @param {bool} [bRedraw=true] Redraw the table or not * @returns {array} The row that was deleted * @dtopt API * * @example * $(document).ready(function() { * var oTable = $('#example').dataTable(); * * // Immediately remove the first row * oTable.fnDeleteRow( 0 ); * } ); */ this.fnDeleteRow = function( mTarget, fnCallBack, bRedraw ) { /* Find settings from table node */ var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); var i, iLen, iAODataIndex; iAODataIndex = (typeof mTarget === 'object') ? _fnNodeToDataIndex(oSettings, mTarget) : mTarget; /* Return the data array from this row */ var oData = oSettings.aoData.splice( iAODataIndex, 1 ); /* Update the _DT_RowIndex parameter */ for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ ) { if ( oSettings.aoData[i].nTr !== null ) { oSettings.aoData[i].nTr._DT_RowIndex = i; } } /* Remove the target row from the search array */ var iDisplayIndex = $.inArray( iAODataIndex, oSettings.aiDisplay ); oSettings.asDataSearch.splice( iDisplayIndex, 1 ); /* Delete from the display arrays */ _fnDeleteIndex( oSettings.aiDisplayMaster, iAODataIndex ); _fnDeleteIndex( oSettings.aiDisplay, iAODataIndex ); /* If there is a user callback function - call it */ if ( typeof fnCallBack === "function" ) { fnCallBack.call( this, oSettings, oData ); } /* Check for an 'overflow' they case for displaying the table */ if ( oSettings._iDisplayStart >= oSettings.fnRecordsDisplay() ) { oSettings._iDisplayStart -= oSettings._iDisplayLength; if ( oSettings._iDisplayStart < 0 ) { oSettings._iDisplayStart = 0; } } if ( bRedraw === undefined || bRedraw ) { _fnCalculateEnd( oSettings ); _fnDraw( oSettings ); } return oData; }; /** * Restore the table to it's original state in the DOM by removing all of DataTables * enhancements, alterations to the DOM structure of the table and event listeners. * @param {boolean} [bRemove=false] Completely remove the table from the DOM * @dtopt API * * @example * $(document).ready(function() { * // This example is fairly pointless in reality, but shows how fnDestroy can be used * var oTable = $('#example').dataTable(); * oTable.fnDestroy(); * } ); */ this.fnDestroy = function ( bRemove ) { var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); var nOrig = oSettings.nTableWrapper.parentNode; var nBody = oSettings.nTBody; var i, iLen; bRemove = (bRemove===undefined) ? false : bRemove; /* Flag to note that the table is currently being destroyed - no action should be taken */ oSettings.bDestroying = true; /* Fire off the destroy callbacks for plug-ins etc */ _fnCallbackFire( oSettings, "aoDestroyCallback", "destroy", [oSettings] ); /* If the table is not being removed, restore the hidden columns */ if ( !bRemove ) { for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) { if ( oSettings.aoColumns[i].bVisible === false ) { this.fnSetColumnVis( i, true ); } } } /* Blitz all DT events */ $(oSettings.nTableWrapper).find('*').andSelf().unbind('.DT'); /* If there is an 'empty' indicator row, remove it */ $('tbody>tr>td.'+oSettings.oClasses.sRowEmpty, oSettings.nTable).parent().remove(); /* When scrolling we had to break the table up - restore it */ if ( oSettings.nTable != oSettings.nTHead.parentNode ) { $(oSettings.nTable).children('thead').remove(); oSettings.nTable.appendChild( oSettings.nTHead ); } if ( oSettings.nTFoot && oSettings.nTable != oSettings.nTFoot.parentNode ) { $(oSettings.nTable).children('tfoot').remove(); oSettings.nTable.appendChild( oSettings.nTFoot ); } /* Remove the DataTables generated nodes, events and classes */ oSettings.nTable.parentNode.removeChild( oSettings.nTable ); $(oSettings.nTableWrapper).remove(); oSettings.aaSorting = []; oSettings.aaSortingFixed = []; _fnSortingClasses( oSettings ); $(_fnGetTrNodes( oSettings )).removeClass( oSettings.asStripeClasses.join(' ') ); $('th, td', oSettings.nTHead).removeClass( [ oSettings.oClasses.sSortable, oSettings.oClasses.sSortableAsc, oSettings.oClasses.sSortableDesc, oSettings.oClasses.sSortableNone ].join(' ') ); if ( oSettings.bJUI ) { $('th span.'+oSettings.oClasses.sSortIcon + ', td span.'+oSettings.oClasses.sSortIcon, oSettings.nTHead).remove(); $('th, td', oSettings.nTHead).each( function () { var jqWrapper = $('div.'+oSettings.oClasses.sSortJUIWrapper, this); var kids = jqWrapper.contents(); $(this).append( kids ); jqWrapper.remove(); } ); } /* Add the TR elements back into the table in their original order */ if ( !bRemove && oSettings.nTableReinsertBefore ) { nOrig.insertBefore( oSettings.nTable, oSettings.nTableReinsertBefore ); } else if ( !bRemove ) { nOrig.appendChild( oSettings.nTable ); } for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ ) { if ( oSettings.aoData[i].nTr !== null ) { nBody.appendChild( oSettings.aoData[i].nTr ); } } /* Restore the width of the original table */ if ( oSettings.oFeatures.bAutoWidth === true ) { oSettings.nTable.style.width = _fnStringToCss(oSettings.sDestroyWidth); } /* If the were originally stripe classes - then we add them back here. Note * this is not fool proof (for example if not all rows had stripe classes - but * it's a good effort without getting carried away */ iLen = oSettings.asDestroyStripes.length; if (iLen) { var anRows = $(nBody).children('tr'); for ( i=0 ; i<iLen ; i++ ) { anRows.filter(':nth-child(' + iLen + 'n + ' + i + ')').addClass( oSettings.asDestroyStripes[i] ); } } /* Remove the settings object from the settings array */ for ( i=0, iLen=DataTable.settings.length ; i<iLen ; i++ ) { if ( DataTable.settings[i] == oSettings ) { DataTable.settings.splice( i, 1 ); } } /* End it all */ oSettings = null; oInit = null; }; /** * Redraw the table * @param {bool} [bComplete=true] Re-filter and resort (if enabled) the table before the draw. * @dtopt API * * @example * $(document).ready(function() { * var oTable = $('#example').dataTable(); * * // Re-draw the table - you wouldn't want to do it here, but it's an example :-) * oTable.fnDraw(); * } ); */ this.fnDraw = function( bComplete ) { var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); if ( bComplete === false ) { _fnCalculateEnd( oSettings ); _fnDraw( oSettings ); } else { _fnReDraw( oSettings ); } }; /** * Filter the input based on data * @param {string} sInput String to filter the table on * @param {int|null} [iColumn] Column to limit filtering to * @param {bool} [bRegex=false] Treat as regular expression or not * @param {bool} [bSmart=true] Perform smart filtering or not * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es) * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false) * @dtopt API * * @example * $(document).ready(function() { * var oTable = $('#example').dataTable(); * * // Sometime later - filter... * oTable.fnFilter( 'test string' ); * } ); */ this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive ) { var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); if ( !oSettings.oFeatures.bFilter ) { return; } if ( bRegex === undefined || bRegex === null ) { bRegex = false; } if ( bSmart === undefined || bSmart === null ) { bSmart = true; } if ( bShowGlobal === undefined || bShowGlobal === null ) { bShowGlobal = true; } if ( bCaseInsensitive === undefined || bCaseInsensitive === null ) { bCaseInsensitive = true; } if ( iColumn === undefined || iColumn === null ) { /* Global filter */ _fnFilterComplete( oSettings, { "sSearch":sInput+"", "bRegex": bRegex, "bSmart": bSmart, "bCaseInsensitive": bCaseInsensitive }, 1 ); if ( bShowGlobal && oSettings.aanFeatures.f ) { var n = oSettings.aanFeatures.f; for ( var i=0, iLen=n.length ; i<iLen ; i++ ) { // IE9 throws an 'unknown error' if document.activeElement is used // inside an iframe or frame... try { if ( n[i]._DT_Input != document.activeElement ) { $(n[i]._DT_Input).val( sInput ); } } catch ( e ) { $(n[i]._DT_Input).val( sInput ); } } } } else { /* Single column filter */ $.extend( oSettings.aoPreSearchCols[ iColumn ], { "sSearch": sInput+"", "bRegex": bRegex, "bSmart": bSmart, "bCaseInsensitive": bCaseInsensitive } ); _fnFilterComplete( oSettings, oSettings.oPreviousSearch, 1 ); } }; /** * Get the data for the whole table, an individual row or an individual cell based on the * provided parameters. * @param {int|node} [mRow] A TR row node, TD/TH cell node or an integer. If given as * a TR node then the data source for the whole row will be returned. If given as a * TD/TH cell node then iCol will be automatically calculated and the data for the * cell returned. If given as an integer, then this is treated as the aoData internal * data index for the row (see fnGetPosition) and the data for that row used. * @param {int} [iCol] Optional column index that you want the data of. * @returns {array|object|string} If mRow is undefined, then the data for all rows is * returned. If mRow is defined, just data for that row, and is iCol is * defined, only data for the designated cell is returned. * @dtopt API * * @example * // Row data * $(document).ready(function() { * oTable = $('#example').dataTable(); * * oTable.$('tr').click( function () { * var data = oTable.fnGetData( this ); * // ... do something with the array / object of data for the row * } ); * } ); * * @example * // Individual cell data * $(document).ready(function() { * oTable = $('#example').dataTable(); * * oTable.$('td').click( function () { * var sData = oTable.fnGetData( this ); * alert( 'The cell clicked on had the value of '+sData ); * } ); * } ); */ this.fnGetData = function( mRow, iCol ) { var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); if ( mRow !== undefined ) { var iRow = mRow; if ( typeof mRow === 'object' ) { var sNode = mRow.nodeName.toLowerCase(); if (sNode === "tr" ) { iRow = _fnNodeToDataIndex(oSettings, mRow); } else if ( sNode === "td" ) { iRow = _fnNodeToDataIndex(oSettings, mRow.parentNode); iCol = _fnNodeToColumnIndex( oSettings, iRow, mRow ); } } if ( iCol !== undefined ) { return _fnGetCellData( oSettings, iRow, iCol, '' ); } return (oSettings.aoData[iRow]!==undefined) ? oSettings.aoData[iRow]._aData : null; } return _fnGetDataMaster( oSettings ); }; /** * Get an array of the TR nodes that are used in the table's body. Note that you will * typically want to use the '$' API method in preference to this as it is more * flexible. * @param {int} [iRow] Optional row index for the TR element you want * @returns {array|node} If iRow is undefined, returns an array of all TR elements * in the table's body, or iRow is defined, just the TR element requested. * @dtopt API * * @example * $(document).ready(function() { * var oTable = $('#example').dataTable(); * * // Get the nodes from the table * var nNodes = oTable.fnGetNodes( ); * } ); */ this.fnGetNodes = function( iRow ) { var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); if ( iRow !== undefined ) { return (oSettings.aoData[iRow]!==undefined) ? oSettings.aoData[iRow].nTr : null; } return _fnGetTrNodes( oSettings ); }; /** * Get the array indexes of a particular cell from it's DOM element * and column index including hidden columns * @param {node} nNode this can either be a TR, TD or TH in the table's body * @returns {int} If nNode is given as a TR, then a single index is returned, or * if given as a cell, an array of [row index, column index (visible), * column index (all)] is given. * @dtopt API * * @example * $(document).ready(function() { * $('#example tbody td').click( function () { * // Get the position of the current data from the node * var aPos = oTable.fnGetPosition( this ); * * // Get the data array for this row * var aData = oTable.fnGetData( aPos[0] ); * * // Update the data array and return the value * aData[ aPos[1] ] = 'clicked'; * this.innerHTML = 'clicked'; * } ); * * // Init DataTables * oTable = $('#example').dataTable(); * } ); */ this.fnGetPosition = function( nNode ) { var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); var sNodeName = nNode.nodeName.toUpperCase(); if ( sNodeName == "TR" ) { return _fnNodeToDataIndex(oSettings, nNode); } else if ( sNodeName == "TD" || sNodeName == "TH" ) { var iDataIndex = _fnNodeToDataIndex( oSettings, nNode.parentNode ); var iColumnIndex = _fnNodeToColumnIndex( oSettings, iDataIndex, nNode ); return [ iDataIndex, _fnColumnIndexToVisible(oSettings, iColumnIndex ), iColumnIndex ]; } return null; }; /** * Check to see if a row is 'open' or not. * @param {node} nTr the table row to check * @returns {boolean} true if the row is currently open, false otherwise * @dtopt API * * @example * $(document).ready(function() { * var oTable; * * // 'open' an information row when a row is clicked on * $('#example tbody tr').click( function () { * if ( oTable.fnIsOpen(this) ) { * oTable.fnClose( this ); * } else { * oTable.fnOpen( this, "Temporary row opened", "info_row" ); * } * } ); * * oTable = $('#example').dataTable(); * } ); */ this.fnIsOpen = function( nTr ) { var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); var aoOpenRows = oSettings.aoOpenRows; for ( var i=0 ; i<oSettings.aoOpenRows.length ; i++ ) { if ( oSettings.aoOpenRows[i].nParent == nTr ) { return true; } } return false; }; /** * This function will place a new row directly after a row which is currently * on display on the page, with the HTML contents that is passed into the * function. This can be used, for example, to ask for confirmation that a * particular record should be deleted. * @param {node} nTr The table row to 'open' * @param {string|node|jQuery} mHtml The HTML to put into the row * @param {string} sClass Class to give the new TD cell * @returns {node} The row opened. Note that if the table row passed in as the * first parameter, is not found in the table, this method will silently * return. * @dtopt API * * @example * $(document).ready(function() { * var oTable; * * // 'open' an information row when a row is clicked on * $('#example tbody tr').click( function () { * if ( oTable.fnIsOpen(this) ) { * oTable.fnClose( this ); * } else { * oTable.fnOpen( this, "Temporary row opened", "info_row" ); * } * } ); * * oTable = $('#example').dataTable(); * } ); */ this.fnOpen = function( nTr, mHtml, sClass ) { /* Find settings from table node */ var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); /* Check that the row given is in the table */ var nTableRows = _fnGetTrNodes( oSettings ); if ( $.inArray(nTr, nTableRows) === -1 ) { return; } /* the old open one if there is one */ this.fnClose( nTr ); var nNewRow = document.createElement("tr"); var nNewCell = document.createElement("td"); nNewRow.appendChild( nNewCell ); nNewCell.className = sClass; nNewCell.colSpan = _fnVisbleColumns( oSettings ); if (typeof mHtml === "string") { nNewCell.innerHTML = mHtml; } else { $(nNewCell).html( mHtml ); } /* If the nTr isn't on the page at the moment - then we don't insert at the moment */ var nTrs = $('tr', oSettings.nTBody); if ( $.inArray(nTr, nTrs) != -1 ) { $(nNewRow).insertAfter(nTr); } oSettings.aoOpenRows.push( { "nTr": nNewRow, "nParent": nTr } ); return nNewRow; }; /** * Change the pagination - provides the internal logic for pagination in a simple API * function. With this function you can have a DataTables table go to the next, * previous, first or last pages. * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last" * or page number to jump to (integer), note that page 0 is the first page. * @param {bool} [bRedraw=true] Redraw the table or not * @dtopt API * * @example * $(document).ready(function() { * var oTable = $('#example').dataTable(); * oTable.fnPageChange( 'next' ); * } ); */ this.fnPageChange = function ( mAction, bRedraw ) { var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); _fnPageChange( oSettings, mAction ); _fnCalculateEnd( oSettings ); if ( bRedraw === undefined || bRedraw ) { _fnDraw( oSettings ); } }; /** * Show a particular column * @param {int} iCol The column whose display should be changed * @param {bool} bShow Show (true) or hide (false) the column * @param {bool} [bRedraw=true] Redraw the table or not * @dtopt API * * @example * $(document).ready(function() { * var oTable = $('#example').dataTable(); * * // Hide the second column after initialisation * oTable.fnSetColumnVis( 1, false ); * } ); */ this.fnSetColumnVis = function ( iCol, bShow, bRedraw ) { var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); var i, iLen; var aoColumns = oSettings.aoColumns; var aoData = oSettings.aoData; var nTd, bAppend, iBefore; /* No point in doing anything if we are requesting what is already true */ if ( aoColumns[iCol].bVisible == bShow ) { return; } /* Show the column */ if ( bShow ) { var iInsert = 0; for ( i=0 ; i<iCol ; i++ ) { if ( aoColumns[i].bVisible ) { iInsert++; } } /* Need to decide if we should use appendChild or insertBefore */ bAppend = (iInsert >= _fnVisbleColumns( oSettings )); /* Which coloumn should we be inserting before? */ if ( !bAppend ) { for ( i=iCol ; i<aoColumns.length ; i++ ) { if ( aoColumns[i].bVisible ) { iBefore = i; break; } } } for ( i=0, iLen=aoData.length ; i<iLen ; i++ ) { if ( aoData[i].nTr !== null ) { if ( bAppend ) { aoData[i].nTr.appendChild( aoData[i]._anHidden[iCol] ); } else { aoData[i].nTr.insertBefore( aoData[i]._anHidden[iCol], _fnGetTdNodes( oSettings, i )[iBefore] ); } } } } else { /* Remove a column from display */ for ( i=0, iLen=aoData.length ; i<iLen ; i++ ) { if ( aoData[i].nTr !== null ) { nTd = _fnGetTdNodes( oSettings, i )[iCol]; aoData[i]._anHidden[iCol] = nTd; nTd.parentNode.removeChild( nTd ); } } } /* Clear to set the visible flag */ aoColumns[iCol].bVisible = bShow; /* Redraw the header and footer based on the new column visibility */ _fnDrawHead( oSettings, oSettings.aoHeader ); if ( oSettings.nTFoot ) { _fnDrawHead( oSettings, oSettings.aoFooter ); } /* If there are any 'open' rows, then we need to alter the colspan for this col change */ for ( i=0, iLen=oSettings.aoOpenRows.length ; i<iLen ; i++ ) { oSettings.aoOpenRows[i].nTr.colSpan = _fnVisbleColumns( oSettings ); } /* Do a redraw incase anything depending on the table columns needs it * (built-in: scrolling) */ if ( bRedraw === undefined || bRedraw ) { _fnAdjustColumnSizing( oSettings ); _fnDraw( oSettings ); } _fnSaveState( oSettings ); }; /** * Get the settings for a particular table for external manipulation * @returns {object} DataTables settings object. See * {@link DataTable.models.oSettings} * @dtopt API * * @example * $(document).ready(function() { * var oTable = $('#example').dataTable(); * var oSettings = oTable.fnSettings(); * * // Show an example parameter from the settings * alert( oSettings._iDisplayStart ); * } ); */ this.fnSettings = function() { return _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); }; /** * Sort the table by a particular column * @param {int} iCol the data index to sort on. Note that this will not match the * 'display index' if you have hidden data entries * @dtopt API * * @example * $(document).ready(function() { * var oTable = $('#example').dataTable(); * * // Sort immediately with columns 0 and 1 * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] ); * } ); */ this.fnSort = function( aaSort ) { var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); oSettings.aaSorting = aaSort; _fnSort( oSettings ); }; /** * Attach a sort listener to an element for a given column * @param {node} nNode the element to attach the sort listener to * @param {int} iColumn the column that a click on this node will sort on * @param {function} [fnCallback] callback function when sort is run * @dtopt API * * @example * $(document).ready(function() { * var oTable = $('#example').dataTable(); * * // Sort on column 1, when 'sorter' is clicked on * oTable.fnSortListener( document.getElementById('sorter'), 1 ); * } ); */ this.fnSortListener = function( nNode, iColumn, fnCallback ) { _fnSortAttachListener( _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ), nNode, iColumn, fnCallback ); }; /** * Update a table cell or row - this method will accept either a single value to * update the cell with, an array of values with one element for each column or * an object in the same format as the original data source. The function is * self-referencing in order to make the multi column updates easier. * @param {object|array|string} mData Data to update the cell/row with * @param {node|int} mRow TR element you want to update or the aoData index * @param {int} [iColumn] The column to update (not used of mData is an array or object) * @param {bool} [bRedraw=true] Redraw the table or not * @param {bool} [bAction=true] Perform pre-draw actions or not * @returns {int} 0 on success, 1 on error * @dtopt API * * @example * $(document).ready(function() { * var oTable = $('#example').dataTable(); * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], 1, 0 ); // Row * } ); */ this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction ) { var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); var i, iLen, sDisplay; var iRow = (typeof mRow === 'object') ? _fnNodeToDataIndex(oSettings, mRow) : mRow; if ( $.isArray(mData) && iColumn === undefined ) { /* Array update - update the whole row */ oSettings.aoData[iRow]._aData = mData.slice(); /* Flag to the function that we are recursing */ for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) { this.fnUpdate( _fnGetCellData( oSettings, iRow, i ), iRow, i, false, false ); } } else if ( $.isPlainObject(mData) && iColumn === undefined ) { /* Object update - update the whole row - assume the developer gets the object right */ oSettings.aoData[iRow]._aData = $.extend( true, {}, mData ); for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) { this.fnUpdate( _fnGetCellData( oSettings, iRow, i ), iRow, i, false, false ); } } else { /* Individual cell update */ _fnSetCellData( oSettings, iRow, iColumn, mData ); sDisplay = _fnGetCellData( oSettings, iRow, iColumn, 'display' ); var oCol = oSettings.aoColumns[iColumn]; if ( oCol.fnRender !== null ) { sDisplay = _fnRender( oSettings, iRow, iColumn ); if ( oCol.bUseRendered ) { _fnSetCellData( oSettings, iRow, iColumn, sDisplay ); } } if ( oSettings.aoData[iRow].nTr !== null ) { /* Do the actual HTML update */ _fnGetTdNodes( oSettings, iRow )[iColumn].innerHTML = sDisplay; } } /* Modify the search index for this row (strictly this is likely not needed, since fnReDraw * will rebuild the search array - however, the redraw might be disabled by the user) */ var iDisplayIndex = $.inArray( iRow, oSettings.aiDisplay ); oSettings.asDataSearch[iDisplayIndex] = _fnBuildSearchRow( oSettings, _fnGetRowData( oSettings, iRow, 'filter', _fnGetColumns( oSettings, 'bSearchable' ) ) ); /* Perform pre-draw actions */ if ( bAction === undefined || bAction ) { _fnAdjustColumnSizing( oSettings ); } /* Redraw the table */ if ( bRedraw === undefined || bRedraw ) { _fnReDraw( oSettings ); } return 0; }; /** * Provide a common method for plug-ins to check the version of DataTables being used, in order * to ensure compatibility. * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the * formats "X" and "X.Y" are also acceptable. * @returns {boolean} true if this version of DataTables is greater or equal to the required * version, or false if this version of DataTales is not suitable * @method * @dtopt API * * @example * $(document).ready(function() { * var oTable = $('#example').dataTable(); * alert( oTable.fnVersionCheck( '1.9.0' ) ); * } ); */ this.fnVersionCheck = DataTable.ext.fnVersionCheck; /* * This is really a good bit rubbish this method of exposing the internal methods * publicly... - To be fixed in 2.0 using methods on the prototype */ /** * Create a wrapper function for exporting an internal functions to an external API. * @param {string} sFunc API function name * @returns {function} wrapped function * @memberof DataTable#oApi */ function _fnExternApiFunc (sFunc) { return function() { var aArgs = [_fnSettingsFromNode(this[DataTable.ext.iApiIndex])].concat( Array.prototype.slice.call(arguments) ); return DataTable.ext.oApi[sFunc].apply( this, aArgs ); }; } /** * Reference to internal functions for use by plug-in developers. Note that these * methods are references to internal functions and are considered to be private. * If you use these methods, be aware that they are liable to change between versions * (check the upgrade notes). * @namespace */ this.oApi = { "_fnExternApiFunc": _fnExternApiFunc, "_fnInitialise": _fnInitialise, "_fnInitComplete": _fnInitComplete, "_fnLanguageCompat": _fnLanguageCompat, "_fnAddColumn": _fnAddColumn, "_fnColumnOptions": _fnColumnOptions, "_fnAddData": _fnAddData, "_fnCreateTr": _fnCreateTr, "_fnGatherData": _fnGatherData, "_fnBuildHead": _fnBuildHead, "_fnDrawHead": _fnDrawHead, "_fnDraw": _fnDraw, "_fnReDraw": _fnReDraw, "_fnAjaxUpdate": _fnAjaxUpdate, "_fnAjaxParameters": _fnAjaxParameters, "_fnAjaxUpdateDraw": _fnAjaxUpdateDraw, "_fnServerParams": _fnServerParams, "_fnAddOptionsHtml": _fnAddOptionsHtml, "_fnFeatureHtmlTable": _fnFeatureHtmlTable, "_fnScrollDraw": _fnScrollDraw, "_fnAdjustColumnSizing": _fnAdjustColumnSizing, "_fnFeatureHtmlFilter": _fnFeatureHtmlFilter, "_fnFilterComplete": _fnFilterComplete, "_fnFilterCustom": _fnFilterCustom, "_fnFilterColumn": _fnFilterColumn, "_fnFilter": _fnFilter, "_fnBuildSearchArray": _fnBuildSearchArray, "_fnBuildSearchRow": _fnBuildSearchRow, "_fnFilterCreateSearch": _fnFilterCreateSearch, "_fnDataToSearch": _fnDataToSearch, "_fnSort": _fnSort, "_fnSortAttachListener": _fnSortAttachListener, "_fnSortingClasses": _fnSortingClasses, "_fnFeatureHtmlPaginate": _fnFeatureHtmlPaginate, "_fnPageChange": _fnPageChange, "_fnFeatureHtmlInfo": _fnFeatureHtmlInfo, "_fnUpdateInfo": _fnUpdateInfo, "_fnFeatureHtmlLength": _fnFeatureHtmlLength, "_fnFeatureHtmlProcessing": _fnFeatureHtmlProcessing, "_fnProcessingDisplay": _fnProcessingDisplay, "_fnVisibleToColumnIndex": _fnVisibleToColumnIndex, "_fnColumnIndexToVisible": _fnColumnIndexToVisible, "_fnNodeToDataIndex": _fnNodeToDataIndex, "_fnVisbleColumns": _fnVisbleColumns, "_fnCalculateEnd": _fnCalculateEnd, "_fnConvertToWidth": _fnConvertToWidth, "_fnCalculateColumnWidths": _fnCalculateColumnWidths, "_fnScrollingWidthAdjust": _fnScrollingWidthAdjust, "_fnGetWidestNode": _fnGetWidestNode, "_fnGetMaxLenString": _fnGetMaxLenString, "_fnStringToCss": _fnStringToCss, "_fnDetectType": _fnDetectType, "_fnSettingsFromNode": _fnSettingsFromNode, "_fnGetDataMaster": _fnGetDataMaster, "_fnGetTrNodes": _fnGetTrNodes, "_fnGetTdNodes": _fnGetTdNodes, "_fnEscapeRegex": _fnEscapeRegex, "_fnDeleteIndex": _fnDeleteIndex, "_fnReOrderIndex": _fnReOrderIndex, "_fnColumnOrdering": _fnColumnOrdering, "_fnLog": _fnLog, "_fnClearTable": _fnClearTable, "_fnSaveState": _fnSaveState, "_fnLoadState": _fnLoadState, "_fnCreateCookie": _fnCreateCookie, "_fnReadCookie": _fnReadCookie, "_fnDetectHeader": _fnDetectHeader, "_fnGetUniqueThs": _fnGetUniqueThs, "_fnScrollBarWidth": _fnScrollBarWidth, "_fnApplyToChildren": _fnApplyToChildren, "_fnMap": _fnMap, "_fnGetRowData": _fnGetRowData, "_fnGetCellData": _fnGetCellData, "_fnSetCellData": _fnSetCellData, "_fnGetObjectDataFn": _fnGetObjectDataFn, "_fnSetObjectDataFn": _fnSetObjectDataFn, "_fnApplyColumnDefs": _fnApplyColumnDefs, "_fnBindAction": _fnBindAction, "_fnExtend": _fnExtend, "_fnCallbackReg": _fnCallbackReg, "_fnCallbackFire": _fnCallbackFire, "_fnJsonString": _fnJsonString, "_fnRender": _fnRender, "_fnNodeToColumnIndex": _fnNodeToColumnIndex, "_fnInfoMacros": _fnInfoMacros, "_fnBrowserDetect": _fnBrowserDetect, "_fnGetColumns": _fnGetColumns }; $.extend( DataTable.ext.oApi, this.oApi ); for ( var sFunc in DataTable.ext.oApi ) { if ( sFunc ) { this[sFunc] = _fnExternApiFunc(sFunc); } } var _that = this; this.each(function() { var i=0, iLen, j, jLen, k, kLen; var sId = this.getAttribute( 'id' ); var bInitHandedOff = false; var bUsePassedData = false; /* Sanity check */ if ( this.nodeName.toLowerCase() != 'table' ) { _fnLog( null, 0, "Attempted to initialise DataTables on a node which is not a "+ "table: "+this.nodeName ); return; } /* Check to see if we are re-initialising a table */ for ( i=0, iLen=DataTable.settings.length ; i<iLen ; i++ ) { /* Base check on table node */ if ( DataTable.settings[i].nTable == this ) { if ( oInit === undefined || oInit.bRetrieve ) { return DataTable.settings[i].oInstance; } else if ( oInit.bDestroy ) { DataTable.settings[i].oInstance.fnDestroy(); break; } else { _fnLog( DataTable.settings[i], 0, "Cannot reinitialise DataTable.\n\n"+ "To retrieve the DataTables object for this table, pass no arguments or see "+ "the docs for bRetrieve and bDestroy" ); return; } } /* If the element we are initialising has the same ID as a table which was previously * initialised, but the table nodes don't match (from before) then we destroy the old * instance by simply deleting it. This is under the assumption that the table has been * destroyed by other methods. Anyone using non-id selectors will need to do this manually */ if ( DataTable.settings[i].sTableId == this.id ) { DataTable.settings.splice( i, 1 ); break; } } /* Ensure the table has an ID - required for accessibility */ if ( sId === null || sId === "" ) { sId = "DataTables_Table_"+(DataTable.ext._oExternConfig.iNextUnique++); this.id = sId; } /* Create the settings object for this table and set some of the default parameters */ var oSettings = $.extend( true, {}, DataTable.models.oSettings, { "nTable": this, "oApi": _that.oApi, "oInit": oInit, "sDestroyWidth": $(this).width(), "sInstance": sId, "sTableId": sId } ); DataTable.settings.push( oSettings ); // Need to add the instance after the instance after the settings object has been added // to the settings array, so we can self reference the table instance if more than one oSettings.oInstance = (_that.length===1) ? _that : $(this).dataTable(); /* Setting up the initialisation object */ if ( !oInit ) { oInit = {}; } // Backwards compatibility, before we apply all the defaults if ( oInit.oLanguage ) { _fnLanguageCompat( oInit.oLanguage ); } oInit = _fnExtend( $.extend(true, {}, DataTable.defaults), oInit ); // Map the initialisation options onto the settings object _fnMap( oSettings.oFeatures, oInit, "bPaginate" ); _fnMap( oSettings.oFeatures, oInit, "bLengthChange" ); _fnMap( oSettings.oFeatures, oInit, "bFilter" ); _fnMap( oSettings.oFeatures, oInit, "bSort" ); _fnMap( oSettings.oFeatures, oInit, "bInfo" ); _fnMap( oSettings.oFeatures, oInit, "bProcessing" ); _fnMap( oSettings.oFeatures, oInit, "bAutoWidth" ); _fnMap( oSettings.oFeatures, oInit, "bSortClasses" ); _fnMap( oSettings.oFeatures, oInit, "bServerSide" ); _fnMap( oSettings.oFeatures, oInit, "bDeferRender" ); _fnMap( oSettings.oScroll, oInit, "sScrollX", "sX" ); _fnMap( oSettings.oScroll, oInit, "sScrollXInner", "sXInner" ); _fnMap( oSettings.oScroll, oInit, "sScrollY", "sY" ); _fnMap( oSettings.oScroll, oInit, "bScrollCollapse", "bCollapse" ); _fnMap( oSettings.oScroll, oInit, "bScrollInfinite", "bInfinite" ); _fnMap( oSettings.oScroll, oInit, "iScrollLoadGap", "iLoadGap" ); _fnMap( oSettings.oScroll, oInit, "bScrollAutoCss", "bAutoCss" ); _fnMap( oSettings, oInit, "asStripeClasses" ); _fnMap( oSettings, oInit, "asStripClasses", "asStripeClasses" ); // legacy _fnMap( oSettings, oInit, "fnServerData" ); _fnMap( oSettings, oInit, "fnFormatNumber" ); _fnMap( oSettings, oInit, "sServerMethod" ); _fnMap( oSettings, oInit, "aaSorting" ); _fnMap( oSettings, oInit, "aaSortingFixed" ); _fnMap( oSettings, oInit, "aLengthMenu" ); _fnMap( oSettings, oInit, "sPaginationType" ); _fnMap( oSettings, oInit, "sAjaxSource" ); _fnMap( oSettings, oInit, "sAjaxDataProp" ); _fnMap( oSettings, oInit, "iCookieDuration" ); _fnMap( oSettings, oInit, "sCookiePrefix" ); _fnMap( oSettings, oInit, "sDom" ); _fnMap( oSettings, oInit, "bSortCellsTop" ); _fnMap( oSettings, oInit, "iTabIndex" ); _fnMap( oSettings, oInit, "oSearch", "oPreviousSearch" ); _fnMap( oSettings, oInit, "aoSearchCols", "aoPreSearchCols" ); _fnMap( oSettings, oInit, "iDisplayLength", "_iDisplayLength" ); _fnMap( oSettings, oInit, "bJQueryUI", "bJUI" ); _fnMap( oSettings, oInit, "fnCookieCallback" ); _fnMap( oSettings, oInit, "fnStateLoad" ); _fnMap( oSettings, oInit, "fnStateSave" ); _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" ); /* Callback functions which are array driven */ _fnCallbackReg( oSettings, 'aoDrawCallback', oInit.fnDrawCallback, 'user' ); _fnCallbackReg( oSettings, 'aoServerParams', oInit.fnServerParams, 'user' ); _fnCallbackReg( oSettings, 'aoStateSaveParams', oInit.fnStateSaveParams, 'user' ); _fnCallbackReg( oSettings, 'aoStateLoadParams', oInit.fnStateLoadParams, 'user' ); _fnCallbackReg( oSettings, 'aoStateLoaded', oInit.fnStateLoaded, 'user' ); _fnCallbackReg( oSettings, 'aoRowCallback', oInit.fnRowCallback, 'user' ); _fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow, 'user' ); _fnCallbackReg( oSettings, 'aoHeaderCallback', oInit.fnHeaderCallback, 'user' ); _fnCallbackReg( oSettings, 'aoFooterCallback', oInit.fnFooterCallback, 'user' ); _fnCallbackReg( oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user' ); _fnCallbackReg( oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user' ); if ( oSettings.oFeatures.bServerSide && oSettings.oFeatures.bSort && oSettings.oFeatures.bSortClasses ) { /* Enable sort classes for server-side processing. Safe to do it here, since server-side * processing must be enabled by the developer */ _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSortingClasses, 'server_side_sort_classes' ); } else if ( oSettings.oFeatures.bDeferRender ) { _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSortingClasses, 'defer_sort_classes' ); } if ( oInit.bJQueryUI ) { /* Use the JUI classes object for display. You could clone the oStdClasses object if * you want to have multiple tables with multiple independent classes */ $.extend( oSettings.oClasses, DataTable.ext.oJUIClasses ); if ( oInit.sDom === DataTable.defaults.sDom && DataTable.defaults.sDom === "lfrtip" ) { /* Set the DOM to use a layout suitable for jQuery UI's theming */ oSettings.sDom = '<"H"lfr>t<"F"ip>'; } } else { $.extend( oSettings.oClasses, DataTable.ext.oStdClasses ); } $(this).addClass( oSettings.oClasses.sTable ); /* Calculate the scroll bar width and cache it for use later on */ if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" ) { oSettings.oScroll.iBarWidth = _fnScrollBarWidth(); } if ( oSettings.iInitDisplayStart === undefined ) { /* Display start point, taking into account the save saving */ oSettings.iInitDisplayStart = oInit.iDisplayStart; oSettings._iDisplayStart = oInit.iDisplayStart; } /* Must be done after everything which can be overridden by a cookie! */ if ( oInit.bStateSave ) { oSettings.oFeatures.bStateSave = true; _fnLoadState( oSettings, oInit ); _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' ); } if ( oInit.iDeferLoading !== null ) { oSettings.bDeferLoading = true; var tmp = $.isArray( oInit.iDeferLoading ); oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading; oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading; } if ( oInit.aaData !== null ) { bUsePassedData = true; } /* Language definitions */ if ( oInit.oLanguage.sUrl !== "" ) { /* Get the language definitions from a file - because this Ajax call makes the language * get async to the remainder of this function we use bInitHandedOff to indicate that * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor */ oSettings.oLanguage.sUrl = oInit.oLanguage.sUrl; $.getJSON( oSettings.oLanguage.sUrl, null, function( json ) { _fnLanguageCompat( json ); $.extend( true, oSettings.oLanguage, oInit.oLanguage, json ); _fnInitialise( oSettings ); } ); bInitHandedOff = true; } else { $.extend( true, oSettings.oLanguage, oInit.oLanguage ); } /* * Stripes */ if ( oInit.asStripeClasses === null ) { oSettings.asStripeClasses =[ oSettings.oClasses.sStripeOdd, oSettings.oClasses.sStripeEven ]; } /* Remove row stripe classes if they are already on the table row */ iLen=oSettings.asStripeClasses.length; oSettings.asDestroyStripes = []; if (iLen) { var bStripeRemove = false; var anRows = $(this).children('tbody').children('tr:lt(' + iLen + ')'); for ( i=0 ; i<iLen ; i++ ) { if ( anRows.hasClass( oSettings.asStripeClasses[i] ) ) { bStripeRemove = true; /* Store the classes which we are about to remove so they can be re-added on destroy */ oSettings.asDestroyStripes.push( oSettings.asStripeClasses[i] ); } } if ( bStripeRemove ) { anRows.removeClass( oSettings.asStripeClasses.join(' ') ); } } /* * Columns * See if we should load columns automatically or use defined ones */ var anThs = []; var aoColumnsInit; var nThead = this.getElementsByTagName('thead'); if ( nThead.length !== 0 ) { _fnDetectHeader( oSettings.aoHeader, nThead[0] ); anThs = _fnGetUniqueThs( oSettings ); } /* If not given a column array, generate one with nulls */ if ( oInit.aoColumns === null ) { aoColumnsInit = []; for ( i=0, iLen=anThs.length ; i<iLen ; i++ ) { aoColumnsInit.push( null ); } } else { aoColumnsInit = oInit.aoColumns; } /* Add the columns */ for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ ) { /* Short cut - use the loop to check if we have column visibility state to restore */ if ( oInit.saved_aoColumns !== undefined && oInit.saved_aoColumns.length == iLen ) { if ( aoColumnsInit[i] === null ) { aoColumnsInit[i] = {}; } aoColumnsInit[i].bVisible = oInit.saved_aoColumns[i].bVisible; } _fnAddColumn( oSettings, anThs ? anThs[i] : null ); } /* Apply the column definitions */ _fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) { _fnColumnOptions( oSettings, iCol, oDef ); } ); /* * Sorting * Check the aaSorting array */ for ( i=0, iLen=oSettings.aaSorting.length ; i<iLen ; i++ ) { if ( oSettings.aaSorting[i][0] >= oSettings.aoColumns.length ) { oSettings.aaSorting[i][0] = 0; } var oColumn = oSettings.aoColumns[ oSettings.aaSorting[i][0] ]; /* Add a default sorting index */ if ( oSettings.aaSorting[i][2] === undefined ) { oSettings.aaSorting[i][2] = 0; } /* If aaSorting is not defined, then we use the first indicator in asSorting */ if ( oInit.aaSorting === undefined && oSettings.saved_aaSorting === undefined ) { oSettings.aaSorting[i][1] = oColumn.asSorting[0]; } /* Set the current sorting index based on aoColumns.asSorting */ for ( j=0, jLen=oColumn.asSorting.length ; j<jLen ; j++ ) { if ( oSettings.aaSorting[i][1] == oColumn.asSorting[j] ) { oSettings.aaSorting[i][2] = j; break; } } } /* Do a first pass on the sorting classes (allows any size changes to be taken into * account, and also will apply sorting disabled classes if disabled */ _fnSortingClasses( oSettings ); /* * Final init * Cache the header, body and footer as required, creating them if needed */ /* Browser support detection */ _fnBrowserDetect( oSettings ); // Work around for Webkit bug 83867 - store the caption-side before removing from doc var captions = $(this).children('caption').each( function () { this._captionSide = $(this).css('caption-side'); } ); var thead = $(this).children('thead'); if ( thead.length === 0 ) { thead = [ document.createElement( 'thead' ) ]; this.appendChild( thead[0] ); } oSettings.nTHead = thead[0]; var tbody = $(this).children('tbody'); if ( tbody.length === 0 ) { tbody = [ document.createElement( 'tbody' ) ]; this.appendChild( tbody[0] ); } oSettings.nTBody = tbody[0]; oSettings.nTBody.setAttribute( "role", "alert" ); oSettings.nTBody.setAttribute( "aria-live", "polite" ); oSettings.nTBody.setAttribute( "aria-relevant", "all" ); var tfoot = $(this).children('tfoot'); if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) { // If we are a scrolling table, and no footer has been given, then we need to create // a tfoot element for the caption element to be appended to tfoot = [ document.createElement( 'tfoot' ) ]; this.appendChild( tfoot[0] ); } if ( tfoot.length > 0 ) { oSettings.nTFoot = tfoot[0]; _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot ); } /* Check if there is data passing into the constructor */ if ( bUsePassedData ) { for ( i=0 ; i<oInit.aaData.length ; i++ ) { _fnAddData( oSettings, oInit.aaData[ i ] ); } } else { /* Grab the data from the page */ _fnGatherData( oSettings ); } /* Copy the data index array */ oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); /* Initialisation complete - table can be drawn */ oSettings.bInitialised = true; /* Check if we need to initialise the table (it might not have been handed off to the * language processor) */ if ( bInitHandedOff === false ) { _fnInitialise( oSettings ); } } ); _that = null; return this; }; /** * Provide a common method for plug-ins to check the version of DataTables being used, in order * to ensure compatibility. * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the * formats "X" and "X.Y" are also acceptable. * @returns {boolean} true if this version of DataTables is greater or equal to the required * version, or false if this version of DataTales is not suitable * @static * @dtopt API-Static * * @example * alert( $.fn.dataTable.fnVersionCheck( '1.9.0' ) ); */ DataTable.fnVersionCheck = function( sVersion ) { /* This is cheap, but effective */ var fnZPad = function (Zpad, count) { while(Zpad.length < count) { Zpad += '0'; } return Zpad; }; var aThis = DataTable.ext.sVersion.split('.'); var aThat = sVersion.split('.'); var sThis = '', sThat = ''; for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) { sThis += fnZPad( aThis[i], 3 ); sThat += fnZPad( aThat[i], 3 ); } return parseInt(sThis, 10) >= parseInt(sThat, 10); }; /** * Check if a TABLE node is a DataTable table already or not. * @param {node} nTable The TABLE node to check if it is a DataTable or not (note that other * node types can be passed in, but will always return false). * @returns {boolean} true the table given is a DataTable, or false otherwise * @static * @dtopt API-Static * * @example * var ex = document.getElementById('example'); * if ( ! $.fn.DataTable.fnIsDataTable( ex ) ) { * $(ex).dataTable(); * } */ DataTable.fnIsDataTable = function ( nTable ) { var o = DataTable.settings; for ( var i=0 ; i<o.length ; i++ ) { if ( o[i].nTable === nTable || o[i].nScrollHead === nTable || o[i].nScrollFoot === nTable ) { return true; } } return false; }; /** * Get all DataTable tables that have been initialised - optionally you can select to * get only currently visible tables. * @param {boolean} [bVisible=false] Flag to indicate if you want all (default) or * visible tables only. * @returns {array} Array of TABLE nodes (not DataTable instances) which are DataTables * @static * @dtopt API-Static * * @example * var table = $.fn.dataTable.fnTables(true); * if ( table.length > 0 ) { * $(table).dataTable().fnAdjustColumnSizing(); * } */ DataTable.fnTables = function ( bVisible ) { var out = []; jQuery.each( DataTable.settings, function (i, o) { if ( !bVisible || (bVisible === true && $(o.nTable).is(':visible')) ) { out.push( o.nTable ); } } ); return out; }; /** * Version string for plug-ins to check compatibility. Allowed format is * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and * e are optional * @member * @type string * @default Version number */ DataTable.version = "1.9.4"; /** * Private data store, containing all of the settings objects that are created for the * tables on a given page. * * Note that the <i>DataTable.settings</i> object is aliased to <i>jQuery.fn.dataTableExt</i> * through which it may be accessed and manipulated, or <i>jQuery.fn.dataTable.settings</i>. * @member * @type array * @default [] * @private */ DataTable.settings = []; /** * Object models container, for the various models that DataTables has available * to it. These models define the objects that are used to hold the active state * and configuration of the table. * @namespace */ DataTable.models = {}; /** * DataTables extension options and plug-ins. This namespace acts as a collection "area" * for plug-ins that can be used to extend the default DataTables behaviour - indeed many * of the build in methods use this method to provide their own capabilities (sorting methods * for example). * * Note that this namespace is aliased to jQuery.fn.dataTableExt so it can be readily accessed * and modified by plug-ins. * @namespace */ DataTable.models.ext = { /** * Plug-in filtering functions - this method of filtering is complimentary to the default * type based filtering, and a lot more comprehensive as it allows you complete control * over the filtering logic. Each element in this array is a function (parameters * described below) that is called for every row in the table, and your logic decides if * it should be included in the filtered data set or not. * <ul> * <li> * Function input parameters: * <ul> * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li> * <li>{array|object} Data for the row to be processed (same as the original format * that was passed in as the data source, or an array from a DOM data source</li> * <li>{int} Row index in aoData ({@link DataTable.models.oSettings.aoData}), which can * be useful to retrieve the TR element if you need DOM interaction.</li> * </ul> * </li> * <li> * Function return: * <ul> * <li>{boolean} Include the row in the filtered result set (true) or not (false)</li> * </ul> * </il> * </ul> * @type array * @default [] * * @example * // The following example shows custom filtering being applied to the fourth column (i.e. * // the aData[3] index) based on two input values from the end-user, matching the data in * // a certain range. * $.fn.dataTableExt.afnFiltering.push( * function( oSettings, aData, iDataIndex ) { * var iMin = document.getElementById('min').value * 1; * var iMax = document.getElementById('max').value * 1; * var iVersion = aData[3] == "-" ? 0 : aData[3]*1; * if ( iMin == "" && iMax == "" ) { * return true; * } * else if ( iMin == "" && iVersion < iMax ) { * return true; * } * else if ( iMin < iVersion && "" == iMax ) { * return true; * } * else if ( iMin < iVersion && iVersion < iMax ) { * return true; * } * return false; * } * ); */ "afnFiltering": [], /** * Plug-in sorting functions - this method of sorting is complimentary to the default type * based sorting that DataTables does automatically, allowing much greater control over the * the data that is being used to sort a column. This is useful if you want to do sorting * based on live data (for example the contents of an 'input' element) rather than just the * static string that DataTables knows of. The way these plug-ins work is that you create * an array of the values you wish to be sorted for the column in question and then return * that array. Which pre-sorting function is run here depends on the sSortDataType parameter * that is used for the column (if any). This is the corollary of <i>ofnSearch</i> for sort * data. * <ul> * <li> * Function input parameters: * <ul> * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li> * <li>{int} Target column index</li> * </ul> * </li> * <li> * Function return: * <ul> * <li>{array} Data for the column to be sorted upon</li> * </ul> * </il> * </ul> * * Note that as of v1.9, it is typically preferable to use <i>mData</i> to prepare data for * the different uses that DataTables can put the data to. Specifically <i>mData</i> when * used as a function will give you a 'type' (sorting, filtering etc) that you can use to * prepare the data as required for the different types. As such, this method is deprecated. * @type array * @default [] * @deprecated * * @example * // Updating the cached sorting information with user entered values in HTML input elements * jQuery.fn.dataTableExt.afnSortData['dom-text'] = function ( oSettings, iColumn ) * { * var aData = []; * $( 'td:eq('+iColumn+') input', oSettings.oApi._fnGetTrNodes(oSettings) ).each( function () { * aData.push( this.value ); * } ); * return aData; * } */ "afnSortData": [], /** * Feature plug-ins - This is an array of objects which describe the feature plug-ins that are * available to DataTables. These feature plug-ins are accessible through the sDom initialisation * option. As such, each feature plug-in must describe a function that is used to initialise * itself (fnInit), a character so the feature can be enabled by sDom (cFeature) and the name * of the feature (sFeature). Thus the objects attached to this method must provide: * <ul> * <li>{function} fnInit Initialisation of the plug-in * <ul> * <li> * Function input parameters: * <ul> * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li> * </ul> * </li> * <li> * Function return: * <ul> * <li>{node|null} The element which contains your feature. Note that the return * may also be void if your plug-in does not require to inject any DOM elements * into DataTables control (sDom) - for example this might be useful when * developing a plug-in which allows table control via keyboard entry.</li> * </ul> * </il> * </ul> * </li> * <li>{character} cFeature Character that will be matched in sDom - case sensitive</li> * <li>{string} sFeature Feature name</li> * </ul> * @type array * @default [] * * @example * // How TableTools initialises itself. * $.fn.dataTableExt.aoFeatures.push( { * "fnInit": function( oSettings ) { * return new TableTools( { "oDTSettings": oSettings } ); * }, * "cFeature": "T", * "sFeature": "TableTools" * } ); */ "aoFeatures": [], /** * Type detection plug-in functions - DataTables utilises types to define how sorting and * filtering behave, and types can be either be defined by the developer (sType for the * column) or they can be automatically detected by the methods in this array. The functions * defined in the array are quite simple, taking a single parameter (the data to analyse) * and returning the type if it is a known type, or null otherwise. * <ul> * <li> * Function input parameters: * <ul> * <li>{*} Data from the column cell to be analysed</li> * </ul> * </li> * <li> * Function return: * <ul> * <li>{string|null} Data type detected, or null if unknown (and thus pass it * on to the other type detection functions.</li> * </ul> * </il> * </ul> * @type array * @default [] * * @example * // Currency type detection plug-in: * jQuery.fn.dataTableExt.aTypes.push( * function ( sData ) { * var sValidChars = "0123456789.-"; * var Char; * * // Check the numeric part * for ( i=1 ; i<sData.length ; i++ ) { * Char = sData.charAt(i); * if (sValidChars.indexOf(Char) == -1) { * return null; * } * } * * // Check prefixed by currency * if ( sData.charAt(0) == '$' || sData.charAt(0) == '£' ) { * return 'currency'; * } * return null; * } * ); */ "aTypes": [], /** * Provide a common method for plug-ins to check the version of DataTables being used, * in order to ensure compatibility. * @type function * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note * that the formats "X" and "X.Y" are also acceptable. * @returns {boolean} true if this version of DataTables is greater or equal to the * required version, or false if this version of DataTales is not suitable * * @example * $(document).ready(function() { * var oTable = $('#example').dataTable(); * alert( oTable.fnVersionCheck( '1.9.0' ) ); * } ); */ "fnVersionCheck": DataTable.fnVersionCheck, /** * Index for what 'this' index API functions should use * @type int * @default 0 */ "iApiIndex": 0, /** * Pre-processing of filtering data plug-ins - When you assign the sType for a column * (or have it automatically detected for you by DataTables or a type detection plug-in), * you will typically be using this for custom sorting, but it can also be used to provide * custom filtering by allowing you to pre-processing the data and returning the data in * the format that should be filtered upon. This is done by adding functions this object * with a parameter name which matches the sType for that target column. This is the * corollary of <i>afnSortData</i> for filtering data. * <ul> * <li> * Function input parameters: * <ul> * <li>{*} Data from the column cell to be prepared for filtering</li> * </ul> * </li> * <li> * Function return: * <ul> * <li>{string|null} Formatted string that will be used for the filtering.</li> * </ul> * </il> * </ul> * * Note that as of v1.9, it is typically preferable to use <i>mData</i> to prepare data for * the different uses that DataTables can put the data to. Specifically <i>mData</i> when * used as a function will give you a 'type' (sorting, filtering etc) that you can use to * prepare the data as required for the different types. As such, this method is deprecated. * @type object * @default {} * @deprecated * * @example * $.fn.dataTableExt.ofnSearch['title-numeric'] = function ( sData ) { * return sData.replace(/\n/g," ").replace( /<.*?>/g, "" ); * } */ "ofnSearch": {}, /** * Container for all private functions in DataTables so they can be exposed externally * @type object * @default {} */ "oApi": {}, /** * Storage for the various classes that DataTables uses * @type object * @default {} */ "oStdClasses": {}, /** * Storage for the various classes that DataTables uses - jQuery UI suitable * @type object * @default {} */ "oJUIClasses": {}, /** * Pagination plug-in methods - The style and controls of the pagination can significantly * impact on how the end user interacts with the data in your table, and DataTables allows * the addition of pagination controls by extending this object, which can then be enabled * through the <i>sPaginationType</i> initialisation parameter. Each pagination type that * is added is an object (the property name of which is what <i>sPaginationType</i> refers * to) that has two properties, both methods that are used by DataTables to update the * control's state. * <ul> * <li> * fnInit - Initialisation of the paging controls. Called only during initialisation * of the table. It is expected that this function will add the required DOM elements * to the page for the paging controls to work. The element pointer * 'oSettings.aanFeatures.p' array is provided by DataTables to contain the paging * controls (note that this is a 2D array to allow for multiple instances of each * DataTables DOM element). It is suggested that you add the controls to this element * as children * <ul> * <li> * Function input parameters: * <ul> * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li> * <li>{node} Container into which the pagination controls must be inserted</li> * <li>{function} Draw callback function - whenever the controls cause a page * change, this method must be called to redraw the table.</li> * </ul> * </li> * <li> * Function return: * <ul> * <li>No return required</li> * </ul> * </il> * </ul> * </il> * <li> * fnInit - This function is called whenever the paging status of the table changes and is * typically used to update classes and/or text of the paging controls to reflex the new * status. * <ul> * <li> * Function input parameters: * <ul> * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li> * <li>{function} Draw callback function - in case you need to redraw the table again * or attach new event listeners</li> * </ul> * </li> * <li> * Function return: * <ul> * <li>No return required</li> * </ul> * </il> * </ul> * </il> * </ul> * @type object * @default {} * * @example * $.fn.dataTableExt.oPagination.four_button = { * "fnInit": function ( oSettings, nPaging, fnCallbackDraw ) { * nFirst = document.createElement( 'span' ); * nPrevious = document.createElement( 'span' ); * nNext = document.createElement( 'span' ); * nLast = document.createElement( 'span' ); * * nFirst.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sFirst ) ); * nPrevious.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sPrevious ) ); * nNext.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sNext ) ); * nLast.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sLast ) ); * * nFirst.className = "paginate_button first"; * nPrevious.className = "paginate_button previous"; * nNext.className="paginate_button next"; * nLast.className = "paginate_button last"; * * nPaging.appendChild( nFirst ); * nPaging.appendChild( nPrevious ); * nPaging.appendChild( nNext ); * nPaging.appendChild( nLast ); * * $(nFirst).click( function () { * oSettings.oApi._fnPageChange( oSettings, "first" ); * fnCallbackDraw( oSettings ); * } ); * * $(nPrevious).click( function() { * oSettings.oApi._fnPageChange( oSettings, "previous" ); * fnCallbackDraw( oSettings ); * } ); * * $(nNext).click( function() { * oSettings.oApi._fnPageChange( oSettings, "next" ); * fnCallbackDraw( oSettings ); * } ); * * $(nLast).click( function() { * oSettings.oApi._fnPageChange( oSettings, "last" ); * fnCallbackDraw( oSettings ); * } ); * * $(nFirst).bind( 'selectstart', function () { return false; } ); * $(nPrevious).bind( 'selectstart', function () { return false; } ); * $(nNext).bind( 'selectstart', function () { return false; } ); * $(nLast).bind( 'selectstart', function () { return false; } ); * }, * * "fnUpdate": function ( oSettings, fnCallbackDraw ) { * if ( !oSettings.aanFeatures.p ) { * return; * } * * // Loop over each instance of the pager * var an = oSettings.aanFeatures.p; * for ( var i=0, iLen=an.length ; i<iLen ; i++ ) { * var buttons = an[i].getElementsByTagName('span'); * if ( oSettings._iDisplayStart === 0 ) { * buttons[0].className = "paginate_disabled_previous"; * buttons[1].className = "paginate_disabled_previous"; * } * else { * buttons[0].className = "paginate_enabled_previous"; * buttons[1].className = "paginate_enabled_previous"; * } * * if ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) { * buttons[2].className = "paginate_disabled_next"; * buttons[3].className = "paginate_disabled_next"; * } * else { * buttons[2].className = "paginate_enabled_next"; * buttons[3].className = "paginate_enabled_next"; * } * } * } * }; */ "oPagination": {}, /** * Sorting plug-in methods - Sorting in DataTables is based on the detected type of the * data column (you can add your own type detection functions, or override automatic * detection using sType). With this specific type given to the column, DataTables will * apply the required sort from the functions in the object. Each sort type must provide * two mandatory methods, one each for ascending and descending sorting, and can optionally * provide a pre-formatting method that will help speed up sorting by allowing DataTables * to pre-format the sort data only once (rather than every time the actual sort functions * are run). The two sorting functions are typical Javascript sort methods: * <ul> * <li> * Function input parameters: * <ul> * <li>{*} Data to compare to the second parameter</li> * <li>{*} Data to compare to the first parameter</li> * </ul> * </li> * <li> * Function return: * <ul> * <li>{int} Sorting match: <0 if first parameter should be sorted lower than * the second parameter, ===0 if the two parameters are equal and >0 if * the first parameter should be sorted height than the second parameter.</li> * </ul> * </il> * </ul> * @type object * @default {} * * @example * // Case-sensitive string sorting, with no pre-formatting method * $.extend( $.fn.dataTableExt.oSort, { * "string-case-asc": function(x,y) { * return ((x < y) ? -1 : ((x > y) ? 1 : 0)); * }, * "string-case-desc": function(x,y) { * return ((x < y) ? 1 : ((x > y) ? -1 : 0)); * } * } ); * * @example * // Case-insensitive string sorting, with pre-formatting * $.extend( $.fn.dataTableExt.oSort, { * "string-pre": function(x) { * return x.toLowerCase(); * }, * "string-asc": function(x,y) { * return ((x < y) ? -1 : ((x > y) ? 1 : 0)); * }, * "string-desc": function(x,y) { * return ((x < y) ? 1 : ((x > y) ? -1 : 0)); * } * } ); */ "oSort": {}, /** * Version string for plug-ins to check compatibility. Allowed format is * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and * e are optional * @type string * @default Version number */ "sVersion": DataTable.version, /** * How should DataTables report an error. Can take the value 'alert' or 'throw' * @type string * @default alert */ "sErrMode": "alert", /** * Store information for DataTables to access globally about other instances * @namespace * @private */ "_oExternConfig": { /* int:iNextUnique - next unique number for an instance */ "iNextUnique": 0 } }; /** * Template object for the way in which DataTables holds information about * search information for the global filter and individual column filters. * @namespace */ DataTable.models.oSearch = { /** * Flag to indicate if the filtering should be case insensitive or not * @type boolean * @default true */ "bCaseInsensitive": true, /** * Applied search term * @type string * @default <i>Empty string</i> */ "sSearch": "", /** * Flag to indicate if the search term should be interpreted as a * regular expression (true) or not (false) and therefore and special * regex characters escaped. * @type boolean * @default false */ "bRegex": false, /** * Flag to indicate if DataTables is to use its smart filtering or not. * @type boolean * @default true */ "bSmart": true }; /** * Template object for the way in which DataTables holds information about * each individual row. This is the object format used for the settings * aoData array. * @namespace */ DataTable.models.oRow = { /** * TR element for the row * @type node * @default null */ "nTr": null, /** * Data object from the original data source for the row. This is either * an array if using the traditional form of DataTables, or an object if * using mData options. The exact type will depend on the passed in * data from the data source, or will be an array if using DOM a data * source. * @type array|object * @default [] */ "_aData": [], /** * Sorting data cache - this array is ostensibly the same length as the * number of columns (although each index is generated only as it is * needed), and holds the data that is used for sorting each column in the * row. We do this cache generation at the start of the sort in order that * the formatting of the sort data need be done only once for each cell * per sort. This array should not be read from or written to by anything * other than the master sorting methods. * @type array * @default [] * @private */ "_aSortData": [], /** * Array of TD elements that are cached for hidden rows, so they can be * reinserted into the table if a column is made visible again (or to act * as a store if a column is made hidden). Only hidden columns have a * reference in the array. For non-hidden columns the value is either * undefined or null. * @type array nodes * @default [] * @private */ "_anHidden": [], /** * Cache of the class name that DataTables has applied to the row, so we * can quickly look at this variable rather than needing to do a DOM check * on className for the nTr property. * @type string * @default <i>Empty string</i> * @private */ "_sRowStripe": "" }; /** * Template object for the column information object in DataTables. This object * is held in the settings aoColumns array and contains all the information that * DataTables needs about each individual column. * * Note that this object is related to {@link DataTable.defaults.columns} * but this one is the internal data store for DataTables's cache of columns. * It should NOT be manipulated outside of DataTables. Any configuration should * be done through the initialisation options. * @namespace */ DataTable.models.oColumn = { /** * A list of the columns that sorting should occur on when this column * is sorted. That this property is an array allows multi-column sorting * to be defined for a column (for example first name / last name columns * would benefit from this). The values are integers pointing to the * columns to be sorted on (typically it will be a single integer pointing * at itself, but that doesn't need to be the case). * @type array */ "aDataSort": null, /** * Define the sorting directions that are applied to the column, in sequence * as the column is repeatedly sorted upon - i.e. the first value is used * as the sorting direction when the column if first sorted (clicked on). * Sort it again (click again) and it will move on to the next index. * Repeat until loop. * @type array */ "asSorting": null, /** * Flag to indicate if the column is searchable, and thus should be included * in the filtering or not. * @type boolean */ "bSearchable": null, /** * Flag to indicate if the column is sortable or not. * @type boolean */ "bSortable": null, /** * <code>Deprecated</code> When using fnRender, you have two options for what * to do with the data, and this property serves as the switch. Firstly, you * can have the sorting and filtering use the rendered value (true - default), * or you can have the sorting and filtering us the original value (false). * * Please note that this option has now been deprecated and will be removed * in the next version of DataTables. Please use mRender / mData rather than * fnRender. * @type boolean * @deprecated */ "bUseRendered": null, /** * Flag to indicate if the column is currently visible in the table or not * @type boolean */ "bVisible": null, /** * Flag to indicate to the type detection method if the automatic type * detection should be used, or if a column type (sType) has been specified * @type boolean * @default true * @private */ "_bAutoType": true, /** * Developer definable function that is called whenever a cell is created (Ajax source, * etc) or processed for input (DOM source). This can be used as a compliment to mRender * allowing you to modify the DOM element (add background colour for example) when the * element is available. * @type function * @param {element} nTd The TD node that has been created * @param {*} sData The Data for the cell * @param {array|object} oData The data for the whole row * @param {int} iRow The row index for the aoData data store * @default null */ "fnCreatedCell": null, /** * Function to get data from a cell in a column. You should <b>never</b> * access data directly through _aData internally in DataTables - always use * the method attached to this property. It allows mData to function as * required. This function is automatically assigned by the column * initialisation method * @type function * @param {array|object} oData The data array/object for the array * (i.e. aoData[]._aData) * @param {string} sSpecific The specific data type you want to get - * 'display', 'type' 'filter' 'sort' * @returns {*} The data for the cell from the given row's data * @default null */ "fnGetData": null, /** * <code>Deprecated</code> Custom display function that will be called for the * display of each cell in this column. * * Please note that this option has now been deprecated and will be removed * in the next version of DataTables. Please use mRender / mData rather than * fnRender. * @type function * @param {object} o Object with the following parameters: * @param {int} o.iDataRow The row in aoData * @param {int} o.iDataColumn The column in question * @param {array} o.aData The data for the row in question * @param {object} o.oSettings The settings object for this DataTables instance * @returns {string} The string you which to use in the display * @default null * @deprecated */ "fnRender": null, /** * Function to set data for a cell in the column. You should <b>never</b> * set the data directly to _aData internally in DataTables - always use * this method. It allows mData to function as required. This function * is automatically assigned by the column initialisation method * @type function * @param {array|object} oData The data array/object for the array * (i.e. aoData[]._aData) * @param {*} sValue Value to set * @default null */ "fnSetData": null, /** * Property to read the value for the cells in the column from the data * source array / object. If null, then the default content is used, if a * function is given then the return from the function is used. * @type function|int|string|null * @default null */ "mData": null, /** * Partner property to mData which is used (only when defined) to get * the data - i.e. it is basically the same as mData, but without the * 'set' option, and also the data fed to it is the result from mData. * This is the rendering method to match the data method of mData. * @type function|int|string|null * @default null */ "mRender": null, /** * Unique header TH/TD element for this column - this is what the sorting * listener is attached to (if sorting is enabled.) * @type node * @default null */ "nTh": null, /** * Unique footer TH/TD element for this column (if there is one). Not used * in DataTables as such, but can be used for plug-ins to reference the * footer for each column. * @type node * @default null */ "nTf": null, /** * The class to apply to all TD elements in the table's TBODY for the column * @type string * @default null */ "sClass": null, /** * When DataTables calculates the column widths to assign to each column, * it finds the longest string in each column and then constructs a * temporary table and reads the widths from that. The problem with this * is that "mmm" is much wider then "iiii", but the latter is a longer * string - thus the calculation can go wrong (doing it properly and putting * it into an DOM object and measuring that is horribly(!) slow). Thus as * a "work around" we provide this option. It will append its value to the * text that is found to be the longest string for the column - i.e. padding. * @type string */ "sContentPadding": null, /** * Allows a default value to be given for a column's data, and will be used * whenever a null data source is encountered (this can be because mData * is set to null, or because the data source itself is null). * @type string * @default null */ "sDefaultContent": null, /** * Name for the column, allowing reference to the column by name as well as * by index (needs a lookup to work by name). * @type string */ "sName": null, /** * Custom sorting data type - defines which of the available plug-ins in * afnSortData the custom sorting will use - if any is defined. * @type string * @default std */ "sSortDataType": 'std', /** * Class to be applied to the header element when sorting on this column * @type string * @default null */ "sSortingClass": null, /** * Class to be applied to the header element when sorting on this column - * when jQuery UI theming is used. * @type string * @default null */ "sSortingClassJUI": null, /** * Title of the column - what is seen in the TH element (nTh). * @type string */ "sTitle": null, /** * Column sorting and filtering type * @type string * @default null */ "sType": null, /** * Width of the column * @type string * @default null */ "sWidth": null, /** * Width of the column when it was first "encountered" * @type string * @default null */ "sWidthOrig": null }; /** * Initialisation options that can be given to DataTables at initialisation * time. * @namespace */ DataTable.defaults = { /** * An array of data to use for the table, passed in at initialisation which * will be used in preference to any data which is already in the DOM. This is * particularly useful for constructing tables purely in Javascript, for * example with a custom Ajax call. * @type array * @default null * @dtopt Option * * @example * // Using a 2D array data source * $(document).ready( function () { * $('#example').dataTable( { * "aaData": [ * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'], * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'], * ], * "aoColumns": [ * { "sTitle": "Engine" }, * { "sTitle": "Browser" }, * { "sTitle": "Platform" }, * { "sTitle": "Version" }, * { "sTitle": "Grade" } * ] * } ); * } ); * * @example * // Using an array of objects as a data source (mData) * $(document).ready( function () { * $('#example').dataTable( { * "aaData": [ * { * "engine": "Trident", * "browser": "Internet Explorer 4.0", * "platform": "Win 95+", * "version": 4, * "grade": "X" * }, * { * "engine": "Trident", * "browser": "Internet Explorer 5.0", * "platform": "Win 95+", * "version": 5, * "grade": "C" * } * ], * "aoColumns": [ * { "sTitle": "Engine", "mData": "engine" }, * { "sTitle": "Browser", "mData": "browser" }, * { "sTitle": "Platform", "mData": "platform" }, * { "sTitle": "Version", "mData": "version" }, * { "sTitle": "Grade", "mData": "grade" } * ] * } ); * } ); */ "aaData": null, /** * If sorting is enabled, then DataTables will perform a first pass sort on * initialisation. You can define which column(s) the sort is performed upon, * and the sorting direction, with this variable. The aaSorting array should * contain an array for each column to be sorted initially containing the * column's index and a direction string ('asc' or 'desc'). * @type array * @default [[0,'asc']] * @dtopt Option * * @example * // Sort by 3rd column first, and then 4th column * $(document).ready( function() { * $('#example').dataTable( { * "aaSorting": [[2,'asc'], [3,'desc']] * } ); * } ); * * // No initial sorting * $(document).ready( function() { * $('#example').dataTable( { * "aaSorting": [] * } ); * } ); */ "aaSorting": [[0,'asc']], /** * This parameter is basically identical to the aaSorting parameter, but * cannot be overridden by user interaction with the table. What this means * is that you could have a column (visible or hidden) which the sorting will * always be forced on first - any sorting after that (from the user) will * then be performed as required. This can be useful for grouping rows * together. * @type array * @default null * @dtopt Option * * @example * $(document).ready( function() { * $('#example').dataTable( { * "aaSortingFixed": [[0,'asc']] * } ); * } ) */ "aaSortingFixed": null, /** * This parameter allows you to readily specify the entries in the length drop * down menu that DataTables shows when pagination is enabled. It can be * either a 1D array of options which will be used for both the displayed * option and the value, or a 2D array which will use the array in the first * position as the value, and the array in the second position as the * displayed options (useful for language strings such as 'All'). * @type array * @default [ 10, 25, 50, 100 ] * @dtopt Option * * @example * $(document).ready( function() { * $('#example').dataTable( { * "aLengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]] * } ); * } ); * * @example * // Setting the default display length as well as length menu * // This is likely to be wanted if you remove the '10' option which * // is the iDisplayLength default. * $(document).ready( function() { * $('#example').dataTable( { * "iDisplayLength": 25, * "aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]] * } ); * } ); */ "aLengthMenu": [ 10, 25, 50, 100 ], /** * The aoColumns option in the initialisation parameter allows you to define * details about the way individual columns behave. For a full list of * column options that can be set, please see * {@link DataTable.defaults.columns}. Note that if you use aoColumns to * define your columns, you must have an entry in the array for every single * column that you have in your table (these can be null if you don't which * to specify any options). * @member */ "aoColumns": null, /** * Very similar to aoColumns, aoColumnDefs allows you to target a specific * column, multiple columns, or all columns, using the aTargets property of * each object in the array. This allows great flexibility when creating * tables, as the aoColumnDefs arrays can be of any length, targeting the * columns you specifically want. aoColumnDefs may use any of the column * options available: {@link DataTable.defaults.columns}, but it _must_ * have aTargets defined in each object in the array. Values in the aTargets * array may be: * <ul> * <li>a string - class name will be matched on the TH for the column</li> * <li>0 or a positive integer - column index counting from the left</li> * <li>a negative integer - column index counting from the right</li> * <li>the string "_all" - all columns (i.e. assign a default)</li> * </ul> * @member */ "aoColumnDefs": null, /** * Basically the same as oSearch, this parameter defines the individual column * filtering state at initialisation time. The array must be of the same size * as the number of columns, and each element be an object with the parameters * "sSearch" and "bEscapeRegex" (the latter is optional). 'null' is also * accepted and the default will be used. * @type array * @default [] * @dtopt Option * * @example * $(document).ready( function() { * $('#example').dataTable( { * "aoSearchCols": [ * null, * { "sSearch": "My filter" }, * null, * { "sSearch": "^[0-9]", "bEscapeRegex": false } * ] * } ); * } ) */ "aoSearchCols": [], /** * An array of CSS classes that should be applied to displayed rows. This * array may be of any length, and DataTables will apply each class * sequentially, looping when required. * @type array * @default null <i>Will take the values determined by the oClasses.sStripe* * options</i> * @dtopt Option * * @example * $(document).ready( function() { * $('#example').dataTable( { * "asStripeClasses": [ 'strip1', 'strip2', 'strip3' ] * } ); * } ) */ "asStripeClasses": null, /** * Enable or disable automatic column width calculation. This can be disabled * as an optimisation (it takes some time to calculate the widths) if the * tables widths are passed in using aoColumns. * @type boolean * @default true * @dtopt Features * * @example * $(document).ready( function () { * $('#example').dataTable( { * "bAutoWidth": false * } ); * } ); */ "bAutoWidth": true, /** * Deferred rendering can provide DataTables with a huge speed boost when you * are using an Ajax or JS data source for the table. This option, when set to * true, will cause DataTables to defer the creation of the table elements for * each row until they are needed for a draw - saving a significant amount of * time. * @type boolean * @default false * @dtopt Features * * @example * $(document).ready( function() { * var oTable = $('#example').dataTable( { * "sAjaxSource": "sources/arrays.txt", * "bDeferRender": true * } ); * } ); */ "bDeferRender": false, /** * Replace a DataTable which matches the given selector and replace it with * one which has the properties of the new initialisation object passed. If no * table matches the selector, then the new DataTable will be constructed as * per normal. * @type boolean * @default false * @dtopt Options * * @example * $(document).ready( function() { * $('#example').dataTable( { * "sScrollY": "200px", * "bPaginate": false * } ); * * // Some time later.... * $('#example').dataTable( { * "bFilter": false, * "bDestroy": true * } ); * } ); */ "bDestroy": false, /** * Enable or disable filtering of data. Filtering in DataTables is "smart" in * that it allows the end user to input multiple words (space separated) and * will match a row containing those words, even if not in the order that was * specified (this allow matching across multiple columns). Note that if you * wish to use filtering in DataTables this must remain 'true' - to remove the * default filtering input box and retain filtering abilities, please use * {@link DataTable.defaults.sDom}. * @type boolean * @default true * @dtopt Features * * @example * $(document).ready( function () { * $('#example').dataTable( { * "bFilter": false * } ); * } ); */ "bFilter": true, /** * Enable or disable the table information display. This shows information * about the data that is currently visible on the page, including information * about filtered data if that action is being performed. * @type boolean * @default true * @dtopt Features * * @example * $(document).ready( function () { * $('#example').dataTable( { * "bInfo": false * } ); * } ); */ "bInfo": true, /** * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some * slightly different and additional mark-up from what DataTables has * traditionally used). * @type boolean * @default false * @dtopt Features * * @example * $(document).ready( function() { * $('#example').dataTable( { * "bJQueryUI": true * } ); * } ); */ "bJQueryUI": false, /** * Allows the end user to select the size of a formatted page from a select * menu (sizes are 10, 25, 50 and 100). Requires pagination (bPaginate). * @type boolean * @default true * @dtopt Features * * @example * $(document).ready( function () { * $('#example').dataTable( { * "bLengthChange": false * } ); * } ); */ "bLengthChange": true, /** * Enable or disable pagination. * @type boolean * @default true * @dtopt Features * * @example * $(document).ready( function () { * $('#example').dataTable( { * "bPaginate": false * } ); * } ); */ "bPaginate": true, /** * Enable or disable the display of a 'processing' indicator when the table is * being processed (e.g. a sort). This is particularly useful for tables with * large amounts of data where it can take a noticeable amount of time to sort * the entries. * @type boolean * @default false * @dtopt Features * * @example * $(document).ready( function () { * $('#example').dataTable( { * "bProcessing": true * } ); * } ); */ "bProcessing": false, /** * Retrieve the DataTables object for the given selector. Note that if the * table has already been initialised, this parameter will cause DataTables * to simply return the object that has already been set up - it will not take * account of any changes you might have made to the initialisation object * passed to DataTables (setting this parameter to true is an acknowledgement * that you understand this). bDestroy can be used to reinitialise a table if * you need. * @type boolean * @default false * @dtopt Options * * @example * $(document).ready( function() { * initTable(); * tableActions(); * } ); * * function initTable () * { * return $('#example').dataTable( { * "sScrollY": "200px", * "bPaginate": false, * "bRetrieve": true * } ); * } * * function tableActions () * { * var oTable = initTable(); * // perform API operations with oTable * } */ "bRetrieve": false, /** * Indicate if DataTables should be allowed to set the padding / margin * etc for the scrolling header elements or not. Typically you will want * this. * @type boolean * @default true * @dtopt Options * * @example * $(document).ready( function() { * $('#example').dataTable( { * "bScrollAutoCss": false, * "sScrollY": "200px" * } ); * } ); */ "bScrollAutoCss": true, /** * When vertical (y) scrolling is enabled, DataTables will force the height of * the table's viewport to the given height at all times (useful for layout). * However, this can look odd when filtering data down to a small data set, * and the footer is left "floating" further down. This parameter (when * enabled) will cause DataTables to collapse the table's viewport down when * the result set will fit within the given Y height. * @type boolean * @default false * @dtopt Options * * @example * $(document).ready( function() { * $('#example').dataTable( { * "sScrollY": "200", * "bScrollCollapse": true * } ); * } ); */ "bScrollCollapse": false, /** * Enable infinite scrolling for DataTables (to be used in combination with * sScrollY). Infinite scrolling means that DataTables will continually load * data as a user scrolls through a table, which is very useful for large * dataset. This cannot be used with pagination, which is automatically * disabled. Note - the Scroller extra for DataTables is recommended in * in preference to this option. * @type boolean * @default false * @dtopt Features * * @example * $(document).ready( function() { * $('#example').dataTable( { * "bScrollInfinite": true, * "bScrollCollapse": true, * "sScrollY": "200px" * } ); * } ); */ "bScrollInfinite": false, /** * Configure DataTables to use server-side processing. Note that the * sAjaxSource parameter must also be given in order to give DataTables a * source to obtain the required data for each draw. * @type boolean * @default false * @dtopt Features * @dtopt Server-side * * @example * $(document).ready( function () { * $('#example').dataTable( { * "bServerSide": true, * "sAjaxSource": "xhr.php" * } ); * } ); */ "bServerSide": false, /** * Enable or disable sorting of columns. Sorting of individual columns can be * disabled by the "bSortable" option for each column. * @type boolean * @default true * @dtopt Features * * @example * $(document).ready( function () { * $('#example').dataTable( { * "bSort": false * } ); * } ); */ "bSort": true, /** * Allows control over whether DataTables should use the top (true) unique * cell that is found for a single column, or the bottom (false - default). * This is useful when using complex headers. * @type boolean * @default false * @dtopt Options * * @example * $(document).ready( function() { * $('#example').dataTable( { * "bSortCellsTop": true * } ); * } ); */ "bSortCellsTop": false, /** * Enable or disable the addition of the classes 'sorting_1', 'sorting_2' and * 'sorting_3' to the columns which are currently being sorted on. This is * presented as a feature switch as it can increase processing time (while * classes are removed and added) so for large data sets you might want to * turn this off. * @type boolean * @default true * @dtopt Features * * @example * $(document).ready( function () { * $('#example').dataTable( { * "bSortClasses": false * } ); * } ); */ "bSortClasses": true, /** * Enable or disable state saving. When enabled a cookie will be used to save * table display information such as pagination information, display length, * filtering and sorting. As such when the end user reloads the page the * display display will match what thy had previously set up. * @type boolean * @default false * @dtopt Features * * @example * $(document).ready( function () { * $('#example').dataTable( { * "bStateSave": true * } ); * } ); */ "bStateSave": false, /** * Customise the cookie and / or the parameters being stored when using * DataTables with state saving enabled. This function is called whenever * the cookie is modified, and it expects a fully formed cookie string to be * returned. Note that the data object passed in is a Javascript object which * must be converted to a string (JSON.stringify for example). * @type function * @param {string} sName Name of the cookie defined by DataTables * @param {object} oData Data to be stored in the cookie * @param {string} sExpires Cookie expires string * @param {string} sPath Path of the cookie to set * @returns {string} Cookie formatted string (which should be encoded by * using encodeURIComponent()) * @dtopt Callbacks * * @example * $(document).ready( function () { * $('#example').dataTable( { * "fnCookieCallback": function (sName, oData, sExpires, sPath) { * // Customise oData or sName or whatever else here * return sName + "="+JSON.stringify(oData)+"; expires=" + sExpires +"; path=" + sPath; * } * } ); * } ); */ "fnCookieCallback": null, /** * This function is called when a TR element is created (and all TD child * elements have been inserted), or registered if using a DOM source, allowing * manipulation of the TR element (adding classes etc). * @type function * @param {node} nRow "TR" element for the current row * @param {array} aData Raw data array for this row * @param {int} iDataIndex The index of this row in aoData * @dtopt Callbacks * * @example * $(document).ready( function() { * $('#example').dataTable( { * "fnCreatedRow": function( nRow, aData, iDataIndex ) { * // Bold the grade for all 'A' grade browsers * if ( aData[4] == "A" ) * { * $('td:eq(4)', nRow).html( '<b>A</b>' ); * } * } * } ); * } ); */ "fnCreatedRow": null, /** * This function is called on every 'draw' event, and allows you to * dynamically modify any aspect you want about the created DOM. * @type function * @param {object} oSettings DataTables settings object * @dtopt Callbacks * * @example * $(document).ready( function() { * $('#example').dataTable( { * "fnDrawCallback": function( oSettings ) { * alert( 'DataTables has redrawn the table' ); * } * } ); * } ); */ "fnDrawCallback": null, /** * Identical to fnHeaderCallback() but for the table footer this function * allows you to modify the table footer on every 'draw' even. * @type function * @param {node} nFoot "TR" element for the footer * @param {array} aData Full table data (as derived from the original HTML) * @param {int} iStart Index for the current display starting point in the * display array * @param {int} iEnd Index for the current display ending point in the * display array * @param {array int} aiDisplay Index array to translate the visual position * to the full data array * @dtopt Callbacks * * @example * $(document).ready( function() { * $('#example').dataTable( { * "fnFooterCallback": function( nFoot, aData, iStart, iEnd, aiDisplay ) { * nFoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+iStart; * } * } ); * } ) */ "fnFooterCallback": null, /** * When rendering large numbers in the information element for the table * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers * to have a comma separator for the 'thousands' units (e.g. 1 million is * rendered as "1,000,000") to help readability for the end user. This * function will override the default method DataTables uses. * @type function * @member * @param {int} iIn number to be formatted * @returns {string} formatted string for DataTables to show the number * @dtopt Callbacks * * @example * $(document).ready( function() { * $('#example').dataTable( { * "fnFormatNumber": function ( iIn ) { * if ( iIn < 1000 ) { * return iIn; * } else { * var * s=(iIn+""), * a=s.split(""), out="", * iLen=s.length; * * for ( var i=0 ; i<iLen ; i++ ) { * if ( i%3 === 0 && i !== 0 ) { * out = "'"+out; * } * out = a[iLen-i-1]+out; * } * } * return out; * }; * } ); * } ); */ "fnFormatNumber": function ( iIn ) { if ( iIn < 1000 ) { // A small optimisation for what is likely to be the majority of use cases return iIn; } var s=(iIn+""), a=s.split(""), out="", iLen=s.length; for ( var i=0 ; i<iLen ; i++ ) { if ( i%3 === 0 && i !== 0 ) { out = this.oLanguage.sInfoThousands+out; } out = a[iLen-i-1]+out; } return out; }, /** * This function is called on every 'draw' event, and allows you to * dynamically modify the header row. This can be used to calculate and * display useful information about the table. * @type function * @param {node} nHead "TR" element for the header * @param {array} aData Full table data (as derived from the original HTML) * @param {int} iStart Index for the current display starting point in the * display array * @param {int} iEnd Index for the current display ending point in the * display array * @param {array int} aiDisplay Index array to translate the visual position * to the full data array * @dtopt Callbacks * * @example * $(document).ready( function() { * $('#example').dataTable( { * "fnHeaderCallback": function( nHead, aData, iStart, iEnd, aiDisplay ) { * nHead.getElementsByTagName('th')[0].innerHTML = "Displaying "+(iEnd-iStart)+" records"; * } * } ); * } ) */ "fnHeaderCallback": null, /** * The information element can be used to convey information about the current * state of the table. Although the internationalisation options presented by * DataTables are quite capable of dealing with most customisations, there may * be times where you wish to customise the string further. This callback * allows you to do exactly that. * @type function * @param {object} oSettings DataTables settings object * @param {int} iStart Starting position in data for the draw * @param {int} iEnd End position in data for the draw * @param {int} iMax Total number of rows in the table (regardless of * filtering) * @param {int} iTotal Total number of rows in the data set, after filtering * @param {string} sPre The string that DataTables has formatted using it's * own rules * @returns {string} The string to be displayed in the information element. * @dtopt Callbacks * * @example * $('#example').dataTable( { * "fnInfoCallback": function( oSettings, iStart, iEnd, iMax, iTotal, sPre ) { * return iStart +" to "+ iEnd; * } * } ); */ "fnInfoCallback": null, /** * Called when the table has been initialised. Normally DataTables will * initialise sequentially and there will be no need for this function, * however, this does not hold true when using external language information * since that is obtained using an async XHR call. * @type function * @param {object} oSettings DataTables settings object * @param {object} json The JSON object request from the server - only * present if client-side Ajax sourced data is used * @dtopt Callbacks * * @example * $(document).ready( function() { * $('#example').dataTable( { * "fnInitComplete": function(oSettings, json) { * alert( 'DataTables has finished its initialisation.' ); * } * } ); * } ) */ "fnInitComplete": null, /** * Called at the very start of each table draw and can be used to cancel the * draw by returning false, any other return (including undefined) results in * the full draw occurring). * @type function * @param {object} oSettings DataTables settings object * @returns {boolean} False will cancel the draw, anything else (including no * return) will allow it to complete. * @dtopt Callbacks * * @example * $(document).ready( function() { * $('#example').dataTable( { * "fnPreDrawCallback": function( oSettings ) { * if ( $('#test').val() == 1 ) { * return false; * } * } * } ); * } ); */ "fnPreDrawCallback": null, /** * This function allows you to 'post process' each row after it have been * generated for each table draw, but before it is rendered on screen. This * function might be used for setting the row class name etc. * @type function * @param {node} nRow "TR" element for the current row * @param {array} aData Raw data array for this row * @param {int} iDisplayIndex The display index for the current table draw * @param {int} iDisplayIndexFull The index of the data in the full list of * rows (after filtering) * @dtopt Callbacks * * @example * $(document).ready( function() { * $('#example').dataTable( { * "fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) { * // Bold the grade for all 'A' grade browsers * if ( aData[4] == "A" ) * { * $('td:eq(4)', nRow).html( '<b>A</b>' ); * } * } * } ); * } ); */ "fnRowCallback": null, /** * This parameter allows you to override the default function which obtains * the data from the server ($.getJSON) so something more suitable for your * application. For example you could use POST data, or pull information from * a Gears or AIR database. * @type function * @member * @param {string} sSource HTTP source to obtain the data from (sAjaxSource) * @param {array} aoData A key/value pair object containing the data to send * to the server * @param {function} fnCallback to be called on completion of the data get * process that will draw the data on the page. * @param {object} oSettings DataTables settings object * @dtopt Callbacks * @dtopt Server-side * * @example * // POST data to server * $(document).ready( function() { * $('#example').dataTable( { * "bProcessing": true, * "bServerSide": true, * "sAjaxSource": "xhr.php", * "fnServerData": function ( sSource, aoData, fnCallback, oSettings ) { * oSettings.jqXHR = $.ajax( { * "dataType": 'json', * "type": "POST", * "url": sSource, * "data": aoData, * "success": fnCallback * } ); * } * } ); * } ); */ "fnServerData": function ( sUrl, aoData, fnCallback, oSettings ) { oSettings.jqXHR = $.ajax( { "url": sUrl, "data": aoData, "success": function (json) { if ( json.sError ) { oSettings.oApi._fnLog( oSettings, 0, json.sError ); } $(oSettings.oInstance).trigger('xhr', [oSettings, json]); fnCallback( json ); }, "dataType": "json", "cache": false, "type": oSettings.sServerMethod, "error": function (xhr, error, thrown) { if ( error == "parsererror" ) { oSettings.oApi._fnLog( oSettings, 0, "DataTables warning: JSON data from "+ "server could not be parsed. This is caused by a JSON formatting error." ); } } } ); }, /** * It is often useful to send extra data to the server when making an Ajax * request - for example custom filtering information, and this callback * function makes it trivial to send extra information to the server. The * passed in parameter is the data set that has been constructed by * DataTables, and you can add to this or modify it as you require. * @type function * @param {array} aoData Data array (array of objects which are name/value * pairs) that has been constructed by DataTables and will be sent to the * server. In the case of Ajax sourced data with server-side processing * this will be an empty array, for server-side processing there will be a * significant number of parameters! * @returns {undefined} Ensure that you modify the aoData array passed in, * as this is passed by reference. * @dtopt Callbacks * @dtopt Server-side * * @example * $(document).ready( function() { * $('#example').dataTable( { * "bProcessing": true, * "bServerSide": true, * "sAjaxSource": "scripts/server_processing.php", * "fnServerParams": function ( aoData ) { * aoData.push( { "name": "more_data", "value": "my_value" } ); * } * } ); * } ); */ "fnServerParams": null, /** * Load the table state. With this function you can define from where, and how, the * state of a table is loaded. By default DataTables will load from its state saving * cookie, but you might wish to use local storage (HTML5) or a server-side database. * @type function * @member * @param {object} oSettings DataTables settings object * @return {object} The DataTables state object to be loaded * @dtopt Callbacks * * @example * $(document).ready( function() { * $('#example').dataTable( { * "bStateSave": true, * "fnStateLoad": function (oSettings) { * var o; * * // Send an Ajax request to the server to get the data. Note that * // this is a synchronous request. * $.ajax( { * "url": "/state_load", * "async": false, * "dataType": "json", * "success": function (json) { * o = json; * } * } ); * * return o; * } * } ); * } ); */ "fnStateLoad": function ( oSettings ) { var sData = this.oApi._fnReadCookie( oSettings.sCookiePrefix+oSettings.sInstance ); var oData; try { oData = (typeof $.parseJSON === 'function') ? $.parseJSON(sData) : eval( '('+sData+')' ); } catch (e) { oData = null; } return oData; }, /** * Callback which allows modification of the saved state prior to loading that state. * This callback is called when the table is loading state from the stored data, but * prior to the settings object being modified by the saved state. Note that for * plug-in authors, you should use the 'stateLoadParams' event to load parameters for * a plug-in. * @type function * @param {object} oSettings DataTables settings object * @param {object} oData The state object that is to be loaded * @dtopt Callbacks * * @example * // Remove a saved filter, so filtering is never loaded * $(document).ready( function() { * $('#example').dataTable( { * "bStateSave": true, * "fnStateLoadParams": function (oSettings, oData) { * oData.oSearch.sSearch = ""; * } * } ); * } ); * * @example * // Disallow state loading by returning false * $(document).ready( function() { * $('#example').dataTable( { * "bStateSave": true, * "fnStateLoadParams": function (oSettings, oData) { * return false; * } * } ); * } ); */ "fnStateLoadParams": null, /** * Callback that is called when the state has been loaded from the state saving method * and the DataTables settings object has been modified as a result of the loaded state. * @type function * @param {object} oSettings DataTables settings object * @param {object} oData The state object that was loaded * @dtopt Callbacks * * @example * // Show an alert with the filtering value that was saved * $(document).ready( function() { * $('#example').dataTable( { * "bStateSave": true, * "fnStateLoaded": function (oSettings, oData) { * alert( 'Saved filter was: '+oData.oSearch.sSearch ); * } * } ); * } ); */ "fnStateLoaded": null, /** * Save the table state. This function allows you to define where and how the state * information for the table is stored - by default it will use a cookie, but you * might want to use local storage (HTML5) or a server-side database. * @type function * @member * @param {object} oSettings DataTables settings object * @param {object} oData The state object to be saved * @dtopt Callbacks * * @example * $(document).ready( function() { * $('#example').dataTable( { * "bStateSave": true, * "fnStateSave": function (oSettings, oData) { * // Send an Ajax request to the server with the state object * $.ajax( { * "url": "/state_save", * "data": oData, * "dataType": "json", * "method": "POST" * "success": function () {} * } ); * } * } ); * } ); */ "fnStateSave": function ( oSettings, oData ) { this.oApi._fnCreateCookie( oSettings.sCookiePrefix+oSettings.sInstance, this.oApi._fnJsonString(oData), oSettings.iCookieDuration, oSettings.sCookiePrefix, oSettings.fnCookieCallback ); }, /** * Callback which allows modification of the state to be saved. Called when the table * has changed state a new state save is required. This method allows modification of * the state saving object prior to actually doing the save, including addition or * other state properties or modification. Note that for plug-in authors, you should * use the 'stateSaveParams' event to save parameters for a plug-in. * @type function * @param {object} oSettings DataTables settings object * @param {object} oData The state object to be saved * @dtopt Callbacks * * @example * // Remove a saved filter, so filtering is never saved * $(document).ready( function() { * $('#example').dataTable( { * "bStateSave": true, * "fnStateSaveParams": function (oSettings, oData) { * oData.oSearch.sSearch = ""; * } * } ); * } ); */ "fnStateSaveParams": null, /** * Duration of the cookie which is used for storing session information. This * value is given in seconds. * @type int * @default 7200 <i>(2 hours)</i> * @dtopt Options * * @example * $(document).ready( function() { * $('#example').dataTable( { * "iCookieDuration": 60*60*24; // 1 day * } ); * } ) */ "iCookieDuration": 7200, /** * When enabled DataTables will not make a request to the server for the first * page draw - rather it will use the data already on the page (no sorting etc * will be applied to it), thus saving on an XHR at load time. iDeferLoading * is used to indicate that deferred loading is required, but it is also used * to tell DataTables how many records there are in the full table (allowing * the information element and pagination to be displayed correctly). In the case * where a filtering is applied to the table on initial load, this can be * indicated by giving the parameter as an array, where the first element is * the number of records available after filtering and the second element is the * number of records without filtering (allowing the table information element * to be shown correctly). * @type int | array * @default null * @dtopt Options * * @example * // 57 records available in the table, no filtering applied * $(document).ready( function() { * $('#example').dataTable( { * "bServerSide": true, * "sAjaxSource": "scripts/server_processing.php", * "iDeferLoading": 57 * } ); * } ); * * @example * // 57 records after filtering, 100 without filtering (an initial filter applied) * $(document).ready( function() { * $('#example').dataTable( { * "bServerSide": true, * "sAjaxSource": "scripts/server_processing.php", * "iDeferLoading": [ 57, 100 ], * "oSearch": { * "sSearch": "my_filter" * } * } ); * } ); */ "iDeferLoading": null, /** * Number of rows to display on a single page when using pagination. If * feature enabled (bLengthChange) then the end user will be able to override * this to a custom setting using a pop-up menu. * @type int * @default 10 * @dtopt Options * * @example * $(document).ready( function() { * $('#example').dataTable( { * "iDisplayLength": 50 * } ); * } ) */ "iDisplayLength": 10, /** * Define the starting point for data display when using DataTables with * pagination. Note that this parameter is the number of records, rather than * the page number, so if you have 10 records per page and want to start on * the third page, it should be "20". * @type int * @default 0 * @dtopt Options * * @example * $(document).ready( function() { * $('#example').dataTable( { * "iDisplayStart": 20 * } ); * } ) */ "iDisplayStart": 0, /** * The scroll gap is the amount of scrolling that is left to go before * DataTables will load the next 'page' of data automatically. You typically * want a gap which is big enough that the scrolling will be smooth for the * user, while not so large that it will load more data than need. * @type int * @default 100 * @dtopt Options * * @example * $(document).ready( function() { * $('#example').dataTable( { * "bScrollInfinite": true, * "bScrollCollapse": true, * "sScrollY": "200px", * "iScrollLoadGap": 50 * } ); * } ); */ "iScrollLoadGap": 100, /** * By default DataTables allows keyboard navigation of the table (sorting, paging, * and filtering) by adding a tabindex attribute to the required elements. This * allows you to tab through the controls and press the enter key to activate them. * The tabindex is default 0, meaning that the tab follows the flow of the document. * You can overrule this using this parameter if you wish. Use a value of -1 to * disable built-in keyboard navigation. * @type int * @default 0 * @dtopt Options * * @example * $(document).ready( function() { * $('#example').dataTable( { * "iTabIndex": 1 * } ); * } ); */ "iTabIndex": 0, /** * All strings that DataTables uses in the user interface that it creates * are defined in this object, allowing you to modified them individually or * completely replace them all as required. * @namespace */ "oLanguage": { /** * Strings that are used for WAI-ARIA labels and controls only (these are not * actually visible on the page, but will be read by screenreaders, and thus * must be internationalised as well). * @namespace */ "oAria": { /** * ARIA label that is added to the table headers when the column may be * sorted ascending by activing the column (click or return when focused). * Note that the column header is prefixed to this string. * @type string * @default : activate to sort column ascending * @dtopt Language * * @example * $(document).ready( function() { * $('#example').dataTable( { * "oLanguage": { * "oAria": { * "sSortAscending": " - click/return to sort ascending" * } * } * } ); * } ); */ "sSortAscending": ": activate to sort column ascending", /** * ARIA label that is added to the table headers when the column may be * sorted descending by activing the column (click or return when focused). * Note that the column header is prefixed to this string. * @type string * @default : activate to sort column ascending * @dtopt Language * * @example * $(document).ready( function() { * $('#example').dataTable( { * "oLanguage": { * "oAria": { * "sSortDescending": " - click/return to sort descending" * } * } * } ); * } ); */ "sSortDescending": ": activate to sort column descending" }, /** * Pagination string used by DataTables for the two built-in pagination * control types ("two_button" and "full_numbers") * @namespace */ "oPaginate": { /** * Text to use when using the 'full_numbers' type of pagination for the * button to take the user to the first page. * @type string * @default First * @dtopt Language * * @example * $(document).ready( function() { * $('#example').dataTable( { * "oLanguage": { * "oPaginate": { * "sFirst": "First page" * } * } * } ); * } ); */ "sFirst": "First", /** * Text to use when using the 'full_numbers' type of pagination for the * button to take the user to the last page. * @type string * @default Last * @dtopt Language * * @example * $(document).ready( function() { * $('#example').dataTable( { * "oLanguage": { * "oPaginate": { * "sLast": "Last page" * } * } * } ); * } ); */ "sLast": "Last", /** * Text to use for the 'next' pagination button (to take the user to the * next page). * @type string * @default Next * @dtopt Language * * @example * $(document).ready( function() { * $('#example').dataTable( { * "oLanguage": { * "oPaginate": { * "sNext": "Next page" * } * } * } ); * } ); */ "sNext": "Next", /** * Text to use for the 'previous' pagination button (to take the user to * the previous page). * @type string * @default Previous * @dtopt Language * * @example * $(document).ready( function() { * $('#example').dataTable( { * "oLanguage": { * "oPaginate": { * "sPrevious": "Previous page" * } * } * } ); * } ); */ "sPrevious": "Previous" }, /** * This string is shown in preference to sZeroRecords when the table is * empty of data (regardless of filtering). Note that this is an optional * parameter - if it is not given, the value of sZeroRecords will be used * instead (either the default or given value). * @type string * @default No data available in table * @dtopt Language * * @example * $(document).ready( function() { * $('#example').dataTable( { * "oLanguage": { * "sEmptyTable": "No data available in table" * } * } ); * } ); */ "sEmptyTable": "No data available in table", /** * This string gives information to the end user about the information that * is current on display on the page. The _START_, _END_ and _TOTAL_ * variables are all dynamically replaced as the table display updates, and * can be freely moved or removed as the language requirements change. * @type string * @default Showing _START_ to _END_ of _TOTAL_ entries * @dtopt Language * * @example * $(document).ready( function() { * $('#example').dataTable( { * "oLanguage": { * "sInfo": "Got a total of _TOTAL_ entries to show (_START_ to _END_)" * } * } ); * } ); */ "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries", /** * Display information string for when the table is empty. Typically the * format of this string should match sInfo. * @type string * @default Showing 0 to 0 of 0 entries * @dtopt Language * * @example * $(document).ready( function() { * $('#example').dataTable( { * "oLanguage": { * "sInfoEmpty": "No entries to show" * } * } ); * } ); */ "sInfoEmpty": "Showing 0 to 0 of 0 entries", /** * When a user filters the information in a table, this string is appended * to the information (sInfo) to give an idea of how strong the filtering * is. The variable _MAX_ is dynamically updated. * @type string * @default (filtered from _MAX_ total entries) * @dtopt Language * * @example * $(document).ready( function() { * $('#example').dataTable( { * "oLanguage": { * "sInfoFiltered": " - filtering from _MAX_ records" * } * } ); * } ); */ "sInfoFiltered": "(filtered from _MAX_ total entries)", /** * If can be useful to append extra information to the info string at times, * and this variable does exactly that. This information will be appended to * the sInfo (sInfoEmpty and sInfoFiltered in whatever combination they are * being used) at all times. * @type string * @default <i>Empty string</i> * @dtopt Language * * @example * $(document).ready( function() { * $('#example').dataTable( { * "oLanguage": { * "sInfoPostFix": "All records shown are derived from real information." * } * } ); * } ); */ "sInfoPostFix": "", /** * DataTables has a build in number formatter (fnFormatNumber) which is used * to format large numbers that are used in the table information. By * default a comma is used, but this can be trivially changed to any * character you wish with this parameter. * @type string * @default , * @dtopt Language * * @example * $(document).ready( function() { * $('#example').dataTable( { * "oLanguage": { * "sInfoThousands": "'" * } * } ); * } ); */ "sInfoThousands": ",", /** * Detail the action that will be taken when the drop down menu for the * pagination length option is changed. The '_MENU_' variable is replaced * with a default select list of 10, 25, 50 and 100, and can be replaced * with a custom select box if required. * @type string * @default Show _MENU_ entries * @dtopt Language * * @example * // Language change only * $(document).ready( function() { * $('#example').dataTable( { * "oLanguage": { * "sLengthMenu": "Display _MENU_ records" * } * } ); * } ); * * @example * // Language and options change * $(document).ready( function() { * $('#example').dataTable( { * "oLanguage": { * "sLengthMenu": 'Display <select>'+ * '<option value="10">10</option>'+ * '<option value="20">20</option>'+ * '<option value="30">30</option>'+ * '<option value="40">40</option>'+ * '<option value="50">50</option>'+ * '<option value="-1">All</option>'+ * '</select> records' * } * } ); * } ); */ "sLengthMenu": "Show _MENU_ entries", /** * When using Ajax sourced data and during the first draw when DataTables is * gathering the data, this message is shown in an empty row in the table to * indicate to the end user the the data is being loaded. Note that this * parameter is not used when loading data by server-side processing, just * Ajax sourced data with client-side processing. * @type string * @default Loading... * @dtopt Language * * @example * $(document).ready( function() { * $('#example').dataTable( { * "oLanguage": { * "sLoadingRecords": "Please wait - loading..." * } * } ); * } ); */ "sLoadingRecords": "Loading...", /** * Text which is displayed when the table is processing a user action * (usually a sort command or similar). * @type string * @default Processing... * @dtopt Language * * @example * $(document).ready( function() { * $('#example').dataTable( { * "oLanguage": { * "sProcessing": "DataTables is currently busy" * } * } ); * } ); */ "sProcessing": "Processing...", /** * Details the actions that will be taken when the user types into the * filtering input text box. The variable "_INPUT_", if used in the string, * is replaced with the HTML text box for the filtering input allowing * control over where it appears in the string. If "_INPUT_" is not given * then the input box is appended to the string automatically. * @type string * @default Search: * @dtopt Language * * @example * // Input text box will be appended at the end automatically * $(document).ready( function() { * $('#example').dataTable( { * "oLanguage": { * "sSearch": "Filter records:" * } * } ); * } ); * * @example * // Specify where the filter should appear * $(document).ready( function() { * $('#example').dataTable( { * "oLanguage": { * "sSearch": "Apply filter _INPUT_ to table" * } * } ); * } ); */ "sSearch": "Search:", /** * All of the language information can be stored in a file on the * server-side, which DataTables will look up if this parameter is passed. * It must store the URL of the language file, which is in a JSON format, * and the object has the same properties as the oLanguage object in the * initialiser object (i.e. the above parameters). Please refer to one of * the example language files to see how this works in action. * @type string * @default <i>Empty string - i.e. disabled</i> * @dtopt Language * * @example * $(document).ready( function() { * $('#example').dataTable( { * "oLanguage": { * "sUrl": "http://www.sprymedia.co.uk/dataTables/lang.txt" * } * } ); * } ); */ "sUrl": "", /** * Text shown inside the table records when the is no information to be * displayed after filtering. sEmptyTable is shown when there is simply no * information in the table at all (regardless of filtering). * @type string * @default No matching records found * @dtopt Language * * @example * $(document).ready( function() { * $('#example').dataTable( { * "oLanguage": { * "sZeroRecords": "No records to display" * } * } ); * } ); */ "sZeroRecords": "No matching records found" }, /** * This parameter allows you to have define the global filtering state at * initialisation time. As an object the "sSearch" parameter must be * defined, but all other parameters are optional. When "bRegex" is true, * the search string will be treated as a regular expression, when false * (default) it will be treated as a straight string. When "bSmart" * DataTables will use it's smart filtering methods (to word match at * any point in the data), when false this will not be done. * @namespace * @extends DataTable.models.oSearch * @dtopt Options * * @example * $(document).ready( function() { * $('#example').dataTable( { * "oSearch": {"sSearch": "Initial search"} * } ); * } ) */ "oSearch": $.extend( {}, DataTable.models.oSearch ), /** * By default DataTables will look for the property 'aaData' when obtaining * data from an Ajax source or for server-side processing - this parameter * allows that property to be changed. You can use Javascript dotted object * notation to get a data source for multiple levels of nesting. * @type string * @default aaData * @dtopt Options * @dtopt Server-side * * @example * // Get data from { "data": [...] } * $(document).ready( function() { * var oTable = $('#example').dataTable( { * "sAjaxSource": "sources/data.txt", * "sAjaxDataProp": "data" * } ); * } ); * * @example * // Get data from { "data": { "inner": [...] } } * $(document).ready( function() { * var oTable = $('#example').dataTable( { * "sAjaxSource": "sources/data.txt", * "sAjaxDataProp": "data.inner" * } ); * } ); */ "sAjaxDataProp": "aaData", /** * You can instruct DataTables to load data from an external source using this * parameter (use aData if you want to pass data in you already have). Simply * provide a url a JSON object can be obtained from. This object must include * the parameter 'aaData' which is the data source for the table. * @type string * @default null * @dtopt Options * @dtopt Server-side * * @example * $(document).ready( function() { * $('#example').dataTable( { * "sAjaxSource": "http://www.sprymedia.co.uk/dataTables/json.php" * } ); * } ) */ "sAjaxSource": null, /** * This parameter can be used to override the default prefix that DataTables * assigns to a cookie when state saving is enabled. * @type string * @default SpryMedia_DataTables_ * @dtopt Options * * @example * $(document).ready( function() { * $('#example').dataTable( { * "sCookiePrefix": "my_datatable_", * } ); * } ); */ "sCookiePrefix": "SpryMedia_DataTables_", /** * This initialisation variable allows you to specify exactly where in the * DOM you want DataTables to inject the various controls it adds to the page * (for example you might want the pagination controls at the top of the * table). DIV elements (with or without a custom class) can also be added to * aid styling. The follow syntax is used: * <ul> * <li>The following options are allowed: * <ul> * <li>'l' - Length changing</li * <li>'f' - Filtering input</li> * <li>'t' - The table!</li> * <li>'i' - Information</li> * <li>'p' - Pagination</li> * <li>'r' - pRocessing</li> * </ul> * </li> * <li>The following constants are allowed: * <ul> * <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li> * <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li> * </ul> * </li> * <li>The following syntax is expected: * <ul> * <li>'<' and '>' - div elements</li> * <li>'<"class" and '>' - div with a class</li> * <li>'<"#id" and '>' - div with an ID</li> * </ul> * </li> * <li>Examples: * <ul> * <li>'<"wrapper"flipt>'</li> * <li>'<lf<t>ip>'</li> * </ul> * </li> * </ul> * @type string * @default lfrtip <i>(when bJQueryUI is false)</i> <b>or</b> * <"H"lfr>t<"F"ip> <i>(when bJQueryUI is true)</i> * @dtopt Options * * @example * $(document).ready( function() { * $('#example').dataTable( { * "sDom": '<"top"i>rt<"bottom"flp><"clear">' * } ); * } ); */ "sDom": "lfrtip", /** * DataTables features two different built-in pagination interaction methods * ('two_button' or 'full_numbers') which present different page controls to * the end user. Further methods can be added using the API (see below). * @type string * @default two_button * @dtopt Options * * @example * $(document).ready( function() { * $('#example').dataTable( { * "sPaginationType": "full_numbers" * } ); * } ) */ "sPaginationType": "two_button", /** * Enable horizontal scrolling. When a table is too wide to fit into a certain * layout, or you have a large number of columns in the table, you can enable * x-scrolling to show the table in a viewport, which can be scrolled. This * property can be any CSS unit, or a number (in which case it will be treated * as a pixel measurement). * @type string * @default <i>blank string - i.e. disabled</i> * @dtopt Features * * @example * $(document).ready( function() { * $('#example').dataTable( { * "sScrollX": "100%", * "bScrollCollapse": true * } ); * } ); */ "sScrollX": "", /** * This property can be used to force a DataTable to use more width than it * might otherwise do when x-scrolling is enabled. For example if you have a * table which requires to be well spaced, this parameter is useful for * "over-sizing" the table, and thus forcing scrolling. This property can by * any CSS unit, or a number (in which case it will be treated as a pixel * measurement). * @type string * @default <i>blank string - i.e. disabled</i> * @dtopt Options * * @example * $(document).ready( function() { * $('#example').dataTable( { * "sScrollX": "100%", * "sScrollXInner": "110%" * } ); * } ); */ "sScrollXInner": "", /** * Enable vertical scrolling. Vertical scrolling will constrain the DataTable * to the given height, and enable scrolling for any data which overflows the * current viewport. This can be used as an alternative to paging to display * a lot of data in a small area (although paging and scrolling can both be * enabled at the same time). This property can be any CSS unit, or a number * (in which case it will be treated as a pixel measurement). * @type string * @default <i>blank string - i.e. disabled</i> * @dtopt Features * * @example * $(document).ready( function() { * $('#example').dataTable( { * "sScrollY": "200px", * "bPaginate": false * } ); * } ); */ "sScrollY": "", /** * Set the HTTP method that is used to make the Ajax call for server-side * processing or Ajax sourced data. * @type string * @default GET * @dtopt Options * @dtopt Server-side * * @example * $(document).ready( function() { * $('#example').dataTable( { * "bServerSide": true, * "sAjaxSource": "scripts/post.php", * "sServerMethod": "POST" * } ); * } ); */ "sServerMethod": "GET" }; /** * Column options that can be given to DataTables at initialisation time. * @namespace */ DataTable.defaults.columns = { /** * Allows a column's sorting to take multiple columns into account when * doing a sort. For example first name / last name columns make sense to * do a multi-column sort over the two columns. * @type array * @default null <i>Takes the value of the column index automatically</i> * @dtopt Columns * * @example * // Using aoColumnDefs * $(document).ready( function() { * $('#example').dataTable( { * "aoColumnDefs": [ * { "aDataSort": [ 0, 1 ], "aTargets": [ 0 ] }, * { "aDataSort": [ 1, 0 ], "aTargets": [ 1 ] }, * { "aDataSort": [ 2, 3, 4 ], "aTargets": [ 2 ] } * ] * } ); * } ); * * @example * // Using aoColumns * $(document).ready( function() { * $('#example').dataTable( { * "aoColumns": [ * { "aDataSort": [ 0, 1 ] }, * { "aDataSort": [ 1, 0 ] }, * { "aDataSort": [ 2, 3, 4 ] }, * null, * null * ] * } ); * } ); */ "aDataSort": null, /** * You can control the default sorting direction, and even alter the behaviour * of the sort handler (i.e. only allow ascending sorting etc) using this * parameter. * @type array * @default [ 'asc', 'desc' ] * @dtopt Columns * * @example * // Using aoColumnDefs * $(document).ready( function() { * $('#example').dataTable( { * "aoColumnDefs": [ * { "asSorting": [ "asc" ], "aTargets": [ 1 ] }, * { "asSorting": [ "desc", "asc", "asc" ], "aTargets": [ 2 ] }, * { "asSorting": [ "desc" ], "aTargets": [ 3 ] } * ] * } ); * } ); * * @example * // Using aoColumns * $(document).ready( function() { * $('#example').dataTable( { * "aoColumns": [ * null, * { "asSorting": [ "asc" ] }, * { "asSorting": [ "desc", "asc", "asc" ] }, * { "asSorting": [ "desc" ] }, * null * ] * } ); * } ); */ "asSorting": [ 'asc', 'desc' ], /** * Enable or disable filtering on the data in this column. * @type boolean * @default true * @dtopt Columns * * @example * // Using aoColumnDefs * $(document).ready( function() { * $('#example').dataTable( { * "aoColumnDefs": [ * { "bSearchable": false, "aTargets": [ 0 ] } * ] } ); * } ); * * @example * // Using aoColumns * $(document).ready( function() { * $('#example').dataTable( { * "aoColumns": [ * { "bSearchable": false }, * null, * null, * null, * null * ] } ); * } ); */ "bSearchable": true, /** * Enable or disable sorting on this column. * @type boolean * @default true * @dtopt Columns * * @example * // Using aoColumnDefs * $(document).ready( function() { * $('#example').dataTable( { * "aoColumnDefs": [ * { "bSortable": false, "aTargets": [ 0 ] } * ] } ); * } ); * * @example * // Using aoColumns * $(document).ready( function() { * $('#example').dataTable( { * "aoColumns": [ * { "bSortable": false }, * null, * null, * null, * null * ] } ); * } ); */ "bSortable": true, /** * <code>Deprecated</code> When using fnRender() for a column, you may wish * to use the original data (before rendering) for sorting and filtering * (the default is to used the rendered data that the user can see). This * may be useful for dates etc. * * Please note that this option has now been deprecated and will be removed * in the next version of DataTables. Please use mRender / mData rather than * fnRender. * @type boolean * @default true * @dtopt Columns * @deprecated */ "bUseRendered": true, /** * Enable or disable the display of this column. * @type boolean * @default true * @dtopt Columns * * @example * // Using aoColumnDefs * $(document).ready( function() { * $('#example').dataTable( { * "aoColumnDefs": [ * { "bVisible": false, "aTargets": [ 0 ] } * ] } ); * } ); * * @example * // Using aoColumns * $(document).ready( function() { * $('#example').dataTable( { * "aoColumns": [ * { "bVisible": false }, * null, * null, * null, * null * ] } ); * } ); */ "bVisible": true, /** * Developer definable function that is called whenever a cell is created (Ajax source, * etc) or processed for input (DOM source). This can be used as a compliment to mRender * allowing you to modify the DOM element (add background colour for example) when the * element is available. * @type function * @param {element} nTd The TD node that has been created * @param {*} sData The Data for the cell * @param {array|object} oData The data for the whole row * @param {int} iRow The row index for the aoData data store * @param {int} iCol The column index for aoColumns * @dtopt Columns * * @example * $(document).ready( function() { * $('#example').dataTable( { * "aoColumnDefs": [ { * "aTargets": [3], * "fnCreatedCell": function (nTd, sData, oData, iRow, iCol) { * if ( sData == "1.7" ) { * $(nTd).css('color', 'blue') * } * } * } ] * }); * } ); */ "fnCreatedCell": null, /** * <code>Deprecated</code> Custom display function that will be called for the * display of each cell in this column. * * Please note that this option has now been deprecated and will be removed * in the next version of DataTables. Please use mRender / mData rather than * fnRender. * @type function * @param {object} o Object with the following parameters: * @param {int} o.iDataRow The row in aoData * @param {int} o.iDataColumn The column in question * @param {array} o.aData The data for the row in question * @param {object} o.oSettings The settings object for this DataTables instance * @param {object} o.mDataProp The data property used for this column * @param {*} val The current cell value * @returns {string} The string you which to use in the display * @dtopt Columns * @deprecated */ "fnRender": null, /** * The column index (starting from 0!) that you wish a sort to be performed * upon when this column is selected for sorting. This can be used for sorting * on hidden columns for example. * @type int * @default -1 <i>Use automatically calculated column index</i> * @dtopt Columns * * @example * // Using aoColumnDefs * $(document).ready( function() { * $('#example').dataTable( { * "aoColumnDefs": [ * { "iDataSort": 1, "aTargets": [ 0 ] } * ] * } ); * } ); * * @example * // Using aoColumns * $(document).ready( function() { * $('#example').dataTable( { * "aoColumns": [ * { "iDataSort": 1 }, * null, * null, * null, * null * ] * } ); * } ); */ "iDataSort": -1, /** * This parameter has been replaced by mData in DataTables to ensure naming * consistency. mDataProp can still be used, as there is backwards compatibility * in DataTables for this option, but it is strongly recommended that you use * mData in preference to mDataProp. * @name DataTable.defaults.columns.mDataProp */ /** * This property can be used to read data from any JSON data source property, * including deeply nested objects / properties. mData can be given in a * number of different ways which effect its behaviour: * <ul> * <li>integer - treated as an array index for the data source. This is the * default that DataTables uses (incrementally increased for each column).</li> * <li>string - read an object property from the data source. Note that you can * use Javascript dotted notation to read deep properties / arrays from the * data source.</li> * <li>null - the sDefaultContent option will be used for the cell (null * by default, so you will need to specify the default content you want - * typically an empty string). This can be useful on generated columns such * as edit / delete action columns.</li> * <li>function - the function given will be executed whenever DataTables * needs to set or get the data for a cell in the column. The function * takes three parameters: * <ul> * <li>{array|object} The data source for the row</li> * <li>{string} The type call data requested - this will be 'set' when * setting data or 'filter', 'display', 'type', 'sort' or undefined when * gathering data. Note that when <i>undefined</i> is given for the type * DataTables expects to get the raw data for the object back</li> * <li>{*} Data to set when the second parameter is 'set'.</li> * </ul> * The return value from the function is not required when 'set' is the type * of call, but otherwise the return is what will be used for the data * requested.</li> * </ul> * * Note that prior to DataTables 1.9.2 mData was called mDataProp. The name change * reflects the flexibility of this property and is consistent with the naming of * mRender. If 'mDataProp' is given, then it will still be used by DataTables, as * it automatically maps the old name to the new if required. * @type string|int|function|null * @default null <i>Use automatically calculated column index</i> * @dtopt Columns * * @example * // Read table data from objects * $(document).ready( function() { * var oTable = $('#example').dataTable( { * "sAjaxSource": "sources/deep.txt", * "aoColumns": [ * { "mData": "engine" }, * { "mData": "browser" }, * { "mData": "platform.inner" }, * { "mData": "platform.details.0" }, * { "mData": "platform.details.1" } * ] * } ); * } ); * * @example * // Using mData as a function to provide different information for * // sorting, filtering and display. In this case, currency (price) * $(document).ready( function() { * var oTable = $('#example').dataTable( { * "aoColumnDefs": [ { * "aTargets": [ 0 ], * "mData": function ( source, type, val ) { * if (type === 'set') { * source.price = val; * // Store the computed dislay and filter values for efficiency * source.price_display = val=="" ? "" : "$"+numberFormat(val); * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val; * return; * } * else if (type === 'display') { * return source.price_display; * } * else if (type === 'filter') { * return source.price_filter; * } * // 'sort', 'type' and undefined all just use the integer * return source.price; * } * } ] * } ); * } ); */ "mData": null, /** * This property is the rendering partner to mData and it is suggested that * when you want to manipulate data for display (including filtering, sorting etc) * but not altering the underlying data for the table, use this property. mData * can actually do everything this property can and more, but this parameter is * easier to use since there is no 'set' option. Like mData is can be given * in a number of different ways to effect its behaviour, with the addition of * supporting array syntax for easy outputting of arrays (including arrays of * objects): * <ul> * <li>integer - treated as an array index for the data source. This is the * default that DataTables uses (incrementally increased for each column).</li> * <li>string - read an object property from the data source. Note that you can * use Javascript dotted notation to read deep properties / arrays from the * data source and also array brackets to indicate that the data reader should * loop over the data source array. When characters are given between the array * brackets, these characters are used to join the data source array together. * For example: "accounts[, ].name" would result in a comma separated list with * the 'name' value from the 'accounts' array of objects.</li> * <li>function - the function given will be executed whenever DataTables * needs to set or get the data for a cell in the column. The function * takes three parameters: * <ul> * <li>{array|object} The data source for the row (based on mData)</li> * <li>{string} The type call data requested - this will be 'filter', 'display', * 'type' or 'sort'.</li> * <li>{array|object} The full data source for the row (not based on mData)</li> * </ul> * The return value from the function is what will be used for the data * requested.</li> * </ul> * @type string|int|function|null * @default null <i>Use mData</i> * @dtopt Columns * * @example * // Create a comma separated list from an array of objects * $(document).ready( function() { * var oTable = $('#example').dataTable( { * "sAjaxSource": "sources/deep.txt", * "aoColumns": [ * { "mData": "engine" }, * { "mData": "browser" }, * { * "mData": "platform", * "mRender": "[, ].name" * } * ] * } ); * } ); * * @example * // Use as a function to create a link from the data source * $(document).ready( function() { * var oTable = $('#example').dataTable( { * "aoColumnDefs": [ * { * "aTargets": [ 0 ], * "mData": "download_link", * "mRender": function ( data, type, full ) { * return '<a href="'+data+'">Download</a>'; * } * ] * } ); * } ); */ "mRender": null, /** * Change the cell type created for the column - either TD cells or TH cells. This * can be useful as TH cells have semantic meaning in the table body, allowing them * to act as a header for a row (you may wish to add scope='row' to the TH elements). * @type string * @default td * @dtopt Columns * * @example * // Make the first column use TH cells * $(document).ready( function() { * var oTable = $('#example').dataTable( { * "aoColumnDefs": [ { * "aTargets": [ 0 ], * "sCellType": "th" * } ] * } ); * } ); */ "sCellType": "td", /** * Class to give to each cell in this column. * @type string * @default <i>Empty string</i> * @dtopt Columns * * @example * // Using aoColumnDefs * $(document).ready( function() { * $('#example').dataTable( { * "aoColumnDefs": [ * { "sClass": "my_class", "aTargets": [ 0 ] } * ] * } ); * } ); * * @example * // Using aoColumns * $(document).ready( function() { * $('#example').dataTable( { * "aoColumns": [ * { "sClass": "my_class" }, * null, * null, * null, * null * ] * } ); * } ); */ "sClass": "", /** * When DataTables calculates the column widths to assign to each column, * it finds the longest string in each column and then constructs a * temporary table and reads the widths from that. The problem with this * is that "mmm" is much wider then "iiii", but the latter is a longer * string - thus the calculation can go wrong (doing it properly and putting * it into an DOM object and measuring that is horribly(!) slow). Thus as * a "work around" we provide this option. It will append its value to the * text that is found to be the longest string for the column - i.e. padding. * Generally you shouldn't need this, and it is not documented on the * general DataTables.net documentation * @type string * @default <i>Empty string<i> * @dtopt Columns * * @example * // Using aoColumns * $(document).ready( function() { * $('#example').dataTable( { * "aoColumns": [ * null, * null, * null, * { * "sContentPadding": "mmm" * } * ] * } ); * } ); */ "sContentPadding": "", /** * Allows a default value to be given for a column's data, and will be used * whenever a null data source is encountered (this can be because mData * is set to null, or because the data source itself is null). * @type string * @default null * @dtopt Columns * * @example * // Using aoColumnDefs * $(document).ready( function() { * $('#example').dataTable( { * "aoColumnDefs": [ * { * "mData": null, * "sDefaultContent": "Edit", * "aTargets": [ -1 ] * } * ] * } ); * } ); * * @example * // Using aoColumns * $(document).ready( function() { * $('#example').dataTable( { * "aoColumns": [ * null, * null, * null, * { * "mData": null, * "sDefaultContent": "Edit" * } * ] * } ); * } ); */ "sDefaultContent": null, /** * This parameter is only used in DataTables' server-side processing. It can * be exceptionally useful to know what columns are being displayed on the * client side, and to map these to database fields. When defined, the names * also allow DataTables to reorder information from the server if it comes * back in an unexpected order (i.e. if you switch your columns around on the * client-side, your server-side code does not also need updating). * @type string * @default <i>Empty string</i> * @dtopt Columns * * @example * // Using aoColumnDefs * $(document).ready( function() { * $('#example').dataTable( { * "aoColumnDefs": [ * { "sName": "engine", "aTargets": [ 0 ] }, * { "sName": "browser", "aTargets": [ 1 ] }, * { "sName": "platform", "aTargets": [ 2 ] }, * { "sName": "version", "aTargets": [ 3 ] }, * { "sName": "grade", "aTargets": [ 4 ] } * ] * } ); * } ); * * @example * // Using aoColumns * $(document).ready( function() { * $('#example').dataTable( { * "aoColumns": [ * { "sName": "engine" }, * { "sName": "browser" }, * { "sName": "platform" }, * { "sName": "version" }, * { "sName": "grade" } * ] * } ); * } ); */ "sName": "", /** * Defines a data source type for the sorting which can be used to read * real-time information from the table (updating the internally cached * version) prior to sorting. This allows sorting to occur on user editable * elements such as form inputs. * @type string * @default std * @dtopt Columns * * @example * // Using aoColumnDefs * $(document).ready( function() { * $('#example').dataTable( { * "aoColumnDefs": [ * { "sSortDataType": "dom-text", "aTargets": [ 2, 3 ] }, * { "sType": "numeric", "aTargets": [ 3 ] }, * { "sSortDataType": "dom-select", "aTargets": [ 4 ] }, * { "sSortDataType": "dom-checkbox", "aTargets": [ 5 ] } * ] * } ); * } ); * * @example * // Using aoColumns * $(document).ready( function() { * $('#example').dataTable( { * "aoColumns": [ * null, * null, * { "sSortDataType": "dom-text" }, * { "sSortDataType": "dom-text", "sType": "numeric" }, * { "sSortDataType": "dom-select" }, * { "sSortDataType": "dom-checkbox" } * ] * } ); * } ); */ "sSortDataType": "std", /** * The title of this column. * @type string * @default null <i>Derived from the 'TH' value for this column in the * original HTML table.</i> * @dtopt Columns * * @example * // Using aoColumnDefs * $(document).ready( function() { * $('#example').dataTable( { * "aoColumnDefs": [ * { "sTitle": "My column title", "aTargets": [ 0 ] } * ] * } ); * } ); * * @example * // Using aoColumns * $(document).ready( function() { * $('#example').dataTable( { * "aoColumns": [ * { "sTitle": "My column title" }, * null, * null, * null, * null * ] * } ); * } ); */ "sTitle": null, /** * The type allows you to specify how the data for this column will be sorted. * Four types (string, numeric, date and html (which will strip HTML tags * before sorting)) are currently available. Note that only date formats * understood by Javascript's Date() object will be accepted as type date. For * example: "Mar 26, 2008 5:03 PM". May take the values: 'string', 'numeric', * 'date' or 'html' (by default). Further types can be adding through * plug-ins. * @type string * @default null <i>Auto-detected from raw data</i> * @dtopt Columns * * @example * // Using aoColumnDefs * $(document).ready( function() { * $('#example').dataTable( { * "aoColumnDefs": [ * { "sType": "html", "aTargets": [ 0 ] } * ] * } ); * } ); * * @example * // Using aoColumns * $(document).ready( function() { * $('#example').dataTable( { * "aoColumns": [ * { "sType": "html" }, * null, * null, * null, * null * ] * } ); * } ); */ "sType": null, /** * Defining the width of the column, this parameter may take any CSS value * (3em, 20px etc). DataTables apples 'smart' widths to columns which have not * been given a specific width through this interface ensuring that the table * remains readable. * @type string * @default null <i>Automatic</i> * @dtopt Columns * * @example * // Using aoColumnDefs * $(document).ready( function() { * $('#example').dataTable( { * "aoColumnDefs": [ * { "sWidth": "20%", "aTargets": [ 0 ] } * ] * } ); * } ); * * @example * // Using aoColumns * $(document).ready( function() { * $('#example').dataTable( { * "aoColumns": [ * { "sWidth": "20%" }, * null, * null, * null, * null * ] * } ); * } ); */ "sWidth": null }; /** * DataTables settings object - this holds all the information needed for a * given table, including configuration, data and current application of the * table options. DataTables does not have a single instance for each DataTable * with the settings attached to that instance, but rather instances of the * DataTable "class" are created on-the-fly as needed (typically by a * $().dataTable() call) and the settings object is then applied to that * instance. * * Note that this object is related to {@link DataTable.defaults} but this * one is the internal data store for DataTables's cache of columns. It should * NOT be manipulated outside of DataTables. Any configuration should be done * through the initialisation options. * @namespace * @todo Really should attach the settings object to individual instances so we * don't need to create new instances on each $().dataTable() call (if the * table already exists). It would also save passing oSettings around and * into every single function. However, this is a very significant * architecture change for DataTables and will almost certainly break * backwards compatibility with older installations. This is something that * will be done in 2.0. */ DataTable.models.oSettings = { /** * Primary features of DataTables and their enablement state. * @namespace */ "oFeatures": { /** * Flag to say if DataTables should automatically try to calculate the * optimum table and columns widths (true) or not (false). * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type boolean */ "bAutoWidth": null, /** * Delay the creation of TR and TD elements until they are actually * needed by a driven page draw. This can give a significant speed * increase for Ajax source and Javascript source data, but makes no * difference at all fro DOM and server-side processing tables. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type boolean */ "bDeferRender": null, /** * Enable filtering on the table or not. Note that if this is disabled * then there is no filtering at all on the table, including fnFilter. * To just remove the filtering input use sDom and remove the 'f' option. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type boolean */ "bFilter": null, /** * Table information element (the 'Showing x of y records' div) enable * flag. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type boolean */ "bInfo": null, /** * Present a user control allowing the end user to change the page size * when pagination is enabled. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type boolean */ "bLengthChange": null, /** * Pagination enabled or not. Note that if this is disabled then length * changing must also be disabled. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type boolean */ "bPaginate": null, /** * Processing indicator enable flag whenever DataTables is enacting a * user request - typically an Ajax request for server-side processing. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type boolean */ "bProcessing": null, /** * Server-side processing enabled flag - when enabled DataTables will * get all data from the server for every draw - there is no filtering, * sorting or paging done on the client-side. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type boolean */ "bServerSide": null, /** * Sorting enablement flag. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type boolean */ "bSort": null, /** * Apply a class to the columns which are being sorted to provide a * visual highlight or not. This can slow things down when enabled since * there is a lot of DOM interaction. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type boolean */ "bSortClasses": null, /** * State saving enablement flag. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type boolean */ "bStateSave": null }, /** * Scrolling settings for a table. * @namespace */ "oScroll": { /** * Indicate if DataTables should be allowed to set the padding / margin * etc for the scrolling header elements or not. Typically you will want * this. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type boolean */ "bAutoCss": null, /** * When the table is shorter in height than sScrollY, collapse the * table container down to the height of the table (when true). * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type boolean */ "bCollapse": null, /** * Infinite scrolling enablement flag. Now deprecated in favour of * using the Scroller plug-in. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type boolean */ "bInfinite": null, /** * Width of the scrollbar for the web-browser's platform. Calculated * during table initialisation. * @type int * @default 0 */ "iBarWidth": 0, /** * Space (in pixels) between the bottom of the scrolling container and * the bottom of the scrolling viewport before the next page is loaded * when using infinite scrolling. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type int */ "iLoadGap": null, /** * Viewport width for horizontal scrolling. Horizontal scrolling is * disabled if an empty string. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type string */ "sX": null, /** * Width to expand the table to when using x-scrolling. Typically you * should not need to use this. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type string * @deprecated */ "sXInner": null, /** * Viewport height for vertical scrolling. Vertical scrolling is disabled * if an empty string. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type string */ "sY": null }, /** * Language information for the table. * @namespace * @extends DataTable.defaults.oLanguage */ "oLanguage": { /** * Information callback function. See * {@link DataTable.defaults.fnInfoCallback} * @type function * @default null */ "fnInfoCallback": null }, /** * Browser support parameters * @namespace */ "oBrowser": { /** * Indicate if the browser incorrectly calculates width:100% inside a * scrolling element (IE6/7) * @type boolean * @default false */ "bScrollOversize": false }, /** * Array referencing the nodes which are used for the features. The * parameters of this object match what is allowed by sDom - i.e. * <ul> * <li>'l' - Length changing</li> * <li>'f' - Filtering input</li> * <li>'t' - The table!</li> * <li>'i' - Information</li> * <li>'p' - Pagination</li> * <li>'r' - pRocessing</li> * </ul> * @type array * @default [] */ "aanFeatures": [], /** * Store data information - see {@link DataTable.models.oRow} for detailed * information. * @type array * @default [] */ "aoData": [], /** * Array of indexes which are in the current display (after filtering etc) * @type array * @default [] */ "aiDisplay": [], /** * Array of indexes for display - no filtering * @type array * @default [] */ "aiDisplayMaster": [], /** * Store information about each column that is in use * @type array * @default [] */ "aoColumns": [], /** * Store information about the table's header * @type array * @default [] */ "aoHeader": [], /** * Store information about the table's footer * @type array * @default [] */ "aoFooter": [], /** * Search data array for regular expression searching * @type array * @default [] */ "asDataSearch": [], /** * Store the applied global search information in case we want to force a * research or compare the old search to a new one. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @namespace * @extends DataTable.models.oSearch */ "oPreviousSearch": {}, /** * Store the applied search for each column - see * {@link DataTable.models.oSearch} for the format that is used for the * filtering information for each column. * @type array * @default [] */ "aoPreSearchCols": [], /** * Sorting that is applied to the table. Note that the inner arrays are * used in the following manner: * <ul> * <li>Index 0 - column number</li> * <li>Index 1 - current sorting direction</li> * <li>Index 2 - index of asSorting for this column</li> * </ul> * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type array * @todo These inner arrays should really be objects */ "aaSorting": null, /** * Sorting that is always applied to the table (i.e. prefixed in front of * aaSorting). * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type array|null * @default null */ "aaSortingFixed": null, /** * Classes to use for the striping of a table. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type array * @default [] */ "asStripeClasses": null, /** * If restoring a table - we should restore its striping classes as well * @type array * @default [] */ "asDestroyStripes": [], /** * If restoring a table - we should restore its width * @type int * @default 0 */ "sDestroyWidth": 0, /** * Callback functions array for every time a row is inserted (i.e. on a draw). * @type array * @default [] */ "aoRowCallback": [], /** * Callback functions for the header on each draw. * @type array * @default [] */ "aoHeaderCallback": [], /** * Callback function for the footer on each draw. * @type array * @default [] */ "aoFooterCallback": [], /** * Array of callback functions for draw callback functions * @type array * @default [] */ "aoDrawCallback": [], /** * Array of callback functions for row created function * @type array * @default [] */ "aoRowCreatedCallback": [], /** * Callback functions for just before the table is redrawn. A return of * false will be used to cancel the draw. * @type array * @default [] */ "aoPreDrawCallback": [], /** * Callback functions for when the table has been initialised. * @type array * @default [] */ "aoInitComplete": [], /** * Callbacks for modifying the settings to be stored for state saving, prior to * saving state. * @type array * @default [] */ "aoStateSaveParams": [], /** * Callbacks for modifying the settings that have been stored for state saving * prior to using the stored values to restore the state. * @type array * @default [] */ "aoStateLoadParams": [], /** * Callbacks for operating on the settings object once the saved state has been * loaded * @type array * @default [] */ "aoStateLoaded": [], /** * Cache the table ID for quick access * @type string * @default <i>Empty string</i> */ "sTableId": "", /** * The TABLE node for the main table * @type node * @default null */ "nTable": null, /** * Permanent ref to the thead element * @type node * @default null */ "nTHead": null, /** * Permanent ref to the tfoot element - if it exists * @type node * @default null */ "nTFoot": null, /** * Permanent ref to the tbody element * @type node * @default null */ "nTBody": null, /** * Cache the wrapper node (contains all DataTables controlled elements) * @type node * @default null */ "nTableWrapper": null, /** * Indicate if when using server-side processing the loading of data * should be deferred until the second draw. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type boolean * @default false */ "bDeferLoading": false, /** * Indicate if all required information has been read in * @type boolean * @default false */ "bInitialised": false, /** * Information about open rows. Each object in the array has the parameters * 'nTr' and 'nParent' * @type array * @default [] */ "aoOpenRows": [], /** * Dictate the positioning of DataTables' control elements - see * {@link DataTable.model.oInit.sDom}. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type string * @default null */ "sDom": null, /** * Which type of pagination should be used. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type string * @default two_button */ "sPaginationType": "two_button", /** * The cookie duration (for bStateSave) in seconds. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type int * @default 0 */ "iCookieDuration": 0, /** * The cookie name prefix. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type string * @default <i>Empty string</i> */ "sCookiePrefix": "", /** * Callback function for cookie creation. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type function * @default null */ "fnCookieCallback": null, /** * Array of callback functions for state saving. Each array element is an * object with the following parameters: * <ul> * <li>function:fn - function to call. Takes two parameters, oSettings * and the JSON string to save that has been thus far created. Returns * a JSON string to be inserted into a json object * (i.e. '"param": [ 0, 1, 2]')</li> * <li>string:sName - name of callback</li> * </ul> * @type array * @default [] */ "aoStateSave": [], /** * Array of callback functions for state loading. Each array element is an * object with the following parameters: * <ul> * <li>function:fn - function to call. Takes two parameters, oSettings * and the object stored. May return false to cancel state loading</li> * <li>string:sName - name of callback</li> * </ul> * @type array * @default [] */ "aoStateLoad": [], /** * State that was loaded from the cookie. Useful for back reference * @type object * @default null */ "oLoadedState": null, /** * Source url for AJAX data for the table. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type string * @default null */ "sAjaxSource": null, /** * Property from a given object from which to read the table data from. This * can be an empty string (when not server-side processing), in which case * it is assumed an an array is given directly. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type string */ "sAjaxDataProp": null, /** * Note if draw should be blocked while getting data * @type boolean * @default true */ "bAjaxDataGet": true, /** * The last jQuery XHR object that was used for server-side data gathering. * This can be used for working with the XHR information in one of the * callbacks * @type object * @default null */ "jqXHR": null, /** * Function to get the server-side data. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type function */ "fnServerData": null, /** * Functions which are called prior to sending an Ajax request so extra * parameters can easily be sent to the server * @type array * @default [] */ "aoServerParams": [], /** * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if * required). * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type string */ "sServerMethod": null, /** * Format numbers for display. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type function */ "fnFormatNumber": null, /** * List of options that can be used for the user selectable length menu. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type array * @default [] */ "aLengthMenu": null, /** * Counter for the draws that the table does. Also used as a tracker for * server-side processing * @type int * @default 0 */ "iDraw": 0, /** * Indicate if a redraw is being done - useful for Ajax * @type boolean * @default false */ "bDrawing": false, /** * Draw index (iDraw) of the last error when parsing the returned data * @type int * @default -1 */ "iDrawError": -1, /** * Paging display length * @type int * @default 10 */ "_iDisplayLength": 10, /** * Paging start point - aiDisplay index * @type int * @default 0 */ "_iDisplayStart": 0, /** * Paging end point - aiDisplay index. Use fnDisplayEnd rather than * this property to get the end point * @type int * @default 10 * @private */ "_iDisplayEnd": 10, /** * Server-side processing - number of records in the result set * (i.e. before filtering), Use fnRecordsTotal rather than * this property to get the value of the number of records, regardless of * the server-side processing setting. * @type int * @default 0 * @private */ "_iRecordsTotal": 0, /** * Server-side processing - number of records in the current display set * (i.e. after filtering). Use fnRecordsDisplay rather than * this property to get the value of the number of records, regardless of * the server-side processing setting. * @type boolean * @default 0 * @private */ "_iRecordsDisplay": 0, /** * Flag to indicate if jQuery UI marking and classes should be used. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type boolean */ "bJUI": null, /** * The classes to use for the table * @type object * @default {} */ "oClasses": {}, /** * Flag attached to the settings object so you can check in the draw * callback if filtering has been done in the draw. Deprecated in favour of * events. * @type boolean * @default false * @deprecated */ "bFiltered": false, /** * Flag attached to the settings object so you can check in the draw * callback if sorting has been done in the draw. Deprecated in favour of * events. * @type boolean * @default false * @deprecated */ "bSorted": false, /** * Indicate that if multiple rows are in the header and there is more than * one unique cell per column, if the top one (true) or bottom one (false) * should be used for sorting / title by DataTables. * Note that this parameter will be set by the initialisation routine. To * set a default use {@link DataTable.defaults}. * @type boolean */ "bSortCellsTop": null, /** * Initialisation object that is used for the table * @type object * @default null */ "oInit": null, /** * Destroy callback functions - for plug-ins to attach themselves to the * destroy so they can clean up markup and events. * @type array * @default [] */ "aoDestroyCallback": [], /** * Get the number of records in the current record set, before filtering * @type function */ "fnRecordsTotal": function () { if ( this.oFeatures.bServerSide ) { return parseInt(this._iRecordsTotal, 10); } else { return this.aiDisplayMaster.length; } }, /** * Get the number of records in the current record set, after filtering * @type function */ "fnRecordsDisplay": function () { if ( this.oFeatures.bServerSide ) { return parseInt(this._iRecordsDisplay, 10); } else { return this.aiDisplay.length; } }, /** * Set the display end point - aiDisplay index * @type function * @todo Should do away with _iDisplayEnd and calculate it on-the-fly here */ "fnDisplayEnd": function () { if ( this.oFeatures.bServerSide ) { if ( this.oFeatures.bPaginate === false || this._iDisplayLength == -1 ) { return this._iDisplayStart+this.aiDisplay.length; } else { return Math.min( this._iDisplayStart+this._iDisplayLength, this._iRecordsDisplay ); } } else { return this._iDisplayEnd; } }, /** * The DataTables object for this table * @type object * @default null */ "oInstance": null, /** * Unique identifier for each instance of the DataTables object. If there * is an ID on the table node, then it takes that value, otherwise an * incrementing internal counter is used. * @type string * @default null */ "sInstance": null, /** * tabindex attribute value that is added to DataTables control elements, allowing * keyboard navigation of the table and its controls. */ "iTabIndex": 0, /** * DIV container for the footer scrolling table if scrolling */ "nScrollHead": null, /** * DIV container for the footer scrolling table if scrolling */ "nScrollFoot": null }; /** * Extension object for DataTables that is used to provide all extension options. * * Note that the <i>DataTable.ext</i> object is available through * <i>jQuery.fn.dataTable.ext</i> where it may be accessed and manipulated. It is * also aliased to <i>jQuery.fn.dataTableExt</i> for historic reasons. * @namespace * @extends DataTable.models.ext */ DataTable.ext = $.extend( true, {}, DataTable.models.ext ); $.extend( DataTable.ext.oStdClasses, { "sTable": "dataTable", /* Two buttons buttons */ "sPagePrevEnabled": "paginate_enabled_previous", "sPagePrevDisabled": "paginate_disabled_previous", "sPageNextEnabled": "paginate_enabled_next", "sPageNextDisabled": "paginate_disabled_next", "sPageJUINext": "", "sPageJUIPrev": "", /* Full numbers paging buttons */ "sPageButton": "paginate_button", "sPageButtonActive": "paginate_active", "sPageButtonStaticDisabled": "paginate_button paginate_button_disabled", "sPageFirst": "first", "sPagePrevious": "previous", "sPageNext": "next", "sPageLast": "last", /* Striping classes */ "sStripeOdd": "odd", "sStripeEven": "even", /* Empty row */ "sRowEmpty": "dataTables_empty", /* Features */ "sWrapper": "dataTables_wrapper", "sFilter": "dataTables_filter", "sInfo": "dataTables_info", "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */ "sLength": "dataTables_length", "sProcessing": "dataTables_processing", /* Sorting */ "sSortAsc": "sorting_asc", "sSortDesc": "sorting_desc", "sSortable": "sorting", /* Sortable in both directions */ "sSortableAsc": "sorting_asc_disabled", "sSortableDesc": "sorting_desc_disabled", "sSortableNone": "sorting_disabled", "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */ "sSortJUIAsc": "", "sSortJUIDesc": "", "sSortJUI": "", "sSortJUIAscAllowed": "", "sSortJUIDescAllowed": "", "sSortJUIWrapper": "", "sSortIcon": "", /* Scrolling */ "sScrollWrapper": "dataTables_scroll", "sScrollHead": "dataTables_scrollHead", "sScrollHeadInner": "dataTables_scrollHeadInner", "sScrollBody": "dataTables_scrollBody", "sScrollFoot": "dataTables_scrollFoot", "sScrollFootInner": "dataTables_scrollFootInner", /* Misc */ "sFooterTH": "", "sJUIHeader": "", "sJUIFooter": "" } ); $.extend( DataTable.ext.oJUIClasses, DataTable.ext.oStdClasses, { /* Two buttons buttons */ "sPagePrevEnabled": "fg-button ui-button ui-state-default ui-corner-left", "sPagePrevDisabled": "fg-button ui-button ui-state-default ui-corner-left ui-state-disabled", "sPageNextEnabled": "fg-button ui-button ui-state-default ui-corner-right", "sPageNextDisabled": "fg-button ui-button ui-state-default ui-corner-right ui-state-disabled", "sPageJUINext": "ui-icon ui-icon-circle-arrow-e", "sPageJUIPrev": "ui-icon ui-icon-circle-arrow-w", /* Full numbers paging buttons */ "sPageButton": "fg-button ui-button ui-state-default", "sPageButtonActive": "fg-button ui-button ui-state-default ui-state-disabled", "sPageButtonStaticDisabled": "fg-button ui-button ui-state-default ui-state-disabled", "sPageFirst": "first ui-corner-tl ui-corner-bl", "sPageLast": "last ui-corner-tr ui-corner-br", /* Features */ "sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+ "ui-buttonset-multi paging_", /* Note that the type is postfixed */ /* Sorting */ "sSortAsc": "ui-state-default", "sSortDesc": "ui-state-default", "sSortable": "ui-state-default", "sSortableAsc": "ui-state-default", "sSortableDesc": "ui-state-default", "sSortableNone": "ui-state-default", "sSortJUIAsc": "css_right ui-icon ui-icon-triangle-1-n", "sSortJUIDesc": "css_right ui-icon ui-icon-triangle-1-s", "sSortJUI": "css_right ui-icon ui-icon-carat-2-n-s", "sSortJUIAscAllowed": "css_right ui-icon ui-icon-carat-1-n", "sSortJUIDescAllowed": "css_right ui-icon ui-icon-carat-1-s", "sSortJUIWrapper": "DataTables_sort_wrapper", "sSortIcon": "DataTables_sort_icon", /* Scrolling */ "sScrollHead": "dataTables_scrollHead ui-state-default", "sScrollFoot": "dataTables_scrollFoot ui-state-default", /* Misc */ "sFooterTH": "ui-state-default", "sJUIHeader": "fg-toolbar ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix", "sJUIFooter": "fg-toolbar ui-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix" } ); /* * Variable: oPagination * Purpose: * Scope: jQuery.fn.dataTableExt */ $.extend( DataTable.ext.oPagination, { /* * Variable: two_button * Purpose: Standard two button (forward/back) pagination * Scope: jQuery.fn.dataTableExt.oPagination */ "two_button": { /* * Function: oPagination.two_button.fnInit * Purpose: Initialise dom elements required for pagination with forward/back buttons only * Returns: - * Inputs: object:oSettings - dataTables settings object * node:nPaging - the DIV which contains this pagination control * function:fnCallbackDraw - draw function which must be called on update */ "fnInit": function ( oSettings, nPaging, fnCallbackDraw ) { var oLang = oSettings.oLanguage.oPaginate; var oClasses = oSettings.oClasses; var fnClickHandler = function ( e ) { if ( oSettings.oApi._fnPageChange( oSettings, e.data.action ) ) { fnCallbackDraw( oSettings ); } }; var sAppend = (!oSettings.bJUI) ? '<a class="'+oSettings.oClasses.sPagePrevDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button">'+oLang.sPrevious+'</a>'+ '<a class="'+oSettings.oClasses.sPageNextDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button">'+oLang.sNext+'</a>' : '<a class="'+oSettings.oClasses.sPagePrevDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button"><span class="'+oSettings.oClasses.sPageJUIPrev+'"></span></a>'+ '<a class="'+oSettings.oClasses.sPageNextDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button"><span class="'+oSettings.oClasses.sPageJUINext+'"></span></a>'; $(nPaging).append( sAppend ); var els = $('a', nPaging); var nPrevious = els[0], nNext = els[1]; oSettings.oApi._fnBindAction( nPrevious, {action: "previous"}, fnClickHandler ); oSettings.oApi._fnBindAction( nNext, {action: "next"}, fnClickHandler ); /* ID the first elements only */ if ( !oSettings.aanFeatures.p ) { nPaging.id = oSettings.sTableId+'_paginate'; nPrevious.id = oSettings.sTableId+'_previous'; nNext.id = oSettings.sTableId+'_next'; nPrevious.setAttribute('aria-controls', oSettings.sTableId); nNext.setAttribute('aria-controls', oSettings.sTableId); } }, /* * Function: oPagination.two_button.fnUpdate * Purpose: Update the two button pagination at the end of the draw * Returns: - * Inputs: object:oSettings - dataTables settings object * function:fnCallbackDraw - draw function to call on page change */ "fnUpdate": function ( oSettings, fnCallbackDraw ) { if ( !oSettings.aanFeatures.p ) { return; } var oClasses = oSettings.oClasses; var an = oSettings.aanFeatures.p; var nNode; /* Loop over each instance of the pager */ for ( var i=0, iLen=an.length ; i<iLen ; i++ ) { nNode = an[i].firstChild; if ( nNode ) { /* Previous page */ nNode.className = ( oSettings._iDisplayStart === 0 ) ? oClasses.sPagePrevDisabled : oClasses.sPagePrevEnabled; /* Next page */ nNode = nNode.nextSibling; nNode.className = ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) ? oClasses.sPageNextDisabled : oClasses.sPageNextEnabled; } } } }, /* * Variable: iFullNumbersShowPages * Purpose: Change the number of pages which can be seen * Scope: jQuery.fn.dataTableExt.oPagination */ "iFullNumbersShowPages": 5, /* * Variable: full_numbers * Purpose: Full numbers pagination * Scope: jQuery.fn.dataTableExt.oPagination */ "full_numbers": { /* * Function: oPagination.full_numbers.fnInit * Purpose: Initialise dom elements required for pagination with a list of the pages * Returns: - * Inputs: object:oSettings - dataTables settings object * node:nPaging - the DIV which contains this pagination control * function:fnCallbackDraw - draw function which must be called on update */ "fnInit": function ( oSettings, nPaging, fnCallbackDraw ) { var oLang = oSettings.oLanguage.oPaginate; var oClasses = oSettings.oClasses; var fnClickHandler = function ( e ) { if ( oSettings.oApi._fnPageChange( oSettings, e.data.action ) ) { fnCallbackDraw( oSettings ); } }; $(nPaging).append( '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPageFirst+'">'+oLang.sFirst+'</a>'+ '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPagePrevious+'">'+oLang.sPrevious+'</a>'+ '<span></span>'+ '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPageNext+'">'+oLang.sNext+'</a>'+ '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPageLast+'">'+oLang.sLast+'</a>' ); var els = $('a', nPaging); var nFirst = els[0], nPrev = els[1], nNext = els[2], nLast = els[3]; oSettings.oApi._fnBindAction( nFirst, {action: "first"}, fnClickHandler ); oSettings.oApi._fnBindAction( nPrev, {action: "previous"}, fnClickHandler ); oSettings.oApi._fnBindAction( nNext, {action: "next"}, fnClickHandler ); oSettings.oApi._fnBindAction( nLast, {action: "last"}, fnClickHandler ); /* ID the first elements only */ if ( !oSettings.aanFeatures.p ) { nPaging.id = oSettings.sTableId+'_paginate'; nFirst.id =oSettings.sTableId+'_first'; nPrev.id =oSettings.sTableId+'_previous'; nNext.id =oSettings.sTableId+'_next'; nLast.id =oSettings.sTableId+'_last'; } }, /* * Function: oPagination.full_numbers.fnUpdate * Purpose: Update the list of page buttons shows * Returns: - * Inputs: object:oSettings - dataTables settings object * function:fnCallbackDraw - draw function to call on page change */ "fnUpdate": function ( oSettings, fnCallbackDraw ) { if ( !oSettings.aanFeatures.p ) { return; } var iPageCount = DataTable.ext.oPagination.iFullNumbersShowPages; var iPageCountHalf = Math.floor(iPageCount / 2); var iPages = Math.ceil((oSettings.fnRecordsDisplay()) / oSettings._iDisplayLength); var iCurrentPage = Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1; var sList = ""; var iStartButton, iEndButton, i, iLen; var oClasses = oSettings.oClasses; var anButtons, anStatic, nPaginateList, nNode; var an = oSettings.aanFeatures.p; var fnBind = function (j) { oSettings.oApi._fnBindAction( this, {"page": j+iStartButton-1}, function(e) { /* Use the information in the element to jump to the required page */ oSettings.oApi._fnPageChange( oSettings, e.data.page ); fnCallbackDraw( oSettings ); e.preventDefault(); } ); }; /* Pages calculation */ if ( oSettings._iDisplayLength === -1 ) { iStartButton = 1; iEndButton = 1; iCurrentPage = 1; } else if (iPages < iPageCount) { iStartButton = 1; iEndButton = iPages; } else if (iCurrentPage <= iPageCountHalf) { iStartButton = 1; iEndButton = iPageCount; } else if (iCurrentPage >= (iPages - iPageCountHalf)) { iStartButton = iPages - iPageCount + 1; iEndButton = iPages; } else { iStartButton = iCurrentPage - Math.ceil(iPageCount / 2) + 1; iEndButton = iStartButton + iPageCount - 1; } /* Build the dynamic list */ for ( i=iStartButton ; i<=iEndButton ; i++ ) { sList += (iCurrentPage !== i) ? '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+'">'+oSettings.fnFormatNumber(i)+'</a>' : '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButtonActive+'">'+oSettings.fnFormatNumber(i)+'</a>'; } /* Loop over each instance of the pager */ for ( i=0, iLen=an.length ; i<iLen ; i++ ) { nNode = an[i]; if ( !nNode.hasChildNodes() ) { continue; } /* Build up the dynamic list first - html and listeners */ $('span:eq(0)', nNode) .html( sList ) .children('a').each( fnBind ); /* Update the permanent button's classes */ anButtons = nNode.getElementsByTagName('a'); anStatic = [ anButtons[0], anButtons[1], anButtons[anButtons.length-2], anButtons[anButtons.length-1] ]; $(anStatic).removeClass( oClasses.sPageButton+" "+oClasses.sPageButtonActive+" "+oClasses.sPageButtonStaticDisabled ); $([anStatic[0], anStatic[1]]).addClass( (iCurrentPage==1) ? oClasses.sPageButtonStaticDisabled : oClasses.sPageButton ); $([anStatic[2], anStatic[3]]).addClass( (iPages===0 || iCurrentPage===iPages || oSettings._iDisplayLength===-1) ? oClasses.sPageButtonStaticDisabled : oClasses.sPageButton ); } } } } ); $.extend( DataTable.ext.oSort, { /* * text sorting */ "string-pre": function ( a ) { if ( typeof a != 'string' ) { a = (a !== null && a.toString) ? a.toString() : ''; } return a.toLowerCase(); }, "string-asc": function ( x, y ) { return ((x < y) ? -1 : ((x > y) ? 1 : 0)); }, "string-desc": function ( x, y ) { return ((x < y) ? 1 : ((x > y) ? -1 : 0)); }, /* * html sorting (ignore html tags) */ "html-pre": function ( a ) { return a.replace( /<.*?>/g, "" ).toLowerCase(); }, "html-asc": function ( x, y ) { return ((x < y) ? -1 : ((x > y) ? 1 : 0)); }, "html-desc": function ( x, y ) { return ((x < y) ? 1 : ((x > y) ? -1 : 0)); }, /* * date sorting */ "date-pre": function ( a ) { var x = Date.parse( a ); if ( isNaN(x) || x==="" ) { x = Date.parse( "01/01/1970 00:00:00" ); } return x; }, "date-asc": function ( x, y ) { return x - y; }, "date-desc": function ( x, y ) { return y - x; }, /* * numerical sorting */ "numeric-pre": function ( a ) { return (a=="-" || a==="") ? 0 : a*1; }, "numeric-asc": function ( x, y ) { return x - y; }, "numeric-desc": function ( x, y ) { return y - x; } } ); $.extend( DataTable.ext.aTypes, [ /* * Function: - * Purpose: Check to see if a string is numeric * Returns: string:'numeric' or null * Inputs: mixed:sText - string to check */ function ( sData ) { /* Allow zero length strings as a number */ if ( typeof sData === 'number' ) { return 'numeric'; } else if ( typeof sData !== 'string' ) { return null; } var sValidFirstChars = "0123456789-"; var sValidChars = "0123456789."; var Char; var bDecimal = false; /* Check for a valid first char (no period and allow negatives) */ Char = sData.charAt(0); if (sValidFirstChars.indexOf(Char) == -1) { return null; } /* Check all the other characters are valid */ for ( var i=1 ; i<sData.length ; i++ ) { Char = sData.charAt(i); if (sValidChars.indexOf(Char) == -1) { return null; } /* Only allowed one decimal place... */ if ( Char == "." ) { if ( bDecimal ) { return null; } bDecimal = true; } } return 'numeric'; }, /* * Function: - * Purpose: Check to see if a string is actually a formatted date * Returns: string:'date' or null * Inputs: string:sText - string to check */ function ( sData ) { var iParse = Date.parse(sData); if ( (iParse !== null && !isNaN(iParse)) || (typeof sData === 'string' && sData.length === 0) ) { return 'date'; } return null; }, /* * Function: - * Purpose: Check to see if a string should be treated as an HTML string * Returns: string:'html' or null * Inputs: string:sText - string to check */ function ( sData ) { if ( typeof sData === 'string' && sData.indexOf('<') != -1 && sData.indexOf('>') != -1 ) { return 'html'; } return null; } ] ); // jQuery aliases $.fn.DataTable = DataTable; $.fn.dataTable = DataTable; $.fn.dataTableSettings = DataTable.settings; $.fn.dataTableExt = DataTable.ext; // Information about events fired by DataTables - for documentation. /** * Draw event, fired whenever the table is redrawn on the page, at the same point as * fnDrawCallback. This may be useful for binding events or performing calculations when * the table is altered at all. * @name DataTable#draw * @event * @param {event} e jQuery event object * @param {object} o DataTables settings object {@link DataTable.models.oSettings} */ /** * Filter event, fired when the filtering applied to the table (using the build in global * global filter, or column filters) is altered. * @name DataTable#filter * @event * @param {event} e jQuery event object * @param {object} o DataTables settings object {@link DataTable.models.oSettings} */ /** * Page change event, fired when the paging of the table is altered. * @name DataTable#page * @event * @param {event} e jQuery event object * @param {object} o DataTables settings object {@link DataTable.models.oSettings} */ /** * Sort event, fired when the sorting applied to the table is altered. * @name DataTable#sort * @event * @param {event} e jQuery event object * @param {object} o DataTables settings object {@link DataTable.models.oSettings} */ /** * DataTables initialisation complete event, fired when the table is fully drawn, * including Ajax data loaded, if Ajax data is required. * @name DataTable#init * @event * @param {event} e jQuery event object * @param {object} oSettings DataTables settings object * @param {object} json The JSON object request from the server - only * present if client-side Ajax sourced data is used</li></ol> */ /** * State save event, fired when the table has changed state a new state save is required. * This method allows modification of the state saving object prior to actually doing the * save, including addition or other state properties (for plug-ins) or modification * of a DataTables core property. * @name DataTable#stateSaveParams * @event * @param {event} e jQuery event object * @param {object} oSettings DataTables settings object * @param {object} json The state information to be saved */ /** * State load event, fired when the table is loading state from the stored data, but * prior to the settings object being modified by the saved state - allowing modification * of the saved state is required or loading of state for a plug-in. * @name DataTable#stateLoadParams * @event * @param {event} e jQuery event object * @param {object} oSettings DataTables settings object * @param {object} json The saved state information */ /** * State loaded event, fired when state has been loaded from stored data and the settings * object has been modified by the loaded data. * @name DataTable#stateLoaded * @event * @param {event} e jQuery event object * @param {object} oSettings DataTables settings object * @param {object} json The saved state information */ /** * Processing event, fired when DataTables is doing some kind of processing (be it, * sort, filter or anything else). Can be used to indicate to the end user that * there is something happening, or that something has finished. * @name DataTable#processing * @event * @param {event} e jQuery event object * @param {object} oSettings DataTables settings object * @param {boolean} bShow Flag for if DataTables is doing processing or not */ /** * Ajax (XHR) event, fired whenever an Ajax request is completed from a request to * made to the server for new data (note that this trigger is called in fnServerData, * if you override fnServerData and which to use this event, you need to trigger it in * you success function). * @name DataTable#xhr * @event * @param {event} e jQuery event object * @param {object} o DataTables settings object {@link DataTable.models.oSettings} * @param {object} json JSON returned from the server */ /** * Destroy event, fired when the DataTable is destroyed by calling fnDestroy or passing * the bDestroy:true parameter in the initialisation object. This can be used to remove * bound events, added DOM nodes, etc. * @name DataTable#destroy * @event * @param {event} e jQuery event object * @param {object} o DataTables settings object {@link DataTable.models.oSettings} */ })); }(window, document)); /*! jQuery UI - v1.10.1 - 2013-02-15 * http://jqueryui.com * Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.effect.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.slider.js, jquery.ui.sortable.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js * Copyright (c) 2013 jQuery Foundation and other contributors Licensed MIT */ (function(e,t){function i(t,n){var r,i,o,u=t.nodeName.toLowerCase();return"area"===u?(r=t.parentNode,i=r.name,!t.href||!i||r.nodeName.toLowerCase()!=="map"?!1:(o=e("img[usemap=#"+i+"]")[0],!!o&&s(o))):(/input|select|textarea|button|object/.test(u)?!t.disabled:"a"===u?t.href||n:n)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return e.css(this,"visibility")==="hidden"}).length}var n=0,r=/^ui-id-\d+$/;e.ui=e.ui||{};if(e.ui.version)return;e.extend(e.ui,{version:"1.10.1",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({_focus:e.fn.focus,focus:function(t,n){return typeof t=="number"?this.each(function(){var r=this;setTimeout(function(){e(r).focus(),n&&n.call(r)},t)}):this._focus.apply(this,arguments)},scrollParent:function(){var t;return e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?t=this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):t=this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(n){if(n!==t)return this.css("zIndex",n);if(this.length){var r=e(this[0]),i,s;while(r.length&&r[0]!==document){i=r.css("position");if(i==="absolute"||i==="relative"||i==="fixed"){s=parseInt(r.css("zIndex"),10);if(!isNaN(s)&&s!==0)return s}r=r.parent()}}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++n)})},removeUniqueId:function(){return this.each(function(){r.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(n){return!!e.data(n,t)}}):function(t,n,r){return!!e.data(t,r[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var n=e.attr(t,"tabindex"),r=isNaN(n);return(r||n>=0)&&i(t,!r)}}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(n,r){function u(t,n,r,s){return e.each(i,function(){n-=parseFloat(e.css(t,"padding"+this))||0,r&&(n-=parseFloat(e.css(t,"border"+this+"Width"))||0),s&&(n-=parseFloat(e.css(t,"margin"+this))||0)}),n}var i=r==="Width"?["Left","Right"]:["Top","Bottom"],s=r.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+r]=function(n){return n===t?o["inner"+r].call(this):this.each(function(){e(this).css(s,u(this,n)+"px")})},e.fn["outer"+r]=function(t,n){return typeof t!="number"?o["outer"+r].call(this,t):this.each(function(){e(this).css(s,u(this,t,!0,n)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(n){return arguments.length?t.call(this,e.camelCase(n)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,n,r){var i,s=e.ui[t].prototype;for(i in r)s.plugins[i]=s.plugins[i]||[],s.plugins[i].push([n,r[i]])},call:function(e,t,n){var r,i=e.plugins[t];if(!i||!e.element[0].parentNode||e.element[0].parentNode.nodeType===11)return;for(r=0;r<i.length;r++)e.options[i[r][0]]&&i[r][1].apply(e.element,n)}},hasScroll:function(t,n){if(e(t).css("overflow")==="hidden")return!1;var r=n&&n==="left"?"scrollLeft":"scrollTop",i=!1;return t[r]>0?!0:(t[r]=1,i=t[r]>0,t[r]=0,i)}})})(jQuery);(function(e,t){var n=0,r=Array.prototype.slice,i=e.cleanData;e.cleanData=function(t){for(var n=0,r;(r=t[n])!=null;n++)try{e(r).triggerHandler("remove")}catch(s){}i(t)},e.widget=function(t,n,r){var i,s,o,u,a={},f=t.split(".")[0];t=t.split(".")[1],i=f+"-"+t,r||(r=n,n=e.Widget),e.expr[":"][i.toLowerCase()]=function(t){return!!e.data(t,i)},e[f]=e[f]||{},s=e[f][t],o=e[f][t]=function(e,t){if(!this._createWidget)return new o(e,t);arguments.length&&this._createWidget(e,t)},e.extend(o,s,{version:r.version,_proto:e.extend({},r),_childConstructors:[]}),u=new n,u.options=e.widget.extend({},u.options),e.each(r,function(t,r){if(!e.isFunction(r)){a[t]=r;return}a[t]=function(){var e=function(){return n.prototype[t].apply(this,arguments)},i=function(e){return n.prototype[t].apply(this,e)};return function(){var t=this._super,n=this._superApply,s;return this._super=e,this._superApply=i,s=r.apply(this,arguments),this._super=t,this._superApply=n,s}}()}),o.prototype=e.widget.extend(u,{widgetEventPrefix:s?u.widgetEventPrefix:t},a,{constructor:o,namespace:f,widgetName:t,widgetFullName:i}),s?(e.each(s._childConstructors,function(t,n){var r=n.prototype;e.widget(r.namespace+"."+r.widgetName,o,n._proto)}),delete s._childConstructors):n._childConstructors.push(o),e.widget.bridge(t,o)},e.widget.extend=function(n){var i=r.call(arguments,1),s=0,o=i.length,u,a;for(;s<o;s++)for(u in i[s])a=i[s][u],i[s].hasOwnProperty(u)&&a!==t&&(e.isPlainObject(a)?n[u]=e.isPlainObject(n[u])?e.widget.extend({},n[u],a):e.widget.extend({},a):n[u]=a);return n},e.widget.bridge=function(n,i){var s=i.prototype.widgetFullName||n;e.fn[n]=function(o){var u=typeof o=="string",a=r.call(arguments,1),f=this;return o=!u&&a.length?e.widget.extend.apply(null,[o].concat(a)):o,u?this.each(function(){var r,i=e.data(this,s);if(!i)return e.error("cannot call methods on "+n+" prior to initialization; "+"attempted to call method '"+o+"'");if(!e.isFunction(i[o])||o.charAt(0)==="_")return e.error("no such method '"+o+"' for "+n+" widget instance");r=i[o].apply(i,a);if(r!==i&&r!==t)return f=r&&r.jquery?f.pushStack(r.get()):r,!1}):this.each(function(){var t=e.data(this,s);t?t.option(o||{})._init():e.data(this,s,new i(o,this))}),f}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(t,r){r=e(r||this.defaultElement||this)[0],this.element=e(r),this.uuid=n++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),r!==this&&(e.data(r,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===r&&this.destroy()}}),this.document=e(r.style?r.ownerDocument:r.document||r),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(n,r){var i=n,s,o,u;if(arguments.length===0)return e.widget.extend({},this.options);if(typeof n=="string"){i={},s=n.split("."),n=s.shift();if(s.length){o=i[n]=e.widget.extend({},this.options[n]);for(u=0;u<s.length-1;u++)o[s[u]]=o[s[u]]||{},o=o[s[u]];n=s.pop();if(r===t)return o[n]===t?null:o[n];o[n]=r}else{if(r===t)return this.options[n]===t?null:this.options[n];i[n]=r}}return this._setOptions(i),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,e==="disabled"&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(t,n,r){var i,s=this;typeof t!="boolean"&&(r=n,n=t,t=!1),r?(n=i=e(n),this.bindings=this.bindings.add(n)):(r=n,n=this.element,i=this.widget()),e.each(r,function(r,o){function u(){if(!t&&(s.options.disabled===!0||e(this).hasClass("ui-state-disabled")))return;return(typeof o=="string"?s[o]:o).apply(s,arguments)}typeof o!="string"&&(u.guid=o.guid=o.guid||u.guid||e.guid++);var a=r.match(/^(\w+)\s*(.*)$/),f=a[1]+s.eventNamespace,l=a[2];l?i.delegate(l,f,u):n.bind(f,u)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function n(){return(typeof e=="string"?r[e]:e).apply(r,arguments)}var r=this;return setTimeout(n,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,n,r){var i,s,o=this.options[t];r=r||{},n=e.Event(n),n.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),n.target=this.element[0],s=n.originalEvent;if(s)for(i in s)i in n||(n[i]=s[i]);return this.element.trigger(n,r),!(e.isFunction(o)&&o.apply(this.element[0],[n].concat(r))===!1||n.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,n){e.Widget.prototype["_"+t]=function(r,i,s){typeof i=="string"&&(i={effect:i});var o,u=i?i===!0||typeof i=="number"?n:i.effect||n:t;i=i||{},typeof i=="number"&&(i={duration:i}),o=!e.isEmptyObject(i),i.complete=s,i.delay&&r.delay(i.delay),o&&e.effects&&e.effects.effect[u]?r[t](i):u!==t&&r[u]?r[u](i.duration,i.easing,s):r.queue(function(n){e(this)[t](),s&&s.call(r[0]),n()})}})})(jQuery);(function(e,t){var n=!1;e(document).mouseup(function(){n=!1}),e.widget("ui.mouse",{version:"1.10.1",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(n){if(!0===e.data(n.target,t.widgetName+".preventClickEvent"))return e.removeData(n.target,t.widgetName+".preventClickEvent"),n.stopImmediatePropagation(),!1}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(t){if(n)return;this._mouseStarted&&this._mouseUp(t),this._mouseDownEvent=t;var r=this,i=t.which===1,s=typeof this.options.cancel=="string"&&t.target.nodeName?e(t.target).closest(this.options.cancel).length:!1;if(!i||s||!this._mouseCapture(t))return!0;this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){r.mouseDelayMet=!0},this.options.delay));if(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)){this._mouseStarted=this._mouseStart(t)!==!1;if(!this._mouseStarted)return t.preventDefault(),!0}return!0===e.data(t.target,this.widgetName+".preventClickEvent")&&e.removeData(t.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return r._mouseMove(e)},this._mouseUpDelegate=function(e){return r._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),t.preventDefault(),n=!0,!0},_mouseMove:function(t){return e.ui.ie&&(!document.documentMode||document.documentMode<9)&&!t.button?this._mouseUp(t):this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(e,t){function h(e,t,n){return[parseFloat(e[0])*(l.test(e[0])?t/100:1),parseFloat(e[1])*(l.test(e[1])?n/100:1)]}function p(t,n){return parseInt(e.css(t,n),10)||0}function d(t){var n=t[0];return n.nodeType===9?{width:t.width(),height:t.height(),offset:{top:0,left:0}}:e.isWindow(n)?{width:t.width(),height:t.height(),offset:{top:t.scrollTop(),left:t.scrollLeft()}}:n.preventDefault?{width:0,height:0,offset:{top:n.pageY,left:n.pageX}}:{width:t.outerWidth(),height:t.outerHeight(),offset:t.offset()}}e.ui=e.ui||{};var n,r=Math.max,i=Math.abs,s=Math.round,o=/left|center|right/,u=/top|center|bottom/,a=/[\+\-]\d+(\.[\d]+)?%?/,f=/^\w+/,l=/%$/,c=e.fn.position;e.position={scrollbarWidth:function(){if(n!==t)return n;var r,i,s=e("<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),o=s.children()[0];return e("body").append(s),r=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,r===i&&(i=s[0].clientWidth),s.remove(),n=r-i},getScrollInfo:function(t){var n=t.isWindow?"":t.element.css("overflow-x"),r=t.isWindow?"":t.element.css("overflow-y"),i=n==="scroll"||n==="auto"&&t.width<t.element[0].scrollWidth,s=r==="scroll"||r==="auto"&&t.height<t.element[0].scrollHeight;return{width:i?e.position.scrollbarWidth():0,height:s?e.position.scrollbarWidth():0}},getWithinInfo:function(t){var n=e(t||window),r=e.isWindow(n[0]);return{element:n,isWindow:r,offset:n.offset()||{left:0,top:0},scrollLeft:n.scrollLeft(),scrollTop:n.scrollTop(),width:r?n.width():n.outerWidth(),height:r?n.height():n.outerHeight()}}},e.fn.position=function(t){if(!t||!t.of)return c.apply(this,arguments);t=e.extend({},t);var n,l,v,m,g,y,b=e(t.of),w=e.position.getWithinInfo(t.within),E=e.position.getScrollInfo(w),S=(t.collision||"flip").split(" "),x={};return y=d(b),b[0].preventDefault&&(t.at="left top"),l=y.width,v=y.height,m=y.offset,g=e.extend({},m),e.each(["my","at"],function(){var e=(t[this]||"").split(" "),n,r;e.length===1&&(e=o.test(e[0])?e.concat(["center"]):u.test(e[0])?["center"].concat(e):["center","center"]),e[0]=o.test(e[0])?e[0]:"center",e[1]=u.test(e[1])?e[1]:"center",n=a.exec(e[0]),r=a.exec(e[1]),x[this]=[n?n[0]:0,r?r[0]:0],t[this]=[f.exec(e[0])[0],f.exec(e[1])[0]]}),S.length===1&&(S[1]=S[0]),t.at[0]==="right"?g.left+=l:t.at[0]==="center"&&(g.left+=l/2),t.at[1]==="bottom"?g.top+=v:t.at[1]==="center"&&(g.top+=v/2),n=h(x.at,l,v),g.left+=n[0],g.top+=n[1],this.each(function(){var o,u,a=e(this),f=a.outerWidth(),c=a.outerHeight(),d=p(this,"marginLeft"),y=p(this,"marginTop"),T=f+d+p(this,"marginRight")+E.width,N=c+y+p(this,"marginBottom")+E.height,C=e.extend({},g),k=h(x.my,a.outerWidth(),a.outerHeight());t.my[0]==="right"?C.left-=f:t.my[0]==="center"&&(C.left-=f/2),t.my[1]==="bottom"?C.top-=c:t.my[1]==="center"&&(C.top-=c/2),C.left+=k[0],C.top+=k[1],e.support.offsetFractions||(C.left=s(C.left),C.top=s(C.top)),o={marginLeft:d,marginTop:y},e.each(["left","top"],function(r,i){e.ui.position[S[r]]&&e.ui.position[S[r]][i](C,{targetWidth:l,targetHeight:v,elemWidth:f,elemHeight:c,collisionPosition:o,collisionWidth:T,collisionHeight:N,offset:[n[0]+k[0],n[1]+k[1]],my:t.my,at:t.at,within:w,elem:a})}),t.using&&(u=function(e){var n=m.left-C.left,s=n+l-f,o=m.top-C.top,u=o+v-c,h={target:{element:b,left:m.left,top:m.top,width:l,height:v},element:{element:a,left:C.left,top:C.top,width:f,height:c},horizontal:s<0?"left":n>0?"right":"center",vertical:u<0?"top":o>0?"bottom":"middle"};l<f&&i(n+s)<l&&(h.horizontal="center"),v<c&&i(o+u)<v&&(h.vertical="middle"),r(i(n),i(s))>r(i(o),i(u))?h.important="horizontal":h.important="vertical",t.using.call(this,e,h)}),a.offset(e.extend(C,{using:u}))})},e.ui.position={fit:{left:function(e,t){var n=t.within,i=n.isWindow?n.scrollLeft:n.offset.left,s=n.width,o=e.left-t.collisionPosition.marginLeft,u=i-o,a=o+t.collisionWidth-s-i,f;t.collisionWidth>s?u>0&&a<=0?(f=e.left+u+t.collisionWidth-s-i,e.left+=u-f):a>0&&u<=0?e.left=i:u>a?e.left=i+s-t.collisionWidth:e.left=i:u>0?e.left+=u:a>0?e.left-=a:e.left=r(e.left-o,e.left)},top:function(e,t){var n=t.within,i=n.isWindow?n.scrollTop:n.offset.top,s=t.within.height,o=e.top-t.collisionPosition.marginTop,u=i-o,a=o+t.collisionHeight-s-i,f;t.collisionHeight>s?u>0&&a<=0?(f=e.top+u+t.collisionHeight-s-i,e.top+=u-f):a>0&&u<=0?e.top=i:u>a?e.top=i+s-t.collisionHeight:e.top=i:u>0?e.top+=u:a>0?e.top-=a:e.top=r(e.top-o,e.top)}},flip:{left:function(e,t){var n=t.within,r=n.offset.left+n.scrollLeft,s=n.width,o=n.isWindow?n.scrollLeft:n.offset.left,u=e.left-t.collisionPosition.marginLeft,a=u-o,f=u+t.collisionWidth-s-o,l=t.my[0]==="left"?-t.elemWidth:t.my[0]==="right"?t.elemWidth:0,c=t.at[0]==="left"?t.targetWidth:t.at[0]==="right"?-t.targetWidth:0,h=-2*t.offset[0],p,d;if(a<0){p=e.left+l+c+h+t.collisionWidth-s-r;if(p<0||p<i(a))e.left+=l+c+h}else if(f>0){d=e.left-t.collisionPosition.marginLeft+l+c+h-o;if(d>0||i(d)<f)e.left+=l+c+h}},top:function(e,t){var n=t.within,r=n.offset.top+n.scrollTop,s=n.height,o=n.isWindow?n.scrollTop:n.offset.top,u=e.top-t.collisionPosition.marginTop,a=u-o,f=u+t.collisionHeight-s-o,l=t.my[1]==="top",c=l?-t.elemHeight:t.my[1]==="bottom"?t.elemHeight:0,h=t.at[1]==="top"?t.targetHeight:t.at[1]==="bottom"?-t.targetHeight:0,p=-2*t.offset[1],d,v;a<0?(v=e.top+c+h+p+t.collisionHeight-s-r,e.top+c+h+p>a&&(v<0||v<i(a))&&(e.top+=c+h+p)):f>0&&(d=e.top-t.collisionPosition.marginTop+c+h+p-o,e.top+c+h+p>f&&(d>0||i(d)<f)&&(e.top+=c+h+p))}},flipfit:{left:function(){e.ui.position.flip.left.apply(this,arguments),e.ui.position.fit.left.apply(this,arguments)},top:function(){e.ui.position.flip.top.apply(this,arguments),e.ui.position.fit.top.apply(this,arguments)}}},function(){var t,n,r,i,s,o=document.getElementsByTagName("body")[0],u=document.createElement("div");t=document.createElement(o?"div":"body"),r={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},o&&e.extend(r,{position:"absolute",left:"-1000px",top:"-1000px"});for(s in r)t.style[s]=r[s];t.appendChild(u),n=o||document.documentElement,n.insertBefore(t,n.firstChild),u.style.cssText="position: absolute; left: 10.7432222px;",i=e(u).offset().left,e.support.offsetFractions=i>10&&i<11,t.innerHTML="",n.removeChild(t)}()})(jQuery);(function(e,t){var n=0,r={},i={};r.height=r.paddingTop=r.paddingBottom=r.borderTopWidth=r.borderBottomWidth="hide",i.height=i.paddingTop=i.paddingBottom=i.borderTopWidth=i.borderBottomWidth="show",e.widget("ui.accordion",{version:"1.10.1",options:{active:0,animate:{},collapsible:!1,event:"click",header:"> li > :first-child,> :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},_create:function(){var t=this.options;this.prevShow=this.prevHide=e(),this.element.addClass("ui-accordion ui-widget ui-helper-reset").attr("role","tablist"),!t.collapsible&&(t.active===!1||t.active==null)&&(t.active=0),this._processPanels(),t.active<0&&(t.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():e(),content:this.active.length?this.active.next():e()}},_createIcons:function(){var t=this.options.icons;t&&(e("<span>").addClass("ui-accordion-header-icon ui-icon "+t.header).prependTo(this.headers),this.active.children(".ui-accordion-header-icon").removeClass(t.header).addClass(t.activeHeader),this.headers.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()},_destroy:function(){var e;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.removeClass("ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this._destroyIcons(),e=this.headers.next().css("display","").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this.options.heightStyle!=="content"&&e.css("height","")},_setOption:function(e,t){if(e==="active"){this._activate(t);return}e==="event"&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(t)),this._super(e,t),e==="collapsible"&&!t&&this.options.active===!1&&this._activate(0),e==="icons"&&(this._destroyIcons(),t&&this._createIcons()),e==="disabled"&&this.headers.add(this.headers.next()).toggleClass("ui-state-disabled",!!t)},_keydown:function(t){if(t.altKey||t.ctrlKey)return;var n=e.ui.keyCode,r=this.headers.length,i=this.headers.index(t.target),s=!1;switch(t.keyCode){case n.RIGHT:case n.DOWN:s=this.headers[(i+1)%r];break;case n.LEFT:case n.UP:s=this.headers[(i-1+r)%r];break;case n.SPACE:case n.ENTER:this._eventHandler(t);break;case n.HOME:s=this.headers[0];break;case n.END:s=this.headers[r-1]}s&&(e(t.target).attr("tabIndex",-1),e(s).attr("tabIndex",0),s.focus(),t.preventDefault())},_panelKeyDown:function(t){t.keyCode===e.ui.keyCode.UP&&t.ctrlKey&&e(t.currentTarget).prev().focus()},refresh:function(){var t=this.options;this._processPanels();if(t.active===!1&&t.collapsible===!0||!this.headers.length)t.active=!1,this.active=e();t.active===!1?this._activate(0):this.active.length&&!e.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(t.active=!1,this.active=e()):this._activate(Math.max(0,t.active-1)):t.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){this.headers=this.element.find(this.options.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all"),this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").filter(":not(.ui-accordion-content-active)").hide()},_refresh:function(){var t,r=this.options,i=r.heightStyle,s=this.element.parent(),o=this.accordionId="ui-accordion-"+(this.element.attr("id")||++n);this.active=this._findActive(r.active).addClass("ui-accordion-header-active ui-state-active ui-corner-top").removeClass("ui-corner-all"),this.active.next().addClass("ui-accordion-content-active").show(),this.headers.attr("role","tab").each(function(t){var n=e(this),r=n.attr("id"),i=n.next(),s=i.attr("id");r||(r=o+"-header-"+t,n.attr("id",r)),s||(s=o+"-panel-"+t,i.attr("id",s)),n.attr("aria-controls",s),i.attr("aria-labelledby",r)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false",tabIndex:-1}).next().attr({"aria-expanded":"false","aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true",tabIndex:0}).next().attr({"aria-expanded":"true","aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(r.event),i==="fill"?(t=s.height(),this.element.siblings(":visible").each(function(){var n=e(this),r=n.css("position");if(r==="absolute"||r==="fixed")return;t-=n.outerHeight(!0)}),this.headers.each(function(){t-=e(this).outerHeight(!0)}),this.headers.next().each(function(){e(this).height(Math.max(0,t-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):i==="auto"&&(t=0,this.headers.next().each(function(){t=Math.max(t,e(this).css("height","").height())}).height(t))},_activate:function(t){var n=this._findActive(t)[0];if(n===this.active[0])return;n=n||this.active[0],this._eventHandler({target:n,currentTarget:n,preventDefault:e.noop})},_findActive:function(t){return typeof t=="number"?this.headers.eq(t):e()},_setupEvents:function(t){var n={keydown:"_keydown"};t&&e.each(t.split(" "),function(e,t){n[t]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,n),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(t){var n=this.options,r=this.active,i=e(t.currentTarget),s=i[0]===r[0],o=s&&n.collapsible,u=o?e():i.next(),a=r.next(),f={oldHeader:r,oldPanel:a,newHeader:o?e():i,newPanel:u};t.preventDefault();if(s&&!n.collapsible||this._trigger("beforeActivate",t,f)===!1)return;n.active=o?!1:this.headers.index(i),this.active=s?e():i,this._toggle(f),r.removeClass("ui-accordion-header-active ui-state-active"),n.icons&&r.children(".ui-accordion-header-icon").removeClass(n.icons.activeHeader).addClass(n.icons.header),s||(i.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"),n.icons&&i.children(".ui-accordion-header-icon").removeClass(n.icons.header).addClass(n.icons.activeHeader),i.next().addClass("ui-accordion-content-active"))},_toggle:function(t){var n=t.newPanel,r=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=n,this.prevHide=r,this.options.animate?this._animate(n,r,t):(r.hide(),n.show(),this._toggleComplete(t)),r.attr({"aria-expanded":"false","aria-hidden":"true"}),r.prev().attr("aria-selected","false"),n.length&&r.length?r.prev().attr("tabIndex",-1):n.length&&this.headers.filter(function(){return e(this).attr("tabIndex")===0}).attr("tabIndex",-1),n.attr({"aria-expanded":"true","aria-hidden":"false"}).prev().attr({"aria-selected":"true",tabIndex:0})},_animate:function(e,t,n){var s,o,u,a=this,f=0,l=e.length&&(!t.length||e.index()<t.index()),c=this.options.animate||{},h=l&&c.down||c,p=function(){a._toggleComplete(n)};typeof h=="number"&&(u=h),typeof h=="string"&&(o=h),o=o||h.easing||c.easing,u=u||h.duration||c.duration;if(!t.length)return e.animate(i,u,o,p);if(!e.length)return t.animate(r,u,o,p);s=e.show().outerHeight(),t.animate(r,{duration:u,easing:o,step:function(e,t){t.now=Math.round(e)}}),e.hide().animate(i,{duration:u,easing:o,complete:p,step:function(e,n){n.now=Math.round(e),n.prop!=="height"?f+=n.now:a.options.heightStyle!=="content"&&(n.now=Math.round(s-t.outerHeight()-f),f=0)}})},_toggleComplete:function(e){var t=e.oldPanel;t.removeClass("ui-accordion-content-active").prev().removeClass("ui-corner-top").addClass("ui-corner-all"),t.length&&(t.parent()[0].className=t.parent()[0].className),this._trigger("activate",null,e)}})})(jQuery);(function(e,t){var n=0;e.widget("ui.autocomplete",{version:"1.10.1",defaultElement:"<input>",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},pending:0,_create:function(){var t,n,r,i=this.element[0].nodeName.toLowerCase(),s=i==="textarea",o=i==="input";this.isMultiLine=s?!0:o?!1:this.element.prop("isContentEditable"),this.valueMethod=this.element[s||o?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(i){if(this.element.prop("readOnly")){t=!0,r=!0,n=!0;return}t=!1,r=!1,n=!1;var s=e.ui.keyCode;switch(i.keyCode){case s.PAGE_UP:t=!0,this._move("previousPage",i);break;case s.PAGE_DOWN:t=!0,this._move("nextPage",i);break;case s.UP:t=!0,this._keyEvent("previous",i);break;case s.DOWN:t=!0,this._keyEvent("next",i);break;case s.ENTER:case s.NUMPAD_ENTER:this.menu.active&&(t=!0,i.preventDefault(),this.menu.select(i));break;case s.TAB:this.menu.active&&this.menu.select(i);break;case s.ESCAPE:this.menu.element.is(":visible")&&(this._value(this.term),this.close(i),i.preventDefault());break;default:n=!0,this._searchTimeout(i)}},keypress:function(r){if(t){t=!1,r.preventDefault();return}if(n)return;var i=e.ui.keyCode;switch(r.keyCode){case i.PAGE_UP:this._move("previousPage",r);break;case i.PAGE_DOWN:this._move("nextPage",r);break;case i.UP:this._keyEvent("previous",r);break;case i.DOWN:this._keyEvent("next",r)}},input:function(e){if(r){r=!1,e.preventDefault();return}this._searchTimeout(e)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){if(this.cancelBlur){delete this.cancelBlur;return}clearTimeout(this.searching),this.close(e),this._change(e)}}),this._initSource(),this.menu=e("<ul>").addClass("ui-autocomplete ui-front").appendTo(this._appendTo()).menu({input:e(),role:null}).hide().data("ui-menu"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur});var n=this.menu.element[0];e(t.target).closest(".ui-menu-item").length||this._delay(function(){var t=this;this.document.one("mousedown",function(r){r.target!==t.element[0]&&r.target!==n&&!e.contains(n,r.target)&&t.close()})})},menufocus:function(t,n){if(this.isNewMenu){this.isNewMenu=!1;if(t.originalEvent&&/^mouse/.test(t.originalEvent.type)){this.menu.blur(),this.document.one("mousemove",function(){e(t.target).trigger(t.originalEvent)});return}}var r=n.item.data("ui-autocomplete-item");!1!==this._trigger("focus",t,{item:r})?t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(r.value):this.liveRegion.text(r.value)},menuselect:function(e,t){var n=t.item.data("ui-autocomplete-item"),r=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=r,this._delay(function(){this.previous=r,this.selectedItem=n})),!1!==this._trigger("select",e,{item:n})&&this._value(n.value),this.term=this._value(),this.close(e),this.selectedItem=n}}),this.liveRegion=e("<span>",{role:"status","aria-live":"polite"}).addClass("ui-helper-hidden-accessible").insertAfter(this.element),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(e,t){this._super(e,t),e==="source"&&this._initSource(),e==="appendTo"&&this.menu.element.appendTo(this._appendTo()),e==="disabled"&&t&&this.xhr&&this.xhr.abort()},_appendTo:function(){var t=this.options.appendTo;return t&&(t=t.jquery||t.nodeType?e(t):this.document.find(t).eq(0)),t||(t=this.element.closest(".ui-front")),t.length||(t=this.document[0].body),t},_initSource:function(){var t,n,r=this;e.isArray(this.options.source)?(t=this.options.source,this.source=function(n,r){r(e.ui.autocomplete.filter(t,n.term))}):typeof this.options.source=="string"?(n=this.options.source,this.source=function(t,i){r.xhr&&r.xhr.abort(),r.xhr=e.ajax({url:n,data:t,dataType:"json",success:function(e){i(e)},error:function(){i([])}})}):this.source=this.options.source},_searchTimeout:function(e){clearTimeout(this.searching),this.searching=this._delay(function(){this.term!==this._value()&&(this.selectedItem=null,this.search(null,e))},this.options.delay)},search:function(e,t){e=e!=null?e:this._value(),this.term=this._value();if(e.length<this.options.minLength)return this.close(t);if(this._trigger("search",t)===!1)return;return this._search(e)},_search:function(e){this.pending++,this.element.addClass("ui-autocomplete-loading"),this.cancelSearch=!1,this.source({term:e},this._response())},_response:function(){var e=this,t=++n;return function(r){t===n&&e.__response(r),e.pending--,e.pending||e.element.removeClass("ui-autocomplete-loading")}},__response:function(e){e&&(e=this._normalize(e)),this._trigger("response",null,{content:e}),!this.options.disabled&&e&&e.length&&!this.cancelSearch?(this._suggest(e),this._trigger("open")):this._close()},close:function(e){this.cancelSearch=!0,this._close(e)},_close:function(e){this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.blur(),this.isNewMenu=!0,this._trigger("close",e))},_change:function(e){this.previous!==this._value()&&this._trigger("change",e,{item:this.selectedItem})},_normalize:function(t){return t.length&&t[0].label&&t[0].value?t:e.map(t,function(t){return typeof t=="string"?{label:t,value:t}:e.extend({label:t.label||t.value,value:t.value||t.label},t)})},_suggest:function(t){var n=this.menu.element.empty();this._renderMenu(n,t),this.menu.refresh(),n.show(),this._resizeMenu(),n.position(e.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next()},_resizeMenu:function(){var e=this.menu.element;e.outerWidth(Math.max(e.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(t,n){var r=this;e.each(n,function(e,n){r._renderItemData(t,n)})},_renderItemData:function(e,t){return this._renderItem(e,t).data("ui-autocomplete-item",t)},_renderItem:function(t,n){return e("<li>").append(e("<a>").text(n.label)).appendTo(t)},_move:function(e,t){if(!this.menu.element.is(":visible")){this.search(null,t);return}if(this.menu.isFirstItem()&&/^previous/.test(e)||this.menu.isLastItem()&&/^next/.test(e)){this._value(this.term),this.menu.blur();return}this.menu[e](t)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(e,t){if(!this.isMultiLine||this.menu.element.is(":visible"))this._move(e,t),t.preventDefault()}}),e.extend(e.ui.autocomplete,{escapeRegex:function(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,n){var r=new RegExp(e.ui.autocomplete.escapeRegex(n),"i");return e.grep(t,function(e){return r.test(e.label||e.value||e)})}}),e.widget("ui.autocomplete",e.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(e){return e+(e>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(e){var t;this._superApply(arguments);if(this.options.disabled||this.cancelSearch)return;e&&e.length?t=this.options.messages.results(e.length):t=this.options.messages.noResults,this.liveRegion.text(t)}})})(jQuery);(function(e,t){var n,r,i,s,o="ui-button ui-widget ui-state-default ui-corner-all",u="ui-state-hover ui-state-active ",a="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",f=function(){var t=e(this).find(":ui-button");setTimeout(function(){t.button("refresh")},1)},l=function(t){var n=t.name,r=t.form,i=e([]);return n&&(n=n.replace(/'/g,"\\'"),r?i=e(r).find("[name='"+n+"']"):i=e("[name='"+n+"']",t.ownerDocument).filter(function(){return!this.form})),i};e.widget("ui.button",{version:"1.10.1",defaultElement:"<button>",options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset"+this.eventNamespace).bind("reset"+this.eventNamespace,f),typeof this.options.disabled!="boolean"?this.options.disabled=!!this.element.prop("disabled"):this.element.prop("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var t=this,u=this.options,a=this.type==="checkbox"||this.type==="radio",c=a?"":"ui-state-active",h="ui-state-focus";u.label===null&&(u.label=this.type==="input"?this.buttonElement.val():this.buttonElement.html()),this._hoverable(this.buttonElement),this.buttonElement.addClass(o).attr("role","button").bind("mouseenter"+this.eventNamespace,function(){if(u.disabled)return;this===n&&e(this).addClass("ui-state-active")}).bind("mouseleave"+this.eventNamespace,function(){if(u.disabled)return;e(this).removeClass(c)}).bind("click"+this.eventNamespace,function(e){u.disabled&&(e.preventDefault(),e.stopImmediatePropagation())}),this.element.bind("focus"+this.eventNamespace,function(){t.buttonElement.addClass(h)}).bind("blur"+this.eventNamespace,function(){t.buttonElement.removeClass(h)}),a&&(this.element.bind("change"+this.eventNamespace,function(){if(s)return;t.refresh()}),this.buttonElement.bind("mousedown"+this.eventNamespace,function(e){if(u.disabled)return;s=!1,r=e.pageX,i=e.pageY}).bind("mouseup"+this.eventNamespace,function(e){if(u.disabled)return;if(r!==e.pageX||i!==e.pageY)s=!0})),this.type==="checkbox"?this.buttonElement.bind("click"+this.eventNamespace,function(){if(u.disabled||s)return!1}):this.type==="radio"?this.buttonElement.bind("click"+this.eventNamespace,function(){if(u.disabled||s)return!1;e(this).addClass("ui-state-active"),t.buttonElement.attr("aria-pressed","true");var n=t.element[0];l(n).not(n).map(function(){return e(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown"+this.eventNamespace,function(){if(u.disabled)return!1;e(this).addClass("ui-state-active"),n=this,t.document.one("mouseup",function(){n=null})}).bind("mouseup"+this.eventNamespace,function(){if(u.disabled)return!1;e(this).removeClass("ui-state-active")}).bind("keydown"+this.eventNamespace,function(t){if(u.disabled)return!1;(t.keyCode===e.ui.keyCode.SPACE||t.keyCode===e.ui.keyCode.ENTER)&&e(this).addClass("ui-state-active")}).bind("keyup"+this.eventNamespace+" blur"+this.eventNamespace,function(){e(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(t){t.keyCode===e.ui.keyCode.SPACE&&e(this).click()})),this._setOption("disabled",u.disabled),this._resetButton()},_determineButtonType:function(){var e,t,n;this.element.is("[type=checkbox]")?this.type="checkbox":this.element.is("[type=radio]")?this.type="radio":this.element.is("input")?this.type="input":this.type="button",this.type==="checkbox"||this.type==="radio"?(e=this.element.parents().last(),t="label[for='"+this.element.attr("id")+"']",this.buttonElement=e.find(t),this.buttonElement.length||(e=e.length?e.siblings():this.element.siblings(),this.buttonElement=e.filter(t),this.buttonElement.length||(this.buttonElement=e.find(t))),this.element.addClass("ui-helper-hidden-accessible"),n=this.element.is(":checked"),n&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.prop("aria-pressed",n)):this.buttonElement=this.element},widget:function(){return this.buttonElement},_destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(o+" "+u+" "+a).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title")},_setOption:function(e,t){this._super(e,t);if(e==="disabled"){t?this.element.prop("disabled",!0):this.element.prop("disabled",!1);return}this._resetButton()},refresh:function(){var t=this.element.is("input, button")?this.element.is(":disabled"):this.element.hasClass("ui-button-disabled");t!==this.options.disabled&&this._setOption("disabled",t),this.type==="radio"?l(this.element[0]).each(function(){e(this).is(":checked")?e(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):e(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):this.type==="checkbox"&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if(this.type==="input"){this.options.label&&this.element.val(this.options.label);return}var t=this.buttonElement.removeClass(a),n=e("<span></span>",this.document[0]).addClass("ui-button-text").html(this.options.label).appendTo(t.empty()).text(),r=this.options.icons,i=r.primary&&r.secondary,s=[];r.primary||r.secondary?(this.options.text&&s.push("ui-button-text-icon"+(i?"s":r.primary?"-primary":"-secondary")),r.primary&&t.prepend("<span class='ui-button-icon-primary ui-icon "+r.primary+"'></span>"),r.secondary&&t.append("<span class='ui-button-icon-secondary ui-icon "+r.secondary+"'></span>"),this.options.text||(s.push(i?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||t.attr("title",e.trim(n)))):s.push("ui-button-text-only"),t.addClass(s.join(" "))}}),e.widget("ui.buttonset",{version:"1.10.1",options:{items:"button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(e,t){e==="disabled"&&this.buttons.button("option",e,t),this._super(e,t)},refresh:function(){var t=this.element.css("direction")==="rtl";this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(t?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(t?"ui-corner-left":"ui-corner-right").end().end()},_destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy")}})})(jQuery);(function(e,t){function s(){this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},e.extend(this._defaults,this.regional[""]),this.dpDiv=o(e("<div id='"+this._mainDivId+"' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"))}function o(t){var n="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return t.delegate(n,"mouseout",function(){e(this).removeClass("ui-state-hover"),this.className.indexOf("ui-datepicker-prev")!==-1&&e(this).removeClass("ui-datepicker-prev-hover"),this.className.indexOf("ui-datepicker-next")!==-1&&e(this).removeClass("ui-datepicker-next-hover")}).delegate(n,"mouseover",function(){e.datepicker._isDisabledDatepicker(i.inline?t.parent()[0]:i.input[0])||(e(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),e(this).addClass("ui-state-hover"),this.className.indexOf("ui-datepicker-prev")!==-1&&e(this).addClass("ui-datepicker-prev-hover"),this.className.indexOf("ui-datepicker-next")!==-1&&e(this).addClass("ui-datepicker-next-hover"))})}function u(t,n){e.extend(t,n);for(var r in n)n[r]==null&&(t[r]=n[r]);return t}e.extend(e.ui,{datepicker:{version:"1.10.1"}});var n="datepicker",r=(new Date).getTime(),i;e.extend(s.prototype,{markerClassName:"hasDatepicker",maxRows:4,_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(e){return u(this._defaults,e||{}),this},_attachDatepicker:function(t,n){var r,i,s;r=t.nodeName.toLowerCase(),i=r==="div"||r==="span",t.id||(this.uuid+=1,t.id="dp"+this.uuid),s=this._newInst(e(t),i),s.settings=e.extend({},n||{}),r==="input"?this._connectDatepicker(t,s):i&&this._inlineDatepicker(t,s)},_newInst:function(t,n){var r=t[0].id.replace(/([^A-Za-z0-9_\-])/g,"\\\\$1");return{id:r,input:t,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:n,dpDiv:n?o(e("<div class='"+this._inlineClass+" ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")):this.dpDiv}},_connectDatepicker:function(t,r){var i=e(t);r.append=e([]),r.trigger=e([]);if(i.hasClass(this.markerClassName))return;this._attachments(i,r),i.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp),this._autoSize(r),e.data(t,n,r),r.settings.disabled&&this._disableDatepicker(t)},_attachments:function(t,n){var r,i,s,o=this._get(n,"appendText"),u=this._get(n,"isRTL");n.append&&n.append.remove(),o&&(n.append=e("<span class='"+this._appendClass+"'>"+o+"</span>"),t[u?"before":"after"](n.append)),t.unbind("focus",this._showDatepicker),n.trigger&&n.trigger.remove(),r=this._get(n,"showOn"),(r==="focus"||r==="both")&&t.focus(this._showDatepicker);if(r==="button"||r==="both")i=this._get(n,"buttonText"),s=this._get(n,"buttonImage"),n.trigger=e(this._get(n,"buttonImageOnly")?e("<img/>").addClass(this._triggerClass).attr({src:s,alt:i,title:i}):e("<button type='button'></button>").addClass(this._triggerClass).html(s?e("<img/>").attr({src:s,alt:i,title:i}):i)),t[u?"before":"after"](n.trigger),n.trigger.click(function(){return e.datepicker._datepickerShowing&&e.datepicker._lastInput===t[0]?e.datepicker._hideDatepicker():e.datepicker._datepickerShowing&&e.datepicker._lastInput!==t[0]?(e.datepicker._hideDatepicker(),e.datepicker._showDatepicker(t[0])):e.datepicker._showDatepicker(t[0]),!1})},_autoSize:function(e){if(this._get(e,"autoSize")&&!e.inline){var t,n,r,i,s=new Date(2009,11,20),o=this._get(e,"dateFormat");o.match(/[DM]/)&&(t=function(e){n=0,r=0;for(i=0;i<e.length;i++)e[i].length>n&&(n=e[i].length,r=i);return r},s.setMonth(t(this._get(e,o.match(/MM/)?"monthNames":"monthNamesShort"))),s.setDate(t(this._get(e,o.match(/DD/)?"dayNames":"dayNamesShort"))+20-s.getDay())),e.input.attr("size",this._formatDate(e,s).length)}},_inlineDatepicker:function(t,r){var i=e(t);if(i.hasClass(this.markerClassName))return;i.addClass(this.markerClassName).append(r.dpDiv),e.data(t,n,r),this._setDate(r,this._getDefaultDate(r),!0),this._updateDatepicker(r),this._updateAlternate(r),r.settings.disabled&&this._disableDatepicker(t),r.dpDiv.css("display","block")},_dialogDatepicker:function(t,r,i,s,o){var a,f,l,c,h,p=this._dialogInst;return p||(this.uuid+=1,a="dp"+this.uuid,this._dialogInput=e("<input type='text' id='"+a+"' style='position: absolute; top: -100px; width: 0px;'/>"),this._dialogInput.keydown(this._doKeyDown),e("body").append(this._dialogInput),p=this._dialogInst=this._newInst(this._dialogInput,!1),p.settings={},e.data(this._dialogInput[0],n,p)),u(p.settings,s||{}),r=r&&r.constructor===Date?this._formatDate(p,r):r,this._dialogInput.val(r),this._pos=o?o.length?o:[o.pageX,o.pageY]:null,this._pos||(f=document.documentElement.clientWidth,l=document.documentElement.clientHeight,c=document.documentElement.scrollLeft||document.body.scrollLeft,h=document.documentElement.scrollTop||document.body.scrollTop,this._pos=[f/2-100+c,l/2-150+h]),this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),p.settings.onSelect=i,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),e.blockUI&&e.blockUI(this.dpDiv),e.data(this._dialogInput[0],n,p),this},_destroyDatepicker:function(t){var r,i=e(t),s=e.data(t,n);if(!i.hasClass(this.markerClassName))return;r=t.nodeName.toLowerCase(),e.removeData(t,n),r==="input"?(s.append.remove(),s.trigger.remove(),i.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):(r==="div"||r==="span")&&i.removeClass(this.markerClassName).empty()},_enableDatepicker:function(t){var r,i,s=e(t),o=e.data(t,n);if(!s.hasClass(this.markerClassName))return;r=t.nodeName.toLowerCase();if(r==="input")t.disabled=!1,o.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""});else if(r==="div"||r==="span")i=s.children("."+this._inlineClass),i.children().removeClass("ui-state-disabled"),i.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1);this._disabledInputs=e.map(this._disabledInputs,function(e){return e===t?null:e})},_disableDatepicker:function(t){var r,i,s=e(t),o=e.data(t,n);if(!s.hasClass(this.markerClassName))return;r=t.nodeName.toLowerCase();if(r==="input")t.disabled=!0,o.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"});else if(r==="div"||r==="span")i=s.children("."+this._inlineClass),i.children().addClass("ui-state-disabled"),i.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0);this._disabledInputs=e.map(this._disabledInputs,function(e){return e===t?null:e}),this._disabledInputs[this._disabledInputs.length]=t},_isDisabledDatepicker:function(e){if(!e)return!1;for(var t=0;t<this._disabledInputs.length;t++)if(this._disabledInputs[t]===e)return!0;return!1},_getInst:function(t){try{return e.data(t,n)}catch(r){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(n,r,i){var s,o,a,f,l=this._getInst(n);if(arguments.length===2&&typeof r=="string")return r==="defaults"?e.extend({},e.datepicker._defaults):l?r==="all"?e.extend({},l.settings):this._get(l,r):null;s=r||{},typeof r=="string"&&(s={},s[r]=i),l&&(this._curInst===l&&this._hideDatepicker(),o=this._getDateDatepicker(n,!0),a=this._getMinMaxDate(l,"min"),f=this._getMinMaxDate(l,"max"),u(l.settings,s),a!==null&&s.dateFormat!==t&&s.minDate===t&&(l.settings.minDate=this._formatDate(l,a)),f!==null&&s.dateFormat!==t&&s.maxDate===t&&(l.settings.maxDate=this._formatDate(l,f)),"disabled"in s&&(s.disabled?this._disableDatepicker(n):this._enableDatepicker(n)),this._attachments(e(n),l),this._autoSize(l),this._setDate(l,o),this._updateAlternate(l),this._updateDatepicker(l))},_changeDatepicker:function(e,t,n){this._optionDatepicker(e,t,n)},_refreshDatepicker:function(e){var t=this._getInst(e);t&&this._updateDatepicker(t)},_setDateDatepicker:function(e,t){var n=this._getInst(e);n&&(this._setDate(n,t),this._updateDatepicker(n),this._updateAlternate(n))},_getDateDatepicker:function(e,t){var n=this._getInst(e);return n&&!n.inline&&this._setDateFromField(n,t),n?this._getDate(n):null},_doKeyDown:function(t){var n,r,i,s=e.datepicker._getInst(t.target),o=!0,u=s.dpDiv.is(".ui-datepicker-rtl");s._keyEvent=!0;if(e.datepicker._datepickerShowing)switch(t.keyCode){case 9:e.datepicker._hideDatepicker(),o=!1;break;case 13:return i=e("td."+e.datepicker._dayOverClass+":not(."+e.datepicker._currentClass+")",s.dpDiv),i[0]&&e.datepicker._selectDay(t.target,s.selectedMonth,s.selectedYear,i[0]),n=e.datepicker._get(s,"onSelect"),n?(r=e.datepicker._formatDate(s),n.apply(s.input?s.input[0]:null,[r,s])):e.datepicker._hideDatepicker(),!1;case 27:e.datepicker._hideDatepicker();break;case 33:e.datepicker._adjustDate(t.target,t.ctrlKey?-e.datepicker._get(s,"stepBigMonths"):-e.datepicker._get(s,"stepMonths"),"M");break;case 34:e.datepicker._adjustDate(t.target,t.ctrlKey?+e.datepicker._get(s,"stepBigMonths"):+e.datepicker._get(s,"stepMonths"),"M");break;case 35:(t.ctrlKey||t.metaKey)&&e.datepicker._clearDate(t.target),o=t.ctrlKey||t.metaKey;break;case 36:(t.ctrlKey||t.metaKey)&&e.datepicker._gotoToday(t.target),o=t.ctrlKey||t.metaKey;break;case 37:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,u?1:-1,"D"),o=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&e.datepicker._adjustDate(t.target,t.ctrlKey?-e.datepicker._get(s,"stepBigMonths"):-e.datepicker._get(s,"stepMonths"),"M");break;case 38:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,-7,"D"),o=t.ctrlKey||t.metaKey;break;case 39:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,u?-1:1,"D"),o=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&e.datepicker._adjustDate(t.target,t.ctrlKey?+e.datepicker._get(s,"stepBigMonths"):+e.datepicker._get(s,"stepMonths"),"M");break;case 40:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,7,"D"),o=t.ctrlKey||t.metaKey;break;default:o=!1}else t.keyCode===36&&t.ctrlKey?e.datepicker._showDatepicker(this):o=!1;o&&(t.preventDefault(),t.stopPropagation())},_doKeyPress:function(t){var n,r,i=e.datepicker._getInst(t.target);if(e.datepicker._get(i,"constrainInput"))return n=e.datepicker._possibleChars(e.datepicker._get(i,"dateFormat")),r=String.fromCharCode(t.charCode==null?t.keyCode:t.charCode),t.ctrlKey||t.metaKey||r<" "||!n||n.indexOf(r)>-1},_doKeyUp:function(t){var n,r=e.datepicker._getInst(t.target);if(r.input.val()!==r.lastVal)try{n=e.datepicker.parseDate(e.datepicker._get(r,"dateFormat"),r.input?r.input.val():null,e.datepicker._getFormatConfig(r)),n&&(e.datepicker._setDateFromField(r),e.datepicker._updateAlternate(r),e.datepicker._updateDatepicker(r))}catch(i){}return!0},_showDatepicker:function(t){t=t.target||t,t.nodeName.toLowerCase()!=="input"&&(t=e("input",t.parentNode)[0]);if(e.datepicker._isDisabledDatepicker(t)||e.datepicker._lastInput===t)return;var n,r,i,s,o,a,f;n=e.datepicker._getInst(t),e.datepicker._curInst&&e.datepicker._curInst!==n&&(e.datepicker._curInst.dpDiv.stop(!0,!0),n&&e.datepicker._datepickerShowing&&e.datepicker._hideDatepicker(e.datepicker._curInst.input[0])),r=e.datepicker._get(n,"beforeShow"),i=r?r.apply(t,[t,n]):{};if(i===!1)return;u(n.settings,i),n.lastVal=null,e.datepicker._lastInput=t,e.datepicker._setDateFromField(n),e.datepicker._inDialog&&(t.value=""),e.datepicker._pos||(e.datepicker._pos=e.datepicker._findPos(t),e.datepicker._pos[1]+=t.offsetHeight),s=!1,e(t).parents().each(function(){return s|=e(this).css("position")==="fixed",!s}),o={left:e.datepicker._pos[0],top:e.datepicker._pos[1]},e.datepicker._pos=null,n.dpDiv.empty(),n.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),e.datepicker._updateDatepicker(n),o=e.datepicker._checkOffset(n,o,s),n.dpDiv.css({position:e.datepicker._inDialog&&e.blockUI?"static":s?"fixed":"absolute",display:"none",left:o.left+"px",top:o.top+"px"}),n.inline||(a=e.datepicker._get(n,"showAnim"),f=e.datepicker._get(n,"duration"),n.dpDiv.zIndex(e(t).zIndex()+1),e.datepicker._datepickerShowing=!0,e.effects&&e.effects.effect[a]?n.dpDiv.show(a,e.datepicker._get(n,"showOptions"),f):n.dpDiv[a||"show"](a?f:null),n.input.is(":visible")&&!n.input.is(":disabled")&&n.input.focus(),e.datepicker._curInst=n)},_updateDatepicker:function(t){this.maxRows=4,i=t,t.dpDiv.empty().append(this._generateHTML(t)),this._attachHandlers(t),t.dpDiv.find("."+this._dayOverClass+" a").mouseover();var n,r=this._getNumberOfMonths(t),s=r[1],o=17;t.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),s>1&&t.dpDiv.addClass("ui-datepicker-multi-"+s).css("width",o*s+"em"),t.dpDiv[(r[0]!==1||r[1]!==1?"add":"remove")+"Class"]("ui-datepicker-multi"),t.dpDiv[(this._get(t,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),t===e.datepicker._curInst&&e.datepicker._datepickerShowing&&t.input&&t.input.is(":visible")&&!t.input.is(":disabled")&&t.input[0]!==document.activeElement&&t.input.focus(),t.yearshtml&&(n=t.yearshtml,setTimeout(function(){n===t.yearshtml&&t.yearshtml&&t.dpDiv.find("select.ui-datepicker-year:first").replaceWith(t.yearshtml),n=t.yearshtml=null},0))},_getBorders:function(e){var t=function(e){return{thin:1,medium:2,thick:3}[e]||e};return[parseFloat(t(e.css("border-left-width"))),parseFloat(t(e.css("border-top-width")))]},_checkOffset:function(t,n,r){var i=t.dpDiv.outerWidth(),s=t.dpDiv.outerHeight(),o=t.input?t.input.outerWidth():0,u=t.input?t.input.outerHeight():0,a=document.documentElement.clientWidth+(r?0:e(document).scrollLeft()),f=document.documentElement.clientHeight+(r?0:e(document).scrollTop());return n.left-=this._get(t,"isRTL")?i-o:0,n.left-=r&&n.left===t.input.offset().left?e(document).scrollLeft():0,n.top-=r&&n.top===t.input.offset().top+u?e(document).scrollTop():0,n.left-=Math.min(n.left,n.left+i>a&&a>i?Math.abs(n.left+i-a):0),n.top-=Math.min(n.top,n.top+s>f&&f>s?Math.abs(s+u):0),n},_findPos:function(t){var n,r=this._getInst(t),i=this._get(r,"isRTL");while(t&&(t.type==="hidden"||t.nodeType!==1||e.expr.filters.hidden(t)))t=t[i?"previousSibling":"nextSibling"];return n=e(t).offset(),[n.left,n.top]},_hideDatepicker:function(t){var r,i,s,o,u=this._curInst;if(!u||t&&u!==e.data(t,n))return;this._datepickerShowing&&(r=this._get(u,"showAnim"),i=this._get(u,"duration"),s=function(){e.datepicker._tidyDialog(u)},e.effects&&(e.effects.effect[r]||e.effects[r])?u.dpDiv.hide(r,e.datepicker._get(u,"showOptions"),i,s):u.dpDiv[r==="slideDown"?"slideUp":r==="fadeIn"?"fadeOut":"hide"](r?i:null,s),r||s(),this._datepickerShowing=!1,o=this._get(u,"onClose"),o&&o.apply(u.input?u.input[0]:null,[u.input?u.input.val():"",u]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),e.blockUI&&(e.unblockUI(),e("body").append(this.dpDiv))),this._inDialog=!1)},_tidyDialog:function(e){e.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(t){if(!e.datepicker._curInst)return;var n=e(t.target),r=e.datepicker._getInst(n[0]);(n[0].id!==e.datepicker._mainDivId&&n.parents("#"+e.datepicker._mainDivId).length===0&&!n.hasClass(e.datepicker.markerClassName)&&!n.closest("."+e.datepicker._triggerClass).length&&e.datepicker._datepickerShowing&&(!e.datepicker._inDialog||!e.blockUI)||n.hasClass(e.datepicker.markerClassName)&&e.datepicker._curInst!==r)&&e.datepicker._hideDatepicker()},_adjustDate:function(t,n,r){var i=e(t),s=this._getInst(i[0]);if(this._isDisabledDatepicker(i[0]))return;this._adjustInstDate(s,n+(r==="M"?this._get(s,"showCurrentAtPos"):0),r),this._updateDatepicker(s)},_gotoToday:function(t){var n,r=e(t),i=this._getInst(r[0]);this._get(i,"gotoCurrent")&&i.currentDay?(i.selectedDay=i.currentDay,i.drawMonth=i.selectedMonth=i.currentMonth,i.drawYear=i.selectedYear=i.currentYear):(n=new Date,i.selectedDay=n.getDate(),i.drawMonth=i.selectedMonth=n.getMonth(),i.drawYear=i.selectedYear=n.getFullYear()),this._notifyChange(i),this._adjustDate(r)},_selectMonthYear:function(t,n,r){var i=e(t),s=this._getInst(i[0]);s["selected"+(r==="M"?"Month":"Year")]=s["draw"+(r==="M"?"Month":"Year")]=parseInt(n.options[n.selectedIndex].value,10),this._notifyChange(s),this._adjustDate(i)},_selectDay:function(t,n,r,i){var s,o=e(t);if(e(i).hasClass(this._unselectableClass)||this._isDisabledDatepicker(o[0]))return;s=this._getInst(o[0]),s.selectedDay=s.currentDay=e("a",i).html(),s.selectedMonth=s.currentMonth=n,s.selectedYear=s.currentYear=r,this._selectDate(t,this._formatDate(s,s.currentDay,s.currentMonth,s.currentYear))},_clearDate:function(t){var n=e(t);this._selectDate(n,"")},_selectDate:function(t,n){var r,i=e(t),s=this._getInst(i[0]);n=n!=null?n:this._formatDate(s),s.input&&s.input.val(n),this._updateAlternate(s),r=this._get(s,"onSelect"),r?r.apply(s.input?s.input[0]:null,[n,s]):s.input&&s.input.trigger("change"),s.inline?this._updateDatepicker(s):(this._hideDatepicker(),this._lastInput=s.input[0],typeof s.input[0]!="object"&&s.input.focus(),this._lastInput=null)},_updateAlternate:function(t){var n,r,i,s=this._get(t,"altField");s&&(n=this._get(t,"altFormat")||this._get(t,"dateFormat"),r=this._getDate(t),i=this.formatDate(n,r,this._getFormatConfig(t)),e(s).each(function(){e(this).val(i)}))},noWeekends:function(e){var t=e.getDay();return[t>0&&t<6,""]},iso8601Week:function(e){var t,n=new Date(e.getTime());return n.setDate(n.getDate()+4-(n.getDay()||7)),t=n.getTime(),n.setMonth(0),n.setDate(1),Math.floor(Math.round((t-n)/864e5)/7)+1},parseDate:function(t,n,r){if(t==null||n==null)throw"Invalid arguments";n=typeof n=="object"?n.toString():n+"";if(n==="")return null;var i,s,o,u=0,a=(r?r.shortYearCutoff:null)||this._defaults.shortYearCutoff,f=typeof a!="string"?a:(new Date).getFullYear()%100+parseInt(a,10),l=(r?r.dayNamesShort:null)||this._defaults.dayNamesShort,c=(r?r.dayNames:null)||this._defaults.dayNames,h=(r?r.monthNamesShort:null)||this._defaults.monthNamesShort,p=(r?r.monthNames:null)||this._defaults.monthNames,d=-1,v=-1,m=-1,g=-1,y=!1,b,w=function(e){var n=i+1<t.length&&t.charAt(i+1)===e;return n&&i++,n},E=function(e){var t=w(e),r=e==="@"?14:e==="!"?20:e==="y"&&t?4:e==="o"?3:2,i=new RegExp("^\\d{1,"+r+"}"),s=n.substring(u).match(i);if(!s)throw"Missing number at position "+u;return u+=s[0].length,parseInt(s[0],10)},S=function(t,r,i){var s=-1,o=e.map(w(t)?i:r,function(e,t){return[[t,e]]}).sort(function(e,t){return-(e[1].length-t[1].length)});e.each(o,function(e,t){var r=t[1];if(n.substr(u,r.length).toLowerCase()===r.toLowerCase())return s=t[0],u+=r.length,!1});if(s!==-1)return s+1;throw"Unknown name at position "+u},x=function(){if(n.charAt(u)!==t.charAt(i))throw"Unexpected literal at position "+u;u++};for(i=0;i<t.length;i++)if(y)t.charAt(i)==="'"&&!w("'")?y=!1:x();else switch(t.charAt(i)){case"d":m=E("d");break;case"D":S("D",l,c);break;case"o":g=E("o");break;case"m":v=E("m");break;case"M":v=S("M",h,p);break;case"y":d=E("y");break;case"@":b=new Date(E("@")),d=b.getFullYear(),v=b.getMonth()+1,m=b.getDate();break;case"!":b=new Date((E("!")-this._ticksTo1970)/1e4),d=b.getFullYear(),v=b.getMonth()+1,m=b.getDate();break;case"'":w("'")?x():y=!0;break;default:x()}if(u<n.length){o=n.substr(u);if(!/^\s+/.test(o))throw"Extra/unparsed characters found in date: "+o}d===-1?d=(new Date).getFullYear():d<100&&(d+=(new Date).getFullYear()-(new Date).getFullYear()%100+(d<=f?0:-100));if(g>-1){v=1,m=g;do{s=this._getDaysInMonth(d,v-1);if(m<=s)break;v++,m-=s}while(!0)}b=this._daylightSavingAdjust(new Date(d,v-1,m));if(b.getFullYear()!==d||b.getMonth()+1!==v||b.getDate()!==m)throw"Invalid date";return b},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1e7,formatDate:function(e,t,n){if(!t)return"";var r,i=(n?n.dayNamesShort:null)||this._defaults.dayNamesShort,s=(n?n.dayNames:null)||this._defaults.dayNames,o=(n?n.monthNamesShort:null)||this._defaults.monthNamesShort,u=(n?n.monthNames:null)||this._defaults.monthNames,a=function(t){var n=r+1<e.length&&e.charAt(r+1)===t;return n&&r++,n},f=function(e,t,n){var r=""+t;if(a(e))while(r.length<n)r="0"+r;return r},l=function(e,t,n,r){return a(e)?r[t]:n[t]},c="",h=!1;if(t)for(r=0;r<e.length;r++)if(h)e.charAt(r)==="'"&&!a("'")?h=!1:c+=e.charAt(r);else switch(e.charAt(r)){case"d":c+=f("d",t.getDate(),2);break;case"D":c+=l("D",t.getDay(),i,s);break;case"o":c+=f("o",Math.round(((new Date(t.getFullYear(),t.getMonth(),t.getDate())).getTime()-(new Date(t.getFullYear(),0,0)).getTime())/864e5),3);break;case"m":c+=f("m",t.getMonth()+1,2);break;case"M":c+=l("M",t.getMonth(),o,u);break;case"y":c+=a("y")?t.getFullYear():(t.getYear()%100<10?"0":"")+t.getYear()%100;break;case"@":c+=t.getTime();break;case"!":c+=t.getTime()*1e4+this._ticksTo1970;break;case"'":a("'")?c+="'":h=!0;break;default:c+=e.charAt(r)}return c},_possibleChars:function(e){var t,n="",r=!1,i=function(n){var r=t+1<e.length&&e.charAt(t+1)===n;return r&&t++,r};for(t=0;t<e.length;t++)if(r)e.charAt(t)==="'"&&!i("'")?r=!1:n+=e.charAt(t);else switch(e.charAt(t)){case"d":case"m":case"y":case"@":n+="0123456789";break;case"D":case"M":return null;case"'":i("'")?n+="'":r=!0;break;default:n+=e.charAt(t)}return n},_get:function(e,n){return e.settings[n]!==t?e.settings[n]:this._defaults[n]},_setDateFromField:function(e,t){if(e.input.val()===e.lastVal)return;var n=this._get(e,"dateFormat"),r=e.lastVal=e.input?e.input.val():null,i=this._getDefaultDate(e),s=i,o=this._getFormatConfig(e);try{s=this.parseDate(n,r,o)||i}catch(u){r=t?"":r}e.selectedDay=s.getDate(),e.drawMonth=e.selectedMonth=s.getMonth(),e.drawYear=e.selectedYear=s.getFullYear(),e.currentDay=r?s.getDate():0,e.currentMonth=r?s.getMonth():0,e.currentYear=r?s.getFullYear():0,this._adjustInstDate(e)},_getDefaultDate:function(e){return this._restrictMinMax(e,this._determineDate(e,this._get(e,"defaultDate"),new Date))},_determineDate:function(t,n,r){var i=function(e){var t=new Date;return t.setDate(t.getDate()+e),t},s=function(n){try{return e.datepicker.parseDate(e.datepicker._get(t,"dateFormat"),n,e.datepicker._getFormatConfig(t))}catch(r){}var i=(n.toLowerCase().match(/^c/)?e.datepicker._getDate(t):null)||new Date,s=i.getFullYear(),o=i.getMonth(),u=i.getDate(),a=/([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,f=a.exec(n);while(f){switch(f[2]||"d"){case"d":case"D":u+=parseInt(f[1],10);break;case"w":case"W":u+=parseInt(f[1],10)*7;break;case"m":case"M":o+=parseInt(f[1],10),u=Math.min(u,e.datepicker._getDaysInMonth(s,o));break;case"y":case"Y":s+=parseInt(f[1],10),u=Math.min(u,e.datepicker._getDaysInMonth(s,o))}f=a.exec(n)}return new Date(s,o,u)},o=n==null||n===""?r:typeof n=="string"?s(n):typeof n=="number"?isNaN(n)?r:i(n):new Date(n.getTime());return o=o&&o.toString()==="Invalid Date"?r:o,o&&(o.setHours(0),o.setMinutes(0),o.setSeconds(0),o.setMilliseconds(0)),this._daylightSavingAdjust(o)},_daylightSavingAdjust:function(e){return e?(e.setHours(e.getHours()>12?e.getHours()+2:0),e):null},_setDate:function(e,t,n){var r=!t,i=e.selectedMonth,s=e.selectedYear,o=this._restrictMinMax(e,this._determineDate(e,t,new Date));e.selectedDay=e.currentDay=o.getDate(),e.drawMonth=e.selectedMonth=e.currentMonth=o.getMonth(),e.drawYear=e.selectedYear=e.currentYear=o.getFullYear(),(i!==e.selectedMonth||s!==e.selectedYear)&&!n&&this._notifyChange(e),this._adjustInstDate(e),e.input&&e.input.val(r?"":this._formatDate(e))},_getDate:function(e){var t=!e.currentYear||e.input&&e.input.val()===""?null:this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return t},_attachHandlers:function(t){var n=this._get(t,"stepMonths"),i="#"+t.id.replace(/\\\\/g,"\\");t.dpDiv.find("[data-handler]").map(function(){var t={prev:function(){window["DP_jQuery_"+r].datepicker._adjustDate(i,-n,"M")},next:function(){window["DP_jQuery_"+r].datepicker._adjustDate(i,+n,"M")},hide:function(){window["DP_jQuery_"+r].datepicker._hideDatepicker()},today:function(){window["DP_jQuery_"+r].datepicker._gotoToday(i)},selectDay:function(){return window["DP_jQuery_"+r].datepicker._selectDay(i,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return window["DP_jQuery_"+r].datepicker._selectMonthYear(i,this,"M"),!1},selectYear:function(){return window["DP_jQuery_"+r].datepicker._selectMonthYear(i,this,"Y"),!1}};e(this).bind(this.getAttribute("data-event"),t[this.getAttribute("data-handler")])})},_generateHTML:function(e){var t,n,r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y,b,w,E,S,x,T,N,C,k,L,A,O,M,_,D,P,H,B,j,F,I,q=new Date,R=this._daylightSavingAdjust(new Date(q.getFullYear(),q.getMonth(),q.getDate())),U=this._get(e,"isRTL"),z=this._get(e,"showButtonPanel"),W=this._get(e,"hideIfNoPrevNext"),X=this._get(e,"navigationAsDateFormat"),V=this._getNumberOfMonths(e),$=this._get(e,"showCurrentAtPos"),J=this._get(e,"stepMonths"),K=V[0]!==1||V[1]!==1,Q=this._daylightSavingAdjust(e.currentDay?new Date(e.currentYear,e.currentMonth,e.currentDay):new Date(9999,9,9)),G=this._getMinMaxDate(e,"min"),Y=this._getMinMaxDate(e,"max"),Z=e.drawMonth-$,et=e.drawYear;Z<0&&(Z+=12,et--);if(Y){t=this._daylightSavingAdjust(new Date(Y.getFullYear(),Y.getMonth()-V[0]*V[1]+1,Y.getDate())),t=G&&t<G?G:t;while(this._daylightSavingAdjust(new Date(et,Z,1))>t)Z--,Z<0&&(Z=11,et--)}e.drawMonth=Z,e.drawYear=et,n=this._get(e,"prevText"),n=X?this.formatDate(n,this._daylightSavingAdjust(new Date(et,Z-J,1)),this._getFormatConfig(e)):n,r=this._canAdjustMonth(e,-1,et,Z)?"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click' title='"+n+"'><span class='ui-icon ui-icon-circle-triangle-"+(U?"e":"w")+"'>"+n+"</span></a>":W?"":"<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+n+"'><span class='ui-icon ui-icon-circle-triangle-"+(U?"e":"w")+"'>"+n+"</span></a>",i=this._get(e,"nextText"),i=X?this.formatDate(i,this._daylightSavingAdjust(new Date(et,Z+J,1)),this._getFormatConfig(e)):i,s=this._canAdjustMonth(e,1,et,Z)?"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(U?"w":"e")+"'>"+i+"</span></a>":W?"":"<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(U?"w":"e")+"'>"+i+"</span></a>",o=this._get(e,"currentText"),u=this._get(e,"gotoCurrent")&&e.currentDay?Q:R,o=X?this.formatDate(o,u,this._getFormatConfig(e)):o,a=e.inline?"":"<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>"+this._get(e,"closeText")+"</button>",f=z?"<div class='ui-datepicker-buttonpane ui-widget-content'>"+(U?a:"")+(this._isInRange(e,u)?"<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'>"+o+"</button>":"")+(U?"":a)+"</div>":"",l=parseInt(this._get(e,"firstDay"),10),l=isNaN(l)?0:l,c=this._get(e,"showWeek"),h=this._get(e,"dayNames"),p=this._get(e,"dayNamesMin"),d=this._get(e,"monthNames"),v=this._get(e,"monthNamesShort"),m=this._get(e,"beforeShowDay"),g=this._get(e,"showOtherMonths"),y=this._get(e,"selectOtherMonths"),b=this._getDefaultDate(e),w="",E;for(S=0;S<V[0];S++){x="",this.maxRows=4;for(T=0;T<V[1];T++){N=this._daylightSavingAdjust(new Date(et,Z,e.selectedDay)),C=" ui-corner-all",k="";if(K){k+="<div class='ui-datepicker-group";if(V[1]>1)switch(T){case 0:k+=" ui-datepicker-group-first",C=" ui-corner-"+(U?"right":"left");break;case V[1]-1:k+=" ui-datepicker-group-last",C=" ui-corner-"+(U?"left":"right");break;default:k+=" ui-datepicker-group-middle",C=""}k+="'>"}k+="<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix"+C+"'>"+(/all|left/.test(C)&&S===0?U?s:r:"")+(/all|right/.test(C)&&S===0?U?r:s:"")+this._generateMonthYearHeader(e,Z,et,G,Y,S>0||T>0,d,v)+"</div><table class='ui-datepicker-calendar'><thead>"+"<tr>",L=c?"<th class='ui-datepicker-week-col'>"+this._get(e,"weekHeader")+"</th>":"";for(E=0;E<7;E++)A=(E+l)%7,L+="<th"+((E+l+6)%7>=5?" class='ui-datepicker-week-end'":"")+">"+"<span title='"+h[A]+"'>"+p[A]+"</span></th>";k+=L+"</tr></thead><tbody>",O=this._getDaysInMonth(et,Z),et===e.selectedYear&&Z===e.selectedMonth&&(e.selectedDay=Math.min(e.selectedDay,O)),M=(this._getFirstDayOfMonth(et,Z)-l+7)%7,_=Math.ceil((M+O)/7),D=K?this.maxRows>_?this.maxRows:_:_,this.maxRows=D,P=this._daylightSavingAdjust(new Date(et,Z,1-M));for(H=0;H<D;H++){k+="<tr>",B=c?"<td class='ui-datepicker-week-col'>"+this._get(e,"calculateWeek")(P)+"</td>":"";for(E=0;E<7;E++)j=m?m.apply(e.input?e.input[0]:null,[P]):[!0,""],F=P.getMonth()!==Z,I=F&&!y||!j[0]||G&&P<G||Y&&P>Y,B+="<td class='"+((E+l+6)%7>=5?" ui-datepicker-week-end":"")+(F?" ui-datepicker-other-month":"")+(P.getTime()===N.getTime()&&Z===e.selectedMonth&&e._keyEvent||b.getTime()===P.getTime()&&b.getTime()===N.getTime()?" "+this._dayOverClass:"")+(I?" "+this._unselectableClass+" ui-state-disabled":"")+(F&&!g?"":" "+j[1]+(P.getTime()===Q.getTime()?" "+this._currentClass:"")+(P.getTime()===R.getTime()?" ui-datepicker-today":""))+"'"+((!F||g)&&j[2]?" title='"+j[2].replace(/'/g,"'")+"'":"")+(I?"":" data-handler='selectDay' data-event='click' data-month='"+P.getMonth()+"' data-year='"+P.getFullYear()+"'")+">"+(F&&!g?" ":I?"<span class='ui-state-default'>"+P.getDate()+"</span>":"<a class='ui-state-default"+(P.getTime()===R.getTime()?" ui-state-highlight":"")+(P.getTime()===Q.getTime()?" ui-state-active":"")+(F?" ui-priority-secondary":"")+"' href='#'>"+P.getDate()+"</a>")+"</td>",P.setDate(P.getDate()+1),P=this._daylightSavingAdjust(P);k+=B+"</tr>"}Z++,Z>11&&(Z=0,et++),k+="</tbody></table>"+(K?"</div>"+(V[0]>0&&T===V[1]-1?"<div class='ui-datepicker-row-break'></div>":""):""),x+=k}w+=x}return w+=f,e._keyEvent=!1,w},_generateMonthYearHeader:function(e,t,n,r,i,s,o,u){var a,f,l,c,h,p,d,v,m=this._get(e,"changeMonth"),g=this._get(e,"changeYear"),y=this._get(e,"showMonthAfterYear"),b="<div class='ui-datepicker-title'>",w="";if(s||!m)w+="<span class='ui-datepicker-month'>"+o[t]+"</span>";else{a=r&&r.getFullYear()===n,f=i&&i.getFullYear()===n,w+="<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";for(l=0;l<12;l++)(!a||l>=r.getMonth())&&(!f||l<=i.getMonth())&&(w+="<option value='"+l+"'"+(l===t?" selected='selected'":"")+">"+u[l]+"</option>");w+="</select>"}y||(b+=w+(s||!m||!g?" ":""));if(!e.yearshtml){e.yearshtml="";if(s||!g)b+="<span class='ui-datepicker-year'>"+n+"</span>";else{c=this._get(e,"yearRange").split(":"),h=(new Date).getFullYear(),p=function(e){var t=e.match(/c[+\-].*/)?n+parseInt(e.substring(1),10):e.match(/[+\-].*/)?h+parseInt(e,10):parseInt(e,10);return isNaN(t)?h:t},d=p(c[0]),v=Math.max(d,p(c[1]||"")),d=r?Math.max(d,r.getFullYear()):d,v=i?Math.min(v,i.getFullYear()):v,e.yearshtml+="<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";for(;d<=v;d++)e.yearshtml+="<option value='"+d+"'"+(d===n?" selected='selected'":"")+">"+d+"</option>";e.yearshtml+="</select>",b+=e.yearshtml,e.yearshtml=null}}return b+=this._get(e,"yearSuffix"),y&&(b+=(s||!m||!g?" ":"")+w),b+="</div>",b},_adjustInstDate:function(e,t,n){var r=e.drawYear+(n==="Y"?t:0),i=e.drawMonth+(n==="M"?t:0),s=Math.min(e.selectedDay,this._getDaysInMonth(r,i))+(n==="D"?t:0),o=this._restrictMinMax(e,this._daylightSavingAdjust(new Date(r,i,s)));e.selectedDay=o.getDate(),e.drawMonth=e.selectedMonth=o.getMonth(),e.drawYear=e.selectedYear=o.getFullYear(),(n==="M"||n==="Y")&&this._notifyChange(e)},_restrictMinMax:function(e,t){var n=this._getMinMaxDate(e,"min"),r=this._getMinMaxDate(e,"max"),i=n&&t<n?n:t;return r&&i>r?r:i},_notifyChange:function(e){var t=this._get(e,"onChangeMonthYear");t&&t.apply(e.input?e.input[0]:null,[e.selectedYear,e.selectedMonth+1,e])},_getNumberOfMonths:function(e){var t=this._get(e,"numberOfMonths");return t==null?[1,1]:typeof t=="number"?[1,t]:t},_getMinMaxDate:function(e,t){return this._determineDate(e,this._get(e,t+"Date"),null)},_getDaysInMonth:function(e,t){return 32-this._daylightSavingAdjust(new Date(e,t,32)).getDate()},_getFirstDayOfMonth:function(e,t){return(new Date(e,t,1)).getDay()},_canAdjustMonth:function(e,t,n,r){var i=this._getNumberOfMonths(e),s=this._daylightSavingAdjust(new Date(n,r+(t<0?t:i[0]*i[1]),1));return t<0&&s.setDate(this._getDaysInMonth(s.getFullYear(),s.getMonth())),this._isInRange(e,s)},_isInRange:function(e,t){var n,r,i=this._getMinMaxDate(e,"min"),s=this._getMinMaxDate(e,"max"),o=null,u=null,a=this._get(e,"yearRange");return a&&(n=a.split(":"),r=(new Date).getFullYear(),o=parseInt(n[0],10),u=parseInt(n[1],10),n[0].match(/[+\-].*/)&&(o+=r),n[1].match(/[+\-].*/)&&(u+=r)),(!i||t.getTime()>=i.getTime())&&(!s||t.getTime()<=s.getTime())&&(!o||t.getFullYear()>=o)&&(!u||t.getFullYear()<=u)},_getFormatConfig:function(e){var t=this._get(e,"shortYearCutoff");return t=typeof t!="string"?t:(new Date).getFullYear()%100+parseInt(t,10),{shortYearCutoff:t,dayNamesShort:this._get(e,"dayNamesShort"),dayNames:this._get(e,"dayNames"),monthNamesShort:this._get(e,"monthNamesShort"),monthNames:this._get(e,"monthNames")}},_formatDate:function(e,t,n,r){t||(e.currentDay=e.selectedDay,e.currentMonth=e.selectedMonth,e.currentYear=e.selectedYear);var i=t?typeof t=="object"?t:this._daylightSavingAdjust(new Date(r,n,t)):this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return this.formatDate(this._get(e,"dateFormat"),i,this._getFormatConfig(e))}}),e.fn.datepicker=function(t){if(!this.length)return this;e.datepicker.initialized||(e(document).mousedown(e.datepicker._checkExternalClick),e.datepicker.initialized=!0),e("#"+e.datepicker._mainDivId).length===0&&e("body").append(e.datepicker.dpDiv);var n=Array.prototype.slice.call(arguments,1);return typeof t!="string"||t!=="isDisabled"&&t!=="getDate"&&t!=="widget"?t==="option"&&arguments.length===2&&typeof arguments[1]=="string"?e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this[0]].concat(n)):this.each(function(){typeof t=="string"?e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this].concat(n)):e.datepicker._attachDatepicker(this,t)}):e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this[0]].concat(n))},e.datepicker=new s,e.datepicker.initialized=!1,e.datepicker.uuid=(new Date).getTime(),e.datepicker.version="1.10.1",window["DP_jQuery_"+r]=e})(jQuery);(function(e,t){var n={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},r={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0};e.widget("ui.dialog",{version:"1.10.1",options:{appendTo:"body",autoOpen:!0,buttons:[],closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:null,maxWidth:null,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(t){var n=e(this).css(t).offset().top;n<0&&e(this).css("top",t.top-n)}},resizable:!0,show:null,title:null,width:300,beforeClose:null,close:null,drag:null,dragStart:null,dragStop:null,focus:null,open:null,resize:null,resizeStart:null,resizeStop:null},_create:function(){this.originalCss={display:this.element[0].style.display,width:this.element[0].style.width,minHeight:this.element[0].style.minHeight,maxHeight:this.element[0].style.maxHeight,height:this.element[0].style.height},this.originalPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.originalTitle=this.element.attr("title"),this.options.title=this.options.title||this.originalTitle,this._createWrapper(),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(this.uiDialog),this._createTitlebar(),this._createButtonPane(),this.options.draggable&&e.fn.draggable&&this._makeDraggable(),this.options.resizable&&e.fn.resizable&&this._makeResizable(),this._isOpen=!1},_init:function(){this.options.autoOpen&&this.open()},_appendTo:function(){var t=this.options.appendTo;return t&&(t.jquery||t.nodeType)?e(t):this.document.find(t||"body").eq(0)},_destroy:function(){var e,t=this.originalPosition;this._destroyOverlay(),this.element.removeUniqueId().removeClass("ui-dialog-content ui-widget-content").css(this.originalCss).detach(),this.uiDialog.stop(!0,!0).remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),e=t.parent.children().eq(t.index),e.length&&e[0]!==this.element[0]?e.before(this.element):t.parent.append(this.element)},widget:function(){return this.uiDialog},disable:e.noop,enable:e.noop,close:function(t){var n=this;if(!this._isOpen||this._trigger("beforeClose",t)===!1)return;this._isOpen=!1,this._destroyOverlay(),this.opener.filter(":focusable").focus().length||e(this.document[0].activeElement).blur(),this._hide(this.uiDialog,this.options.hide,function(){n._trigger("close",t)})},isOpen:function(){return this._isOpen},moveToTop:function(){this._moveToTop()},_moveToTop:function(e,t){var n=!!this.uiDialog.nextAll(":visible").insertBefore(this.uiDialog).length;return n&&!t&&this._trigger("focus",e),n},open:function(){var t=this;if(this._isOpen){this._moveToTop()&&this._focusTabbable();return}this._isOpen=!0,this.opener=e(this.document[0].activeElement),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this._show(this.uiDialog,this.options.show,function(){t._focusTabbable(),t._trigger("focus")}),this._trigger("open")},_focusTabbable:function(){var e=this.element.find("[autofocus]");e.length||(e=this.element.find(":tabbable")),e.length||(e=this.uiDialogButtonPane.find(":tabbable")),e.length||(e=this.uiDialogTitlebarClose.filter(":tabbable")),e.length||(e=this.uiDialog),e.eq(0).focus()},_keepFocus:function(t){function n(){var t=this.document[0].activeElement,n=this.uiDialog[0]===t||e.contains(this.uiDialog[0],t);n||this._focusTabbable()}t.preventDefault(),n.call(this),this._delay(n)},_createWrapper:function(){this.uiDialog=e("<div>").addClass("ui-dialog ui-widget ui-widget-content ui-corner-all ui-front "+this.options.dialogClass).hide().attr({tabIndex:-1,role:"dialog"}).appendTo(this._appendTo()),this._on(this.uiDialog,{keydown:function(t){if(this.options.closeOnEscape&&!t.isDefaultPrevented()&&t.keyCode&&t.keyCode===e.ui.keyCode.ESCAPE){t.preventDefault(),this.close(t);return}if(t.keyCode!==e.ui.keyCode.TAB)return;var n=this.uiDialog.find(":tabbable"),r=n.filter(":first"),i=n.filter(":last");t.target!==i[0]&&t.target!==this.uiDialog[0]||!!t.shiftKey?(t.target===r[0]||t.target===this.uiDialog[0])&&t.shiftKey&&(i.focus(1),t.preventDefault()):(r.focus(1),t.preventDefault())},mousedown:function(e){this._moveToTop(e)&&this._focusTabbable()}}),this.element.find("[aria-describedby]").length||this.uiDialog.attr({"aria-describedby":this.element.uniqueId().attr("id")})},_createTitlebar:function(){var t;this.uiDialogTitlebar=e("<div>").addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(this.uiDialog),this._on(this.uiDialogTitlebar,{mousedown:function(t){e(t.target).closest(".ui-dialog-titlebar-close")||this.uiDialog.focus()}}),this.uiDialogTitlebarClose=e("<button></button>").button({label:this.options.closeText,icons:{primary:"ui-icon-closethick"},text:!1}).addClass("ui-dialog-titlebar-close").appendTo(this.uiDialogTitlebar),this._on(this.uiDialogTitlebarClose,{click:function(e){e.preventDefault(),this.close(e)}}),t=e("<span>").uniqueId().addClass("ui-dialog-title").prependTo(this.uiDialogTitlebar),this._title(t),this.uiDialog.attr({"aria-labelledby":t.attr("id")})},_title:function(e){this.options.title||e.html(" "),e.text(this.options.title)},_createButtonPane:function(){this.uiDialogButtonPane=e("<div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),this.uiButtonSet=e("<div>").addClass("ui-dialog-buttonset").appendTo(this.uiDialogButtonPane),this._createButtons()},_createButtons:function(){var t=this,n=this.options.buttons;this.uiDialogButtonPane.remove(),this.uiButtonSet.empty();if(e.isEmptyObject(n)||e.isArray(n)&&!n.length){this.uiDialog.removeClass("ui-dialog-buttons");return}e.each(n,function(n,r){var i,s;r=e.isFunction(r)?{click:r,text:n}:r,r=e.extend({type:"button"},r),i=r.click,r.click=function(){i.apply(t.element[0],arguments)},s={icons:r.icons,text:r.showText},delete r.icons,delete r.showText,e("<button></button>",r).button(s).appendTo(t.uiButtonSet)}),this.uiDialog.addClass("ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog)},_makeDraggable:function(){function r(e){return{position:e.position,offset:e.offset}}var t=this,n=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(n,i){e(this).addClass("ui-dialog-dragging"),t._blockFrames(),t._trigger("dragStart",n,r(i))},drag:function(e,n){t._trigger("drag",e,r(n))},stop:function(i,s){n.position=[s.position.left-t.document.scrollLeft(),s.position.top-t.document.scrollTop()],e(this).removeClass("ui-dialog-dragging"),t._unblockFrames(),t._trigger("dragStop",i,r(s))}})},_makeResizable:function(){function o(e){return{originalPosition:e.originalPosition,originalSize:e.originalSize,position:e.position,size:e.size}}var t=this,n=this.options,r=n.resizable,i=this.uiDialog.css("position"),s=typeof r=="string"?r:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:n.maxWidth,maxHeight:n.maxHeight,minWidth:n.minWidth,minHeight:this._minHeight(),handles:s,start:function(n,r){e(this).addClass("ui-dialog-resizing"),t._blockFrames(),t._trigger("resizeStart",n,o(r))},resize:function(e,n){t._trigger("resize",e,o(n))},stop:function(r,i){n.height=e(this).height(),n.width=e(this).width(),e(this).removeClass("ui-dialog-resizing"),t._unblockFrames(),t._trigger("resizeStop",r,o(i))}}).css("position",i)},_minHeight:function(){var e=this.options;return e.height==="auto"?e.minHeight:Math.min(e.minHeight,e.height)},_position:function(){var e=this.uiDialog.is(":visible");e||this.uiDialog.show(),this.uiDialog.position(this.options.position),e||this.uiDialog.hide()},_setOptions:function(t){var i=this,s=!1,o={};e.each(t,function(e,t){i._setOption(e,t),e in n&&(s=!0),e in r&&(o[e]=t)}),s&&(this._size(),this._position()),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option",o)},_setOption:function(e,t){var n,r,i=this.uiDialog;e==="dialogClass"&&i.removeClass(this.options.dialogClass).addClass(t);if(e==="disabled")return;this._super(e,t),e==="appendTo"&&this.uiDialog.appendTo(this._appendTo()),e==="buttons"&&this._createButtons(),e==="closeText"&&this.uiDialogTitlebarClose.button({label:""+t}),e==="draggable"&&(n=i.is(":data(ui-draggable)"),n&&!t&&i.draggable("destroy"),!n&&t&&this._makeDraggable()),e==="position"&&this._position(),e==="resizable"&&(r=i.is(":data(ui-resizable)"),r&&!t&&i.resizable("destroy"),r&&typeof t=="string"&&i.resizable("option","handles",t),!r&&t!==!1&&this._makeResizable()),e==="title"&&this._title(this.uiDialogTitlebar.find(".ui-dialog-title"))},_size:function(){var e,t,n,r=this.options;this.element.show().css({width:"auto",minHeight:0,maxHeight:"none",height:0}),r.minWidth>r.width&&(r.width=r.minWidth),e=this.uiDialog.css({height:"auto",width:r.width}).outerHeight(),t=Math.max(0,r.minHeight-e),n=typeof r.maxHeight=="number"?Math.max(0,r.maxHeight-e):"none",r.height==="auto"?this.element.css({minHeight:t,maxHeight:n,height:"auto"}):this.element.height(Math.max(0,r.height-e)),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())},_blockFrames:function(){this.iframeBlocks=this.document.find("iframe").map(function(){var t=e(this);return e("<div>").css({position:"absolute",width:t.outerWidth(),height:t.outerHeight()}).appendTo(t.parent()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_createOverlay:function(){if(!this.options.modal)return;e.ui.dialog.overlayInstances||this._delay(function(){e.ui.dialog.overlayInstances&&this.document.bind("focusin.dialog",function(t){!e(t.target).closest(".ui-dialog").length&&!e(t.target).closest(".ui-datepicker").length&&(t.preventDefault(),e(".ui-dialog:visible:last .ui-dialog-content").data("ui-dialog")._focusTabbable())})}),this.overlay=e("<div>").addClass("ui-widget-overlay ui-front").appendTo(this._appendTo()),this._on(this.overlay,{mousedown:"_keepFocus"}),e.ui.dialog.overlayInstances++},_destroyOverlay:function(){if(!this.options.modal)return;this.overlay&&(e.ui.dialog.overlayInstances--,e.ui.dialog.overlayInstances||this.document.unbind("focusin.dialog"),this.overlay.remove(),this.overlay=null)}}),e.ui.dialog.overlayInstances=0,e.uiBackCompat!==!1&&e.widget("ui.dialog",e.ui.dialog,{_position:function(){var t=this.options.position,n=[],r=[0,0],i;if(t){if(typeof t=="string"||typeof t=="object"&&"0"in t)n=t.split?t.split(" "):[t[0],t[1]],n.length===1&&(n[1]=n[0]),e.each(["left","top"],function(e,t){+n[e]===n[e]&&(r[e]=n[e],n[e]=t)}),t={my:n[0]+(r[0]<0?r[0]:"+"+r[0])+" "+n[1]+(r[1]<0?r[1]:"+"+r[1]),at:n.join(" ")};t=e.extend({},e.ui.dialog.prototype.options.position,t)}else t=e.ui.dialog.prototype.options.position;i=this.uiDialog.is(":visible"),i||this.uiDialog.show(),this.uiDialog.position(t),i||this.uiDialog.hide()}})})(jQuery);(function(e,t){e.widget("ui.draggable",e.ui.mouse,{version:"1.10.1",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){this.options.helper==="original"&&!/^(?:r|a|f)/.test(this.element.css("position"))&&(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},_destroy:function(){this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy()},_mouseCapture:function(t){var n=this.options;return this.helper||n.disabled||e(t.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(t),this.handle?(e(n.iframeFix===!0?"iframe":n.iframeFix).each(function(){e("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>").css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(e(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(t){var n=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,n.cursorAt&&this._adjustOffsetFromHelper(n.cursorAt),n.containment&&this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!n.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_mouseDrag:function(t,n){this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute");if(!n){var r=this._uiHash();if(this._trigger("drag",t,r)===!1)return this._mouseUp({}),!1;this.position=r.position}if(!this.options.axis||this.options.axis!=="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!=="x")this.helper[0].style.top=this.position.top+"px";return e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var n,r=this,i=!1,s=!1;e.ui.ddmanager&&!this.options.dropBehaviour&&(s=e.ui.ddmanager.drop(this,t)),this.dropped&&(s=this.dropped,this.dropped=!1),n=this.element[0];while(n&&(n=n.parentNode))n===document&&(i=!0);return!i&&this.options.helper==="original"?!1:(this.options.revert==="invalid"&&!s||this.options.revert==="valid"&&s||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){r._trigger("stop",t)!==!1&&r._clear()}):this._trigger("stop",t)!==!1&&this._clear(),!1)},_mouseUp:function(t){return e("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){var n=!this.options.handle||!e(this.options.handle,this.element).length?!0:!1;return e(this.options.handle,this.element).find("*").addBack().each(function(){this===t.target&&(n=!0)}),n},_createHelper:function(t){var n=this.options,r=e.isFunction(n.helper)?e(n.helper.apply(this.element[0],[t])):n.helper==="clone"?this.element.clone().removeAttr("id"):this.element;return r.parents("body").length||r.appendTo(n.appendTo==="parent"?this.element[0].parentNode:n.appendTo),r[0]!==this.element[0]&&!/(fixed|absolute)/.test(r.css("position"))&&r.css("position","absolute"),r},_adjustOffsetFromHelper:function(t){typeof t=="string"&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();this.cssPosition==="absolute"&&this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()==="html"&&e.ui.ie)t={top:0,left:0};return{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition==="relative"){var e=this.element.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,n,r,i=this.options;i.containment==="parent"&&(i.containment=this.helper[0].parentNode);if(i.containment==="document"||i.containment==="window")this.containment=[i.containment==="document"?0:e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,i.containment==="document"?0:e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,(i.containment==="document"?0:e(window).scrollLeft())+e(i.containment==="document"?document:window).width()-this.helperProportions.width-this.margins.left,(i.containment==="document"?0:e(window).scrollTop())+(e(i.containment==="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(i.containment)&&i.containment.constructor!==Array){n=e(i.containment),r=n[0];if(!r)return;t=e(r).css("overflow")!=="hidden",this.containment=[(parseInt(e(r).css("borderLeftWidth"),10)||0)+(parseInt(e(r).css("paddingLeft"),10)||0),(parseInt(e(r).css("borderTopWidth"),10)||0)+(parseInt(e(r).css("paddingTop"),10)||0),(t?Math.max(r.scrollWidth,r.offsetWidth):r.offsetWidth)-(parseInt(e(r).css("borderLeftWidth"),10)||0)-(parseInt(e(r).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(t?Math.max(r.scrollHeight,r.offsetHeight):r.offsetHeight)-(parseInt(e(r).css("borderTopWidth"),10)||0)-(parseInt(e(r).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=n}else i.containment.constructor===Array&&(this.containment=i.containment)},_convertPositionTo:function(t,n){n||(n=this.position);var r=t==="absolute"?1:-1,i=this.cssPosition!=="absolute"||this.scrollParent[0]!==document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,s=/(html|body)/i.test(i[0].tagName);return{top:n.top+this.offset.relative.top*r+this.offset.parent.top*r-(this.cssPosition==="fixed"?-this.scrollParent.scrollTop():s?0:i.scrollTop())*r,left:n.left+this.offset.relative.left*r+this.offset.parent.left*r-(this.cssPosition==="fixed"?-this.scrollParent.scrollLeft():s?0:i.scrollLeft())*r}},_generatePosition:function(t){var n,r,i,s,o=this.options,u=this.cssPosition!=="absolute"||this.scrollParent[0]!==document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,a=/(html|body)/i.test(u[0].tagName),f=t.pageX,l=t.pageY;return this.originalPosition&&(this.containment&&(this.relative_container?(r=this.relative_container.offset(),n=[this.containment[0]+r.left,this.containment[1]+r.top,this.containment[2]+r.left,this.containment[3]+r.top]):n=this.containment,t.pageX-this.offset.click.left<n[0]&&(f=n[0]+this.offset.click.left),t.pageY-this.offset.click.top<n[1]&&(l=n[1]+this.offset.click.top),t.pageX-this.offset.click.left>n[2]&&(f=n[2]+this.offset.click.left),t.pageY-this.offset.click.top>n[3]&&(l=n[3]+this.offset.click.top)),o.grid&&(i=o.grid[1]?this.originalPageY+Math.round((l-this.originalPageY)/o.grid[1])*o.grid[1]:this.originalPageY,l=n?i-this.offset.click.top>=n[1]||i-this.offset.click.top>n[3]?i:i-this.offset.click.top>=n[1]?i-o.grid[1]:i+o.grid[1]:i,s=o.grid[0]?this.originalPageX+Math.round((f-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX,f=n?s-this.offset.click.left>=n[0]||s-this.offset.click.left>n[2]?s:s-this.offset.click.left>=n[0]?s-o.grid[0]:s+o.grid[0]:s)),{top:l-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(this.cssPosition==="fixed"?-this.scrollParent.scrollTop():a?0:u.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(this.cssPosition==="fixed"?-this.scrollParent.scrollLeft():a?0:u.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]!==this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(t,n,r){return r=r||this._uiHash(),e.ui.plugin.call(this,t,[n,r]),t==="drag"&&(this.positionAbs=this._convertPositionTo("absolute")),e.Widget.prototype._trigger.call(this,t,n,r)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),e.ui.plugin.add("draggable","connectToSortable",{start:function(t,n){var r=e(this).data("ui-draggable"),i=r.options,s=e.extend({},n,{item:r.element});r.sortables=[],e(i.connectToSortable).each(function(){var n=e.data(this,"ui-sortable");n&&!n.options.disabled&&(r.sortables.push({instance:n,shouldRevert:n.options.revert}),n.refreshPositions(),n._trigger("activate",t,s))})},stop:function(t,n){var r=e(this).data("ui-draggable"),i=e.extend({},n,{item:r.element});e.each(r.sortables,function(){this.instance.isOver?(this.instance.isOver=0,r.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=!0),this.instance._mouseStop(t),this.instance.options.helper=this.instance.options._helper,r.options.helper==="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",t,i))})},drag:function(t,n){var r=e(this).data("ui-draggable"),i=this;e.each(r.sortables,function(){var s=!1,o=this;this.instance.positionAbs=r.positionAbs,this.instance.helperProportions=r.helperProportions,this.instance.offset.click=r.offset.click,this.instance._intersectsWith(this.instance.containerCache)&&(s=!0,e.each(r.sortables,function(){return this.instance.positionAbs=r.positionAbs,this.instance.helperProportions=r.helperProportions,this.instance.offset.click=r.offset.click,this!==o&&this.instance._intersectsWith(this.instance.containerCache)&&e.contains(o.instance.element[0],this.instance.element[0])&&(s=!1),s})),s?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=e(i).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return n.helper[0]},t.target=this.instance.currentItem[0],this.instance._mouseCapture(t,!0),this.instance._mouseStart(t,!0,!0),this.instance.offset.click.top=r.offset.click.top,this.instance.offset.click.left=r.offset.click.left,this.instance.offset.parent.left-=r.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=r.offset.parent.top-this.instance.offset.parent.top,r._trigger("toSortable",t),r.dropped=this.instance.element,r.currentItem=r.element,this.instance.fromOutside=r),this.instance.currentItem&&this.instance._mouseDrag(t)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",t,this.instance._uiHash(this.instance)),this.instance._mouseStop(t,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),r._trigger("fromSortable",t),r.dropped=!1)})}}),e.ui.plugin.add("draggable","cursor",{start:function(){var t=e("body"),n=e(this).data("ui-draggable").options;t.css("cursor")&&(n._cursor=t.css("cursor")),t.css("cursor",n.cursor)},stop:function(){var t=e(this).data("ui-draggable").options;t._cursor&&e("body").css("cursor",t._cursor)}}),e.ui.plugin.add("draggable","opacity",{start:function(t,n){var r=e(n.helper),i=e(this).data("ui-draggable").options;r.css("opacity")&&(i._opacity=r.css("opacity")),r.css("opacity",i.opacity)},stop:function(t,n){var r=e(this).data("ui-draggable").options;r._opacity&&e(n.helper).css("opacity",r._opacity)}}),e.ui.plugin.add("draggable","scroll",{start:function(){var t=e(this).data("ui-draggable");t.scrollParent[0]!==document&&t.scrollParent[0].tagName!=="HTML"&&(t.overflowOffset=t.scrollParent.offset())},drag:function(t){var n=e(this).data("ui-draggable"),r=n.options,i=!1;if(n.scrollParent[0]!==document&&n.scrollParent[0].tagName!=="HTML"){if(!r.axis||r.axis!=="x")n.overflowOffset.top+n.scrollParent[0].offsetHeight-t.pageY<r.scrollSensitivity?n.scrollParent[0].scrollTop=i=n.scrollParent[0].scrollTop+r.scrollSpeed:t.pageY-n.overflowOffset.top<r.scrollSensitivity&&(n.scrollParent[0].scrollTop=i=n.scrollParent[0].scrollTop-r.scrollSpeed);if(!r.axis||r.axis!=="y")n.overflowOffset.left+n.scrollParent[0].offsetWidth-t.pageX<r.scrollSensitivity?n.scrollParent[0].scrollLeft=i=n.scrollParent[0].scrollLeft+r.scrollSpeed:t.pageX-n.overflowOffset.left<r.scrollSensitivity&&(n.scrollParent[0].scrollLeft=i=n.scrollParent[0].scrollLeft-r.scrollSpeed)}else{if(!r.axis||r.axis!=="x")t.pageY-e(document).scrollTop()<r.scrollSensitivity?i=e(document).scrollTop(e(document).scrollTop()-r.scrollSpeed):e(window).height()-(t.pageY-e(document).scrollTop())<r.scrollSensitivity&&(i=e(document).scrollTop(e(document).scrollTop()+r.scrollSpeed));if(!r.axis||r.axis!=="y")t.pageX-e(document).scrollLeft()<r.scrollSensitivity?i=e(document).scrollLeft(e(document).scrollLeft()-r.scrollSpeed):e(window).width()-(t.pageX-e(document).scrollLeft())<r.scrollSensitivity&&(i=e(document).scrollLeft(e(document).scrollLeft()+r.scrollSpeed))}i!==!1&&e.ui.ddmanager&&!r.dropBehaviour&&e.ui.ddmanager.prepareOffsets(n,t)}}),e.ui.plugin.add("draggable","snap",{start:function(){var t=e(this).data("ui-draggable"),n=t.options;t.snapElements=[],e(n.snap.constructor!==String?n.snap.items||":data(ui-draggable)":n.snap).each(function(){var n=e(this),r=n.offset();this!==t.element[0]&&t.snapElements.push({item:this,width:n.outerWidth(),height:n.outerHeight(),top:r.top,left:r.left})})},drag:function(t,n){var r,i,s,o,u,a,f,l,c,h,p=e(this).data("ui-draggable"),d=p.options,v=d.snapTolerance,m=n.offset.left,g=m+p.helperProportions.width,y=n.offset.top,b=y+p.helperProportions.height;for(c=p.snapElements.length-1;c>=0;c--){u=p.snapElements[c].left,a=u+p.snapElements[c].width,f=p.snapElements[c].top,l=f+p.snapElements[c].height;if(!(u-v<m&&m<a+v&&f-v<y&&y<l+v||u-v<m&&m<a+v&&f-v<b&&b<l+v||u-v<g&&g<a+v&&f-v<y&&y<l+v||u-v<g&&g<a+v&&f-v<b&&b<l+v)){p.snapElements[c].snapping&&p.options.snap.release&&p.options.snap.release.call(p.element,t,e.extend(p._uiHash(),{snapItem:p.snapElements[c].item})),p.snapElements[c].snapping=!1;continue}d.snapMode!=="inner"&&(r=Math.abs(f-b)<=v,i=Math.abs(l-y)<=v,s=Math.abs(u-g)<=v,o=Math.abs(a-m)<=v,r&&(n.position.top=p._convertPositionTo("relative",{top:f-p.helperProportions.height,left:0}).top-p.margins.top),i&&(n.position.top=p._convertPositionTo("relative",{top:l,left:0}).top-p.margins.top),s&&(n.position.left=p._convertPositionTo("relative",{top:0,left:u-p.helperProportions.width}).left-p.margins.left),o&&(n.position.left=p._convertPositionTo("relative",{top:0,left:a}).left-p.margins.left)),h=r||i||s||o,d.snapMode!=="outer"&&(r=Math.abs(f-y)<=v,i=Math.abs(l-b)<=v,s=Math.abs(u-m)<=v,o=Math.abs(a-g)<=v,r&&(n.position.top=p._convertPositionTo("relative",{top:f,left:0}).top-p.margins.top),i&&(n.position.top=p._convertPositionTo("relative",{top:l-p.helperProportions.height,left:0}).top-p.margins.top),s&&(n.position.left=p._convertPositionTo("relative",{top:0,left:u}).left-p.margins.left),o&&(n.position.left=p._convertPositionTo("relative",{top:0,left:a-p.helperProportions.width}).left-p.margins.left)),!p.snapElements[c].snapping&&(r||i||s||o||h)&&p.options.snap.snap&&p.options.snap.snap.call(p.element,t,e.extend(p._uiHash(),{snapItem:p.snapElements[c].item})),p.snapElements[c].snapping=r||i||s||o||h}}}),e.ui.plugin.add("draggable","stack",{start:function(){var t,n=this.data("ui-draggable").options,r=e.makeArray(e(n.stack)).sort(function(t,n){return(parseInt(e(t).css("zIndex"),10)||0)-(parseInt(e(n).css("zIndex"),10)||0)});if(!r.length)return;t=parseInt(e(r[0]).css("zIndex"),10)||0,e(r).each(function(n){e(this).css("zIndex",t+n)}),this.css("zIndex",t+r.length)}}),e.ui.plugin.add("draggable","zIndex",{start:function(t,n){var r=e(n.helper),i=e(this).data("ui-draggable").options;r.css("zIndex")&&(i._zIndex=r.css("zIndex")),r.css("zIndex",i.zIndex)},stop:function(t,n){var r=e(this).data("ui-draggable").options;r._zIndex&&e(n.helper).css("zIndex",r._zIndex)}})})(jQuery);(function(e,t){function n(e,t,n){return e>t&&e<t+n}e.widget("ui.droppable",{version:"1.10.1",widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect",activate:null,deactivate:null,drop:null,out:null,over:null},_create:function(){var t=this.options,n=t.accept;this.isover=!1,this.isout=!0,this.accept=e.isFunction(n)?n:function(e){return e.is(n)},this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight},e.ui.ddmanager.droppables[t.scope]=e.ui.ddmanager.droppables[t.scope]||[],e.ui.ddmanager.droppables[t.scope].push(this),t.addClasses&&this.element.addClass("ui-droppable")},_destroy:function(){var t=0,n=e.ui.ddmanager.droppables[this.options.scope];for(;t<n.length;t++)n[t]===this&&n.splice(t,1);this.element.removeClass("ui-droppable ui-droppable-disabled")},_setOption:function(t,n){t==="accept"&&(this.accept=e.isFunction(n)?n:function(e){return e.is(n)}),e.Widget.prototype._setOption.apply(this,arguments)},_activate:function(t){var n=e.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),n&&this._trigger("activate",t,this.ui(n))},_deactivate:function(t){var n=e.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),n&&this._trigger("deactivate",t,this.ui(n))},_over:function(t){var n=e.ui.ddmanager.current;if(!n||(n.currentItem||n.element)[0]===this.element[0])return;this.accept.call(this.element[0],n.currentItem||n.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",t,this.ui(n)))},_out:function(t){var n=e.ui.ddmanager.current;if(!n||(n.currentItem||n.element)[0]===this.element[0])return;this.accept.call(this.element[0],n.currentItem||n.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",t,this.ui(n)))},_drop:function(t,n){var r=n||e.ui.ddmanager.current,i=!1;return!r||(r.currentItem||r.element)[0]===this.element[0]?!1:(this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function(){var t=e.data(this,"ui-droppable");if(t.options.greedy&&!t.options.disabled&&t.options.scope===r.options.scope&&t.accept.call(t.element[0],r.currentItem||r.element)&&e.ui.intersect(r,e.extend(t,{offset:t.element.offset()}),t.options.tolerance))return i=!0,!1}),i?!1:this.accept.call(this.element[0],r.currentItem||r.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",t,this.ui(r)),this.element):!1)},ui:function(e){return{draggable:e.currentItem||e.element,helper:e.helper,position:e.position,offset:e.positionAbs}}}),e.ui.intersect=function(e,t,r){if(!t.offset)return!1;var i,s,o=(e.positionAbs||e.position.absolute).left,u=o+e.helperProportions.width,a=(e.positionAbs||e.position.absolute).top,f=a+e.helperProportions.height,l=t.offset.left,c=l+t.proportions.width,h=t.offset.top,p=h+t.proportions.height;switch(r){case"fit":return l<=o&&u<=c&&h<=a&&f<=p;case"intersect":return l<o+e.helperProportions.width/2&&u-e.helperProportions.width/2<c&&h<a+e.helperProportions.height/2&&f-e.helperProportions.height/2<p;case"pointer":return i=(e.positionAbs||e.position.absolute).left+(e.clickOffset||e.offset.click).left,s=(e.positionAbs||e.position.absolute).top+(e.clickOffset||e.offset.click).top,n(s,h,t.proportions.height)&&n(i,l,t.proportions.width);case"touch":return(a>=h&&a<=p||f>=h&&f<=p||a<h&&f>p)&&(o>=l&&o<=c||u>=l&&u<=c||o<l&&u>c);default:return!1}},e.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(t,n){var r,i,s=e.ui.ddmanager.droppables[t.options.scope]||[],o=n?n.type:null,u=(t.currentItem||t.element).find(":data(ui-droppable)").addBack();e:for(r=0;r<s.length;r++){if(s[r].options.disabled||t&&!s[r].accept.call(s[r].element[0],t.currentItem||t.element))continue;for(i=0;i<u.length;i++)if(u[i]===s[r].element[0]){s[r].proportions.height=0;continue e}s[r].visible=s[r].element.css("display")!=="none";if(!s[r].visible)continue;o==="mousedown"&&s[r]._activate.call(s[r],n),s[r].offset=s[r].element.offset(),s[r].proportions={width:s[r].element[0].offsetWidth,height:s[r].element[0].offsetHeight}}},drop:function(t,n){var r=!1;return e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(!this.options)return;!this.options.disabled&&this.visible&&e.ui.intersect(t,this,this.options.tolerance)&&(r=this._drop.call(this,n)||r),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],t.currentItem||t.element)&&(this.isout=!0,this.isover=!1,this._deactivate.call(this,n))}),r},dragStart:function(t,n){t.element.parentsUntil("body").bind("scroll.droppable",function(){t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,n)})},drag:function(t,n){t.options.refreshPositions&&e.ui.ddmanager.prepareOffsets(t,n),e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(this.options.disabled||this.greedyChild||!this.visible)return;var r,i,s,o=e.ui.intersect(t,this,this.options.tolerance),u=!o&&this.isover?"isout":o&&!this.isover?"isover":null;if(!u)return;this.options.greedy&&(i=this.options.scope,s=this.element.parents(":data(ui-droppable)").filter(function(){return e.data(this,"ui-droppable").options.scope===i}),s.length&&(r=e.data(s[0],"ui-droppable"),r.greedyChild=u==="isover")),r&&u==="isover"&&(r.isover=!1,r.isout=!0,r._out.call(r,n)),this[u]=!0,this[u==="isout"?"isover":"isout"]=!1,this[u==="isover"?"_over":"_out"].call(this,n),r&&u==="isout"&&(r.isout=!1,r.isover=!0,r._over.call(r,n))})},dragStop:function(t,n){t.element.parentsUntil("body").unbind("scroll.droppable"),t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,n)}}})(jQuery);jQuery.effects||function(e,t){var n="ui-effects-";e.effects={effect:{}},function(e,t){function h(e,t,n){var r=u[t.type]||{};return e==null?n||!t.def?null:t.def:(e=r.floor?~~e:parseFloat(e),isNaN(e)?t.def:r.mod?(e+r.mod)%r.mod:0>e?0:r.max<e?r.max:e)}function p(t){var n=s(),r=n._rgba=[];return t=t.toLowerCase(),c(i,function(e,i){var s,u=i.re.exec(t),a=u&&i.parse(u),f=i.space||"rgba";if(a)return s=n[f](a),n[o[f].cache]=s[o[f].cache],r=n._rgba=s._rgba,!1}),r.length?(r.join()==="0,0,0,0"&&e.extend(r,l.transparent),n):l[t]}function d(e,t,n){return n=(n+1)%1,n*6<1?e+(t-e)*n*6:n*2<1?t:n*3<2?e+(t-e)*(2/3-n)*6:e}var n="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",r=/^([\-+])=\s*(\d+\.?\d*)/,i=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(e){return[e[1],e[2],e[3],e[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(e){return[e[1]*2.55,e[2]*2.55,e[3]*2.55,e[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(e){return[parseInt(e[1],16),parseInt(e[2],16),parseInt(e[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(e){return[parseInt(e[1]+e[1],16),parseInt(e[2]+e[2],16),parseInt(e[3]+e[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(e){return[e[1],e[2]/100,e[3]/100,e[4]]}}],s=e.Color=function(t,n,r,i){return new e.Color.fn.parse(t,n,r,i)},o={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},u={"byte":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},a=s.support={},f=e("<p>")[0],l,c=e.each;f.style.cssText="background-color:rgba(1,1,1,.5)",a.rgba=f.style.backgroundColor.indexOf("rgba")>-1,c(o,function(e,t){t.cache="_"+e,t.props.alpha={idx:3,type:"percent",def:1}}),s.fn=e.extend(s.prototype,{parse:function(n,r,i,u){if(n===t)return this._rgba=[null,null,null,null],this;if(n.jquery||n.nodeType)n=e(n).css(r),r=t;var a=this,f=e.type(n),d=this._rgba=[];r!==t&&(n=[n,r,i,u],f="array");if(f==="string")return this.parse(p(n)||l._default);if(f==="array")return c(o.rgba.props,function(e,t){d[t.idx]=h(n[t.idx],t)}),this;if(f==="object")return n instanceof s?c(o,function(e,t){n[t.cache]&&(a[t.cache]=n[t.cache].slice())}):c(o,function(t,r){var i=r.cache;c(r.props,function(e,t){if(!a[i]&&r.to){if(e==="alpha"||n[e]==null)return;a[i]=r.to(a._rgba)}a[i][t.idx]=h(n[e],t,!0)}),a[i]&&e.inArray(null,a[i].slice(0,3))<0&&(a[i][3]=1,r.from&&(a._rgba=r.from(a[i])))}),this},is:function(e){var t=s(e),n=!0,r=this;return c(o,function(e,i){var s,o=t[i.cache];return o&&(s=r[i.cache]||i.to&&i.to(r._rgba)||[],c(i.props,function(e,t){if(o[t.idx]!=null)return n=o[t.idx]===s[t.idx],n})),n}),n},_space:function(){var e=[],t=this;return c(o,function(n,r){t[r.cache]&&e.push(n)}),e.pop()},transition:function(e,t){var n=s(e),r=n._space(),i=o[r],a=this.alpha()===0?s("transparent"):this,f=a[i.cache]||i.to(a._rgba),l=f.slice();return n=n[i.cache],c(i.props,function(e,r){var i=r.idx,s=f[i],o=n[i],a=u[r.type]||{};if(o===null)return;s===null?l[i]=o:(a.mod&&(o-s>a.mod/2?s+=a.mod:s-o>a.mod/2&&(s-=a.mod)),l[i]=h((o-s)*t+s,r))}),this[r](l)},blend:function(t){if(this._rgba[3]===1)return this;var n=this._rgba.slice(),r=n.pop(),i=s(t)._rgba;return s(e.map(n,function(e,t){return(1-r)*i[t]+r*e}))},toRgbaString:function(){var t="rgba(",n=e.map(this._rgba,function(e,t){return e==null?t>2?1:0:e});return n[3]===1&&(n.pop(),t="rgb("),t+n.join()+")"},toHslaString:function(){var t="hsla(",n=e.map(this.hsla(),function(e,t){return e==null&&(e=t>2?1:0),t&&t<3&&(e=Math.round(e*100)+"%"),e});return n[3]===1&&(n.pop(),t="hsl("),t+n.join()+")"},toHexString:function(t){var n=this._rgba.slice(),r=n.pop();return t&&n.push(~~(r*255)),"#"+e.map(n,function(e){return e=(e||0).toString(16),e.length===1?"0"+e:e}).join("")},toString:function(){return this._rgba[3]===0?"transparent":this.toRgbaString()}}),s.fn.parse.prototype=s.fn,o.hsla.to=function(e){if(e[0]==null||e[1]==null||e[2]==null)return[null,null,null,e[3]];var t=e[0]/255,n=e[1]/255,r=e[2]/255,i=e[3],s=Math.max(t,n,r),o=Math.min(t,n,r),u=s-o,a=s+o,f=a*.5,l,c;return o===s?l=0:t===s?l=60*(n-r)/u+360:n===s?l=60*(r-t)/u+120:l=60*(t-n)/u+240,u===0?c=0:f<=.5?c=u/a:c=u/(2-a),[Math.round(l)%360,c,f,i==null?1:i]},o.hsla.from=function(e){if(e[0]==null||e[1]==null||e[2]==null)return[null,null,null,e[3]];var t=e[0]/360,n=e[1],r=e[2],i=e[3],s=r<=.5?r*(1+n):r+n-r*n,o=2*r-s;return[Math.round(d(o,s,t+1/3)*255),Math.round(d(o,s,t)*255),Math.round(d(o,s,t-1/3)*255),i]},c(o,function(n,i){var o=i.props,u=i.cache,a=i.to,f=i.from;s.fn[n]=function(n){a&&!this[u]&&(this[u]=a(this._rgba));if(n===t)return this[u].slice();var r,i=e.type(n),l=i==="array"||i==="object"?n:arguments,p=this[u].slice();return c(o,function(e,t){var n=l[i==="object"?e:t.idx];n==null&&(n=p[t.idx]),p[t.idx]=h(n,t)}),f?(r=s(f(p)),r[u]=p,r):s(p)},c(o,function(t,i){if(s.fn[t])return;s.fn[t]=function(s){var o=e.type(s),u=t==="alpha"?this._hsla?"hsla":"rgba":n,a=this[u](),f=a[i.idx],l;return o==="undefined"?f:(o==="function"&&(s=s.call(this,f),o=e.type(s)),s==null&&i.empty?this:(o==="string"&&(l=r.exec(s),l&&(s=f+parseFloat(l[2])*(l[1]==="+"?1:-1))),a[i.idx]=s,this[u](a)))}})}),s.hook=function(t){var n=t.split(" ");c(n,function(t,n){e.cssHooks[n]={set:function(t,r){var i,o,u="";if(r!=="transparent"&&(e.type(r)!=="string"||(i=p(r)))){r=s(i||r);if(!a.rgba&&r._rgba[3]!==1){o=n==="backgroundColor"?t.parentNode:t;while((u===""||u==="transparent")&&o&&o.style)try{u=e.css(o,"backgroundColor"),o=o.parentNode}catch(f){}r=r.blend(u&&u!=="transparent"?u:"_default")}r=r.toRgbaString()}try{t.style[n]=r}catch(f){}}},e.fx.step[n]=function(t){t.colorInit||(t.start=s(t.elem,n),t.end=s(t.end),t.colorInit=!0),e.cssHooks[n].set(t.elem,t.start.transition(t.end,t.pos))}})},s.hook(n),e.cssHooks.borderColor={expand:function(e){var t={};return c(["Top","Right","Bottom","Left"],function(n,r){t["border"+r+"Color"]=e}),t}},l=e.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(jQuery),function(){function i(t){var n,r,i=t.ownerDocument.defaultView?t.ownerDocument.defaultView.getComputedStyle(t,null):t.currentStyle,s={};if(i&&i.length&&i[0]&&i[i[0]]){r=i.length;while(r--)n=i[r],typeof i[n]=="string"&&(s[e.camelCase(n)]=i[n])}else for(n in i)typeof i[n]=="string"&&(s[n]=i[n]);return s}function s(t,n){var i={},s,o;for(s in n)o=n[s],t[s]!==o&&!r[s]&&(e.fx.step[s]||!isNaN(parseFloat(o)))&&(i[s]=o);return i}var n=["add","remove","toggle"],r={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};e.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(t,n){e.fx.step[n]=function(e){if(e.end!=="none"&&!e.setAttr||e.pos===1&&!e.setAttr)jQuery.style(e.elem,n,e.end),e.setAttr=!0}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}),e.effects.animateClass=function(t,r,o,u){var a=e.speed(r,o,u);return this.queue(function(){var r=e(this),o=r.attr("class")||"",u,f=a.children?r.find("*").addBack():r;f=f.map(function(){var t=e(this);return{el:t,start:i(this)}}),u=function(){e.each(n,function(e,n){t[n]&&r[n+"Class"](t[n])})},u(),f=f.map(function(){return this.end=i(this.el[0]),this.diff=s(this.start,this.end),this}),r.attr("class",o),f=f.map(function(){var t=this,n=e.Deferred(),r=e.extend({},a,{queue:!1,complete:function(){n.resolve(t)}});return this.el.animate(this.diff,r),n.promise()}),e.when.apply(e,f.get()).done(function(){u(),e.each(arguments,function(){var t=this.el;e.each(this.diff,function(e){t.css(e,"")})}),a.complete.call(r[0])})})},e.fn.extend({_addClass:e.fn.addClass,addClass:function(t,n,r,i){return n?e.effects.animateClass.call(this,{add:t},n,r,i):this._addClass(t)},_removeClass:e.fn.removeClass,removeClass:function(t,n,r,i){return arguments.length>1?e.effects.animateClass.call(this,{remove:t},n,r,i):this._removeClass.apply(this,arguments)},_toggleClass:e.fn.toggleClass,toggleClass:function(n,r,i,s,o){return typeof r=="boolean"||r===t?i?e.effects.animateClass.call(this,r?{add:n}:{remove:n},i,s,o):this._toggleClass(n,r):e.effects.animateClass.call(this,{toggle:n},r,i,s)},switchClass:function(t,n,r,i,s){return e.effects.animateClass.call(this,{add:n,remove:t},r,i,s)}})}(),function(){function r(t,n,r,i){e.isPlainObject(t)&&(n=t,t=t.effect),t={effect:t},n==null&&(n={}),e.isFunction(n)&&(i=n,r=null,n={});if(typeof n=="number"||e.fx.speeds[n])i=r,r=n,n={};return e.isFunction(r)&&(i=r,r=null),n&&e.extend(t,n),r=r||n.duration,t.duration=e.fx.off?0:typeof r=="number"?r:r in e.fx.speeds?e.fx.speeds[r]:e.fx.speeds._default,t.complete=i||n.complete,t}function i(t){return!t||typeof t=="number"||e.fx.speeds[t]?!0:typeof t=="string"&&!e.effects.effect[t]}e.extend(e.effects,{version:"1.10.1",save:function(e,t){for(var r=0;r<t.length;r++)t[r]!==null&&e.data(n+t[r],e[0].style[t[r]])},restore:function(e,r){var i,s;for(s=0;s<r.length;s++)r[s]!==null&&(i=e.data(n+r[s]),i===t&&(i=""),e.css(r[s],i))},setMode:function(e,t){return t==="toggle"&&(t=e.is(":hidden")?"show":"hide"),t},getBaseline:function(e,t){var n,r;switch(e[0]){case"top":n=0;break;case"middle":n=.5;break;case"bottom":n=1;break;default:n=e[0]/t.height}switch(e[1]){case"left":r=0;break;case"center":r=.5;break;case"right":r=1;break;default:r=e[1]/t.width}return{x:r,y:n}},createWrapper:function(t){if(t.parent().is(".ui-effects-wrapper"))return t.parent();var n={width:t.outerWidth(!0),height:t.outerHeight(!0),"float":t.css("float")},r=e("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),i={width:t.width(),height:t.height()},s=document.activeElement;try{s.id}catch(o){s=document.body}return t.wrap(r),(t[0]===s||e.contains(t[0],s))&&e(s).focus(),r=t.parent(),t.css("position")==="static"?(r.css({position:"relative"}),t.css({position:"relative"})):(e.extend(n,{position:t.css("position"),zIndex:t.css("z-index")}),e.each(["top","left","bottom","right"],function(e,r){n[r]=t.css(r),isNaN(parseInt(n[r],10))&&(n[r]="auto")}),t.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),t.css(i),r.css(n).show()},removeWrapper:function(t){var n=document.activeElement;return t.parent().is(".ui-effects-wrapper")&&(t.parent().replaceWith(t),(t[0]===n||e.contains(t[0],n))&&e(n).focus()),t},setTransition:function(t,n,r,i){return i=i||{},e.each(n,function(e,n){var s=t.cssUnit(n);s[0]>0&&(i[n]=s[0]*r+s[1])}),i}}),e.fn.extend({effect:function(){function o(n){function u(){e.isFunction(i)&&i.call(r[0]),e.isFunction(n)&&n()}var r=e(this),i=t.complete,o=t.mode;(r.is(":hidden")?o==="hide":o==="show")?u():s.call(r[0],t,u)}var t=r.apply(this,arguments),n=t.mode,i=t.queue,s=e.effects.effect[t.effect];return e.fx.off||!s?n?this[n](t.duration,t.complete):this.each(function(){t.complete&&t.complete.call(this)}):i===!1?this.each(o):this.queue(i||"fx",o)},_show:e.fn.show,show:function(e){if(i(e))return this._show.apply(this,arguments);var t=r.apply(this,arguments);return t.mode="show",this.effect.call(this,t)},_hide:e.fn.hide,hide:function(e){if(i(e))return this._hide.apply(this,arguments);var t=r.apply(this,arguments);return t.mode="hide",this.effect.call(this,t)},__toggle:e.fn.toggle,toggle:function(t){if(i(t)||typeof t=="boolean"||e.isFunction(t))return this.__toggle.apply(this,arguments);var n=r.apply(this,arguments);return n.mode="toggle",this.effect.call(this,n)},cssUnit:function(t){var n=this.css(t),r=[];return e.each(["em","px","%","pt"],function(e,t){n.indexOf(t)>0&&(r=[parseFloat(n),t])}),r}})}(),function(){var t={};e.each(["Quad","Cubic","Quart","Quint","Expo"],function(e,n){t[n]=function(t){return Math.pow(t,e+2)}}),e.extend(t,{Sine:function(e){return 1-Math.cos(e*Math.PI/2)},Circ:function(e){return 1-Math.sqrt(1-e*e)},Elastic:function(e){return e===0||e===1?e:-Math.pow(2,8*(e-1))*Math.sin(((e-1)*80-7.5)*Math.PI/15)},Back:function(e){return e*e*(3*e-2)},Bounce:function(e){var t,n=4;while(e<((t=Math.pow(2,--n))-1)/11);return 1/Math.pow(4,3-n)-7.5625*Math.pow((t*3-2)/22-e,2)}}),e.each(t,function(t,n){e.easing["easeIn"+t]=n,e.easing["easeOut"+t]=function(e){return 1-n(1-e)},e.easing["easeInOut"+t]=function(e){return e<.5?n(e*2)/2:1-n(e*-2+2)/2}})}()}(jQuery);(function(e,t){var n=/up|down|vertical/,r=/up|left|vertical|horizontal/;e.effects.effect.blind=function(t,i){var s=e(this),o=["position","top","bottom","left","right","height","width"],u=e.effects.setMode(s,t.mode||"hide"),a=t.direction||"up",f=n.test(a),l=f?"height":"width",c=f?"top":"left",h=r.test(a),p={},d=u==="show",v,m,g;s.parent().is(".ui-effects-wrapper")?e.effects.save(s.parent(),o):e.effects.save(s,o),s.show(),v=e.effects.createWrapper(s).css({overflow:"hidden"}),m=v[l](),g=parseFloat(v.css(c))||0,p[l]=d?m:0,h||(s.css(f?"bottom":"right",0).css(f?"top":"left","auto").css({position:"absolute"}),p[c]=d?g:m+g),d&&(v.css(l,0),h||v.css(c,g+m)),v.animate(p,{duration:t.duration,easing:t.easing,queue:!1,complete:function(){u==="hide"&&s.hide(),e.effects.restore(s,o),e.effects.removeWrapper(s),i()}})}})(jQuery);(function(e,t){e.effects.effect.bounce=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"effect"),o=s==="hide",u=s==="show",a=t.direction||"up",f=t.distance,l=t.times||5,c=l*2+(u||o?1:0),h=t.duration/c,p=t.easing,d=a==="up"||a==="down"?"top":"left",v=a==="up"||a==="left",m,g,y,b=r.queue(),w=b.length;(u||o)&&i.push("opacity"),e.effects.save(r,i),r.show(),e.effects.createWrapper(r),f||(f=r[d==="top"?"outerHeight":"outerWidth"]()/3),u&&(y={opacity:1},y[d]=0,r.css("opacity",0).css(d,v?-f*2:f*2).animate(y,h,p)),o&&(f/=Math.pow(2,l-1)),y={},y[d]=0;for(m=0;m<l;m++)g={},g[d]=(v?"-=":"+=")+f,r.animate(g,h,p).animate(y,h,p),f=o?f*2:f/2;o&&(g={opacity:0},g[d]=(v?"-=":"+=")+f,r.animate(g,h,p)),r.queue(function(){o&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}),w>1&&b.splice.apply(b,[1,0].concat(b.splice(w,c+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.clip=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=t.direction||"vertical",a=u==="vertical",f=a?"height":"width",l=a?"top":"left",c={},h,p,d;e.effects.save(r,i),r.show(),h=e.effects.createWrapper(r).css({overflow:"hidden"}),p=r[0].tagName==="IMG"?h:r,d=p[f](),o&&(p.css(f,0),p.css(l,d/2)),c[f]=o?d:0,c[l]=o?0:d/2,p.animate(c,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){o||r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.drop=function(t,n){var r=e(this),i=["position","top","bottom","left","right","opacity","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=t.direction||"left",a=u==="up"||u==="down"?"top":"left",f=u==="up"||u==="left"?"pos":"neg",l={opacity:o?1:0},c;e.effects.save(r,i),r.show(),e.effects.createWrapper(r),c=t.distance||r[a==="top"?"outerHeight":"outerWidth"](!0)/2,o&&r.css("opacity",0).css(a,f==="pos"?-c:c),l[a]=(o?f==="pos"?"+=":"-=":f==="pos"?"-=":"+=")+c,r.animate(l,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.explode=function(t,n){function y(){c.push(this),c.length===r*i&&b()}function b(){s.css({visibility:"visible"}),e(c).remove(),u||s.hide(),n()}var r=t.pieces?Math.round(Math.sqrt(t.pieces)):3,i=r,s=e(this),o=e.effects.setMode(s,t.mode||"hide"),u=o==="show",a=s.show().css("visibility","hidden").offset(),f=Math.ceil(s.outerWidth()/i),l=Math.ceil(s.outerHeight()/r),c=[],h,p,d,v,m,g;for(h=0;h<r;h++){v=a.top+h*l,g=h-(r-1)/2;for(p=0;p<i;p++)d=a.left+p*f,m=p-(i-1)/2,s.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-p*f,top:-h*l}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:f,height:l,left:d+(u?m*f:0),top:v+(u?g*l:0),opacity:u?0:1}).animate({left:d+(u?0:m*f),top:v+(u?0:g*l),opacity:u?1:0},t.duration||500,t.easing,y)}}})(jQuery);(function(e,t){e.effects.effect.fade=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"toggle");r.animate({opacity:i},{queue:!1,duration:t.duration,easing:t.easing,complete:n})}})(jQuery);(function(e,t){e.effects.effect.fold=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=s==="hide",a=t.size||15,f=/([0-9]+)%/.exec(a),l=!!t.horizFirst,c=o!==l,h=c?["width","height"]:["height","width"],p=t.duration/2,d,v,m={},g={};e.effects.save(r,i),r.show(),d=e.effects.createWrapper(r).css({overflow:"hidden"}),v=c?[d.width(),d.height()]:[d.height(),d.width()],f&&(a=parseInt(f[1],10)/100*v[u?0:1]),o&&d.css(l?{height:0,width:a}:{height:a,width:0}),m[h[0]]=o?v[0]:a,g[h[1]]=o?v[1]:0,d.animate(m,p,t.easing).animate(g,p,t.easing,function(){u&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()})}})(jQuery);(function(e,t){e.effects.effect.highlight=function(t,n){var r=e(this),i=["backgroundImage","backgroundColor","opacity"],s=e.effects.setMode(r,t.mode||"show"),o={backgroundColor:r.css("backgroundColor")};s==="hide"&&(o.opacity=0),e.effects.save(r,i),r.show().css({backgroundImage:"none",backgroundColor:t.color||"#ffff99"}).animate(o,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),n()}})}})(jQuery);(function(e,t){e.effects.effect.pulsate=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"show"),s=i==="show",o=i==="hide",u=s||i==="hide",a=(t.times||5)*2+(u?1:0),f=t.duration/a,l=0,c=r.queue(),h=c.length,p;if(s||!r.is(":visible"))r.css("opacity",0).show(),l=1;for(p=1;p<a;p++)r.animate({opacity:l},f,t.easing),l=1-l;r.animate({opacity:l},f,t.easing),r.queue(function(){o&&r.hide(),n()}),h>1&&c.splice.apply(c,[1,0].concat(c.splice(h,a+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.puff=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"hide"),s=i==="hide",o=parseInt(t.percent,10)||150,u=o/100,a={height:r.height(),width:r.width(),outerHeight:r.outerHeight(),outerWidth:r.outerWidth()};e.extend(t,{effect:"scale",queue:!1,fade:!0,mode:i,complete:n,percent:s?o:100,from:s?a:{height:a.height*u,width:a.width*u,outerHeight:a.outerHeight*u,outerWidth:a.outerWidth*u}}),r.effect(t)},e.effects.effect.scale=function(t,n){var r=e(this),i=e.extend(!0,{},t),s=e.effects.setMode(r,t.mode||"effect"),o=parseInt(t.percent,10)||(parseInt(t.percent,10)===0?0:s==="hide"?0:100),u=t.direction||"both",a=t.origin,f={height:r.height(),width:r.width(),outerHeight:r.outerHeight(),outerWidth:r.outerWidth()},l={y:u!=="horizontal"?o/100:1,x:u!=="vertical"?o/100:1};i.effect="size",i.queue=!1,i.complete=n,s!=="effect"&&(i.origin=a||["middle","center"],i.restore=!0),i.from=t.from||(s==="show"?{height:0,width:0,outerHeight:0,outerWidth:0}:f),i.to={height:f.height*l.y,width:f.width*l.x,outerHeight:f.outerHeight*l.y,outerWidth:f.outerWidth*l.x},i.fade&&(s==="show"&&(i.from.opacity=0,i.to.opacity=1),s==="hide"&&(i.from.opacity=1,i.to.opacity=0)),r.effect(i)},e.effects.effect.size=function(t,n){var r,i,s,o=e(this),u=["position","top","bottom","left","right","width","height","overflow","opacity"],a=["position","top","bottom","left","right","overflow","opacity"],f=["width","height","overflow"],l=["fontSize"],c=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],h=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],p=e.effects.setMode(o,t.mode||"effect"),d=t.restore||p!=="effect",v=t.scale||"both",m=t.origin||["middle","center"],g=o.css("position"),y=d?u:a,b={height:0,width:0,outerHeight:0,outerWidth:0};p==="show"&&o.show(),r={height:o.height(),width:o.width(),outerHeight:o.outerHeight(),outerWidth:o.outerWidth()},t.mode==="toggle"&&p==="show"?(o.from=t.to||b,o.to=t.from||r):(o.from=t.from||(p==="show"?b:r),o.to=t.to||(p==="hide"?b:r)),s={from:{y:o.from.height/r.height,x:o.from.width/r.width},to:{y:o.to.height/r.height,x:o.to.width/r.width}};if(v==="box"||v==="both")s.from.y!==s.to.y&&(y=y.concat(c),o.from=e.effects.setTransition(o,c,s.from.y,o.from),o.to=e.effects.setTransition(o,c,s.to.y,o.to)),s.from.x!==s.to.x&&(y=y.concat(h),o.from=e.effects.setTransition(o,h,s.from.x,o.from),o.to=e.effects.setTransition(o,h,s.to.x,o.to));(v==="content"||v==="both")&&s.from.y!==s.to.y&&(y=y.concat(l).concat(f),o.from=e.effects.setTransition(o,l,s.from.y,o.from),o.to=e.effects.setTransition(o,l,s.to.y,o.to)),e.effects.save(o,y),o.show(),e.effects.createWrapper(o),o.css("overflow","hidden").css(o.from),m&&(i=e.effects.getBaseline(m,r),o.from.top=(r.outerHeight-o.outerHeight())*i.y,o.from.left=(r.outerWidth-o.outerWidth())*i.x,o.to.top=(r.outerHeight-o.to.outerHeight)*i.y,o.to.left=(r.outerWidth-o.to.outerWidth)*i.x),o.css(o.from);if(v==="content"||v==="both")c=c.concat(["marginTop","marginBottom"]).concat(l),h=h.concat(["marginLeft","marginRight"]),f=u.concat(c).concat(h),o.find("*[width]").each(function(){var n=e(this),r={height:n.height(),width:n.width(),outerHeight:n.outerHeight(),outerWidth:n.outerWidth()};d&&e.effects.save(n,f),n.from={height:r.height*s.from.y,width:r.width*s.from.x,outerHeight:r.outerHeight*s.from.y,outerWidth:r.outerWidth*s.from.x},n.to={height:r.height*s.to.y,width:r.width*s.to.x,outerHeight:r.height*s.to.y,outerWidth:r.width*s.to.x},s.from.y!==s.to.y&&(n.from=e.effects.setTransition(n,c,s.from.y,n.from),n.to=e.effects.setTransition(n,c,s.to.y,n.to)),s.from.x!==s.to.x&&(n.from=e.effects.setTransition(n,h,s.from.x,n.from),n.to=e.effects.setTransition(n,h,s.to.x,n.to)),n.css(n.from),n.animate(n.to,t.duration,t.easing,function(){d&&e.effects.restore(n,f)})});o.animate(o.to,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){o.to.opacity===0&&o.css("opacity",o.from.opacity),p==="hide"&&o.hide(),e.effects.restore(o,y),d||(g==="static"?o.css({position:"relative",top:o.to.top,left:o.to.left}):e.each(["top","left"],function(e,t){o.css(t,function(t,n){var r=parseInt(n,10),i=e?o.to.left:o.to.top;return n==="auto"?i+"px":r+i+"px"})})),e.effects.removeWrapper(o),n()}})}})(jQuery);(function(e,t){e.effects.effect.shake=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"effect"),o=t.direction||"left",u=t.distance||20,a=t.times||3,f=a*2+1,l=Math.round(t.duration/f),c=o==="up"||o==="down"?"top":"left",h=o==="up"||o==="left",p={},d={},v={},m,g=r.queue(),y=g.length;e.effects.save(r,i),r.show(),e.effects.createWrapper(r),p[c]=(h?"-=":"+=")+u,d[c]=(h?"+=":"-=")+u*2,v[c]=(h?"-=":"+=")+u*2,r.animate(p,l,t.easing);for(m=1;m<a;m++)r.animate(d,l,t.easing).animate(v,l,t.easing);r.animate(d,l,t.easing).animate(p,l/2,t.easing).queue(function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}),y>1&&g.splice.apply(g,[1,0].concat(g.splice(y,f+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.slide=function(t,n){var r=e(this),i=["position","top","bottom","left","right","width","height"],s=e.effects.setMode(r,t.mode||"show"),o=s==="show",u=t.direction||"left",a=u==="up"||u==="down"?"top":"left",f=u==="up"||u==="left",l,c={};e.effects.save(r,i),r.show(),l=t.distance||r[a==="top"?"outerHeight":"outerWidth"](!0),e.effects.createWrapper(r).css({overflow:"hidden"}),o&&r.css(a,f?isNaN(l)?"-"+l:-l:l),c[a]=(o?f?"+=":"-=":f?"-=":"+=")+l,r.animate(c,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.transfer=function(t,n){var r=e(this),i=e(t.to),s=i.css("position")==="fixed",o=e("body"),u=s?o.scrollTop():0,a=s?o.scrollLeft():0,f=i.offset(),l={top:f.top-u,left:f.left-a,height:i.innerHeight(),width:i.innerWidth()},c=r.offset(),h=e("<div class='ui-effects-transfer'></div>").appendTo(document.body).addClass(t.className).css({top:c.top-u,left:c.left-a,height:r.innerHeight(),width:r.innerWidth(),position:s?"fixed":"absolute"}).animate(l,t.duration,t.easing,function(){h.remove(),n()})}})(jQuery);(function(e,t){e.widget("ui.menu",{version:"1.10.1",defaultElement:"<ul>",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content ui-corner-all").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}).bind("click"+this.eventNamespace,e.proxy(function(e){this.options.disabled&&e.preventDefault()},this)),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item > a":function(e){e.preventDefault()},"click .ui-state-disabled > a":function(e){e.preventDefault()},"click .ui-menu-item:has(a)":function(t){var n=e(t.target).closest(".ui-menu-item");!this.mouseHandled&&n.not(".ui-state-disabled").length&&(this.mouseHandled=!0,this.select(t),n.has(".ui-menu").length?this.expand(t):this.element.is(":focus")||(this.element.trigger("focus",[!0]),this.active&&this.active.parents(".ui-menu").length===1&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(t){var n=e(t.currentTarget);n.siblings().children(".ui-state-active").removeClass("ui-state-active"),this.focus(t,n)},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(e,t){var n=this.active||this.element.children(".ui-menu-item").eq(0);t||this.focus(e,n)},blur:function(t){this._delay(function(){e.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){e(t.target).closest(".ui-menu").length||this.collapseAll(t),this.mouseHandled=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeClass("ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").children("a").removeUniqueId().removeClass("ui-corner-all ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var t=e(this);t.data("ui-menu-submenu-carat")&&t.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(t){function a(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}var n,r,i,s,o,u=!0;switch(t.keyCode){case e.ui.keyCode.PAGE_UP:this.previousPage(t);break;case e.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case e.ui.keyCode.HOME:this._move("first","first",t);break;case e.ui.keyCode.END:this._move("last","last",t);break;case e.ui.keyCode.UP:this.previous(t);break;case e.ui.keyCode.DOWN:this.next(t);break;case e.ui.keyCode.LEFT:this.collapse(t);break;case e.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case e.ui.keyCode.ENTER:case e.ui.keyCode.SPACE:this._activate(t);break;case e.ui.keyCode.ESCAPE:this.collapse(t);break;default:u=!1,r=this.previousFilter||"",i=String.fromCharCode(t.keyCode),s=!1,clearTimeout(this.filterTimer),i===r?s=!0:i=r+i,o=new RegExp("^"+a(i),"i"),n=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())}),n=s&&n.index(this.active.next())!==-1?this.active.nextAll(".ui-menu-item"):n,n.length||(i=String.fromCharCode(t.keyCode),o=new RegExp("^"+a(i),"i"),n=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())})),n.length?(this.focus(t,n),n.length>1?(this.previousFilter=i,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter):delete this.previousFilter}u&&t.preventDefault()},_activate:function(e){this.active.is(".ui-state-disabled")||(this.active.children("a[aria-haspopup='true']").length?this.expand(e):this.select(e))},refresh:function(){var t,n=this.options.icons.submenu,r=this.element.find(this.options.menus);r.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-corner-all").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=e(this),r=t.prev("a"),i=e("<span>").addClass("ui-menu-icon ui-icon "+n).data("ui-menu-submenu-carat",!0);r.attr("aria-haspopup","true").prepend(i),t.attr("aria-labelledby",r.attr("id"))}),t=r.add(this.element),t.children(":not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","presentation").children("a").uniqueId().addClass("ui-corner-all").attr({tabIndex:-1,role:this._itemRole()}),t.children(":not(.ui-menu-item)").each(function(){var t=e(this);/[^\-\u2014\u2013\s]/.test(t.text())||t.addClass("ui-widget-content ui-menu-divider")}),t.children(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!e.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(e,t){e==="icons"&&this.element.find(".ui-menu-icon").removeClass(this.options.icons.submenu).addClass(t.submenu),this._super(e,t)},focus:function(e,t){var n,r;this.blur(e,e&&e.type==="focus"),this._scrollIntoView(t),this.active=t.first(),r=this.active.children("a").addClass("ui-state-focus"),this.options.role&&this.element.attr("aria-activedescendant",r.attr("id")),this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"),e&&e.type==="keydown"?this._close():this.timer=this._delay(function(){this._close()},this.delay),n=t.children(".ui-menu"),n.length&&/^mouse/.test(e.type)&&this._startOpening(n),this.activeMenu=t.parent(),this._trigger("focus",e,{item:t})},_scrollIntoView:function(t){var n,r,i,s,o,u;this._hasScroll()&&(n=parseFloat(e.css(this.activeMenu[0],"borderTopWidth"))||0,r=parseFloat(e.css(this.activeMenu[0],"paddingTop"))||0,i=t.offset().top-this.activeMenu.offset().top-n-r,s=this.activeMenu.scrollTop(),o=this.activeMenu.height(),u=t.height(),i<0?this.activeMenu.scrollTop(s+i):i+u>o&&this.activeMenu.scrollTop(s+i-o+u))},blur:function(e,t){t||clearTimeout(this.timer);if(!this.active)return;this.active.children("a").removeClass("ui-state-focus"),this.active=null,this._trigger("blur",e,{item:this.active})},_startOpening:function(e){clearTimeout(this.timer);if(e.attr("aria-hidden")!=="true")return;this.timer=this._delay(function(){this._close(),this._open(e)},this.delay)},_open:function(t){var n=e.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(t.parents(".ui-menu")).hide().attr("aria-hidden","true"),t.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(n)},collapseAll:function(t,n){clearTimeout(this.timer),this.timer=this._delay(function(){var r=n?this.element:e(t&&t.target).closest(this.element.find(".ui-menu"));r.length||(r=this.element),this._close(r),this.blur(t),this.activeMenu=r},this.delay)},_close:function(e){e||(e=this.active?this.active.parent():this.element),e.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find("a.ui-state-active").removeClass("ui-state-active")},collapse:function(e){var t=this.active&&this.active.parent().closest(".ui-menu-item",this.element);t&&t.length&&(this._close(),this.focus(e,t))},expand:function(e){var t=this.active&&this.active.children(".ui-menu ").children(".ui-menu-item").first();t&&t.length&&(this._open(t.parent()),this._delay(function(){this.focus(e,t)}))},next:function(e){this._move("next","first",e)},previous:function(e){this._move("prev","last",e)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(e,t,n){var r;this.active&&(e==="first"||e==="last"?r=this.active[e==="first"?"prevAll":"nextAll"](".ui-menu-item").eq(-1):r=this.active[e+"All"](".ui-menu-item").eq(0));if(!r||!r.length||!this.active)r=this.activeMenu.children(".ui-menu-item")[t]();this.focus(n,r)},nextPage:function(t){var n,r,i;if(!this.active){this.next(t);return}if(this.isLastItem())return;this._hasScroll()?(r=this.active.offset().top,i=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return n=e(this),n.offset().top-r-i<0}),this.focus(t,n)):this.focus(t,this.activeMenu.children(".ui-menu-item")[this.active?"last":"first"]())},previousPage:function(t){var n,r,i;if(!this.active){this.next(t);return}if(this.isFirstItem())return;this._hasScroll()?(r=this.active.offset().top,i=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return n=e(this),n.offset().top-r+i>0}),this.focus(t,n)):this.focus(t,this.activeMenu.children(".ui-menu-item").first())},_hasScroll:function(){return this.element.outerHeight()<this.element.prop("scrollHeight")},select:function(t){this.active=this.active||e(t.target).closest(".ui-menu-item");var n={item:this.active};this.active.has(".ui-menu").length||this.collapseAll(t,!0),this._trigger("select",t,n)}})})(jQuery);(function(e,t){e.widget("ui.progressbar",{version:"1.10.1",options:{max:100,value:0,change:null,complete:null},min:0,_create:function(){this.oldValue=this.options.value=this._constrainedValue(),this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min}),this.valueDiv=e("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element),this._refreshValue()},_destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove()},value:function(e){if(e===t)return this.options.value;this.options.value=this._constrainedValue(e),this._refreshValue()},_constrainedValue:function(e){return e===t&&(e=this.options.value),this.indeterminate=e===!1,typeof e!="number"&&(e=0),this.indeterminate?!1:Math.min(this.options.max,Math.max(this.min,e))},_setOptions:function(e){var t=e.value;delete e.value,this._super(e),this.options.value=this._constrainedValue(t),this._refreshValue()},_setOption:function(e,t){e==="max"&&(t=Math.max(this.min,t)),this._super(e,t)},_percentage:function(){return this.indeterminate?100:100*(this.options.value-this.min)/(this.options.max-this.min)},_refreshValue:function(){var t=this.options.value,n=this._percentage();this.valueDiv.toggle(this.indeterminate||t>this.min).toggleClass("ui-corner-right",t===this.options.max).width(n.toFixed(0)+"%"),this.element.toggleClass("ui-progressbar-indeterminate",this.indeterminate),this.indeterminate?(this.element.removeAttr("aria-valuenow"),this.overlayDiv||(this.overlayDiv=e("<div class='ui-progressbar-overlay'></div>").appendTo(this.valueDiv))):(this.element.attr({"aria-valuemax":this.options.max,"aria-valuenow":t}),this.overlayDiv&&(this.overlayDiv.remove(),this.overlayDiv=null)),this.oldValue!==t&&(this.oldValue=t,this._trigger("change")),t===this.options.max&&this._trigger("complete")}})})(jQuery);(function(e,t){function n(e){return parseInt(e,10)||0}function r(e){return!isNaN(parseInt(e,10))}e.widget("ui.resizable",e.ui.mouse,{version:"1.10.1",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_create:function(){var t,n,r,i,s,o=this,u=this.options;this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!u.aspectRatio,aspectRatio:u.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:u.helper||u.ghost||u.animate?u.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.data("ui-resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=u.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se");if(this.handles.constructor===String){this.handles==="all"&&(this.handles="n,e,s,w,se,sw,ne,nw"),t=this.handles.split(","),this.handles={};for(n=0;n<t.length;n++)r=e.trim(t[n]),s="ui-resizable-"+r,i=e("<div class='ui-resizable-handle "+s+"'></div>"),i.css({zIndex:u.zIndex}),"se"===r&&i.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[r]=".ui-resizable-"+r,this.element.append(i)}this._renderAxis=function(t){var n,r,i,s;t=t||this.element;for(n in this.handles){this.handles[n].constructor===String&&(this.handles[n]=e(this.handles[n],this.element).show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(r=e(this.handles[n],this.element),s=/sw|ne|nw|se|n|s/.test(n)?r.outerHeight():r.outerWidth(),i=["padding",/ne|nw|n/.test(n)?"Top":/se|sw|s/.test(n)?"Bottom":/^e$/.test(n)?"Right":"Left"].join(""),t.css(i,s),this._proportionallyResize());if(!e(this.handles[n]).length)continue}},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(i=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=i&&i[1]?i[1]:"se")}),u.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){if(u.disabled)return;e(this).removeClass("ui-resizable-autohide"),o._handles.show()}).mouseleave(function(){if(u.disabled)return;o.resizing||(e(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,n=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(n(this.element),t=this.element,this.originalElement.css({position:t.css("position"),width:t.outerWidth(),height:t.outerHeight(),top:t.css("top"),left:t.css("left")}).insertAfter(t),t.remove()),this.originalElement.css("resize",this.originalResizeStyle),n(this.originalElement),this},_mouseCapture:function(t){var n,r,i=!1;for(n in this.handles){r=e(this.handles[n])[0];if(r===t.target||e.contains(r,t.target))i=!0}return!this.options.disabled&&i},_mouseStart:function(t){var r,i,s,o=this.options,u=this.element.position(),a=this.element;return this.resizing=!0,/absolute/.test(a.css("position"))?a.css({position:"absolute",top:a.css("top"),left:a.css("left")}):a.is(".ui-draggable")&&a.css({position:"absolute",top:u.top,left:u.left}),this._renderProxy(),r=n(this.helper.css("left")),i=n(this.helper.css("top")),o.containment&&(r+=e(o.containment).scrollLeft()||0,i+=e(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:r,top:i},this.size=this._helper?{width:a.outerWidth(),height:a.outerHeight()}:{width:a.width(),height:a.height()},this.originalSize=this._helper?{width:a.outerWidth(),height:a.outerHeight()}:{width:a.width(),height:a.height()},this.originalPosition={left:r,top:i},this.sizeDiff={width:a.outerWidth()-a.width(),height:a.outerHeight()-a.height()},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio=typeof o.aspectRatio=="number"?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,s=e(".ui-resizable-"+this.axis).css("cursor"),e("body").css("cursor",s==="auto"?this.axis+"-resize":s),a.addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(t){var n,r=this.helper,i={},s=this.originalMousePosition,o=this.axis,u=this.position.top,a=this.position.left,f=this.size.width,l=this.size.height,c=t.pageX-s.left||0,h=t.pageY-s.top||0,p=this._change[o];if(!p)return!1;n=p.apply(this,[t,c,h]),this._updateVirtualBoundaries(t.shiftKey);if(this._aspectRatio||t.shiftKey)n=this._updateRatio(n,t);return n=this._respectSize(n,t),this._updateCache(n),this._propagate("resize",t),this.position.top!==u&&(i.top=this.position.top+"px"),this.position.left!==a&&(i.left=this.position.left+"px"),this.size.width!==f&&(i.width=this.size.width+"px"),this.size.height!==l&&(i.height=this.size.height+"px"),r.css(i),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(i)||this._trigger("resize",t,this.ui()),!1},_mouseStop:function(t){this.resizing=!1;var n,r,i,s,o,u,a,f=this.options,l=this;return this._helper&&(n=this._proportionallyResizeElements,r=n.length&&/textarea/i.test(n[0].nodeName),i=r&&e.ui.hasScroll(n[0],"left")?0:l.sizeDiff.height,s=r?0:l.sizeDiff.width,o={width:l.helper.width()-s,height:l.helper.height()-i},u=parseInt(l.element.css("left"),10)+(l.position.left-l.originalPosition.left)||null,a=parseInt(l.element.css("top"),10)+(l.position.top-l.originalPosition.top)||null,f.animate||this.element.css(e.extend(o,{top:a,left:u})),l.helper.height(l.size.height),l.helper.width(l.size.width),this._helper&&!f.animate&&this._proportionallyResize()),e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t,n,i,s,o,u=this.options;o={minWidth:r(u.minWidth)?u.minWidth:0,maxWidth:r(u.maxWidth)?u.maxWidth:Infinity,minHeight:r(u.minHeight)?u.minHeight:0,maxHeight:r(u.maxHeight)?u.maxHeight:Infinity};if(this._aspectRatio||e)t=o.minHeight*this.aspectRatio,i=o.minWidth/this.aspectRatio,n=o.maxHeight*this.aspectRatio,s=o.maxWidth/this.aspectRatio,t>o.minWidth&&(o.minWidth=t),i>o.minHeight&&(o.minHeight=i),n<o.maxWidth&&(o.maxWidth=n),s<o.maxHeight&&(o.maxHeight=s);this._vBoundaries=o},_updateCache:function(e){this.offset=this.helper.offset(),r(e.left)&&(this.position.left=e.left),r(e.top)&&(this.position.top=e.top),r(e.height)&&(this.size.height=e.height),r(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,n=this.size,i=this.axis;return r(e.height)?e.width=e.height*this.aspectRatio:r(e.width)&&(e.height=e.width/this.aspectRatio),i==="sw"&&(e.left=t.left+(n.width-e.width),e.top=null),i==="nw"&&(e.top=t.top+(n.height-e.height),e.left=t.left+(n.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,n=this.axis,i=r(e.width)&&t.maxWidth&&t.maxWidth<e.width,s=r(e.height)&&t.maxHeight&&t.maxHeight<e.height,o=r(e.width)&&t.minWidth&&t.minWidth>e.width,u=r(e.height)&&t.minHeight&&t.minHeight>e.height,a=this.originalPosition.left+this.originalSize.width,f=this.position.top+this.size.height,l=/sw|nw|w/.test(n),c=/nw|ne|n/.test(n);return o&&(e.width=t.minWidth),u&&(e.height=t.minHeight),i&&(e.width=t.maxWidth),s&&(e.height=t.maxHeight),o&&l&&(e.left=a-t.minWidth),i&&l&&(e.left=a-t.maxWidth),u&&c&&(e.top=f-t.minHeight),s&&c&&(e.top=f-t.maxHeight),!e.width&&!e.height&&!e.left&&e.top?e.top=null:!e.width&&!e.height&&!e.top&&e.left&&(e.left=null),e},_proportionallyResize:function(){if(!this._proportionallyResizeElements.length)return;var e,t,n,r,i,s=this.helper||this.element;for(e=0;e<this._proportionallyResizeElements.length;e++){i=this._proportionallyResizeElements[e];if(!this.borderDif){this.borderDif=[],n=[i.css("borderTopWidth"),i.css("borderRightWidth"),i.css("borderBottomWidth"),i.css("borderLeftWidth")],r=[i.css("paddingTop"),i.css("paddingRight"),i.css("paddingBottom"),i.css("paddingLeft")];for(t=0;t<n.length;t++)this.borderDif[t]=(parseInt(n[t],10)||0)+(parseInt(r[t],10)||0)}i.css({height:s.height()-this.borderDif[0]-this.borderDif[2]||0,width:s.width()-this.borderDif[1]-this.borderDif[3]||0})}},_renderProxy:function(){var t=this.element,n=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e("<div style='overflow:hidden;'></div>"),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++n.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var n=this.originalSize,r=this.originalPosition;return{left:r.left+t,width:n.width-t}},n:function(e,t,n){var r=this.originalSize,i=this.originalPosition;return{top:i.top+n,height:r.height-n}},s:function(e,t,n){return{height:this.originalSize.height+n}},se:function(t,n,r){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,n,r]))},sw:function(t,n,r){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,n,r]))},ne:function(t,n,r){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,n,r]))},nw:function(t,n,r){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,n,r]))}},_propagate:function(t,n){e.ui.plugin.call(this,t,[n,this.ui()]),t!=="resize"&&this._trigger(t,n,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","animate",{stop:function(t){var n=e(this).data("ui-resizable"),r=n.options,i=n._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),o=s&&e.ui.hasScroll(i[0],"left")?0:n.sizeDiff.height,u=s?0:n.sizeDiff.width,a={width:n.size.width-u,height:n.size.height-o},f=parseInt(n.element.css("left"),10)+(n.position.left-n.originalPosition.left)||null,l=parseInt(n.element.css("top"),10)+(n.position.top-n.originalPosition.top)||null;n.element.animate(e.extend(a,l&&f?{top:l,left:f}:{}),{duration:r.animateDuration,easing:r.animateEasing,step:function(){var r={width:parseInt(n.element.css("width"),10),height:parseInt(n.element.css("height"),10),top:parseInt(n.element.css("top"),10),left:parseInt(n.element.css("left"),10)};i&&i.length&&e(i[0]).css({width:r.width,height:r.height}),n._updateCache(r),n._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(){var t,r,i,s,o,u,a,f=e(this).data("ui-resizable"),l=f.options,c=f.element,h=l.containment,p=h instanceof e?h.get(0):/parent/.test(h)?c.parent().get(0):h;if(!p)return;f.containerElement=e(p),/document/.test(h)||h===document?(f.containerOffset={left:0,top:0},f.containerPosition={left:0,top:0},f.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(t=e(p),r=[],e(["Top","Right","Left","Bottom"]).each(function(e,i){r[e]=n(t.css("padding"+i))}),f.containerOffset=t.offset(),f.containerPosition=t.position(),f.containerSize={height:t.innerHeight()-r[3],width:t.innerWidth()-r[1]},i=f.containerOffset,s=f.containerSize.height,o=f.containerSize.width,u=e.ui.hasScroll(p,"left")?p.scrollWidth:o,a=e.ui.hasScroll(p)?p.scrollHeight:s,f.parentData={element:p,left:i.left,top:i.top,width:u,height:a})},resize:function(t){var n,r,i,s,o=e(this).data("ui-resizable"),u=o.options,a=o.containerOffset,f=o.position,l=o._aspectRatio||t.shiftKey,c={top:0,left:0},h=o.containerElement;h[0]!==document&&/static/.test(h.css("position"))&&(c=a),f.left<(o._helper?a.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-a.left:o.position.left-c.left),l&&(o.size.height=o.size.width/o.aspectRatio),o.position.left=u.helper?a.left:0),f.top<(o._helper?a.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-a.top:o.position.top),l&&(o.size.width=o.size.height*o.aspectRatio),o.position.top=o._helper?a.top:0),o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top,n=Math.abs((o._helper?o.offset.left-c.left:o.offset.left-c.left)+o.sizeDiff.width),r=Math.abs((o._helper?o.offset.top-c.top:o.offset.top-a.top)+o.sizeDiff.height),i=o.containerElement.get(0)===o.element.parent().get(0),s=/relative|absolute/.test(o.containerElement.css("position")),i&&s&&(n-=o.parentData.left),n+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-n,l&&(o.size.height=o.size.width/o.aspectRatio)),r+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-r,l&&(o.size.width=o.size.height*o.aspectRatio))},stop:function(){var t=e(this).data("ui-resizable"),n=t.options,r=t.containerOffset,i=t.containerPosition,s=t.containerElement,o=e(t.helper),u=o.offset(),a=o.outerWidth()-t.sizeDiff.width,f=o.outerHeight()-t.sizeDiff.height;t._helper&&!n.animate&&/relative/.test(s.css("position"))&&e(this).css({left:u.left-i.left-r.left,width:a,height:f}),t._helper&&!n.animate&&/static/.test(s.css("position"))&&e(this).css({left:u.left-i.left-r.left,width:a,height:f})}}),e.ui.plugin.add("resizable","alsoResize",{start:function(){var t=e(this).data("ui-resizable"),n=t.options,r=function(t){e(t).each(function(){var t=e(this);t.data("ui-resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};typeof n.alsoResize=="object"&&!n.alsoResize.parentNode?n.alsoResize.length?(n.alsoResize=n.alsoResize[0],r(n.alsoResize)):e.each(n.alsoResize,function(e){r(e)}):r(n.alsoResize)},resize:function(t,n){var r=e(this).data("ui-resizable"),i=r.options,s=r.originalSize,o=r.originalPosition,u={height:r.size.height-s.height||0,width:r.size.width-s.width||0,top:r.position.top-o.top||0,left:r.position.left-o.left||0},a=function(t,r){e(t).each(function(){var t=e(this),i=e(this).data("ui-resizable-alsoresize"),s={},o=r&&r.length?r:t.parents(n.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var n=(i[t]||0)+(u[t]||0);n&&n>=0&&(s[t]=n||null)}),t.css(s)})};typeof i.alsoResize=="object"&&!i.alsoResize.nodeType?e.each(i.alsoResize,function(e,t){a(e,t)}):a(i.alsoResize)},stop:function(){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","ghost",{start:function(){var t=e(this).data("ui-resizable"),n=t.options,r=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:r.height,width:r.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof n.ghost=="string"?n.ghost:""),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).data("ui-resizable");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).data("ui-resizable");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(){var t=e(this).data("ui-resizable"),n=t.options,r=t.size,i=t.originalSize,s=t.originalPosition,o=t.axis,u=typeof n.grid=="number"?[n.grid,n.grid]:n.grid,a=u[0]||1,f=u[1]||1,l=Math.round((r.width-i.width)/a)*a,c=Math.round((r.height-i.height)/f)*f,h=i.width+l,p=i.height+c,d=n.maxWidth&&n.maxWidth<h,v=n.maxHeight&&n.maxHeight<p,m=n.minWidth&&n.minWidth>h,g=n.minHeight&&n.minHeight>p;n.grid=u,m&&(h+=a),g&&(p+=f),d&&(h-=a),v&&(p-=f),/^(se|s|e)$/.test(o)?(t.size.width=h,t.size.height=p):/^(ne)$/.test(o)?(t.size.width=h,t.size.height=p,t.position.top=s.top-c):/^(sw)$/.test(o)?(t.size.width=h,t.size.height=p,t.position.left=s.left-l):(t.size.width=h,t.size.height=p,t.position.top=s.top-c,t.position.left=s.left-l)}})})(jQuery);(function(e,t){e.widget("ui.selectable",e.ui.mouse,{version:"1.10.1",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var t,n=this;this.element.addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){t=e(n.options.filter,n.element[0]),t.addClass("ui-selectee"),t.each(function(){var t=e(this),n=t.offset();e.data(this,"selectable-item",{element:this,$element:t,left:n.left,top:n.top,right:n.left+t.outerWidth(),bottom:n.top+t.outerHeight(),startselected:!1,selected:t.hasClass("ui-selected"),selecting:t.hasClass("ui-selecting"),unselecting:t.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=t.addClass("ui-selectee"),this._mouseInit(),this.helper=e("<div class='ui-selectable-helper'></div>")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(t){var n=this,r=this.options;this.opos=[t.pageX,t.pageY];if(this.options.disabled)return;this.selectees=e(r.filter,this.element[0]),this._trigger("start",t),e(r.appendTo).append(this.helper),this.helper.css({left:t.pageX,top:t.pageY,width:0,height:0}),r.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var r=e.data(this,"selectable-item");r.startselected=!0,!t.metaKey&&!t.ctrlKey&&(r.$element.removeClass("ui-selected"),r.selected=!1,r.$element.addClass("ui-unselecting"),r.unselecting=!0,n._trigger("unselecting",t,{unselecting:r.element}))}),e(t.target).parents().addBack().each(function(){var r,i=e.data(this,"selectable-item");if(i)return r=!t.metaKey&&!t.ctrlKey||!i.$element.hasClass("ui-selected"),i.$element.removeClass(r?"ui-unselecting":"ui-selected").addClass(r?"ui-selecting":"ui-unselecting"),i.unselecting=!r,i.selecting=r,i.selected=r,r?n._trigger("selecting",t,{selecting:i.element}):n._trigger("unselecting",t,{unselecting:i.element}),!1})},_mouseDrag:function(t){this.dragged=!0;if(this.options.disabled)return;var n,r=this,i=this.options,s=this.opos[0],o=this.opos[1],u=t.pageX,a=t.pageY;return s>u&&(n=u,u=s,s=n),o>a&&(n=a,a=o,o=n),this.helper.css({left:s,top:o,width:u-s,height:a-o}),this.selectees.each(function(){var n=e.data(this,"selectable-item"),f=!1;if(!n||n.element===r.element[0])return;i.tolerance==="touch"?f=!(n.left>u||n.right<s||n.top>a||n.bottom<o):i.tolerance==="fit"&&(f=n.left>s&&n.right<u&&n.top>o&&n.bottom<a),f?(n.selected&&(n.$element.removeClass("ui-selected"),n.selected=!1),n.unselecting&&(n.$element.removeClass("ui-unselecting"),n.unselecting=!1),n.selecting||(n.$element.addClass("ui-selecting"),n.selecting=!0,r._trigger("selecting",t,{selecting:n.element}))):(n.selecting&&((t.metaKey||t.ctrlKey)&&n.startselected?(n.$element.removeClass("ui-selecting"),n.selecting=!1,n.$element.addClass("ui-selected"),n.selected=!0):(n.$element.removeClass("ui-selecting"),n.selecting=!1,n.startselected&&(n.$element.addClass("ui-unselecting"),n.unselecting=!0),r._trigger("unselecting",t,{unselecting:n.element}))),n.selected&&!t.metaKey&&!t.ctrlKey&&!n.startselected&&(n.$element.removeClass("ui-selected"),n.selected=!1,n.$element.addClass("ui-unselecting"),n.unselecting=!0,r._trigger("unselecting",t,{unselecting:n.element})))}),!1},_mouseStop:function(t){var n=this;return this.dragged=!1,e(".ui-unselecting",this.element[0]).each(function(){var r=e.data(this,"selectable-item");r.$element.removeClass("ui-unselecting"),r.unselecting=!1,r.startselected=!1,n._trigger("unselected",t,{unselected:r.element})}),e(".ui-selecting",this.element[0]).each(function(){var r=e.data(this,"selectable-item");r.$element.removeClass("ui-selecting").addClass("ui-selected"),r.selecting=!1,r.selected=!0,r.startselected=!0,n._trigger("selected",t,{selected:r.element})}),this._trigger("stop",t),this.helper.remove(),!1}})})(jQuery);(function(e,t){var n=5;e.widget("ui.slider",e.ui.mouse,{version:"1.10.1",widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null,change:null,slide:null,start:null,stop:null},_create:function(){this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"),this._refresh(),this._setOption("disabled",this.options.disabled),this._animateOff=!1},_refresh:function(){this._createRange(),this._createHandles(),this._setupEvents(),this._refreshValue()},_createHandles:function(){var t,n,r=this.options,i=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),s="<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",o=[];n=r.values&&r.values.length||1,i.length>n&&(i.slice(n).remove(),i=i.slice(0,n));for(t=i.length;t<n;t++)o.push(s);this.handles=i.add(e(o.join("")).appendTo(this.element)),this.handle=this.handles.eq(0),this.handles.each(function(t){e(this).data("ui-slider-handle-index",t)})},_createRange:function(){var t=this.options,n="";t.range?(t.range===!0&&(t.values?t.values.length&&t.values.length!==2?t.values=[t.values[0],t.values[0]]:e.isArray(t.values)&&(t.values=t.values.slice(0)):t.values=[this._valueMin(),this._valueMin()]),!this.range||!this.range.length?(this.range=e("<div></div>").appendTo(this.element),n="ui-slider-range ui-widget-header ui-corner-all"):this.range.removeClass("ui-slider-range-min ui-slider-range-max").css({left:"",bottom:""}),this.range.addClass(n+(t.range==="min"||t.range==="max"?" ui-slider-range-"+t.range:""))):this.range=e([])},_setupEvents:function(){var e=this.handles.add(this.range).filter("a");this._off(e),this._on(e,this._handleEvents),this._hoverable(e),this._focusable(e)},_destroy:function(){this.handles.remove(),this.range.remove(),this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-widget ui-widget-content ui-corner-all"),this._mouseDestroy()},_mouseCapture:function(t){var n,r,i,s,o,u,a,f,l=this,c=this.options;return c.disabled?!1:(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),n={x:t.pageX,y:t.pageY},r=this._normValueFromMouse(n),i=this._valueMax()-this._valueMin()+1,this.handles.each(function(t){var n=Math.abs(r-l.values(t));if(i>n||i===n&&(t===l._lastChangedValue||l.values(t)===c.min))i=n,s=e(this),o=t}),u=this._start(t,o),u===!1?!1:(this._mouseSliding=!0,this._handleIndex=o,s.addClass("ui-state-active").focus(),a=s.offset(),f=!e(t.target).parents().addBack().is(".ui-slider-handle"),this._clickOffset=f?{left:0,top:0}:{left:t.pageX-a.left-s.width()/2,top:t.pageY-a.top-s.height()/2-(parseInt(s.css("borderTopWidth"),10)||0)-(parseInt(s.css("borderBottomWidth"),10)||0)+(parseInt(s.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(t,o,r),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(e){var t={x:e.pageX,y:e.pageY},n=this._normValueFromMouse(t);return this._slide(e,this._handleIndex,n),!1},_mouseStop:function(e){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(e,this._handleIndex),this._change(e,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(e){var t,n,r,i,s;return this.orientation==="horizontal"?(t=this.elementSize.width,n=e.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(t=this.elementSize.height,n=e.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),r=n/t,r>1&&(r=1),r<0&&(r=0),this.orientation==="vertical"&&(r=1-r),i=this._valueMax()-this._valueMin(),s=this._valueMin()+r*i,this._trimAlignValue(s)},_start:function(e,t){var n={handle:this.handles[t],value:this.value()};return this.options.values&&this.options.values.length&&(n.value=this.values(t),n.values=this.values()),this._trigger("start",e,n)},_slide:function(e,t,n){var r,i,s;this.options.values&&this.options.values.length?(r=this.values(t?0:1),this.options.values.length===2&&this.options.range===!0&&(t===0&&n>r||t===1&&n<r)&&(n=r),n!==this.values(t)&&(i=this.values(),i[t]=n,s=this._trigger("slide",e,{handle:this.handles[t],value:n,values:i}),r=this.values(t?0:1),s!==!1&&this.values(t,n,!0))):n!==this.value()&&(s=this._trigger("slide",e,{handle:this.handles[t],value:n}),s!==!1&&this.value(n))},_stop:function(e,t){var n={handle:this.handles[t],value:this.value()};this.options.values&&this.options.values.length&&(n.value=this.values(t),n.values=this.values()),this._trigger("stop",e,n)},_change:function(e,t){if(!this._keySliding&&!this._mouseSliding){var n={handle:this.handles[t],value:this.value()};this.options.values&&this.options.values.length&&(n.value=this.values(t),n.values=this.values()),this._lastChangedValue=t,this._trigger("change",e,n)}},value:function(e){if(arguments.length){this.options.value=this._trimAlignValue(e),this._refreshValue(),this._change(null,0);return}return this._value()},values:function(t,n){var r,i,s;if(arguments.length>1){this.options.values[t]=this._trimAlignValue(n),this._refreshValue(),this._change(null,t);return}if(!arguments.length)return this._values();if(!e.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(t):this.value();r=this.options.values,i=arguments[0];for(s=0;s<r.length;s+=1)r[s]=this._trimAlignValue(i[s]),this._change(null,s);this._refreshValue()},_setOption:function(t,n){var r,i=0;t==="range"&&this.options.range===!0&&(n==="min"?(this.options.value=this._values(0),this.options.values=null):n==="max"&&(this.options.value=this._values(this.options.values.length-1),this.options.values=null)),e.isArray(this.options.values)&&(i=this.options.values.length),e.Widget.prototype._setOption.apply(this,arguments);switch(t){case"orientation":this._detectOrientation(),this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation),this._refreshValue();break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":this._animateOff=!0,this._refreshValue();for(r=0;r<i;r+=1)this._change(null,r);this._animateOff=!1;break;case"min":case"max":this._animateOff=!0,this._refreshValue(),this._animateOff=!1;break;case"range":this._animateOff=!0,this._refresh(),this._animateOff=!1}},_value:function(){var e=this.options.value;return e=this._trimAlignValue(e),e},_values:function(e){var t,n,r;if(arguments.length)return t=this.options.values[e],t=this._trimAlignValue(t),t;if(this.options.values&&this.options.values.length){n=this.options.values.slice();for(r=0;r<n.length;r+=1)n[r]=this._trimAlignValue(n[r]);return n}return[]},_trimAlignValue:function(e){if(e<=this._valueMin())return this._valueMin();if(e>=this._valueMax())return this._valueMax();var t=this.options.step>0?this.options.step:1,n=(e-this._valueMin())%t,r=e-n;return Math.abs(n)*2>=t&&(r+=n>0?t:-t),parseFloat(r.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var t,n,r,i,s,o=this.options.range,u=this.options,a=this,f=this._animateOff?!1:u.animate,l={};this.options.values&&this.options.values.length?this.handles.each(function(r){n=(a.values(r)-a._valueMin())/(a._valueMax()-a._valueMin())*100,l[a.orientation==="horizontal"?"left":"bottom"]=n+"%",e(this).stop(1,1)[f?"animate":"css"](l,u.animate),a.options.range===!0&&(a.orientation==="horizontal"?(r===0&&a.range.stop(1,1)[f?"animate":"css"]({left:n+"%"},u.animate),r===1&&a.range[f?"animate":"css"]({width:n-t+"%"},{queue:!1,duration:u.animate})):(r===0&&a.range.stop(1,1)[f?"animate":"css"]({bottom:n+"%"},u.animate),r===1&&a.range[f?"animate":"css"]({height:n-t+"%"},{queue:!1,duration:u.animate}))),t=n}):(r=this.value(),i=this._valueMin(),s=this._valueMax(),n=s!==i?(r-i)/(s-i)*100:0,l[this.orientation==="horizontal"?"left":"bottom"]=n+"%",this.handle.stop(1,1)[f?"animate":"css"](l,u.animate),o==="min"&&this.orientation==="horizontal"&&this.range.stop(1,1)[f?"animate":"css"]({width:n+"%"},u.animate),o==="max"&&this.orientation==="horizontal"&&this.range[f?"animate":"css"]({width:100-n+"%"},{queue:!1,duration:u.animate}),o==="min"&&this.orientation==="vertical"&&this.range.stop(1,1)[f?"animate":"css"]({height:n+"%"},u.animate),o==="max"&&this.orientation==="vertical"&&this.range[f?"animate":"css"]({height:100-n+"%"},{queue:!1,duration:u.animate}))},_handleEvents:{keydown:function(t){var r,i,s,o,u=e(t.target).data("ui-slider-handle-index");switch(t.keyCode){case e.ui.keyCode.HOME:case e.ui.keyCode.END:case e.ui.keyCode.PAGE_UP:case e.ui.keyCode.PAGE_DOWN:case e.ui.keyCode.UP:case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:case e.ui.keyCode.LEFT:t.preventDefault();if(!this._keySliding){this._keySliding=!0,e(t.target).addClass("ui-state-active"),r=this._start(t,u);if(r===!1)return}}o=this.options.step,this.options.values&&this.options.values.length?i=s=this.values(u):i=s=this.value();switch(t.keyCode){case e.ui.keyCode.HOME:s=this._valueMin();break;case e.ui.keyCode.END:s=this._valueMax();break;case e.ui.keyCode.PAGE_UP:s=this._trimAlignValue(i+(this._valueMax()-this._valueMin())/n);break;case e.ui.keyCode.PAGE_DOWN:s=this._trimAlignValue(i-(this._valueMax()-this._valueMin())/n);break;case e.ui.keyCode.UP:case e.ui.keyCode.RIGHT:if(i===this._valueMax())return;s=this._trimAlignValue(i+o);break;case e.ui.keyCode.DOWN:case e.ui.keyCode.LEFT:if(i===this._valueMin())return;s=this._trimAlignValue(i-o)}this._slide(t,u,s)},click:function(e){e.preventDefault()},keyup:function(t){var n=e(t.target).data("ui-slider-handle-index");this._keySliding&&(this._keySliding=!1,this._stop(t,n),this._change(t,n),e(t.target).removeClass("ui-state-active"))}}})})(jQuery);(function(e,t){function n(e,t,n){return e>t&&e<t+n}e.widget("ui.sortable",e.ui.mouse,{version:"1.10.1",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_create:function(){var e=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?e.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var e=this.items.length-1;e>=0;e--)this.items[e].item.removeData(this.widgetName+"-item");return this},_setOption:function(t,n){t==="disabled"?(this.options[t]=n,this.widget().toggleClass("ui-sortable-disabled",!!n)):e.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(t,n){var r=null,i=!1,s=this;if(this.reverting)return!1;if(this.options.disabled||this.options.type==="static")return!1;this._refreshItems(t),e(t.target).parents().each(function(){if(e.data(this,s.widgetName+"-item")===s)return r=e(this),!1}),e.data(t.target,s.widgetName+"-item")===s&&(r=e(t.target));if(!r)return!1;if(this.options.handle&&!n){e(this.options.handle,r).find("*").addBack().each(function(){this===t.target&&(i=!0)});if(!i)return!1}return this.currentItem=r,this._removeCurrentsFromItems(),!0},_mouseStart:function(t,n,r){var i,s=this.options;this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(t),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,s.cursorAt&&this._adjustOffsetFromHelper(s.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),s.containment&&this._setContainment(),s.cursor&&(e("body").css("cursor")&&(this._storedCursor=e("body").css("cursor")),e("body").css("cursor",s.cursor)),s.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",s.opacity)),s.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",s.zIndex)),this.scrollParent[0]!==document&&this.scrollParent[0].tagName!=="HTML"&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",t,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions();if(!r)for(i=this.containers.length-1;i>=0;i--)this.containers[i]._trigger("activate",t,this._uiHash(this));return e.ui.ddmanager&&(e.ui.ddmanager.current=this),e.ui.ddmanager&&!s.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(t),!0},_mouseDrag:function(t){var n,r,i,s,o=this.options,u=!1;this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==document&&this.scrollParent[0].tagName!=="HTML"?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-t.pageY<o.scrollSensitivity?this.scrollParent[0].scrollTop=u=this.scrollParent[0].scrollTop+o.scrollSpeed:t.pageY-this.overflowOffset.top<o.scrollSensitivity&&(this.scrollParent[0].scrollTop=u=this.scrollParent[0].scrollTop-o.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-t.pageX<o.scrollSensitivity?this.scrollParent[0].scrollLeft=u=this.scrollParent[0].scrollLeft+o.scrollSpeed:t.pageX-this.overflowOffset.left<o.scrollSensitivity&&(this.scrollParent[0].scrollLeft=u=this.scrollParent[0].scrollLeft-o.scrollSpeed)):(t.pageY-e(document).scrollTop()<o.scrollSensitivity?u=e(document).scrollTop(e(document).scrollTop()-o.scrollSpeed):e(window).height()-(t.pageY-e(document).scrollTop())<o.scrollSensitivity&&(u=e(document).scrollTop(e(document).scrollTop()+o.scrollSpeed)),t.pageX-e(document).scrollLeft()<o.scrollSensitivity?u=e(document).scrollLeft(e(document).scrollLeft()-o.scrollSpeed):e(window).width()-(t.pageX-e(document).scrollLeft())<o.scrollSensitivity&&(u=e(document).scrollLeft(e(document).scrollLeft()+o.scrollSpeed))),u!==!1&&e.ui.ddmanager&&!o.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t)),this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!=="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!=="x")this.helper[0].style.top=this.position.top+"px";for(n=this.items.length-1;n>=0;n--){r=this.items[n],i=r.item[0],s=this._intersectsWithPointer(r);if(!s)continue;if(r.instance!==this.currentContainer)continue;if(i!==this.currentItem[0]&&this.placeholder[s===1?"next":"prev"]()[0]!==i&&!e.contains(this.placeholder[0],i)&&(this.options.type==="semi-dynamic"?!e.contains(this.element[0],i):!0)){this.direction=s===1?"down":"up";if(this.options.tolerance!=="pointer"&&!this._intersectsWithSides(r))break;this._rearrange(t,r),this._trigger("change",t,this._uiHash());break}}return this._contactContainers(t),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),this._trigger("sort",t,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(t,n){if(!t)return;e.ui.ddmanager&&!this.options.dropBehaviour&&e.ui.ddmanager.drop(this,t);if(this.options.revert){var r=this,i=this.placeholder.offset();this.reverting=!0,e(this.helper).animate({left:i.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollLeft),top:i.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){r._clear(t)})}else this._clear(t,n);return!1},cancel:function(){if(this.dragging){this._mouseUp({target:null}),this.options.helper==="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var t=this.containers.length-1;t>=0;t--)this.containers[t]._trigger("deactivate",null,this._uiHash(this)),this.containers[t].containerCache.over&&(this.containers[t]._trigger("out",null,this._uiHash(this)),this.containers[t].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.options.helper!=="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),e.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?e(this.domPosition.prev).after(this.currentItem):e(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(t){var n=this._getItemsAsjQuery(t&&t.connected),r=[];return t=t||{},e(n).each(function(){var n=(e(t.item||this).attr(t.attribute||"id")||"").match(t.expression||/(.+)[\-=_](.+)/);n&&r.push((t.key||n[1]+"[]")+"="+(t.key&&t.expression?n[1]:n[2]))}),!r.length&&t.key&&r.push(t.key+"="),r.join("&")},toArray:function(t){var n=this._getItemsAsjQuery(t&&t.connected),r=[];return t=t||{},n.each(function(){r.push(e(t.item||this).attr(t.attribute||"id")||"")}),r},_intersectsWith:function(e){var t=this.positionAbs.left,n=t+this.helperProportions.width,r=this.positionAbs.top,i=r+this.helperProportions.height,s=e.left,o=s+e.width,u=e.top,a=u+e.height,f=this.offset.click.top,l=this.offset.click.left,c=r+f>u&&r+f<a&&t+l>s&&t+l<o;return this.options.tolerance==="pointer"||this.options.forcePointerForContainers||this.options.tolerance!=="pointer"&&this.helperProportions[this.floating?"width":"height"]>e[this.floating?"width":"height"]?c:s<t+this.helperProportions.width/2&&n-this.helperProportions.width/2<o&&u<r+this.helperProportions.height/2&&i-this.helperProportions.height/2<a},_intersectsWithPointer:function(e){var t=this.options.axis==="x"||n(this.positionAbs.top+this.offset.click.top,e.top,e.height),r=this.options.axis==="y"||n(this.positionAbs.left+this.offset.click.left,e.left,e.width),i=t&&r,s=this._getDragVerticalDirection(),o=this._getDragHorizontalDirection();return i?this.floating?o&&o==="right"||s==="down"?2:1:s&&(s==="down"?2:1):!1},_intersectsWithSides:function(e){var t=n(this.positionAbs.top+this.offset.click.top,e.top+e.height/2,e.height),r=n(this.positionAbs.left+this.offset.click.left,e.left+e.width/2,e.width),i=this._getDragVerticalDirection(),s=this._getDragHorizontalDirection();return this.floating&&s?s==="right"&&r||s==="left"&&!r:i&&(i==="down"&&t||i==="up"&&!t)},_getDragVerticalDirection:function(){var e=this.positionAbs.top-this.lastPositionAbs.top;return e!==0&&(e>0?"down":"up")},_getDragHorizontalDirection:function(){var e=this.positionAbs.left-this.lastPositionAbs.left;return e!==0&&(e>0?"right":"left")},refresh:function(e){return this._refreshItems(e),this.refreshPositions(),this},_connectWith:function(){var e=this.options;return e.connectWith.constructor===String?[e.connectWith]:e.connectWith},_getItemsAsjQuery:function(t){var n,r,i,s,o=[],u=[],a=this._connectWith();if(a&&t)for(n=a.length-1;n>=0;n--){i=e(a[n]);for(r=i.length-1;r>=0;r--)s=e.data(i[r],this.widgetFullName),s&&s!==this&&!s.options.disabled&&u.push([e.isFunction(s.options.items)?s.options.items.call(s.element):e(s.options.items,s.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),s])}u.push([e.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):e(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(n=u.length-1;n>=0;n--)u[n][0].each(function(){o.push(this)});return e(o)},_removeCurrentsFromItems:function(){var t=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=e.grep(this.items,function(e){for(var n=0;n<t.length;n++)if(t[n]===e.item[0])return!1;return!0})},_refreshItems:function(t){this.items=[],this.containers=[this];var n,r,i,s,o,u,a,f,l=this.items,c=[[e.isFunction(this.options.items)?this.options.items.call(this.element[0],t,{item:this.currentItem}):e(this.options.items,this.element),this]],h=this._connectWith();if(h&&this.ready)for(n=h.length-1;n>=0;n--){i=e(h[n]);for(r=i.length-1;r>=0;r--)s=e.data(i[r],this.widgetFullName),s&&s!==this&&!s.options.disabled&&(c.push([e.isFunction(s.options.items)?s.options.items.call(s.element[0],t,{item:this.currentItem}):e(s.options.items,s.element),s]),this.containers.push(s))}for(n=c.length-1;n>=0;n--){o=c[n][1],u=c[n][0];for(r=0,f=u.length;r<f;r++)a=e(u[r]),a.data(this.widgetName+"-item",o),l.push({item:a,instance:o,width:0,height:0,left:0,top:0})}},refreshPositions:function(t){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var n,r,i,s;for(n=this.items.length-1;n>=0;n--){r=this.items[n];if(r.instance!==this.currentContainer&&this.currentContainer&&r.item[0]!==this.currentItem[0])continue;i=this.options.toleranceElement?e(this.options.toleranceElement,r.item):r.item,t||(r.width=i.outerWidth(),r.height=i.outerHeight()),s=i.offset(),r.left=s.left,r.top=s.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(n=this.containers.length-1;n>=0;n--)s=this.containers[n].element.offset(),this.containers[n].containerCache.left=s.left,this.containers[n].containerCache.top=s.top,this.containers[n].containerCache.width=this.containers[n].element.outerWidth(),this.containers[n].containerCache.height=this.containers[n].element.outerHeight();return this},_createPlaceholder:function(t){t=t||this;var n,r=t.options;if(!r.placeholder||r.placeholder.constructor===String)n=r.placeholder,r.placeholder={element:function(){var r=e(document.createElement(t.currentItem[0].nodeName)).addClass(n||t.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];return n||(r.style.visibility="hidden"),r},update:function(e,i){if(n&&!r.forcePlaceholderSize)return;i.height()||i.height(t.currentItem.innerHeight()-parseInt(t.currentItem.css("paddingTop")||0,10)-parseInt(t.currentItem.css("paddingBottom")||0,10)),i.width()||i.width(t.currentItem.innerWidth()-parseInt(t.currentItem.css("paddingLeft")||0,10)-parseInt(t.currentItem.css("paddingRight")||0,10))}};t.placeholder=e(r.placeholder.element.call(t.element,t.currentItem)),t.currentItem.after(t.placeholder),r.placeholder.update(t,t.placeholder)},_contactContainers:function(t){var n,r,i,s,o,u,a,f,l,c=null,h=null;for(n=this.containers.length-1;n>=0;n--){if(e.contains(this.currentItem[0],this.containers[n].element[0]))continue;if(this._intersectsWith(this.containers[n].containerCache)){if(c&&e.contains(this.containers[n].element[0],c.element[0]))continue;c=this.containers[n],h=n}else this.containers[n].containerCache.over&&(this.containers[n]._trigger("out",t,this._uiHash(this)),this.containers[n].containerCache.over=0)}if(!c)return;if(this.containers.length===1)this.containers[h]._trigger("over",t,this._uiHash(this)),this.containers[h].containerCache.over=1;else{i=1e4,s=null,o=this.containers[h].floating?"left":"top",u=this.containers[h].floating?"width":"height",a=this.positionAbs[o]+this.offset.click[o];for(r=this.items.length-1;r>=0;r--){if(!e.contains(this.containers[h].element[0],this.items[r].item[0]))continue;if(this.items[r].item[0]===this.currentItem[0])continue;f=this.items[r].item.offset()[o],l=!1,Math.abs(f-a)>Math.abs(f+this.items[r][u]-a)&&(l=!0,f+=this.items[r][u]),Math.abs(f-a)<i&&(i=Math.abs(f-a),s=this.items[r],this.direction=l?"up":"down")}if(!s&&!this.options.dropOnEmpty)return;this.currentContainer=this.containers[h],s?this._rearrange(t,s,null,!0):this._rearrange(t,null,this.containers[h].element,!0),this._trigger("change",t,this._uiHash()),this.containers[h]._trigger("change",t,this._uiHash(this)),this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[h]._trigger("over",t,this._uiHash(this)),this.containers[h].containerCache.over=1}},_createHelper:function(t){var n=this.options,r=e.isFunction(n.helper)?e(n.helper.apply(this.element[0],[t,this.currentItem])):n.helper==="clone"?this.currentItem.clone():this.currentItem;return r.parents("body").length||e(n.appendTo!=="parent"?n.appendTo:this.currentItem[0].parentNode)[0].appendChild(r[0]),r[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(!r[0].style.width||n.forceHelperSize)&&r.width(this.currentItem.width()),(!r[0].style.height||n.forceHelperSize)&&r.height(this.currentItem.height()),r},_adjustOffsetFromHelper:function(t){typeof t=="string"&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();this.cssPosition==="absolute"&&this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()==="html"&&e.ui.ie)t={top:0,left:0};return{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition==="relative"){var e=this.currentItem.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,n,r,i=this.options;i.containment==="parent"&&(i.containment=this.helper[0].parentNode);if(i.containment==="document"||i.containment==="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,e(i.containment==="document"?document:window).width()-this.helperProportions.width-this.margins.left,(e(i.containment==="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];/^(document|window|parent)$/.test(i.containment)||(t=e(i.containment)[0],n=e(i.containment).offset(),r=e(t).css("overflow")!=="hidden",this.containment=[n.left+(parseInt(e(t).css("borderLeftWidth"),10)||0)+(parseInt(e(t).css("paddingLeft"),10)||0)-this.margins.left,n.top+(parseInt(e(t).css("borderTopWidth"),10)||0)+(parseInt(e(t).css("paddingTop"),10)||0)-this.margins.top,n.left+(r?Math.max(t.scrollWidth,t.offsetWidth):t.offsetWidth)-(parseInt(e(t).css("borderLeftWidth"),10)||0)-(parseInt(e(t).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,n.top+(r?Math.max(t.scrollHeight,t.offsetHeight):t.offsetHeight)-(parseInt(e(t).css("borderTopWidth"),10)||0)-(parseInt(e(t).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(t,n){n||(n=this.position);var r=t==="absolute"?1:-1,i=this.cssPosition!=="absolute"||this.scrollParent[0]!==document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,s=/(html|body)/i.test(i[0].tagName);return{top:n.top+this.offset.relative.top*r+this.offset.parent.top*r-(this.cssPosition==="fixed"?-this.scrollParent.scrollTop():s?0:i.scrollTop())*r,left:n.left+this.offset.relative.left*r+this.offset.parent.left*r-(this.cssPosition==="fixed"?-this.scrollParent.scrollLeft():s?0:i.scrollLeft())*r}},_generatePosition:function(t){var n,r,i=this.options,s=t.pageX,o=t.pageY,u=this.cssPosition!=="absolute"||this.scrollParent[0]!==document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,a=/(html|body)/i.test(u[0].tagName);return this.cssPosition==="relative"&&(this.scrollParent[0]===document||this.scrollParent[0]===this.offsetParent[0])&&(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(t.pageX-this.offset.click.left<this.containment[0]&&(s=this.containment[0]+this.offset.click.left),t.pageY-this.offset.click.top<this.containment[1]&&(o=this.containment[1]+this.offset.click.top),t.pageX-this.offset.click.left>this.containment[2]&&(s=this.containment[2]+this.offset.click.left),t.pageY-this.offset.click.top>this.containment[3]&&(o=this.containment[3]+this.offset.click.top)),i.grid&&(n=this.originalPageY+Math.round((o-this.originalPageY)/i.grid[1])*i.grid[1],o=this.containment?n-this.offset.click.top>=this.containment[1]&&n-this.offset.click.top<=this.containment[3]?n:n-this.offset.click.top>=this.containment[1]?n-i.grid[1]:n+i.grid[1]:n,r=this.originalPageX+Math.round((s-this.originalPageX)/i.grid[0])*i.grid[0],s=this.containment?r-this.offset.click.left>=this.containment[0]&&r-this.offset.click.left<=this.containment[2]?r:r-this.offset.click.left>=this.containment[0]?r-i.grid[0]:r+i.grid[0]:r)),{top:o-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(this.cssPosition==="fixed"?-this.scrollParent.scrollTop():a?0:u.scrollTop()),left:s-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(this.cssPosition==="fixed"?-this.scrollParent.scrollLeft():a?0:u.scrollLeft())}},_rearrange:function(e,t,n,r){n?n[0].appendChild(this.placeholder[0]):t.item[0].parentNode.insertBefore(this.placeholder[0],this.direction==="down"?t.item[0]:t.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var i=this.counter;this._delay(function(){i===this.counter&&this.refreshPositions(!r)})},_clear:function(t,n){this.reverting=!1;var r,i=[];!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null;if(this.helper[0]===this.currentItem[0]){for(r in this._storedCSS)if(this._storedCSS[r]==="auto"||this._storedCSS[r]==="static")this._storedCSS[r]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!n&&i.push(function(e){this._trigger("receive",e,this._uiHash(this.fromOutside))}),(this.fromOutside||this.domPosition.prev!==this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!==this.currentItem.parent()[0])&&!n&&i.push(function(e){this._trigger("update",e,this._uiHash())}),this!==this.currentContainer&&(n||(i.push(function(e){this._trigger("remove",e,this._uiHash())}),i.push(function(e){return function(t){e._trigger("receive",t,this._uiHash(this))}}.call(this,this.currentContainer)),i.push(function(e){return function(t){e._trigger("update",t,this._uiHash(this))}}.call(this,this.currentContainer))));for(r=this.containers.length-1;r>=0;r--)n||i.push(function(e){return function(t){e._trigger("deactivate",t,this._uiHash(this))}}.call(this,this.containers[r])),this.containers[r].containerCache.over&&(i.push(function(e){return function(t){e._trigger("out",t,this._uiHash(this))}}.call(this,this.containers[r])),this.containers[r].containerCache.over=0);this._storedCursor&&e("body").css("cursor",this._storedCursor),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex",this._storedZIndex==="auto"?"":this._storedZIndex),this.dragging=!1;if(this.cancelHelperRemoval){if(!n){this._trigger("beforeStop",t,this._uiHash());for(r=0;r<i.length;r++)i[r].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!1}n||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null;if(!n){for(r=0;r<i.length;r++)i[r].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!0},_trigger:function(){e.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(t){var n=t||this;return{helper:n.helper,placeholder:n.placeholder||e([]),position:n.position,originalPosition:n.originalPosition,offset:n.positionAbs,item:n.currentItem,sender:t?t.element:null}}})})(jQuery);(function(e){function t(e){return function(){var t=this.element.val();e.apply(this,arguments),this._refresh(),t!==this.element.val()&&this._trigger("change")}}e.widget("ui.spinner",{version:"1.10.1",defaultElement:"<input>",widgetEventPrefix:"spin",options:{culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var t={},n=this.element;return e.each(["min","max","step"],function(e,r){var i=n.attr(r);i!==undefined&&i.length&&(t[r]=i)}),t},_events:{keydown:function(e){this._start(e)&&this._keydown(e)&&e.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(e){if(this.cancelBlur){delete this.cancelBlur;return}this._refresh(),this.previous!==this.element.val()&&this._trigger("change",e)},mousewheel:function(e,t){if(!t)return;if(!this.spinning&&!this._start(e))return!1;this._spin((t>0?1:-1)*this.options.step,e),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(e)},100),e.preventDefault()},"mousedown .ui-spinner-button":function(t){function r(){var e=this.element[0]===this.document[0].activeElement;e||(this.element.focus(),this.previous=n,this._delay(function(){this.previous=n}))}var n;n=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),t.preventDefault(),r.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,r.call(this)});if(this._start(t)===!1)return;this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(t){if(!e(t.currentTarget).hasClass("ui-state-active"))return;if(this._start(t)===!1)return!1;this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseleave .ui-spinner-button":"_stop"},_draw:function(){var e=this.uiSpinner=this.element.addClass("ui-spinner-input").attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this.element.attr("role","spinbutton"),this.buttons=e.find(".ui-spinner-button").attr("tabIndex",-1).button().removeClass("ui-corner-all"),this.buttons.height()>Math.ceil(e.height()*.5)&&e.height()>0&&e.height(e.height()),this.options.disabled&&this.disable()},_keydown:function(t){var n=this.options,r=e.ui.keyCode;switch(t.keyCode){case r.UP:return this._repeat(null,1,t),!0;case r.DOWN:return this._repeat(null,-1,t),!0;case r.PAGE_UP:return this._repeat(null,n.page,t),!0;case r.PAGE_DOWN:return this._repeat(null,-n.page,t),!0}return!1},_uiSpinnerHtml:function(){return"<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"},_buttonHtml:function(){return"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'><span class='ui-icon "+this.options.icons.up+"'>▲</span>"+"</a>"+"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>"+"<span class='ui-icon "+this.options.icons.down+"'>▼</span>"+"</a>"},_start:function(e){return!this.spinning&&this._trigger("start",e)===!1?!1:(this.counter||(this.counter=1),this.spinning=!0,!0)},_repeat:function(e,t,n){e=e||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,t,n)},e),this._spin(t*this.options.step,n)},_spin:function(e,t){var n=this.value()||0;this.counter||(this.counter=1),n=this._adjustValue(n+e*this._increment(this.counter));if(!this.spinning||this._trigger("spin",t,{value:n})!==!1)this._value(n),this.counter++},_increment:function(t){var n=this.options.incremental;return n?e.isFunction(n)?n(t):Math.floor(t*t*t/5e4-t*t/500+17*t/200+1):1},_precision:function(){var e=this._precisionOf(this.options.step);return this.options.min!==null&&(e=Math.max(e,this._precisionOf(this.options.min))),e},_precisionOf:function(e){var t=e.toString(),n=t.indexOf(".");return n===-1?0:t.length-n-1},_adjustValue:function(e){var t,n,r=this.options;return t=r.min!==null?r.min:0,n=e-t,n=Math.round(n/r.step)*r.step,e=t+n,e=parseFloat(e.toFixed(this._precision())),r.max!==null&&e>r.max?r.max:r.min!==null&&e<r.min?r.min:e},_stop:function(e){if(!this.spinning)return;clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger("stop",e)},_setOption:function(e,t){if(e==="culture"||e==="numberFormat"){var n=this._parse(this.element.val());this.options[e]=t,this.element.val(this._format(n));return}(e==="max"||e==="min"||e==="step")&&typeof t=="string"&&(t=this._parse(t)),e==="icons"&&(this.buttons.first().find(".ui-icon").removeClass(this.options.icons.up).addClass(t.up),this.buttons.last().find(".ui-icon").removeClass(this.options.icons.down).addClass(t.down)),this._super(e,t),e==="disabled"&&(t?(this.element.prop("disabled",!0),this.buttons.button("disable")):(this.element.prop("disabled",!1),this.buttons.button("enable")))},_setOptions:t(function(e){this._super(e),this._value(this.element.val())}),_parse:function(e){return typeof e=="string"&&e!==""&&(e=window.Globalize&&this.options.numberFormat?Globalize.parseFloat(e,10,this.options.culture):+e),e===""||isNaN(e)?null:e},_format:function(e){return e===""?"":window.Globalize&&this.options.numberFormat?Globalize.format(e,this.options.numberFormat,this.options.culture):e},_refresh:function(){this.element.attr({"aria-valuemin":this.options.min,"aria-valuemax":this.options.max,"aria-valuenow":this._parse(this.element.val())})},_value:function(e,t){var n;e!==""&&(n=this._parse(e),n!==null&&(t||(n=this._adjustValue(n)),e=this._format(n))),this.element.val(e),this._refresh()},_destroy:function(){this.element.removeClass("ui-spinner-input").prop("disabled",!1).removeAttr("autocomplete").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.uiSpinner.replaceWith(this.element)},stepUp:t(function(e){this._stepUp(e)}),_stepUp:function(e){this._start()&&(this._spin((e||1)*this.options.step),this._stop())},stepDown:t(function(e){this._stepDown(e)}),_stepDown:function(e){this._start()&&(this._spin((e||1)*-this.options.step),this._stop())},pageUp:t(function(e){this._stepUp((e||1)*this.options.page)}),pageDown:t(function(e){this._stepDown((e||1)*this.options.page)}),value:function(e){if(!arguments.length)return this._parse(this.element.val());t(this._value).call(this,e)},widget:function(){return this.uiSpinner}})})(jQuery);(function(e,t){function i(){return++n}function s(e){return e.hash.length>1&&decodeURIComponent(e.href.replace(r,""))===decodeURIComponent(location.href.replace(r,""))}var n=0,r=/#.*$/;e.widget("ui.tabs",{version:"1.10.1",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var t=this,n=this.options;this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",n.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(t){e(this).is(".ui-state-disabled")&&t.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){e(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs(),n.active=this._initialActive(),e.isArray(n.disabled)&&(n.disabled=e.unique(n.disabled.concat(e.map(this.tabs.filter(".ui-state-disabled"),function(e){return t.tabs.index(e)}))).sort()),this.options.active!==!1&&this.anchors.length?this.active=this._findActive(n.active):this.active=e(),this._refresh(),this.active.length&&this.load(n.active)},_initialActive:function(){var t=this.options.active,n=this.options.collapsible,r=location.hash.substring(1);if(t===null){r&&this.tabs.each(function(n,i){if(e(i).attr("aria-controls")===r)return t=n,!1}),t===null&&(t=this.tabs.index(this.tabs.filter(".ui-tabs-active")));if(t===null||t===-1)t=this.tabs.length?0:!1}return t!==!1&&(t=this.tabs.index(this.tabs.eq(t)),t===-1&&(t=n?!1:0)),!n&&t===!1&&this.anchors.length&&(t=0),t},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):e()}},_tabKeydown:function(t){var n=e(this.document[0].activeElement).closest("li"),r=this.tabs.index(n),i=!0;if(this._handlePageNav(t))return;switch(t.keyCode){case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:r++;break;case e.ui.keyCode.UP:case e.ui.keyCode.LEFT:i=!1,r--;break;case e.ui.keyCode.END:r=this.anchors.length-1;break;case e.ui.keyCode.HOME:r=0;break;case e.ui.keyCode.SPACE:t.preventDefault(),clearTimeout(this.activating),this._activate(r);return;case e.ui.keyCode.ENTER:t.preventDefault(),clearTimeout(this.activating),this._activate(r===this.options.active?!1:r);return;default:return}t.preventDefault(),clearTimeout(this.activating),r=this._focusNextTab(r,i),t.ctrlKey||(n.attr("aria-selected","false"),this.tabs.eq(r).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",r)},this.delay))},_panelKeydown:function(t){if(this._handlePageNav(t))return;t.ctrlKey&&t.keyCode===e.ui.keyCode.UP&&(t.preventDefault(),this.active.focus())},_handlePageNav:function(t){if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_UP)return this._activate(this._focusNextTab(this.options.active-1,!1)),!0;if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_DOWN)return this._activate(this._focusNextTab(this.options.active+1,!0)),!0},_findNextTab:function(t,n){function i(){return t>r&&(t=0),t<0&&(t=r),t}var r=this.tabs.length-1;while(e.inArray(i(),this.options.disabled)!==-1)t=n?t+1:t-1;return t},_focusNextTab:function(e,t){return e=this._findNextTab(e,t),this.tabs.eq(e).focus(),e},_setOption:function(e,t){if(e==="active"){this._activate(t);return}if(e==="disabled"){this._setupDisabled(t);return}this._super(e,t),e==="collapsible"&&(this.element.toggleClass("ui-tabs-collapsible",t),!t&&this.options.active===!1&&this._activate(0)),e==="event"&&this._setupEvents(t),e==="heightStyle"&&this._setupHeightStyle(t)},_tabId:function(e){return e.attr("aria-controls")||"ui-tabs-"+i()},_sanitizeSelector:function(e){return e?e.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var t=this.options,n=this.tablist.children(":has(a[href])");t.disabled=e.map(n.filter(".ui-state-disabled"),function(e){return n.index(e)}),this._processTabs(),t.active===!1||!this.anchors.length?(t.active=!1,this.active=e()):this.active.length&&!e.contains(this.tablist[0],this.active[0])?this.tabs.length===t.disabled.length?(t.active=!1,this.active=e()):this._activate(this._findNextTab(Math.max(0,t.active-1),!1)):t.active=this.tabs.index(this.active),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded":"false","aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-expanded":"true","aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var t=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return e("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=e(),this.anchors.each(function(n,r){var i,o,u,a=e(r).uniqueId().attr("id"),f=e(r).closest("li"),l=f.attr("aria-controls");s(r)?(i=r.hash,o=t.element.find(t._sanitizeSelector(i))):(u=t._tabId(f),i="#"+u,o=t.element.find(i),o.length||(o=t._createPanel(u),o.insertAfter(t.panels[n-1]||t.tablist)),o.attr("aria-live","polite")),o.length&&(t.panels=t.panels.add(o)),l&&f.data("ui-tabs-aria-controls",l),f.attr({"aria-controls":i.substring(1),"aria-labelledby":a}),o.attr("aria-labelledby",a)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.element.find("ol,ul").eq(0)},_createPanel:function(t){return e("<div>").attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(t){e.isArray(t)&&(t.length?t.length===this.anchors.length&&(t=!0):t=!1);for(var n=0,r;r=this.tabs[n];n++)t===!0||e.inArray(n,t)!==-1?e(r).addClass("ui-state-disabled").attr("aria-disabled","true"):e(r).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=t},_setupEvents:function(t){var n={click:function(e){e.preventDefault()}};t&&e.each(t.split(" "),function(e,t){n[t]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,n),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(t){var n,r=this.element.parent();t==="fill"?(n=r.height(),n-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var t=e(this),r=t.css("position");if(r==="absolute"||r==="fixed")return;n-=t.outerHeight(!0)}),this.element.children().not(this.panels).each(function(){n-=e(this).outerHeight(!0)}),this.panels.each(function(){e(this).height(Math.max(0,n-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):t==="auto"&&(n=0,this.panels.each(function(){n=Math.max(n,e(this).height("").height())}).height(n))},_eventHandler:function(t){var n=this.options,r=this.active,i=e(t.currentTarget),s=i.closest("li"),o=s[0]===r[0],u=o&&n.collapsible,a=u?e():this._getPanelForTab(s),f=r.length?this._getPanelForTab(r):e(),l={oldTab:r,oldPanel:f,newTab:u?e():s,newPanel:a};t.preventDefault();if(s.hasClass("ui-state-disabled")||s.hasClass("ui-tabs-loading")||this.running||o&&!n.collapsible||this._trigger("beforeActivate",t,l)===!1)return;n.active=u?!1:this.tabs.index(s),this.active=o?e():s,this.xhr&&this.xhr.abort(),!f.length&&!a.length&&e.error("jQuery UI Tabs: Mismatching fragment identifier."),a.length&&this.load(this.tabs.index(s),t),this._toggle(t,l)},_toggle:function(t,n){function o(){r.running=!1,r._trigger("activate",t,n)}function u(){n.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),i.length&&r.options.show?r._show(i,r.options.show,o):(i.show(),o())}var r=this,i=n.newPanel,s=n.oldPanel;this.running=!0,s.length&&this.options.hide?this._hide(s,this.options.hide,function(){n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),u()}):(n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),s.hide(),u()),s.attr({"aria-expanded":"false","aria-hidden":"true"}),n.oldTab.attr("aria-selected","false"),i.length&&s.length?n.oldTab.attr("tabIndex",-1):i.length&&this.tabs.filter(function(){return e(this).attr("tabIndex")===0}).attr("tabIndex",-1),i.attr({"aria-expanded":"true","aria-hidden":"false"}),n.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(t){var n,r=this._findActive(t);if(r[0]===this.active[0])return;r.length||(r=this.active),n=r.find(".ui-tabs-anchor")[0],this._eventHandler({target:n,currentTarget:n,preventDefault:e.noop})},_findActive:function(t){return t===!1?e():this.tabs.eq(t)},_getIndex:function(e){return typeof e=="string"&&(e=this.anchors.index(this.anchors.filter("[href$='"+e+"']"))),e},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeUniqueId(),this.tabs.add(this.panels).each(function(){e.data(this,"ui-tabs-destroy")?e(this).remove():e(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var t=e(this),n=t.data("ui-tabs-aria-controls");n?t.attr("aria-controls",n).removeData("ui-tabs-aria-controls"):t.removeAttr("aria-controls")}),this.panels.show(),this.options.heightStyle!=="content"&&this.panels.css("height","")},enable:function(n){var r=this.options.disabled;if(r===!1)return;n===t?r=!1:(n=this._getIndex(n),e.isArray(r)?r=e.map(r,function(e){return e!==n?e:null}):r=e.map(this.tabs,function(e,t){return t!==n?t:null})),this._setupDisabled(r)},disable:function(n){var r=this.options.disabled;if(r===!0)return;if(n===t)r=!0;else{n=this._getIndex(n);if(e.inArray(n,r)!==-1)return;e.isArray(r)?r=e.merge([n],r).sort():r=[n]}this._setupDisabled(r)},load:function(t,n){t=this._getIndex(t);var r=this,i=this.tabs.eq(t),o=i.find(".ui-tabs-anchor"),u=this._getPanelForTab(i),a={tab:i,panel:u};if(s(o[0]))return;this.xhr=e.ajax(this._ajaxSettings(o,n,a)),this.xhr&&this.xhr.statusText!=="canceled"&&(i.addClass("ui-tabs-loading"),u.attr("aria-busy","true"),this.xhr.success(function(e){setTimeout(function(){u.html(e),r._trigger("load",n,a)},1)}).complete(function(e,t){setTimeout(function(){t==="abort"&&r.panels.stop(!1,!0),i.removeClass("ui-tabs-loading"),u.removeAttr("aria-busy"),e===r.xhr&&delete r.xhr},1)}))},_ajaxSettings:function(t,n,r){var i=this;return{url:t.attr("href"),beforeSend:function(t,s){return i._trigger("beforeLoad",n,e.extend({jqXHR:t,ajaxSettings:s},r))}}},_getPanelForTab:function(t){var n=e(t).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+n))}})})(jQuery);(function(e){function n(t,n){var r=(t.attr("aria-describedby")||"").split(/\s+/);r.push(n),t.data("ui-tooltip-id",n).attr("aria-describedby",e.trim(r.join(" ")))}function r(t){var n=t.data("ui-tooltip-id"),r=(t.attr("aria-describedby")||"").split(/\s+/),i=e.inArray(n,r);i!==-1&&r.splice(i,1),t.removeData("ui-tooltip-id"),r=e.trim(r.join(" ")),r?t.attr("aria-describedby",r):t.removeAttr("aria-describedby")}var t=0;e.widget("ui.tooltip",{version:"1.10.1",options:{content:function(){var t=e(this).attr("title")||"";return e("<a>").text(t).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable()},_setOption:function(t,n){var r=this;if(t==="disabled"){this[n?"_disable":"_enable"](),this.options[t]=n;return}this._super(t,n),t==="content"&&e.each(this.tooltips,function(e,t){r._updateContent(t)})},_disable:function(){var t=this;e.each(this.tooltips,function(n,r){var i=e.Event("blur");i.target=i.currentTarget=r[0],t.close(i,!0)}),this.element.find(this.options.items).addBack().each(function(){var t=e(this);t.is("[title]")&&t.data("ui-tooltip-title",t.attr("title")).attr("title","")})},_enable:function(){this.element.find(this.options.items).addBack().each(function(){var t=e(this);t.data("ui-tooltip-title")&&t.attr("title",t.data("ui-tooltip-title"))})},open:function(t){var n=this,r=e(t?t.target:this.element).closest(this.options.items);if(!r.length||r.data("ui-tooltip-id"))return;r.attr("title")&&r.data("ui-tooltip-title",r.attr("title")),r.data("ui-tooltip-open",!0),t&&t.type==="mouseover"&&r.parents().each(function(){var t=e(this),r;t.data("ui-tooltip-open")&&(r=e.Event("blur"),r.target=r.currentTarget=this,n.close(r,!0)),t.attr("title")&&(t.uniqueId(),n.parents[this.id]={element:this,title:t.attr("title")},t.attr("title",""))}),this._updateContent(r,t)},_updateContent:function(e,t){var n,r=this.options.content,i=this,s=t?t.type:null;if(typeof r=="string")return this._open(t,e,r);n=r.call(e[0],function(n){if(!e.data("ui-tooltip-open"))return;i._delay(function(){t&&(t.type=s),this._open(t,e,n)})}),n&&this._open(t,e,n)},_open:function(t,r,i){function f(e){a.of=e;if(s.is(":hidden"))return;s.position(a)}var s,o,u,a=e.extend({},this.options.position);if(!i)return;s=this._find(r);if(s.length){s.find(".ui-tooltip-content").html(i);return}r.is("[title]")&&(t&&t.type==="mouseover"?r.attr("title",""):r.removeAttr("title")),s=this._tooltip(r),n(r,s.attr("id")),s.find(".ui-tooltip-content").html(i),this.options.track&&t&&/^mouse/.test(t.type)?(this._on(this.document,{mousemove:f}),f(t)):s.position(e.extend({of:r},this.options.position)),s.hide(),this._show(s,this.options.show),this.options.show&&this.options.show.delay&&(u=this.delayedShow=setInterval(function(){s.is(":visible")&&(f(a.of),clearInterval(u))},e.fx.interval)),this._trigger("open",t,{tooltip:s}),o={keyup:function(t){if(t.keyCode===e.ui.keyCode.ESCAPE){var n=e.Event(t);n.currentTarget=r[0],this.close(n,!0)}},remove:function(){this._removeTooltip(s)}};if(!t||t.type==="mouseover")o.mouseleave="close";if(!t||t.type==="focusin")o.focusout="close";this._on(!0,r,o)},close:function(t){var n=this,i=e(t?t.currentTarget:this.element),s=this._find(i);if(this.closing)return;clearInterval(this.delayedShow),i.data("ui-tooltip-title")&&i.attr("title",i.data("ui-tooltip-title")),r(i),s.stop(!0),this._hide(s,this.options.hide,function(){n._removeTooltip(e(this))}),i.removeData("ui-tooltip-open"),this._off(i,"mouseleave focusout keyup"),i[0]!==this.element[0]&&this._off(i,"remove"),this._off(this.document,"mousemove"),t&&t.type==="mouseleave"&&e.each(this.parents,function(t,r){e(r.element).attr("title",r.title),delete n.parents[t]}),this.closing=!0,this._trigger("close",t,{tooltip:s}),this.closing=!1},_tooltip:function(n){var r="ui-tooltip-"+t++,i=e("<div>").attr({id:r,role:"tooltip"}).addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||""));return e("<div>").addClass("ui-tooltip-content").appendTo(i),i.appendTo(this.document[0].body),this.tooltips[r]=n,i},_find:function(t){var n=t.data("ui-tooltip-id");return n?e("#"+n):e()},_removeTooltip:function(e){e.remove(),delete this.tooltips[e.attr("id")]},_destroy:function(){var t=this;e.each(this.tooltips,function(n,r){var i=e.Event("blur");i.target=i.currentTarget=r[0],t.close(i,!0),e("#"+n).remove(),r.data("ui-tooltip-title")&&(r.attr("title",r.data("ui-tooltip-title")),r.removeData("ui-tooltip-title"))})}})})(jQuery); /* Dutch (UTF-8) initialisation for the jQuery UI date picker plugin. */ /* Written by Mathias Bynens <http://mathiasbynens.be/> */ jQuery(function($){ $.datepicker.regional['nl'] = { closeText: 'Sluiten', prevText: '←', nextText: '→', currentText: 'Vandaag', monthNames: ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december'], monthNamesShort: ['jan', 'feb', 'maa', 'apr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'], dayNames: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'], dayNamesShort: ['zon', 'maa', 'din', 'woe', 'don', 'vri', 'zat'], dayNamesMin: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'], weekHeader: 'Wk', dateFormat: 'dd-mm-yy', firstDay: 1, isRTL: false, showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['nl']); }); /* HTML5 Sortable (http://farhadi.ir/projects/html5sortable) * Released under the MIT license. */ (function(a){var b,c=a();a.fn.sortable=function(d){var e=String(d);return d=a.extend({connectWith:!1},d),this.each(function(){if(/^enable|disable|destroy$/.test(e)){var f=a(this).children(a(this).data("items")).attr("draggable",e=="enable");e=="destroy"&&f.add(this).removeData("connectWith items").off("dragstart.h5s dragend.h5s selectstart.h5s dragover.h5s dragenter.h5s drop.h5s");return}var g,h,f=a(this).children(d.items),i=a("<"+(/^ul|ol$/i.test(this.tagName)?"li":"div")+' class="sortable-placeholder">');f.find(d.handle).mousedown(function(){g=!0}).mouseup(function(){g=!1}),a(this).data("items",d.items),c=c.add(i),d.connectWith&&a(d.connectWith).add(this).data("connectWith",d.connectWith),f.attr("draggable","true").on("dragstart.h5s",function(c){if(d.handle&&!g)return!1;g=!1;var e=c.originalEvent.dataTransfer;e.effectAllowed="move",e.setData("Text","dummy"),h=(b=a(this)).addClass("sortable-dragging").index()}).on("dragend.h5s",function(){b.removeClass("sortable-dragging").show(),c.detach(),h!=b.index()&&f.parent().trigger("sortupdate",{item:b}),b=null}).not("a[href], img").on("selectstart.h5s",function(){return this.dragDrop&&this.dragDrop(),!1}).end().add([this,i]).on("dragover.h5s dragenter.h5s drop.h5s",function(e){return!f.is(b)&&d.connectWith!==a(b).parent().data("connectWith")?!0:e.type=="drop"?(e.stopPropagation(),c.filter(":visible").after(b),!1):(e.preventDefault(),e.originalEvent.dataTransfer.dropEffect="move",f.is(this)?(d.forcePlaceholderSize&&i.height(b.outerHeight()),b.hide(),a(this)[i.index()<a(this).index()?"after":"before"](i),c.not(i).detach()):!c.is(this)&&!a(this).children(d.items).length&&(c.detach(),a(this).append(i)),!1)})})}})(jQuery); /*! * Nestable jQuery Plugin - Copyright (c) 2012 David Bushell - http://dbushell.com/ * Dual-licensed under the BSD or MIT licenses */ ;(function($, window, document, undefined) { var hasTouch = 'ontouchstart' in window; /** * Detect CSS pointer-events property * events are normally disabled on the dragging element to avoid conflicts * https://github.com/ausi/Feature-detection-technique-for-pointer-events/blob/master/modernizr-pointerevents.js */ var hasPointerEvents = (function() { var el = document.createElement('div'), docEl = document.documentElement; if (!('pointerEvents' in el.style)) { return false; } el.style.pointerEvents = 'auto'; el.style.pointerEvents = 'x'; docEl.appendChild(el); var supports = window.getComputedStyle && window.getComputedStyle(el, '').pointerEvents === 'auto'; docEl.removeChild(el); return !!supports; })(); var eStart = hasTouch ? 'touchstart' : 'mousedown', eMove = hasTouch ? 'touchmove' : 'mousemove', eEnd = hasTouch ? 'touchend' : 'mouseup'; eCancel = hasTouch ? 'touchcancel' : 'mouseup'; var defaults = { listNodeName : 'ol', itemNodeName : 'li', rootClass : 'dd', listClass : 'dd-list', itemClass : 'dd-item', dragClass : 'dd-dragel', handleClass : 'dd-handle', collapsedClass : 'dd-collapsed', placeClass : 'dd-placeholder', noDragClass : 'dd-nodrag', emptyClass : 'dd-empty', expandBtnHTML : '<button data-action="expand" type="button">Expand</button>', collapseBtnHTML : '<button data-action="collapse" type="button">Collapse</button>', group : 0, maxDepth : 5, threshold : 20 }; function Plugin(element, options) { this.w = $(window); this.el = $(element); this.options = $.extend({}, defaults, options); this.init(); } Plugin.prototype = { init: function() { var list = this; list.reset(); list.el.data('nestable-group', this.options.group); list.placeEl = $('<div class="' + list.options.placeClass + '"/>'); $.each(this.el.find(list.options.itemNodeName), function(k, el) { list.setParent($(el)); }); list.el.on('click', 'button', function(e) { if (list.dragEl || (!hasTouch && e.button !== 0)) { return; } var target = $(e.currentTarget), action = target.data('action'), item = target.parent(list.options.itemNodeName); if (action === 'collapse') { list.collapseItem(item); } if (action === 'expand') { list.expandItem(item); } }); var onStartEvent = function(e) { var handle = $(e.target); if (!handle.hasClass(list.options.handleClass)) { if (handle.closest('.' + list.options.noDragClass).length) { return; } handle = handle.closest('.' + list.options.handleClass); } if (!handle.length || list.dragEl || (!hasTouch && e.button !== 0) || (hasTouch && e.touches.length !== 1)) { return; } e.preventDefault(); list.dragStart(hasTouch ? e.touches[0] : e); }; var onMoveEvent = function(e) { if (list.dragEl) { e.preventDefault(); list.dragMove(hasTouch ? e.touches[0] : e); } }; var onEndEvent = function(e) { if (list.dragEl) { e.preventDefault(); list.dragStop(hasTouch ? e.touches[0] : e); } }; if (hasTouch) { list.el[0].addEventListener(eStart, onStartEvent, false); window.addEventListener(eMove, onMoveEvent, false); window.addEventListener(eEnd, onEndEvent, false); window.addEventListener(eCancel, onEndEvent, false); } else { list.el.on(eStart, onStartEvent); list.w.on(eMove, onMoveEvent); list.w.on(eEnd, onEndEvent); } }, serialize: function() { var data, depth = 0, list = this; step = function(level, depth) { var array = [ ], items = level.children(list.options.itemNodeName); items.each(function() { var li = $(this), item = $.extend({}, li.data()), sub = li.children(list.options.listNodeName); if (sub.length) { item.children = step(sub, depth + 1); } array.push(item); }); return array; }; data = step(list.el.find(list.options.listNodeName).first(), depth); return data; }, serialise: function() { return this.serialize(); }, reset: function() { this.mouse = { offsetX : 0, offsetY : 0, startX : 0, startY : 0, lastX : 0, lastY : 0, nowX : 0, nowY : 0, distX : 0, distY : 0, dirAx : 0, dirX : 0, dirY : 0, lastDirX : 0, lastDirY : 0, distAxX : 0, distAxY : 0 }; this.moving = false; this.dragEl = null; this.dragRootEl = null; this.dragDepth = 0; this.hasNewRoot = false; this.pointEl = null; }, expandItem: function(li) { li.removeClass(this.options.collapsedClass); li.children('[data-action="expand"]').hide(); li.children('[data-action="collapse"]').show(); li.children(this.options.listNodeName).show(); }, collapseItem: function(li) { var lists = li.children(this.options.listNodeName); if (lists.length) { li.addClass(this.options.collapsedClass); li.children('[data-action="collapse"]').hide(); li.children('[data-action="expand"]').show(); li.children(this.options.listNodeName).hide(); } }, expandAll: function() { var list = this; list.el.find(list.options.itemNodeName).each(function() { list.expandItem($(this)); }); }, collapseAll: function() { var list = this; list.el.find(list.options.itemNodeName).each(function() { list.collapseItem($(this)); }); }, setParent: function(li) { if (li.children(this.options.listNodeName).length) { li.prepend($(this.options.expandBtnHTML)); li.prepend($(this.options.collapseBtnHTML)); } li.children('[data-action="expand"]').hide(); }, unsetParent: function(li) { li.removeClass(this.options.collapsedClass); li.children('[data-action]').remove(); li.children(this.options.listNodeName).remove(); }, dragStart: function(e) { var mouse = this.mouse, target = $(e.target), dragItem = target.closest(this.options.itemNodeName); this.placeEl.css('height', dragItem.height()); mouse.offsetX = e.offsetX !== undefined ? e.offsetX : e.pageX - target.offset().left; mouse.offsetY = e.offsetY !== undefined ? e.offsetY : e.pageY - target.offset().top; mouse.startX = mouse.lastX = e.pageX; mouse.startY = mouse.lastY = e.pageY; this.dragRootEl = this.el; this.dragEl = $(document.createElement(this.options.listNodeName)).addClass(this.options.listClass + ' ' + this.options.dragClass); this.dragEl.css('width', dragItem.width()); // fix for zepto.js //dragItem.after(this.placeEl).detach().appendTo(this.dragEl); dragItem.after(this.placeEl); dragItem[0].parentNode.removeChild(dragItem[0]); dragItem.appendTo(this.dragEl); $(document.body).append(this.dragEl); this.dragEl.css({ 'left' : e.pageX - mouse.offsetX, 'top' : e.pageY - mouse.offsetY }); // total depth of dragging item var i, depth, items = this.dragEl.find(this.options.itemNodeName); for (i = 0; i < items.length; i++) { depth = $(items[i]).parents(this.options.listNodeName).length; if (depth > this.dragDepth) { this.dragDepth = depth; } } }, dragStop: function(e) { // fix for zepto.js //this.placeEl.replaceWith(this.dragEl.children(this.options.itemNodeName + ':first').detach()); var el = this.dragEl.children(this.options.itemNodeName).first(); el[0].parentNode.removeChild(el[0]); this.placeEl.replaceWith(el); this.dragEl.remove(); this.el.trigger('change'); if (this.hasNewRoot) { this.dragRootEl.trigger('change'); } this.reset(); }, dragMove: function(e) { var list, parent, prev, next, depth, opt = this.options, mouse = this.mouse; this.dragEl.css({ 'left' : e.pageX - mouse.offsetX, 'top' : e.pageY - mouse.offsetY }); // mouse position last events mouse.lastX = mouse.nowX; mouse.lastY = mouse.nowY; // mouse position this events mouse.nowX = e.pageX; mouse.nowY = e.pageY; // distance mouse moved between events mouse.distX = mouse.nowX - mouse.lastX; mouse.distY = mouse.nowY - mouse.lastY; // direction mouse was moving mouse.lastDirX = mouse.dirX; mouse.lastDirY = mouse.dirY; // direction mouse is now moving (on both axis) mouse.dirX = mouse.distX === 0 ? 0 : mouse.distX > 0 ? 1 : -1; mouse.dirY = mouse.distY === 0 ? 0 : mouse.distY > 0 ? 1 : -1; // axis mouse is now moving on var newAx = Math.abs(mouse.distX) > Math.abs(mouse.distY) ? 1 : 0; // do nothing on first move if (!mouse.moving) { mouse.dirAx = newAx; mouse.moving = true; return; } // calc distance moved on this axis (and direction) if (mouse.dirAx !== newAx) { mouse.distAxX = 0; mouse.distAxY = 0; } else { mouse.distAxX += Math.abs(mouse.distX); if (mouse.dirX !== 0 && mouse.dirX !== mouse.lastDirX) { mouse.distAxX = 0; } mouse.distAxY += Math.abs(mouse.distY); if (mouse.dirY !== 0 && mouse.dirY !== mouse.lastDirY) { mouse.distAxY = 0; } } mouse.dirAx = newAx; /** * move horizontal */ if (mouse.dirAx && mouse.distAxX >= opt.threshold) { // reset move distance on x-axis for new phase mouse.distAxX = 0; prev = this.placeEl.prev(opt.itemNodeName); // increase horizontal level if previous sibling exists and is not collapsed if (mouse.distX > 0 && prev.length && !prev.hasClass(opt.collapsedClass)) { // cannot increase level when item above is collapsed list = prev.find(opt.listNodeName).last(); // check if depth limit has reached depth = this.placeEl.parents(opt.listNodeName).length; if (depth + this.dragDepth <= opt.maxDepth) { // create new sub-level if one doesn't exist if (!list.length) { list = $('<' + opt.listNodeName + '/>').addClass(opt.listClass); list.append(this.placeEl); prev.append(list); this.setParent(prev); } else { // else append to next level up list = prev.children(opt.listNodeName).last(); list.append(this.placeEl); } } } // decrease horizontal level if (mouse.distX < 0) { // we can't decrease a level if an item preceeds the current one next = this.placeEl.next(opt.itemNodeName); if (!next.length) { parent = this.placeEl.parent(); this.placeEl.closest(opt.itemNodeName).after(this.placeEl); if (!parent.children().length) { this.unsetParent(parent.parent()); } } } } var isEmpty = false; // find list item under cursor if (!hasPointerEvents) { this.dragEl[0].style.visibility = 'hidden'; } this.pointEl = $(document.elementFromPoint(e.pageX - document.body.scrollLeft, e.pageY - (window.pageYOffset || document.documentElement.scrollTop))); if (!hasPointerEvents) { this.dragEl[0].style.visibility = 'visible'; } if (this.pointEl.hasClass(opt.handleClass)) { this.pointEl = this.pointEl.parent(opt.itemNodeName); } if (this.pointEl.hasClass(opt.emptyClass)) { isEmpty = true; } else if (!this.pointEl.length || !this.pointEl.hasClass(opt.itemClass)) { return; } // find parent list of item under cursor var pointElRoot = this.pointEl.closest('.' + opt.rootClass), isNewRoot = this.dragRootEl.data('nestable-id') !== pointElRoot.data('nestable-id'); /** * move vertical */ if (!mouse.dirAx || isNewRoot || isEmpty) { // check if groups match if dragging over new root if (isNewRoot && opt.group !== pointElRoot.data('nestable-group')) { return; } // check depth limit depth = this.dragDepth - 1 + this.pointEl.parents(opt.listNodeName).length; if (depth > opt.maxDepth) { return; } var before = e.pageY < (this.pointEl.offset().top + this.pointEl.height() / 2); parent = this.placeEl.parent(); // if empty create new list to replace empty placeholder if (isEmpty) { list = $(document.createElement(opt.listNodeName)).addClass(opt.listClass); list.append(this.placeEl); this.pointEl.replaceWith(list); } else if (before) { this.pointEl.before(this.placeEl); } else { this.pointEl.after(this.placeEl); } if (!parent.children().length) { this.unsetParent(parent.parent()); } if (!this.dragRootEl.find(opt.itemNodeName).length) { this.dragRootEl.append('<div class="' + opt.emptyClass + '"/>'); } // parent root list has changed if (isNewRoot) { this.dragRootEl = pointElRoot; this.hasNewRoot = this.el[0] !== this.dragRootEl[0]; } } } }; $.fn.nestable = function(params) { var lists = this, retval = this; lists.each(function() { var plugin = $(this).data("nestable"); if (!plugin) { $(this).data("nestable", new Plugin(this, params)); $(this).data("nestable-id", new Date().getTime()); } else { if (typeof params === 'string' && typeof plugin[params] === 'function') { retval = plugin[params](); } } }); return retval || lists; }; })(window.jQuery || window.Zepto, window, document); /** * -------------------------------------------------------------------- * jQuery customfileinput plugin * Author: Scott Jehl, scott@filamentgroup.com * Copyright (c) 2009 Filament Group * licensed under MIT (filamentgroup.com/examples/mit-license.txt) * -------------------------------------------------------------------- */ $.fn.customFileInput = function(){ //apply events and styles for file input element var fileInput = $(this) .addClass('customfile-input') //add class for CSS .mouseover(function(){ upload.addClass('customfile-hover'); }) .mouseout(function(){ upload.removeClass('customfile-hover'); }) .focus(function(){ upload.addClass('customfile-focus'); fileInput.data('val', fileInput.val()); }) .blur(function(){ upload.removeClass('customfile-focus'); $(this).trigger('checkChange'); }) .bind('disable',function(){ fileInput.attr('disabled',true); upload.addClass('customfile-disabled'); }) .bind('enable',function(){ fileInput.removeAttr('disabled'); upload.removeClass('customfile-disabled'); }) .bind('checkChange', function(){ if(fileInput.val() && fileInput.val() != fileInput.data('val')){ fileInput.trigger('change'); } }) .bind('change',function(){ //get file name var fileName = $(this).val().split(/\\/).pop(); //get file extension var fileExt = 'customfile-ext-' + fileName.split('.').pop().toLowerCase(); //update the feedback uploadFeedback .text(fileName) //set feedback text to filename .removeClass(uploadFeedback.data('fileExt') || '') //remove any existing file extension class .addClass(fileExt) //add file extension class .data('fileExt', fileExt) //store file extension for class removal on next change .addClass('customfile-feedback-populated'); //add class to show populated state //change text of button uploadButton.text('Kies een bestand'); }) .click(function(){ //for IE and Opera, make sure change fires after choosing a file, using an async callback fileInput.data('val', fileInput.val()); setTimeout(function(){ fileInput.trigger('checkChange'); },100); }); //create custom control container var upload = $('<div class="customfile"></div>'); //create custom control button var uploadButton = $('<span class="customfile-button" aria-hidden="true">voeg foto toe</span>').appendTo(upload); //create custom control feedback var uploadFeedback = $('<span class="customfile-feedback" aria-hidden="true">Geen bestand geselecteerd...</span>').appendTo(upload); //match disabled state if(fileInput.is('[disabled]')){ fileInput.trigger('disable'); } //on mousemove, keep file input under the cursor to steal click upload .mousemove(function(e){ fileInput.css({ 'left': e.pageX - upload.offset().left - fileInput.outerWidth() + 20, //position right side 20px right of cursor X) 'top': e.pageY - upload.offset().top - $(window).scrollTop() - 3 }); }) .insertAfter(fileInput); //insert after the input fileInput.appendTo(upload); //return jQuery return $(this); }; /** * Farbtastic Color Picker 1.2 * © 2008 Steven Wittens * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ jQuery.fn.farbtastic = function (callback) { $.farbtastic(this, callback); return this; }; jQuery.farbtastic = function (container, callback) { var container = $(container).get(0); return container.farbtastic || (container.farbtastic = new jQuery._farbtastic(container, callback)); } jQuery._farbtastic = function (container, callback) { // Store farbtastic object var fb = this; // Insert markup $(container).html('<div class="farbtastic"><div class="color"></div><div class="wheel"></div><div class="overlay"></div><div class="h-marker marker"></div><div class="sl-marker marker"></div></div>'); var e = $('.farbtastic', container); fb.wheel = $('.wheel', container).get(0); // Dimensions fb.radius = 84; fb.square = 100; fb.width = 194; // Fix background PNGs in IE6 if (navigator.appVersion.match(/MSIE [0-6]\./)) { $('*', e).each(function () { if (this.currentStyle.backgroundImage != 'none') { var image = this.currentStyle.backgroundImage; image = this.currentStyle.backgroundImage.substring(5, image.length - 2); $(this).css({ 'backgroundImage': 'none', 'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')" }); } }); } /** * Link to the given element(s) or callback. */ fb.linkTo = function (callback) { // Unbind previous nodes if (typeof fb.callback == 'object') { $(fb.callback).unbind('keyup', fb.updateValue); } // Reset color fb.color = null; // Bind callback or elements if (typeof callback == 'function') { fb.callback = callback; } else if (typeof callback == 'object' || typeof callback == 'string') { fb.callback = $(callback); fb.callback.bind('keyup', fb.updateValue); if (fb.callback.get(0).value) { fb.setColor(fb.callback.get(0).value); } } return this; } fb.updateValue = function (event) { if (this.value && this.value != fb.color) { fb.setColor(this.value); } } /** * Change color with HTML syntax #123456 */ fb.setColor = function (color) { var unpack = fb.unpack(color); if (fb.color != color && unpack) { fb.color = color; fb.rgb = unpack; fb.hsl = fb.RGBToHSL(fb.rgb); fb.updateDisplay(); } return this; } /** * Change color with HSL triplet [0..1, 0..1, 0..1] */ fb.setHSL = function (hsl) { fb.hsl = hsl; fb.rgb = fb.HSLToRGB(hsl); fb.color = fb.pack(fb.rgb); fb.updateDisplay(); return this; } ///////////////////////////////////////////////////// /** * Retrieve the coordinates of the given event relative to the center * of the widget. */ fb.widgetCoords = function (event) { var x, y; var el = event.target || event.srcElement; var reference = fb.wheel; if (typeof event.offsetX != 'undefined') { // Use offset coordinates and find common offsetParent var pos = { x: event.offsetX, y: event.offsetY }; // Send the coordinates upwards through the offsetParent chain. var e = el; while (e) { e.mouseX = pos.x; e.mouseY = pos.y; pos.x += e.offsetLeft; pos.y += e.offsetTop; e = e.offsetParent; } // Look for the coordinates starting from the wheel widget. var e = reference; var offset = { x: 0, y: 0 } while (e) { if (typeof e.mouseX != 'undefined') { x = e.mouseX - offset.x; y = e.mouseY - offset.y; break; } offset.x += e.offsetLeft; offset.y += e.offsetTop; e = e.offsetParent; } // Reset stored coordinates e = el; while (e) { e.mouseX = undefined; e.mouseY = undefined; e = e.offsetParent; } } else { // Use absolute coordinates var pos = fb.absolutePosition(reference); x = (event.pageX || 0*(event.clientX + $('html').get(0).scrollLeft)) - pos.x; y = (event.pageY || 0*(event.clientY + $('html').get(0).scrollTop)) - pos.y; } // Subtract distance to middle return { x: x - fb.width / 2, y: y - fb.width / 2 }; } /** * Mousedown handler */ fb.mousedown = function (event) { // Capture mouse if (!document.dragging) { $(document).bind('mousemove', fb.mousemove).bind('mouseup', fb.mouseup); document.dragging = true; } // Check which area is being dragged var pos = fb.widgetCoords(event); fb.circleDrag = Math.max(Math.abs(pos.x), Math.abs(pos.y)) * 2 > fb.square; // Process fb.mousemove(event); return false; } /** * Mousemove handler */ fb.mousemove = function (event) { // Get coordinates relative to color picker center var pos = fb.widgetCoords(event); // Set new HSL parameters if (fb.circleDrag) { var hue = Math.atan2(pos.x, -pos.y) / 6.28; if (hue < 0) hue += 1; fb.setHSL([hue, fb.hsl[1], fb.hsl[2]]); } else { var sat = Math.max(0, Math.min(1, -(pos.x / fb.square) + .5)); var lum = Math.max(0, Math.min(1, -(pos.y / fb.square) + .5)); fb.setHSL([fb.hsl[0], sat, lum]); } return false; } /** * Mouseup handler */ fb.mouseup = function () { // Uncapture mouse $(document).unbind('mousemove', fb.mousemove); $(document).unbind('mouseup', fb.mouseup); document.dragging = false; } /** * Update the markers and styles */ fb.updateDisplay = function () { // Markers var angle = fb.hsl[0] * 6.28; $('.h-marker', e).css({ left: Math.round(Math.sin(angle) * fb.radius + fb.width / 2) + 'px', top: Math.round(-Math.cos(angle) * fb.radius + fb.width / 2) + 'px' }); $('.sl-marker', e).css({ left: Math.round(fb.square * (.5 - fb.hsl[1]) + fb.width / 2) + 'px', top: Math.round(fb.square * (.5 - fb.hsl[2]) + fb.width / 2) + 'px' }); // Saturation/Luminance gradient $('.color', e).css('backgroundColor', fb.pack(fb.HSLToRGB([fb.hsl[0], 1, 0.5]))); // Linked elements or callback if (typeof fb.callback == 'object') { // Set background/foreground color $(fb.callback).css({ backgroundColor: fb.color, color: fb.hsl[2] > 0.5 ? '#000' : '#fff' }); // Change linked value $(fb.callback).each(function() { if (this.value && this.value != fb.color) { this.value = fb.color; } }); } else if (typeof fb.callback == 'function') { fb.callback.call(fb, fb.color); } } /** * Get absolute position of element */ fb.absolutePosition = function (el) { var r = { x: el.offsetLeft, y: el.offsetTop }; // Resolve relative to offsetParent if (el.offsetParent) { var tmp = fb.absolutePosition(el.offsetParent); r.x += tmp.x; r.y += tmp.y; } return r; }; /* Various color utility functions */ fb.pack = function (rgb) { var r = Math.round(rgb[0] * 255); var g = Math.round(rgb[1] * 255); var b = Math.round(rgb[2] * 255); return '#' + (r < 16 ? '0' : '') + r.toString(16) + (g < 16 ? '0' : '') + g.toString(16) + (b < 16 ? '0' : '') + b.toString(16); } fb.unpack = function (color) { if (color.length == 7) { return [parseInt('0x' + color.substring(1, 3)) / 255, parseInt('0x' + color.substring(3, 5)) / 255, parseInt('0x' + color.substring(5, 7)) / 255]; } else if (color.length == 4) { return [parseInt('0x' + color.substring(1, 2)) / 15, parseInt('0x' + color.substring(2, 3)) / 15, parseInt('0x' + color.substring(3, 4)) / 15]; } } fb.HSLToRGB = function (hsl) { var m1, m2, r, g, b; var h = hsl[0], s = hsl[1], l = hsl[2]; m2 = (l <= 0.5) ? l * (s + 1) : l + s - l*s; m1 = l * 2 - m2; return [this.hueToRGB(m1, m2, h+0.33333), this.hueToRGB(m1, m2, h), this.hueToRGB(m1, m2, h-0.33333)]; } fb.hueToRGB = function (m1, m2, h) { h = (h < 0) ? h + 1 : ((h > 1) ? h - 1 : h); if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; if (h * 2 < 1) return m2; if (h * 3 < 2) return m1 + (m2 - m1) * (0.66666 - h) * 6; return m1; } fb.RGBToHSL = function (rgb) { var min, max, delta, h, s, l; var r = rgb[0], g = rgb[1], b = rgb[2]; min = Math.min(r, Math.min(g, b)); max = Math.max(r, Math.max(g, b)); delta = max - min; l = (min + max) / 2; s = 0; if (l > 0 && l < 1) { s = delta / (l < 0.5 ? (2 * l) : (2 - 2 * l)); } h = 0; if (delta > 0) { if (max == r && max != g) h += (g - b) / delta; if (max == g && max != b) h += (2 + (b - r) / delta); if (max == b && max != r) h += (4 + (r - g) / delta); h /= 6; } return [h, s, l]; } // Install mousedown handler (the others are set on the document on-demand) $('*', e).mousedown(fb.mousedown); // Init color fb.setColor('#000000'); // Set linked elements/callback if (callback) { fb.linkTo(callback); } } ; /*! jQuery UI - v1.11.1+CommonJS - 2014-09-17 * http://jqueryui.com * Includes: widget.js * Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */ (function( factory ) { if ( typeof define === "function" && define.amd ) { // AMD. Register as an anonymous module. define([ "jquery" ], factory ); } else if (typeof exports === "object") { // Node/CommonJS: factory(require("jquery")); } else { // Browser globals factory( jQuery ); } }(function( $ ) { /*! * jQuery UI Widget 1.11.1 * http://jqueryui.com * * Copyright 2014 jQuery Foundation and other contributors * Released under the MIT license. * http://jquery.org/license * * http://api.jqueryui.com/jQuery.widget/ */ var widget_uuid = 0, widget_slice = Array.prototype.slice; $.cleanData = (function( orig ) { return function( elems ) { var events, elem, i; for ( i = 0; (elem = elems[i]) != null; i++ ) { try { // Only trigger remove when necessary to save time events = $._data( elem, "events" ); if ( events && events.remove ) { $( elem ).triggerHandler( "remove" ); } // http://bugs.jquery.com/ticket/8235 } catch( e ) {} } orig( elems ); }; })( $.cleanData ); $.widget = function( name, base, prototype ) { var fullName, existingConstructor, constructor, basePrototype, // proxiedPrototype allows the provided prototype to remain unmodified // so that it can be used as a mixin for multiple widgets (#8876) proxiedPrototype = {}, namespace = name.split( "." )[ 0 ]; name = name.split( "." )[ 1 ]; fullName = namespace + "-" + name; if ( !prototype ) { prototype = base; base = $.Widget; } // create selector for plugin $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { return !!$.data( elem, fullName ); }; $[ namespace ] = $[ namespace ] || {}; existingConstructor = $[ namespace ][ name ]; constructor = $[ namespace ][ name ] = function( options, element ) { // allow instantiation without "new" keyword if ( !this._createWidget ) { return new constructor( options, element ); } // allow instantiation without initializing for simple inheritance // must use "new" keyword (the code above always passes args) if ( arguments.length ) { this._createWidget( options, element ); } }; // extend with the existing constructor to carry over any static properties $.extend( constructor, existingConstructor, { version: prototype.version, // copy the object used to create the prototype in case we need to // redefine the widget later _proto: $.extend( {}, prototype ), // track widgets that inherit from this widget in case this widget is // redefined after a widget inherits from it _childConstructors: [] }); basePrototype = new base(); // we need to make the options hash a property directly on the new instance // otherwise we'll modify the options hash on the prototype that we're // inheriting from basePrototype.options = $.widget.extend( {}, basePrototype.options ); $.each( prototype, function( prop, value ) { if ( !$.isFunction( value ) ) { proxiedPrototype[ prop ] = value; return; } proxiedPrototype[ prop ] = (function() { var _super = function() { return base.prototype[ prop ].apply( this, arguments ); }, _superApply = function( args ) { return base.prototype[ prop ].apply( this, args ); }; return function() { var __super = this._super, __superApply = this._superApply, returnValue; this._super = _super; this._superApply = _superApply; returnValue = value.apply( this, arguments ); this._super = __super; this._superApply = __superApply; return returnValue; }; })(); }); constructor.prototype = $.widget.extend( basePrototype, { // TODO: remove support for widgetEventPrefix // always use the name + a colon as the prefix, e.g., draggable:start // don't prefix for widgets that aren't DOM-based widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name }, proxiedPrototype, { constructor: constructor, namespace: namespace, widgetName: name, widgetFullName: fullName }); // If this widget is being redefined then we need to find all widgets that // are inheriting from it and redefine all of them so that they inherit from // the new version of this widget. We're essentially trying to replace one // level in the prototype chain. if ( existingConstructor ) { $.each( existingConstructor._childConstructors, function( i, child ) { var childPrototype = child.prototype; // redefine the child widget using the same prototype that was // originally used, but inherit from the new version of the base $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); }); // remove the list of existing child constructors from the old constructor // so the old child constructors can be garbage collected delete existingConstructor._childConstructors; } else { base._childConstructors.push( constructor ); } $.widget.bridge( name, constructor ); return constructor; }; $.widget.extend = function( target ) { var input = widget_slice.call( arguments, 1 ), inputIndex = 0, inputLength = input.length, key, value; for ( ; inputIndex < inputLength; inputIndex++ ) { for ( key in input[ inputIndex ] ) { value = input[ inputIndex ][ key ]; if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { // Clone objects if ( $.isPlainObject( value ) ) { target[ key ] = $.isPlainObject( target[ key ] ) ? $.widget.extend( {}, target[ key ], value ) : // Don't extend strings, arrays, etc. with objects $.widget.extend( {}, value ); // Copy everything else by reference } else { target[ key ] = value; } } } } return target; }; $.widget.bridge = function( name, object ) { var fullName = object.prototype.widgetFullName || name; $.fn[ name ] = function( options ) { var isMethodCall = typeof options === "string", args = widget_slice.call( arguments, 1 ), returnValue = this; // allow multiple hashes to be passed on init options = !isMethodCall && args.length ? $.widget.extend.apply( null, [ options ].concat(args) ) : options; if ( isMethodCall ) { this.each(function() { var methodValue, instance = $.data( this, fullName ); if ( options === "instance" ) { returnValue = instance; return false; } if ( !instance ) { return $.error( "cannot call methods on " + name + " prior to initialization; " + "attempted to call method '" + options + "'" ); } if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) { return $.error( "no such method '" + options + "' for " + name + " widget instance" ); } methodValue = instance[ options ].apply( instance, args ); if ( methodValue !== instance && methodValue !== undefined ) { returnValue = methodValue && methodValue.jquery ? returnValue.pushStack( methodValue.get() ) : methodValue; return false; } }); } else { this.each(function() { var instance = $.data( this, fullName ); if ( instance ) { instance.option( options || {} ); if ( instance._init ) { instance._init(); } } else { $.data( this, fullName, new object( options, this ) ); } }); } return returnValue; }; }; $.Widget = function( /* options, element */ ) {}; $.Widget._childConstructors = []; $.Widget.prototype = { widgetName: "widget", widgetEventPrefix: "", defaultElement: "<div>", options: { disabled: false, // callbacks create: null }, _createWidget: function( options, element ) { element = $( element || this.defaultElement || this )[ 0 ]; this.element = $( element ); this.uuid = widget_uuid++; this.eventNamespace = "." + this.widgetName + this.uuid; this.options = $.widget.extend( {}, this.options, this._getCreateOptions(), options ); this.bindings = $(); this.hoverable = $(); this.focusable = $(); if ( element !== this ) { $.data( element, this.widgetFullName, this ); this._on( true, this.element, { remove: function( event ) { if ( event.target === element ) { this.destroy(); } } }); this.document = $( element.style ? // element within the document element.ownerDocument : // element is window or document element.document || element ); this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); } this._create(); this._trigger( "create", null, this._getCreateEventData() ); this._init(); }, _getCreateOptions: $.noop, _getCreateEventData: $.noop, _create: $.noop, _init: $.noop, destroy: function() { this._destroy(); // we can probably remove the unbind calls in 2.0 // all event bindings should go through this._on() this.element .unbind( this.eventNamespace ) .removeData( this.widgetFullName ) // support: jquery <1.6.3 // http://bugs.jquery.com/ticket/9413 .removeData( $.camelCase( this.widgetFullName ) ); this.widget() .unbind( this.eventNamespace ) .removeAttr( "aria-disabled" ) .removeClass( this.widgetFullName + "-disabled " + "ui-state-disabled" ); // clean up events and states this.bindings.unbind( this.eventNamespace ); this.hoverable.removeClass( "ui-state-hover" ); this.focusable.removeClass( "ui-state-focus" ); }, _destroy: $.noop, widget: function() { return this.element; }, option: function( key, value ) { var options = key, parts, curOption, i; if ( arguments.length === 0 ) { // don't return a reference to the internal hash return $.widget.extend( {}, this.options ); } if ( typeof key === "string" ) { // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } options = {}; parts = key.split( "." ); key = parts.shift(); if ( parts.length ) { curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); for ( i = 0; i < parts.length - 1; i++ ) { curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; curOption = curOption[ parts[ i ] ]; } key = parts.pop(); if ( arguments.length === 1 ) { return curOption[ key ] === undefined ? null : curOption[ key ]; } curOption[ key ] = value; } else { if ( arguments.length === 1 ) { return this.options[ key ] === undefined ? null : this.options[ key ]; } options[ key ] = value; } } this._setOptions( options ); return this; }, _setOptions: function( options ) { var key; for ( key in options ) { this._setOption( key, options[ key ] ); } return this; }, _setOption: function( key, value ) { this.options[ key ] = value; if ( key === "disabled" ) { this.widget() .toggleClass( this.widgetFullName + "-disabled", !!value ); // If the widget is becoming disabled, then nothing is interactive if ( value ) { this.hoverable.removeClass( "ui-state-hover" ); this.focusable.removeClass( "ui-state-focus" ); } } return this; }, enable: function() { return this._setOptions({ disabled: false }); }, disable: function() { return this._setOptions({ disabled: true }); }, _on: function( suppressDisabledCheck, element, handlers ) { var delegateElement, instance = this; // no suppressDisabledCheck flag, shuffle arguments if ( typeof suppressDisabledCheck !== "boolean" ) { handlers = element; element = suppressDisabledCheck; suppressDisabledCheck = false; } // no element argument, shuffle and use this.element if ( !handlers ) { handlers = element; element = this.element; delegateElement = this.widget(); } else { element = delegateElement = $( element ); this.bindings = this.bindings.add( element ); } $.each( handlers, function( event, handler ) { function handlerProxy() { // allow widgets to customize the disabled handling // - disabled as an array instead of boolean // - disabled class as method for disabling individual parts if ( !suppressDisabledCheck && ( instance.options.disabled === true || $( this ).hasClass( "ui-state-disabled" ) ) ) { return; } return ( typeof handler === "string" ? instance[ handler ] : handler ) .apply( instance, arguments ); } // copy the guid so direct unbinding works if ( typeof handler !== "string" ) { handlerProxy.guid = handler.guid = handler.guid || handlerProxy.guid || $.guid++; } var match = event.match( /^([\w:-]*)\s*(.*)$/ ), eventName = match[1] + instance.eventNamespace, selector = match[2]; if ( selector ) { delegateElement.delegate( selector, eventName, handlerProxy ); } else { element.bind( eventName, handlerProxy ); } }); }, _off: function( element, eventName ) { eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace; element.unbind( eventName ).undelegate( eventName ); }, _delay: function( handler, delay ) { function handlerProxy() { return ( typeof handler === "string" ? instance[ handler ] : handler ) .apply( instance, arguments ); } var instance = this; return setTimeout( handlerProxy, delay || 0 ); }, _hoverable: function( element ) { this.hoverable = this.hoverable.add( element ); this._on( element, { mouseenter: function( event ) { $( event.currentTarget ).addClass( "ui-state-hover" ); }, mouseleave: function( event ) { $( event.currentTarget ).removeClass( "ui-state-hover" ); } }); }, _focusable: function( element ) { this.focusable = this.focusable.add( element ); this._on( element, { focusin: function( event ) { $( event.currentTarget ).addClass( "ui-state-focus" ); }, focusout: function( event ) { $( event.currentTarget ).removeClass( "ui-state-focus" ); } }); }, _trigger: function( type, event, data ) { var prop, orig, callback = this.options[ type ]; data = data || {}; event = $.Event( event ); event.type = ( type === this.widgetEventPrefix ? type : this.widgetEventPrefix + type ).toLowerCase(); // the original event may come from any element // so we need to reset the target on the new event event.target = this.element[ 0 ]; // copy original event properties over to the new event orig = event.originalEvent; if ( orig ) { for ( prop in orig ) { if ( !( prop in event ) ) { event[ prop ] = orig[ prop ]; } } } this.element.trigger( event, data ); return !( $.isFunction( callback ) && callback.apply( this.element[0], [ event ].concat( data ) ) === false || event.isDefaultPrevented() ); } }; $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { if ( typeof options === "string" ) { options = { effect: options }; } var hasOptions, effectName = !options ? method : options === true || typeof options === "number" ? defaultEffect : options.effect || defaultEffect; options = options || {}; if ( typeof options === "number" ) { options = { duration: options }; } hasOptions = !$.isEmptyObject( options ); options.complete = callback; if ( options.delay ) { element.delay( options.delay ); } if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { element[ method ]( options ); } else if ( effectName !== method && element[ effectName ] ) { element[ effectName ]( options.duration, options.easing, callback ); } else { element.queue(function( next ) { $( this )[ method ](); if ( callback ) { callback.call( element[ 0 ] ); } next(); }); } }; }); var widget = $.widget; })); /* * jQuery Iframe Transport Plugin 1.8.3 * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2011, Sebastian Tschan * https://blueimp.net * * Licensed under the MIT license: * http://www.opensource.org/licenses/MIT */ /* global define, require, window, document */ (function (factory) { 'use strict'; if (typeof define === 'function' && define.amd) { // Register as an anonymous AMD module: define(['jquery'], factory); } else if (typeof exports === 'object') { // Node/CommonJS: factory(require('jquery')); } else { // Browser globals: factory(window.jQuery); } }(function ($) { 'use strict'; // Helper variable to create unique names for the transport iframes: var counter = 0; // The iframe transport accepts four additional options: // options.fileInput: a jQuery collection of file input fields // options.paramName: the parameter name for the file form data, // overrides the name property of the file input field(s), // can be a string or an array of strings. // options.formData: an array of objects with name and value properties, // equivalent to the return data of .serializeArray(), e.g.: // [{name: 'a', value: 1}, {name: 'b', value: 2}] // options.initialIframeSrc: the URL of the initial iframe src, // by default set to "javascript:false;" $.ajaxTransport('iframe', function (options) { if (options.async) { // javascript:false as initial iframe src // prevents warning popups on HTTPS in IE6: /*jshint scripturl: true */ var initialIframeSrc = options.initialIframeSrc || 'javascript:false;', /*jshint scripturl: false */ form, iframe, addParamChar; return { send: function (_, completeCallback) { form = $('<form style="display:none;"></form>'); form.attr('accept-charset', options.formAcceptCharset); addParamChar = /\?/.test(options.url) ? '&' : '?'; // XDomainRequest only supports GET and POST: if (options.type === 'DELETE') { options.url = options.url + addParamChar + '_method=DELETE'; options.type = 'POST'; } else if (options.type === 'PUT') { options.url = options.url + addParamChar + '_method=PUT'; options.type = 'POST'; } else if (options.type === 'PATCH') { options.url = options.url + addParamChar + '_method=PATCH'; options.type = 'POST'; } // IE versions below IE8 cannot set the name property of // elements that have already been added to the DOM, // so we set the name along with the iframe HTML markup: counter += 1; iframe = $( '<iframe src="' + initialIframeSrc + '" name="iframe-transport-' + counter + '"></iframe>' ).bind('load', function () { var fileInputClones, paramNames = $.isArray(options.paramName) ? options.paramName : [options.paramName]; iframe .unbind('load') .bind('load', function () { var response; // Wrap in a try/catch block to catch exceptions thrown // when trying to access cross-domain iframe contents: try { response = iframe.contents(); // Google Chrome and Firefox do not throw an // exception when calling iframe.contents() on // cross-domain requests, so we unify the response: if (!response.length || !response[0].firstChild) { throw new Error(); } } catch (e) { response = undefined; } // The complete callback returns the // iframe content document as response object: completeCallback( 200, 'success', {'iframe': response} ); // Fix for IE endless progress bar activity bug // (happens on form submits to iframe targets): $('<iframe src="' + initialIframeSrc + '"></iframe>') .appendTo(form); window.setTimeout(function () { // Removing the form in a setTimeout call // allows Chrome's developer tools to display // the response result form.remove(); }, 0); }); form .prop('target', iframe.prop('name')) .prop('action', options.url) .prop('method', options.type); if (options.formData) { $.each(options.formData, function (index, field) { $('<input type="hidden"/>') .prop('name', field.name) .val(field.value) .appendTo(form); }); } if (options.fileInput && options.fileInput.length && options.type === 'POST') { fileInputClones = options.fileInput.clone(); // Insert a clone for each file input field: options.fileInput.after(function (index) { return fileInputClones[index]; }); if (options.paramName) { options.fileInput.each(function (index) { $(this).prop( 'name', paramNames[index] || options.paramName ); }); } // Appending the file input fields to the hidden form // removes them from their original location: form .append(options.fileInput) .prop('enctype', 'multipart/form-data') // enctype must be set as encoding for IE: .prop('encoding', 'multipart/form-data'); // Remove the HTML5 form attribute from the input(s): options.fileInput.removeAttr('form'); } form.submit(); // Insert the file input fields at their original location // by replacing the clones with the originals: if (fileInputClones && fileInputClones.length) { options.fileInput.each(function (index, input) { var clone = $(fileInputClones[index]); // Restore the original name and form properties: $(input) .prop('name', clone.prop('name')) .attr('form', clone.attr('form')); clone.replaceWith(input); }); } }); form.append(iframe).appendTo(document.body); }, abort: function () { if (iframe) { // javascript:false as iframe src aborts the request // and prevents warning popups on HTTPS in IE6. // concat is used to avoid the "Script URL" JSLint error: iframe .unbind('load') .prop('src', initialIframeSrc); } if (form) { form.remove(); } } }; } }); // The iframe transport returns the iframe content document as response. // The following adds converters from iframe to text, json, html, xml // and script. // Please note that the Content-Type for JSON responses has to be text/plain // or text/html, if the browser doesn't include application/json in the // Accept header, else IE will show a download dialog. // The Content-Type for XML responses on the other hand has to be always // application/xml or text/xml, so IE properly parses the XML response. // See also // https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#content-type-negotiation $.ajaxSetup({ converters: { 'iframe text': function (iframe) { return iframe && $(iframe[0].body).text(); }, 'iframe json': function (iframe) { return iframe && $.parseJSON($(iframe[0].body).text()); }, 'iframe html': function (iframe) { return iframe && $(iframe[0].body).html(); }, 'iframe xml': function (iframe) { var xmlDoc = iframe && iframe[0]; return xmlDoc && $.isXMLDoc(xmlDoc) ? xmlDoc : $.parseXML((xmlDoc.XMLDocument && xmlDoc.XMLDocument.xml) || $(xmlDoc.body).html()); }, 'iframe script': function (iframe) { return iframe && $.globalEval($(iframe[0].body).text()); } } }); })); /* * jQuery File Upload Plugin 5.42.3 * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2010, Sebastian Tschan * https://blueimp.net * * Licensed under the MIT license: * http://www.opensource.org/licenses/MIT */ /* jshint nomen:false */ /* global define, require, window, document, location, Blob, FormData */ (function (factory) { 'use strict'; if (typeof define === 'function' && define.amd) { // Register as an anonymous AMD module: define([ 'jquery', 'jquery.ui.widget' ], factory); } else if (typeof exports === 'object') { // Node/CommonJS: factory( require('jquery'), require('./vendor/jquery.ui.widget') ); } else { // Browser globals: factory(window.jQuery); } }(function ($) { 'use strict'; // Detect file input support, based on // http://viljamis.com/blog/2012/file-upload-support-on-mobile/ $.support.fileInput = !(new RegExp( // Handle devices which give false positives for the feature detection: '(Android (1\\.[0156]|2\\.[01]))' + '|(Windows Phone (OS 7|8\\.0))|(XBLWP)|(ZuneWP)|(WPDesktop)' + '|(w(eb)?OSBrowser)|(webOS)' + '|(Kindle/(1\\.0|2\\.[05]|3\\.0))' ).test(window.navigator.userAgent) || // Feature detection for all other devices: $('<input type="file">').prop('disabled')); // The FileReader API is not actually used, but works as feature detection, // as some Safari versions (5?) support XHR file uploads via the FormData API, // but not non-multipart XHR file uploads. // window.XMLHttpRequestUpload is not available on IE10, so we check for // window.ProgressEvent instead to detect XHR2 file upload capability: $.support.xhrFileUpload = !!(window.ProgressEvent && window.FileReader); $.support.xhrFormDataFileUpload = !!window.FormData; // Detect support for Blob slicing (required for chunked uploads): $.support.blobSlice = window.Blob && (Blob.prototype.slice || Blob.prototype.webkitSlice || Blob.prototype.mozSlice); // Helper function to create drag handlers for dragover/dragenter/dragleave: function getDragHandler(type) { var isDragOver = type === 'dragover'; return function (e) { e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer; var dataTransfer = e.dataTransfer; if (dataTransfer && $.inArray('Files', dataTransfer.types) !== -1 && this._trigger( type, $.Event(type, {delegatedEvent: e}) ) !== false) { e.preventDefault(); if (isDragOver) { dataTransfer.dropEffect = 'copy'; } } }; } // The fileupload widget listens for change events on file input fields defined // via fileInput setting and paste or drop events of the given dropZone. // In addition to the default jQuery Widget methods, the fileupload widget // exposes the "add" and "send" methods, to add or directly send files using // the fileupload API. // By default, files added via file input selection, paste, drag & drop or // "add" method are uploaded immediately, but it is possible to override // the "add" callback option to queue file uploads. $.widget('blueimp.fileupload', { options: { // The drop target element(s), by the default the complete document. // Set to null to disable drag & drop support: dropZone: $(document), // The paste target element(s), by the default undefined. // Set to a DOM node or jQuery object to enable file pasting: pasteZone: undefined, // The file input field(s), that are listened to for change events. // If undefined, it is set to the file input fields inside // of the widget element on plugin initialization. // Set to null to disable the change listener. fileInput: undefined, // By default, the file input field is replaced with a clone after // each input field change event. This is required for iframe transport // queues and allows change events to be fired for the same file // selection, but can be disabled by setting the following option to false: replaceFileInput: true, // The parameter name for the file form data (the request argument name). // If undefined or empty, the name property of the file input field is // used, or "files[]" if the file input name property is also empty, // can be a string or an array of strings: paramName: undefined, // By default, each file of a selection is uploaded using an individual // request for XHR type uploads. Set to false to upload file // selections in one request each: singleFileUploads: true, // To limit the number of files uploaded with one XHR request, // set the following option to an integer greater than 0: limitMultiFileUploads: undefined, // The following option limits the number of files uploaded with one // XHR request to keep the request size under or equal to the defined // limit in bytes: limitMultiFileUploadSize: undefined, // Multipart file uploads add a number of bytes to each uploaded file, // therefore the following option adds an overhead for each file used // in the limitMultiFileUploadSize configuration: limitMultiFileUploadSizeOverhead: 512, // Set the following option to true to issue all file upload requests // in a sequential order: sequentialUploads: false, // To limit the number of concurrent uploads, // set the following option to an integer greater than 0: limitConcurrentUploads: undefined, // Set the following option to true to force iframe transport uploads: forceIframeTransport: false, // Set the following option to the location of a redirect url on the // origin server, for cross-domain iframe transport uploads: redirect: undefined, // The parameter name for the redirect url, sent as part of the form // data and set to 'redirect' if this option is empty: redirectParamName: undefined, // Set the following option to the location of a postMessage window, // to enable postMessage transport uploads: postMessage: undefined, // By default, XHR file uploads are sent as multipart/form-data. // The iframe transport is always using multipart/form-data. // Set to false to enable non-multipart XHR uploads: multipart: true, // To upload large files in smaller chunks, set the following option // to a preferred maximum chunk size. If set to 0, null or undefined, // or the browser does not support the required Blob API, files will // be uploaded as a whole. maxChunkSize: undefined, // When a non-multipart upload or a chunked multipart upload has been // aborted, this option can be used to resume the upload by setting // it to the size of the already uploaded bytes. This option is most // useful when modifying the options object inside of the "add" or // "send" callbacks, as the options are cloned for each file upload. uploadedBytes: undefined, // By default, failed (abort or error) file uploads are removed from the // global progress calculation. Set the following option to false to // prevent recalculating the global progress data: recalculateProgress: true, // Interval in milliseconds to calculate and trigger progress events: progressInterval: 100, // Interval in milliseconds to calculate progress bitrate: bitrateInterval: 500, // By default, uploads are started automatically when adding files: autoUpload: true, // Error and info messages: messages: { uploadedBytes: 'Uploaded bytes exceed file size' }, // Translation function, gets the message key to be translated // and an object with context specific data as arguments: i18n: function (message, context) { message = this.messages[message] || message.toString(); if (context) { $.each(context, function (key, value) { message = message.replace('{' + key + '}', value); }); } return message; }, // Additional form data to be sent along with the file uploads can be set // using this option, which accepts an array of objects with name and // value properties, a function returning such an array, a FormData // object (for XHR file uploads), or a simple object. // The form of the first fileInput is given as parameter to the function: formData: function (form) { return form.serializeArray(); }, // The add callback is invoked as soon as files are added to the fileupload // widget (via file input selection, drag & drop, paste or add API call). // If the singleFileUploads option is enabled, this callback will be // called once for each file in the selection for XHR file uploads, else // once for each file selection. // // The upload starts when the submit method is invoked on the data parameter. // The data object contains a files property holding the added files // and allows you to override plugin options as well as define ajax settings. // // Listeners for this callback can also be bound the following way: // .bind('fileuploadadd', func); // // data.submit() returns a Promise object and allows to attach additional // handlers using jQuery's Deferred callbacks: // data.submit().done(func).fail(func).always(func); add: function (e, data) { if (e.isDefaultPrevented()) { return false; } if (data.autoUpload || (data.autoUpload !== false && $(this).fileupload('option', 'autoUpload'))) { data.process().done(function () { data.submit(); }); } }, // Other callbacks: // Callback for the submit event of each file upload: // submit: function (e, data) {}, // .bind('fileuploadsubmit', func); // Callback for the start of each file upload request: // send: function (e, data) {}, // .bind('fileuploadsend', func); // Callback for successful uploads: // done: function (e, data) {}, // .bind('fileuploaddone', func); // Callback for failed (abort or error) uploads: // fail: function (e, data) {}, // .bind('fileuploadfail', func); // Callback for completed (success, abort or error) requests: // always: function (e, data) {}, // .bind('fileuploadalways', func); // Callback for upload progress events: // progress: function (e, data) {}, // .bind('fileuploadprogress', func); // Callback for global upload progress events: // progressall: function (e, data) {}, // .bind('fileuploadprogressall', func); // Callback for uploads start, equivalent to the global ajaxStart event: // start: function (e) {}, // .bind('fileuploadstart', func); // Callback for uploads stop, equivalent to the global ajaxStop event: // stop: function (e) {}, // .bind('fileuploadstop', func); // Callback for change events of the fileInput(s): // change: function (e, data) {}, // .bind('fileuploadchange', func); // Callback for paste events to the pasteZone(s): // paste: function (e, data) {}, // .bind('fileuploadpaste', func); // Callback for drop events of the dropZone(s): // drop: function (e, data) {}, // .bind('fileuploaddrop', func); // Callback for dragover events of the dropZone(s): // dragover: function (e) {}, // .bind('fileuploaddragover', func); // Callback for the start of each chunk upload request: // chunksend: function (e, data) {}, // .bind('fileuploadchunksend', func); // Callback for successful chunk uploads: // chunkdone: function (e, data) {}, // .bind('fileuploadchunkdone', func); // Callback for failed (abort or error) chunk uploads: // chunkfail: function (e, data) {}, // .bind('fileuploadchunkfail', func); // Callback for completed (success, abort or error) chunk upload requests: // chunkalways: function (e, data) {}, // .bind('fileuploadchunkalways', func); // The plugin options are used as settings object for the ajax calls. // The following are jQuery ajax settings required for the file uploads: processData: false, contentType: false, cache: false }, // A list of options that require reinitializing event listeners and/or // special initialization code: _specialOptions: [ 'fileInput', 'dropZone', 'pasteZone', 'multipart', 'forceIframeTransport' ], _blobSlice: $.support.blobSlice && function () { var slice = this.slice || this.webkitSlice || this.mozSlice; return slice.apply(this, arguments); }, _BitrateTimer: function () { this.timestamp = ((Date.now) ? Date.now() : (new Date()).getTime()); this.loaded = 0; this.bitrate = 0; this.getBitrate = function (now, loaded, interval) { var timeDiff = now - this.timestamp; if (!this.bitrate || !interval || timeDiff > interval) { this.bitrate = (loaded - this.loaded) * (1000 / timeDiff) * 8; this.loaded = loaded; this.timestamp = now; } return this.bitrate; }; }, _isXHRUpload: function (options) { return !options.forceIframeTransport && ((!options.multipart && $.support.xhrFileUpload) || $.support.xhrFormDataFileUpload); }, _getFormData: function (options) { var formData; if ($.type(options.formData) === 'function') { return options.formData(options.form); } if ($.isArray(options.formData)) { return options.formData; } if ($.type(options.formData) === 'object') { formData = []; $.each(options.formData, function (name, value) { formData.push({name: name, value: value}); }); return formData; } return []; }, _getTotal: function (files) { var total = 0; $.each(files, function (index, file) { total += file.size || 1; }); return total; }, _initProgressObject: function (obj) { var progress = { loaded: 0, total: 0, bitrate: 0 }; if (obj._progress) { $.extend(obj._progress, progress); } else { obj._progress = progress; } }, _initResponseObject: function (obj) { var prop; if (obj._response) { for (prop in obj._response) { if (obj._response.hasOwnProperty(prop)) { delete obj._response[prop]; } } } else { obj._response = {}; } }, _onProgress: function (e, data) { if (e.lengthComputable) { var now = ((Date.now) ? Date.now() : (new Date()).getTime()), loaded; if (data._time && data.progressInterval && (now - data._time < data.progressInterval) && e.loaded !== e.total) { return; } data._time = now; loaded = Math.floor( e.loaded / e.total * (data.chunkSize || data._progress.total) ) + (data.uploadedBytes || 0); // Add the difference from the previously loaded state // to the global loaded counter: this._progress.loaded += (loaded - data._progress.loaded); this._progress.bitrate = this._bitrateTimer.getBitrate( now, this._progress.loaded, data.bitrateInterval ); data._progress.loaded = data.loaded = loaded; data._progress.bitrate = data.bitrate = data._bitrateTimer.getBitrate( now, loaded, data.bitrateInterval ); // Trigger a custom progress event with a total data property set // to the file size(s) of the current upload and a loaded data // property calculated accordingly: this._trigger( 'progress', $.Event('progress', {delegatedEvent: e}), data ); // Trigger a global progress event for all current file uploads, // including ajax calls queued for sequential file uploads: this._trigger( 'progressall', $.Event('progressall', {delegatedEvent: e}), this._progress ); } }, _initProgressListener: function (options) { var that = this, xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr(); // Accesss to the native XHR object is required to add event listeners // for the upload progress event: if (xhr.upload) { $(xhr.upload).bind('progress', function (e) { var oe = e.originalEvent; // Make sure the progress event properties get copied over: e.lengthComputable = oe.lengthComputable; e.loaded = oe.loaded; e.total = oe.total; that._onProgress(e, options); }); options.xhr = function () { return xhr; }; } }, _isInstanceOf: function (type, obj) { // Cross-frame instanceof check return Object.prototype.toString.call(obj) === '[object ' + type + ']'; }, _initXHRData: function (options) { var that = this, formData, file = options.files[0], // Ignore non-multipart setting if not supported: multipart = options.multipart || !$.support.xhrFileUpload, paramName = $.type(options.paramName) === 'array' ? options.paramName[0] : options.paramName; options.headers = $.extend({}, options.headers); if (options.contentRange) { options.headers['Content-Range'] = options.contentRange; } if (!multipart || options.blob || !this._isInstanceOf('File', file)) { options.headers['Content-Disposition'] = 'attachment; filename="' + encodeURI(file.name) + '"'; } if (!multipart) { options.contentType = file.type || 'application/octet-stream'; options.data = options.blob || file; } else if ($.support.xhrFormDataFileUpload) { if (options.postMessage) { // window.postMessage does not allow sending FormData // objects, so we just add the File/Blob objects to // the formData array and let the postMessage window // create the FormData object out of this array: formData = this._getFormData(options); if (options.blob) { formData.push({ name: paramName, value: options.blob }); } else { $.each(options.files, function (index, file) { formData.push({ name: ($.type(options.paramName) === 'array' && options.paramName[index]) || paramName, value: file }); }); } } else { if (that._isInstanceOf('FormData', options.formData)) { formData = options.formData; } else { formData = new FormData(); $.each(this._getFormData(options), function (index, field) { formData.append(field.name, field.value); }); } if (options.blob) { formData.append(paramName, options.blob, file.name); } else { $.each(options.files, function (index, file) { // This check allows the tests to run with // dummy objects: if (that._isInstanceOf('File', file) || that._isInstanceOf('Blob', file)) { formData.append( ($.type(options.paramName) === 'array' && options.paramName[index]) || paramName, file, file.uploadName || file.name ); } }); } } options.data = formData; } // Blob reference is not needed anymore, free memory: options.blob = null; }, _initIframeSettings: function (options) { var targetHost = $('<a></a>').prop('href', options.url).prop('host'); // Setting the dataType to iframe enables the iframe transport: options.dataType = 'iframe ' + (options.dataType || ''); // The iframe transport accepts a serialized array as form data: options.formData = this._getFormData(options); // Add redirect url to form data on cross-domain uploads: if (options.redirect && targetHost && targetHost !== location.host) { options.formData.push({ name: options.redirectParamName || 'redirect', value: options.redirect }); } }, _initDataSettings: function (options) { if (this._isXHRUpload(options)) { if (!this._chunkedUpload(options, true)) { if (!options.data) { this._initXHRData(options); } this._initProgressListener(options); } if (options.postMessage) { // Setting the dataType to postmessage enables the // postMessage transport: options.dataType = 'postmessage ' + (options.dataType || ''); } } else { this._initIframeSettings(options); } }, _getParamName: function (options) { var fileInput = $(options.fileInput), paramName = options.paramName; if (!paramName) { paramName = []; fileInput.each(function () { var input = $(this), name = input.prop('name') || 'files[]', i = (input.prop('files') || [1]).length; while (i) { paramName.push(name); i -= 1; } }); if (!paramName.length) { paramName = [fileInput.prop('name') || 'files[]']; } } else if (!$.isArray(paramName)) { paramName = [paramName]; } return paramName; }, _initFormSettings: function (options) { // Retrieve missing options from the input field and the // associated form, if available: if (!options.form || !options.form.length) { options.form = $(options.fileInput.prop('form')); // If the given file input doesn't have an associated form, // use the default widget file input's form: if (!options.form.length) { options.form = $(this.options.fileInput.prop('form')); } } options.paramName = this._getParamName(options); if (!options.url) { options.url = options.form.prop('action') || location.href; } // The HTTP request method must be "POST" or "PUT": options.type = (options.type || ($.type(options.form.prop('method')) === 'string' && options.form.prop('method')) || '' ).toUpperCase(); if (options.type !== 'POST' && options.type !== 'PUT' && options.type !== 'PATCH') { options.type = 'POST'; } if (!options.formAcceptCharset) { options.formAcceptCharset = options.form.attr('accept-charset'); } }, _getAJAXSettings: function (data) { var options = $.extend({}, this.options, data); this._initFormSettings(options); this._initDataSettings(options); return options; }, // jQuery 1.6 doesn't provide .state(), // while jQuery 1.8+ removed .isRejected() and .isResolved(): _getDeferredState: function (deferred) { if (deferred.state) { return deferred.state(); } if (deferred.isResolved()) { return 'resolved'; } if (deferred.isRejected()) { return 'rejected'; } return 'pending'; }, // Maps jqXHR callbacks to the equivalent // methods of the given Promise object: _enhancePromise: function (promise) { promise.success = promise.done; promise.error = promise.fail; promise.complete = promise.always; return promise; }, // Creates and returns a Promise object enhanced with // the jqXHR methods abort, success, error and complete: _getXHRPromise: function (resolveOrReject, context, args) { var dfd = $.Deferred(), promise = dfd.promise(); context = context || this.options.context || promise; if (resolveOrReject === true) { dfd.resolveWith(context, args); } else if (resolveOrReject === false) { dfd.rejectWith(context, args); } promise.abort = dfd.promise; return this._enhancePromise(promise); }, // Adds convenience methods to the data callback argument: _addConvenienceMethods: function (e, data) { var that = this, getPromise = function (args) { return $.Deferred().resolveWith(that, args).promise(); }; data.process = function (resolveFunc, rejectFunc) { if (resolveFunc || rejectFunc) { data._processQueue = this._processQueue = (this._processQueue || getPromise([this])).pipe( function () { if (data.errorThrown) { return $.Deferred() .rejectWith(that, [data]).promise(); } return getPromise(arguments); } ).pipe(resolveFunc, rejectFunc); } return this._processQueue || getPromise([this]); }; data.submit = function () { if (this.state() !== 'pending') { data.jqXHR = this.jqXHR = (that._trigger( 'submit', $.Event('submit', {delegatedEvent: e}), this ) !== false) && that._onSend(e, this); } return this.jqXHR || that._getXHRPromise(); }; data.abort = function () { if (this.jqXHR) { return this.jqXHR.abort(); } this.errorThrown = 'abort'; that._trigger('fail', null, this); return that._getXHRPromise(false); }; data.state = function () { if (this.jqXHR) { return that._getDeferredState(this.jqXHR); } if (this._processQueue) { return that._getDeferredState(this._processQueue); } }; data.processing = function () { return !this.jqXHR && this._processQueue && that ._getDeferredState(this._processQueue) === 'pending'; }; data.progress = function () { return this._progress; }; data.response = function () { return this._response; }; }, // Parses the Range header from the server response // and returns the uploaded bytes: _getUploadedBytes: function (jqXHR) { var range = jqXHR.getResponseHeader('Range'), parts = range && range.split('-'), upperBytesPos = parts && parts.length > 1 && parseInt(parts[1], 10); return upperBytesPos && upperBytesPos + 1; }, // Uploads a file in multiple, sequential requests // by splitting the file up in multiple blob chunks. // If the second parameter is true, only tests if the file // should be uploaded in chunks, but does not invoke any // upload requests: _chunkedUpload: function (options, testOnly) { options.uploadedBytes = options.uploadedBytes || 0; var that = this, file = options.files[0], fs = file.size, ub = options.uploadedBytes, mcs = options.maxChunkSize || fs, slice = this._blobSlice, dfd = $.Deferred(), promise = dfd.promise(), jqXHR, upload; if (!(this._isXHRUpload(options) && slice && (ub || mcs < fs)) || options.data) { return false; } if (testOnly) { return true; } if (ub >= fs) { file.error = options.i18n('uploadedBytes'); return this._getXHRPromise( false, options.context, [null, 'error', file.error] ); } // The chunk upload method: upload = function () { // Clone the options object for each chunk upload: var o = $.extend({}, options), currentLoaded = o._progress.loaded; o.blob = slice.call( file, ub, ub + mcs, file.type ); // Store the current chunk size, as the blob itself // will be dereferenced after data processing: o.chunkSize = o.blob.size; // Expose the chunk bytes position range: o.contentRange = 'bytes ' + ub + '-' + (ub + o.chunkSize - 1) + '/' + fs; // Process the upload data (the blob and potential form data): that._initXHRData(o); // Add progress listeners for this chunk upload: that._initProgressListener(o); jqXHR = ((that._trigger('chunksend', null, o) !== false && $.ajax(o)) || that._getXHRPromise(false, o.context)) .done(function (result, textStatus, jqXHR) { ub = that._getUploadedBytes(jqXHR) || (ub + o.chunkSize); // Create a progress event if no final progress event // with loaded equaling total has been triggered // for this chunk: if (currentLoaded + o.chunkSize - o._progress.loaded) { that._onProgress($.Event('progress', { lengthComputable: true, loaded: ub - o.uploadedBytes, total: ub - o.uploadedBytes }), o); } options.uploadedBytes = o.uploadedBytes = ub; o.result = result; o.textStatus = textStatus; o.jqXHR = jqXHR; that._trigger('chunkdone', null, o); that._trigger('chunkalways', null, o); if (ub < fs) { // File upload not yet complete, // continue with the next chunk: upload(); } else { dfd.resolveWith( o.context, [result, textStatus, jqXHR] ); } }) .fail(function (jqXHR, textStatus, errorThrown) { o.jqXHR = jqXHR; o.textStatus = textStatus; o.errorThrown = errorThrown; that._trigger('chunkfail', null, o); that._trigger('chunkalways', null, o); dfd.rejectWith( o.context, [jqXHR, textStatus, errorThrown] ); }); }; this._enhancePromise(promise); promise.abort = function () { return jqXHR.abort(); }; upload(); return promise; }, _beforeSend: function (e, data) { if (this._active === 0) { // the start callback is triggered when an upload starts // and no other uploads are currently running, // equivalent to the global ajaxStart event: this._trigger('start'); // Set timer for global bitrate progress calculation: this._bitrateTimer = new this._BitrateTimer(); // Reset the global progress values: this._progress.loaded = this._progress.total = 0; this._progress.bitrate = 0; } // Make sure the container objects for the .response() and // .progress() methods on the data object are available // and reset to their initial state: this._initResponseObject(data); this._initProgressObject(data); data._progress.loaded = data.loaded = data.uploadedBytes || 0; data._progress.total = data.total = this._getTotal(data.files) || 1; data._progress.bitrate = data.bitrate = 0; this._active += 1; // Initialize the global progress values: this._progress.loaded += data.loaded; this._progress.total += data.total; }, _onDone: function (result, textStatus, jqXHR, options) { var total = options._progress.total, response = options._response; if (options._progress.loaded < total) { // Create a progress event if no final progress event // with loaded equaling total has been triggered: this._onProgress($.Event('progress', { lengthComputable: true, loaded: total, total: total }), options); } response.result = options.result = result; response.textStatus = options.textStatus = textStatus; response.jqXHR = options.jqXHR = jqXHR; this._trigger('done', null, options); }, _onFail: function (jqXHR, textStatus, errorThrown, options) { var response = options._response; if (options.recalculateProgress) { // Remove the failed (error or abort) file upload from // the global progress calculation: this._progress.loaded -= options._progress.loaded; this._progress.total -= options._progress.total; } response.jqXHR = options.jqXHR = jqXHR; response.textStatus = options.textStatus = textStatus; response.errorThrown = options.errorThrown = errorThrown; this._trigger('fail', null, options); }, _onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) { // jqXHRorResult, textStatus and jqXHRorError are added to the // options object via done and fail callbacks this._trigger('always', null, options); }, _onSend: function (e, data) { if (!data.submit) { this._addConvenienceMethods(e, data); } var that = this, jqXHR, aborted, slot, pipe, options = that._getAJAXSettings(data), send = function () { that._sending += 1; // Set timer for bitrate progress calculation: options._bitrateTimer = new that._BitrateTimer(); jqXHR = jqXHR || ( ((aborted || that._trigger( 'send', $.Event('send', {delegatedEvent: e}), options ) === false) && that._getXHRPromise(false, options.context, aborted)) || that._chunkedUpload(options) || $.ajax(options) ).done(function (result, textStatus, jqXHR) { that._onDone(result, textStatus, jqXHR, options); }).fail(function (jqXHR, textStatus, errorThrown) { that._onFail(jqXHR, textStatus, errorThrown, options); }).always(function (jqXHRorResult, textStatus, jqXHRorError) { that._onAlways( jqXHRorResult, textStatus, jqXHRorError, options ); that._sending -= 1; that._active -= 1; if (options.limitConcurrentUploads && options.limitConcurrentUploads > that._sending) { // Start the next queued upload, // that has not been aborted: var nextSlot = that._slots.shift(); while (nextSlot) { if (that._getDeferredState(nextSlot) === 'pending') { nextSlot.resolve(); break; } nextSlot = that._slots.shift(); } } if (that._active === 0) { // The stop callback is triggered when all uploads have // been completed, equivalent to the global ajaxStop event: that._trigger('stop'); } }); return jqXHR; }; this._beforeSend(e, options); if (this.options.sequentialUploads || (this.options.limitConcurrentUploads && this.options.limitConcurrentUploads <= this._sending)) { if (this.options.limitConcurrentUploads > 1) { slot = $.Deferred(); this._slots.push(slot); pipe = slot.pipe(send); } else { this._sequence = this._sequence.pipe(send, send); pipe = this._sequence; } // Return the piped Promise object, enhanced with an abort method, // which is delegated to the jqXHR object of the current upload, // and jqXHR callbacks mapped to the equivalent Promise methods: pipe.abort = function () { aborted = [undefined, 'abort', 'abort']; if (!jqXHR) { if (slot) { slot.rejectWith(options.context, aborted); } return send(); } return jqXHR.abort(); }; return this._enhancePromise(pipe); } return send(); }, _onAdd: function (e, data) { var that = this, result = true, options = $.extend({}, this.options, data), files = data.files, filesLength = files.length, limit = options.limitMultiFileUploads, limitSize = options.limitMultiFileUploadSize, overhead = options.limitMultiFileUploadSizeOverhead, batchSize = 0, paramName = this._getParamName(options), paramNameSet, paramNameSlice, fileSet, i, j = 0; if (limitSize && (!filesLength || files[0].size === undefined)) { limitSize = undefined; } if (!(options.singleFileUploads || limit || limitSize) || !this._isXHRUpload(options)) { fileSet = [files]; paramNameSet = [paramName]; } else if (!(options.singleFileUploads || limitSize) && limit) { fileSet = []; paramNameSet = []; for (i = 0; i < filesLength; i += limit) { fileSet.push(files.slice(i, i + limit)); paramNameSlice = paramName.slice(i, i + limit); if (!paramNameSlice.length) { paramNameSlice = paramName; } paramNameSet.push(paramNameSlice); } } else if (!options.singleFileUploads && limitSize) { fileSet = []; paramNameSet = []; for (i = 0; i < filesLength; i = i + 1) { batchSize += files[i].size + overhead; if (i + 1 === filesLength || ((batchSize + files[i + 1].size + overhead) > limitSize) || (limit && i + 1 - j >= limit)) { fileSet.push(files.slice(j, i + 1)); paramNameSlice = paramName.slice(j, i + 1); if (!paramNameSlice.length) { paramNameSlice = paramName; } paramNameSet.push(paramNameSlice); j = i + 1; batchSize = 0; } } } else { paramNameSet = paramName; } data.originalFiles = files; $.each(fileSet || files, function (index, element) { var newData = $.extend({}, data); newData.files = fileSet ? element : [element]; newData.paramName = paramNameSet[index]; that._initResponseObject(newData); that._initProgressObject(newData); that._addConvenienceMethods(e, newData); result = that._trigger( 'add', $.Event('add', {delegatedEvent: e}), newData ); return result; }); return result; }, _replaceFileInput: function (data) { var input = data.fileInput, inputClone = input.clone(true); // Add a reference for the new cloned file input to the data argument: data.fileInputClone = inputClone; $('<form></form>').append(inputClone)[0].reset(); // Detaching allows to insert the fileInput on another form // without loosing the file input value: input.after(inputClone).detach(); // Avoid memory leaks with the detached file input: $.cleanData(input.unbind('remove')); // Replace the original file input element in the fileInput // elements set with the clone, which has been copied including // event handlers: this.options.fileInput = this.options.fileInput.map(function (i, el) { if (el === input[0]) { return inputClone[0]; } return el; }); // If the widget has been initialized on the file input itself, // override this.element with the file input clone: if (input[0] === this.element[0]) { this.element = inputClone; } }, _handleFileTreeEntry: function (entry, path) { var that = this, dfd = $.Deferred(), errorHandler = function (e) { if (e && !e.entry) { e.entry = entry; } // Since $.when returns immediately if one // Deferred is rejected, we use resolve instead. // This allows valid files and invalid items // to be returned together in one set: dfd.resolve([e]); }, successHandler = function (entries) { that._handleFileTreeEntries( entries, path + entry.name + '/' ).done(function (files) { dfd.resolve(files); }).fail(errorHandler); }, readEntries = function () { dirReader.readEntries(function (results) { if (!results.length) { successHandler(entries); } else { entries = entries.concat(results); readEntries(); } }, errorHandler); }, dirReader, entries = []; path = path || ''; if (entry.isFile) { if (entry._file) { // Workaround for Chrome bug #149735 entry._file.relativePath = path; dfd.resolve(entry._file); } else { entry.file(function (file) { file.relativePath = path; dfd.resolve(file); }, errorHandler); } } else if (entry.isDirectory) { dirReader = entry.createReader(); readEntries(); } else { // Return an empy list for file system items // other than files or directories: dfd.resolve([]); } return dfd.promise(); }, _handleFileTreeEntries: function (entries, path) { var that = this; return $.when.apply( $, $.map(entries, function (entry) { return that._handleFileTreeEntry(entry, path); }) ).pipe(function () { return Array.prototype.concat.apply( [], arguments ); }); }, _getDroppedFiles: function (dataTransfer) { dataTransfer = dataTransfer || {}; var items = dataTransfer.items; if (items && items.length && (items[0].webkitGetAsEntry || items[0].getAsEntry)) { return this._handleFileTreeEntries( $.map(items, function (item) { var entry; if (item.webkitGetAsEntry) { entry = item.webkitGetAsEntry(); if (entry) { // Workaround for Chrome bug #149735: entry._file = item.getAsFile(); } return entry; } return item.getAsEntry(); }) ); } return $.Deferred().resolve( $.makeArray(dataTransfer.files) ).promise(); }, _getSingleFileInputFiles: function (fileInput) { fileInput = $(fileInput); var entries = fileInput.prop('webkitEntries') || fileInput.prop('entries'), files, value; if (entries && entries.length) { return this._handleFileTreeEntries(entries); } files = $.makeArray(fileInput.prop('files')); if (!files.length) { value = fileInput.prop('value'); if (!value) { return $.Deferred().resolve([]).promise(); } // If the files property is not available, the browser does not // support the File API and we add a pseudo File object with // the input value as name with path information removed: files = [{name: value.replace(/^.*\\/, '')}]; } else if (files[0].name === undefined && files[0].fileName) { // File normalization for Safari 4 and Firefox 3: $.each(files, function (index, file) { file.name = file.fileName; file.size = file.fileSize; }); } return $.Deferred().resolve(files).promise(); }, _getFileInputFiles: function (fileInput) { if (!(fileInput instanceof $) || fileInput.length === 1) { return this._getSingleFileInputFiles(fileInput); } return $.when.apply( $, $.map(fileInput, this._getSingleFileInputFiles) ).pipe(function () { return Array.prototype.concat.apply( [], arguments ); }); }, _onChange: function (e) { var that = this, data = { fileInput: $(e.target), form: $(e.target.form) }; this._getFileInputFiles(data.fileInput).always(function (files) { data.files = files; if (that.options.replaceFileInput) { that._replaceFileInput(data); } if (that._trigger( 'change', $.Event('change', {delegatedEvent: e}), data ) !== false) { that._onAdd(e, data); } }); }, _onPaste: function (e) { var items = e.originalEvent && e.originalEvent.clipboardData && e.originalEvent.clipboardData.items, data = {files: []}; if (items && items.length) { $.each(items, function (index, item) { var file = item.getAsFile && item.getAsFile(); if (file) { data.files.push(file); } }); if (this._trigger( 'paste', $.Event('paste', {delegatedEvent: e}), data ) !== false) { this._onAdd(e, data); } } }, _onDrop: function (e) { e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer; var that = this, dataTransfer = e.dataTransfer, data = {}; if (dataTransfer && dataTransfer.files && dataTransfer.files.length) { e.preventDefault(); this._getDroppedFiles(dataTransfer).always(function (files) { data.files = files; if (that._trigger( 'drop', $.Event('drop', {delegatedEvent: e}), data ) !== false) { that._onAdd(e, data); } }); } }, _onDragOver: getDragHandler('dragover'), _onDragEnter: getDragHandler('dragenter'), _onDragLeave: getDragHandler('dragleave'), _initEventHandlers: function () { if (this._isXHRUpload(this.options)) { this._on(this.options.dropZone, { dragover: this._onDragOver, drop: this._onDrop, // event.preventDefault() on dragenter is required for IE10+: dragenter: this._onDragEnter, // dragleave is not required, but added for completeness: dragleave: this._onDragLeave }); this._on(this.options.pasteZone, { paste: this._onPaste }); } if ($.support.fileInput) { this._on(this.options.fileInput, { change: this._onChange }); } }, _destroyEventHandlers: function () { this._off(this.options.dropZone, 'dragenter dragleave dragover drop'); this._off(this.options.pasteZone, 'paste'); this._off(this.options.fileInput, 'change'); }, _setOption: function (key, value) { var reinit = $.inArray(key, this._specialOptions) !== -1; if (reinit) { this._destroyEventHandlers(); } this._super(key, value); if (reinit) { this._initSpecialOptions(); this._initEventHandlers(); } }, _initSpecialOptions: function () { var options = this.options; if (options.fileInput === undefined) { options.fileInput = this.element.is('input[type="file"]') ? this.element : this.element.find('input[type="file"]'); } else if (!(options.fileInput instanceof $)) { options.fileInput = $(options.fileInput); } if (!(options.dropZone instanceof $)) { options.dropZone = $(options.dropZone); } if (!(options.pasteZone instanceof $)) { options.pasteZone = $(options.pasteZone); } }, _getRegExp: function (str) { var parts = str.split('/'), modifiers = parts.pop(); parts.shift(); return new RegExp(parts.join('/'), modifiers); }, _isRegExpOption: function (key, value) { return key !== 'url' && $.type(value) === 'string' && /^\/.*\/[igm]{0,3}$/.test(value); }, _initDataAttributes: function () { var that = this, options = this.options, data = this.element.data(); // Initialize options set via HTML5 data-attributes: $.each( this.element[0].attributes, function (index, attr) { var key = attr.name.toLowerCase(), value; if (/^data-/.test(key)) { // Convert hyphen-ated key to camelCase: key = key.slice(5).replace(/-[a-z]/g, function (str) { return str.charAt(1).toUpperCase(); }); value = data[key]; if (that._isRegExpOption(key, value)) { value = that._getRegExp(value); } options[key] = value; } } ); }, _create: function () { this._initDataAttributes(); this._initSpecialOptions(); this._slots = []; this._sequence = this._getXHRPromise(true); this._sending = this._active = 0; this._initProgressObject(this); this._initEventHandlers(); }, // This method is exposed to the widget API and allows to query // the number of active uploads: active: function () { return this._active; }, // This method is exposed to the widget API and allows to query // the widget upload progress. // It returns an object with loaded, total and bitrate properties // for the running uploads: progress: function () { return this._progress; }, // This method is exposed to the widget API and allows adding files // using the fileupload API. The data parameter accepts an object which // must have a files property and can contain additional options: // .fileupload('add', {files: filesList}); add: function (data) { var that = this; if (!data || this.options.disabled) { return; } if (data.fileInput && !data.files) { this._getFileInputFiles(data.fileInput).always(function (files) { data.files = files; that._onAdd(null, data); }); } else { data.files = $.makeArray(data.files); this._onAdd(null, data); } }, // This method is exposed to the widget API and allows sending files // using the fileupload API. The data parameter accepts an object which // must have a files or fileInput property and can contain additional options: // .fileupload('send', {files: filesList}); // The method returns a Promise object for the file upload call. send: function (data) { if (data && !this.options.disabled) { if (data.fileInput && !data.files) { var that = this, dfd = $.Deferred(), promise = dfd.promise(), jqXHR, aborted; promise.abort = function () { aborted = true; if (jqXHR) { return jqXHR.abort(); } dfd.reject(null, 'abort', 'abort'); return promise; }; this._getFileInputFiles(data.fileInput).always( function (files) { if (aborted) { return; } if (!files.length) { dfd.reject(); return; } data.files = files; jqXHR = that._onSend(null, data); jqXHR.then( function (result, textStatus, jqXHR) { dfd.resolve(result, textStatus, jqXHR); }, function (jqXHR, textStatus, errorThrown) { dfd.reject(jqXHR, textStatus, errorThrown); } ); } ); return this._enhancePromise(promise); } data.files = $.makeArray(data.files); if (data.files.length) { return this._onSend(null, data); } } return this._getXHRPromise(false, data && data.context); } }); })); // ┌────────────────────────────────────────────────────────────────────┐ \\ // │ Raphaël 2.1.2 - JavaScript Vector Library │ \\ // ├────────────────────────────────────────────────────────────────────┤ \\ // │ Copyright © 2008-2012 Dmitry Baranovskiy (http://raphaeljs.com) │ \\ // │ Copyright © 2008-2012 Sencha Labs (http://sencha.com) │ \\ // ├────────────────────────────────────────────────────────────────────┤ \\ // │ Licensed under the MIT (http://raphaeljs.com/license.html) license.│ \\ // └────────────────────────────────────────────────────────────────────┘ \\ // Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ┌────────────────────────────────────────────────────────────┐ \\ // │ Eve 0.4.2 - JavaScript Events Library │ \\ // ├────────────────────────────────────────────────────────────┤ \\ // │ Author Dmitry Baranovskiy (http://dmitry.baranovskiy.com/) │ \\ // └────────────────────────────────────────────────────────────┘ \\ (function (glob) { var version = "0.4.2", has = "hasOwnProperty", separator = /[\.\/]/, wildcard = "*", fun = function () {}, numsort = function (a, b) { return a - b; }, current_event, stop, events = {n: {}}, /*\ * eve [ method ] * Fires event with given `name`, given scope and other parameters. > Arguments - name (string) name of the *event*, dot (`.`) or slash (`/`) separated - scope (object) context for the event handlers - varargs (...) the rest of arguments will be sent to event handlers = (object) array of returned values from the listeners \*/ eve = function (name, scope) { name = String(name); var e = events, oldstop = stop, args = Array.prototype.slice.call(arguments, 2), listeners = eve.listeners(name), z = 0, f = false, l, indexed = [], queue = {}, out = [], ce = current_event, errors = []; current_event = name; stop = 0; for (var i = 0, ii = listeners.length; i < ii; i++) if ("zIndex" in listeners[i]) { indexed.push(listeners[i].zIndex); if (listeners[i].zIndex < 0) { queue[listeners[i].zIndex] = listeners[i]; } } indexed.sort(numsort); while (indexed[z] < 0) { l = queue[indexed[z++]]; out.push(l.apply(scope, args)); if (stop) { stop = oldstop; return out; } } for (i = 0; i < ii; i++) { l = listeners[i]; if ("zIndex" in l) { if (l.zIndex == indexed[z]) { out.push(l.apply(scope, args)); if (stop) { break; } do { z++; l = queue[indexed[z]]; l && out.push(l.apply(scope, args)); if (stop) { break; } } while (l) } else { queue[l.zIndex] = l; } } else { out.push(l.apply(scope, args)); if (stop) { break; } } } stop = oldstop; current_event = ce; return out.length ? out : null; }; // Undocumented. Debug only. eve._events = events; /*\ * eve.listeners [ method ] * Internal method which gives you array of all event handlers that will be triggered by the given `name`. > Arguments - name (string) name of the event, dot (`.`) or slash (`/`) separated = (array) array of event handlers \*/ eve.listeners = function (name) { var names = name.split(separator), e = events, item, items, k, i, ii, j, jj, nes, es = [e], out = []; for (i = 0, ii = names.length; i < ii; i++) { nes = []; for (j = 0, jj = es.length; j < jj; j++) { e = es[j].n; items = [e[names[i]], e[wildcard]]; k = 2; while (k--) { item = items[k]; if (item) { nes.push(item); out = out.concat(item.f || []); } } } es = nes; } return out; }; /*\ * eve.on [ method ] ** * Binds given event handler with a given name. You can use wildcards “`*`” for the names: | eve.on("*.under.*", f); | eve("mouse.under.floor"); // triggers f * Use @eve to trigger the listener. ** > Arguments ** - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards - f (function) event handler function ** = (function) returned function accepts a single numeric parameter that represents z-index of the handler. It is an optional feature and only used when you need to ensure that some subset of handlers will be invoked in a given order, despite of the order of assignment. > Example: | eve.on("mouse", eatIt)(2); | eve.on("mouse", scream); | eve.on("mouse", catchIt)(1); * This will ensure that `catchIt()` function will be called before `eatIt()`. * * If you want to put your handler before non-indexed handlers, specify a negative value. * Note: I assume most of the time you don’t need to worry about z-index, but it’s nice to have this feature “just in case”. \*/ eve.on = function (name, f) { name = String(name); if (typeof f != "function") { return function () {}; } var names = name.split(separator), e = events; for (var i = 0, ii = names.length; i < ii; i++) { e = e.n; e = e.hasOwnProperty(names[i]) && e[names[i]] || (e[names[i]] = {n: {}}); } e.f = e.f || []; for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) { return fun; } e.f.push(f); return function (zIndex) { if (+zIndex == +zIndex) { f.zIndex = +zIndex; } }; }; /*\ * eve.f [ method ] ** * Returns function that will fire given event with optional arguments. * Arguments that will be passed to the result function will be also * concated to the list of final arguments. | el.onclick = eve.f("click", 1, 2); | eve.on("click", function (a, b, c) { | console.log(a, b, c); // 1, 2, [event object] | }); > Arguments - event (string) event name - varargs (…) and any other arguments = (function) possible event handler function \*/ eve.f = function (event) { var attrs = [].slice.call(arguments, 1); return function () { eve.apply(null, [event, null].concat(attrs).concat([].slice.call(arguments, 0))); }; }; /*\ * eve.stop [ method ] ** * Is used inside an event handler to stop the event, preventing any subsequent listeners from firing. \*/ eve.stop = function () { stop = 1; }; /*\ * eve.nt [ method ] ** * Could be used inside event handler to figure out actual name of the event. ** > Arguments ** - subname (string) #optional subname of the event ** = (string) name of the event, if `subname` is not specified * or = (boolean) `true`, if current event’s name contains `subname` \*/ eve.nt = function (subname) { if (subname) { return new RegExp("(?:\\.|\\/|^)" + subname + "(?:\\.|\\/|$)").test(current_event); } return current_event; }; /*\ * eve.nts [ method ] ** * Could be used inside event handler to figure out actual name of the event. ** ** = (array) names of the event \*/ eve.nts = function () { return current_event.split(separator); }; /*\ * eve.off [ method ] ** * Removes given function from the list of event listeners assigned to given name. * If no arguments specified all the events will be cleared. ** > Arguments ** - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards - f (function) event handler function \*/ /*\ * eve.unbind [ method ] ** * See @eve.off \*/ eve.off = eve.unbind = function (name, f) { if (!name) { eve._events = events = {n: {}}; return; } var names = name.split(separator), e, key, splice, i, ii, j, jj, cur = [events]; for (i = 0, ii = names.length; i < ii; i++) { for (j = 0; j < cur.length; j += splice.length - 2) { splice = [j, 1]; e = cur[j].n; if (names[i] != wildcard) { if (e[names[i]]) { splice.push(e[names[i]]); } } else { for (key in e) if (e[has](key)) { splice.push(e[key]); } } cur.splice.apply(cur, splice); } } for (i = 0, ii = cur.length; i < ii; i++) { e = cur[i]; while (e.n) { if (f) { if (e.f) { for (j = 0, jj = e.f.length; j < jj; j++) if (e.f[j] == f) { e.f.splice(j, 1); break; } !e.f.length && delete e.f; } for (key in e.n) if (e.n[has](key) && e.n[key].f) { var funcs = e.n[key].f; for (j = 0, jj = funcs.length; j < jj; j++) if (funcs[j] == f) { funcs.splice(j, 1); break; } !funcs.length && delete e.n[key].f; } } else { delete e.f; for (key in e.n) if (e.n[has](key) && e.n[key].f) { delete e.n[key].f; } } e = e.n; } } }; /*\ * eve.once [ method ] ** * Binds given event handler with a given name to only run once then unbind itself. | eve.once("login", f); | eve("login"); // triggers f | eve("login"); // no listeners * Use @eve to trigger the listener. ** > Arguments ** - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards - f (function) event handler function ** = (function) same return function as @eve.on \*/ eve.once = function (name, f) { var f2 = function () { eve.unbind(name, f2); return f.apply(this, arguments); }; return eve.on(name, f2); }; /*\ * eve.version [ property (string) ] ** * Current version of the library. \*/ eve.version = version; eve.toString = function () { return "You are running Eve " + version; }; (typeof module != "undefined" && module.exports) ? (module.exports = eve) : (typeof define != "undefined" ? (define("eve", [], function() { return eve; })) : (glob.eve = eve)); })(this); // ┌─────────────────────────────────────────────────────────────────────┐ \\ // │ "Raphaël 2.1.2" - JavaScript Vector Library │ \\ // ├─────────────────────────────────────────────────────────────────────┤ \\ // │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com) │ \\ // │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com) │ \\ // │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\ // └─────────────────────────────────────────────────────────────────────┘ \\ (function (glob, factory) { // AMD support if (typeof define === "function" && define.amd) { // Define as an anonymous module define(["eve"], function( eve ) { return factory(glob, eve); }); } else { // Browser globals (glob is window) // Raphael adds itself to window factory(glob, glob.eve); } }(this, function (window, eve) { /*\ * Raphael [ method ] ** * Creates a canvas object on which to draw. * You must do this first, as all future calls to drawing methods * from this instance will be bound to this canvas. > Parameters ** - container (HTMLElement|string) DOM element or its ID which is going to be a parent for drawing surface - width (number) - height (number) - callback (function) #optional callback function which is going to be executed in the context of newly created paper * or - x (number) - y (number) - width (number) - height (number) - callback (function) #optional callback function which is going to be executed in the context of newly created paper * or - all (array) (first 3 or 4 elements in the array are equal to [containerID, width, height] or [x, y, width, height]. The rest are element descriptions in format {type: type, <attributes>}). See @Paper.add. - callback (function) #optional callback function which is going to be executed in the context of newly created paper * or - onReadyCallback (function) function that is going to be called on DOM ready event. You can also subscribe to this event via Eve’s “DOMLoad” event. In this case method returns `undefined`. = (object) @Paper > Usage | // Each of the following examples create a canvas | // that is 320px wide by 200px high. | // Canvas is created at the viewport’s 10,50 coordinate. | var paper = Raphael(10, 50, 320, 200); | // Canvas is created at the top left corner of the #notepad element | // (or its top right corner in dir="rtl" elements) | var paper = Raphael(document.getElementById("notepad"), 320, 200); | // Same as above | var paper = Raphael("notepad", 320, 200); | // Image dump | var set = Raphael(["notepad", 320, 200, { | type: "rect", | x: 10, | y: 10, | width: 25, | height: 25, | stroke: "#f00" | }, { | type: "text", | x: 30, | y: 40, | text: "Dump" | }]); \*/ function R(first) { if (R.is(first, "function")) { return loaded ? first() : eve.on("raphael.DOMload", first); } else if (R.is(first, array)) { return R._engine.create[apply](R, first.splice(0, 3 + R.is(first[0], nu))).add(first); } else { var args = Array.prototype.slice.call(arguments, 0); if (R.is(args[args.length - 1], "function")) { var f = args.pop(); return loaded ? f.call(R._engine.create[apply](R, args)) : eve.on("raphael.DOMload", function () { f.call(R._engine.create[apply](R, args)); }); } else { return R._engine.create[apply](R, arguments); } } } R.version = "2.1.2"; R.eve = eve; var loaded, separator = /[, ]+/, elements = {circle: 1, rect: 1, path: 1, ellipse: 1, text: 1, image: 1}, formatrg = /\{(\d+)\}/g, proto = "prototype", has = "hasOwnProperty", g = { doc: document, win: window }, oldRaphael = { was: Object.prototype[has].call(g.win, "Raphael"), is: g.win.Raphael }, Paper = function () { /*\ * Paper.ca [ property (object) ] ** * Shortcut for @Paper.customAttributes \*/ /*\ * Paper.customAttributes [ property (object) ] ** * If you have a set of attributes that you would like to represent * as a function of some number you can do it easily with custom attributes: > Usage | paper.customAttributes.hue = function (num) { | num = num % 1; | return {fill: "hsb(" + num + ", 0.75, 1)"}; | }; | // Custom attribute “hue” will change fill | // to be given hue with fixed saturation and brightness. | // Now you can use it like this: | var c = paper.circle(10, 10, 10).attr({hue: .45}); | // or even like this: | c.animate({hue: 1}, 1e3); | | // You could also create custom attribute | // with multiple parameters: | paper.customAttributes.hsb = function (h, s, b) { | return {fill: "hsb(" + [h, s, b].join(",") + ")"}; | }; | c.attr({hsb: "0.5 .8 1"}); | c.animate({hsb: [1, 0, 0.5]}, 1e3); \*/ this.ca = this.customAttributes = {}; }, paperproto, appendChild = "appendChild", apply = "apply", concat = "concat", supportsTouch = ('ontouchstart' in g.win) || g.win.DocumentTouch && g.doc instanceof DocumentTouch, //taken from Modernizr touch test E = "", S = " ", Str = String, split = "split", events = "click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel"[split](S), touchMap = { mousedown: "touchstart", mousemove: "touchmove", mouseup: "touchend" }, lowerCase = Str.prototype.toLowerCase, math = Math, mmax = math.max, mmin = math.min, abs = math.abs, pow = math.pow, PI = math.PI, nu = "number", string = "string", array = "array", toString = "toString", fillString = "fill", objectToString = Object.prototype.toString, paper = {}, push = "push", ISURL = R._ISURL = /^url\(['"]?([^\)]+?)['"]?\)$/i, colourRegExp = /^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+%?)?)\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\))\s*$/i, isnan = {"NaN": 1, "Infinity": 1, "-Infinity": 1}, bezierrg = /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/, round = math.round, setAttribute = "setAttribute", toFloat = parseFloat, toInt = parseInt, upperCase = Str.prototype.toUpperCase, availableAttrs = R._availableAttrs = { "arrow-end": "none", "arrow-start": "none", blur: 0, "clip-rect": "0 0 1e9 1e9", cursor: "default", cx: 0, cy: 0, fill: "#fff", "fill-opacity": 1, font: '10px "Arial"', "font-family": '"Arial"', "font-size": "10", "font-style": "normal", "font-weight": 400, gradient: 0, height: 0, href: "http://raphaeljs.com/", "letter-spacing": 0, opacity: 1, path: "M0,0", r: 0, rx: 0, ry: 0, src: "", stroke: "#000", "stroke-dasharray": "", "stroke-linecap": "butt", "stroke-linejoin": "butt", "stroke-miterlimit": 0, "stroke-opacity": 1, "stroke-width": 1, target: "_blank", "text-anchor": "middle", title: "Raphael", transform: "", width: 0, x: 0, y: 0 }, availableAnimAttrs = R._availableAnimAttrs = { blur: nu, "clip-rect": "csv", cx: nu, cy: nu, fill: "colour", "fill-opacity": nu, "font-size": nu, height: nu, opacity: nu, path: "path", r: nu, rx: nu, ry: nu, stroke: "colour", "stroke-opacity": nu, "stroke-width": nu, transform: "transform", width: nu, x: nu, y: nu }, whitespace = /[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]/g, commaSpaces = /[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*/, hsrg = {hs: 1, rg: 1}, p2s = /,?([achlmqrstvxz]),?/gi, pathCommand = /([achlmrqstvz])[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*)+)/ig, tCommand = /([rstm])[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*)+)/ig, pathValues = /(-?\d*\.?\d*(?:e[\-+]?\d+)?)[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*/ig, radial_gradient = R._radial_gradient = /^r(?:\(([^,]+?)[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*([^\)]+?)\))?/, eldata = {}, sortByKey = function (a, b) { return a.key - b.key; }, sortByNumber = function (a, b) { return toFloat(a) - toFloat(b); }, fun = function () {}, pipe = function (x) { return x; }, rectPath = R._rectPath = function (x, y, w, h, r) { if (r) { return [["M", x + r, y], ["l", w - r * 2, 0], ["a", r, r, 0, 0, 1, r, r], ["l", 0, h - r * 2], ["a", r, r, 0, 0, 1, -r, r], ["l", r * 2 - w, 0], ["a", r, r, 0, 0, 1, -r, -r], ["l", 0, r * 2 - h], ["a", r, r, 0, 0, 1, r, -r], ["z"]]; } return [["M", x, y], ["l", w, 0], ["l", 0, h], ["l", -w, 0], ["z"]]; }, ellipsePath = function (x, y, rx, ry) { if (ry == null) { ry = rx; } return [["M", x, y], ["m", 0, -ry], ["a", rx, ry, 0, 1, 1, 0, 2 * ry], ["a", rx, ry, 0, 1, 1, 0, -2 * ry], ["z"]]; }, getPath = R._getPath = { path: function (el) { return el.attr("path"); }, circle: function (el) { var a = el.attrs; return ellipsePath(a.cx, a.cy, a.r); }, ellipse: function (el) { var a = el.attrs; return ellipsePath(a.cx, a.cy, a.rx, a.ry); }, rect: function (el) { var a = el.attrs; return rectPath(a.x, a.y, a.width, a.height, a.r); }, image: function (el) { var a = el.attrs; return rectPath(a.x, a.y, a.width, a.height); }, text: function (el) { var bbox = el._getBBox(); return rectPath(bbox.x, bbox.y, bbox.width, bbox.height); }, set : function(el) { var bbox = el._getBBox(); return rectPath(bbox.x, bbox.y, bbox.width, bbox.height); } }, /*\ * Raphael.mapPath [ method ] ** * Transform the path string with given matrix. > Parameters - path (string) path string - matrix (object) see @Matrix = (string) transformed path string \*/ mapPath = R.mapPath = function (path, matrix) { if (!matrix) { return path; } var x, y, i, j, ii, jj, pathi; path = path2curve(path); for (i = 0, ii = path.length; i < ii; i++) { pathi = path[i]; for (j = 1, jj = pathi.length; j < jj; j += 2) { x = matrix.x(pathi[j], pathi[j + 1]); y = matrix.y(pathi[j], pathi[j + 1]); pathi[j] = x; pathi[j + 1] = y; } } return path; }; R._g = g; /*\ * Raphael.type [ property (string) ] ** * Can be “SVG”, “VML” or empty, depending on browser support. \*/ R.type = (g.win.SVGAngle || g.doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") ? "SVG" : "VML"); if (R.type == "VML") { var d = g.doc.createElement("div"), b; d.innerHTML = '<v:shape adj="1"/>'; b = d.firstChild; b.style.behavior = "url(#default#VML)"; if (!(b && typeof b.adj == "object")) { return (R.type = E); } d = null; } /*\ * Raphael.svg [ property (boolean) ] ** * `true` if browser supports SVG. \*/ /*\ * Raphael.vml [ property (boolean) ] ** * `true` if browser supports VML. \*/ R.svg = !(R.vml = R.type == "VML"); R._Paper = Paper; /*\ * Raphael.fn [ property (object) ] ** * You can add your own method to the canvas. For example if you want to draw a pie chart, * you can create your own pie chart function and ship it as a Raphaël plugin. To do this * you need to extend the `Raphael.fn` object. You should modify the `fn` object before a * Raphaël instance is created, otherwise it will take no effect. Please note that the * ability for namespaced plugins was removed in Raphael 2.0. It is up to the plugin to * ensure any namespacing ensures proper context. > Usage | Raphael.fn.arrow = function (x1, y1, x2, y2, size) { | return this.path( ... ); | }; | // or create namespace | Raphael.fn.mystuff = { | arrow: function () {…}, | star: function () {…}, | // etc… | }; | var paper = Raphael(10, 10, 630, 480); | // then use it | paper.arrow(10, 10, 30, 30, 5).attr({fill: "#f00"}); | paper.mystuff.arrow(); | paper.mystuff.star(); \*/ R.fn = paperproto = Paper.prototype = R.prototype; R._id = 0; R._oid = 0; /*\ * Raphael.is [ method ] ** * Handfull replacement for `typeof` operator. > Parameters - o (…) any object or primitive - type (string) name of the type, i.e. “string”, “function”, “number”, etc. = (boolean) is given value is of given type \*/ R.is = function (o, type) { type = lowerCase.call(type); if (type == "finite") { return !isnan[has](+o); } if (type == "array") { return o instanceof Array; } return (type == "null" && o === null) || (type == typeof o && o !== null) || (type == "object" && o === Object(o)) || (type == "array" && Array.isArray && Array.isArray(o)) || objectToString.call(o).slice(8, -1).toLowerCase() == type; }; function clone(obj) { if (typeof obj == "function" || Object(obj) !== obj) { return obj; } var res = new obj.constructor; for (var key in obj) if (obj[has](key)) { res[key] = clone(obj[key]); } return res; } /*\ * Raphael.angle [ method ] ** * Returns angle between two or three points > Parameters - x1 (number) x coord of first point - y1 (number) y coord of first point - x2 (number) x coord of second point - y2 (number) y coord of second point - x3 (number) #optional x coord of third point - y3 (number) #optional y coord of third point = (number) angle in degrees. \*/ R.angle = function (x1, y1, x2, y2, x3, y3) { if (x3 == null) { var x = x1 - x2, y = y1 - y2; if (!x && !y) { return 0; } return (180 + math.atan2(-y, -x) * 180 / PI + 360) % 360; } else { return R.angle(x1, y1, x3, y3) - R.angle(x2, y2, x3, y3); } }; /*\ * Raphael.rad [ method ] ** * Transform angle to radians > Parameters - deg (number) angle in degrees = (number) angle in radians. \*/ R.rad = function (deg) { return deg % 360 * PI / 180; }; /*\ * Raphael.deg [ method ] ** * Transform angle to degrees > Parameters - deg (number) angle in radians = (number) angle in degrees. \*/ R.deg = function (rad) { return rad * 180 / PI % 360; }; /*\ * Raphael.snapTo [ method ] ** * Snaps given value to given grid. > Parameters - values (array|number) given array of values or step of the grid - value (number) value to adjust - tolerance (number) #optional tolerance for snapping. Default is `10`. = (number) adjusted value. \*/ R.snapTo = function (values, value, tolerance) { tolerance = R.is(tolerance, "finite") ? tolerance : 10; if (R.is(values, array)) { var i = values.length; while (i--) if (abs(values[i] - value) <= tolerance) { return values[i]; } } else { values = +values; var rem = value % values; if (rem < tolerance) { return value - rem; } if (rem > values - tolerance) { return value - rem + values; } } return value; }; /*\ * Raphael.createUUID [ method ] ** * Returns RFC4122, version 4 ID \*/ var createUUID = R.createUUID = (function (uuidRegEx, uuidReplacer) { return function () { return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(uuidRegEx, uuidReplacer).toUpperCase(); }; })(/[xy]/g, function (c) { var r = math.random() * 16 | 0, v = c == "x" ? r : (r & 3 | 8); return v.toString(16); }); /*\ * Raphael.setWindow [ method ] ** * Used when you need to draw in `<iframe>`. Switched window to the iframe one. > Parameters - newwin (window) new window object \*/ R.setWindow = function (newwin) { eve("raphael.setWindow", R, g.win, newwin); g.win = newwin; g.doc = g.win.document; if (R._engine.initWin) { R._engine.initWin(g.win); } }; var toHex = function (color) { if (R.vml) { // http://dean.edwards.name/weblog/2009/10/convert-any-colour-value-to-hex-in-msie/ var trim = /^\s+|\s+$/g; var bod; try { var docum = new ActiveXObject("htmlfile"); docum.write("<body>"); docum.close(); bod = docum.body; } catch(e) { bod = createPopup().document.body; } var range = bod.createTextRange(); toHex = cacher(function (color) { try { bod.style.color = Str(color).replace(trim, E); var value = range.queryCommandValue("ForeColor"); value = ((value & 255) << 16) | (value & 65280) | ((value & 16711680) >>> 16); return "#" + ("000000" + value.toString(16)).slice(-6); } catch(e) { return "none"; } }); } else { var i = g.doc.createElement("i"); i.title = "Rapha\xebl Colour Picker"; i.style.display = "none"; g.doc.body.appendChild(i); toHex = cacher(function (color) { i.style.color = color; return g.doc.defaultView.getComputedStyle(i, E).getPropertyValue("color"); }); } return toHex(color); }, hsbtoString = function () { return "hsb(" + [this.h, this.s, this.b] + ")"; }, hsltoString = function () { return "hsl(" + [this.h, this.s, this.l] + ")"; }, rgbtoString = function () { return this.hex; }, prepareRGB = function (r, g, b) { if (g == null && R.is(r, "object") && "r" in r && "g" in r && "b" in r) { b = r.b; g = r.g; r = r.r; } if (g == null && R.is(r, string)) { var clr = R.getRGB(r); r = clr.r; g = clr.g; b = clr.b; } if (r > 1 || g > 1 || b > 1) { r /= 255; g /= 255; b /= 255; } return [r, g, b]; }, packageRGB = function (r, g, b, o) { r *= 255; g *= 255; b *= 255; var rgb = { r: r, g: g, b: b, hex: R.rgb(r, g, b), toString: rgbtoString }; R.is(o, "finite") && (rgb.opacity = o); return rgb; }; /*\ * Raphael.color [ method ] ** * Parses the color string and returns object with all values for the given color. > Parameters - clr (string) color string in one of the supported formats (see @Raphael.getRGB) = (object) Combined RGB & HSB object in format: o { o r (number) red, o g (number) green, o b (number) blue, o hex (string) color in HTML/CSS format: #••••••, o error (boolean) `true` if string can’t be parsed, o h (number) hue, o s (number) saturation, o v (number) value (brightness), o l (number) lightness o } \*/ R.color = function (clr) { var rgb; if (R.is(clr, "object") && "h" in clr && "s" in clr && "b" in clr) { rgb = R.hsb2rgb(clr); clr.r = rgb.r; clr.g = rgb.g; clr.b = rgb.b; clr.hex = rgb.hex; } else if (R.is(clr, "object") && "h" in clr && "s" in clr && "l" in clr) { rgb = R.hsl2rgb(clr); clr.r = rgb.r; clr.g = rgb.g; clr.b = rgb.b; clr.hex = rgb.hex; } else { if (R.is(clr, "string")) { clr = R.getRGB(clr); } if (R.is(clr, "object") && "r" in clr && "g" in clr && "b" in clr) { rgb = R.rgb2hsl(clr); clr.h = rgb.h; clr.s = rgb.s; clr.l = rgb.l; rgb = R.rgb2hsb(clr); clr.v = rgb.b; } else { clr = {hex: "none"}; clr.r = clr.g = clr.b = clr.h = clr.s = clr.v = clr.l = -1; } } clr.toString = rgbtoString; return clr; }; /*\ * Raphael.hsb2rgb [ method ] ** * Converts HSB values to RGB object. > Parameters - h (number) hue - s (number) saturation - v (number) value or brightness = (object) RGB object in format: o { o r (number) red, o g (number) green, o b (number) blue, o hex (string) color in HTML/CSS format: #•••••• o } \*/ R.hsb2rgb = function (h, s, v, o) { if (this.is(h, "object") && "h" in h && "s" in h && "b" in h) { v = h.b; s = h.s; h = h.h; o = h.o; } h *= 360; var R, G, B, X, C; h = (h % 360) / 60; C = v * s; X = C * (1 - abs(h % 2 - 1)); R = G = B = v - C; h = ~~h; R += [C, X, 0, 0, X, C][h]; G += [X, C, C, X, 0, 0][h]; B += [0, 0, X, C, C, X][h]; return packageRGB(R, G, B, o); }; /*\ * Raphael.hsl2rgb [ method ] ** * Converts HSL values to RGB object. > Parameters - h (number) hue - s (number) saturation - l (number) luminosity = (object) RGB object in format: o { o r (number) red, o g (number) green, o b (number) blue, o hex (string) color in HTML/CSS format: #•••••• o } \*/ R.hsl2rgb = function (h, s, l, o) { if (this.is(h, "object") && "h" in h && "s" in h && "l" in h) { l = h.l; s = h.s; h = h.h; } if (h > 1 || s > 1 || l > 1) { h /= 360; s /= 100; l /= 100; } h *= 360; var R, G, B, X, C; h = (h % 360) / 60; C = 2 * s * (l < .5 ? l : 1 - l); X = C * (1 - abs(h % 2 - 1)); R = G = B = l - C / 2; h = ~~h; R += [C, X, 0, 0, X, C][h]; G += [X, C, C, X, 0, 0][h]; B += [0, 0, X, C, C, X][h]; return packageRGB(R, G, B, o); }; /*\ * Raphael.rgb2hsb [ method ] ** * Converts RGB values to HSB object. > Parameters - r (number) red - g (number) green - b (number) blue = (object) HSB object in format: o { o h (number) hue o s (number) saturation o b (number) brightness o } \*/ R.rgb2hsb = function (r, g, b) { b = prepareRGB(r, g, b); r = b[0]; g = b[1]; b = b[2]; var H, S, V, C; V = mmax(r, g, b); C = V - mmin(r, g, b); H = (C == 0 ? null : V == r ? (g - b) / C : V == g ? (b - r) / C + 2 : (r - g) / C + 4 ); H = ((H + 360) % 6) * 60 / 360; S = C == 0 ? 0 : C / V; return {h: H, s: S, b: V, toString: hsbtoString}; }; /*\ * Raphael.rgb2hsl [ method ] ** * Converts RGB values to HSL object. > Parameters - r (number) red - g (number) green - b (number) blue = (object) HSL object in format: o { o h (number) hue o s (number) saturation o l (number) luminosity o } \*/ R.rgb2hsl = function (r, g, b) { b = prepareRGB(r, g, b); r = b[0]; g = b[1]; b = b[2]; var H, S, L, M, m, C; M = mmax(r, g, b); m = mmin(r, g, b); C = M - m; H = (C == 0 ? null : M == r ? (g - b) / C : M == g ? (b - r) / C + 2 : (r - g) / C + 4); H = ((H + 360) % 6) * 60 / 360; L = (M + m) / 2; S = (C == 0 ? 0 : L < .5 ? C / (2 * L) : C / (2 - 2 * L)); return {h: H, s: S, l: L, toString: hsltoString}; }; R._path2string = function () { return this.join(",").replace(p2s, "$1"); }; function repush(array, item) { for (var i = 0, ii = array.length; i < ii; i++) if (array[i] === item) { return array.push(array.splice(i, 1)[0]); } } function cacher(f, scope, postprocessor) { function newf() { var arg = Array.prototype.slice.call(arguments, 0), args = arg.join("\u2400"), cache = newf.cache = newf.cache || {}, count = newf.count = newf.count || []; if (cache[has](args)) { repush(count, args); return postprocessor ? postprocessor(cache[args]) : cache[args]; } count.length >= 1e3 && delete cache[count.shift()]; count.push(args); cache[args] = f[apply](scope, arg); return postprocessor ? postprocessor(cache[args]) : cache[args]; } return newf; } var preload = R._preload = function (src, f) { var img = g.doc.createElement("img"); img.style.cssText = "position:absolute;left:-9999em;top:-9999em"; img.onload = function () { f.call(this); this.onload = null; g.doc.body.removeChild(this); }; img.onerror = function () { g.doc.body.removeChild(this); }; g.doc.body.appendChild(img); img.src = src; }; function clrToString() { return this.hex; } /*\ * Raphael.getRGB [ method ] ** * Parses colour string as RGB object > Parameters - colour (string) colour string in one of formats: # <ul> # <li>Colour name (“<code>red</code>”, “<code>green</code>”, “<code>cornflowerblue</code>”, etc)</li> # <li>#••• — shortened HTML colour: (“<code>#000</code>”, “<code>#fc0</code>”, etc)</li> # <li>#•••••• — full length HTML colour: (“<code>#000000</code>”, “<code>#bd2300</code>”)</li> # <li>rgb(•••, •••, •••) — red, green and blue channels’ values: (“<code>rgb(200, 100, 0)</code>”)</li> # <li>rgb(•••%, •••%, •••%) — same as above, but in %: (“<code>rgb(100%, 175%, 0%)</code>”)</li> # <li>hsb(•••, •••, •••) — hue, saturation and brightness values: (“<code>hsb(0.5, 0.25, 1)</code>”)</li> # <li>hsb(•••%, •••%, •••%) — same as above, but in %</li> # <li>hsl(•••, •••, •••) — same as hsb</li> # <li>hsl(•••%, •••%, •••%) — same as hsb</li> # </ul> = (object) RGB object in format: o { o r (number) red, o g (number) green, o b (number) blue o hex (string) color in HTML/CSS format: #••••••, o error (boolean) true if string can’t be parsed o } \*/ R.getRGB = cacher(function (colour) { if (!colour || !!((colour = Str(colour)).indexOf("-") + 1)) { return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: clrToString}; } if (colour == "none") { return {r: -1, g: -1, b: -1, hex: "none", toString: clrToString}; } !(hsrg[has](colour.toLowerCase().substring(0, 2)) || colour.charAt() == "#") && (colour = toHex(colour)); var res, red, green, blue, opacity, t, values, rgb = colour.match(colourRegExp); if (rgb) { if (rgb[2]) { blue = toInt(rgb[2].substring(5), 16); green = toInt(rgb[2].substring(3, 5), 16); red = toInt(rgb[2].substring(1, 3), 16); } if (rgb[3]) { blue = toInt((t = rgb[3].charAt(3)) + t, 16); green = toInt((t = rgb[3].charAt(2)) + t, 16); red = toInt((t = rgb[3].charAt(1)) + t, 16); } if (rgb[4]) { values = rgb[4][split](commaSpaces); red = toFloat(values[0]); values[0].slice(-1) == "%" && (red *= 2.55); green = toFloat(values[1]); values[1].slice(-1) == "%" && (green *= 2.55); blue = toFloat(values[2]); values[2].slice(-1) == "%" && (blue *= 2.55); rgb[1].toLowerCase().slice(0, 4) == "rgba" && (opacity = toFloat(values[3])); values[3] && values[3].slice(-1) == "%" && (opacity /= 100); } if (rgb[5]) { values = rgb[5][split](commaSpaces); red = toFloat(values[0]); values[0].slice(-1) == "%" && (red *= 2.55); green = toFloat(values[1]); values[1].slice(-1) == "%" && (green *= 2.55); blue = toFloat(values[2]); values[2].slice(-1) == "%" && (blue *= 2.55); (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360); rgb[1].toLowerCase().slice(0, 4) == "hsba" && (opacity = toFloat(values[3])); values[3] && values[3].slice(-1) == "%" && (opacity /= 100); return R.hsb2rgb(red, green, blue, opacity); } if (rgb[6]) { values = rgb[6][split](commaSpaces); red = toFloat(values[0]); values[0].slice(-1) == "%" && (red *= 2.55); green = toFloat(values[1]); values[1].slice(-1) == "%" && (green *= 2.55); blue = toFloat(values[2]); values[2].slice(-1) == "%" && (blue *= 2.55); (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360); rgb[1].toLowerCase().slice(0, 4) == "hsla" && (opacity = toFloat(values[3])); values[3] && values[3].slice(-1) == "%" && (opacity /= 100); return R.hsl2rgb(red, green, blue, opacity); } rgb = {r: red, g: green, b: blue, toString: clrToString}; rgb.hex = "#" + (16777216 | blue | (green << 8) | (red << 16)).toString(16).slice(1); R.is(opacity, "finite") && (rgb.opacity = opacity); return rgb; } return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: clrToString}; }, R); /*\ * Raphael.hsb [ method ] ** * Converts HSB values to hex representation of the colour. > Parameters - h (number) hue - s (number) saturation - b (number) value or brightness = (string) hex representation of the colour. \*/ R.hsb = cacher(function (h, s, b) { return R.hsb2rgb(h, s, b).hex; }); /*\ * Raphael.hsl [ method ] ** * Converts HSL values to hex representation of the colour. > Parameters - h (number) hue - s (number) saturation - l (number) luminosity = (string) hex representation of the colour. \*/ R.hsl = cacher(function (h, s, l) { return R.hsl2rgb(h, s, l).hex; }); /*\ * Raphael.rgb [ method ] ** * Converts RGB values to hex representation of the colour. > Parameters - r (number) red - g (number) green - b (number) blue = (string) hex representation of the colour. \*/ R.rgb = cacher(function (r, g, b) { return "#" + (16777216 | b | (g << 8) | (r << 16)).toString(16).slice(1); }); /*\ * Raphael.getColor [ method ] ** * On each call returns next colour in the spectrum. To reset it back to red call @Raphael.getColor.reset > Parameters - value (number) #optional brightness, default is `0.75` = (string) hex representation of the colour. \*/ R.getColor = function (value) { var start = this.getColor.start = this.getColor.start || {h: 0, s: 1, b: value || .75}, rgb = this.hsb2rgb(start.h, start.s, start.b); start.h += .075; if (start.h > 1) { start.h = 0; start.s -= .2; start.s <= 0 && (this.getColor.start = {h: 0, s: 1, b: start.b}); } return rgb.hex; }; /*\ * Raphael.getColor.reset [ method ] ** * Resets spectrum position for @Raphael.getColor back to red. \*/ R.getColor.reset = function () { delete this.start; }; // http://schepers.cc/getting-to-the-point function catmullRom2bezier(crp, z) { var d = []; for (var i = 0, iLen = crp.length; iLen - 2 * !z > i; i += 2) { var p = [ {x: +crp[i - 2], y: +crp[i - 1]}, {x: +crp[i], y: +crp[i + 1]}, {x: +crp[i + 2], y: +crp[i + 3]}, {x: +crp[i + 4], y: +crp[i + 5]} ]; if (z) { if (!i) { p[0] = {x: +crp[iLen - 2], y: +crp[iLen - 1]}; } else if (iLen - 4 == i) { p[3] = {x: +crp[0], y: +crp[1]}; } else if (iLen - 2 == i) { p[2] = {x: +crp[0], y: +crp[1]}; p[3] = {x: +crp[2], y: +crp[3]}; } } else { if (iLen - 4 == i) { p[3] = p[2]; } else if (!i) { p[0] = {x: +crp[i], y: +crp[i + 1]}; } } d.push(["C", (-p[0].x + 6 * p[1].x + p[2].x) / 6, (-p[0].y + 6 * p[1].y + p[2].y) / 6, (p[1].x + 6 * p[2].x - p[3].x) / 6, (p[1].y + 6*p[2].y - p[3].y) / 6, p[2].x, p[2].y ]); } return d; } /*\ * Raphael.parsePathString [ method ] ** * Utility method ** * Parses given path string into an array of arrays of path segments. > Parameters - pathString (string|array) path string or array of segments (in the last case it will be returned straight away) = (array) array of segments. \*/ R.parsePathString = function (pathString) { if (!pathString) { return null; } var pth = paths(pathString); if (pth.arr) { return pathClone(pth.arr); } var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, r: 4, q: 4, s: 4, t: 2, v: 1, z: 0}, data = []; if (R.is(pathString, array) && R.is(pathString[0], array)) { // rough assumption data = pathClone(pathString); } if (!data.length) { Str(pathString).replace(pathCommand, function (a, b, c) { var params = [], name = b.toLowerCase(); c.replace(pathValues, function (a, b) { b && params.push(+b); }); if (name == "m" && params.length > 2) { data.push([b][concat](params.splice(0, 2))); name = "l"; b = b == "m" ? "l" : "L"; } if (name == "r") { data.push([b][concat](params)); } else while (params.length >= paramCounts[name]) { data.push([b][concat](params.splice(0, paramCounts[name]))); if (!paramCounts[name]) { break; } } }); } data.toString = R._path2string; pth.arr = pathClone(data); return data; }; /*\ * Raphael.parseTransformString [ method ] ** * Utility method ** * Parses given path string into an array of transformations. > Parameters - TString (string|array) transform string or array of transformations (in the last case it will be returned straight away) = (array) array of transformations. \*/ R.parseTransformString = cacher(function (TString) { if (!TString) { return null; } var paramCounts = {r: 3, s: 4, t: 2, m: 6}, data = []; if (R.is(TString, array) && R.is(TString[0], array)) { // rough assumption data = pathClone(TString); } if (!data.length) { Str(TString).replace(tCommand, function (a, b, c) { var params = [], name = lowerCase.call(b); c.replace(pathValues, function (a, b) { b && params.push(+b); }); data.push([b][concat](params)); }); } data.toString = R._path2string; return data; }); // PATHS var paths = function (ps) { var p = paths.ps = paths.ps || {}; if (p[ps]) { p[ps].sleep = 100; } else { p[ps] = { sleep: 100 }; } setTimeout(function () { for (var key in p) if (p[has](key) && key != ps) { p[key].sleep--; !p[key].sleep && delete p[key]; } }); return p[ps]; }; /*\ * Raphael.findDotsAtSegment [ method ] ** * Utility method ** * Find dot coordinates on the given cubic bezier curve at the given t. > Parameters - p1x (number) x of the first point of the curve - p1y (number) y of the first point of the curve - c1x (number) x of the first anchor of the curve - c1y (number) y of the first anchor of the curve - c2x (number) x of the second anchor of the curve - c2y (number) y of the second anchor of the curve - p2x (number) x of the second point of the curve - p2y (number) y of the second point of the curve - t (number) position on the curve (0..1) = (object) point information in format: o { o x: (number) x coordinate of the point o y: (number) y coordinate of the point o m: { o x: (number) x coordinate of the left anchor o y: (number) y coordinate of the left anchor o } o n: { o x: (number) x coordinate of the right anchor o y: (number) y coordinate of the right anchor o } o start: { o x: (number) x coordinate of the start of the curve o y: (number) y coordinate of the start of the curve o } o end: { o x: (number) x coordinate of the end of the curve o y: (number) y coordinate of the end of the curve o } o alpha: (number) angle of the curve derivative at the point o } \*/ R.findDotsAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) { var t1 = 1 - t, t13 = pow(t1, 3), t12 = pow(t1, 2), t2 = t * t, t3 = t2 * t, x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x, y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y, mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x), my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y), nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x), ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y), ax = t1 * p1x + t * c1x, ay = t1 * p1y + t * c1y, cx = t1 * c2x + t * p2x, cy = t1 * c2y + t * p2y, alpha = (90 - math.atan2(mx - nx, my - ny) * 180 / PI); (mx > nx || my < ny) && (alpha += 180); return { x: x, y: y, m: {x: mx, y: my}, n: {x: nx, y: ny}, start: {x: ax, y: ay}, end: {x: cx, y: cy}, alpha: alpha }; }; /*\ * Raphael.bezierBBox [ method ] ** * Utility method ** * Return bounding box of a given cubic bezier curve > Parameters - p1x (number) x of the first point of the curve - p1y (number) y of the first point of the curve - c1x (number) x of the first anchor of the curve - c1y (number) y of the first anchor of the curve - c2x (number) x of the second anchor of the curve - c2y (number) y of the second anchor of the curve - p2x (number) x of the second point of the curve - p2y (number) y of the second point of the curve * or - bez (array) array of six points for bezier curve = (object) point information in format: o { o min: { o x: (number) x coordinate of the left point o y: (number) y coordinate of the top point o } o max: { o x: (number) x coordinate of the right point o y: (number) y coordinate of the bottom point o } o } \*/ R.bezierBBox = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) { if (!R.is(p1x, "array")) { p1x = [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y]; } var bbox = curveDim.apply(null, p1x); return { x: bbox.min.x, y: bbox.min.y, x2: bbox.max.x, y2: bbox.max.y, width: bbox.max.x - bbox.min.x, height: bbox.max.y - bbox.min.y }; }; /*\ * Raphael.isPointInsideBBox [ method ] ** * Utility method ** * Returns `true` if given point is inside bounding boxes. > Parameters - bbox (string) bounding box - x (string) x coordinate of the point - y (string) y coordinate of the point = (boolean) `true` if point inside \*/ R.isPointInsideBBox = function (bbox, x, y) { return x >= bbox.x && x <= bbox.x2 && y >= bbox.y && y <= bbox.y2; }; /*\ * Raphael.isBBoxIntersect [ method ] ** * Utility method ** * Returns `true` if two bounding boxes intersect > Parameters - bbox1 (string) first bounding box - bbox2 (string) second bounding box = (boolean) `true` if they intersect \*/ R.isBBoxIntersect = function (bbox1, bbox2) { var i = R.isPointInsideBBox; return i(bbox2, bbox1.x, bbox1.y) || i(bbox2, bbox1.x2, bbox1.y) || i(bbox2, bbox1.x, bbox1.y2) || i(bbox2, bbox1.x2, bbox1.y2) || i(bbox1, bbox2.x, bbox2.y) || i(bbox1, bbox2.x2, bbox2.y) || i(bbox1, bbox2.x, bbox2.y2) || i(bbox1, bbox2.x2, bbox2.y2) || (bbox1.x < bbox2.x2 && bbox1.x > bbox2.x || bbox2.x < bbox1.x2 && bbox2.x > bbox1.x) && (bbox1.y < bbox2.y2 && bbox1.y > bbox2.y || bbox2.y < bbox1.y2 && bbox2.y > bbox1.y); }; function base3(t, p1, p2, p3, p4) { var t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4, t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3; return t * t2 - 3 * p1 + 3 * p2; } function bezlen(x1, y1, x2, y2, x3, y3, x4, y4, z) { if (z == null) { z = 1; } z = z > 1 ? 1 : z < 0 ? 0 : z; var z2 = z / 2, n = 12, Tvalues = [-0.1252,0.1252,-0.3678,0.3678,-0.5873,0.5873,-0.7699,0.7699,-0.9041,0.9041,-0.9816,0.9816], Cvalues = [0.2491,0.2491,0.2335,0.2335,0.2032,0.2032,0.1601,0.1601,0.1069,0.1069,0.0472,0.0472], sum = 0; for (var i = 0; i < n; i++) { var ct = z2 * Tvalues[i] + z2, xbase = base3(ct, x1, x2, x3, x4), ybase = base3(ct, y1, y2, y3, y4), comb = xbase * xbase + ybase * ybase; sum += Cvalues[i] * math.sqrt(comb); } return z2 * sum; } function getTatLen(x1, y1, x2, y2, x3, y3, x4, y4, ll) { if (ll < 0 || bezlen(x1, y1, x2, y2, x3, y3, x4, y4) < ll) { return; } var t = 1, step = t / 2, t2 = t - step, l, e = .01; l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2); while (abs(l - ll) > e) { step /= 2; t2 += (l < ll ? 1 : -1) * step; l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2); } return t2; } function intersect(x1, y1, x2, y2, x3, y3, x4, y4) { if ( mmax(x1, x2) < mmin(x3, x4) || mmin(x1, x2) > mmax(x3, x4) || mmax(y1, y2) < mmin(y3, y4) || mmin(y1, y2) > mmax(y3, y4) ) { return; } var nx = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4), ny = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4), denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); if (!denominator) { return; } var px = nx / denominator, py = ny / denominator, px2 = +px.toFixed(2), py2 = +py.toFixed(2); if ( px2 < +mmin(x1, x2).toFixed(2) || px2 > +mmax(x1, x2).toFixed(2) || px2 < +mmin(x3, x4).toFixed(2) || px2 > +mmax(x3, x4).toFixed(2) || py2 < +mmin(y1, y2).toFixed(2) || py2 > +mmax(y1, y2).toFixed(2) || py2 < +mmin(y3, y4).toFixed(2) || py2 > +mmax(y3, y4).toFixed(2) ) { return; } return {x: px, y: py}; } function inter(bez1, bez2) { return interHelper(bez1, bez2); } function interCount(bez1, bez2) { return interHelper(bez1, bez2, 1); } function interHelper(bez1, bez2, justCount) { var bbox1 = R.bezierBBox(bez1), bbox2 = R.bezierBBox(bez2); if (!R.isBBoxIntersect(bbox1, bbox2)) { return justCount ? 0 : []; } var l1 = bezlen.apply(0, bez1), l2 = bezlen.apply(0, bez2), n1 = mmax(~~(l1 / 5), 1), n2 = mmax(~~(l2 / 5), 1), dots1 = [], dots2 = [], xy = {}, res = justCount ? 0 : []; for (var i = 0; i < n1 + 1; i++) { var p = R.findDotsAtSegment.apply(R, bez1.concat(i / n1)); dots1.push({x: p.x, y: p.y, t: i / n1}); } for (i = 0; i < n2 + 1; i++) { p = R.findDotsAtSegment.apply(R, bez2.concat(i / n2)); dots2.push({x: p.x, y: p.y, t: i / n2}); } for (i = 0; i < n1; i++) { for (var j = 0; j < n2; j++) { var di = dots1[i], di1 = dots1[i + 1], dj = dots2[j], dj1 = dots2[j + 1], ci = abs(di1.x - di.x) < .001 ? "y" : "x", cj = abs(dj1.x - dj.x) < .001 ? "y" : "x", is = intersect(di.x, di.y, di1.x, di1.y, dj.x, dj.y, dj1.x, dj1.y); if (is) { if (xy[is.x.toFixed(4)] == is.y.toFixed(4)) { continue; } xy[is.x.toFixed(4)] = is.y.toFixed(4); var t1 = di.t + abs((is[ci] - di[ci]) / (di1[ci] - di[ci])) * (di1.t - di.t), t2 = dj.t + abs((is[cj] - dj[cj]) / (dj1[cj] - dj[cj])) * (dj1.t - dj.t); if (t1 >= 0 && t1 <= 1.001 && t2 >= 0 && t2 <= 1.001) { if (justCount) { res++; } else { res.push({ x: is.x, y: is.y, t1: mmin(t1, 1), t2: mmin(t2, 1) }); } } } } } return res; } /*\ * Raphael.pathIntersection [ method ] ** * Utility method ** * Finds intersections of two paths > Parameters - path1 (string) path string - path2 (string) path string = (array) dots of intersection o [ o { o x: (number) x coordinate of the point o y: (number) y coordinate of the point o t1: (number) t value for segment of path1 o t2: (number) t value for segment of path2 o segment1: (number) order number for segment of path1 o segment2: (number) order number for segment of path2 o bez1: (array) eight coordinates representing beziér curve for the segment of path1 o bez2: (array) eight coordinates representing beziér curve for the segment of path2 o } o ] \*/ R.pathIntersection = function (path1, path2) { return interPathHelper(path1, path2); }; R.pathIntersectionNumber = function (path1, path2) { return interPathHelper(path1, path2, 1); }; function interPathHelper(path1, path2, justCount) { path1 = R._path2curve(path1); path2 = R._path2curve(path2); var x1, y1, x2, y2, x1m, y1m, x2m, y2m, bez1, bez2, res = justCount ? 0 : []; for (var i = 0, ii = path1.length; i < ii; i++) { var pi = path1[i]; if (pi[0] == "M") { x1 = x1m = pi[1]; y1 = y1m = pi[2]; } else { if (pi[0] == "C") { bez1 = [x1, y1].concat(pi.slice(1)); x1 = bez1[6]; y1 = bez1[7]; } else { bez1 = [x1, y1, x1, y1, x1m, y1m, x1m, y1m]; x1 = x1m; y1 = y1m; } for (var j = 0, jj = path2.length; j < jj; j++) { var pj = path2[j]; if (pj[0] == "M") { x2 = x2m = pj[1]; y2 = y2m = pj[2]; } else { if (pj[0] == "C") { bez2 = [x2, y2].concat(pj.slice(1)); x2 = bez2[6]; y2 = bez2[7]; } else { bez2 = [x2, y2, x2, y2, x2m, y2m, x2m, y2m]; x2 = x2m; y2 = y2m; } var intr = interHelper(bez1, bez2, justCount); if (justCount) { res += intr; } else { for (var k = 0, kk = intr.length; k < kk; k++) { intr[k].segment1 = i; intr[k].segment2 = j; intr[k].bez1 = bez1; intr[k].bez2 = bez2; } res = res.concat(intr); } } } } } return res; } /*\ * Raphael.isPointInsidePath [ method ] ** * Utility method ** * Returns `true` if given point is inside a given closed path. > Parameters - path (string) path string - x (number) x of the point - y (number) y of the point = (boolean) true, if point is inside the path \*/ R.isPointInsidePath = function (path, x, y) { var bbox = R.pathBBox(path); return R.isPointInsideBBox(bbox, x, y) && interPathHelper(path, [["M", x, y], ["H", bbox.x2 + 10]], 1) % 2 == 1; }; R._removedFactory = function (methodname) { return function () { eve("raphael.log", null, "Rapha\xebl: you are calling to method \u201c" + methodname + "\u201d of removed object", methodname); }; }; /*\ * Raphael.pathBBox [ method ] ** * Utility method ** * Return bounding box of a given path > Parameters - path (string) path string = (object) bounding box o { o x: (number) x coordinate of the left top point of the box o y: (number) y coordinate of the left top point of the box o x2: (number) x coordinate of the right bottom point of the box o y2: (number) y coordinate of the right bottom point of the box o width: (number) width of the box o height: (number) height of the box o cx: (number) x coordinate of the center of the box o cy: (number) y coordinate of the center of the box o } \*/ var pathDimensions = R.pathBBox = function (path) { var pth = paths(path); if (pth.bbox) { return clone(pth.bbox); } if (!path) { return {x: 0, y: 0, width: 0, height: 0, x2: 0, y2: 0}; } path = path2curve(path); var x = 0, y = 0, X = [], Y = [], p; for (var i = 0, ii = path.length; i < ii; i++) { p = path[i]; if (p[0] == "M") { x = p[1]; y = p[2]; X.push(x); Y.push(y); } else { var dim = curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]); X = X[concat](dim.min.x, dim.max.x); Y = Y[concat](dim.min.y, dim.max.y); x = p[5]; y = p[6]; } } var xmin = mmin[apply](0, X), ymin = mmin[apply](0, Y), xmax = mmax[apply](0, X), ymax = mmax[apply](0, Y), width = xmax - xmin, height = ymax - ymin, bb = { x: xmin, y: ymin, x2: xmax, y2: ymax, width: width, height: height, cx: xmin + width / 2, cy: ymin + height / 2 }; pth.bbox = clone(bb); return bb; }, pathClone = function (pathArray) { var res = clone(pathArray); res.toString = R._path2string; return res; }, pathToRelative = R._pathToRelative = function (pathArray) { var pth = paths(pathArray); if (pth.rel) { return pathClone(pth.rel); } if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption pathArray = R.parsePathString(pathArray); } var res = [], x = 0, y = 0, mx = 0, my = 0, start = 0; if (pathArray[0][0] == "M") { x = pathArray[0][1]; y = pathArray[0][2]; mx = x; my = y; start++; res.push(["M", x, y]); } for (var i = start, ii = pathArray.length; i < ii; i++) { var r = res[i] = [], pa = pathArray[i]; if (pa[0] != lowerCase.call(pa[0])) { r[0] = lowerCase.call(pa[0]); switch (r[0]) { case "a": r[1] = pa[1]; r[2] = pa[2]; r[3] = pa[3]; r[4] = pa[4]; r[5] = pa[5]; r[6] = +(pa[6] - x).toFixed(3); r[7] = +(pa[7] - y).toFixed(3); break; case "v": r[1] = +(pa[1] - y).toFixed(3); break; case "m": mx = pa[1]; my = pa[2]; default: for (var j = 1, jj = pa.length; j < jj; j++) { r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3); } } } else { r = res[i] = []; if (pa[0] == "m") { mx = pa[1] + x; my = pa[2] + y; } for (var k = 0, kk = pa.length; k < kk; k++) { res[i][k] = pa[k]; } } var len = res[i].length; switch (res[i][0]) { case "z": x = mx; y = my; break; case "h": x += +res[i][len - 1]; break; case "v": y += +res[i][len - 1]; break; default: x += +res[i][len - 2]; y += +res[i][len - 1]; } } res.toString = R._path2string; pth.rel = pathClone(res); return res; }, pathToAbsolute = R._pathToAbsolute = function (pathArray) { var pth = paths(pathArray); if (pth.abs) { return pathClone(pth.abs); } if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption pathArray = R.parsePathString(pathArray); } if (!pathArray || !pathArray.length) { return [["M", 0, 0]]; } var res = [], x = 0, y = 0, mx = 0, my = 0, start = 0; if (pathArray[0][0] == "M") { x = +pathArray[0][1]; y = +pathArray[0][2]; mx = x; my = y; start++; res[0] = ["M", x, y]; } var crz = pathArray.length == 3 && pathArray[0][0] == "M" && pathArray[1][0].toUpperCase() == "R" && pathArray[2][0].toUpperCase() == "Z"; for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) { res.push(r = []); pa = pathArray[i]; if (pa[0] != upperCase.call(pa[0])) { r[0] = upperCase.call(pa[0]); switch (r[0]) { case "A": r[1] = pa[1]; r[2] = pa[2]; r[3] = pa[3]; r[4] = pa[4]; r[5] = pa[5]; r[6] = +(pa[6] + x); r[7] = +(pa[7] + y); break; case "V": r[1] = +pa[1] + y; break; case "H": r[1] = +pa[1] + x; break; case "R": var dots = [x, y][concat](pa.slice(1)); for (var j = 2, jj = dots.length; j < jj; j++) { dots[j] = +dots[j] + x; dots[++j] = +dots[j] + y; } res.pop(); res = res[concat](catmullRom2bezier(dots, crz)); break; case "M": mx = +pa[1] + x; my = +pa[2] + y; default: for (j = 1, jj = pa.length; j < jj; j++) { r[j] = +pa[j] + ((j % 2) ? x : y); } } } else if (pa[0] == "R") { dots = [x, y][concat](pa.slice(1)); res.pop(); res = res[concat](catmullRom2bezier(dots, crz)); r = ["R"][concat](pa.slice(-2)); } else { for (var k = 0, kk = pa.length; k < kk; k++) { r[k] = pa[k]; } } switch (r[0]) { case "Z": x = mx; y = my; break; case "H": x = r[1]; break; case "V": y = r[1]; break; case "M": mx = r[r.length - 2]; my = r[r.length - 1]; default: x = r[r.length - 2]; y = r[r.length - 1]; } } res.toString = R._path2string; pth.abs = pathClone(res); return res; }, l2c = function (x1, y1, x2, y2) { return [x1, y1, x2, y2, x2, y2]; }, q2c = function (x1, y1, ax, ay, x2, y2) { var _13 = 1 / 3, _23 = 2 / 3; return [ _13 * x1 + _23 * ax, _13 * y1 + _23 * ay, _13 * x2 + _23 * ax, _13 * y2 + _23 * ay, x2, y2 ]; }, a2c = function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) { // for more information of where this math came from visit: // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes var _120 = PI * 120 / 180, rad = PI / 180 * (+angle || 0), res = [], xy, rotate = cacher(function (x, y, rad) { var X = x * math.cos(rad) - y * math.sin(rad), Y = x * math.sin(rad) + y * math.cos(rad); return {x: X, y: Y}; }); if (!recursive) { xy = rotate(x1, y1, -rad); x1 = xy.x; y1 = xy.y; xy = rotate(x2, y2, -rad); x2 = xy.x; y2 = xy.y; var cos = math.cos(PI / 180 * angle), sin = math.sin(PI / 180 * angle), x = (x1 - x2) / 2, y = (y1 - y2) / 2; var h = (x * x) / (rx * rx) + (y * y) / (ry * ry); if (h > 1) { h = math.sqrt(h); rx = h * rx; ry = h * ry; } var rx2 = rx * rx, ry2 = ry * ry, k = (large_arc_flag == sweep_flag ? -1 : 1) * math.sqrt(abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))), cx = k * rx * y / ry + (x1 + x2) / 2, cy = k * -ry * x / rx + (y1 + y2) / 2, f1 = math.asin(((y1 - cy) / ry).toFixed(9)), f2 = math.asin(((y2 - cy) / ry).toFixed(9)); f1 = x1 < cx ? PI - f1 : f1; f2 = x2 < cx ? PI - f2 : f2; f1 < 0 && (f1 = PI * 2 + f1); f2 < 0 && (f2 = PI * 2 + f2); if (sweep_flag && f1 > f2) { f1 = f1 - PI * 2; } if (!sweep_flag && f2 > f1) { f2 = f2 - PI * 2; } } else { f1 = recursive[0]; f2 = recursive[1]; cx = recursive[2]; cy = recursive[3]; } var df = f2 - f1; if (abs(df) > _120) { var f2old = f2, x2old = x2, y2old = y2; f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1); x2 = cx + rx * math.cos(f2); y2 = cy + ry * math.sin(f2); res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]); } df = f2 - f1; var c1 = math.cos(f1), s1 = math.sin(f1), c2 = math.cos(f2), s2 = math.sin(f2), t = math.tan(df / 4), hx = 4 / 3 * rx * t, hy = 4 / 3 * ry * t, m1 = [x1, y1], m2 = [x1 + hx * s1, y1 - hy * c1], m3 = [x2 + hx * s2, y2 - hy * c2], m4 = [x2, y2]; m2[0] = 2 * m1[0] - m2[0]; m2[1] = 2 * m1[1] - m2[1]; if (recursive) { return [m2, m3, m4][concat](res); } else { res = [m2, m3, m4][concat](res).join()[split](","); var newres = []; for (var i = 0, ii = res.length; i < ii; i++) { newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x; } return newres; } }, findDotAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) { var t1 = 1 - t; return { x: pow(t1, 3) * p1x + pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow(t, 3) * p2x, y: pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y }; }, curveDim = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) { var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x), b = 2 * (c1x - p1x) - 2 * (c2x - c1x), c = p1x - c1x, t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a, t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a, y = [p1y, p2y], x = [p1x, p2x], dot; abs(t1) > "1e12" && (t1 = .5); abs(t2) > "1e12" && (t2 = .5); if (t1 > 0 && t1 < 1) { dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1); x.push(dot.x); y.push(dot.y); } if (t2 > 0 && t2 < 1) { dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2); x.push(dot.x); y.push(dot.y); } a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y); b = 2 * (c1y - p1y) - 2 * (c2y - c1y); c = p1y - c1y; t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a; t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a; abs(t1) > "1e12" && (t1 = .5); abs(t2) > "1e12" && (t2 = .5); if (t1 > 0 && t1 < 1) { dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1); x.push(dot.x); y.push(dot.y); } if (t2 > 0 && t2 < 1) { dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2); x.push(dot.x); y.push(dot.y); } return { min: {x: mmin[apply](0, x), y: mmin[apply](0, y)}, max: {x: mmax[apply](0, x), y: mmax[apply](0, y)} }; }), path2curve = R._path2curve = cacher(function (path, path2) { var pth = !path2 && paths(path); if (!path2 && pth.curve) { return pathClone(pth.curve); } var p = pathToAbsolute(path), p2 = path2 && pathToAbsolute(path2), attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null}, attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null}, processPath = function (path, d, pcom) { var nx, ny; if (!path) { return ["C", d.x, d.y, d.x, d.y, d.x, d.y]; } !(path[0] in {T:1, Q:1}) && (d.qx = d.qy = null); switch (path[0]) { case "M": d.X = path[1]; d.Y = path[2]; break; case "A": path = ["C"][concat](a2c[apply](0, [d.x, d.y][concat](path.slice(1)))); break; case "S": if (pcom == "C" || pcom == "S") { // In "S" case we have to take into account, if the previous command is C/S. nx = d.x * 2 - d.bx; // And reflect the previous ny = d.y * 2 - d.by; // command's control point relative to the current point. } else { // or some else or nothing nx = d.x; ny = d.y; } path = ["C", nx, ny][concat](path.slice(1)); break; case "T": if (pcom == "Q" || pcom == "T") { // In "T" case we have to take into account, if the previous command is Q/T. d.qx = d.x * 2 - d.qx; // And make a reflection similar d.qy = d.y * 2 - d.qy; // to case "S". } else { // or something else or nothing d.qx = d.x; d.qy = d.y; } path = ["C"][concat](q2c(d.x, d.y, d.qx, d.qy, path[1], path[2])); break; case "Q": d.qx = path[1]; d.qy = path[2]; path = ["C"][concat](q2c(d.x, d.y, path[1], path[2], path[3], path[4])); break; case "L": path = ["C"][concat](l2c(d.x, d.y, path[1], path[2])); break; case "H": path = ["C"][concat](l2c(d.x, d.y, path[1], d.y)); break; case "V": path = ["C"][concat](l2c(d.x, d.y, d.x, path[1])); break; case "Z": path = ["C"][concat](l2c(d.x, d.y, d.X, d.Y)); break; } return path; }, fixArc = function (pp, i) { if (pp[i].length > 7) { pp[i].shift(); var pi = pp[i]; while (pi.length) { pp.splice(i++, 0, ["C"][concat](pi.splice(0, 6))); } pp.splice(i, 1); ii = mmax(p.length, p2 && p2.length || 0); } }, fixM = function (path1, path2, a1, a2, i) { if (path1 && path2 && path1[i][0] == "M" && path2[i][0] != "M") { path2.splice(i, 0, ["M", a2.x, a2.y]); a1.bx = 0; a1.by = 0; a1.x = path1[i][1]; a1.y = path1[i][2]; ii = mmax(p.length, p2 && p2.length || 0); } }; for (var i = 0, ii = mmax(p.length, p2 && p2.length || 0); i < ii; i++) { p[i] = processPath(p[i], attrs); fixArc(p, i); p2 && (p2[i] = processPath(p2[i], attrs2)); p2 && fixArc(p2, i); fixM(p, p2, attrs, attrs2, i); fixM(p2, p, attrs2, attrs, i); var seg = p[i], seg2 = p2 && p2[i], seglen = seg.length, seg2len = p2 && seg2.length; attrs.x = seg[seglen - 2]; attrs.y = seg[seglen - 1]; attrs.bx = toFloat(seg[seglen - 4]) || attrs.x; attrs.by = toFloat(seg[seglen - 3]) || attrs.y; attrs2.bx = p2 && (toFloat(seg2[seg2len - 4]) || attrs2.x); attrs2.by = p2 && (toFloat(seg2[seg2len - 3]) || attrs2.y); attrs2.x = p2 && seg2[seg2len - 2]; attrs2.y = p2 && seg2[seg2len - 1]; } if (!p2) { pth.curve = pathClone(p); } return p2 ? [p, p2] : p; }, null, pathClone), parseDots = R._parseDots = cacher(function (gradient) { var dots = []; for (var i = 0, ii = gradient.length; i < ii; i++) { var dot = {}, par = gradient[i].match(/^([^:]*):?([\d\.]*)/); dot.color = R.getRGB(par[1]); if (dot.color.error) { return null; } dot.color = dot.color.hex; par[2] && (dot.offset = par[2] + "%"); dots.push(dot); } for (i = 1, ii = dots.length - 1; i < ii; i++) { if (!dots[i].offset) { var start = toFloat(dots[i - 1].offset || 0), end = 0; for (var j = i + 1; j < ii; j++) { if (dots[j].offset) { end = dots[j].offset; break; } } if (!end) { end = 100; j = ii; } end = toFloat(end); var d = (end - start) / (j - i + 1); for (; i < j; i++) { start += d; dots[i].offset = start + "%"; } } } return dots; }), tear = R._tear = function (el, paper) { el == paper.top && (paper.top = el.prev); el == paper.bottom && (paper.bottom = el.next); el.next && (el.next.prev = el.prev); el.prev && (el.prev.next = el.next); }, tofront = R._tofront = function (el, paper) { if (paper.top === el) { return; } tear(el, paper); el.next = null; el.prev = paper.top; paper.top.next = el; paper.top = el; }, toback = R._toback = function (el, paper) { if (paper.bottom === el) { return; } tear(el, paper); el.next = paper.bottom; el.prev = null; paper.bottom.prev = el; paper.bottom = el; }, insertafter = R._insertafter = function (el, el2, paper) { tear(el, paper); el2 == paper.top && (paper.top = el); el2.next && (el2.next.prev = el); el.next = el2.next; el.prev = el2; el2.next = el; }, insertbefore = R._insertbefore = function (el, el2, paper) { tear(el, paper); el2 == paper.bottom && (paper.bottom = el); el2.prev && (el2.prev.next = el); el.prev = el2.prev; el2.prev = el; el.next = el2; }, /*\ * Raphael.toMatrix [ method ] ** * Utility method ** * Returns matrix of transformations applied to a given path > Parameters - path (string) path string - transform (string|array) transformation string = (object) @Matrix \*/ toMatrix = R.toMatrix = function (path, transform) { var bb = pathDimensions(path), el = { _: { transform: E }, getBBox: function () { return bb; } }; extractTransform(el, transform); return el.matrix; }, /*\ * Raphael.transformPath [ method ] ** * Utility method ** * Returns path transformed by a given transformation > Parameters - path (string) path string - transform (string|array) transformation string = (string) path \*/ transformPath = R.transformPath = function (path, transform) { return mapPath(path, toMatrix(path, transform)); }, extractTransform = R._extractTransform = function (el, tstr) { if (tstr == null) { return el._.transform; } tstr = Str(tstr).replace(/\.{3}|\u2026/g, el._.transform || E); var tdata = R.parseTransformString(tstr), deg = 0, dx = 0, dy = 0, sx = 1, sy = 1, _ = el._, m = new Matrix; _.transform = tdata || []; if (tdata) { for (var i = 0, ii = tdata.length; i < ii; i++) { var t = tdata[i], tlen = t.length, command = Str(t[0]).toLowerCase(), absolute = t[0] != command, inver = absolute ? m.invert() : 0, x1, y1, x2, y2, bb; if (command == "t" && tlen == 3) { if (absolute) { x1 = inver.x(0, 0); y1 = inver.y(0, 0); x2 = inver.x(t[1], t[2]); y2 = inver.y(t[1], t[2]); m.translate(x2 - x1, y2 - y1); } else { m.translate(t[1], t[2]); } } else if (command == "r") { if (tlen == 2) { bb = bb || el.getBBox(1); m.rotate(t[1], bb.x + bb.width / 2, bb.y + bb.height / 2); deg += t[1]; } else if (tlen == 4) { if (absolute) { x2 = inver.x(t[2], t[3]); y2 = inver.y(t[2], t[3]); m.rotate(t[1], x2, y2); } else { m.rotate(t[1], t[2], t[3]); } deg += t[1]; } } else if (command == "s") { if (tlen == 2 || tlen == 3) { bb = bb || el.getBBox(1); m.scale(t[1], t[tlen - 1], bb.x + bb.width / 2, bb.y + bb.height / 2); sx *= t[1]; sy *= t[tlen - 1]; } else if (tlen == 5) { if (absolute) { x2 = inver.x(t[3], t[4]); y2 = inver.y(t[3], t[4]); m.scale(t[1], t[2], x2, y2); } else { m.scale(t[1], t[2], t[3], t[4]); } sx *= t[1]; sy *= t[2]; } } else if (command == "m" && tlen == 7) { m.add(t[1], t[2], t[3], t[4], t[5], t[6]); } _.dirtyT = 1; el.matrix = m; } } /*\ * Element.matrix [ property (object) ] ** * Keeps @Matrix object, which represents element transformation \*/ el.matrix = m; _.sx = sx; _.sy = sy; _.deg = deg; _.dx = dx = m.e; _.dy = dy = m.f; if (sx == 1 && sy == 1 && !deg && _.bbox) { _.bbox.x += +dx; _.bbox.y += +dy; } else { _.dirtyT = 1; } }, getEmpty = function (item) { var l = item[0]; switch (l.toLowerCase()) { case "t": return [l, 0, 0]; case "m": return [l, 1, 0, 0, 1, 0, 0]; case "r": if (item.length == 4) { return [l, 0, item[2], item[3]]; } else { return [l, 0]; } case "s": if (item.length == 5) { return [l, 1, 1, item[3], item[4]]; } else if (item.length == 3) { return [l, 1, 1]; } else { return [l, 1]; } } }, equaliseTransform = R._equaliseTransform = function (t1, t2) { t2 = Str(t2).replace(/\.{3}|\u2026/g, t1); t1 = R.parseTransformString(t1) || []; t2 = R.parseTransformString(t2) || []; var maxlength = mmax(t1.length, t2.length), from = [], to = [], i = 0, j, jj, tt1, tt2; for (; i < maxlength; i++) { tt1 = t1[i] || getEmpty(t2[i]); tt2 = t2[i] || getEmpty(tt1); if ((tt1[0] != tt2[0]) || (tt1[0].toLowerCase() == "r" && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) || (tt1[0].toLowerCase() == "s" && (tt1[3] != tt2[3] || tt1[4] != tt2[4])) ) { return; } from[i] = []; to[i] = []; for (j = 0, jj = mmax(tt1.length, tt2.length); j < jj; j++) { j in tt1 && (from[i][j] = tt1[j]); j in tt2 && (to[i][j] = tt2[j]); } } return { from: from, to: to }; }; R._getContainer = function (x, y, w, h) { var container; container = h == null && !R.is(x, "object") ? g.doc.getElementById(x) : x; if (container == null) { return; } if (container.tagName) { if (y == null) { return { container: container, width: container.style.pixelWidth || container.offsetWidth, height: container.style.pixelHeight || container.offsetHeight }; } else { return { container: container, width: y, height: w }; } } return { container: 1, x: x, y: y, width: w, height: h }; }; /*\ * Raphael.pathToRelative [ method ] ** * Utility method ** * Converts path to relative form > Parameters - pathString (string|array) path string or array of segments = (array) array of segments. \*/ R.pathToRelative = pathToRelative; R._engine = {}; /*\ * Raphael.path2curve [ method ] ** * Utility method ** * Converts path to a new path where all segments are cubic bezier curves. > Parameters - pathString (string|array) path string or array of segments = (array) array of segments. \*/ R.path2curve = path2curve; /*\ * Raphael.matrix [ method ] ** * Utility method ** * Returns matrix based on given parameters. > Parameters - a (number) - b (number) - c (number) - d (number) - e (number) - f (number) = (object) @Matrix \*/ R.matrix = function (a, b, c, d, e, f) { return new Matrix(a, b, c, d, e, f); }; function Matrix(a, b, c, d, e, f) { if (a != null) { this.a = +a; this.b = +b; this.c = +c; this.d = +d; this.e = +e; this.f = +f; } else { this.a = 1; this.b = 0; this.c = 0; this.d = 1; this.e = 0; this.f = 0; } } (function (matrixproto) { /*\ * Matrix.add [ method ] ** * Adds given matrix to existing one. > Parameters - a (number) - b (number) - c (number) - d (number) - e (number) - f (number) or - matrix (object) @Matrix \*/ matrixproto.add = function (a, b, c, d, e, f) { var out = [[], [], []], m = [[this.a, this.c, this.e], [this.b, this.d, this.f], [0, 0, 1]], matrix = [[a, c, e], [b, d, f], [0, 0, 1]], x, y, z, res; if (a && a instanceof Matrix) { matrix = [[a.a, a.c, a.e], [a.b, a.d, a.f], [0, 0, 1]]; } for (x = 0; x < 3; x++) { for (y = 0; y < 3; y++) { res = 0; for (z = 0; z < 3; z++) { res += m[x][z] * matrix[z][y]; } out[x][y] = res; } } this.a = out[0][0]; this.b = out[1][0]; this.c = out[0][1]; this.d = out[1][1]; this.e = out[0][2]; this.f = out[1][2]; }; /*\ * Matrix.invert [ method ] ** * Returns inverted version of the matrix = (object) @Matrix \*/ matrixproto.invert = function () { var me = this, x = me.a * me.d - me.b * me.c; return new Matrix(me.d / x, -me.b / x, -me.c / x, me.a / x, (me.c * me.f - me.d * me.e) / x, (me.b * me.e - me.a * me.f) / x); }; /*\ * Matrix.clone [ method ] ** * Returns copy of the matrix = (object) @Matrix \*/ matrixproto.clone = function () { return new Matrix(this.a, this.b, this.c, this.d, this.e, this.f); }; /*\ * Matrix.translate [ method ] ** * Translate the matrix > Parameters - x (number) - y (number) \*/ matrixproto.translate = function (x, y) { this.add(1, 0, 0, 1, x, y); }; /*\ * Matrix.scale [ method ] ** * Scales the matrix > Parameters - x (number) - y (number) #optional - cx (number) #optional - cy (number) #optional \*/ matrixproto.scale = function (x, y, cx, cy) { y == null && (y = x); (cx || cy) && this.add(1, 0, 0, 1, cx, cy); this.add(x, 0, 0, y, 0, 0); (cx || cy) && this.add(1, 0, 0, 1, -cx, -cy); }; /*\ * Matrix.rotate [ method ] ** * Rotates the matrix > Parameters - a (number) - x (number) - y (number) \*/ matrixproto.rotate = function (a, x, y) { a = R.rad(a); x = x || 0; y = y || 0; var cos = +math.cos(a).toFixed(9), sin = +math.sin(a).toFixed(9); this.add(cos, sin, -sin, cos, x, y); this.add(1, 0, 0, 1, -x, -y); }; /*\ * Matrix.x [ method ] ** * Return x coordinate for given point after transformation described by the matrix. See also @Matrix.y > Parameters - x (number) - y (number) = (number) x \*/ matrixproto.x = function (x, y) { return x * this.a + y * this.c + this.e; }; /*\ * Matrix.y [ method ] ** * Return y coordinate for given point after transformation described by the matrix. See also @Matrix.x > Parameters - x (number) - y (number) = (number) y \*/ matrixproto.y = function (x, y) { return x * this.b + y * this.d + this.f; }; matrixproto.get = function (i) { return +this[Str.fromCharCode(97 + i)].toFixed(4); }; matrixproto.toString = function () { return R.svg ? "matrix(" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)].join() + ")" : [this.get(0), this.get(2), this.get(1), this.get(3), 0, 0].join(); }; matrixproto.toFilter = function () { return "progid:DXImageTransform.Microsoft.Matrix(M11=" + this.get(0) + ", M12=" + this.get(2) + ", M21=" + this.get(1) + ", M22=" + this.get(3) + ", Dx=" + this.get(4) + ", Dy=" + this.get(5) + ", sizingmethod='auto expand')"; }; matrixproto.offset = function () { return [this.e.toFixed(4), this.f.toFixed(4)]; }; function norm(a) { return a[0] * a[0] + a[1] * a[1]; } function normalize(a) { var mag = math.sqrt(norm(a)); a[0] && (a[0] /= mag); a[1] && (a[1] /= mag); } /*\ * Matrix.split [ method ] ** * Splits matrix into primitive transformations = (object) in format: o dx (number) translation by x o dy (number) translation by y o scalex (number) scale by x o scaley (number) scale by y o shear (number) shear o rotate (number) rotation in deg o isSimple (boolean) could it be represented via simple transformations \*/ matrixproto.split = function () { var out = {}; // translation out.dx = this.e; out.dy = this.f; // scale and shear var row = [[this.a, this.c], [this.b, this.d]]; out.scalex = math.sqrt(norm(row[0])); normalize(row[0]); out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1]; row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear]; out.scaley = math.sqrt(norm(row[1])); normalize(row[1]); out.shear /= out.scaley; // rotation var sin = -row[0][1], cos = row[1][1]; if (cos < 0) { out.rotate = R.deg(math.acos(cos)); if (sin < 0) { out.rotate = 360 - out.rotate; } } else { out.rotate = R.deg(math.asin(sin)); } out.isSimple = !+out.shear.toFixed(9) && (out.scalex.toFixed(9) == out.scaley.toFixed(9) || !out.rotate); out.isSuperSimple = !+out.shear.toFixed(9) && out.scalex.toFixed(9) == out.scaley.toFixed(9) && !out.rotate; out.noRotation = !+out.shear.toFixed(9) && !out.rotate; return out; }; /*\ * Matrix.toTransformString [ method ] ** * Return transform string that represents given matrix = (string) transform string \*/ matrixproto.toTransformString = function (shorter) { var s = shorter || this[split](); if (s.isSimple) { s.scalex = +s.scalex.toFixed(4); s.scaley = +s.scaley.toFixed(4); s.rotate = +s.rotate.toFixed(4); return (s.dx || s.dy ? "t" + [s.dx, s.dy] : E) + (s.scalex != 1 || s.scaley != 1 ? "s" + [s.scalex, s.scaley, 0, 0] : E) + (s.rotate ? "r" + [s.rotate, 0, 0] : E); } else { return "m" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)]; } }; })(Matrix.prototype); // WebKit rendering bug workaround method var version = navigator.userAgent.match(/Version\/(.*?)\s/) || navigator.userAgent.match(/Chrome\/(\d+)/); if ((navigator.vendor == "Apple Computer, Inc.") && (version && version[1] < 4 || navigator.platform.slice(0, 2) == "iP") || (navigator.vendor == "Google Inc." && version && version[1] < 8)) { /*\ * Paper.safari [ method ] ** * There is an inconvenient rendering bug in Safari (WebKit): * sometimes the rendering should be forced. * This method should help with dealing with this bug. \*/ paperproto.safari = function () { var rect = this.rect(-99, -99, this.width + 99, this.height + 99).attr({stroke: "none"}); setTimeout(function () {rect.remove();}); }; } else { paperproto.safari = fun; } var preventDefault = function () { this.returnValue = false; }, preventTouch = function () { return this.originalEvent.preventDefault(); }, stopPropagation = function () { this.cancelBubble = true; }, stopTouch = function () { return this.originalEvent.stopPropagation(); }, getEventPosition = function (e) { var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop, scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft; return { x: e.clientX + scrollX, y: e.clientY + scrollY }; }, addEvent = (function () { if (g.doc.addEventListener) { return function (obj, type, fn, element) { var f = function (e) { var pos = getEventPosition(e); return fn.call(element, e, pos.x, pos.y); }; obj.addEventListener(type, f, false); if (supportsTouch && touchMap[type]) { var _f = function (e) { var pos = getEventPosition(e), olde = e; for (var i = 0, ii = e.targetTouches && e.targetTouches.length; i < ii; i++) { if (e.targetTouches[i].target == obj) { e = e.targetTouches[i]; e.originalEvent = olde; e.preventDefault = preventTouch; e.stopPropagation = stopTouch; break; } } return fn.call(element, e, pos.x, pos.y); }; obj.addEventListener(touchMap[type], _f, false); } return function () { obj.removeEventListener(type, f, false); if (supportsTouch && touchMap[type]) obj.removeEventListener(touchMap[type], f, false); return true; }; }; } else if (g.doc.attachEvent) { return function (obj, type, fn, element) { var f = function (e) { e = e || g.win.event; var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop, scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft, x = e.clientX + scrollX, y = e.clientY + scrollY; e.preventDefault = e.preventDefault || preventDefault; e.stopPropagation = e.stopPropagation || stopPropagation; return fn.call(element, e, x, y); }; obj.attachEvent("on" + type, f); var detacher = function () { obj.detachEvent("on" + type, f); return true; }; return detacher; }; } })(), drag = [], dragMove = function (e) { var x = e.clientX, y = e.clientY, scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop, scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft, dragi, j = drag.length; while (j--) { dragi = drag[j]; if (supportsTouch && e.touches) { var i = e.touches.length, touch; while (i--) { touch = e.touches[i]; if (touch.identifier == dragi.el._drag.id) { x = touch.clientX; y = touch.clientY; (e.originalEvent ? e.originalEvent : e).preventDefault(); break; } } } else { e.preventDefault(); } var node = dragi.el.node, o, next = node.nextSibling, parent = node.parentNode, display = node.style.display; g.win.opera && parent.removeChild(node); node.style.display = "none"; o = dragi.el.paper.getElementByPoint(x, y); node.style.display = display; g.win.opera && (next ? parent.insertBefore(node, next) : parent.appendChild(node)); o && eve("raphael.drag.over." + dragi.el.id, dragi.el, o); x += scrollX; y += scrollY; eve("raphael.drag.move." + dragi.el.id, dragi.move_scope || dragi.el, x - dragi.el._drag.x, y - dragi.el._drag.y, x, y, e); } }, dragUp = function (e) { R.unmousemove(dragMove).unmouseup(dragUp); var i = drag.length, dragi; while (i--) { dragi = drag[i]; dragi.el._drag = {}; eve("raphael.drag.end." + dragi.el.id, dragi.end_scope || dragi.start_scope || dragi.move_scope || dragi.el, e); } drag = []; }, /*\ * Raphael.el [ property (object) ] ** * You can add your own method to elements. This is usefull when you want to hack default functionality or * want to wrap some common transformation or attributes in one method. In difference to canvas methods, * you can redefine element method at any time. Expending element methods wouldn’t affect set. > Usage | Raphael.el.red = function () { | this.attr({fill: "#f00"}); | }; | // then use it | paper.circle(100, 100, 20).red(); \*/ elproto = R.el = {}; /*\ * Element.click [ method ] ** * Adds event handler for click for the element. > Parameters - handler (function) handler for the event = (object) @Element \*/ /*\ * Element.unclick [ method ] ** * Removes event handler for click for the element. > Parameters - handler (function) #optional handler for the event = (object) @Element \*/ /*\ * Element.dblclick [ method ] ** * Adds event handler for double click for the element. > Parameters - handler (function) handler for the event = (object) @Element \*/ /*\ * Element.undblclick [ method ] ** * Removes event handler for double click for the element. > Parameters - handler (function) #optional handler for the event = (object) @Element \*/ /*\ * Element.mousedown [ method ] ** * Adds event handler for mousedown for the element. > Parameters - handler (function) handler for the event = (object) @Element \*/ /*\ * Element.unmousedown [ method ] ** * Removes event handler for mousedown for the element. > Parameters - handler (function) #optional handler for the event = (object) @Element \*/ /*\ * Element.mousemove [ method ] ** * Adds event handler for mousemove for the element. > Parameters - handler (function) handler for the event = (object) @Element \*/ /*\ * Element.unmousemove [ method ] ** * Removes event handler for mousemove for the element. > Parameters - handler (function) #optional handler for the event = (object) @Element \*/ /*\ * Element.mouseout [ method ] ** * Adds event handler for mouseout for the element. > Parameters - handler (function) handler for the event = (object) @Element \*/ /*\ * Element.unmouseout [ method ] ** * Removes event handler for mouseout for the element. > Parameters - handler (function) #optional handler for the event = (object) @Element \*/ /*\ * Element.mouseover [ method ] ** * Adds event handler for mouseover for the element. > Parameters - handler (function) handler for the event = (object) @Element \*/ /*\ * Element.unmouseover [ method ] ** * Removes event handler for mouseover for the element. > Parameters - handler (function) #optional handler for the event = (object) @Element \*/ /*\ * Element.mouseup [ method ] ** * Adds event handler for mouseup for the element. > Parameters - handler (function) handler for the event = (object) @Element \*/ /*\ * Element.unmouseup [ method ] ** * Removes event handler for mouseup for the element. > Parameters - handler (function) #optional handler for the event = (object) @Element \*/ /*\ * Element.touchstart [ method ] ** * Adds event handler for touchstart for the element. > Parameters - handler (function) handler for the event = (object) @Element \*/ /*\ * Element.untouchstart [ method ] ** * Removes event handler for touchstart for the element. > Parameters - handler (function) #optional handler for the event = (object) @Element \*/ /*\ * Element.touchmove [ method ] ** * Adds event handler for touchmove for the element. > Parameters - handler (function) handler for the event = (object) @Element \*/ /*\ * Element.untouchmove [ method ] ** * Removes event handler for touchmove for the element. > Parameters - handler (function) #optional handler for the event = (object) @Element \*/ /*\ * Element.touchend [ method ] ** * Adds event handler for touchend for the element. > Parameters - handler (function) handler for the event = (object) @Element \*/ /*\ * Element.untouchend [ method ] ** * Removes event handler for touchend for the element. > Parameters - handler (function) #optional handler for the event = (object) @Element \*/ /*\ * Element.touchcancel [ method ] ** * Adds event handler for touchcancel for the element. > Parameters - handler (function) handler for the event = (object) @Element \*/ /*\ * Element.untouchcancel [ method ] ** * Removes event handler for touchcancel for the element. > Parameters - handler (function) #optional handler for the event = (object) @Element \*/ for (var i = events.length; i--;) { (function (eventName) { R[eventName] = elproto[eventName] = function (fn, scope) { if (R.is(fn, "function")) { this.events = this.events || []; this.events.push({name: eventName, f: fn, unbind: addEvent(this.shape || this.node || g.doc, eventName, fn, scope || this)}); } return this; }; R["un" + eventName] = elproto["un" + eventName] = function (fn) { var events = this.events || [], l = events.length; while (l--){ if (events[l].name == eventName && (R.is(fn, "undefined") || events[l].f == fn)) { events[l].unbind(); events.splice(l, 1); !events.length && delete this.events; } } return this; }; })(events[i]); } /*\ * Element.data [ method ] ** * Adds or retrieves given value asociated with given key. ** * See also @Element.removeData > Parameters - key (string) key to store data - value (any) #optional value to store = (object) @Element * or, if value is not specified: = (any) value * or, if key and value are not specified: = (object) Key/value pairs for all the data associated with the element. > Usage | for (var i = 0, i < 5, i++) { | paper.circle(10 + 15 * i, 10, 10) | .attr({fill: "#000"}) | .data("i", i) | .click(function () { | alert(this.data("i")); | }); | } \*/ elproto.data = function (key, value) { var data = eldata[this.id] = eldata[this.id] || {}; if (arguments.length == 0) { return data; } if (arguments.length == 1) { if (R.is(key, "object")) { for (var i in key) if (key[has](i)) { this.data(i, key[i]); } return this; } eve("raphael.data.get." + this.id, this, data[key], key); return data[key]; } data[key] = value; eve("raphael.data.set." + this.id, this, value, key); return this; }; /*\ * Element.removeData [ method ] ** * Removes value associated with an element by given key. * If key is not provided, removes all the data of the element. > Parameters - key (string) #optional key = (object) @Element \*/ elproto.removeData = function (key) { if (key == null) { eldata[this.id] = {}; } else { eldata[this.id] && delete eldata[this.id][key]; } return this; }; /*\ * Element.getData [ method ] ** * Retrieves the element data = (object) data \*/ elproto.getData = function () { return clone(eldata[this.id] || {}); }; /*\ * Element.hover [ method ] ** * Adds event handlers for hover for the element. > Parameters - f_in (function) handler for hover in - f_out (function) handler for hover out - icontext (object) #optional context for hover in handler - ocontext (object) #optional context for hover out handler = (object) @Element \*/ elproto.hover = function (f_in, f_out, scope_in, scope_out) { return this.mouseover(f_in, scope_in).mouseout(f_out, scope_out || scope_in); }; /*\ * Element.unhover [ method ] ** * Removes event handlers for hover for the element. > Parameters - f_in (function) handler for hover in - f_out (function) handler for hover out = (object) @Element \*/ elproto.unhover = function (f_in, f_out) { return this.unmouseover(f_in).unmouseout(f_out); }; var draggable = []; /*\ * Element.drag [ method ] ** * Adds event handlers for drag of the element. > Parameters - onmove (function) handler for moving - onstart (function) handler for drag start - onend (function) handler for drag end - mcontext (object) #optional context for moving handler - scontext (object) #optional context for drag start handler - econtext (object) #optional context for drag end handler * Additionaly following `drag` events will be triggered: `drag.start.<id>` on start, * `drag.end.<id>` on end and `drag.move.<id>` on every move. When element will be dragged over another element * `drag.over.<id>` will be fired as well. * * Start event and start handler will be called in specified context or in context of the element with following parameters: o x (number) x position of the mouse o y (number) y position of the mouse o event (object) DOM event object * Move event and move handler will be called in specified context or in context of the element with following parameters: o dx (number) shift by x from the start point o dy (number) shift by y from the start point o x (number) x position of the mouse o y (number) y position of the mouse o event (object) DOM event object * End event and end handler will be called in specified context or in context of the element with following parameters: o event (object) DOM event object = (object) @Element \*/ elproto.drag = function (onmove, onstart, onend, move_scope, start_scope, end_scope) { function start(e) { (e.originalEvent || e).preventDefault(); var x = e.clientX, y = e.clientY, scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop, scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft; this._drag.id = e.identifier; if (supportsTouch && e.touches) { var i = e.touches.length, touch; while (i--) { touch = e.touches[i]; this._drag.id = touch.identifier; if (touch.identifier == this._drag.id) { x = touch.clientX; y = touch.clientY; break; } } } this._drag.x = x + scrollX; this._drag.y = y + scrollY; !drag.length && R.mousemove(dragMove).mouseup(dragUp); drag.push({el: this, move_scope: move_scope, start_scope: start_scope, end_scope: end_scope}); onstart && eve.on("raphael.drag.start." + this.id, onstart); onmove && eve.on("raphael.drag.move." + this.id, onmove); onend && eve.on("raphael.drag.end." + this.id, onend); eve("raphael.drag.start." + this.id, start_scope || move_scope || this, e.clientX + scrollX, e.clientY + scrollY, e); } this._drag = {}; draggable.push({el: this, start: start}); this.mousedown(start); return this; }; /*\ * Element.onDragOver [ method ] ** * Shortcut for assigning event handler for `drag.over.<id>` event, where id is id of the element (see @Element.id). > Parameters - f (function) handler for event, first argument would be the element you are dragging over \*/ elproto.onDragOver = function (f) { f ? eve.on("raphael.drag.over." + this.id, f) : eve.unbind("raphael.drag.over." + this.id); }; /*\ * Element.undrag [ method ] ** * Removes all drag event handlers from given element. \*/ elproto.undrag = function () { var i = draggable.length; while (i--) if (draggable[i].el == this) { this.unmousedown(draggable[i].start); draggable.splice(i, 1); eve.unbind("raphael.drag.*." + this.id); } !draggable.length && R.unmousemove(dragMove).unmouseup(dragUp); drag = []; }; /*\ * Paper.circle [ method ] ** * Draws a circle. ** > Parameters ** - x (number) x coordinate of the centre - y (number) y coordinate of the centre - r (number) radius = (object) Raphaël element object with type “circle” ** > Usage | var c = paper.circle(50, 50, 40); \*/ paperproto.circle = function (x, y, r) { var out = R._engine.circle(this, x || 0, y || 0, r || 0); this.__set__ && this.__set__.push(out); return out; }; /*\ * Paper.rect [ method ] * * Draws a rectangle. ** > Parameters ** - x (number) x coordinate of the top left corner - y (number) y coordinate of the top left corner - width (number) width - height (number) height - r (number) #optional radius for rounded corners, default is 0 = (object) Raphaël element object with type “rect” ** > Usage | // regular rectangle | var c = paper.rect(10, 10, 50, 50); | // rectangle with rounded corners | var c = paper.rect(40, 40, 50, 50, 10); \*/ paperproto.rect = function (x, y, w, h, r) { var out = R._engine.rect(this, x || 0, y || 0, w || 0, h || 0, r || 0); this.__set__ && this.__set__.push(out); return out; }; /*\ * Paper.ellipse [ method ] ** * Draws an ellipse. ** > Parameters ** - x (number) x coordinate of the centre - y (number) y coordinate of the centre - rx (number) horizontal radius - ry (number) vertical radius = (object) Raphaël element object with type “ellipse” ** > Usage | var c = paper.ellipse(50, 50, 40, 20); \*/ paperproto.ellipse = function (x, y, rx, ry) { var out = R._engine.ellipse(this, x || 0, y || 0, rx || 0, ry || 0); this.__set__ && this.__set__.push(out); return out; }; /*\ * Paper.path [ method ] ** * Creates a path element by given path data string. > Parameters - pathString (string) #optional path string in SVG format. * Path string consists of one-letter commands, followed by comma seprarated arguments in numercal form. Example: | "M10,20L30,40" * Here we can see two commands: “M”, with arguments `(10, 20)` and “L” with arguments `(30, 40)`. Upper case letter mean command is absolute, lower case—relative. * # <p>Here is short list of commands available, for more details see <a href="http://www.w3.org/TR/SVG/paths.html#PathData" title="Details of a path's data attribute's format are described in the SVG specification.">SVG path string format</a>.</p> # <table><thead><tr><th>Command</th><th>Name</th><th>Parameters</th></tr></thead><tbody> # <tr><td>M</td><td>moveto</td><td>(x y)+</td></tr> # <tr><td>Z</td><td>closepath</td><td>(none)</td></tr> # <tr><td>L</td><td>lineto</td><td>(x y)+</td></tr> # <tr><td>H</td><td>horizontal lineto</td><td>x+</td></tr> # <tr><td>V</td><td>vertical lineto</td><td>y+</td></tr> # <tr><td>C</td><td>curveto</td><td>(x1 y1 x2 y2 x y)+</td></tr> # <tr><td>S</td><td>smooth curveto</td><td>(x2 y2 x y)+</td></tr> # <tr><td>Q</td><td>quadratic Bézier curveto</td><td>(x1 y1 x y)+</td></tr> # <tr><td>T</td><td>smooth quadratic Bézier curveto</td><td>(x y)+</td></tr> # <tr><td>A</td><td>elliptical arc</td><td>(rx ry x-axis-rotation large-arc-flag sweep-flag x y)+</td></tr> # <tr><td>R</td><td><a href="http://en.wikipedia.org/wiki/Catmull–Rom_spline#Catmull.E2.80.93Rom_spline">Catmull-Rom curveto</a>*</td><td>x1 y1 (x y)+</td></tr></tbody></table> * * “Catmull-Rom curveto” is a not standard SVG command and added in 2.0 to make life easier. * Note: there is a special case when path consist of just three commands: “M10,10R…z”. In this case path will smoothly connects to its beginning. > Usage | var c = paper.path("M10 10L90 90"); | // draw a diagonal line: | // move to 10,10, line to 90,90 * For example of path strings, check out these icons: http://raphaeljs.com/icons/ \*/ paperproto.path = function (pathString) { pathString && !R.is(pathString, string) && !R.is(pathString[0], array) && (pathString += E); var out = R._engine.path(R.format[apply](R, arguments), this); this.__set__ && this.__set__.push(out); return out; }; /*\ * Paper.image [ method ] ** * Embeds an image into the surface. ** > Parameters ** - src (string) URI of the source image - x (number) x coordinate position - y (number) y coordinate position - width (number) width of the image - height (number) height of the image = (object) Raphaël element object with type “image” ** > Usage | var c = paper.image("apple.png", 10, 10, 80, 80); \*/ paperproto.image = function (src, x, y, w, h) { var out = R._engine.image(this, src || "about:blank", x || 0, y || 0, w || 0, h || 0); this.__set__ && this.__set__.push(out); return out; }; /*\ * Paper.text [ method ] ** * Draws a text string. If you need line breaks, put “\n” in the string. ** > Parameters ** - x (number) x coordinate position - y (number) y coordinate position - text (string) The text string to draw = (object) Raphaël element object with type “text” ** > Usage | var t = paper.text(50, 50, "Raphaël\nkicks\nbutt!"); \*/ paperproto.text = function (x, y, text) { var out = R._engine.text(this, x || 0, y || 0, Str(text)); this.__set__ && this.__set__.push(out); return out; }; /*\ * Paper.set [ method ] ** * Creates array-like object to keep and operate several elements at once. * Warning: it doesn’t create any elements for itself in the page, it just groups existing elements. * Sets act as pseudo elements — all methods available to an element can be used on a set. = (object) array-like object that represents set of elements ** > Usage | var st = paper.set(); | st.push( | paper.circle(10, 10, 5), | paper.circle(30, 10, 5) | ); | st.attr({fill: "red"}); // changes the fill of both circles \*/ paperproto.set = function (itemsArray) { !R.is(itemsArray, "array") && (itemsArray = Array.prototype.splice.call(arguments, 0, arguments.length)); var out = new Set(itemsArray); this.__set__ && this.__set__.push(out); out["paper"] = this; out["type"] = "set"; return out; }; /*\ * Paper.setStart [ method ] ** * Creates @Paper.set. All elements that will be created after calling this method and before calling * @Paper.setFinish will be added to the set. ** > Usage | paper.setStart(); | paper.circle(10, 10, 5), | paper.circle(30, 10, 5) | var st = paper.setFinish(); | st.attr({fill: "red"}); // changes the fill of both circles \*/ paperproto.setStart = function (set) { this.__set__ = set || this.set(); }; /*\ * Paper.setFinish [ method ] ** * See @Paper.setStart. This method finishes catching and returns resulting set. ** = (object) set \*/ paperproto.setFinish = function (set) { var out = this.__set__; delete this.__set__; return out; }; /*\ * Paper.setSize [ method ] ** * If you need to change dimensions of the canvas call this method ** > Parameters ** - width (number) new width of the canvas - height (number) new height of the canvas \*/ paperproto.setSize = function (width, height) { return R._engine.setSize.call(this, width, height); }; /*\ * Paper.setViewBox [ method ] ** * Sets the view box of the paper. Practically it gives you ability to zoom and pan whole paper surface by * specifying new boundaries. ** > Parameters ** - x (number) new x position, default is `0` - y (number) new y position, default is `0` - w (number) new width of the canvas - h (number) new height of the canvas - fit (boolean) `true` if you want graphics to fit into new boundary box \*/ paperproto.setViewBox = function (x, y, w, h, fit) { return R._engine.setViewBox.call(this, x, y, w, h, fit); }; /*\ * Paper.top [ property ] ** * Points to the topmost element on the paper \*/ /*\ * Paper.bottom [ property ] ** * Points to the bottom element on the paper \*/ paperproto.top = paperproto.bottom = null; /*\ * Paper.raphael [ property ] ** * Points to the @Raphael object/function \*/ paperproto.raphael = R; var getOffset = function (elem) { var box = elem.getBoundingClientRect(), doc = elem.ownerDocument, body = doc.body, docElem = doc.documentElement, clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0, top = box.top + (g.win.pageYOffset || docElem.scrollTop || body.scrollTop ) - clientTop, left = box.left + (g.win.pageXOffset || docElem.scrollLeft || body.scrollLeft) - clientLeft; return { y: top, x: left }; }; /*\ * Paper.getElementByPoint [ method ] ** * Returns you topmost element under given point. ** = (object) Raphaël element object > Parameters ** - x (number) x coordinate from the top left corner of the window - y (number) y coordinate from the top left corner of the window > Usage | paper.getElementByPoint(mouseX, mouseY).attr({stroke: "#f00"}); \*/ paperproto.getElementByPoint = function (x, y) { var paper = this, svg = paper.canvas, target = g.doc.elementFromPoint(x, y); if (g.win.opera && target.tagName == "svg") { var so = getOffset(svg), sr = svg.createSVGRect(); sr.x = x - so.x; sr.y = y - so.y; sr.width = sr.height = 1; var hits = svg.getIntersectionList(sr, null); if (hits.length) { target = hits[hits.length - 1]; } } if (!target) { return null; } while (target.parentNode && target != svg.parentNode && !target.raphael) { target = target.parentNode; } target == paper.canvas.parentNode && (target = svg); target = target && target.raphael ? paper.getById(target.raphaelid) : null; return target; }; /*\ * Paper.getElementsByBBox [ method ] ** * Returns set of elements that have an intersecting bounding box ** > Parameters ** - bbox (object) bbox to check with = (object) @Set \*/ paperproto.getElementsByBBox = function (bbox) { var set = this.set(); this.forEach(function (el) { if (R.isBBoxIntersect(el.getBBox(), bbox)) { set.push(el); } }); return set; }; /*\ * Paper.getById [ method ] ** * Returns you element by its internal ID. ** > Parameters ** - id (number) id = (object) Raphaël element object \*/ paperproto.getById = function (id) { var bot = this.bottom; while (bot) { if (bot.id == id) { return bot; } bot = bot.next; } return null; }; /*\ * Paper.forEach [ method ] ** * Executes given function for each element on the paper * * If callback function returns `false` it will stop loop running. ** > Parameters ** - callback (function) function to run - thisArg (object) context object for the callback = (object) Paper object > Usage | paper.forEach(function (el) { | el.attr({ stroke: "blue" }); | }); \*/ paperproto.forEach = function (callback, thisArg) { var bot = this.bottom; while (bot) { if (callback.call(thisArg, bot) === false) { return this; } bot = bot.next; } return this; }; /*\ * Paper.getElementsByPoint [ method ] ** * Returns set of elements that have common point inside ** > Parameters ** - x (number) x coordinate of the point - y (number) y coordinate of the point = (object) @Set \*/ paperproto.getElementsByPoint = function (x, y) { var set = this.set(); this.forEach(function (el) { if (el.isPointInside(x, y)) { set.push(el); } }); return set; }; function x_y() { return this.x + S + this.y; } function x_y_w_h() { return this.x + S + this.y + S + this.width + " \xd7 " + this.height; } /*\ * Element.isPointInside [ method ] ** * Determine if given point is inside this element’s shape ** > Parameters ** - x (number) x coordinate of the point - y (number) y coordinate of the point = (boolean) `true` if point inside the shape \*/ elproto.isPointInside = function (x, y) { var rp = this.realPath = getPath[this.type](this); if (this.attr('transform') && this.attr('transform').length) { rp = R.transformPath(rp, this.attr('transform')); } return R.isPointInsidePath(rp, x, y); }; /*\ * Element.getBBox [ method ] ** * Return bounding box for a given element ** > Parameters ** - isWithoutTransform (boolean) flag, `true` if you want to have bounding box before transformations. Default is `false`. = (object) Bounding box object: o { o x: (number) top left corner x o y: (number) top left corner y o x2: (number) bottom right corner x o y2: (number) bottom right corner y o width: (number) width o height: (number) height o } \*/ elproto.getBBox = function (isWithoutTransform) { if (this.removed) { return {}; } var _ = this._; if (isWithoutTransform) { if (_.dirty || !_.bboxwt) { this.realPath = getPath[this.type](this); _.bboxwt = pathDimensions(this.realPath); _.bboxwt.toString = x_y_w_h; _.dirty = 0; } return _.bboxwt; } if (_.dirty || _.dirtyT || !_.bbox) { if (_.dirty || !this.realPath) { _.bboxwt = 0; this.realPath = getPath[this.type](this); } _.bbox = pathDimensions(mapPath(this.realPath, this.matrix)); _.bbox.toString = x_y_w_h; _.dirty = _.dirtyT = 0; } return _.bbox; }; /*\ * Element.clone [ method ] ** = (object) clone of a given element ** \*/ elproto.clone = function () { if (this.removed) { return null; } var out = this.paper[this.type]().attr(this.attr()); this.__set__ && this.__set__.push(out); return out; }; /*\ * Element.glow [ method ] ** * Return set of elements that create glow-like effect around given element. See @Paper.set. * * Note: Glow is not connected to the element. If you change element attributes it won’t adjust itself. ** > Parameters ** - glow (object) #optional parameters object with all properties optional: o { o width (number) size of the glow, default is `10` o fill (boolean) will it be filled, default is `false` o opacity (number) opacity, default is `0.5` o offsetx (number) horizontal offset, default is `0` o offsety (number) vertical offset, default is `0` o color (string) glow colour, default is `black` o } = (object) @Paper.set of elements that represents glow \*/ elproto.glow = function (glow) { if (this.type == "text") { return null; } glow = glow || {}; var s = { width: (glow.width || 10) + (+this.attr("stroke-width") || 1), fill: glow.fill || false, opacity: glow.opacity || .5, offsetx: glow.offsetx || 0, offsety: glow.offsety || 0, color: glow.color || "#000" }, c = s.width / 2, r = this.paper, out = r.set(), path = this.realPath || getPath[this.type](this); path = this.matrix ? mapPath(path, this.matrix) : path; for (var i = 1; i < c + 1; i++) { out.push(r.path(path).attr({ stroke: s.color, fill: s.fill ? s.color : "none", "stroke-linejoin": "round", "stroke-linecap": "round", "stroke-width": +(s.width / c * i).toFixed(3), opacity: +(s.opacity / c).toFixed(3) })); } return out.insertBefore(this).translate(s.offsetx, s.offsety); }; var curveslengths = {}, getPointAtSegmentLength = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) { if (length == null) { return bezlen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y); } else { return R.findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, getTatLen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length)); } }, getLengthFactory = function (istotal, subpath) { return function (path, length, onlystart) { path = path2curve(path); var x, y, p, l, sp = "", subpaths = {}, point, len = 0; for (var i = 0, ii = path.length; i < ii; i++) { p = path[i]; if (p[0] == "M") { x = +p[1]; y = +p[2]; } else { l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]); if (len + l > length) { if (subpath && !subpaths.start) { point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len); sp += ["C" + point.start.x, point.start.y, point.m.x, point.m.y, point.x, point.y]; if (onlystart) {return sp;} subpaths.start = sp; sp = ["M" + point.x, point.y + "C" + point.n.x, point.n.y, point.end.x, point.end.y, p[5], p[6]].join(); len += l; x = +p[5]; y = +p[6]; continue; } if (!istotal && !subpath) { point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len); return {x: point.x, y: point.y, alpha: point.alpha}; } } len += l; x = +p[5]; y = +p[6]; } sp += p.shift() + p; } subpaths.end = sp; point = istotal ? len : subpath ? subpaths : R.findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1); point.alpha && (point = {x: point.x, y: point.y, alpha: point.alpha}); return point; }; }; var getTotalLength = getLengthFactory(1), getPointAtLength = getLengthFactory(), getSubpathsAtLength = getLengthFactory(0, 1); /*\ * Raphael.getTotalLength [ method ] ** * Returns length of the given path in pixels. ** > Parameters ** - path (string) SVG path string. ** = (number) length. \*/ R.getTotalLength = getTotalLength; /*\ * Raphael.getPointAtLength [ method ] ** * Return coordinates of the point located at the given length on the given path. ** > Parameters ** - path (string) SVG path string - length (number) ** = (object) representation of the point: o { o x: (number) x coordinate o y: (number) y coordinate o alpha: (number) angle of derivative o } \*/ R.getPointAtLength = getPointAtLength; /*\ * Raphael.getSubpath [ method ] ** * Return subpath of a given path from given length to given length. ** > Parameters ** - path (string) SVG path string - from (number) position of the start of the segment - to (number) position of the end of the segment ** = (string) pathstring for the segment \*/ R.getSubpath = function (path, from, to) { if (this.getTotalLength(path) - to < 1e-6) { return getSubpathsAtLength(path, from).end; } var a = getSubpathsAtLength(path, to, 1); return from ? getSubpathsAtLength(a, from).end : a; }; /*\ * Element.getTotalLength [ method ] ** * Returns length of the path in pixels. Only works for element of “path” type. = (number) length. \*/ elproto.getTotalLength = function () { var path = this.getPath(); if (!path) { return; } if (this.node.getTotalLength) { return this.node.getTotalLength(); } return getTotalLength(path); }; /*\ * Element.getPointAtLength [ method ] ** * Return coordinates of the point located at the given length on the given path. Only works for element of “path” type. ** > Parameters ** - length (number) ** = (object) representation of the point: o { o x: (number) x coordinate o y: (number) y coordinate o alpha: (number) angle of derivative o } \*/ elproto.getPointAtLength = function (length) { var path = this.getPath(); if (!path) { return; } return getPointAtLength(path, length); }; /*\ * Element.getPath [ method ] ** * Returns path of the element. Only works for elements of “path” type and simple elements like circle. = (object) path ** \*/ elproto.getPath = function () { var path, getPath = R._getPath[this.type]; if (this.type == "text" || this.type == "set") { return; } if (getPath) { path = getPath(this); } return path; }; /*\ * Element.getSubpath [ method ] ** * Return subpath of a given element from given length to given length. Only works for element of “path” type. ** > Parameters ** - from (number) position of the start of the segment - to (number) position of the end of the segment ** = (string) pathstring for the segment \*/ elproto.getSubpath = function (from, to) { var path = this.getPath(); if (!path) { return; } return R.getSubpath(path, from, to); }; /*\ * Raphael.easing_formulas [ property ] ** * Object that contains easing formulas for animation. You could extend it with your own. By default it has following list of easing: # <ul> # <li>“linear”</li> # <li>“<” or “easeIn” or “ease-in”</li> # <li>“>” or “easeOut” or “ease-out”</li> # <li>“<>” or “easeInOut” or “ease-in-out”</li> # <li>“backIn” or “back-in”</li> # <li>“backOut” or “back-out”</li> # <li>“elastic”</li> # <li>“bounce”</li> # </ul> # <p>See also <a href="http://raphaeljs.com/easing.html">Easing demo</a>.</p> \*/ var ef = R.easing_formulas = { linear: function (n) { return n; }, "<": function (n) { return pow(n, 1.7); }, ">": function (n) { return pow(n, .48); }, "<>": function (n) { var q = .48 - n / 1.04, Q = math.sqrt(.1734 + q * q), x = Q - q, X = pow(abs(x), 1 / 3) * (x < 0 ? -1 : 1), y = -Q - q, Y = pow(abs(y), 1 / 3) * (y < 0 ? -1 : 1), t = X + Y + .5; return (1 - t) * 3 * t * t + t * t * t; }, backIn: function (n) { var s = 1.70158; return n * n * ((s + 1) * n - s); }, backOut: function (n) { n = n - 1; var s = 1.70158; return n * n * ((s + 1) * n + s) + 1; }, elastic: function (n) { if (n == !!n) { return n; } return pow(2, -10 * n) * math.sin((n - .075) * (2 * PI) / .3) + 1; }, bounce: function (n) { var s = 7.5625, p = 2.75, l; if (n < (1 / p)) { l = s * n * n; } else { if (n < (2 / p)) { n -= (1.5 / p); l = s * n * n + .75; } else { if (n < (2.5 / p)) { n -= (2.25 / p); l = s * n * n + .9375; } else { n -= (2.625 / p); l = s * n * n + .984375; } } } return l; } }; ef.easeIn = ef["ease-in"] = ef["<"]; ef.easeOut = ef["ease-out"] = ef[">"]; ef.easeInOut = ef["ease-in-out"] = ef["<>"]; ef["back-in"] = ef.backIn; ef["back-out"] = ef.backOut; var animationElements = [], requestAnimFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) { setTimeout(callback, 16); }, animation = function () { var Now = +new Date, l = 0; for (; l < animationElements.length; l++) { var e = animationElements[l]; if (e.el.removed || e.paused) { continue; } var time = Now - e.start, ms = e.ms, easing = e.easing, from = e.from, diff = e.diff, to = e.to, t = e.t, that = e.el, set = {}, now, init = {}, key; if (e.initstatus) { time = (e.initstatus * e.anim.top - e.prev) / (e.percent - e.prev) * ms; e.status = e.initstatus; delete e.initstatus; e.stop && animationElements.splice(l--, 1); } else { e.status = (e.prev + (e.percent - e.prev) * (time / ms)) / e.anim.top; } if (time < 0) { continue; } if (time < ms) { var pos = easing(time / ms); for (var attr in from) if (from[has](attr)) { switch (availableAnimAttrs[attr]) { case nu: now = +from[attr] + pos * ms * diff[attr]; break; case "colour": now = "rgb(" + [ upto255(round(from[attr].r + pos * ms * diff[attr].r)), upto255(round(from[attr].g + pos * ms * diff[attr].g)), upto255(round(from[attr].b + pos * ms * diff[attr].b)) ].join(",") + ")"; break; case "path": now = []; for (var i = 0, ii = from[attr].length; i < ii; i++) { now[i] = [from[attr][i][0]]; for (var j = 1, jj = from[attr][i].length; j < jj; j++) { now[i][j] = +from[attr][i][j] + pos * ms * diff[attr][i][j]; } now[i] = now[i].join(S); } now = now.join(S); break; case "transform": if (diff[attr].real) { now = []; for (i = 0, ii = from[attr].length; i < ii; i++) { now[i] = [from[attr][i][0]]; for (j = 1, jj = from[attr][i].length; j < jj; j++) { now[i][j] = from[attr][i][j] + pos * ms * diff[attr][i][j]; } } } else { var get = function (i) { return +from[attr][i] + pos * ms * diff[attr][i]; }; // now = [["r", get(2), 0, 0], ["t", get(3), get(4)], ["s", get(0), get(1), 0, 0]]; now = [["m", get(0), get(1), get(2), get(3), get(4), get(5)]]; } break; case "csv": if (attr == "clip-rect") { now = []; i = 4; while (i--) { now[i] = +from[attr][i] + pos * ms * diff[attr][i]; } } break; default: var from2 = [][concat](from[attr]); now = []; i = that.paper.customAttributes[attr].length; while (i--) { now[i] = +from2[i] + pos * ms * diff[attr][i]; } break; } set[attr] = now; } that.attr(set); (function (id, that, anim) { setTimeout(function () { eve("raphael.anim.frame." + id, that, anim); }); })(that.id, that, e.anim); } else { (function(f, el, a) { setTimeout(function() { eve("raphael.anim.frame." + el.id, el, a); eve("raphael.anim.finish." + el.id, el, a); R.is(f, "function") && f.call(el); }); })(e.callback, that, e.anim); that.attr(to); animationElements.splice(l--, 1); if (e.repeat > 1 && !e.next) { for (key in to) if (to[has](key)) { init[key] = e.totalOrigin[key]; } e.el.attr(init); runAnimation(e.anim, e.el, e.anim.percents[0], null, e.totalOrigin, e.repeat - 1); } if (e.next && !e.stop) { runAnimation(e.anim, e.el, e.next, null, e.totalOrigin, e.repeat); } } } R.svg && that && that.paper && that.paper.safari(); animationElements.length && requestAnimFrame(animation); }, upto255 = function (color) { return color > 255 ? 255 : color < 0 ? 0 : color; }; /*\ * Element.animateWith [ method ] ** * Acts similar to @Element.animate, but ensure that given animation runs in sync with another given element. ** > Parameters ** - el (object) element to sync with - anim (object) animation to sync with - params (object) #optional final attributes for the element, see also @Element.attr - ms (number) #optional number of milliseconds for animation to run - easing (string) #optional easing type. Accept on of @Raphael.easing_formulas or CSS format: `cubic‐bezier(XX, XX, XX, XX)` - callback (function) #optional callback function. Will be called at the end of animation. * or - element (object) element to sync with - anim (object) animation to sync with - animation (object) #optional animation object, see @Raphael.animation ** = (object) original element \*/ elproto.animateWith = function (el, anim, params, ms, easing, callback) { var element = this; if (element.removed) { callback && callback.call(element); return element; } var a = params instanceof Animation ? params : R.animation(params, ms, easing, callback), x, y; runAnimation(a, element, a.percents[0], null, element.attr()); for (var i = 0, ii = animationElements.length; i < ii; i++) { if (animationElements[i].anim == anim && animationElements[i].el == el) { animationElements[ii - 1].start = animationElements[i].start; break; } } return element; // // // var a = params ? R.animation(params, ms, easing, callback) : anim, // status = element.status(anim); // return this.animate(a).status(a, status * anim.ms / a.ms); }; function CubicBezierAtTime(t, p1x, p1y, p2x, p2y, duration) { var cx = 3 * p1x, bx = 3 * (p2x - p1x) - cx, ax = 1 - cx - bx, cy = 3 * p1y, by = 3 * (p2y - p1y) - cy, ay = 1 - cy - by; function sampleCurveX(t) { return ((ax * t + bx) * t + cx) * t; } function solve(x, epsilon) { var t = solveCurveX(x, epsilon); return ((ay * t + by) * t + cy) * t; } function solveCurveX(x, epsilon) { var t0, t1, t2, x2, d2, i; for(t2 = x, i = 0; i < 8; i++) { x2 = sampleCurveX(t2) - x; if (abs(x2) < epsilon) { return t2; } d2 = (3 * ax * t2 + 2 * bx) * t2 + cx; if (abs(d2) < 1e-6) { break; } t2 = t2 - x2 / d2; } t0 = 0; t1 = 1; t2 = x; if (t2 < t0) { return t0; } if (t2 > t1) { return t1; } while (t0 < t1) { x2 = sampleCurveX(t2); if (abs(x2 - x) < epsilon) { return t2; } if (x > x2) { t0 = t2; } else { t1 = t2; } t2 = (t1 - t0) / 2 + t0; } return t2; } return solve(t, 1 / (200 * duration)); } elproto.onAnimation = function (f) { f ? eve.on("raphael.anim.frame." + this.id, f) : eve.unbind("raphael.anim.frame." + this.id); return this; }; function Animation(anim, ms) { var percents = [], newAnim = {}; this.ms = ms; this.times = 1; if (anim) { for (var attr in anim) if (anim[has](attr)) { newAnim[toFloat(attr)] = anim[attr]; percents.push(toFloat(attr)); } percents.sort(sortByNumber); } this.anim = newAnim; this.top = percents[percents.length - 1]; this.percents = percents; } /*\ * Animation.delay [ method ] ** * Creates a copy of existing animation object with given delay. ** > Parameters ** - delay (number) number of ms to pass between animation start and actual animation ** = (object) new altered Animation object | var anim = Raphael.animation({cx: 10, cy: 20}, 2e3); | circle1.animate(anim); // run the given animation immediately | circle2.animate(anim.delay(500)); // run the given animation after 500 ms \*/ Animation.prototype.delay = function (delay) { var a = new Animation(this.anim, this.ms); a.times = this.times; a.del = +delay || 0; return a; }; /*\ * Animation.repeat [ method ] ** * Creates a copy of existing animation object with given repetition. ** > Parameters ** - repeat (number) number iterations of animation. For infinite animation pass `Infinity` ** = (object) new altered Animation object \*/ Animation.prototype.repeat = function (times) { var a = new Animation(this.anim, this.ms); a.del = this.del; a.times = math.floor(mmax(times, 0)) || 1; return a; }; function runAnimation(anim, element, percent, status, totalOrigin, times) { percent = toFloat(percent); var params, isInAnim, isInAnimSet, percents = [], next, prev, timestamp, ms = anim.ms, from = {}, to = {}, diff = {}; if (status) { for (i = 0, ii = animationElements.length; i < ii; i++) { var e = animationElements[i]; if (e.el.id == element.id && e.anim == anim) { if (e.percent != percent) { animationElements.splice(i, 1); isInAnimSet = 1; } else { isInAnim = e; } element.attr(e.totalOrigin); break; } } } else { status = +to; // NaN } for (var i = 0, ii = anim.percents.length; i < ii; i++) { if (anim.percents[i] == percent || anim.percents[i] > status * anim.top) { percent = anim.percents[i]; prev = anim.percents[i - 1] || 0; ms = ms / anim.top * (percent - prev); next = anim.percents[i + 1]; params = anim.anim[percent]; break; } else if (status) { element.attr(anim.anim[anim.percents[i]]); } } if (!params) { return; } if (!isInAnim) { for (var attr in params) if (params[has](attr)) { if (availableAnimAttrs[has](attr) || element.paper.customAttributes[has](attr)) { from[attr] = element.attr(attr); (from[attr] == null) && (from[attr] = availableAttrs[attr]); to[attr] = params[attr]; switch (availableAnimAttrs[attr]) { case nu: diff[attr] = (to[attr] - from[attr]) / ms; break; case "colour": from[attr] = R.getRGB(from[attr]); var toColour = R.getRGB(to[attr]); diff[attr] = { r: (toColour.r - from[attr].r) / ms, g: (toColour.g - from[attr].g) / ms, b: (toColour.b - from[attr].b) / ms }; break; case "path": var pathes = path2curve(from[attr], to[attr]), toPath = pathes[1]; from[attr] = pathes[0]; diff[attr] = []; for (i = 0, ii = from[attr].length; i < ii; i++) { diff[attr][i] = [0]; for (var j = 1, jj = from[attr][i].length; j < jj; j++) { diff[attr][i][j] = (toPath[i][j] - from[attr][i][j]) / ms; } } break; case "transform": var _ = element._, eq = equaliseTransform(_[attr], to[attr]); if (eq) { from[attr] = eq.from; to[attr] = eq.to; diff[attr] = []; diff[attr].real = true; for (i = 0, ii = from[attr].length; i < ii; i++) { diff[attr][i] = [from[attr][i][0]]; for (j = 1, jj = from[attr][i].length; j < jj; j++) { diff[attr][i][j] = (to[attr][i][j] - from[attr][i][j]) / ms; } } } else { var m = (element.matrix || new Matrix), to2 = { _: {transform: _.transform}, getBBox: function () { return element.getBBox(1); } }; from[attr] = [ m.a, m.b, m.c, m.d, m.e, m.f ]; extractTransform(to2, to[attr]); to[attr] = to2._.transform; diff[attr] = [ (to2.matrix.a - m.a) / ms, (to2.matrix.b - m.b) / ms, (to2.matrix.c - m.c) / ms, (to2.matrix.d - m.d) / ms, (to2.matrix.e - m.e) / ms, (to2.matrix.f - m.f) / ms ]; // from[attr] = [_.sx, _.sy, _.deg, _.dx, _.dy]; // var to2 = {_:{}, getBBox: function () { return element.getBBox(); }}; // extractTransform(to2, to[attr]); // diff[attr] = [ // (to2._.sx - _.sx) / ms, // (to2._.sy - _.sy) / ms, // (to2._.deg - _.deg) / ms, // (to2._.dx - _.dx) / ms, // (to2._.dy - _.dy) / ms // ]; } break; case "csv": var values = Str(params[attr])[split](separator), from2 = Str(from[attr])[split](separator); if (attr == "clip-rect") { from[attr] = from2; diff[attr] = []; i = from2.length; while (i--) { diff[attr][i] = (values[i] - from[attr][i]) / ms; } } to[attr] = values; break; default: values = [][concat](params[attr]); from2 = [][concat](from[attr]); diff[attr] = []; i = element.paper.customAttributes[attr].length; while (i--) { diff[attr][i] = ((values[i] || 0) - (from2[i] || 0)) / ms; } break; } } } var easing = params.easing, easyeasy = R.easing_formulas[easing]; if (!easyeasy) { easyeasy = Str(easing).match(bezierrg); if (easyeasy && easyeasy.length == 5) { var curve = easyeasy; easyeasy = function (t) { return CubicBezierAtTime(t, +curve[1], +curve[2], +curve[3], +curve[4], ms); }; } else { easyeasy = pipe; } } timestamp = params.start || anim.start || +new Date; e = { anim: anim, percent: percent, timestamp: timestamp, start: timestamp + (anim.del || 0), status: 0, initstatus: status || 0, stop: false, ms: ms, easing: easyeasy, from: from, diff: diff, to: to, el: element, callback: params.callback, prev: prev, next: next, repeat: times || anim.times, origin: element.attr(), totalOrigin: totalOrigin }; animationElements.push(e); if (status && !isInAnim && !isInAnimSet) { e.stop = true; e.start = new Date - ms * status; if (animationElements.length == 1) { return animation(); } } if (isInAnimSet) { e.start = new Date - e.ms * status; } animationElements.length == 1 && requestAnimFrame(animation); } else { isInAnim.initstatus = status; isInAnim.start = new Date - isInAnim.ms * status; } eve("raphael.anim.start." + element.id, element, anim); } /*\ * Raphael.animation [ method ] ** * Creates an animation object that can be passed to the @Element.animate or @Element.animateWith methods. * See also @Animation.delay and @Animation.repeat methods. ** > Parameters ** - params (object) final attributes for the element, see also @Element.attr - ms (number) number of milliseconds for animation to run - easing (string) #optional easing type. Accept one of @Raphael.easing_formulas or CSS format: `cubic‐bezier(XX, XX, XX, XX)` - callback (function) #optional callback function. Will be called at the end of animation. ** = (object) @Animation \*/ R.animation = function (params, ms, easing, callback) { if (params instanceof Animation) { return params; } if (R.is(easing, "function") || !easing) { callback = callback || easing || null; easing = null; } params = Object(params); ms = +ms || 0; var p = {}, json, attr; for (attr in params) if (params[has](attr) && toFloat(attr) != attr && toFloat(attr) + "%" != attr) { json = true; p[attr] = params[attr]; } if (!json) { return new Animation(params, ms); } else { easing && (p.easing = easing); callback && (p.callback = callback); return new Animation({100: p}, ms); } }; /*\ * Element.animate [ method ] ** * Creates and starts animation for given element. ** > Parameters ** - params (object) final attributes for the element, see also @Element.attr - ms (number) number of milliseconds for animation to run - easing (string) #optional easing type. Accept one of @Raphael.easing_formulas or CSS format: `cubic‐bezier(XX, XX, XX, XX)` - callback (function) #optional callback function. Will be called at the end of animation. * or - animation (object) animation object, see @Raphael.animation ** = (object) original element \*/ elproto.animate = function (params, ms, easing, callback) { var element = this; if (element.removed) { callback && callback.call(element); return element; } var anim = params instanceof Animation ? params : R.animation(params, ms, easing, callback); runAnimation(anim, element, anim.percents[0], null, element.attr()); return element; }; /*\ * Element.setTime [ method ] ** * Sets the status of animation of the element in milliseconds. Similar to @Element.status method. ** > Parameters ** - anim (object) animation object - value (number) number of milliseconds from the beginning of the animation ** = (object) original element if `value` is specified * Note, that during animation following events are triggered: * * On each animation frame event `anim.frame.<id>`, on start `anim.start.<id>` and on end `anim.finish.<id>`. \*/ elproto.setTime = function (anim, value) { if (anim && value != null) { this.status(anim, mmin(value, anim.ms) / anim.ms); } return this; }; /*\ * Element.status [ method ] ** * Gets or sets the status of animation of the element. ** > Parameters ** - anim (object) #optional animation object - value (number) #optional 0 – 1. If specified, method works like a setter and sets the status of a given animation to the value. This will cause animation to jump to the given position. ** = (number) status * or = (array) status if `anim` is not specified. Array of objects in format: o { o anim: (object) animation object o status: (number) status o } * or = (object) original element if `value` is specified \*/ elproto.status = function (anim, value) { var out = [], i = 0, len, e; if (value != null) { runAnimation(anim, this, -1, mmin(value, 1)); return this; } else { len = animationElements.length; for (; i < len; i++) { e = animationElements[i]; if (e.el.id == this.id && (!anim || e.anim == anim)) { if (anim) { return e.status; } out.push({ anim: e.anim, status: e.status }); } } if (anim) { return 0; } return out; } }; /*\ * Element.pause [ method ] ** * Stops animation of the element with ability to resume it later on. ** > Parameters ** - anim (object) #optional animation object ** = (object) original element \*/ elproto.pause = function (anim) { for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) { if (eve("raphael.anim.pause." + this.id, this, animationElements[i].anim) !== false) { animationElements[i].paused = true; } } return this; }; /*\ * Element.resume [ method ] ** * Resumes animation if it was paused with @Element.pause method. ** > Parameters ** - anim (object) #optional animation object ** = (object) original element \*/ elproto.resume = function (anim) { for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) { var e = animationElements[i]; if (eve("raphael.anim.resume." + this.id, this, e.anim) !== false) { delete e.paused; this.status(e.anim, e.status); } } return this; }; /*\ * Element.stop [ method ] ** * Stops animation of the element. ** > Parameters ** - anim (object) #optional animation object ** = (object) original element \*/ elproto.stop = function (anim) { for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) { if (eve("raphael.anim.stop." + this.id, this, animationElements[i].anim) !== false) { animationElements.splice(i--, 1); } } return this; }; function stopAnimation(paper) { for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.paper == paper) { animationElements.splice(i--, 1); } } eve.on("raphael.remove", stopAnimation); eve.on("raphael.clear", stopAnimation); elproto.toString = function () { return "Rapha\xebl\u2019s object"; }; // Set var Set = function (items) { this.items = []; this.length = 0; this.type = "set"; if (items) { for (var i = 0, ii = items.length; i < ii; i++) { if (items[i] && (items[i].constructor == elproto.constructor || items[i].constructor == Set)) { this[this.items.length] = this.items[this.items.length] = items[i]; this.length++; } } } }, setproto = Set.prototype; /*\ * Set.push [ method ] ** * Adds each argument to the current set. = (object) original element \*/ setproto.push = function () { var item, len; for (var i = 0, ii = arguments.length; i < ii; i++) { item = arguments[i]; if (item && (item.constructor == elproto.constructor || item.constructor == Set)) { len = this.items.length; this[len] = this.items[len] = item; this.length++; } } return this; }; /*\ * Set.pop [ method ] ** * Removes last element and returns it. = (object) element \*/ setproto.pop = function () { this.length && delete this[this.length--]; return this.items.pop(); }; /*\ * Set.forEach [ method ] ** * Executes given function for each element in the set. * * If function returns `false` it will stop loop running. ** > Parameters ** - callback (function) function to run - thisArg (object) context object for the callback = (object) Set object \*/ setproto.forEach = function (callback, thisArg) { for (var i = 0, ii = this.items.length; i < ii; i++) { if (callback.call(thisArg, this.items[i], i) === false) { return this; } } return this; }; for (var method in elproto) if (elproto[has](method)) { setproto[method] = (function (methodname) { return function () { var arg = arguments; return this.forEach(function (el) { el[methodname][apply](el, arg); }); }; })(method); } setproto.attr = function (name, value) { if (name && R.is(name, array) && R.is(name[0], "object")) { for (var j = 0, jj = name.length; j < jj; j++) { this.items[j].attr(name[j]); } } else { for (var i = 0, ii = this.items.length; i < ii; i++) { this.items[i].attr(name, value); } } return this; }; /*\ * Set.clear [ method ] ** * Removeds all elements from the set \*/ setproto.clear = function () { while (this.length) { this.pop(); } }; /*\ * Set.splice [ method ] ** * Removes given element from the set ** > Parameters ** - index (number) position of the deletion - count (number) number of element to remove - insertion… (object) #optional elements to insert = (object) set elements that were deleted \*/ setproto.splice = function (index, count, insertion) { index = index < 0 ? mmax(this.length + index, 0) : index; count = mmax(0, mmin(this.length - index, count)); var tail = [], todel = [], args = [], i; for (i = 2; i < arguments.length; i++) { args.push(arguments[i]); } for (i = 0; i < count; i++) { todel.push(this[index + i]); } for (; i < this.length - index; i++) { tail.push(this[index + i]); } var arglen = args.length; for (i = 0; i < arglen + tail.length; i++) { this.items[index + i] = this[index + i] = i < arglen ? args[i] : tail[i - arglen]; } i = this.items.length = this.length -= count - arglen; while (this[i]) { delete this[i++]; } return new Set(todel); }; /*\ * Set.exclude [ method ] ** * Removes given element from the set ** > Parameters ** - element (object) element to remove = (boolean) `true` if object was found & removed from the set \*/ setproto.exclude = function (el) { for (var i = 0, ii = this.length; i < ii; i++) if (this[i] == el) { this.splice(i, 1); return true; } }; setproto.animate = function (params, ms, easing, callback) { (R.is(easing, "function") || !easing) && (callback = easing || null); var len = this.items.length, i = len, item, set = this, collector; if (!len) { return this; } callback && (collector = function () { !--len && callback.call(set); }); easing = R.is(easing, string) ? easing : collector; var anim = R.animation(params, ms, easing, collector); item = this.items[--i].animate(anim); while (i--) { this.items[i] && !this.items[i].removed && this.items[i].animateWith(item, anim, anim); (this.items[i] && !this.items[i].removed) || len--; } return this; }; setproto.insertAfter = function (el) { var i = this.items.length; while (i--) { this.items[i].insertAfter(el); } return this; }; setproto.getBBox = function () { var x = [], y = [], x2 = [], y2 = []; for (var i = this.items.length; i--;) if (!this.items[i].removed) { var box = this.items[i].getBBox(); x.push(box.x); y.push(box.y); x2.push(box.x + box.width); y2.push(box.y + box.height); } x = mmin[apply](0, x); y = mmin[apply](0, y); x2 = mmax[apply](0, x2); y2 = mmax[apply](0, y2); return { x: x, y: y, x2: x2, y2: y2, width: x2 - x, height: y2 - y }; }; setproto.clone = function (s) { s = this.paper.set(); for (var i = 0, ii = this.items.length; i < ii; i++) { s.push(this.items[i].clone()); } return s; }; setproto.toString = function () { return "Rapha\xebl\u2018s set"; }; setproto.glow = function(glowConfig) { var ret = this.paper.set(); this.forEach(function(shape, index){ var g = shape.glow(glowConfig); if(g != null){ g.forEach(function(shape2, index2){ ret.push(shape2); }); } }); return ret; }; /*\ * Set.isPointInside [ method ] ** * Determine if given point is inside this set’s elements ** > Parameters ** - x (number) x coordinate of the point - y (number) y coordinate of the point = (boolean) `true` if point is inside any of the set's elements \*/ setproto.isPointInside = function (x, y) { var isPointInside = false; this.forEach(function (el) { if (el.isPointInside(x, y)) { console.log('runned'); isPointInside = true; return false; // stop loop } }); return isPointInside; }; /*\ * Raphael.registerFont [ method ] ** * Adds given font to the registered set of fonts for Raphaël. Should be used as an internal call from within Cufón’s font file. * Returns original parameter, so it could be used with chaining. # <a href="http://wiki.github.com/sorccu/cufon/about">More about Cufón and how to convert your font form TTF, OTF, etc to JavaScript file.</a> ** > Parameters ** - font (object) the font to register = (object) the font you passed in > Usage | Cufon.registerFont(Raphael.registerFont({…})); \*/ R.registerFont = function (font) { if (!font.face) { return font; } this.fonts = this.fonts || {}; var fontcopy = { w: font.w, face: {}, glyphs: {} }, family = font.face["font-family"]; for (var prop in font.face) if (font.face[has](prop)) { fontcopy.face[prop] = font.face[prop]; } if (this.fonts[family]) { this.fonts[family].push(fontcopy); } else { this.fonts[family] = [fontcopy]; } if (!font.svg) { fontcopy.face["units-per-em"] = toInt(font.face["units-per-em"], 10); for (var glyph in font.glyphs) if (font.glyphs[has](glyph)) { var path = font.glyphs[glyph]; fontcopy.glyphs[glyph] = { w: path.w, k: {}, d: path.d && "M" + path.d.replace(/[mlcxtrv]/g, function (command) { return {l: "L", c: "C", x: "z", t: "m", r: "l", v: "c"}[command] || "M"; }) + "z" }; if (path.k) { for (var k in path.k) if (path[has](k)) { fontcopy.glyphs[glyph].k[k] = path.k[k]; } } } } return font; }; /*\ * Paper.getFont [ method ] ** * Finds font object in the registered fonts by given parameters. You could specify only one word from the font name, like “Myriad” for “Myriad Pro”. ** > Parameters ** - family (string) font family name or any word from it - weight (string) #optional font weight - style (string) #optional font style - stretch (string) #optional font stretch = (object) the font object > Usage | paper.print(100, 100, "Test string", paper.getFont("Times", 800), 30); \*/ paperproto.getFont = function (family, weight, style, stretch) { stretch = stretch || "normal"; style = style || "normal"; weight = +weight || {normal: 400, bold: 700, lighter: 300, bolder: 800}[weight] || 400; if (!R.fonts) { return; } var font = R.fonts[family]; if (!font) { var name = new RegExp("(^|\\s)" + family.replace(/[^\w\d\s+!~.:_-]/g, E) + "(\\s|$)", "i"); for (var fontName in R.fonts) if (R.fonts[has](fontName)) { if (name.test(fontName)) { font = R.fonts[fontName]; break; } } } var thefont; if (font) { for (var i = 0, ii = font.length; i < ii; i++) { thefont = font[i]; if (thefont.face["font-weight"] == weight && (thefont.face["font-style"] == style || !thefont.face["font-style"]) && thefont.face["font-stretch"] == stretch) { break; } } } return thefont; }; /*\ * Paper.print [ method ] ** * Creates path that represent given text written using given font at given position with given size. * Result of the method is path element that contains whole text as a separate path. ** > Parameters ** - x (number) x position of the text - y (number) y position of the text - string (string) text to print - font (object) font object, see @Paper.getFont - size (number) #optional size of the font, default is `16` - origin (string) #optional could be `"baseline"` or `"middle"`, default is `"middle"` - letter_spacing (number) #optional number in range `-1..1`, default is `0` - line_spacing (number) #optional number in range `1..3`, default is `1` = (object) resulting path element, which consist of all letters > Usage | var txt = r.print(10, 50, "print", r.getFont("Museo"), 30).attr({fill: "#fff"}); \*/ paperproto.print = function (x, y, string, font, size, origin, letter_spacing, line_spacing) { origin = origin || "middle"; // baseline|middle letter_spacing = mmax(mmin(letter_spacing || 0, 1), -1); line_spacing = mmax(mmin(line_spacing || 1, 3), 1); var letters = Str(string)[split](E), shift = 0, notfirst = 0, path = E, scale; R.is(font, "string") && (font = this.getFont(font)); if (font) { scale = (size || 16) / font.face["units-per-em"]; var bb = font.face.bbox[split](separator), top = +bb[0], lineHeight = bb[3] - bb[1], shifty = 0, height = +bb[1] + (origin == "baseline" ? lineHeight + (+font.face.descent) : lineHeight / 2); for (var i = 0, ii = letters.length; i < ii; i++) { if (letters[i] == "\n") { shift = 0; curr = 0; notfirst = 0; shifty += lineHeight * line_spacing; } else { var prev = notfirst && font.glyphs[letters[i - 1]] || {}, curr = font.glyphs[letters[i]]; shift += notfirst ? (prev.w || font.w) + (prev.k && prev.k[letters[i]] || 0) + (font.w * letter_spacing) : 0; notfirst = 1; } if (curr && curr.d) { path += R.transformPath(curr.d, ["t", shift * scale, shifty * scale, "s", scale, scale, top, height, "t", (x - top) / scale, (y - height) / scale]); } } } return this.path(path).attr({ fill: "#000", stroke: "none" }); }; /*\ * Paper.add [ method ] ** * Imports elements in JSON array in format `{type: type, <attributes>}` ** > Parameters ** - json (array) = (object) resulting set of imported elements > Usage | paper.add([ | { | type: "circle", | cx: 10, | cy: 10, | r: 5 | }, | { | type: "rect", | x: 10, | y: 10, | width: 10, | height: 10, | fill: "#fc0" | } | ]); \*/ paperproto.add = function (json) { if (R.is(json, "array")) { var res = this.set(), i = 0, ii = json.length, j; for (; i < ii; i++) { j = json[i] || {}; elements[has](j.type) && res.push(this[j.type]().attr(j)); } } return res; }; /*\ * Raphael.format [ method ] ** * Simple format function. Replaces construction of type “`{<number>}`” to the corresponding argument. ** > Parameters ** - token (string) string to format - … (string) rest of arguments will be treated as parameters for replacement = (string) formated string > Usage | var x = 10, | y = 20, | width = 40, | height = 50; | // this will draw a rectangular shape equivalent to "M10,20h40v50h-40z" | paper.path(Raphael.format("M{0},{1}h{2}v{3}h{4}z", x, y, width, height, -width)); \*/ R.format = function (token, params) { var args = R.is(params, array) ? [0][concat](params) : arguments; token && R.is(token, string) && args.length - 1 && (token = token.replace(formatrg, function (str, i) { return args[++i] == null ? E : args[i]; })); return token || E; }; /*\ * Raphael.fullfill [ method ] ** * A little bit more advanced format function than @Raphael.format. Replaces construction of type “`{<name>}`” to the corresponding argument. ** > Parameters ** - token (string) string to format - json (object) object which properties will be used as a replacement = (string) formated string > Usage | // this will draw a rectangular shape equivalent to "M10,20h40v50h-40z" | paper.path(Raphael.fullfill("M{x},{y}h{dim.width}v{dim.height}h{dim['negative width']}z", { | x: 10, | y: 20, | dim: { | width: 40, | height: 50, | "negative width": -40 | } | })); \*/ R.fullfill = (function () { var tokenRegex = /\{([^\}]+)\}/g, objNotationRegex = /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g, // matches .xxxxx or ["xxxxx"] to run over object properties replacer = function (all, key, obj) { var res = obj; key.replace(objNotationRegex, function (all, name, quote, quotedName, isFunc) { name = name || quotedName; if (res) { if (name in res) { res = res[name]; } typeof res == "function" && isFunc && (res = res()); } }); res = (res == null || res == obj ? all : res) + ""; return res; }; return function (str, obj) { return String(str).replace(tokenRegex, function (all, key) { return replacer(all, key, obj); }); }; })(); /*\ * Raphael.ninja [ method ] ** * If you want to leave no trace of Raphaël (Well, Raphaël creates only one global variable `Raphael`, but anyway.) You can use `ninja` method. * Beware, that in this case plugins could stop working, because they are depending on global variable existance. ** = (object) Raphael object > Usage | (function (local_raphael) { | var paper = local_raphael(10, 10, 320, 200); | … | })(Raphael.ninja()); \*/ R.ninja = function () { oldRaphael.was ? (g.win.Raphael = oldRaphael.is) : delete Raphael; return R; }; /*\ * Raphael.st [ property (object) ] ** * You can add your own method to elements and sets. It is wise to add a set method for each element method * you added, so you will be able to call the same method on sets too. ** * See also @Raphael.el. > Usage | Raphael.el.red = function () { | this.attr({fill: "#f00"}); | }; | Raphael.st.red = function () { | this.forEach(function (el) { | el.red(); | }); | }; | // then use it | paper.set(paper.circle(100, 100, 20), paper.circle(110, 100, 20)).red(); \*/ R.st = setproto; // Firefox <3.6 fix: http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html (function (doc, loaded, f) { if (doc.readyState == null && doc.addEventListener){ doc.addEventListener(loaded, f = function () { doc.removeEventListener(loaded, f, false); doc.readyState = "complete"; }, false); doc.readyState = "loading"; } function isLoaded() { (/in/).test(doc.readyState) ? setTimeout(isLoaded, 9) : R.eve("raphael.DOMload"); } isLoaded(); })(document, "DOMContentLoaded"); eve.on("raphael.DOMload", function () { loaded = true; }); // ┌─────────────────────────────────────────────────────────────────────┐ \\ // │ Raphaël - JavaScript Vector Library │ \\ // ├─────────────────────────────────────────────────────────────────────┤ \\ // │ SVG Module │ \\ // ├─────────────────────────────────────────────────────────────────────┤ \\ // │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com) │ \\ // │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com) │ \\ // │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\ // └─────────────────────────────────────────────────────────────────────┘ \\ (function(){ if (!R.svg) { return; } var has = "hasOwnProperty", Str = String, toFloat = parseFloat, toInt = parseInt, math = Math, mmax = math.max, abs = math.abs, pow = math.pow, separator = /[, ]+/, eve = R.eve, E = "", S = " "; var xlink = "http://www.w3.org/1999/xlink", markers = { block: "M5,0 0,2.5 5,5z", classic: "M5,0 0,2.5 5,5 3.5,3 3.5,2z", diamond: "M2.5,0 5,2.5 2.5,5 0,2.5z", open: "M6,1 1,3.5 6,6", oval: "M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z" }, markerCounter = {}; R.toString = function () { return "Your browser supports SVG.\nYou are running Rapha\xebl " + this.version; }; var $ = function (el, attr) { if (attr) { if (typeof el == "string") { el = $(el); } for (var key in attr) if (attr[has](key)) { if (key.substring(0, 6) == "xlink:") { el.setAttributeNS(xlink, key.substring(6), Str(attr[key])); } else { el.setAttribute(key, Str(attr[key])); } } } else { el = R._g.doc.createElementNS("http://www.w3.org/2000/svg", el); el.style && (el.style.webkitTapHighlightColor = "rgba(0,0,0,0)"); } return el; }, addGradientFill = function (element, gradient) { var type = "linear", id = element.id + gradient, fx = .5, fy = .5, o = element.node, SVG = element.paper, s = o.style, el = R._g.doc.getElementById(id); if (!el) { gradient = Str(gradient).replace(R._radial_gradient, function (all, _fx, _fy) { type = "radial"; if (_fx && _fy) { fx = toFloat(_fx); fy = toFloat(_fy); var dir = ((fy > .5) * 2 - 1); pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && (fy = math.sqrt(.25 - pow(fx - .5, 2)) * dir + .5) && fy != .5 && (fy = fy.toFixed(5) - 1e-5 * dir); } return E; }); gradient = gradient.split(/\s*\-\s*/); if (type == "linear") { var angle = gradient.shift(); angle = -toFloat(angle); if (isNaN(angle)) { return null; } var vector = [0, 0, math.cos(R.rad(angle)), math.sin(R.rad(angle))], max = 1 / (mmax(abs(vector[2]), abs(vector[3])) || 1); vector[2] *= max; vector[3] *= max; if (vector[2] < 0) { vector[0] = -vector[2]; vector[2] = 0; } if (vector[3] < 0) { vector[1] = -vector[3]; vector[3] = 0; } } var dots = R._parseDots(gradient); if (!dots) { return null; } id = id.replace(/[\(\)\s,\xb0#]/g, "_"); if (element.gradient && id != element.gradient.id) { SVG.defs.removeChild(element.gradient); delete element.gradient; } if (!element.gradient) { el = $(type + "Gradient", {id: id}); element.gradient = el; $(el, type == "radial" ? { fx: fx, fy: fy } : { x1: vector[0], y1: vector[1], x2: vector[2], y2: vector[3], gradientTransform: element.matrix.invert() }); SVG.defs.appendChild(el); for (var i = 0, ii = dots.length; i < ii; i++) { el.appendChild($("stop", { offset: dots[i].offset ? dots[i].offset : i ? "100%" : "0%", "stop-color": dots[i].color || "#fff" })); } } } $(o, { fill: "url(#" + id + ")", opacity: 1, "fill-opacity": 1 }); s.fill = E; s.opacity = 1; s.fillOpacity = 1; return 1; }, updatePosition = function (o) { var bbox = o.getBBox(1); $(o.pattern, {patternTransform: o.matrix.invert() + " translate(" + bbox.x + "," + bbox.y + ")"}); }, addArrow = function (o, value, isEnd) { if (o.type == "path") { var values = Str(value).toLowerCase().split("-"), p = o.paper, se = isEnd ? "end" : "start", node = o.node, attrs = o.attrs, stroke = attrs["stroke-width"], i = values.length, type = "classic", from, to, dx, refX, attr, w = 3, h = 3, t = 5; while (i--) { switch (values[i]) { case "block": case "classic": case "oval": case "diamond": case "open": case "none": type = values[i]; break; case "wide": h = 5; break; case "narrow": h = 2; break; case "long": w = 5; break; case "short": w = 2; break; } } if (type == "open") { w += 2; h += 2; t += 2; dx = 1; refX = isEnd ? 4 : 1; attr = { fill: "none", stroke: attrs.stroke }; } else { refX = dx = w / 2; attr = { fill: attrs.stroke, stroke: "none" }; } if (o._.arrows) { if (isEnd) { o._.arrows.endPath && markerCounter[o._.arrows.endPath]--; o._.arrows.endMarker && markerCounter[o._.arrows.endMarker]--; } else { o._.arrows.startPath && markerCounter[o._.arrows.startPath]--; o._.arrows.startMarker && markerCounter[o._.arrows.startMarker]--; } } else { o._.arrows = {}; } if (type != "none") { var pathId = "raphael-marker-" + type, markerId = "raphael-marker-" + se + type + w + h; if (!R._g.doc.getElementById(pathId)) { p.defs.appendChild($($("path"), { "stroke-linecap": "round", d: markers[type], id: pathId })); markerCounter[pathId] = 1; } else { markerCounter[pathId]++; } var marker = R._g.doc.getElementById(markerId), use; if (!marker) { marker = $($("marker"), { id: markerId, markerHeight: h, markerWidth: w, orient: "auto", refX: refX, refY: h / 2 }); use = $($("use"), { "xlink:href": "#" + pathId, transform: (isEnd ? "rotate(180 " + w / 2 + " " + h / 2 + ") " : E) + "scale(" + w / t + "," + h / t + ")", "stroke-width": (1 / ((w / t + h / t) / 2)).toFixed(4) }); marker.appendChild(use); p.defs.appendChild(marker); markerCounter[markerId] = 1; } else { markerCounter[markerId]++; use = marker.getElementsByTagName("use")[0]; } $(use, attr); var delta = dx * (type != "diamond" && type != "oval"); if (isEnd) { from = o._.arrows.startdx * stroke || 0; to = R.getTotalLength(attrs.path) - delta * stroke; } else { from = delta * stroke; to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0); } attr = {}; attr["marker-" + se] = "url(#" + markerId + ")"; if (to || from) { attr.d = R.getSubpath(attrs.path, from, to); } $(node, attr); o._.arrows[se + "Path"] = pathId; o._.arrows[se + "Marker"] = markerId; o._.arrows[se + "dx"] = delta; o._.arrows[se + "Type"] = type; o._.arrows[se + "String"] = value; } else { if (isEnd) { from = o._.arrows.startdx * stroke || 0; to = R.getTotalLength(attrs.path) - from; } else { from = 0; to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0); } o._.arrows[se + "Path"] && $(node, {d: R.getSubpath(attrs.path, from, to)}); delete o._.arrows[se + "Path"]; delete o._.arrows[se + "Marker"]; delete o._.arrows[se + "dx"]; delete o._.arrows[se + "Type"]; delete o._.arrows[se + "String"]; } for (attr in markerCounter) if (markerCounter[has](attr) && !markerCounter[attr]) { var item = R._g.doc.getElementById(attr); item && item.parentNode.removeChild(item); } } }, dasharray = { "": [0], "none": [0], "-": [3, 1], ".": [1, 1], "-.": [3, 1, 1, 1], "-..": [3, 1, 1, 1, 1, 1], ". ": [1, 3], "- ": [4, 3], "--": [8, 3], "- .": [4, 3, 1, 3], "--.": [8, 3, 1, 3], "--..": [8, 3, 1, 3, 1, 3] }, addDashes = function (o, value, params) { value = dasharray[Str(value).toLowerCase()]; if (value) { var width = o.attrs["stroke-width"] || "1", butt = {round: width, square: width, butt: 0}[o.attrs["stroke-linecap"] || params["stroke-linecap"]] || 0, dashes = [], i = value.length; while (i--) { dashes[i] = value[i] * width + ((i % 2) ? 1 : -1) * butt; } $(o.node, {"stroke-dasharray": dashes.join(",")}); } }, setFillAndStroke = function (o, params) { var node = o.node, attrs = o.attrs, vis = node.style.visibility; node.style.visibility = "hidden"; for (var att in params) { if (params[has](att)) { if (!R._availableAttrs[has](att)) { continue; } var value = params[att]; attrs[att] = value; switch (att) { case "blur": o.blur(value); break; case "href": case "title": var hl = $("title"); var val = R._g.doc.createTextNode(value); hl.appendChild(val); node.appendChild(hl); break; case "target": var pn = node.parentNode; if (pn.tagName.toLowerCase() != "a") { var hl = $("a"); pn.insertBefore(hl, node); hl.appendChild(node); pn = hl; } if (att == "target") { pn.setAttributeNS(xlink, "show", value == "blank" ? "new" : value); } else { pn.setAttributeNS(xlink, att, value); } break; case "cursor": node.style.cursor = value; break; case "transform": o.transform(value); break; case "arrow-start": addArrow(o, value); break; case "arrow-end": addArrow(o, value, 1); break; case "clip-rect": var rect = Str(value).split(separator); if (rect.length == 4) { o.clip && o.clip.parentNode.parentNode.removeChild(o.clip.parentNode); var el = $("clipPath"), rc = $("rect"); el.id = R.createUUID(); $(rc, { x: rect[0], y: rect[1], width: rect[2], height: rect[3] }); el.appendChild(rc); o.paper.defs.appendChild(el); $(node, {"clip-path": "url(#" + el.id + ")"}); o.clip = rc; } if (!value) { var path = node.getAttribute("clip-path"); if (path) { var clip = R._g.doc.getElementById(path.replace(/(^url\(#|\)$)/g, E)); clip && clip.parentNode.removeChild(clip); $(node, {"clip-path": E}); delete o.clip; } } break; case "path": if (o.type == "path") { $(node, {d: value ? attrs.path = R._pathToAbsolute(value) : "M0,0"}); o._.dirty = 1; if (o._.arrows) { "startString" in o._.arrows && addArrow(o, o._.arrows.startString); "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1); } } break; case "width": node.setAttribute(att, value); o._.dirty = 1; if (attrs.fx) { att = "x"; value = attrs.x; } else { break; } case "x": if (attrs.fx) { value = -attrs.x - (attrs.width || 0); } case "rx": if (att == "rx" && o.type == "rect") { break; } case "cx": node.setAttribute(att, value); o.pattern && updatePosition(o); o._.dirty = 1; break; case "height": node.setAttribute(att, value); o._.dirty = 1; if (attrs.fy) { att = "y"; value = attrs.y; } else { break; } case "y": if (attrs.fy) { value = -attrs.y - (attrs.height || 0); } case "ry": if (att == "ry" && o.type == "rect") { break; } case "cy": node.setAttribute(att, value); o.pattern && updatePosition(o); o._.dirty = 1; break; case "r": if (o.type == "rect") { $(node, {rx: value, ry: value}); } else { node.setAttribute(att, value); } o._.dirty = 1; break; case "src": if (o.type == "image") { node.setAttributeNS(xlink, "href", value); } break; case "stroke-width": if (o._.sx != 1 || o._.sy != 1) { value /= mmax(abs(o._.sx), abs(o._.sy)) || 1; } if (o.paper._vbSize) { value *= o.paper._vbSize; } node.setAttribute(att, value); if (attrs["stroke-dasharray"]) { addDashes(o, attrs["stroke-dasharray"], params); } if (o._.arrows) { "startString" in o._.arrows && addArrow(o, o._.arrows.startString); "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1); } break; case "stroke-dasharray": addDashes(o, value, params); break; case "fill": var isURL = Str(value).match(R._ISURL); if (isURL) { el = $("pattern"); var ig = $("image"); el.id = R.createUUID(); $(el, {x: 0, y: 0, patternUnits: "userSpaceOnUse", height: 1, width: 1}); $(ig, {x: 0, y: 0, "xlink:href": isURL[1]}); el.appendChild(ig); (function (el) { R._preload(isURL[1], function () { var w = this.offsetWidth, h = this.offsetHeight; $(el, {width: w, height: h}); $(ig, {width: w, height: h}); o.paper.safari(); }); })(el); o.paper.defs.appendChild(el); $(node, {fill: "url(#" + el.id + ")"}); o.pattern = el; o.pattern && updatePosition(o); break; } var clr = R.getRGB(value); if (!clr.error) { delete params.gradient; delete attrs.gradient; !R.is(attrs.opacity, "undefined") && R.is(params.opacity, "undefined") && $(node, {opacity: attrs.opacity}); !R.is(attrs["fill-opacity"], "undefined") && R.is(params["fill-opacity"], "undefined") && $(node, {"fill-opacity": attrs["fill-opacity"]}); } else if ((o.type == "circle" || o.type == "ellipse" || Str(value).charAt() != "r") && addGradientFill(o, value)) { if ("opacity" in attrs || "fill-opacity" in attrs) { var gradient = R._g.doc.getElementById(node.getAttribute("fill").replace(/^url\(#|\)$/g, E)); if (gradient) { var stops = gradient.getElementsByTagName("stop"); $(stops[stops.length - 1], {"stop-opacity": ("opacity" in attrs ? attrs.opacity : 1) * ("fill-opacity" in attrs ? attrs["fill-opacity"] : 1)}); } } attrs.gradient = value; attrs.fill = "none"; break; } clr[has]("opacity") && $(node, {"fill-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity}); case "stroke": clr = R.getRGB(value); node.setAttribute(att, clr.hex); att == "stroke" && clr[has]("opacity") && $(node, {"stroke-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity}); if (att == "stroke" && o._.arrows) { "startString" in o._.arrows && addArrow(o, o._.arrows.startString); "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1); } break; case "gradient": (o.type == "circle" || o.type == "ellipse" || Str(value).charAt() != "r") && addGradientFill(o, value); break; case "opacity": if (attrs.gradient && !attrs[has]("stroke-opacity")) { $(node, {"stroke-opacity": value > 1 ? value / 100 : value}); } // fall case "fill-opacity": if (attrs.gradient) { gradient = R._g.doc.getElementById(node.getAttribute("fill").replace(/^url\(#|\)$/g, E)); if (gradient) { stops = gradient.getElementsByTagName("stop"); $(stops[stops.length - 1], {"stop-opacity": value}); } break; } default: att == "font-size" && (value = toInt(value, 10) + "px"); var cssrule = att.replace(/(\-.)/g, function (w) { return w.substring(1).toUpperCase(); }); node.style[cssrule] = value; o._.dirty = 1; node.setAttribute(att, value); break; } } } tuneText(o, params); node.style.visibility = vis; }, leading = 1.2, tuneText = function (el, params) { if (el.type != "text" || !(params[has]("text") || params[has]("font") || params[has]("font-size") || params[has]("x") || params[has]("y"))) { return; } var a = el.attrs, node = el.node, fontSize = node.firstChild ? toInt(R._g.doc.defaultView.getComputedStyle(node.firstChild, E).getPropertyValue("font-size"), 10) : 10; if (params[has]("text")) { a.text = params.text; while (node.firstChild) { node.removeChild(node.firstChild); } var texts = Str(params.text).split("\n"), tspans = [], tspan; for (var i = 0, ii = texts.length; i < ii; i++) { tspan = $("tspan"); i && $(tspan, {dy: fontSize * leading, x: a.x}); tspan.appendChild(R._g.doc.createTextNode(texts[i])); node.appendChild(tspan); tspans[i] = tspan; } } else { tspans = node.getElementsByTagName("tspan"); for (i = 0, ii = tspans.length; i < ii; i++) if (i) { $(tspans[i], {dy: fontSize * leading, x: a.x}); } else { $(tspans[0], {dy: 0}); } } $(node, {x: a.x, y: a.y}); el._.dirty = 1; var bb = el._getBBox(), dif = a.y - (bb.y + bb.height / 2); dif && R.is(dif, "finite") && $(tspans[0], {dy: dif}); }, Element = function (node, svg) { var X = 0, Y = 0; /*\ * Element.node [ property (object) ] ** * Gives you a reference to the DOM object, so you can assign event handlers or just mess around. ** * Note: Don’t mess with it. > Usage | // draw a circle at coordinate 10,10 with radius of 10 | var c = paper.circle(10, 10, 10); | c.node.onclick = function () { | c.attr("fill", "red"); | }; \*/ this[0] = this.node = node; /*\ * Element.raphael [ property (object) ] ** * Internal reference to @Raphael object. In case it is not available. > Usage | Raphael.el.red = function () { | var hsb = this.paper.raphael.rgb2hsb(this.attr("fill")); | hsb.h = 1; | this.attr({fill: this.paper.raphael.hsb2rgb(hsb).hex}); | } \*/ node.raphael = true; /*\ * Element.id [ property (number) ] ** * Unique id of the element. Especially usesful when you want to listen to events of the element, * because all events are fired in format `<module>.<action>.<id>`. Also useful for @Paper.getById method. \*/ this.id = R._oid++; node.raphaelid = this.id; this.matrix = R.matrix(); this.realPath = null; /*\ * Element.paper [ property (object) ] ** * Internal reference to “paper” where object drawn. Mainly for use in plugins and element extensions. > Usage | Raphael.el.cross = function () { | this.attr({fill: "red"}); | this.paper.path("M10,10L50,50M50,10L10,50") | .attr({stroke: "red"}); | } \*/ this.paper = svg; this.attrs = this.attrs || {}; this._ = { transform: [], sx: 1, sy: 1, deg: 0, dx: 0, dy: 0, dirty: 1 }; !svg.bottom && (svg.bottom = this); /*\ * Element.prev [ property (object) ] ** * Reference to the previous element in the hierarchy. \*/ this.prev = svg.top; svg.top && (svg.top.next = this); svg.top = this; /*\ * Element.next [ property (object) ] ** * Reference to the next element in the hierarchy. \*/ this.next = null; }, elproto = R.el; Element.prototype = elproto; elproto.constructor = Element; R._engine.path = function (pathString, SVG) { var el = $("path"); SVG.canvas && SVG.canvas.appendChild(el); var p = new Element(el, SVG); p.type = "path"; setFillAndStroke(p, { fill: "none", stroke: "#000", path: pathString }); return p; }; /*\ * Element.rotate [ method ] ** * Deprecated! Use @Element.transform instead. * Adds rotation by given angle around given point to the list of * transformations of the element. > Parameters - deg (number) angle in degrees - cx (number) #optional x coordinate of the centre of rotation - cy (number) #optional y coordinate of the centre of rotation * If cx & cy aren’t specified centre of the shape is used as a point of rotation. = (object) @Element \*/ elproto.rotate = function (deg, cx, cy) { if (this.removed) { return this; } deg = Str(deg).split(separator); if (deg.length - 1) { cx = toFloat(deg[1]); cy = toFloat(deg[2]); } deg = toFloat(deg[0]); (cy == null) && (cx = cy); if (cx == null || cy == null) { var bbox = this.getBBox(1); cx = bbox.x + bbox.width / 2; cy = bbox.y + bbox.height / 2; } this.transform(this._.transform.concat([["r", deg, cx, cy]])); return this; }; /*\ * Element.scale [ method ] ** * Deprecated! Use @Element.transform instead. * Adds scale by given amount relative to given point to the list of * transformations of the element. > Parameters - sx (number) horisontal scale amount - sy (number) vertical scale amount - cx (number) #optional x coordinate of the centre of scale - cy (number) #optional y coordinate of the centre of scale * If cx & cy aren’t specified centre of the shape is used instead. = (object) @Element \*/ elproto.scale = function (sx, sy, cx, cy) { if (this.removed) { return this; } sx = Str(sx).split(separator); if (sx.length - 1) { sy = toFloat(sx[1]); cx = toFloat(sx[2]); cy = toFloat(sx[3]); } sx = toFloat(sx[0]); (sy == null) && (sy = sx); (cy == null) && (cx = cy); if (cx == null || cy == null) { var bbox = this.getBBox(1); } cx = cx == null ? bbox.x + bbox.width / 2 : cx; cy = cy == null ? bbox.y + bbox.height / 2 : cy; this.transform(this._.transform.concat([["s", sx, sy, cx, cy]])); return this; }; /*\ * Element.translate [ method ] ** * Deprecated! Use @Element.transform instead. * Adds translation by given amount to the list of transformations of the element. > Parameters - dx (number) horisontal shift - dy (number) vertical shift = (object) @Element \*/ elproto.translate = function (dx, dy) { if (this.removed) { return this; } dx = Str(dx).split(separator); if (dx.length - 1) { dy = toFloat(dx[1]); } dx = toFloat(dx[0]) || 0; dy = +dy || 0; this.transform(this._.transform.concat([["t", dx, dy]])); return this; }; /*\ * Element.transform [ method ] ** * Adds transformation to the element which is separate to other attributes, * i.e. translation doesn’t change `x` or `y` of the rectange. The format * of transformation string is similar to the path string syntax: | "t100,100r30,100,100s2,2,100,100r45s1.5" * Each letter is a command. There are four commands: `t` is for translate, `r` is for rotate, `s` is for * scale and `m` is for matrix. * * There are also alternative “absolute” translation, rotation and scale: `T`, `R` and `S`. They will not take previous transformation into account. For example, `...T100,0` will always move element 100 px horisontally, while `...t100,0` could move it vertically if there is `r90` before. Just compare results of `r90t100,0` and `r90T100,0`. * * So, the example line above could be read like “translate by 100, 100; rotate 30° around 100, 100; scale twice around 100, 100; * rotate 45° around centre; scale 1.5 times relative to centre”. As you can see rotate and scale commands have origin * coordinates as optional parameters, the default is the centre point of the element. * Matrix accepts six parameters. > Usage | var el = paper.rect(10, 20, 300, 200); | // translate 100, 100, rotate 45°, translate -100, 0 | el.transform("t100,100r45t-100,0"); | // if you want you can append or prepend transformations | el.transform("...t50,50"); | el.transform("s2..."); | // or even wrap | el.transform("t50,50...t-50-50"); | // to reset transformation call method with empty string | el.transform(""); | // to get current value call it without parameters | console.log(el.transform()); > Parameters - tstr (string) #optional transformation string * If tstr isn’t specified = (string) current transformation string * else = (object) @Element \*/ elproto.transform = function (tstr) { var _ = this._; if (tstr == null) { return _.transform; } R._extractTransform(this, tstr); this.clip && $(this.clip, {transform: this.matrix.invert()}); this.pattern && updatePosition(this); this.node && $(this.node, {transform: this.matrix}); if (_.sx != 1 || _.sy != 1) { var sw = this.attrs[has]("stroke-width") ? this.attrs["stroke-width"] : 1; this.attr({"stroke-width": sw}); } return this; }; /*\ * Element.hide [ method ] ** * Makes element invisible. See @Element.show. = (object) @Element \*/ elproto.hide = function () { !this.removed && this.paper.safari(this.node.style.display = "none"); return this; }; /*\ * Element.show [ method ] ** * Makes element visible. See @Element.hide. = (object) @Element \*/ elproto.show = function () { !this.removed && this.paper.safari(this.node.style.display = ""); return this; }; /*\ * Element.remove [ method ] ** * Removes element from the paper. \*/ elproto.remove = function () { if (this.removed || !this.node.parentNode) { return; } var paper = this.paper; paper.__set__ && paper.__set__.exclude(this); eve.unbind("raphael.*.*." + this.id); if (this.gradient) { paper.defs.removeChild(this.gradient); } R._tear(this, paper); if (this.node.parentNode.tagName.toLowerCase() == "a") { this.node.parentNode.parentNode.removeChild(this.node.parentNode); } else { this.node.parentNode.removeChild(this.node); } for (var i in this) { this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null; } this.removed = true; }; elproto._getBBox = function () { if (this.node.style.display == "none") { this.show(); var hide = true; } var bbox = {}; try { bbox = this.node.getBBox(); } catch(e) { // Firefox 3.0.x plays badly here } finally { bbox = bbox || {}; } hide && this.hide(); return bbox; }; /*\ * Element.attr [ method ] ** * Sets the attributes of the element. > Parameters - attrName (string) attribute’s name - value (string) value * or - params (object) object of name/value pairs * or - attrName (string) attribute’s name * or - attrNames (array) in this case method returns array of current values for given attribute names = (object) @Element if attrsName & value or params are passed in. = (...) value of the attribute if only attrsName is passed in. = (array) array of values of the attribute if attrsNames is passed in. = (object) object of attributes if nothing is passed in. > Possible parameters # <p>Please refer to the <a href="http://www.w3.org/TR/SVG/" title="The W3C Recommendation for the SVG language describes these properties in detail.">SVG specification</a> for an explanation of these parameters.</p> o arrow-end (string) arrowhead on the end of the path. The format for string is `<type>[-<width>[-<length>]]`. Possible types: `classic`, `block`, `open`, `oval`, `diamond`, `none`, width: `wide`, `narrow`, `medium`, length: `long`, `short`, `midium`. o clip-rect (string) comma or space separated values: x, y, width and height o cursor (string) CSS type of the cursor o cx (number) the x-axis coordinate of the center of the circle, or ellipse o cy (number) the y-axis coordinate of the center of the circle, or ellipse o fill (string) colour, gradient or image o fill-opacity (number) o font (string) o font-family (string) o font-size (number) font size in pixels o font-weight (string) o height (number) o href (string) URL, if specified element behaves as hyperlink o opacity (number) o path (string) SVG path string format o r (number) radius of the circle, ellipse or rounded corner on the rect o rx (number) horisontal radius of the ellipse o ry (number) vertical radius of the ellipse o src (string) image URL, only works for @Element.image element o stroke (string) stroke colour o stroke-dasharray (string) [“”, “`-`”, “`.`”, “`-.`”, “`-..`”, “`. `”, “`- `”, “`--`”, “`- .`”, “`--.`”, “`--..`”] o stroke-linecap (string) [“`butt`”, “`square`”, “`round`”] o stroke-linejoin (string) [“`bevel`”, “`round`”, “`miter`”] o stroke-miterlimit (number) o stroke-opacity (number) o stroke-width (number) stroke width in pixels, default is '1' o target (string) used with href o text (string) contents of the text element. Use `\n` for multiline text o text-anchor (string) [“`start`”, “`middle`”, “`end`”], default is “`middle`” o title (string) will create tooltip with a given text o transform (string) see @Element.transform o width (number) o x (number) o y (number) > Gradients * Linear gradient format: “`‹angle›-‹colour›[-‹colour›[:‹offset›]]*-‹colour›`”, example: “`90-#fff-#000`” – 90° * gradient from white to black or “`0-#fff-#f00:20-#000`” – 0° gradient from white via red (at 20%) to black. * * radial gradient: “`r[(‹fx›, ‹fy›)]‹colour›[-‹colour›[:‹offset›]]*-‹colour›`”, example: “`r#fff-#000`” – * gradient from white to black or “`r(0.25, 0.75)#fff-#000`” – gradient from white to black with focus point * at 0.25, 0.75. Focus point coordinates are in 0..1 range. Radial gradients can only be applied to circles and ellipses. > Path String # <p>Please refer to <a href="http://www.w3.org/TR/SVG/paths.html#PathData" title="Details of a path’s data attribute’s format are described in the SVG specification.">SVG documentation regarding path string</a>. Raphaël fully supports it.</p> > Colour Parsing # <ul> # <li>Colour name (“<code>red</code>”, “<code>green</code>”, “<code>cornflowerblue</code>”, etc)</li> # <li>#••• — shortened HTML colour: (“<code>#000</code>”, “<code>#fc0</code>”, etc)</li> # <li>#•••••• — full length HTML colour: (“<code>#000000</code>”, “<code>#bd2300</code>”)</li> # <li>rgb(•••, •••, •••) — red, green and blue channels’ values: (“<code>rgb(200, 100, 0)</code>”)</li> # <li>rgb(•••%, •••%, •••%) — same as above, but in %: (“<code>rgb(100%, 175%, 0%)</code>”)</li> # <li>rgba(•••, •••, •••, •••) — red, green and blue channels’ values: (“<code>rgba(200, 100, 0, .5)</code>”)</li> # <li>rgba(•••%, •••%, •••%, •••%) — same as above, but in %: (“<code>rgba(100%, 175%, 0%, 50%)</code>”)</li> # <li>hsb(•••, •••, •••) — hue, saturation and brightness values: (“<code>hsb(0.5, 0.25, 1)</code>”)</li> # <li>hsb(•••%, •••%, •••%) — same as above, but in %</li> # <li>hsba(•••, •••, •••, •••) — same as above, but with opacity</li> # <li>hsl(•••, •••, •••) — almost the same as hsb, see <a href="http://en.wikipedia.org/wiki/HSL_and_HSV" title="HSL and HSV - Wikipedia, the free encyclopedia">Wikipedia page</a></li> # <li>hsl(•••%, •••%, •••%) — same as above, but in %</li> # <li>hsla(•••, •••, •••, •••) — same as above, but with opacity</li> # <li>Optionally for hsb and hsl you could specify hue as a degree: “<code>hsl(240deg, 1, .5)</code>” or, if you want to go fancy, “<code>hsl(240°, 1, .5)</code>”</li> # </ul> \*/ elproto.attr = function (name, value) { if (this.removed) { return this; } if (name == null) { var res = {}; for (var a in this.attrs) if (this.attrs[has](a)) { res[a] = this.attrs[a]; } res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient; res.transform = this._.transform; return res; } if (value == null && R.is(name, "string")) { if (name == "fill" && this.attrs.fill == "none" && this.attrs.gradient) { return this.attrs.gradient; } if (name == "transform") { return this._.transform; } var names = name.split(separator), out = {}; for (var i = 0, ii = names.length; i < ii; i++) { name = names[i]; if (name in this.attrs) { out[name] = this.attrs[name]; } else if (R.is(this.paper.customAttributes[name], "function")) { out[name] = this.paper.customAttributes[name].def; } else { out[name] = R._availableAttrs[name]; } } return ii - 1 ? out : out[names[0]]; } if (value == null && R.is(name, "array")) { out = {}; for (i = 0, ii = name.length; i < ii; i++) { out[name[i]] = this.attr(name[i]); } return out; } if (value != null) { var params = {}; params[name] = value; } else if (name != null && R.is(name, "object")) { params = name; } for (var key in params) { eve("raphael.attr." + key + "." + this.id, this, params[key]); } for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) { var par = this.paper.customAttributes[key].apply(this, [].concat(params[key])); this.attrs[key] = params[key]; for (var subkey in par) if (par[has](subkey)) { params[subkey] = par[subkey]; } } setFillAndStroke(this, params); return this; }; /*\ * Element.toFront [ method ] ** * Moves the element so it is the closest to the viewer’s eyes, on top of other elements. = (object) @Element \*/ elproto.toFront = function () { if (this.removed) { return this; } if (this.node.parentNode.tagName.toLowerCase() == "a") { this.node.parentNode.parentNode.appendChild(this.node.parentNode); } else { this.node.parentNode.appendChild(this.node); } var svg = this.paper; svg.top != this && R._tofront(this, svg); return this; }; /*\ * Element.toBack [ method ] ** * Moves the element so it is the furthest from the viewer’s eyes, behind other elements. = (object) @Element \*/ elproto.toBack = function () { if (this.removed) { return this; } var parent = this.node.parentNode; if (parent.tagName.toLowerCase() == "a") { parent.parentNode.insertBefore(this.node.parentNode, this.node.parentNode.parentNode.firstChild); } else if (parent.firstChild != this.node) { parent.insertBefore(this.node, this.node.parentNode.firstChild); } R._toback(this, this.paper); var svg = this.paper; return this; }; /*\ * Element.insertAfter [ method ] ** * Inserts current object after the given one. = (object) @Element \*/ elproto.insertAfter = function (element) { if (this.removed) { return this; } var node = element.node || element[element.length - 1].node; if (node.nextSibling) { node.parentNode.insertBefore(this.node, node.nextSibling); } else { node.parentNode.appendChild(this.node); } R._insertafter(this, element, this.paper); return this; }; /*\ * Element.insertBefore [ method ] ** * Inserts current object before the given one. = (object) @Element \*/ elproto.insertBefore = function (element) { if (this.removed) { return this; } var node = element.node || element[0].node; node.parentNode.insertBefore(this.node, node); R._insertbefore(this, element, this.paper); return this; }; elproto.blur = function (size) { // Experimental. No Safari support. Use it on your own risk. var t = this; if (+size !== 0) { var fltr = $("filter"), blur = $("feGaussianBlur"); t.attrs.blur = size; fltr.id = R.createUUID(); $(blur, {stdDeviation: +size || 1.5}); fltr.appendChild(blur); t.paper.defs.appendChild(fltr); t._blur = fltr; $(t.node, {filter: "url(#" + fltr.id + ")"}); } else { if (t._blur) { t._blur.parentNode.removeChild(t._blur); delete t._blur; delete t.attrs.blur; } t.node.removeAttribute("filter"); } return t; }; R._engine.circle = function (svg, x, y, r) { var el = $("circle"); svg.canvas && svg.canvas.appendChild(el); var res = new Element(el, svg); res.attrs = {cx: x, cy: y, r: r, fill: "none", stroke: "#000"}; res.type = "circle"; $(el, res.attrs); return res; }; R._engine.rect = function (svg, x, y, w, h, r) { var el = $("rect"); svg.canvas && svg.canvas.appendChild(el); var res = new Element(el, svg); res.attrs = {x: x, y: y, width: w, height: h, r: r || 0, rx: r || 0, ry: r || 0, fill: "none", stroke: "#000"}; res.type = "rect"; $(el, res.attrs); return res; }; R._engine.ellipse = function (svg, x, y, rx, ry) { var el = $("ellipse"); svg.canvas && svg.canvas.appendChild(el); var res = new Element(el, svg); res.attrs = {cx: x, cy: y, rx: rx, ry: ry, fill: "none", stroke: "#000"}; res.type = "ellipse"; $(el, res.attrs); return res; }; R._engine.image = function (svg, src, x, y, w, h) { var el = $("image"); $(el, {x: x, y: y, width: w, height: h, preserveAspectRatio: "none"}); el.setAttributeNS(xlink, "href", src); svg.canvas && svg.canvas.appendChild(el); var res = new Element(el, svg); res.attrs = {x: x, y: y, width: w, height: h, src: src}; res.type = "image"; return res; }; R._engine.text = function (svg, x, y, text) { var el = $("text"); svg.canvas && svg.canvas.appendChild(el); var res = new Element(el, svg); res.attrs = { x: x, y: y, "text-anchor": "middle", text: text, font: R._availableAttrs.font, stroke: "none", fill: "#000" }; res.type = "text"; setFillAndStroke(res, res.attrs); return res; }; R._engine.setSize = function (width, height) { this.width = width || this.width; this.height = height || this.height; this.canvas.setAttribute("width", this.width); this.canvas.setAttribute("height", this.height); if (this._viewBox) { this.setViewBox.apply(this, this._viewBox); } return this; }; R._engine.create = function () { var con = R._getContainer.apply(0, arguments), container = con && con.container, x = con.x, y = con.y, width = con.width, height = con.height; if (!container) { throw new Error("SVG container not found."); } var cnvs = $("svg"), css = "overflow:hidden;", isFloating; x = x || 0; y = y || 0; width = width || 512; height = height || 342; $(cnvs, { height: height, version: 1.1, width: width, xmlns: "http://www.w3.org/2000/svg" }); if (container == 1) { cnvs.style.cssText = css + "position:absolute;left:" + x + "px;top:" + y + "px"; R._g.doc.body.appendChild(cnvs); isFloating = 1; } else { cnvs.style.cssText = css + "position:relative"; if (container.firstChild) { container.insertBefore(cnvs, container.firstChild); } else { container.appendChild(cnvs); } } container = new R._Paper; container.width = width; container.height = height; container.canvas = cnvs; container.clear(); container._left = container._top = 0; isFloating && (container.renderfix = function () {}); container.renderfix(); return container; }; R._engine.setViewBox = function (x, y, w, h, fit) { eve("raphael.setViewBox", this, this._viewBox, [x, y, w, h, fit]); var size = mmax(w / this.width, h / this.height), top = this.top, aspectRatio = fit ? "meet" : "xMinYMin", vb, sw; if (x == null) { if (this._vbSize) { size = 1; } delete this._vbSize; vb = "0 0 " + this.width + S + this.height; } else { this._vbSize = size; vb = x + S + y + S + w + S + h; } $(this.canvas, { viewBox: vb, preserveAspectRatio: aspectRatio }); while (size && top) { sw = "stroke-width" in top.attrs ? top.attrs["stroke-width"] : 1; top.attr({"stroke-width": sw}); top._.dirty = 1; top._.dirtyT = 1; top = top.prev; } this._viewBox = [x, y, w, h, !!fit]; return this; }; /*\ * Paper.renderfix [ method ] ** * Fixes the issue of Firefox and IE9 regarding subpixel rendering. If paper is dependant * on other elements after reflow it could shift half pixel which cause for lines to lost their crispness. * This method fixes the issue. ** Special thanks to Mariusz Nowak (http://www.medikoo.com/) for this method. \*/ R.prototype.renderfix = function () { var cnvs = this.canvas, s = cnvs.style, pos; try { pos = cnvs.getScreenCTM() || cnvs.createSVGMatrix(); } catch (e) { pos = cnvs.createSVGMatrix(); } var left = -pos.e % 1, top = -pos.f % 1; if (left || top) { if (left) { this._left = (this._left + left) % 1; s.left = this._left + "px"; } if (top) { this._top = (this._top + top) % 1; s.top = this._top + "px"; } } }; /*\ * Paper.clear [ method ] ** * Clears the paper, i.e. removes all the elements. \*/ R.prototype.clear = function () { R.eve("raphael.clear", this); var c = this.canvas; while (c.firstChild) { c.removeChild(c.firstChild); } this.bottom = this.top = null; (this.desc = $("desc")).appendChild(R._g.doc.createTextNode("Created with Rapha\xebl " + R.version)); c.appendChild(this.desc); c.appendChild(this.defs = $("defs")); }; /*\ * Paper.remove [ method ] ** * Removes the paper from the DOM. \*/ R.prototype.remove = function () { eve("raphael.remove", this); this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas); for (var i in this) { this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null; } }; var setproto = R.st; for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) { setproto[method] = (function (methodname) { return function () { var arg = arguments; return this.forEach(function (el) { el[methodname].apply(el, arg); }); }; })(method); } })(); // ┌─────────────────────────────────────────────────────────────────────┐ \\ // │ Raphaël - JavaScript Vector Library │ \\ // ├─────────────────────────────────────────────────────────────────────┤ \\ // │ VML Module │ \\ // ├─────────────────────────────────────────────────────────────────────┤ \\ // │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com) │ \\ // │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com) │ \\ // │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\ // └─────────────────────────────────────────────────────────────────────┘ \\ (function(){ if (!R.vml) { return; } var has = "hasOwnProperty", Str = String, toFloat = parseFloat, math = Math, round = math.round, mmax = math.max, mmin = math.min, abs = math.abs, fillString = "fill", separator = /[, ]+/, eve = R.eve, ms = " progid:DXImageTransform.Microsoft", S = " ", E = "", map = {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"}, bites = /([clmz]),?([^clmz]*)/gi, blurregexp = / progid:\S+Blur\([^\)]+\)/g, val = /-?[^,\s-]+/g, cssDot = "position:absolute;left:0;top:0;width:1px;height:1px", zoom = 21600, pathTypes = {path: 1, rect: 1, image: 1}, ovalTypes = {circle: 1, ellipse: 1}, path2vml = function (path) { var total = /[ahqstv]/ig, command = R._pathToAbsolute; Str(path).match(total) && (command = R._path2curve); total = /[clmz]/g; if (command == R._pathToAbsolute && !Str(path).match(total)) { var res = Str(path).replace(bites, function (all, command, args) { var vals = [], isMove = command.toLowerCase() == "m", res = map[command]; args.replace(val, function (value) { if (isMove && vals.length == 2) { res += vals + map[command == "m" ? "l" : "L"]; vals = []; } vals.push(round(value * zoom)); }); return res + vals; }); return res; } var pa = command(path), p, r; res = []; for (var i = 0, ii = pa.length; i < ii; i++) { p = pa[i]; r = pa[i][0].toLowerCase(); r == "z" && (r = "x"); for (var j = 1, jj = p.length; j < jj; j++) { r += round(p[j] * zoom) + (j != jj - 1 ? "," : E); } res.push(r); } return res.join(S); }, compensation = function (deg, dx, dy) { var m = R.matrix(); m.rotate(-deg, .5, .5); return { dx: m.x(dx, dy), dy: m.y(dx, dy) }; }, setCoords = function (p, sx, sy, dx, dy, deg) { var _ = p._, m = p.matrix, fillpos = _.fillpos, o = p.node, s = o.style, y = 1, flip = "", dxdy, kx = zoom / sx, ky = zoom / sy; s.visibility = "hidden"; if (!sx || !sy) { return; } o.coordsize = abs(kx) + S + abs(ky); s.rotation = deg * (sx * sy < 0 ? -1 : 1); if (deg) { var c = compensation(deg, dx, dy); dx = c.dx; dy = c.dy; } sx < 0 && (flip += "x"); sy < 0 && (flip += " y") && (y = -1); s.flip = flip; o.coordorigin = (dx * -kx) + S + (dy * -ky); if (fillpos || _.fillsize) { var fill = o.getElementsByTagName(fillString); fill = fill && fill[0]; o.removeChild(fill); if (fillpos) { c = compensation(deg, m.x(fillpos[0], fillpos[1]), m.y(fillpos[0], fillpos[1])); fill.position = c.dx * y + S + c.dy * y; } if (_.fillsize) { fill.size = _.fillsize[0] * abs(sx) + S + _.fillsize[1] * abs(sy); } o.appendChild(fill); } s.visibility = "visible"; }; R.toString = function () { return "Your browser doesn\u2019t support SVG. Falling down to VML.\nYou are running Rapha\xebl " + this.version; }; var addArrow = function (o, value, isEnd) { var values = Str(value).toLowerCase().split("-"), se = isEnd ? "end" : "start", i = values.length, type = "classic", w = "medium", h = "medium"; while (i--) { switch (values[i]) { case "block": case "classic": case "oval": case "diamond": case "open": case "none": type = values[i]; break; case "wide": case "narrow": h = values[i]; break; case "long": case "short": w = values[i]; break; } } var stroke = o.node.getElementsByTagName("stroke")[0]; stroke[se + "arrow"] = type; stroke[se + "arrowlength"] = w; stroke[se + "arrowwidth"] = h; }, setFillAndStroke = function (o, params) { // o.paper.canvas.style.display = "none"; o.attrs = o.attrs || {}; var node = o.node, a = o.attrs, s = node.style, xy, newpath = pathTypes[o.type] && (params.x != a.x || params.y != a.y || params.width != a.width || params.height != a.height || params.cx != a.cx || params.cy != a.cy || params.rx != a.rx || params.ry != a.ry || params.r != a.r), isOval = ovalTypes[o.type] && (a.cx != params.cx || a.cy != params.cy || a.r != params.r || a.rx != params.rx || a.ry != params.ry), res = o; for (var par in params) if (params[has](par)) { a[par] = params[par]; } if (newpath) { a.path = R._getPath[o.type](o); o._.dirty = 1; } params.href && (node.href = params.href); params.title && (node.title = params.title); params.target && (node.target = params.target); params.cursor && (s.cursor = params.cursor); "blur" in params && o.blur(params.blur); if (params.path && o.type == "path" || newpath) { node.path = path2vml(~Str(a.path).toLowerCase().indexOf("r") ? R._pathToAbsolute(a.path) : a.path); if (o.type == "image") { o._.fillpos = [a.x, a.y]; o._.fillsize = [a.width, a.height]; setCoords(o, 1, 1, 0, 0, 0); } } "transform" in params && o.transform(params.transform); if (isOval) { var cx = +a.cx, cy = +a.cy, rx = +a.rx || +a.r || 0, ry = +a.ry || +a.r || 0; node.path = R.format("ar{0},{1},{2},{3},{4},{1},{4},{1}x", round((cx - rx) * zoom), round((cy - ry) * zoom), round((cx + rx) * zoom), round((cy + ry) * zoom), round(cx * zoom)); o._.dirty = 1; } if ("clip-rect" in params) { var rect = Str(params["clip-rect"]).split(separator); if (rect.length == 4) { rect[2] = +rect[2] + (+rect[0]); rect[3] = +rect[3] + (+rect[1]); var div = node.clipRect || R._g.doc.createElement("div"), dstyle = div.style; dstyle.clip = R.format("rect({1}px {2}px {3}px {0}px)", rect); if (!node.clipRect) { dstyle.position = "absolute"; dstyle.top = 0; dstyle.left = 0; dstyle.width = o.paper.width + "px"; dstyle.height = o.paper.height + "px"; node.parentNode.insertBefore(div, node); div.appendChild(node); node.clipRect = div; } } if (!params["clip-rect"]) { node.clipRect && (node.clipRect.style.clip = "auto"); } } if (o.textpath) { var textpathStyle = o.textpath.style; params.font && (textpathStyle.font = params.font); params["font-family"] && (textpathStyle.fontFamily = '"' + params["font-family"].split(",")[0].replace(/^['"]+|['"]+$/g, E) + '"'); params["font-size"] && (textpathStyle.fontSize = params["font-size"]); params["font-weight"] && (textpathStyle.fontWeight = params["font-weight"]); params["font-style"] && (textpathStyle.fontStyle = params["font-style"]); } if ("arrow-start" in params) { addArrow(res, params["arrow-start"]); } if ("arrow-end" in params) { addArrow(res, params["arrow-end"], 1); } if (params.opacity != null || params["stroke-width"] != null || params.fill != null || params.src != null || params.stroke != null || params["stroke-width"] != null || params["stroke-opacity"] != null || params["fill-opacity"] != null || params["stroke-dasharray"] != null || params["stroke-miterlimit"] != null || params["stroke-linejoin"] != null || params["stroke-linecap"] != null) { var fill = node.getElementsByTagName(fillString), newfill = false; fill = fill && fill[0]; !fill && (newfill = fill = createNode(fillString)); if (o.type == "image" && params.src) { fill.src = params.src; } params.fill && (fill.on = true); if (fill.on == null || params.fill == "none" || params.fill === null) { fill.on = false; } if (fill.on && params.fill) { var isURL = Str(params.fill).match(R._ISURL); if (isURL) { fill.parentNode == node && node.removeChild(fill); fill.rotate = true; fill.src = isURL[1]; fill.type = "tile"; var bbox = o.getBBox(1); fill.position = bbox.x + S + bbox.y; o._.fillpos = [bbox.x, bbox.y]; R._preload(isURL[1], function () { o._.fillsize = [this.offsetWidth, this.offsetHeight]; }); } else { fill.color = R.getRGB(params.fill).hex; fill.src = E; fill.type = "solid"; if (R.getRGB(params.fill).error && (res.type in {circle: 1, ellipse: 1} || Str(params.fill).charAt() != "r") && addGradientFill(res, params.fill, fill)) { a.fill = "none"; a.gradient = params.fill; fill.rotate = false; } } } if ("fill-opacity" in params || "opacity" in params) { var opacity = ((+a["fill-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+R.getRGB(params.fill).o + 1 || 2) - 1); opacity = mmin(mmax(opacity, 0), 1); fill.opacity = opacity; if (fill.src) { fill.color = "none"; } } node.appendChild(fill); var stroke = (node.getElementsByTagName("stroke") && node.getElementsByTagName("stroke")[0]), newstroke = false; !stroke && (newstroke = stroke = createNode("stroke")); if ((params.stroke && params.stroke != "none") || params["stroke-width"] || params["stroke-opacity"] != null || params["stroke-dasharray"] || params["stroke-miterlimit"] || params["stroke-linejoin"] || params["stroke-linecap"]) { stroke.on = true; } (params.stroke == "none" || params.stroke === null || stroke.on == null || params.stroke == 0 || params["stroke-width"] == 0) && (stroke.on = false); var strokeColor = R.getRGB(params.stroke); stroke.on && params.stroke && (stroke.color = strokeColor.hex); opacity = ((+a["stroke-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+strokeColor.o + 1 || 2) - 1); var width = (toFloat(params["stroke-width"]) || 1) * .75; opacity = mmin(mmax(opacity, 0), 1); params["stroke-width"] == null && (width = a["stroke-width"]); params["stroke-width"] && (stroke.weight = width); width && width < 1 && (opacity *= width) && (stroke.weight = 1); stroke.opacity = opacity; params["stroke-linejoin"] && (stroke.joinstyle = params["stroke-linejoin"] || "miter"); stroke.miterlimit = params["stroke-miterlimit"] || 8; params["stroke-linecap"] && (stroke.endcap = params["stroke-linecap"] == "butt" ? "flat" : params["stroke-linecap"] == "square" ? "square" : "round"); if (params["stroke-dasharray"]) { var dasharray = { "-": "shortdash", ".": "shortdot", "-.": "shortdashdot", "-..": "shortdashdotdot", ". ": "dot", "- ": "dash", "--": "longdash", "- .": "dashdot", "--.": "longdashdot", "--..": "longdashdotdot" }; stroke.dashstyle = dasharray[has](params["stroke-dasharray"]) ? dasharray[params["stroke-dasharray"]] : E; } newstroke && node.appendChild(stroke); } if (res.type == "text") { res.paper.canvas.style.display = E; var span = res.paper.span, m = 100, fontSize = a.font && a.font.match(/\d+(?:\.\d*)?(?=px)/); s = span.style; a.font && (s.font = a.font); a["font-family"] && (s.fontFamily = a["font-family"]); a["font-weight"] && (s.fontWeight = a["font-weight"]); a["font-style"] && (s.fontStyle = a["font-style"]); fontSize = toFloat(a["font-size"] || fontSize && fontSize[0]) || 10; s.fontSize = fontSize * m + "px"; res.textpath.string && (span.innerHTML = Str(res.textpath.string).replace(/</g, "<").replace(/&/g, "&").replace(/\n/g, "<br>")); var brect = span.getBoundingClientRect(); res.W = a.w = (brect.right - brect.left) / m; res.H = a.h = (brect.bottom - brect.top) / m; // res.paper.canvas.style.display = "none"; res.X = a.x; res.Y = a.y + res.H / 2; ("x" in params || "y" in params) && (res.path.v = R.format("m{0},{1}l{2},{1}", round(a.x * zoom), round(a.y * zoom), round(a.x * zoom) + 1)); var dirtyattrs = ["x", "y", "text", "font", "font-family", "font-weight", "font-style", "font-size"]; for (var d = 0, dd = dirtyattrs.length; d < dd; d++) if (dirtyattrs[d] in params) { res._.dirty = 1; break; } // text-anchor emulation switch (a["text-anchor"]) { case "start": res.textpath.style["v-text-align"] = "left"; res.bbx = res.W / 2; break; case "end": res.textpath.style["v-text-align"] = "right"; res.bbx = -res.W / 2; break; default: res.textpath.style["v-text-align"] = "center"; res.bbx = 0; break; } res.textpath.style["v-text-kern"] = true; } // res.paper.canvas.style.display = E; }, addGradientFill = function (o, gradient, fill) { o.attrs = o.attrs || {}; var attrs = o.attrs, pow = Math.pow, opacity, oindex, type = "linear", fxfy = ".5 .5"; o.attrs.gradient = gradient; gradient = Str(gradient).replace(R._radial_gradient, function (all, fx, fy) { type = "radial"; if (fx && fy) { fx = toFloat(fx); fy = toFloat(fy); pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && (fy = math.sqrt(.25 - pow(fx - .5, 2)) * ((fy > .5) * 2 - 1) + .5); fxfy = fx + S + fy; } return E; }); gradient = gradient.split(/\s*\-\s*/); if (type == "linear") { var angle = gradient.shift(); angle = -toFloat(angle); if (isNaN(angle)) { return null; } } var dots = R._parseDots(gradient); if (!dots) { return null; } o = o.shape || o.node; if (dots.length) { o.removeChild(fill); fill.on = true; fill.method = "none"; fill.color = dots[0].color; fill.color2 = dots[dots.length - 1].color; var clrs = []; for (var i = 0, ii = dots.length; i < ii; i++) { dots[i].offset && clrs.push(dots[i].offset + S + dots[i].color); } fill.colors = clrs.length ? clrs.join() : "0% " + fill.color; if (type == "radial") { fill.type = "gradientTitle"; fill.focus = "100%"; fill.focussize = "0 0"; fill.focusposition = fxfy; fill.angle = 0; } else { // fill.rotate= true; fill.type = "gradient"; fill.angle = (270 - angle) % 360; } o.appendChild(fill); } return 1; }, Element = function (node, vml) { this[0] = this.node = node; node.raphael = true; this.id = R._oid++; node.raphaelid = this.id; this.X = 0; this.Y = 0; this.attrs = {}; this.paper = vml; this.matrix = R.matrix(); this._ = { transform: [], sx: 1, sy: 1, dx: 0, dy: 0, deg: 0, dirty: 1, dirtyT: 1 }; !vml.bottom && (vml.bottom = this); this.prev = vml.top; vml.top && (vml.top.next = this); vml.top = this; this.next = null; }; var elproto = R.el; Element.prototype = elproto; elproto.constructor = Element; elproto.transform = function (tstr) { if (tstr == null) { return this._.transform; } var vbs = this.paper._viewBoxShift, vbt = vbs ? "s" + [vbs.scale, vbs.scale] + "-1-1t" + [vbs.dx, vbs.dy] : E, oldt; if (vbs) { oldt = tstr = Str(tstr).replace(/\.{3}|\u2026/g, this._.transform || E); } R._extractTransform(this, vbt + tstr); var matrix = this.matrix.clone(), skew = this.skew, o = this.node, split, isGrad = ~Str(this.attrs.fill).indexOf("-"), isPatt = !Str(this.attrs.fill).indexOf("url("); matrix.translate(1, 1); if (isPatt || isGrad || this.type == "image") { skew.matrix = "1 0 0 1"; skew.offset = "0 0"; split = matrix.split(); if ((isGrad && split.noRotation) || !split.isSimple) { o.style.filter = matrix.toFilter(); var bb = this.getBBox(), bbt = this.getBBox(1), dx = bb.x - bbt.x, dy = bb.y - bbt.y; o.coordorigin = (dx * -zoom) + S + (dy * -zoom); setCoords(this, 1, 1, dx, dy, 0); } else { o.style.filter = E; setCoords(this, split.scalex, split.scaley, split.dx, split.dy, split.rotate); } } else { o.style.filter = E; skew.matrix = Str(matrix); skew.offset = matrix.offset(); } oldt && (this._.transform = oldt); return this; }; elproto.rotate = function (deg, cx, cy) { if (this.removed) { return this; } if (deg == null) { return; } deg = Str(deg).split(separator); if (deg.length - 1) { cx = toFloat(deg[1]); cy = toFloat(deg[2]); } deg = toFloat(deg[0]); (cy == null) && (cx = cy); if (cx == null || cy == null) { var bbox = this.getBBox(1); cx = bbox.x + bbox.width / 2; cy = bbox.y + bbox.height / 2; } this._.dirtyT = 1; this.transform(this._.transform.concat([["r", deg, cx, cy]])); return this; }; elproto.translate = function (dx, dy) { if (this.removed) { return this; } dx = Str(dx).split(separator); if (dx.length - 1) { dy = toFloat(dx[1]); } dx = toFloat(dx[0]) || 0; dy = +dy || 0; if (this._.bbox) { this._.bbox.x += dx; this._.bbox.y += dy; } this.transform(this._.transform.concat([["t", dx, dy]])); return this; }; elproto.scale = function (sx, sy, cx, cy) { if (this.removed) { return this; } sx = Str(sx).split(separator); if (sx.length - 1) { sy = toFloat(sx[1]); cx = toFloat(sx[2]); cy = toFloat(sx[3]); isNaN(cx) && (cx = null); isNaN(cy) && (cy = null); } sx = toFloat(sx[0]); (sy == null) && (sy = sx); (cy == null) && (cx = cy); if (cx == null || cy == null) { var bbox = this.getBBox(1); } cx = cx == null ? bbox.x + bbox.width / 2 : cx; cy = cy == null ? bbox.y + bbox.height / 2 : cy; this.transform(this._.transform.concat([["s", sx, sy, cx, cy]])); this._.dirtyT = 1; return this; }; elproto.hide = function () { !this.removed && (this.node.style.display = "none"); return this; }; elproto.show = function () { !this.removed && (this.node.style.display = E); return this; }; elproto._getBBox = function () { if (this.removed) { return {}; } return { x: this.X + (this.bbx || 0) - this.W / 2, y: this.Y - this.H, width: this.W, height: this.H }; }; elproto.remove = function () { if (this.removed || !this.node.parentNode) { return; } this.paper.__set__ && this.paper.__set__.exclude(this); R.eve.unbind("raphael.*.*." + this.id); R._tear(this, this.paper); this.node.parentNode.removeChild(this.node); this.shape && this.shape.parentNode.removeChild(this.shape); for (var i in this) { this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null; } this.removed = true; }; elproto.attr = function (name, value) { if (this.removed) { return this; } if (name == null) { var res = {}; for (var a in this.attrs) if (this.attrs[has](a)) { res[a] = this.attrs[a]; } res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient; res.transform = this._.transform; return res; } if (value == null && R.is(name, "string")) { if (name == fillString && this.attrs.fill == "none" && this.attrs.gradient) { return this.attrs.gradient; } var names = name.split(separator), out = {}; for (var i = 0, ii = names.length; i < ii; i++) { name = names[i]; if (name in this.attrs) { out[name] = this.attrs[name]; } else if (R.is(this.paper.customAttributes[name], "function")) { out[name] = this.paper.customAttributes[name].def; } else { out[name] = R._availableAttrs[name]; } } return ii - 1 ? out : out[names[0]]; } if (this.attrs && value == null && R.is(name, "array")) { out = {}; for (i = 0, ii = name.length; i < ii; i++) { out[name[i]] = this.attr(name[i]); } return out; } var params; if (value != null) { params = {}; params[name] = value; } value == null && R.is(name, "object") && (params = name); for (var key in params) { eve("raphael.attr." + key + "." + this.id, this, params[key]); } if (params) { for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) { var par = this.paper.customAttributes[key].apply(this, [].concat(params[key])); this.attrs[key] = params[key]; for (var subkey in par) if (par[has](subkey)) { params[subkey] = par[subkey]; } } // this.paper.canvas.style.display = "none"; if (params.text && this.type == "text") { this.textpath.string = params.text; } setFillAndStroke(this, params); // this.paper.canvas.style.display = E; } return this; }; elproto.toFront = function () { !this.removed && this.node.parentNode.appendChild(this.node); this.paper && this.paper.top != this && R._tofront(this, this.paper); return this; }; elproto.toBack = function () { if (this.removed) { return this; } if (this.node.parentNode.firstChild != this.node) { this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild); R._toback(this, this.paper); } return this; }; elproto.insertAfter = function (element) { if (this.removed) { return this; } if (element.constructor == R.st.constructor) { element = element[element.length - 1]; } if (element.node.nextSibling) { element.node.parentNode.insertBefore(this.node, element.node.nextSibling); } else { element.node.parentNode.appendChild(this.node); } R._insertafter(this, element, this.paper); return this; }; elproto.insertBefore = function (element) { if (this.removed) { return this; } if (element.constructor == R.st.constructor) { element = element[0]; } element.node.parentNode.insertBefore(this.node, element.node); R._insertbefore(this, element, this.paper); return this; }; elproto.blur = function (size) { var s = this.node.runtimeStyle, f = s.filter; f = f.replace(blurregexp, E); if (+size !== 0) { this.attrs.blur = size; s.filter = f + S + ms + ".Blur(pixelradius=" + (+size || 1.5) + ")"; s.margin = R.format("-{0}px 0 0 -{0}px", round(+size || 1.5)); } else { s.filter = f; s.margin = 0; delete this.attrs.blur; } return this; }; R._engine.path = function (pathString, vml) { var el = createNode("shape"); el.style.cssText = cssDot; el.coordsize = zoom + S + zoom; el.coordorigin = vml.coordorigin; var p = new Element(el, vml), attr = {fill: "none", stroke: "#000"}; pathString && (attr.path = pathString); p.type = "path"; p.path = []; p.Path = E; setFillAndStroke(p, attr); vml.canvas.appendChild(el); var skew = createNode("skew"); skew.on = true; el.appendChild(skew); p.skew = skew; p.transform(E); return p; }; R._engine.rect = function (vml, x, y, w, h, r) { var path = R._rectPath(x, y, w, h, r), res = vml.path(path), a = res.attrs; res.X = a.x = x; res.Y = a.y = y; res.W = a.width = w; res.H = a.height = h; a.r = r; a.path = path; res.type = "rect"; return res; }; R._engine.ellipse = function (vml, x, y, rx, ry) { var res = vml.path(), a = res.attrs; res.X = x - rx; res.Y = y - ry; res.W = rx * 2; res.H = ry * 2; res.type = "ellipse"; setFillAndStroke(res, { cx: x, cy: y, rx: rx, ry: ry }); return res; }; R._engine.circle = function (vml, x, y, r) { var res = vml.path(), a = res.attrs; res.X = x - r; res.Y = y - r; res.W = res.H = r * 2; res.type = "circle"; setFillAndStroke(res, { cx: x, cy: y, r: r }); return res; }; R._engine.image = function (vml, src, x, y, w, h) { var path = R._rectPath(x, y, w, h), res = vml.path(path).attr({stroke: "none"}), a = res.attrs, node = res.node, fill = node.getElementsByTagName(fillString)[0]; a.src = src; res.X = a.x = x; res.Y = a.y = y; res.W = a.width = w; res.H = a.height = h; a.path = path; res.type = "image"; fill.parentNode == node && node.removeChild(fill); fill.rotate = true; fill.src = src; fill.type = "tile"; res._.fillpos = [x, y]; res._.fillsize = [w, h]; node.appendChild(fill); setCoords(res, 1, 1, 0, 0, 0); return res; }; R._engine.text = function (vml, x, y, text) { var el = createNode("shape"), path = createNode("path"), o = createNode("textpath"); x = x || 0; y = y || 0; text = text || ""; path.v = R.format("m{0},{1}l{2},{1}", round(x * zoom), round(y * zoom), round(x * zoom) + 1); path.textpathok = true; o.string = Str(text); o.on = true; el.style.cssText = cssDot; el.coordsize = zoom + S + zoom; el.coordorigin = "0 0"; var p = new Element(el, vml), attr = { fill: "#000", stroke: "none", font: R._availableAttrs.font, text: text }; p.shape = el; p.path = path; p.textpath = o; p.type = "text"; p.attrs.text = Str(text); p.attrs.x = x; p.attrs.y = y; p.attrs.w = 1; p.attrs.h = 1; setFillAndStroke(p, attr); el.appendChild(o); el.appendChild(path); vml.canvas.appendChild(el); var skew = createNode("skew"); skew.on = true; el.appendChild(skew); p.skew = skew; p.transform(E); return p; }; R._engine.setSize = function (width, height) { var cs = this.canvas.style; this.width = width; this.height = height; width == +width && (width += "px"); height == +height && (height += "px"); cs.width = width; cs.height = height; cs.clip = "rect(0 " + width + " " + height + " 0)"; if (this._viewBox) { R._engine.setViewBox.apply(this, this._viewBox); } return this; }; R._engine.setViewBox = function (x, y, w, h, fit) { R.eve("raphael.setViewBox", this, this._viewBox, [x, y, w, h, fit]); var width = this.width, height = this.height, size = 1 / mmax(w / width, h / height), H, W; if (fit) { H = height / h; W = width / w; if (w * H < width) { x -= (width - w * H) / 2 / H; } if (h * W < height) { y -= (height - h * W) / 2 / W; } } this._viewBox = [x, y, w, h, !!fit]; this._viewBoxShift = { dx: -x, dy: -y, scale: size }; this.forEach(function (el) { el.transform("..."); }); return this; }; var createNode; R._engine.initWin = function (win) { var doc = win.document; doc.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)"); try { !doc.namespaces.rvml && doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml"); createNode = function (tagName) { return doc.createElement('<rvml:' + tagName + ' class="rvml">'); }; } catch (e) { createNode = function (tagName) { return doc.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">'); }; } }; R._engine.initWin(R._g.win); R._engine.create = function () { var con = R._getContainer.apply(0, arguments), container = con.container, height = con.height, s, width = con.width, x = con.x, y = con.y; if (!container) { throw new Error("VML container not found."); } var res = new R._Paper, c = res.canvas = R._g.doc.createElement("div"), cs = c.style; x = x || 0; y = y || 0; width = width || 512; height = height || 342; res.width = width; res.height = height; width == +width && (width += "px"); height == +height && (height += "px"); res.coordsize = zoom * 1e3 + S + zoom * 1e3; res.coordorigin = "0 0"; res.span = R._g.doc.createElement("span"); res.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;"; c.appendChild(res.span); cs.cssText = R.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden", width, height); if (container == 1) { R._g.doc.body.appendChild(c); cs.left = x + "px"; cs.top = y + "px"; cs.position = "absolute"; } else { if (container.firstChild) { container.insertBefore(c, container.firstChild); } else { container.appendChild(c); } } res.renderfix = function () {}; return res; }; R.prototype.clear = function () { R.eve("raphael.clear", this); this.canvas.innerHTML = E; this.span = R._g.doc.createElement("span"); this.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;"; this.canvas.appendChild(this.span); this.bottom = this.top = null; }; R.prototype.remove = function () { R.eve("raphael.remove", this); this.canvas.parentNode.removeChild(this.canvas); for (var i in this) { this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null; } return true; }; var setproto = R.st; for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) { setproto[method] = (function (methodname) { return function () { var arg = arguments; return this.forEach(function (el) { el[methodname].apply(el, arg); }); }; })(method); } })(); // EXPOSE // SVG and VML are appended just before the EXPOSE line // Even with AMD, Raphael should be defined globally oldRaphael.was ? (g.win.Raphael = R) : (Raphael = R); return R; })); (function() { var $, Morris, minutesSpecHelper, secondsSpecHelper, __slice = [].slice, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; Morris = window.Morris = {}; $ = jQuery; Morris.EventEmitter = (function() { function EventEmitter() {} EventEmitter.prototype.on = function(name, handler) { if (this.handlers == null) { this.handlers = {}; } if (this.handlers[name] == null) { this.handlers[name] = []; } this.handlers[name].push(handler); return this; }; EventEmitter.prototype.fire = function() { var args, handler, name, _i, _len, _ref, _results; name = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; if ((this.handlers != null) && (this.handlers[name] != null)) { _ref = this.handlers[name]; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { handler = _ref[_i]; _results.push(handler.apply(null, args)); } return _results; } }; return EventEmitter; })(); Morris.commas = function(num) { var absnum, intnum, ret, strabsnum; if (num != null) { ret = num < 0 ? "-" : ""; absnum = Math.abs(num); intnum = Math.floor(absnum).toFixed(0); ret += intnum.replace(/(?=(?:\d{3})+$)(?!^)/g, ','); strabsnum = absnum.toString(); if (strabsnum.length > intnum.length) { ret += strabsnum.slice(intnum.length); } return ret; } else { return '-'; } }; Morris.pad2 = function(number) { return (number < 10 ? '0' : '') + number; }; Morris.Grid = (function(_super) { __extends(Grid, _super); function Grid(options) { var _this = this; if (typeof options.element === 'string') { this.el = $(document.getElementById(options.element)); } else { this.el = $(options.element); } if (!(this.el != null) || this.el.length === 0) { throw new Error("Graph container element not found"); } if (this.el.css('position') === 'static') { this.el.css('position', 'relative'); } this.options = $.extend({}, this.gridDefaults, this.defaults || {}, options); if (typeof this.options.units === 'string') { this.options.postUnits = options.units; } this.raphael = new Raphael(this.el[0]); this.elementWidth = null; this.elementHeight = null; this.dirty = false; if (this.init) { this.init(); } this.setData(this.options.data); this.el.bind('mousemove', function(evt) { var offset; offset = _this.el.offset(); return _this.fire('hovermove', evt.pageX - offset.left, evt.pageY - offset.top); }); this.el.bind('mouseout', function(evt) { return _this.fire('hoverout'); }); this.el.bind('touchstart touchmove touchend', function(evt) { var offset, touch; touch = evt.originalEvent.touches[0] || evt.originalEvent.changedTouches[0]; offset = _this.el.offset(); _this.fire('hover', touch.pageX - offset.left, touch.pageY - offset.top); return touch; }); this.el.bind('click', function(evt) { var offset; offset = _this.el.offset(); return _this.fire('gridclick', evt.pageX - offset.left, evt.pageY - offset.top); }); if (this.postInit) { this.postInit(); } } Grid.prototype.gridDefaults = { dateFormat: null, axes: true, grid: true, gridLineColor: '#aaa', gridStrokeWidth: 0.5, gridTextColor: '#888', gridTextSize: 12, gridTextFamily: 'sans-serif', gridTextWeight: 'normal', hideHover: false, yLabelFormat: null, xLabelAngle: 0, numLines: 5, padding: 25, parseTime: true, postUnits: '', preUnits: '', ymax: 'auto', ymin: 'auto 0', goals: [], goalStrokeWidth: 1.0, goalLineColors: ['#666633', '#999966', '#cc6666', '#663333'], events: [], eventStrokeWidth: 1.0, eventLineColors: ['#005a04', '#ccffbb', '#3a5f0b', '#005502'] }; Grid.prototype.setData = function(data, redraw) { var e, idx, index, maxGoal, minGoal, ret, row, step, total, y, ykey, ymax, ymin, yval; if (redraw == null) { redraw = true; } this.options.data = data; if (!(data != null) || data.length === 0) { this.data = []; this.raphael.clear(); if (this.hover != null) { this.hover.hide(); } return; } ymax = this.cumulative ? 0 : null; ymin = this.cumulative ? 0 : null; if (this.options.goals.length > 0) { minGoal = Math.min.apply(null, this.options.goals); maxGoal = Math.max.apply(null, this.options.goals); ymin = ymin != null ? Math.min(ymin, minGoal) : minGoal; ymax = ymax != null ? Math.max(ymax, maxGoal) : maxGoal; } this.data = (function() { var _i, _len, _results; _results = []; for (index = _i = 0, _len = data.length; _i < _len; index = ++_i) { row = data[index]; ret = {}; ret.label = row[this.options.xkey]; if (this.options.parseTime) { ret.x = Morris.parseDate(ret.label); if (this.options.dateFormat) { ret.label = this.options.dateFormat(ret.x); } else if (typeof ret.label === 'number') { ret.label = new Date(ret.label).toString(); } } else { ret.x = index; if (this.options.xLabelFormat) { ret.label = this.options.xLabelFormat(ret); } } total = 0; ret.y = (function() { var _j, _len1, _ref, _results1; _ref = this.options.ykeys; _results1 = []; for (idx = _j = 0, _len1 = _ref.length; _j < _len1; idx = ++_j) { ykey = _ref[idx]; yval = row[ykey]; if (typeof yval === 'string') { yval = parseFloat(yval); } if ((yval != null) && typeof yval !== 'number') { yval = null; } if (yval != null) { if (this.cumulative) { total += yval; } else { if (ymax != null) { ymax = Math.max(yval, ymax); ymin = Math.min(yval, ymin); } else { ymax = ymin = yval; } } } if (this.cumulative && (total != null)) { ymax = Math.max(total, ymax); ymin = Math.min(total, ymin); } _results1.push(yval); } return _results1; }).call(this); _results.push(ret); } return _results; }).call(this); if (this.options.parseTime) { this.data = this.data.sort(function(a, b) { return (a.x > b.x) - (b.x > a.x); }); } this.xmin = this.data[0].x; this.xmax = this.data[this.data.length - 1].x; this.events = []; if (this.options.parseTime && this.options.events.length > 0) { this.events = (function() { var _i, _len, _ref, _results; _ref = this.options.events; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { e = _ref[_i]; _results.push(Morris.parseDate(e)); } return _results; }).call(this); this.xmax = Math.max(this.xmax, Math.max.apply(null, this.events)); this.xmin = Math.min(this.xmin, Math.min.apply(null, this.events)); } if (this.xmin === this.xmax) { this.xmin -= 1; this.xmax += 1; } this.ymin = this.yboundary('min', ymin); this.ymax = this.yboundary('max', ymax); if (this.ymin === this.ymax) { if (ymin) { this.ymin -= 1; } this.ymax += 1; } if (this.options.axes === true || this.options.grid === true) { if (this.options.ymax === this.gridDefaults.ymax && this.options.ymin === this.gridDefaults.ymin) { this.grid = this.autoGridLines(this.ymin, this.ymax, this.options.numLines); this.ymin = Math.min(this.ymin, this.grid[0]); this.ymax = Math.max(this.ymax, this.grid[this.grid.length - 1]); } else { step = (this.ymax - this.ymin) / (this.options.numLines - 1); this.grid = (function() { var _i, _ref, _ref1, _results; _results = []; for (y = _i = _ref = this.ymin, _ref1 = this.ymax; _ref <= _ref1 ? _i <= _ref1 : _i >= _ref1; y = _i += step) { _results.push(y); } return _results; }).call(this); } } this.dirty = true; if (redraw) { return this.redraw(); } }; Grid.prototype.yboundary = function(boundaryType, currentValue) { var boundaryOption, suggestedValue; boundaryOption = this.options["y" + boundaryType]; if (typeof boundaryOption === 'string') { if (boundaryOption.slice(0, 4) === 'auto') { if (boundaryOption.length > 5) { suggestedValue = parseInt(boundaryOption.slice(5), 10); if (currentValue == null) { return suggestedValue; } return Math[boundaryType](currentValue, suggestedValue); } else { if (currentValue != null) { return currentValue; } else { return 0; } } } else { return parseInt(boundaryOption, 10); } } else { return boundaryOption; } }; Grid.prototype.autoGridLines = function(ymin, ymax, nlines) { var gmax, gmin, grid, smag, span, step, unit, y, ymag; span = ymax - ymin; ymag = Math.floor(Math.log(span) / Math.log(10)); unit = Math.pow(10, ymag); gmin = Math.floor(ymin / unit) * unit; gmax = Math.ceil(ymax / unit) * unit; step = (gmax - gmin) / (nlines - 1); if (unit === 1 && step > 1 && Math.ceil(step) !== step) { step = Math.ceil(step); gmax = gmin + step * (nlines - 1); } if (gmin < 0 && gmax > 0) { gmin = Math.floor(ymin / step) * step; gmax = Math.ceil(ymax / step) * step; } if (step < 1) { smag = Math.floor(Math.log(step) / Math.log(10)); grid = (function() { var _i, _results; _results = []; for (y = _i = gmin; gmin <= gmax ? _i <= gmax : _i >= gmax; y = _i += step) { _results.push(parseFloat(y.toFixed(1 - smag))); } return _results; })(); } else { grid = (function() { var _i, _results; _results = []; for (y = _i = gmin; gmin <= gmax ? _i <= gmax : _i >= gmax; y = _i += step) { _results.push(y); } return _results; })(); } return grid; }; Grid.prototype._calc = function() { var bottomOffsets, gridLine, h, i, w, yLabelWidths; w = this.el.width(); h = this.el.height(); if (this.elementWidth !== w || this.elementHeight !== h || this.dirty) { this.elementWidth = w; this.elementHeight = h; this.dirty = false; this.left = this.options.padding; this.right = this.elementWidth - this.options.padding; this.top = this.options.padding; this.bottom = this.elementHeight - this.options.padding; if (this.options.axes) { yLabelWidths = (function() { var _i, _len, _ref, _results; _ref = this.grid; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { gridLine = _ref[_i]; _results.push(this.measureText(this.yAxisFormat(gridLine)).width); } return _results; }).call(this); this.left += Math.max.apply(Math, yLabelWidths); bottomOffsets = (function() { var _i, _ref, _results; _results = []; for (i = _i = 0, _ref = this.data.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { _results.push(this.measureText(this.data[i].text, -this.options.xLabelAngle).height); } return _results; }).call(this); this.bottom -= Math.max.apply(Math, bottomOffsets); } this.width = Math.max(1, this.right - this.left); this.height = Math.max(1, this.bottom - this.top); this.dx = this.width / (this.xmax - this.xmin); this.dy = this.height / (this.ymax - this.ymin); if (this.calc) { return this.calc(); } } }; Grid.prototype.transY = function(y) { return this.bottom - (y - this.ymin) * this.dy; }; Grid.prototype.transX = function(x) { if (this.data.length === 1) { return (this.left + this.right) / 2; } else { return this.left + (x - this.xmin) * this.dx; } }; Grid.prototype.redraw = function() { this.raphael.clear(); this._calc(); this.drawGrid(); this.drawGoals(); this.drawEvents(); if (this.draw) { return this.draw(); } }; Grid.prototype.measureText = function(text, angle) { var ret, tt; if (angle == null) { angle = 0; } tt = this.raphael.text(100, 100, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).rotate(angle); ret = tt.getBBox(); tt.remove(); return ret; }; Grid.prototype.yAxisFormat = function(label) { return this.yLabelFormat(label); }; Grid.prototype.yLabelFormat = function(label) { if (typeof this.options.yLabelFormat === 'function') { return this.options.yLabelFormat(label); } else { return "" + this.options.preUnits + (Morris.commas(label)) + this.options.postUnits; } }; Grid.prototype.updateHover = function(x, y) { var hit, _ref; hit = this.hitTest(x, y); if (hit != null) { return (_ref = this.hover).update.apply(_ref, hit); } }; Grid.prototype.drawGrid = function() { var lineY, y, _i, _len, _ref, _results; if (this.options.grid === false && this.options.axes === false) { return; } _ref = this.grid; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { lineY = _ref[_i]; y = this.transY(lineY); if (this.options.axes) { this.drawYAxisLabel(this.left - this.options.padding / 2, y, this.yAxisFormat(lineY)); } if (this.options.grid) { _results.push(this.drawGridLine("M" + this.left + "," + y + "H" + (this.left + this.width))); } else { _results.push(void 0); } } return _results; }; Grid.prototype.drawGoals = function() { var color, goal, i, _i, _len, _ref, _results; _ref = this.options.goals; _results = []; for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { goal = _ref[i]; color = this.options.goalLineColors[i % this.options.goalLineColors.length]; _results.push(this.drawGoal(goal, color)); } return _results; }; Grid.prototype.drawEvents = function() { var color, event, i, _i, _len, _ref, _results; _ref = this.events; _results = []; for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { event = _ref[i]; color = this.options.eventLineColors[i % this.options.eventLineColors.length]; _results.push(this.drawEvent(event, color)); } return _results; }; Grid.prototype.drawGoal = function(goal, color) { return this.raphael.path("M" + this.left + "," + (this.transY(goal)) + "H" + this.right).attr('stroke', color).attr('stroke-width', this.options.goalStrokeWidth); }; Grid.prototype.drawEvent = function(event, color) { return this.raphael.path("M" + (this.transX(event)) + "," + this.bottom + "V" + this.top).attr('stroke', color).attr('stroke-width', this.options.eventStrokeWidth); }; Grid.prototype.drawYAxisLabel = function(xPos, yPos, text) { return this.raphael.text(xPos, yPos, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).attr('fill', this.options.gridTextColor).attr('text-anchor', 'end'); }; Grid.prototype.drawGridLine = function(path) { return this.raphael.path(path).attr('stroke', this.options.gridLineColor).attr('stroke-width', this.options.gridStrokeWidth); }; return Grid; })(Morris.EventEmitter); Morris.parseDate = function(date) { var isecs, m, msecs, n, o, offsetmins, p, q, r, ret, secs; if (typeof date === 'number') { return date; } m = date.match(/^(\d+) Q(\d)$/); n = date.match(/^(\d+)-(\d+)$/); o = date.match(/^(\d+)-(\d+)-(\d+)$/); p = date.match(/^(\d+) W(\d+)$/); q = date.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+)(Z|([+-])(\d\d):?(\d\d))?$/); r = date.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+):(\d+(\.\d+)?)(Z|([+-])(\d\d):?(\d\d))?$/); if (m) { return new Date(parseInt(m[1], 10), parseInt(m[2], 10) * 3 - 1, 1).getTime(); } else if (n) { return new Date(parseInt(n[1], 10), parseInt(n[2], 10) - 1, 1).getTime(); } else if (o) { return new Date(parseInt(o[1], 10), parseInt(o[2], 10) - 1, parseInt(o[3], 10)).getTime(); } else if (p) { ret = new Date(parseInt(p[1], 10), 0, 1); if (ret.getDay() !== 4) { ret.setMonth(0, 1 + ((4 - ret.getDay()) + 7) % 7); } return ret.getTime() + parseInt(p[2], 10) * 604800000; } else if (q) { if (!q[6]) { return new Date(parseInt(q[1], 10), parseInt(q[2], 10) - 1, parseInt(q[3], 10), parseInt(q[4], 10), parseInt(q[5], 10)).getTime(); } else { offsetmins = 0; if (q[6] !== 'Z') { offsetmins = parseInt(q[8], 10) * 60 + parseInt(q[9], 10); if (q[7] === '+') { offsetmins = 0 - offsetmins; } } return Date.UTC(parseInt(q[1], 10), parseInt(q[2], 10) - 1, parseInt(q[3], 10), parseInt(q[4], 10), parseInt(q[5], 10) + offsetmins); } } else if (r) { secs = parseFloat(r[6]); isecs = Math.floor(secs); msecs = Math.round((secs - isecs) * 1000); if (!r[8]) { return new Date(parseInt(r[1], 10), parseInt(r[2], 10) - 1, parseInt(r[3], 10), parseInt(r[4], 10), parseInt(r[5], 10), isecs, msecs).getTime(); } else { offsetmins = 0; if (r[8] !== 'Z') { offsetmins = parseInt(r[10], 10) * 60 + parseInt(r[11], 10); if (r[9] === '+') { offsetmins = 0 - offsetmins; } } return Date.UTC(parseInt(r[1], 10), parseInt(r[2], 10) - 1, parseInt(r[3], 10), parseInt(r[4], 10), parseInt(r[5], 10) + offsetmins, isecs, msecs); } } else { return new Date(parseInt(date, 10), 0, 1).getTime(); } }; Morris.Hover = (function() { Hover.defaults = { "class": 'morris-hover morris-default-style' }; function Hover(options) { if (options == null) { options = {}; } this.options = $.extend({}, Morris.Hover.defaults, options); this.el = $("<div class='" + this.options["class"] + "'></div>"); this.el.hide(); this.options.parent.append(this.el); } Hover.prototype.update = function(html, x, y) { this.html(html); this.show(); return this.moveTo(x, y); }; Hover.prototype.html = function(content) { return this.el.html(content); }; Hover.prototype.moveTo = function(x, y) { var hoverHeight, hoverWidth, left, parentHeight, parentWidth, top; parentWidth = this.options.parent.innerWidth(); parentHeight = this.options.parent.innerHeight(); hoverWidth = this.el.outerWidth(); hoverHeight = this.el.outerHeight(); left = Math.min(Math.max(0, x - hoverWidth / 2), parentWidth - hoverWidth); if (y != null) { top = y - hoverHeight - 10; if (top < 0) { top = y + 10; if (top + hoverHeight > parentHeight) { top = parentHeight / 2 - hoverHeight / 2; } } } else { top = parentHeight / 2 - hoverHeight / 2; } return this.el.css({ left: left + "px", top: parseInt(top) + "px" }); }; Hover.prototype.show = function() { return this.el.show(); }; Hover.prototype.hide = function() { return this.el.hide(); }; return Hover; })(); Morris.Line = (function(_super) { __extends(Line, _super); function Line(options) { this.hilight = __bind(this.hilight, this); this.onHoverOut = __bind(this.onHoverOut, this); this.onHoverMove = __bind(this.onHoverMove, this); this.onGridClick = __bind(this.onGridClick, this); if (!(this instanceof Morris.Line)) { return new Morris.Line(options); } Line.__super__.constructor.call(this, options); } Line.prototype.init = function() { this.pointGrow = Raphael.animation({ r: this.options.pointSize + 3 }, 25, 'linear'); this.pointShrink = Raphael.animation({ r: this.options.pointSize }, 25, 'linear'); if (this.options.hideHover !== 'always') { this.hover = new Morris.Hover({ parent: this.el }); this.on('hovermove', this.onHoverMove); this.on('hoverout', this.onHoverOut); return this.on('gridclick', this.onGridClick); } }; Line.prototype.defaults = { lineWidth: 3, pointSize: 4, lineColors: ['#0b62a4', '#7A92A3', '#4da74d', '#afd8f8', '#edc240', '#cb4b4b', '#9440ed'], pointWidths: [1], pointStrokeColors: ['#ffffff'], pointFillColors: [], smooth: true, xLabels: 'auto', xLabelFormat: null, xLabelMargin: 24, continuousLine: true, hideHover: false }; Line.prototype.calc = function() { this.calcPoints(); return this.generatePaths(); }; Line.prototype.calcPoints = function() { var row, y, _i, _len, _ref, _results; _ref = this.data; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { row = _ref[_i]; row._x = this.transX(row.x); row._y = (function() { var _j, _len1, _ref1, _results1; _ref1 = row.y; _results1 = []; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { y = _ref1[_j]; if (y != null) { _results1.push(this.transY(y)); } else { _results1.push(y); } } return _results1; }).call(this); _results.push(row._ymax = Math.min.apply(null, [this.bottom].concat((function() { var _j, _len1, _ref1, _results1; _ref1 = row._y; _results1 = []; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { y = _ref1[_j]; if (y != null) { _results1.push(y); } } return _results1; })()))); } return _results; }; Line.prototype.hitTest = function(x, y) { var index, r, _i, _len, _ref; if (this.data.length === 0) { return null; } _ref = this.data.slice(1); for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) { r = _ref[index]; if (x < (r._x + this.data[index]._x) / 2) { break; } } return index; }; Line.prototype.onGridClick = function(x, y) { var index; index = this.hitTest(x, y); return this.fire('click', index, this.options.data[index], x, y); }; Line.prototype.onHoverMove = function(x, y) { var index; index = this.hitTest(x, y); return this.displayHoverForRow(index); }; Line.prototype.onHoverOut = function() { if (this.options.hideHover !== false) { return this.displayHoverForRow(null); } }; Line.prototype.displayHoverForRow = function(index) { var _ref; if (index != null) { (_ref = this.hover).update.apply(_ref, this.hoverContentForRow(index)); return this.hilight(index); } else { this.hover.hide(); return this.hilight(); } }; Line.prototype.hoverContentForRow = function(index) { var content, j, row, y, _i, _len, _ref; row = this.data[index]; content = "<div class='morris-hover-row-label'>" + row.label + "</div>"; _ref = row.y; for (j = _i = 0, _len = _ref.length; _i < _len; j = ++_i) { y = _ref[j]; content += "<div class='morris-hover-point' style='color: " + (this.colorFor(row, j, 'label')) + "'>\n " + this.options.labels[j] + ":\n " + (this.yLabelFormat(y)) + "\n</div>"; } if (typeof this.options.hoverCallback === 'function') { content = this.options.hoverCallback(index, this.options, content); } return [content, row._x, row._ymax]; }; Line.prototype.generatePaths = function() { var c, coords, i, r, smooth; return this.paths = (function() { var _i, _ref, _ref1, _results; _results = []; for (i = _i = 0, _ref = this.options.ykeys.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { smooth = this.options.smooth === true || (_ref1 = this.options.ykeys[i], __indexOf.call(this.options.smooth, _ref1) >= 0); coords = (function() { var _j, _len, _ref2, _results1; _ref2 = this.data; _results1 = []; for (_j = 0, _len = _ref2.length; _j < _len; _j++) { r = _ref2[_j]; if (r._y[i] !== void 0) { _results1.push({ x: r._x, y: r._y[i] }); } } return _results1; }).call(this); if (this.options.continuousLine) { coords = (function() { var _j, _len, _results1; _results1 = []; for (_j = 0, _len = coords.length; _j < _len; _j++) { c = coords[_j]; if (c.y !== null) { _results1.push(c); } } return _results1; })(); } if (coords.length > 1) { _results.push(Morris.Line.createPath(coords, smooth, this.bottom)); } else { _results.push(null); } } return _results; }).call(this); }; Line.prototype.draw = function() { if (this.options.axes) { this.drawXAxis(); } this.drawSeries(); if (this.options.hideHover === false) { return this.displayHoverForRow(this.data.length - 1); } }; Line.prototype.drawXAxis = function() { var drawLabel, l, labels, prevAngleMargin, prevLabelMargin, row, ypos, _i, _len, _results, _this = this; ypos = this.bottom + this.options.padding / 2; prevLabelMargin = null; prevAngleMargin = null; drawLabel = function(labelText, xpos) { var label, labelBox, margin, offset, textBox; label = _this.drawXAxisLabel(_this.transX(xpos), ypos, labelText); textBox = label.getBBox(); label.transform("r" + (-_this.options.xLabelAngle)); labelBox = label.getBBox(); label.transform("t0," + (labelBox.height / 2) + "..."); if (_this.options.xLabelAngle !== 0) { offset = -0.5 * textBox.width * Math.cos(_this.options.xLabelAngle * Math.PI / 180.0); label.transform("t" + offset + ",0..."); } labelBox = label.getBBox(); if ((!(prevLabelMargin != null) || prevLabelMargin >= labelBox.x + labelBox.width || (prevAngleMargin != null) && prevAngleMargin >= labelBox.x) && labelBox.x >= 0 && (labelBox.x + labelBox.width) < _this.el.width()) { if (_this.options.xLabelAngle !== 0) { margin = 1.25 * _this.options.gridTextSize / Math.sin(_this.options.xLabelAngle * Math.PI / 180.0); prevAngleMargin = labelBox.x - margin; } return prevLabelMargin = labelBox.x - _this.options.xLabelMargin; } else { return label.remove(); } }; if (this.options.parseTime) { if (this.data.length === 1 && this.options.xLabels === 'auto') { labels = [[this.data[0].label, this.data[0].x]]; } else { labels = Morris.labelSeries(this.xmin, this.xmax, this.width, this.options.xLabels, this.options.xLabelFormat); } } else { labels = (function() { var _i, _len, _ref, _results; _ref = this.data; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { row = _ref[_i]; _results.push([row.label, row.x]); } return _results; }).call(this); } labels.reverse(); _results = []; for (_i = 0, _len = labels.length; _i < _len; _i++) { l = labels[_i]; _results.push(drawLabel(l[0], l[1])); } return _results; }; Line.prototype.drawSeries = function() { var i, _i, _j, _ref, _ref1, _results; this.seriesPoints = []; for (i = _i = _ref = this.options.ykeys.length - 1; _ref <= 0 ? _i <= 0 : _i >= 0; i = _ref <= 0 ? ++_i : --_i) { this._drawLineFor(i); } _results = []; for (i = _j = _ref1 = this.options.ykeys.length - 1; _ref1 <= 0 ? _j <= 0 : _j >= 0; i = _ref1 <= 0 ? ++_j : --_j) { _results.push(this._drawPointFor(i)); } return _results; }; Line.prototype._drawPointFor = function(index) { var circle, row, _i, _len, _ref, _results; this.seriesPoints[index] = []; _ref = this.data; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { row = _ref[_i]; circle = null; if (row._y[index] != null) { circle = this.drawLinePoint(row._x, row._y[index], this.options.pointSize, this.colorFor(row, index, 'point'), index); } _results.push(this.seriesPoints[index].push(circle)); } return _results; }; Line.prototype._drawLineFor = function(index) { var path; path = this.paths[index]; if (path !== null) { return this.drawLinePath(path, this.colorFor(null, index, 'line')); } }; Line.createPath = function(coords, smooth, bottom) { var coord, g, grads, i, ix, lg, path, prevCoord, x1, x2, y1, y2, _i, _len; path = ""; if (smooth) { grads = Morris.Line.gradients(coords); } prevCoord = { y: null }; for (i = _i = 0, _len = coords.length; _i < _len; i = ++_i) { coord = coords[i]; if (coord.y != null) { if (prevCoord.y != null) { if (smooth) { g = grads[i]; lg = grads[i - 1]; ix = (coord.x - prevCoord.x) / 4; x1 = prevCoord.x + ix; y1 = Math.min(bottom, prevCoord.y + ix * lg); x2 = coord.x - ix; y2 = Math.min(bottom, coord.y - ix * g); path += "C" + x1 + "," + y1 + "," + x2 + "," + y2 + "," + coord.x + "," + coord.y; } else { path += "L" + coord.x + "," + coord.y; } } else { if (!smooth || (grads[i] != null)) { path += "M" + coord.x + "," + coord.y; } } } prevCoord = coord; } return path; }; Line.gradients = function(coords) { var coord, grad, i, nextCoord, prevCoord, _i, _len, _results; grad = function(a, b) { return (a.y - b.y) / (a.x - b.x); }; _results = []; for (i = _i = 0, _len = coords.length; _i < _len; i = ++_i) { coord = coords[i]; if (coord.y != null) { nextCoord = coords[i + 1] || { y: null }; prevCoord = coords[i - 1] || { y: null }; if ((prevCoord.y != null) && (nextCoord.y != null)) { _results.push(grad(prevCoord, nextCoord)); } else if (prevCoord.y != null) { _results.push(grad(prevCoord, coord)); } else if (nextCoord.y != null) { _results.push(grad(coord, nextCoord)); } else { _results.push(null); } } else { _results.push(null); } } return _results; }; Line.prototype.hilight = function(index) { var i, _i, _j, _ref, _ref1; if (this.prevHilight !== null && this.prevHilight !== index) { for (i = _i = 0, _ref = this.seriesPoints.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; i = 0 <= _ref ? ++_i : --_i) { if (this.seriesPoints[i][this.prevHilight]) { this.seriesPoints[i][this.prevHilight].animate(this.pointShrink); } } } if (index !== null && this.prevHilight !== index) { for (i = _j = 0, _ref1 = this.seriesPoints.length - 1; 0 <= _ref1 ? _j <= _ref1 : _j >= _ref1; i = 0 <= _ref1 ? ++_j : --_j) { if (this.seriesPoints[i][index]) { this.seriesPoints[i][index].animate(this.pointGrow); } } } return this.prevHilight = index; }; Line.prototype.colorFor = function(row, sidx, type) { if (typeof this.options.lineColors === 'function') { return this.options.lineColors.call(this, row, sidx, type); } else if (type === 'point') { return this.options.pointFillColors[sidx % this.options.pointFillColors.length] || this.options.lineColors[sidx % this.options.lineColors.length]; } else { return this.options.lineColors[sidx % this.options.lineColors.length]; } }; Line.prototype.drawXAxisLabel = function(xPos, yPos, text) { return this.raphael.text(xPos, yPos, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).attr('fill', this.options.gridTextColor); }; Line.prototype.drawLinePath = function(path, lineColor) { return this.raphael.path(path).attr('stroke', lineColor).attr('stroke-width', this.options.lineWidth); }; Line.prototype.drawLinePoint = function(xPos, yPos, size, pointColor, lineIndex) { return this.raphael.circle(xPos, yPos, size).attr('fill', pointColor).attr('stroke-width', this.strokeWidthForSeries(lineIndex)).attr('stroke', this.strokeForSeries(lineIndex)); }; Line.prototype.strokeWidthForSeries = function(index) { return this.options.pointWidths[index % this.options.pointWidths.length]; }; Line.prototype.strokeForSeries = function(index) { return this.options.pointStrokeColors[index % this.options.pointStrokeColors.length]; }; return Line; })(Morris.Grid); Morris.labelSeries = function(dmin, dmax, pxwidth, specName, xLabelFormat) { var d, d0, ddensity, name, ret, s, spec, t, _i, _len, _ref; ddensity = 200 * (dmax - dmin) / pxwidth; d0 = new Date(dmin); spec = Morris.LABEL_SPECS[specName]; if (spec === void 0) { _ref = Morris.AUTO_LABEL_ORDER; for (_i = 0, _len = _ref.length; _i < _len; _i++) { name = _ref[_i]; s = Morris.LABEL_SPECS[name]; if (ddensity >= s.span) { spec = s; break; } } } if (spec === void 0) { spec = Morris.LABEL_SPECS["second"]; } if (xLabelFormat) { spec = $.extend({}, spec, { fmt: xLabelFormat }); } d = spec.start(d0); ret = []; while ((t = d.getTime()) <= dmax) { if (t >= dmin) { ret.push([spec.fmt(d), t]); } spec.incr(d); } return ret; }; minutesSpecHelper = function(interval) { return { span: interval * 60 * 1000, start: function(d) { return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours()); }, fmt: function(d) { return "" + (Morris.pad2(d.getHours())) + ":" + (Morris.pad2(d.getMinutes())); }, incr: function(d) { return d.setUTCMinutes(d.getUTCMinutes() + interval); } }; }; secondsSpecHelper = function(interval) { return { span: interval * 1000, start: function(d) { return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes()); }, fmt: function(d) { return "" + (Morris.pad2(d.getHours())) + ":" + (Morris.pad2(d.getMinutes())) + ":" + (Morris.pad2(d.getSeconds())); }, incr: function(d) { return d.setUTCSeconds(d.getUTCSeconds() + interval); } }; }; Morris.LABEL_SPECS = { "decade": { span: 172800000000, start: function(d) { return new Date(d.getFullYear() - d.getFullYear() % 10, 0, 1); }, fmt: function(d) { return "" + (d.getFullYear()); }, incr: function(d) { return d.setFullYear(d.getFullYear() + 10); } }, "year": { span: 17280000000, start: function(d) { return new Date(d.getFullYear(), 0, 1); }, fmt: function(d) { return "" + (d.getFullYear()); }, incr: function(d) { return d.setFullYear(d.getFullYear() + 1); } }, "month": { span: 2419200000, start: function(d) { return new Date(d.getFullYear(), d.getMonth(), 1); }, fmt: function(d) { return "" + (d.getFullYear()) + "-" + (Morris.pad2(d.getMonth() + 1)); }, incr: function(d) { return d.setMonth(d.getMonth() + 1); } }, "day": { span: 86400000, start: function(d) { return new Date(d.getFullYear(), d.getMonth(), d.getDate()); }, fmt: function(d) { return "" + (d.getFullYear()) + "-" + (Morris.pad2(d.getMonth() + 1)) + "-" + (Morris.pad2(d.getDate())); }, incr: function(d) { return d.setDate(d.getDate() + 1); } }, "hour": minutesSpecHelper(60), "30min": minutesSpecHelper(30), "15min": minutesSpecHelper(15), "10min": minutesSpecHelper(10), "5min": minutesSpecHelper(5), "minute": minutesSpecHelper(1), "30sec": secondsSpecHelper(30), "15sec": secondsSpecHelper(15), "10sec": secondsSpecHelper(10), "5sec": secondsSpecHelper(5), "second": secondsSpecHelper(1) }; Morris.AUTO_LABEL_ORDER = ["decade", "year", "month", "day", "hour", "30min", "15min", "10min", "5min", "minute", "30sec", "15sec", "10sec", "5sec", "second"]; Morris.Area = (function(_super) { var areaDefaults; __extends(Area, _super); areaDefaults = { fillOpacity: 'auto', behaveLikeLine: false }; function Area(options) { var areaOptions; if (!(this instanceof Morris.Area)) { return new Morris.Area(options); } areaOptions = $.extend({}, areaDefaults, options); this.cumulative = !areaOptions.behaveLikeLine; if (areaOptions.fillOpacity === 'auto') { areaOptions.fillOpacity = areaOptions.behaveLikeLine ? .8 : 1; } Area.__super__.constructor.call(this, areaOptions); } Area.prototype.calcPoints = function() { var row, total, y, _i, _len, _ref, _results; _ref = this.data; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { row = _ref[_i]; row._x = this.transX(row.x); total = 0; row._y = (function() { var _j, _len1, _ref1, _results1; _ref1 = row.y; _results1 = []; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { y = _ref1[_j]; if (this.options.behaveLikeLine) { _results1.push(this.transY(y)); } else { total += y || 0; _results1.push(this.transY(total)); } } return _results1; }).call(this); _results.push(row._ymax = Math.max.apply(Math, row._y)); } return _results; }; Area.prototype.drawSeries = function() { var i, range, _i, _j, _k, _len, _ref, _ref1, _results, _results1, _results2; this.seriesPoints = []; if (this.options.behaveLikeLine) { range = (function() { _results = []; for (var _i = 0, _ref = this.options.ykeys.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; 0 <= _ref ? _i++ : _i--){ _results.push(_i); } return _results; }).apply(this); } else { range = (function() { _results1 = []; for (var _j = _ref1 = this.options.ykeys.length - 1; _ref1 <= 0 ? _j <= 0 : _j >= 0; _ref1 <= 0 ? _j++ : _j--){ _results1.push(_j); } return _results1; }).apply(this); } _results2 = []; for (_k = 0, _len = range.length; _k < _len; _k++) { i = range[_k]; this._drawFillFor(i); this._drawLineFor(i); _results2.push(this._drawPointFor(i)); } return _results2; }; Area.prototype._drawFillFor = function(index) { var path; path = this.paths[index]; if (path !== null) { path = path + ("L" + (this.transX(this.xmax)) + "," + this.bottom + "L" + (this.transX(this.xmin)) + "," + this.bottom + "Z"); return this.drawFilledPath(path, this.fillForSeries(index)); } }; Area.prototype.fillForSeries = function(i) { var color; color = Raphael.rgb2hsl(this.colorFor(this.data[i], i, 'line')); return Raphael.hsl(color.h, this.options.behaveLikeLine ? color.s * 0.9 : color.s * 0.75, Math.min(0.98, this.options.behaveLikeLine ? color.l * 1.2 : color.l * 1.25)); }; Area.prototype.drawFilledPath = function(path, fill) { return this.raphael.path(path).attr('fill', fill).attr('fill-opacity', this.options.fillOpacity).attr('stroke-width', 0); }; return Area; })(Morris.Line); Morris.Bar = (function(_super) { __extends(Bar, _super); function Bar(options) { this.onHoverOut = __bind(this.onHoverOut, this); this.onHoverMove = __bind(this.onHoverMove, this); this.onGridClick = __bind(this.onGridClick, this); if (!(this instanceof Morris.Bar)) { return new Morris.Bar(options); } Bar.__super__.constructor.call(this, $.extend({}, options, { parseTime: false })); } Bar.prototype.init = function() { this.cumulative = this.options.stacked; if (this.options.hideHover !== 'always') { this.hover = new Morris.Hover({ parent: this.el }); this.on('hovermove', this.onHoverMove); this.on('hoverout', this.onHoverOut); return this.on('gridclick', this.onGridClick); } }; Bar.prototype.defaults = { barSizeRatio: 0.75, barGap: 3, barColors: ['#0b62a4', '#7a92a3', '#4da74d', '#afd8f8', '#edc240', '#cb4b4b', '#9440ed'], xLabelMargin: 50 }; Bar.prototype.calc = function() { var _ref; this.calcBars(); if (this.options.hideHover === false) { return (_ref = this.hover).update.apply(_ref, this.hoverContentForRow(this.data.length - 1)); } }; Bar.prototype.calcBars = function() { var idx, row, y, _i, _len, _ref, _results; _ref = this.data; _results = []; for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) { row = _ref[idx]; row._x = this.left + this.width * (idx + 0.5) / this.data.length; _results.push(row._y = (function() { var _j, _len1, _ref1, _results1; _ref1 = row.y; _results1 = []; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { y = _ref1[_j]; if (y != null) { _results1.push(this.transY(y)); } else { _results1.push(null); } } return _results1; }).call(this)); } return _results; }; Bar.prototype.draw = function() { if (this.options.axes) { this.drawXAxis(); } return this.drawSeries(); }; Bar.prototype.drawXAxis = function() { var i, label, labelBox, margin, offset, prevAngleMargin, prevLabelMargin, row, textBox, ypos, _i, _ref, _results; ypos = this.bottom + this.options.padding / 2; prevLabelMargin = null; prevAngleMargin = null; _results = []; for (i = _i = 0, _ref = this.data.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { row = this.data[this.data.length - 1 - i]; label = this.drawXAxisLabel(row._x, ypos, row.label); textBox = label.getBBox(); label.transform("r" + (-this.options.xLabelAngle)); labelBox = label.getBBox(); label.transform("t0," + (labelBox.height / 2) + "..."); if (this.options.xLabelAngle !== 0) { offset = -0.5 * textBox.width * Math.cos(this.options.xLabelAngle * Math.PI / 180.0); label.transform("t" + offset + ",0..."); } if ((!(prevLabelMargin != null) || prevLabelMargin >= labelBox.x + labelBox.width || (prevAngleMargin != null) && prevAngleMargin >= labelBox.x) && labelBox.x >= 0 && (labelBox.x + labelBox.width) < this.el.width()) { if (this.options.xLabelAngle !== 0) { margin = 1.25 * this.options.gridTextSize / Math.sin(this.options.xLabelAngle * Math.PI / 180.0); prevAngleMargin = labelBox.x - margin; } _results.push(prevLabelMargin = labelBox.x - this.options.xLabelMargin); } else { _results.push(label.remove()); } } return _results; }; Bar.prototype.drawSeries = function() { var barWidth, bottom, groupWidth, idx, lastTop, left, leftPadding, numBars, row, sidx, size, top, ypos, zeroPos; groupWidth = this.width / this.options.data.length; numBars = this.options.stacked != null ? 1 : this.options.ykeys.length; barWidth = (groupWidth * this.options.barSizeRatio - this.options.barGap * (numBars - 1)) / numBars; leftPadding = groupWidth * (1 - this.options.barSizeRatio) / 2; zeroPos = this.ymin <= 0 && this.ymax >= 0 ? this.transY(0) : null; return this.bars = (function() { var _i, _len, _ref, _results; _ref = this.data; _results = []; for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) { row = _ref[idx]; lastTop = 0; _results.push((function() { var _j, _len1, _ref1, _results1; _ref1 = row._y; _results1 = []; for (sidx = _j = 0, _len1 = _ref1.length; _j < _len1; sidx = ++_j) { ypos = _ref1[sidx]; if (ypos !== null) { if (zeroPos) { top = Math.min(ypos, zeroPos); bottom = Math.max(ypos, zeroPos); } else { top = ypos; bottom = this.bottom; } left = this.left + idx * groupWidth + leftPadding; if (!this.options.stacked) { left += sidx * (barWidth + this.options.barGap); } size = bottom - top; if (this.options.stacked) { top -= lastTop; } this.drawBar(left, top, barWidth, size, this.colorFor(row, sidx, 'bar')); _results1.push(lastTop += size); } else { _results1.push(null); } } return _results1; }).call(this)); } return _results; }).call(this); }; Bar.prototype.colorFor = function(row, sidx, type) { var r, s; if (typeof this.options.barColors === 'function') { r = { x: row.x, y: row.y[sidx], label: row.label }; s = { index: sidx, key: this.options.ykeys[sidx], label: this.options.labels[sidx] }; return this.options.barColors.call(this, r, s, type); } else { return this.options.barColors[sidx % this.options.barColors.length]; } }; Bar.prototype.hitTest = function(x, y) { if (this.data.length === 0) { return null; } x = Math.max(Math.min(x, this.right), this.left); return Math.min(this.data.length - 1, Math.floor((x - this.left) / (this.width / this.data.length))); }; Bar.prototype.onGridClick = function(x, y) { var index; index = this.hitTest(x, y); return this.fire('click', index, this.options.data[index], x, y); }; Bar.prototype.onHoverMove = function(x, y) { var index, _ref; index = this.hitTest(x, y); return (_ref = this.hover).update.apply(_ref, this.hoverContentForRow(index)); }; Bar.prototype.onHoverOut = function() { if (this.options.hideHover !== false) { return this.hover.hide(); } }; Bar.prototype.hoverContentForRow = function(index) { var content, j, row, x, y, _i, _len, _ref; row = this.data[index]; content = "<div class='morris-hover-row-label'>" + row.label + "</div>"; _ref = row.y; for (j = _i = 0, _len = _ref.length; _i < _len; j = ++_i) { y = _ref[j]; content += "<div class='morris-hover-point' style='color: " + (this.colorFor(row, j, 'label')) + "'>\n " + this.options.labels[j] + ":\n " + (this.yLabelFormat(y)) + "\n</div>"; } if (typeof this.options.hoverCallback === 'function') { content = this.options.hoverCallback(index, this.options, content); } x = this.left + (index + 0.5) * this.width / this.data.length; return [content, x]; }; Bar.prototype.drawXAxisLabel = function(xPos, yPos, text) { var label; return label = this.raphael.text(xPos, yPos, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).attr('fill', this.options.gridTextColor); }; Bar.prototype.drawBar = function(xPos, yPos, width, height, barColor) { return this.raphael.rect(xPos, yPos, width, height).attr('fill', barColor).attr('stroke-width', 0); }; return Bar; })(Morris.Grid); Morris.Donut = (function(_super) { __extends(Donut, _super); Donut.prototype.defaults = { colors: ['#0B62A4', '#3980B5', '#679DC6', '#95BBD7', '#B0CCE1', '#095791', '#095085', '#083E67', '#052C48', '#042135'], backgroundColor: '#FFFFFF', labelColor: '#000000', formatter: Morris.commas }; function Donut(options) { this.select = __bind(this.select, this); this.click = __bind(this.click, this); var row; if (!(this instanceof Morris.Donut)) { return new Morris.Donut(options); } if (typeof options.element === 'string') { this.el = $(document.getElementById(options.element)); } else { this.el = $(options.element); } this.options = $.extend({}, this.defaults, options); if (this.el === null || this.el.length === 0) { throw new Error("Graph placeholder not found."); } if (options.data === void 0 || options.data.length === 0) { return; } this.data = options.data; this.values = (function() { var _i, _len, _ref, _results; _ref = this.data; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { row = _ref[_i]; _results.push(parseFloat(row.value)); } return _results; }).call(this); this.redraw(); } Donut.prototype.redraw = function() { var C, cx, cy, i, idx, last, max_value, min, next, seg, total, value, w, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results; this.el.empty(); this.raphael = new Raphael(this.el[0]); cx = this.el.width() / 2; cy = this.el.height() / 2; w = (Math.min(cx, cy) - 10) / 3; total = 0; _ref = this.values; for (_i = 0, _len = _ref.length; _i < _len; _i++) { value = _ref[_i]; total += value; } min = 5 / (2 * w); C = 1.9999 * Math.PI - min * this.data.length; last = 0; idx = 0; this.segments = []; _ref1 = this.values; for (i = _j = 0, _len1 = _ref1.length; _j < _len1; i = ++_j) { value = _ref1[i]; next = last + min + C * (value / total); seg = new Morris.DonutSegment(cx, cy, w * 2, w, last, next, this.options.colors[idx % this.options.colors.length], this.options.backgroundColor, idx, this.raphael); seg.render(); this.segments.push(seg); seg.on('hover', this.select); seg.on('click', this.click); last = next; idx += 1; } this.text1 = this.drawEmptyDonutLabel(cx, cy - 10, this.options.labelColor, 15, 800); this.text2 = this.drawEmptyDonutLabel(cx, cy + 10, this.options.labelColor, 14); max_value = Math.max.apply(null, (function() { var _k, _len2, _ref2, _results; _ref2 = this.values; _results = []; for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { value = _ref2[_k]; _results.push(value); } return _results; }).call(this)); idx = 0; _ref2 = this.values; _results = []; for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { value = _ref2[_k]; if (value === max_value) { this.select(idx); break; } _results.push(idx += 1); } return _results; }; Donut.prototype.click = function(idx) { return this.fire('click', idx, this.data[idx]); }; Donut.prototype.select = function(idx) { var row, s, segment, _i, _len, _ref; _ref = this.segments; for (_i = 0, _len = _ref.length; _i < _len; _i++) { s = _ref[_i]; s.deselect(); } segment = this.segments[idx]; segment.select(); row = this.data[idx]; return this.setLabels(row.label, this.options.formatter(row.value, row)); }; Donut.prototype.setLabels = function(label1, label2) { var inner, maxHeightBottom, maxHeightTop, maxWidth, text1bbox, text1scale, text2bbox, text2scale; inner = (Math.min(this.el.width() / 2, this.el.height() / 2) - 10) * 2 / 3; maxWidth = 1.8 * inner; maxHeightTop = inner / 2; maxHeightBottom = inner / 3; this.text1.attr({ text: label1, transform: '' }); text1bbox = this.text1.getBBox(); text1scale = Math.min(maxWidth / text1bbox.width, maxHeightTop / text1bbox.height); this.text1.attr({ transform: "S" + text1scale + "," + text1scale + "," + (text1bbox.x + text1bbox.width / 2) + "," + (text1bbox.y + text1bbox.height) }); this.text2.attr({ text: label2, transform: '' }); text2bbox = this.text2.getBBox(); text2scale = Math.min(maxWidth / text2bbox.width, maxHeightBottom / text2bbox.height); return this.text2.attr({ transform: "S" + text2scale + "," + text2scale + "," + (text2bbox.x + text2bbox.width / 2) + "," + text2bbox.y }); }; Donut.prototype.drawEmptyDonutLabel = function(xPos, yPos, color, fontSize, fontWeight) { var text; text = this.raphael.text(xPos, yPos, '').attr('font-size', fontSize).attr('fill', color); if (fontWeight != null) { text.attr('font-weight', fontWeight); } return text; }; return Donut; })(Morris.EventEmitter); Morris.DonutSegment = (function(_super) { __extends(DonutSegment, _super); function DonutSegment(cx, cy, inner, outer, p0, p1, color, backgroundColor, index, raphael) { this.cx = cx; this.cy = cy; this.inner = inner; this.outer = outer; this.color = color; this.backgroundColor = backgroundColor; this.index = index; this.raphael = raphael; this.deselect = __bind(this.deselect, this); this.select = __bind(this.select, this); this.sin_p0 = Math.sin(p0); this.cos_p0 = Math.cos(p0); this.sin_p1 = Math.sin(p1); this.cos_p1 = Math.cos(p1); this.is_long = (p1 - p0) > Math.PI ? 1 : 0; this.path = this.calcSegment(this.inner + 3, this.inner + this.outer - 5); this.selectedPath = this.calcSegment(this.inner + 3, this.inner + this.outer); this.hilight = this.calcArc(this.inner); } DonutSegment.prototype.calcArcPoints = function(r) { return [this.cx + r * this.sin_p0, this.cy + r * this.cos_p0, this.cx + r * this.sin_p1, this.cy + r * this.cos_p1]; }; DonutSegment.prototype.calcSegment = function(r1, r2) { var ix0, ix1, iy0, iy1, ox0, ox1, oy0, oy1, _ref, _ref1; _ref = this.calcArcPoints(r1), ix0 = _ref[0], iy0 = _ref[1], ix1 = _ref[2], iy1 = _ref[3]; _ref1 = this.calcArcPoints(r2), ox0 = _ref1[0], oy0 = _ref1[1], ox1 = _ref1[2], oy1 = _ref1[3]; return ("M" + ix0 + "," + iy0) + ("A" + r1 + "," + r1 + ",0," + this.is_long + ",0," + ix1 + "," + iy1) + ("L" + ox1 + "," + oy1) + ("A" + r2 + "," + r2 + ",0," + this.is_long + ",1," + ox0 + "," + oy0) + "Z"; }; DonutSegment.prototype.calcArc = function(r) { var ix0, ix1, iy0, iy1, _ref; _ref = this.calcArcPoints(r), ix0 = _ref[0], iy0 = _ref[1], ix1 = _ref[2], iy1 = _ref[3]; return ("M" + ix0 + "," + iy0) + ("A" + r + "," + r + ",0," + this.is_long + ",0," + ix1 + "," + iy1); }; DonutSegment.prototype.render = function() { var _this = this; this.arc = this.drawDonutArc(this.hilight, this.color); return this.seg = this.drawDonutSegment(this.path, this.color, this.backgroundColor, function() { return _this.fire('hover', _this.index); }, function() { return _this.fire('click', _this.index); }); }; DonutSegment.prototype.drawDonutArc = function(path, color) { return this.raphael.path(path).attr({ stroke: color, 'stroke-width': 2, opacity: 0 }); }; DonutSegment.prototype.drawDonutSegment = function(path, fillColor, strokeColor, hoverFunction, clickFunction) { return this.raphael.path(path).attr({ fill: fillColor, stroke: strokeColor, 'stroke-width': 3 }).hover(hoverFunction).click(clickFunction); }; DonutSegment.prototype.select = function() { if (!this.selected) { this.seg.animate({ path: this.selectedPath }, 150, '<>'); this.arc.animate({ opacity: 1 }, 150, '<>'); return this.selected = true; } }; DonutSegment.prototype.deselect = function() { if (this.selected) { this.seg.animate({ path: this.path }, 150, '<>'); this.arc.animate({ opacity: 0 }, 150, '<>'); return this.selected = false; } }; return DonutSegment; })(Morris.EventEmitter); }).call(this); /*! NProgress (c) 2013, Rico Sta. Cruz * http://ricostacruz.com/nprogress */ ;(function(factory) { if (typeof module === 'function') { module.exports = factory(this.jQuery || require('jquery')); } else { this.NProgress = factory(this.jQuery); } })(function($) { var NProgress = {}; NProgress.version = '0.1.2'; var Settings = NProgress.settings = { minimum: 0.08, easing: 'ease', positionUsing: '', speed: 200, trickle: true, trickleRate: 0.02, trickleSpeed: 800, showSpinner: true, template: '<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>' }; /** * Updates configuration. * * NProgress.configure({ * minimum: 0.1 * }); */ NProgress.configure = function(options) { $.extend(Settings, options); return this; }; /** * Last number. */ NProgress.status = null; /** * Sets the progress bar status, where `n` is a number from `0.0` to `1.0`. * * NProgress.set(0.4); * NProgress.set(1.0); */ NProgress.set = function(n) { var started = NProgress.isStarted(); n = clamp(n, Settings.minimum, 1); NProgress.status = (n === 1 ? null : n); var $progress = NProgress.render(!started), $bar = $progress.find('[role="bar"]'), speed = Settings.speed, ease = Settings.easing; $progress[0].offsetWidth; /* Repaint */ $progress.queue(function(next) { // Set positionUsing if it hasn't already been set if (Settings.positionUsing === '') Settings.positionUsing = NProgress.getPositioningCSS(); // Add transition $bar.css(barPositionCSS(n, speed, ease)); if (n === 1) { // Fade out $progress.css({ transition: 'none', opacity: 1 }); $progress[0].offsetWidth; /* Repaint */ setTimeout(function() { $progress.css({ transition: 'all '+speed+'ms linear', opacity: 0 }); setTimeout(function() { NProgress.remove(); next(); }, speed); }, speed); } else { setTimeout(next, speed); } }); return this; }; NProgress.isStarted = function() { return typeof NProgress.status === 'number'; }; /** * Shows the progress bar. * This is the same as setting the status to 0%, except that it doesn't go backwards. * * NProgress.start(); * */ NProgress.start = function() { if (!NProgress.status) NProgress.set(0); var work = function() { setTimeout(function() { if (!NProgress.status) return; NProgress.trickle(); work(); }, Settings.trickleSpeed); }; if (Settings.trickle) work(); return this; }; /** * Hides the progress bar. * This is the *sort of* the same as setting the status to 100%, with the * difference being `done()` makes some placebo effect of some realistic motion. * * NProgress.done(); * * If `true` is passed, it will show the progress bar even if its hidden. * * NProgress.done(true); */ NProgress.done = function(force) { if (!force && !NProgress.status) return this; return NProgress.inc(0.3 + 0.5 * Math.random()).set(1); }; /** * Increments by a random amount. */ NProgress.inc = function(amount) { var n = NProgress.status; if (!n) { return NProgress.start(); } else { if (typeof amount !== 'number') { amount = (1 - n) * clamp(Math.random() * n, 0.1, 0.95); } n = clamp(n + amount, 0, 0.994); return NProgress.set(n); } }; NProgress.trickle = function() { return NProgress.inc(Math.random() * Settings.trickleRate); }; /** * (Internal) renders the progress bar markup based on the `template` * setting. */ NProgress.render = function(fromStart) { if (NProgress.isRendered()) return $("#nprogress"); $('html').addClass('nprogress-busy'); var $el = $("<div id='nprogress'>") .html(Settings.template); var perc = fromStart ? '-100' : toBarPerc(NProgress.status || 0); $el.find('[role="bar"]').css({ transition: 'all 0 linear', transform: 'translate3d('+perc+'%,0,0)' }); if (!Settings.showSpinner) $el.find('[role="spinner"]').remove(); $el.appendTo(document.body); return $el; }; /** * Removes the element. Opposite of render(). */ NProgress.remove = function() { $('html').removeClass('nprogress-busy'); $('#nprogress').remove(); }; /** * Checks if the progress bar is rendered. */ NProgress.isRendered = function() { return ($("#nprogress").length > 0); }; /** * Determine which positioning CSS rule to use. */ NProgress.getPositioningCSS = function() { // Sniff on document.body.style var bodyStyle = document.body.style; // Sniff prefixes var vendorPrefix = ('WebkitTransform' in bodyStyle) ? 'Webkit' : ('MozTransform' in bodyStyle) ? 'Moz' : ('msTransform' in bodyStyle) ? 'ms' : ('OTransform' in bodyStyle) ? 'O' : ''; if (vendorPrefix + 'Perspective' in bodyStyle) { // Modern browsers with 3D support, e.g. Webkit, IE10 return 'translate3d'; } else if (vendorPrefix + 'Transform' in bodyStyle) { // Browsers without 3D support, e.g. IE9 return 'translate'; } else { // Browsers without translate() support, e.g. IE7-8 return 'margin'; } }; /** * Helpers */ function clamp(n, min, max) { if (n < min) return min; if (n > max) return max; return n; } /** * (Internal) converts a percentage (`0..1`) to a bar translateX * percentage (`-100%..0%`). */ function toBarPerc(n) { return (-1 + n) * 100; } /** * (Internal) returns the correct CSS for changing the bar's * position given an n percentage, and speed and ease from Settings */ function barPositionCSS(n, speed, ease) { var barCSS; if (Settings.positionUsing === 'translate3d') { barCSS = { transform: 'translate3d('+toBarPerc(n)+'%,0,0)' }; } else if (Settings.positionUsing === 'translate') { barCSS = { transform: 'translate('+toBarPerc(n)+'%,0)' }; } else { barCSS = { 'margin-left': toBarPerc(n)+'%' }; } barCSS.transition = 'all '+speed+'ms '+ease; return barCSS; } return NProgress; }); /* wysihtml5 v0.4.0pre https://github.com/xing/wysihtml5 Author: Christopher Blum (https://github.com/tiff) Copyright (C) 2012 XING AG Licensed under the MIT license (MIT) Rangy, a cross-browser JavaScript range and selection library http://code.google.com/p/rangy/ Copyright 2011, Tim Down Licensed under the MIT license. Version: 1.2.2 Build date: 13 November 2011 */ var wysihtml5={version:"0.4.0pre",commands:{},dom:{},quirks:{},toolbar:{},lang:{},selection:{},views:{},INVISIBLE_SPACE:"\ufeff",EMPTY_FUNCTION:function(){},ELEMENT_NODE:1,TEXT_NODE:3,BACKSPACE_KEY:8,ENTER_KEY:13,ESCAPE_KEY:27,SPACE_KEY:32,DELETE_KEY:46}; window.rangy=function(){function a(a,b){var c=typeof a[b];return c==l||!(c!=h||!a[b])||"unknown"==c}function c(a,b){return!(typeof a[b]!=h||!a[b])}function b(a,b){return typeof a[b]!=p}function d(a){return function(b,c){for(var d=c.length;d--;)if(!a(b,c[d]))return!1;return!0}}function e(a){return a&&r(a,q)&&v(a,D)}function f(a){window.alert("Rangy not supported in your browser. Reason: "+a);t.initialized=!0;t.supported=!1}function g(){if(!t.initialized){var b,d=!1,l=!1;a(document,"createRange")&& (b=document.createRange(),r(b,u)&&v(b,n)&&(d=!0),b.detach());(b=c(document,"body")?document.body:document.getElementsByTagName("body")[0])&&a(b,"createTextRange")&&(b=b.createTextRange(),e(b)&&(l=!0));d||l||f("Neither Range nor TextRange are implemented");t.initialized=!0;t.features={implementsDomRange:d,implementsTextRange:l};d=A.concat(w);l=0;for(b=d.length;l<b;++l)try{d[l](t)}catch(h){c(window,"console")&&a(window.console,"log")&&window.console.log("Init listener threw an exception. Continuing.", h)}}}function k(a){this.name=a;this.supported=this.initialized=!1}var h="object",l="function",p="undefined",n="startContainer startOffset endContainer endOffset collapsed commonAncestorContainer START_TO_START START_TO_END END_TO_START END_TO_END".split(" "),u="setStart setStartBefore setStartAfter setEnd setEndBefore setEndAfter collapse selectNode selectNodeContents compareBoundaryPoints deleteContents extractContents cloneContents insertNode surroundContents cloneRange toString detach".split(" "), D="boundingHeight boundingLeft boundingTop boundingWidth htmlText text".split(" "),q="collapse compareEndPoints duplicate getBookmark moveToBookmark moveToElementText parentElement pasteHTML select setEndPoint getBoundingClientRect".split(" "),r=d(a),s=d(c),v=d(b),t={version:"1.2.2",initialized:!1,supported:!0,util:{isHostMethod:a,isHostObject:c,isHostProperty:b,areHostMethods:r,areHostObjects:s,areHostProperties:v,isTextRange:e},features:{},modules:{},config:{alertOnWarn:!1,preferTextRange:!1}}; t.fail=f;t.warn=function(a){a="Rangy warning: "+a;t.config.alertOnWarn?window.alert(a):typeof window.console!=p&&typeof window.console.log!=p&&window.console.log(a)};({}).hasOwnProperty?t.util.extend=function(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c])}:f("hasOwnProperty not supported");var w=[],A=[];t.init=g;t.addInitListener=function(a){t.initialized?a(t):w.push(a)};var z=[];t.addCreateMissingNativeApiListener=function(a){z.push(a)};t.createMissingNativeApi=function(a){a=a||window;g(); for(var b=0,c=z.length;b<c;++b)z[b](a)};k.prototype.fail=function(a){this.initialized=!0;this.supported=!1;throw Error("Module '"+this.name+"' failed to load: "+a);};k.prototype.warn=function(a){t.warn("Module "+this.name+": "+a)};k.prototype.createError=function(a){return Error("Error in Rangy "+this.name+" module: "+a)};t.createModule=function(a,b){var c=new k(a);t.modules[a]=c;A.push(function(a){b(a,c);c.initialized=!0;c.supported=!0})};t.requireModules=function(a){for(var b=0,c=a.length,d,e;b< c;++b){e=a[b];d=t.modules[e];if(!(d&&d instanceof k))throw Error("Module '"+e+"' not found");if(!d.supported)throw Error("Module '"+e+"' not supported");}};var E=!1,s=function(a){E||(E=!0,t.initialized||g())};if(typeof window==p)f("No window found");else if(typeof document==p)f("No document found");else return a(document,"addEventListener")&&document.addEventListener("DOMContentLoaded",s,!1),a(window,"addEventListener")?window.addEventListener("load",s,!1):a(window,"attachEvent")?window.attachEvent("onload", s):f("Window does not have required addEventListener or attachEvent method"),t}(); rangy.createModule("DomUtil",function(a,c){function b(a){for(var b=0;a=a.previousSibling;)b++;return b}function d(a,b){var c=[],d;for(d=a;d;d=d.parentNode)c.push(d);for(d=b;d;d=d.parentNode)if(r(c,d))return d;return null}function e(a,b,c){for(c=c?a:a.parentNode;c;){a=c.parentNode;if(a===b)return c;c=a}return null}function f(a){a=a.nodeType;return 3==a||4==a||8==a}function g(a,b){var c=b.nextSibling,d=b.parentNode;c?d.insertBefore(a,c):d.appendChild(a);return a}function k(a){if(9==a.nodeType)return a; if(typeof a.ownerDocument!=u)return a.ownerDocument;if(typeof a.document!=u)return a.document;if(a.parentNode)return k(a.parentNode);throw Error("getDocument: no document found for node");}function h(a){return a?f(a)?'"'+a.data+'"':1==a.nodeType?"<"+a.nodeName+(a.id?' id="'+a.id+'"':"")+">["+a.childNodes.length+"]":a.nodeName:"[No node]"}function l(a){this._next=this.root=a}function p(a,b){this.node=a;this.offset=b}function n(a){this.code=this[a];this.codeName=a;this.message="DOMException: "+this.codeName} var u="undefined",D=a.util;D.areHostMethods(document,["createDocumentFragment","createElement","createTextNode"])||c.fail("document missing a Node creation method");D.isHostMethod(document,"getElementsByTagName")||c.fail("document missing getElementsByTagName method");var q=document.createElement("div");D.areHostMethods(q,["insertBefore","appendChild","cloneNode"])||c.fail("Incomplete Element implementation");D.isHostProperty(q,"innerHTML")||c.fail("Element is missing innerHTML property");q=document.createTextNode("test"); D.areHostMethods(q,["splitText","deleteData","insertData","appendData","cloneNode"])||c.fail("Incomplete Text Node implementation");var r=function(a,b){for(var c=a.length;c--;)if(a[c]===b)return!0;return!1};l.prototype={_current:null,hasNext:function(){return!!this._next},next:function(){var a=this._current=this._next,b;if(this._current){b=a.firstChild;if(!b)for(b=null;a!==this.root&&!(b=a.nextSibling);)a=a.parentNode;this._next=b}return this._current},detach:function(){this._current=this._next=this.root= null}};p.prototype={equals:function(a){return this.node===a.node&this.offset==a.offset},inspect:function(){return"[DomPosition("+h(this.node)+":"+this.offset+")]"}};n.prototype={INDEX_SIZE_ERR:1,HIERARCHY_REQUEST_ERR:3,WRONG_DOCUMENT_ERR:4,NO_MODIFICATION_ALLOWED_ERR:7,NOT_FOUND_ERR:8,NOT_SUPPORTED_ERR:9,INVALID_STATE_ERR:11};n.prototype.toString=function(){return this.message};a.dom={arrayContains:r,isHtmlNamespace:function(a){var b;return typeof a.namespaceURI==u||null===(b=a.namespaceURI)||"http://www.w3.org/1999/xhtml"== b},parentElement:function(a){a=a.parentNode;return 1==a.nodeType?a:null},getNodeIndex:b,getNodeLength:function(a){var b;return f(a)?a.length:(b=a.childNodes)?b.length:0},getCommonAncestor:d,isAncestorOf:function(a,b,c){for(b=c?b:b.parentNode;b;){if(b===a)return!0;b=b.parentNode}return!1},getClosestAncestorIn:e,isCharacterDataNode:f,insertAfter:g,splitDataNode:function(a,b){var c=a.cloneNode(!1);c.deleteData(0,b);a.deleteData(b,a.length-b);g(c,a);return c},getDocument:k,getWindow:function(a){a=k(a); if(typeof a.defaultView!=u)return a.defaultView;if(typeof a.parentWindow!=u)return a.parentWindow;throw Error("Cannot get a window object for node");},getIframeWindow:function(a){if(typeof a.contentWindow!=u)return a.contentWindow;if(typeof a.contentDocument!=u)return a.contentDocument.defaultView;throw Error("getIframeWindow: No Window object found for iframe element");},getIframeDocument:function(a){if(typeof a.contentDocument!=u)return a.contentDocument;if(typeof a.contentWindow!=u)return a.contentWindow.document; throw Error("getIframeWindow: No Document object found for iframe element");},getBody:function(a){return D.isHostObject(a,"body")?a.body:a.getElementsByTagName("body")[0]},getRootContainer:function(a){for(var b;b=a.parentNode;)a=b;return a},comparePoints:function(a,c,l,h){var f;if(a==l)return c===h?0:c<h?-1:1;if(f=e(l,a,!0))return c<=b(f)?-1:1;if(f=e(a,l,!0))return b(f)<h?-1:1;c=d(a,l);a=a===c?c:e(a,c,!0);l=l===c?c:e(l,c,!0);if(a===l)throw Error("comparePoints got to case 4 and childA and childB are the same!"); for(c=c.firstChild;c;){if(c===a)return-1;if(c===l)return 1;c=c.nextSibling}throw Error("Should not be here!");},inspectNode:h,fragmentFromNodeChildren:function(a){for(var b=k(a).createDocumentFragment(),c;c=a.firstChild;)b.appendChild(c);return b},createIterator:function(a){return new l(a)},DomPosition:p};a.DOMException=n}); rangy.createModule("DomRange",function(a,c){function b(a,b){return 3!=a.nodeType&&(m.isAncestorOf(a,b.startContainer,!0)||m.isAncestorOf(a,b.endContainer,!0))}function d(a){return m.getDocument(a.startContainer)}function e(a,b,c){if(b=a._listeners[b])for(var d=0,e=b.length;d<e;++d)b[d].call(a,{target:a,args:c})}function f(a){return new I(a.parentNode,m.getNodeIndex(a))}function g(a){return new I(a.parentNode,m.getNodeIndex(a)+1)}function k(a,b,c){var d=11==a.nodeType?a.firstChild:a;m.isCharacterDataNode(b)? c==b.length?m.insertAfter(a,b):b.parentNode.insertBefore(a,0==c?b:m.splitDataNode(b,c)):c>=b.childNodes.length?b.appendChild(a):b.insertBefore(a,b.childNodes[c]);return d}function h(a){for(var b,c,e=d(a.range).createDocumentFragment();c=a.next();){b=a.isPartiallySelectedSubtree();c=c.cloneNode(!b);b&&(b=a.getSubtreeIterator(),c.appendChild(h(b)),b.detach(!0));if(10==c.nodeType)throw new F("HIERARCHY_REQUEST_ERR");e.appendChild(c)}return e}function l(a,b,c){var d,e;for(c=c||{stop:!1};d=a.next();)if(a.isPartiallySelectedSubtree())if(!1=== b(d)){c.stop=!0;break}else{if(d=a.getSubtreeIterator(),l(d,b,c),d.detach(!0),c.stop)break}else for(d=m.createIterator(d);e=d.next();)if(!1===b(e)){c.stop=!0;return}}function p(a){for(var b;a.next();)a.isPartiallySelectedSubtree()?(b=a.getSubtreeIterator(),p(b),b.detach(!0)):a.remove()}function n(a){for(var b,c=d(a.range).createDocumentFragment(),e;b=a.next();){a.isPartiallySelectedSubtree()?(b=b.cloneNode(!1),e=a.getSubtreeIterator(),b.appendChild(n(e)),e.detach(!0)):a.remove();if(10==b.nodeType)throw new F("HIERARCHY_REQUEST_ERR"); c.appendChild(b)}return c}function u(a,b,c){var d=!(!b||!b.length),e,h=!!c;d&&(e=RegExp("^("+b.join("|")+")$"));var f=[];l(new q(a,!1),function(a){d&&!e.test(a.nodeType)||h&&!c(a)||f.push(a)});return f}function D(a){return"["+("undefined"==typeof a.getName?"Range":a.getName())+"("+m.inspectNode(a.startContainer)+":"+a.startOffset+", "+m.inspectNode(a.endContainer)+":"+a.endOffset+")]"}function q(a,b){this.range=a;this.clonePartiallySelectedTextNodes=b;if(!a.collapsed){this.sc=a.startContainer;this.so= a.startOffset;this.ec=a.endContainer;this.eo=a.endOffset;var c=a.commonAncestorContainer;this.sc===this.ec&&m.isCharacterDataNode(this.sc)?(this.isSingleCharacterDataNode=!0,this._first=this._last=this._next=this.sc):(this._first=this._next=this.sc!==c||m.isCharacterDataNode(this.sc)?m.getClosestAncestorIn(this.sc,c,!0):this.sc.childNodes[this.so],this._last=this.ec!==c||m.isCharacterDataNode(this.ec)?m.getClosestAncestorIn(this.ec,c,!0):this.ec.childNodes[this.eo-1])}}function r(a){this.code=this[a]; this.codeName=a;this.message="RangeException: "+this.codeName}function s(a,b,c){this.nodes=u(a,b,c);this._next=this.nodes[0];this._position=0}function v(a){return function(b,c){for(var d,e=c?b:b.parentNode;e;){d=e.nodeType;if(m.arrayContains(a,d))return e;e=e.parentNode}return null}}function t(a,b){if(da(a,b))throw new r("INVALID_NODE_TYPE_ERR");}function w(a){if(!a.startContainer)throw new F("INVALID_STATE_ERR");}function A(a,b){if(!m.arrayContains(b,a.nodeType))throw new r("INVALID_NODE_TYPE_ERR"); }function z(a,b){if(0>b||b>(m.isCharacterDataNode(a)?a.length:a.childNodes.length))throw new F("INDEX_SIZE_ERR");}function E(a,b){if(S(a,!0)!==S(b,!0))throw new F("WRONG_DOCUMENT_ERR");}function y(a){if(ea(a,!0))throw new F("NO_MODIFICATION_ALLOWED_ERR");}function B(a,b){if(!a)throw new F(b);}function x(a){w(a);if(!m.arrayContains(M,a.startContainer.nodeType)&&!S(a.startContainer,!0)||!m.arrayContains(M,a.endContainer.nodeType)&&!S(a.endContainer,!0)||!(a.startOffset<=(m.isCharacterDataNode(a.startContainer)? a.startContainer.length:a.startContainer.childNodes.length)&&a.endOffset<=(m.isCharacterDataNode(a.endContainer)?a.endContainer.length:a.endContainer.childNodes.length)))throw Error("Range error: Range is no longer valid after DOM mutation ("+a.inspect()+")");}function L(){}function H(a){a.START_TO_START=U;a.START_TO_END=Y;a.END_TO_END=fa;a.END_TO_START=Z;a.NODE_BEFORE=$;a.NODE_AFTER=aa;a.NODE_BEFORE_AND_AFTER=ba;a.NODE_INSIDE=V}function G(a){H(a);H(a.prototype)}function N(a,b){return function(){x(this); var c=this.startContainer,d=this.startOffset,e=this.commonAncestorContainer,h=new q(this,!0);c!==e&&(c=m.getClosestAncestorIn(c,e,!0),d=g(c),c=d.node,d=d.offset);l(h,y);h.reset();e=a(h);h.detach();b(this,c,d,c,d);return e}}function P(c,d,e){function l(a,b){return function(c){w(this);A(c,J);A(Q(c),M);c=(a?f:g)(c);(b?h:T)(this,c.node,c.offset)}}function h(a,b,c){var e=a.endContainer,l=a.endOffset;if(b!==a.startContainer||c!==a.startOffset){if(Q(b)!=Q(e)||1==m.comparePoints(b,c,e,l))e=b,l=c;d(a,b,c, e,l)}}function T(a,b,c){var e=a.startContainer,l=a.startOffset;if(b!==a.endContainer||c!==a.endOffset){if(Q(b)!=Q(e)||-1==m.comparePoints(b,c,e,l))e=b,l=c;d(a,e,l,b,c)}}c.prototype=new L;a.util.extend(c.prototype,{setStart:function(a,b){w(this);t(a,!0);z(a,b);h(this,a,b)},setEnd:function(a,b){w(this);t(a,!0);z(a,b);T(this,a,b)},setStartBefore:l(!0,!0),setStartAfter:l(!1,!0),setEndBefore:l(!0,!1),setEndAfter:l(!1,!1),collapse:function(a){x(this);a?d(this,this.startContainer,this.startOffset,this.startContainer, this.startOffset):d(this,this.endContainer,this.endOffset,this.endContainer,this.endOffset)},selectNodeContents:function(a){w(this);t(a,!0);d(this,a,0,a,m.getNodeLength(a))},selectNode:function(a){w(this);t(a,!1);A(a,J);var b=f(a);a=g(a);d(this,b.node,b.offset,a.node,a.offset)},extractContents:N(n,d),deleteContents:N(p,d),canSurroundContents:function(){x(this);y(this.startContainer);y(this.endContainer);var a=new q(this,!0),c=a._first&&b(a._first,this)||a._last&&b(a._last,this);a.detach();return!c}, detach:function(){e(this)},splitBoundaries:function(){x(this);var a=this.startContainer,b=this.startOffset,c=this.endContainer,e=this.endOffset,l=a===c;m.isCharacterDataNode(c)&&(0<e&&e<c.length)&&m.splitDataNode(c,e);m.isCharacterDataNode(a)&&(0<b&&b<a.length)&&(a=m.splitDataNode(a,b),l?(e-=b,c=a):c==a.parentNode&&e>=m.getNodeIndex(a)&&e++,b=0);d(this,a,b,c,e)},normalizeBoundaries:function(){x(this);var a=this.startContainer,b=this.startOffset,c=this.endContainer,e=this.endOffset,l=function(a){var b= a.nextSibling;b&&b.nodeType==a.nodeType&&(c=a,e=a.length,a.appendData(b.data),b.parentNode.removeChild(b))},h=function(d){var l=d.previousSibling;if(l&&l.nodeType==d.nodeType){a=d;var h=d.length;b=l.length;d.insertData(0,l.data);l.parentNode.removeChild(l);a==c?(e+=b,c=a):c==d.parentNode&&(l=m.getNodeIndex(d),e==l?(c=d,e=h):e>l&&e--)}},f=!0;m.isCharacterDataNode(c)?c.length==e&&l(c):(0<e&&(f=c.childNodes[e-1])&&m.isCharacterDataNode(f)&&l(f),f=!this.collapsed);f?m.isCharacterDataNode(a)?0==b&&h(a): b<a.childNodes.length&&(l=a.childNodes[b])&&m.isCharacterDataNode(l)&&h(l):(a=c,b=e);d(this,a,b,c,e)},collapseToPoint:function(a,b){w(this);t(a,!0);z(a,b);a===this.startContainer&&b===this.startOffset&&a===this.endContainer&&b===this.endOffset||d(this,a,b,a,b)}});G(c)}function O(a){a.collapsed=a.startContainer===a.endContainer&&a.startOffset===a.endOffset;a.commonAncestorContainer=a.collapsed?a.startContainer:m.getCommonAncestor(a.startContainer,a.endContainer)}function R(a,b,c,d,l){var h=a.startContainer!== b||a.startOffset!==c,f=a.endContainer!==d||a.endOffset!==l;a.startContainer=b;a.startOffset=c;a.endContainer=d;a.endOffset=l;O(a);e(a,"boundarychange",{startMoved:h,endMoved:f})}function C(a){this.startContainer=a;this.startOffset=0;this.endContainer=a;this.endOffset=0;this._listeners={boundarychange:[],detach:[]};O(this)}a.requireModules(["DomUtil"]);var m=a.dom,I=m.DomPosition,F=a.DOMException;q.prototype={_current:null,_next:null,_first:null,_last:null,isSingleCharacterDataNode:!1,reset:function(){this._current= null;this._next=this._first},hasNext:function(){return!!this._next},next:function(){var a=this._current=this._next;a&&(this._next=a!==this._last?a.nextSibling:null,m.isCharacterDataNode(a)&&this.clonePartiallySelectedTextNodes&&(a===this.ec&&(a=a.cloneNode(!0)).deleteData(this.eo,a.length-this.eo),this._current===this.sc&&(a=a.cloneNode(!0)).deleteData(0,this.so)));return a},remove:function(){var a=this._current,b,c;!m.isCharacterDataNode(a)||a!==this.sc&&a!==this.ec?a.parentNode&&a.parentNode.removeChild(a): (b=a===this.sc?this.so:0,c=a===this.ec?this.eo:a.length,b!=c&&a.deleteData(b,c-b))},isPartiallySelectedSubtree:function(){return b(this._current,this.range)},getSubtreeIterator:function(){var a;if(this.isSingleCharacterDataNode)a=this.range.cloneRange(),a.collapse();else{a=new C(d(this.range));var b=this._current,c=b,e=0,l=b,h=m.getNodeLength(b);m.isAncestorOf(b,this.sc,!0)&&(c=this.sc,e=this.so);m.isAncestorOf(b,this.ec,!0)&&(l=this.ec,h=this.eo);R(a,c,e,l,h)}return new q(a,this.clonePartiallySelectedTextNodes)}, detach:function(a){a&&this.range.detach();this.range=this._current=this._next=this._first=this._last=this.sc=this.so=this.ec=this.eo=null}};r.prototype={BAD_BOUNDARYPOINTS_ERR:1,INVALID_NODE_TYPE_ERR:2};r.prototype.toString=function(){return this.message};s.prototype={_current:null,hasNext:function(){return!!this._next},next:function(){this._current=this._next;this._next=this.nodes[++this._position];return this._current},detach:function(){this._current=this._next=this.nodes=null}};var J=[1,3,4,5, 7,8,10],M=[2,9,11],K=[1,3,4,5,7,8,10,11],T=[1,3,4,5,7,8],Q=m.getRootContainer,S=v([9,11]),ea=v([5,6,10,12]),da=v([6,10,12]),ca=document.createElement("style"),W=!1;try{ca.innerHTML="<b>x</b>",W=3==ca.firstChild.nodeType}catch(ga){}a.features.htmlParsingConforms=W;var X="startContainer startOffset endContainer endOffset collapsed commonAncestorContainer".split(" "),U=0,Y=1,fa=2,Z=3,$=0,aa=1,ba=2,V=3;L.prototype={attachListener:function(a,b){this._listeners[a].push(b)},compareBoundaryPoints:function(a, b){x(this);E(this.startContainer,b.startContainer);var c=a==Z||a==U?"start":"end",d=a==Y||a==U?"start":"end";return m.comparePoints(this[c+"Container"],this[c+"Offset"],b[d+"Container"],b[d+"Offset"])},insertNode:function(a){x(this);A(a,K);y(this.startContainer);if(m.isAncestorOf(a,this.startContainer,!0))throw new F("HIERARCHY_REQUEST_ERR");a=k(a,this.startContainer,this.startOffset);this.setStartBefore(a)},cloneContents:function(){x(this);var a,b;if(this.collapsed)return d(this).createDocumentFragment(); if(this.startContainer===this.endContainer&&m.isCharacterDataNode(this.startContainer))return a=this.startContainer.cloneNode(!0),a.data=a.data.slice(this.startOffset,this.endOffset),b=d(this).createDocumentFragment(),b.appendChild(a),b;b=new q(this,!0);a=h(b);b.detach();return a},canSurroundContents:function(){x(this);y(this.startContainer);y(this.endContainer);var a=new q(this,!0),c=a._first&&b(a._first,this)||a._last&&b(a._last,this);a.detach();return!c},surroundContents:function(a){A(a,T);if(!this.canSurroundContents())throw new r("BAD_BOUNDARYPOINTS_ERR"); var b=this.extractContents();if(a.hasChildNodes())for(;a.lastChild;)a.removeChild(a.lastChild);k(a,this.startContainer,this.startOffset);a.appendChild(b);this.selectNode(a)},cloneRange:function(){x(this);for(var a=new C(d(this)),b=X.length,c;b--;)c=X[b],a[c]=this[c];return a},toString:function(){x(this);var a=this.startContainer;if(a===this.endContainer&&m.isCharacterDataNode(a))return 3==a.nodeType||4==a.nodeType?a.data.slice(this.startOffset,this.endOffset):"";var b=[],a=new q(this,!0);l(a,function(a){3!= a.nodeType&&4!=a.nodeType||b.push(a.data)});a.detach();return b.join("")},compareNode:function(a){x(this);var b=a.parentNode,c=m.getNodeIndex(a);if(!b)throw new F("NOT_FOUND_ERR");a=this.comparePoint(b,c);b=this.comparePoint(b,c+1);return 0>a?0<b?ba:$:0<b?aa:V},comparePoint:function(a,b){x(this);B(a,"HIERARCHY_REQUEST_ERR");E(a,this.startContainer);return 0>m.comparePoints(a,b,this.startContainer,this.startOffset)?-1:0<m.comparePoints(a,b,this.endContainer,this.endOffset)?1:0},createContextualFragment:W? function(a){var b=this.startContainer,c=m.getDocument(b);if(!b)throw new F("INVALID_STATE_ERR");var d=null;1==b.nodeType?d=b:m.isCharacterDataNode(b)&&(d=m.parentElement(b));d=null===d||"HTML"==d.nodeName&&m.isHtmlNamespace(m.getDocument(d).documentElement)&&m.isHtmlNamespace(d)?c.createElement("body"):d.cloneNode(!1);d.innerHTML=a;return m.fragmentFromNodeChildren(d)}:function(a){w(this);var b=d(this).createElement("body");b.innerHTML=a;return m.fragmentFromNodeChildren(b)},toHtml:function(){x(this); var a=d(this).createElement("div");a.appendChild(this.cloneContents());return a.innerHTML},intersectsNode:function(a,b){x(this);B(a,"NOT_FOUND_ERR");if(m.getDocument(a)!==d(this))return!1;var c=a.parentNode,e=m.getNodeIndex(a);B(c,"NOT_FOUND_ERR");var l=m.comparePoints(c,e,this.endContainer,this.endOffset),c=m.comparePoints(c,e+1,this.startContainer,this.startOffset);return b?0>=l&&0<=c:0>l&&0<c},isPointInRange:function(a,b){x(this);B(a,"HIERARCHY_REQUEST_ERR");E(a,this.startContainer);return 0<= m.comparePoints(a,b,this.startContainer,this.startOffset)&&0>=m.comparePoints(a,b,this.endContainer,this.endOffset)},intersectsRange:function(a,b){x(this);if(d(a)!=d(this))throw new F("WRONG_DOCUMENT_ERR");var c=m.comparePoints(this.startContainer,this.startOffset,a.endContainer,a.endOffset),e=m.comparePoints(this.endContainer,this.endOffset,a.startContainer,a.startOffset);return b?0>=c&&0<=e:0>c&&0<e},intersection:function(a){if(this.intersectsRange(a)){var b=m.comparePoints(this.startContainer, this.startOffset,a.startContainer,a.startOffset),c=m.comparePoints(this.endContainer,this.endOffset,a.endContainer,a.endOffset),d=this.cloneRange();-1==b&&d.setStart(a.startContainer,a.startOffset);1==c&&d.setEnd(a.endContainer,a.endOffset);return d}return null},union:function(a){if(this.intersectsRange(a,!0)){var b=this.cloneRange();-1==m.comparePoints(a.startContainer,a.startOffset,this.startContainer,this.startOffset)&&b.setStart(a.startContainer,a.startOffset);1==m.comparePoints(a.endContainer, a.endOffset,this.endContainer,this.endOffset)&&b.setEnd(a.endContainer,a.endOffset);return b}throw new r("Ranges do not intersect");},containsNode:function(a,b){return b?this.intersectsNode(a,!1):this.compareNode(a)==V},containsNodeContents:function(a){return 0<=this.comparePoint(a,0)&&0>=this.comparePoint(a,m.getNodeLength(a))},containsRange:function(a){return this.intersection(a).equals(a)},containsNodeText:function(a){var b=this.cloneRange();b.selectNode(a);var c=b.getNodes([3]);return 0<c.length? (b.setStart(c[0],0),a=c.pop(),b.setEnd(a,a.length),a=this.containsRange(b),b.detach(),a):this.containsNodeContents(a)},createNodeIterator:function(a,b){x(this);return new s(this,a,b)},getNodes:function(a,b){x(this);return u(this,a,b)},getDocument:function(){return d(this)},collapseBefore:function(a){w(this);this.setEndBefore(a);this.collapse(!1)},collapseAfter:function(a){w(this);this.setStartAfter(a);this.collapse(!0)},getName:function(){return"DomRange"},equals:function(a){return C.rangesEqual(this, a)},inspect:function(){return D(this)}};P(C,R,function(a){w(a);a.startContainer=a.startOffset=a.endContainer=a.endOffset=null;a.collapsed=a.commonAncestorContainer=null;e(a,"detach",null);a._listeners=null});a.rangePrototype=L.prototype;C.rangeProperties=X;C.RangeIterator=q;C.copyComparisonConstants=G;C.createPrototypeRange=P;C.inspect=D;C.getRangeDocument=d;C.rangesEqual=function(a,b){return a.startContainer===b.startContainer&&a.startOffset===b.startOffset&&a.endContainer===b.endContainer&&a.endOffset=== b.endOffset};a.DomRange=C;a.RangeException=r}); rangy.createModule("WrappedRange",function(a,c){function b(a,b,c,d){var e=a.duplicate();e.collapse(c);var h=e.parentElement();f.isAncestorOf(b,h,!0)||(h=b);if(!h.canHaveHTML)return new g(h.parentNode,f.getNodeIndex(h));b=f.getDocument(h).createElement("span");var k,s=c?"StartToStart":"StartToEnd";do h.insertBefore(b,b.previousSibling),e.moveToElementText(b);while(0<(k=e.compareEndPoints(s,a))&&b.previousSibling);s=b.nextSibling;if(-1==k&&s&&f.isCharacterDataNode(s)){e.setEndPoint(c?"EndToStart":"EndToEnd", a);if(/[\r\n]/.test(s.data))for(h=e.duplicate(),c=h.text.replace(/\r\n/g,"\r").length,c=h.moveStart("character",c);-1==h.compareEndPoints("StartToEnd",h);)c++,h.moveStart("character",1);else c=e.text.length;h=new g(s,c)}else s=(d||!c)&&b.previousSibling,h=(c=(d||c)&&b.nextSibling)&&f.isCharacterDataNode(c)?new g(c,0):s&&f.isCharacterDataNode(s)?new g(s,s.length):new g(h,f.getNodeIndex(b));b.parentNode.removeChild(b);return h}function d(a,b){var c,d,e=a.offset,h=f.getDocument(a.node),g=h.body.createTextRange(), k=f.isCharacterDataNode(a.node);k?(c=a.node,d=c.parentNode):(c=a.node.childNodes,c=e<c.length?c[e]:null,d=a.node);h=h.createElement("span");h.innerHTML="&#feff;";c?d.insertBefore(h,c):d.appendChild(h);g.moveToElementText(h);g.collapse(!b);d.removeChild(h);if(k)g[b?"moveStart":"moveEnd"]("character",e);return g}a.requireModules(["DomUtil","DomRange"]);var e,f=a.dom,g=f.DomPosition,k=a.DomRange;if(a.features.implementsDomRange&&(!a.features.implementsTextRange||!a.config.preferTextRange))(function(){function b(a){for(var c= d.length,e;c--;)e=d[c],a[e]=a.nativeRange[e]}var c,d=k.rangeProperties,h;e=function(a){if(!a)throw Error("Range must be specified");this.nativeRange=a;b(this)};k.createPrototypeRange(e,function(a,b,c,d,e){var h=a.endContainer!==d||a.endOffset!=e;if(a.startContainer!==b||a.startOffset!=c||h)a.setEnd(d,e),a.setStart(b,c)},function(a){a.nativeRange.detach();a.detached=!0;for(var b=d.length,c;b--;)c=d[b],a[c]=null});c=e.prototype;c.selectNode=function(a){this.nativeRange.selectNode(a);b(this)};c.deleteContents= function(){this.nativeRange.deleteContents();b(this)};c.extractContents=function(){var a=this.nativeRange.extractContents();b(this);return a};c.cloneContents=function(){return this.nativeRange.cloneContents()};c.surroundContents=function(a){this.nativeRange.surroundContents(a);b(this)};c.collapse=function(a){this.nativeRange.collapse(a);b(this)};c.cloneRange=function(){return new e(this.nativeRange.cloneRange())};c.refresh=function(){b(this)};c.toString=function(){return this.nativeRange.toString()}; var g=document.createTextNode("test");f.getBody(document).appendChild(g);var q=document.createRange();q.setStart(g,0);q.setEnd(g,0);try{q.setStart(g,1),c.setStart=function(a,c){this.nativeRange.setStart(a,c);b(this)},c.setEnd=function(a,c){this.nativeRange.setEnd(a,c);b(this)},h=function(a){return function(c){this.nativeRange[a](c);b(this)}}}catch(r){c.setStart=function(a,c){try{this.nativeRange.setStart(a,c)}catch(d){this.nativeRange.setEnd(a,c),this.nativeRange.setStart(a,c)}b(this)},c.setEnd=function(a, c){try{this.nativeRange.setEnd(a,c)}catch(d){this.nativeRange.setStart(a,c),this.nativeRange.setEnd(a,c)}b(this)},h=function(a,c){return function(d){try{this.nativeRange[a](d)}catch(e){this.nativeRange[c](d),this.nativeRange[a](d)}b(this)}}}c.setStartBefore=h("setStartBefore","setEndBefore");c.setStartAfter=h("setStartAfter","setEndAfter");c.setEndBefore=h("setEndBefore","setStartBefore");c.setEndAfter=h("setEndAfter","setStartAfter");q.selectNodeContents(g);c.selectNodeContents=q.startContainer== g&&q.endContainer==g&&0==q.startOffset&&q.endOffset==g.length?function(a){this.nativeRange.selectNodeContents(a);b(this)}:function(a){this.setStart(a,0);this.setEnd(a,k.getEndOffset(a))};q.selectNodeContents(g);q.setEnd(g,3);h=document.createRange();h.selectNodeContents(g);h.setEnd(g,4);h.setStart(g,2);-1==q.compareBoundaryPoints(q.START_TO_END,h)&1==q.compareBoundaryPoints(q.END_TO_START,h)?c.compareBoundaryPoints=function(a,b){b=b.nativeRange||b;a==b.START_TO_END?a=b.END_TO_START:a==b.END_TO_START&& (a=b.START_TO_END);return this.nativeRange.compareBoundaryPoints(a,b)}:c.compareBoundaryPoints=function(a,b){return this.nativeRange.compareBoundaryPoints(a,b.nativeRange||b)};a.util.isHostMethod(q,"createContextualFragment")&&(c.createContextualFragment=function(a){return this.nativeRange.createContextualFragment(a)});f.getBody(document).removeChild(g);q.detach();h.detach()})(),a.createNativeRange=function(a){a=a||document;return a.createRange()};else if(a.features.implementsTextRange){e=function(a){this.textRange= a;this.refresh()};e.prototype=new k(document);e.prototype.refresh=function(){var a,c,d=this.textRange;a=d.parentElement();var e=d.duplicate();e.collapse(!0);c=e.parentElement();e=d.duplicate();e.collapse(!1);d=e.parentElement();c=c==d?c:f.getCommonAncestor(c,d);c=c==a?c:f.getCommonAncestor(a,c);0==this.textRange.compareEndPoints("StartToEnd",this.textRange)?c=a=b(this.textRange,c,!0,!0):(a=b(this.textRange,c,!0,!1),c=b(this.textRange,c,!1,!1));this.setStart(a.node,a.offset);this.setEnd(c.node,c.offset)}; k.copyComparisonConstants(e);var h=function(){return this}();"undefined"==typeof h.Range&&(h.Range=e);a.createNativeRange=function(a){a=a||document;return a.body.createTextRange()}}a.features.implementsTextRange&&(e.rangeToTextRange=function(a){if(a.collapsed)return d(new g(a.startContainer,a.startOffset),!0);var b=d(new g(a.startContainer,a.startOffset),!0),c=d(new g(a.endContainer,a.endOffset),!1);a=f.getDocument(a.startContainer).body.createTextRange();a.setEndPoint("StartToStart",b);a.setEndPoint("EndToEnd", c);return a});e.prototype.getName=function(){return"WrappedRange"};a.WrappedRange=e;a.createRange=function(b){b=b||document;return new e(a.createNativeRange(b))};a.createRangyRange=function(a){a=a||document;return new k(a)};a.createIframeRange=function(b){return a.createRange(f.getIframeDocument(b))};a.createIframeRangyRange=function(b){return a.createRangyRange(f.getIframeDocument(b))};a.addCreateMissingNativeApiListener(function(b){b=b.document;"undefined"==typeof b.createRange&&(b.createRange= function(){return a.createRange(this)});b=b=null})}); rangy.createModule("WrappedSelection",function(a,c){function b(a){return(a||window).getSelection()}function d(a){return(a||window).document.selection}function e(a,b,c){var d=c?"end":"start";c=c?"start":"end";a.anchorNode=b[d+"Container"];a.anchorOffset=b[d+"Offset"];a.focusNode=b[c+"Container"];a.focusOffset=b[c+"Offset"]}function f(a){a.anchorNode=a.focusNode=null;a.anchorOffset=a.focusOffset=0;a.rangeCount=0;a.isCollapsed=!0;a._ranges.length=0}function g(b){var c;b instanceof v?(c=b._selectionNativeRange, c||(c=a.createNativeRange(r.getDocument(b.startContainer)),c.setEnd(b.endContainer,b.endOffset),c.setStart(b.startContainer,b.startOffset),b._selectionNativeRange=c,b.attachListener("detach",function(){this._selectionNativeRange=null}))):b instanceof t?c=b.nativeRange:a.features.implementsDomRange&&b instanceof r.getWindow(b.startContainer).Range&&(c=b);return c}function k(a){var b=a.getNodes(),c;a:if(b.length&&1==b[0].nodeType){c=1;for(var d=b.length;c<d;++c)if(!r.isAncestorOf(b[0],b[c])){c=!1;break a}c= !0}else c=!1;if(!c)throw Error("getSingleElementFromRange: range "+a.inspect()+" did not consist of a single element");return b[0]}function h(a,b){var c=new t(b);a._ranges=[c];e(a,c,!1);a.rangeCount=1;a.isCollapsed=c.collapsed}function l(b){b._ranges.length=0;if("None"==b.docSelection.type)f(b);else{var c=b.docSelection.createRange();if(c&&"undefined"!=typeof c.text)h(b,c);else{b.rangeCount=c.length;for(var d,l=r.getDocument(c.item(0)),g=0;g<b.rangeCount;++g)d=a.createRange(l),d.selectNode(c.item(g)), b._ranges.push(d);b.isCollapsed=1==b.rangeCount&&b._ranges[0].collapsed;e(b,b._ranges[b.rangeCount-1],!1)}}}function p(a,b){for(var c=a.docSelection.createRange(),d=k(b),e=r.getDocument(c.item(0)),e=r.getBody(e).createControlRange(),h=0,f=c.length;h<f;++h)e.add(c.item(h));try{e.add(d)}catch(g){throw Error("addRange(): Element within the specified Range could not be added to control selection (does it have layout?)");}e.select();l(a)}function n(a,b,c){this.nativeSelection=a;this.docSelection=b;this._ranges= [];this.win=c;this.refresh()}function u(a,b){for(var c=r.getDocument(b[0].startContainer),c=r.getBody(c).createControlRange(),d=0,e;d<rangeCount;++d){e=k(b[d]);try{c.add(e)}catch(h){throw Error("setRanges(): Element within the one of the specified Ranges could not be added to control selection (does it have layout?)");}}c.select();l(a)}function D(a,b){if(a.anchorNode&&r.getDocument(a.anchorNode)!==r.getDocument(b))throw new w("WRONG_DOCUMENT_ERR");}function q(a){var b=[],c=new A(a.anchorNode,a.anchorOffset), d=new A(a.focusNode,a.focusOffset),e="function"==typeof a.getName?a.getName():"Selection";if("undefined"!=typeof a.rangeCount)for(var h=0,l=a.rangeCount;h<l;++h)b[h]=v.inspect(a.getRangeAt(h));return"["+e+"(Ranges: "+b.join(", ")+")(anchor: "+c.inspect()+", focus: "+d.inspect()+"]"}a.requireModules(["DomUtil","DomRange","WrappedRange"]);a.config.checkSelectionRanges=!0;var r=a.dom,s=a.util,v=a.DomRange,t=a.WrappedRange,w=a.DOMException,A=r.DomPosition,z,E,y=a.util.isHostMethod(window,"getSelection"), B=a.util.isHostObject(document,"selection"),x=B&&(!y||a.config.preferTextRange);x?(z=d,a.isSelectionValid=function(a){a=(a||window).document;var b=a.selection;return"None"!=b.type||r.getDocument(b.createRange().parentElement())==a}):y?(z=b,a.isSelectionValid=function(){return!0}):c.fail("Neither document.selection or window.getSelection() detected.");a.getNativeSelection=z;var y=z(),L=a.createNativeRange(document),H=r.getBody(document),G=s.areHostObjects(y,s.areHostProperties(y,["anchorOffset","focusOffset"])); a.features.selectionHasAnchorAndFocus=G;var N=s.isHostMethod(y,"extend");a.features.selectionHasExtend=N;var P="number"==typeof y.rangeCount;a.features.selectionHasRangeCount=P;var O=!1,R=!0;s.areHostMethods(y,["addRange","getRangeAt","removeAllRanges"])&&("number"==typeof y.rangeCount&&a.features.implementsDomRange)&&function(){var a=document.createElement("iframe");H.appendChild(a);var b=r.getIframeDocument(a);b.open();b.write("<html><head></head><body>12</body></html>");b.close();var c=r.getIframeWindow(a).getSelection(), d=b.documentElement.lastChild.firstChild,b=b.createRange();b.setStart(d,1);b.collapse(!0);c.addRange(b);R=1==c.rangeCount;c.removeAllRanges();var e=b.cloneRange();b.setStart(d,0);e.setEnd(d,2);c.addRange(b);c.addRange(e);O=2==c.rangeCount;b.detach();e.detach();H.removeChild(a)}();a.features.selectionSupportsMultipleRanges=O;a.features.collapsedNonEditableSelectionsSupported=R;var C=!1,m;H&&s.isHostMethod(H,"createControlRange")&&(m=H.createControlRange(),s.areHostProperties(m,["item","add"])&&(C= !0));a.features.implementsControlRange=C;E=G?function(a){return a.anchorNode===a.focusNode&&a.anchorOffset===a.focusOffset}:function(a){return a.rangeCount?a.getRangeAt(a.rangeCount-1).collapsed:!1};var I;s.isHostMethod(y,"getRangeAt")?I=function(a,b){try{return a.getRangeAt(b)}catch(c){return null}}:G&&(I=function(b){var c=r.getDocument(b.anchorNode),c=a.createRange(c);c.setStart(b.anchorNode,b.anchorOffset);c.setEnd(b.focusNode,b.focusOffset);c.collapsed!==this.isCollapsed&&(c.setStart(b.focusNode, b.focusOffset),c.setEnd(b.anchorNode,b.anchorOffset));return c});a.getSelection=function(a){a=a||window;var b=a._rangySelection,c=z(a),e=B?d(a):null;b?(b.nativeSelection=c,b.docSelection=e,b.refresh(a)):(b=new n(c,e,a),a._rangySelection=b);return b};a.getIframeSelection=function(b){return a.getSelection(r.getIframeWindow(b))};m=n.prototype;if(!x&&G&&s.areHostMethods(y,["removeAllRanges","addRange"])){m.removeAllRanges=function(){this.nativeSelection.removeAllRanges();f(this)};var F=function(b,c){var d= v.getRangeDocument(c),d=a.createRange(d);d.collapseToPoint(c.endContainer,c.endOffset);b.nativeSelection.addRange(g(d));b.nativeSelection.extend(c.startContainer,c.startOffset);b.refresh()};m.addRange=P?function(b,c){if(C&&B&&"Control"==this.docSelection.type)p(this,b);else if(c&&N)F(this,b);else{var d;O?d=this.rangeCount:(this.removeAllRanges(),d=0);this.nativeSelection.addRange(g(b));this.rangeCount=this.nativeSelection.rangeCount;this.rangeCount==d+1?(a.config.checkSelectionRanges&&(d=I(this.nativeSelection, this.rangeCount-1))&&!v.rangesEqual(d,b)&&(b=new t(d)),this._ranges[this.rangeCount-1]=b,e(this,b,K(this.nativeSelection)),this.isCollapsed=E(this)):this.refresh()}}:function(a,b){b&&N?F(this,a):(this.nativeSelection.addRange(g(a)),this.refresh())};m.setRanges=function(a){if(C&&1<a.length)u(this,a);else{this.removeAllRanges();for(var b=0,c=a.length;b<c;++b)this.addRange(a[b])}}}else if(s.isHostMethod(y,"empty")&&s.isHostMethod(L,"select")&&C&&x)m.removeAllRanges=function(){try{if(this.docSelection.empty(), "None"!=this.docSelection.type){var a;if(this.anchorNode)a=r.getDocument(this.anchorNode);else if("Control"==this.docSelection.type){var b=this.docSelection.createRange();b.length&&(a=r.getDocument(b.item(0)).body.createTextRange())}a&&(a.body.createTextRange().select(),this.docSelection.empty())}}catch(c){}f(this)},m.addRange=function(a){"Control"==this.docSelection.type?p(this,a):(t.rangeToTextRange(a).select(),this._ranges[0]=a,this.rangeCount=1,this.isCollapsed=this._ranges[0].collapsed,e(this, a,!1))},m.setRanges=function(a){this.removeAllRanges();var b=a.length;1<b?u(this,a):b&&this.addRange(a[0])};else return c.fail("No means of selecting a Range or TextRange was found"),!1;m.getRangeAt=function(a){if(0>a||a>=this.rangeCount)throw new w("INDEX_SIZE_ERR");return this._ranges[a]};var J;if(x)J=function(b){var c;a.isSelectionValid(b.win)?c=b.docSelection.createRange():(c=r.getBody(b.win.document).createTextRange(),c.collapse(!0));"Control"==b.docSelection.type?l(b):c&&"undefined"!=typeof c.text? h(b,c):f(b)};else if(s.isHostMethod(y,"getRangeAt")&&"number"==typeof y.rangeCount)J=function(b){if(C&&B&&"Control"==b.docSelection.type)l(b);else if(b._ranges.length=b.rangeCount=b.nativeSelection.rangeCount,b.rangeCount){for(var c=0,d=b.rangeCount;c<d;++c)b._ranges[c]=new a.WrappedRange(b.nativeSelection.getRangeAt(c));e(b,b._ranges[b.rangeCount-1],K(b.nativeSelection));b.isCollapsed=E(b)}else f(b)};else if(G&&"boolean"==typeof y.isCollapsed&&"boolean"==typeof L.collapsed&&a.features.implementsDomRange)J= function(a){var b;b=a.nativeSelection;b.anchorNode?(b=I(b,0),a._ranges=[b],a.rangeCount=1,b=a.nativeSelection,a.anchorNode=b.anchorNode,a.anchorOffset=b.anchorOffset,a.focusNode=b.focusNode,a.focusOffset=b.focusOffset,a.isCollapsed=E(a)):f(a)};else return c.fail("No means of obtaining a Range or TextRange from the user's selection was found"),!1;m.refresh=function(a){var b=a?this._ranges.slice(0):null;J(this);if(a){a=b.length;if(a!=this._ranges.length)return!1;for(;a--;)if(!v.rangesEqual(b[a],this._ranges[a]))return!1; return!0}};var M=function(a,b){var c=a.getAllRanges(),d=!1;a.removeAllRanges();for(var e=0,h=c.length;e<h;++e)d||b!==c[e]?a.addRange(c[e]):d=!0;a.rangeCount||f(a)};m.removeRange=C?function(a){if("Control"==this.docSelection.type){var b=this.docSelection.createRange();a=k(a);for(var c=r.getDocument(b.item(0)),c=r.getBody(c).createControlRange(),d,e=!1,h=0,f=b.length;h<f;++h)d=b.item(h),d!==a||e?c.add(b.item(h)):e=!0;c.select();l(this)}else M(this,a)}:function(a){M(this,a)};var K;!x&&G&&a.features.implementsDomRange? (K=function(a){var b=!1;a.anchorNode&&(b=1==r.comparePoints(a.anchorNode,a.anchorOffset,a.focusNode,a.focusOffset));return b},m.isBackwards=function(){return K(this)}):K=m.isBackwards=function(){return!1};m.toString=function(){for(var a=[],b=0,c=this.rangeCount;b<c;++b)a[b]=""+this._ranges[b];return a.join("")};m.collapse=function(b,c){D(this,b);var d=a.createRange(r.getDocument(b));d.collapseToPoint(b,c);this.removeAllRanges();this.addRange(d);this.isCollapsed=!0};m.collapseToStart=function(){if(this.rangeCount){var a= this._ranges[0];this.collapse(a.startContainer,a.startOffset)}else throw new w("INVALID_STATE_ERR");};m.collapseToEnd=function(){if(this.rangeCount){var a=this._ranges[this.rangeCount-1];this.collapse(a.endContainer,a.endOffset)}else throw new w("INVALID_STATE_ERR");};m.selectAllChildren=function(b){D(this,b);var c=a.createRange(r.getDocument(b));c.selectNodeContents(b);this.removeAllRanges();this.addRange(c)};m.deleteFromDocument=function(){if(C&&B&&"Control"==this.docSelection.type){for(var a=this.docSelection.createRange(), b;a.length;)b=a.item(0),a.remove(b),b.parentNode.removeChild(b);this.refresh()}else if(this.rangeCount){a=this.getAllRanges();this.removeAllRanges();b=0;for(var c=a.length;b<c;++b)a[b].deleteContents();this.addRange(a[c-1])}};m.getAllRanges=function(){return this._ranges.slice(0)};m.setSingleRange=function(a){this.setRanges([a])};m.containsNode=function(a,b){for(var c=0,d=this._ranges.length;c<d;++c)if(this._ranges[c].containsNode(a,b))return!0;return!1};m.toHtml=function(){var a="";if(this.rangeCount){for(var a= v.getRangeDocument(this._ranges[0]).createElement("div"),b=0,c=this._ranges.length;b<c;++b)a.appendChild(this._ranges[b].cloneContents());a=a.innerHTML}return a};m.getName=function(){return"WrappedSelection"};m.inspect=function(){return q(this)};m.detach=function(){this.win=this.anchorNode=this.focusNode=this.win._rangySelection=null};n.inspect=q;a.Selection=n;a.selectionPrototype=m;a.addCreateMissingNativeApiListener(function(b){"undefined"==typeof b.getSelection&&(b.getSelection=function(){return a.getSelection(this)}); b=null})});var Base=function(){}; Base.extend=function(a,c){var b=Base.prototype.extend;Base._prototyping=!0;var d=new this;b.call(d,a);d.base=function(){};delete Base._prototyping;var e=d.constructor,f=d.constructor=function(){if(!Base._prototyping)if(this._constructing||this.constructor==f)this._constructing=!0,e.apply(this,arguments),delete this._constructing;else if(null!=arguments[0])return(arguments[0].extend||b).call(arguments[0],d)};f.ancestor=this;f.extend=this.extend;f.forEach=this.forEach;f.implement=this.implement;f.prototype= d;f.toString=this.toString;f.valueOf=function(a){return"object"==a?f:e.valueOf()};b.call(f,c);"function"==typeof f.init&&f.init();return f}; Base.prototype={extend:function(a,c){if(1<arguments.length){var b=this[a];if(b&&"function"==typeof c&&(!b.valueOf||b.valueOf()!=c.valueOf())&&/\bbase\b/.test(c)){var d=c.valueOf();c=function(){var a=this.base||Base.prototype.base;this.base=b;var c=d.apply(this,arguments);this.base=a;return c};c.valueOf=function(a){return"object"==a?c:d};c.toString=Base.toString}this[a]=c}else if(a){var e=Base.prototype.extend;Base._prototyping||"function"==typeof this||(e=this.extend||e);for(var f={toSource:null}, g=["constructor","toString","valueOf"],k=Base._prototyping?0:1;h=g[k++];)a[h]!=f[h]&&e.call(this,h,a[h]);for(var h in a)f[h]||e.call(this,h,a[h])}return this}}; Base=Base.extend({constructor:function(a){this.extend(a)}},{ancestor:Object,version:"1.1",forEach:function(a,c,b){for(var d in a)void 0===this.prototype[d]&&c.call(b,a[d],d,a)},implement:function(){for(var a=0;a<arguments.length;a++)if("function"==typeof arguments[a])arguments[a](this.prototype);else this.prototype.extend(arguments[a]);return this},toString:function(){return String(this.valueOf())}}); wysihtml5.browser=function(){var a=navigator.userAgent,c=document.createElement("div"),b=-1!==a.indexOf("MSIE")&&-1===a.indexOf("Opera"),d=-1!==a.indexOf("Gecko")&&-1===a.indexOf("KHTML"),e=-1!==a.indexOf("AppleWebKit/"),f=-1!==a.indexOf("Chrome/"),g=-1!==a.indexOf("Opera/");return{USER_AGENT:a,supported:function(){var a=this.USER_AGENT.toLowerCase(),b="contentEditable"in c,d=document.execCommand&&document.queryCommandSupported&&document.queryCommandState,e=document.querySelector&&document.querySelectorAll, a=this.isIos()&&5>+(/ipad|iphone|ipod/.test(a)&&a.match(/ os (\d+).+? like mac os x/)||[,0])[1]||this.isAndroid()&&4>+(a.match(/android (\d+)/)||[,0])[1]||-1!==a.indexOf("opera mobi")||-1!==a.indexOf("hpwos/");return b&&d&&e&&!a},isTouchDevice:function(){return this.supportsEvent("touchmove")},isIos:function(){return/ipad|iphone|ipod/i.test(this.USER_AGENT)},isAndroid:function(){return-1!==this.USER_AGENT.indexOf("Android")},supportsSandboxedIframes:function(){return b},throwsMixedContentWarningWhenIframeSrcIsEmpty:function(){return!("querySelector"in document)},displaysCaretInEmptyContentEditableCorrectly:function(){return b},hasCurrentStyleProperty:function(){return"currentStyle"in c},hasHistoryIssue:function(){return d&&"Mac"===navigator.platform.substr(0,3)},insertsLineBreaksOnReturn:function(){return d},supportsPlaceholderAttributeOn:function(a){return"placeholder"in a},supportsEvent:function(a){var b;(b="on"+a in c)||(c.setAttribute("on"+a,"return;"),b="function"===typeof c["on"+a]);return b},supportsEventsInIframeCorrectly:function(){return!g}, supportsHTML5Tags:function(a){a=a.createElement("div");a.innerHTML="<article>foo</article>";return"<article>foo</article>"===a.innerHTML.toLowerCase()},supportsCommand:function(){var a={formatBlock:b,insertUnorderedList:b||e,insertOrderedList:b||e},c={insertHTML:d};return function(b,d){if(!a[d]){try{return b.queryCommandSupported(d)}catch(e){}try{return b.queryCommandEnabled(d)}catch(f){return!!c[d]}}return!1}}(),doesAutoLinkingInContentEditable:function(){return b},canDisableAutoLinking:function(){return this.supportsCommand(document, "AutoUrlDetect")},clearsContentEditableCorrectly:function(){return d||g||e},supportsGetAttributeCorrectly:function(){return"1"!=document.createElement("td").getAttribute("rowspan")},canSelectImagesInContentEditable:function(){return d||b||g},autoScrollsToCaret:function(){return!e},autoClosesUnclosedTags:function(){var a=c.cloneNode(!1),b;a.innerHTML="<p><div></div>";a=a.innerHTML.toLowerCase();b="<p></p><div></div>"===a||"<p><div></div></p>"===a;this.autoClosesUnclosedTags=function(){return b};return b}, supportsNativeGetElementsByClassName:function(){return-1!==String(document.getElementsByClassName).indexOf("[native code]")},supportsSelectionModify:function(){return"getSelection"in window&&"modify"in window.getSelection()},needsSpaceAfterLineBreak:function(){return g},supportsSpeechApiOn:function(b){return 11<=(a.match(/Chrome\/(\d+)/)||[,0])[1]&&("onwebkitspeechchange"in b||"speech"in b)},crashesWhenDefineProperty:function(a){return b&&("XMLHttpRequest"===a||"XDomainRequest"===a)},doesAsyncFocus:function(){return b}, hasProblemsSettingCaretAfterImg:function(){return b},hasUndoInContextMenu:function(){return d||f||g},hasInsertNodeIssue:function(){return g},hasIframeFocusIssue:function(){return b},createsNestedInvalidMarkupAfterPaste:function(){return e}}}(); wysihtml5.lang.array=function(a){return{contains:function(c){if(a.indexOf)return-1!==a.indexOf(c);for(var b=0,d=a.length;b<d;b++)if(a[b]===c)return!0;return!1},without:function(c){c=wysihtml5.lang.array(c);for(var b=[],d=0,e=a.length;d<e;d++)c.contains(a[d])||b.push(a[d]);return b},get:function(){for(var c=0,b=a.length,d=[];c<b;c++)d.push(a[c]);return d}}}; wysihtml5.lang.Dispatcher=Base.extend({on:function(a,c){this.events=this.events||{};this.events[a]=this.events[a]||[];this.events[a].push(c);return this},off:function(a,c){this.events=this.events||{};var b=0,d,e;if(a){d=this.events[a]||[];for(e=[];b<d.length;b++)d[b]!==c&&c&&e.push(d[b]);this.events[a]=e}else this.events={};return this},fire:function(a,c){this.events=this.events||{};for(var b=this.events[a]||[],d=0;d<b.length;d++)b[d].call(this,c);return this},observe:function(){return this.on.apply(this, arguments)},stopObserving:function(){return this.off.apply(this,arguments)}});wysihtml5.lang.object=function(a){return{merge:function(c){for(var b in c)a[b]=c[b];return this},get:function(){return a},clone:function(){var c={},b;for(b in a)c[b]=a[b];return c},isArray:function(){return"[object Array]"===Object.prototype.toString.call(a)}}}; (function(){var a=/^\s+/,c=/\s+$/,b=/[&<>"]/g,d={"&":"&","<":"<",">":">",'"':"""};wysihtml5.lang.string=function(e){e=String(e);return{trim:function(){return e.replace(a,"").replace(c,"")},interpolate:function(a){for(var b in a)e=this.replace("#{"+b+"}").by(a[b]);return e},replace:function(a){return{by:function(b){return e.split(a).join(b)}}},escapeHTML:function(){return e.replace(b,function(a){return d[a]})}}}})(); (function(a){function c(a){return a.replace(e,function(a,b){var c=(b.match(f)||[])[1]||"",d=k[c];b=b.replace(f,"");b.split(d).length>b.split(c).length&&(b+=c,c="");var e=d=b;b.length>g&&(e=e.substr(0,g)+"...");"www."===d.substr(0,4)&&(d="http://"+d);return'<a href="'+d+'">'+e+"</a>"+c})}function b(h){if(!d.contains(h.nodeName))if(h.nodeType===a.TEXT_NODE&&h.data.match(e)){var l=h.parentNode,f=a.lang.string(h.data).escapeHTML(),g;g=l.ownerDocument;var k=g._wysihtml5_tempElement;k||(k=g._wysihtml5_tempElement= g.createElement("div"));g=k;g.innerHTML="<span></span>"+c(f);for(g.removeChild(g.firstChild);g.firstChild;)l.insertBefore(g.firstChild,h);l.removeChild(h)}else{l=a.lang.array(h.childNodes).get();f=l.length;for(g=0;g<f;g++)b(l[g]);return h}}var d=a.lang.array("CODE PRE A SCRIPT HEAD TITLE STYLE".split(" ")),e=/((https?:\/\/|www\.)[^\s<]{3,})/gi,f=/([^\w\/\-](,?))$/i,g=100,k={")":"(","]":"[","}":"{"};a.dom.autoLink=function(a){var c;a:{c=a;for(var e;c.parentNode;){c=c.parentNode;e=c.nodeName;if(d.contains(e)){c= !0;break a}if("body"===e)break}c=!1}if(c)return a;a===a.ownerDocument.documentElement&&(a=a.ownerDocument.body);return b(a)};a.dom.autoLink.URL_REG_EXP=e})(wysihtml5); (function(a){var c=a.dom;c.addClass=function(a,d){var e=a.classList;if(e)return e.add(d);c.hasClass(a,d)||(a.className+=" "+d)};c.removeClass=function(a,c){var e=a.classList;if(e)return e.remove(c);a.className=a.className.replace(RegExp("(^|\\s+)"+c+"(\\s+|$)")," ")};c.hasClass=function(a,c){var e=a.classList;if(e)return e.contains(c);e=a.className;return 0<e.length&&(e==c||RegExp("(^|\\s)"+c+"(\\s|$)").test(e))}})(wysihtml5); wysihtml5.dom.contains=function(){var a=document.documentElement;if(a.contains)return function(a,b){b.nodeType!==wysihtml5.ELEMENT_NODE&&(b=b.parentNode);return a!==b&&a.contains(b)};if(a.compareDocumentPosition)return function(a,b){return!!(a.compareDocumentPosition(b)&16)}}(); wysihtml5.dom.convertToList=function(){function a(a,b){var d=a.createElement("li");b.appendChild(d);return d}return function(c,b){if("UL"===c.nodeName||"OL"===c.nodeName||"MENU"===c.nodeName)return c;var d=c.ownerDocument,e=d.createElement(b),f=c.querySelectorAll("br"),g=f.length,k,h,l,p,n;for(n=0;n<g;n++)for(k=f[n];(h=k.parentNode)&&h!==c&&h.lastChild===k;){if("block"===wysihtml5.dom.getStyle("display").from(h)){h.removeChild(k);break}wysihtml5.dom.insert(k).after(k.parentNode)}f=wysihtml5.lang.array(c.childNodes).get(); g=f.length;for(n=0;n<g;n++)p=p||a(d,e),k=f[n],h="block"===wysihtml5.dom.getStyle("display").from(k),l="BR"===k.nodeName,h?(p=p.firstChild?a(d,e):p,p.appendChild(k),p=null):l?p=p.firstChild?null:p:p.appendChild(k);0===f.length&&a(d,e);c.parentNode.replaceChild(e,c);return e}}();wysihtml5.dom.copyAttributes=function(a){return{from:function(c){return{to:function(b){for(var d,e=0,f=a.length;e<f;e++)d=a[e],"undefined"!==typeof c[d]&&""!==c[d]&&(b[d]=c[d]);return{andTo:arguments.callee}}}}}}; (function(a){var c=["-webkit-box-sizing","-moz-box-sizing","-ms-box-sizing","box-sizing"],b=function(b){var e;a:{e=0;for(var f=c.length;e<f;e++)if("border-box"===a.getStyle(c[e]).from(b)){e=c[e];break a}e=void 0}return e?parseInt(a.getStyle("width").from(b),10)<b.offsetWidth:!1};a.copyStyles=function(d){return{from:function(e){b(e)&&(d=wysihtml5.lang.array(d).without(c));for(var f="",g=d.length,k=0,h;k<g;k++)h=d[k],f+=h+":"+a.getStyle(h).from(e)+";";return{to:function(b){a.setStyles(f).on(b);return{andTo:arguments.callee}}}}}}})(wysihtml5.dom); (function(a){a.dom.delegate=function(c,b,d,e){return a.dom.observe(c,d,function(d){for(var g=d.target,k=a.lang.array(c.querySelectorAll(b));g&&g!==c;){if(k.contains(g)){e.call(g,d);break}g=g.parentNode}})}})(wysihtml5); wysihtml5.dom.getAsDom=function(){var a="abbr article aside audio bdi canvas command datalist details figcaption figure footer header hgroup keygen mark meter nav output progress rp rt ruby svg section source summary time track video wbr".split(" ");return function(c,b){b=b||document;var d;if("object"===typeof c&&c.nodeType)d=b.createElement("div"),d.appendChild(c);else if(wysihtml5.browser.supportsHTML5Tags(b))d=b.createElement("div"),d.innerHTML=c;else{d=b;if(!d._wysihtml5_supportsHTML5Tags){for(var e= 0,f=a.length;e<f;e++)d.createElement(a[e]);d._wysihtml5_supportsHTML5Tags=!0}d=b;e=d.createElement("div");e.style.display="none";d.body.appendChild(e);try{e.innerHTML=c}catch(g){}d.body.removeChild(e);d=e}return d}}(); wysihtml5.dom.getParentElement=function(){function a(a,b){return b&&b.length?"string"===typeof b?a===b:wysihtml5.lang.array(b).contains(a):!0}return function(c,b,d){d=d||50;if(b.className||b.classRegExp){a:{var e=b.nodeName,f=b.className;for(b=b.classRegExp;d--&&c&&"BODY"!==c.nodeName;){var g;if(g=c.nodeType===wysihtml5.ELEMENT_NODE)if(g=a(c.nodeName,e)){g=f;var k=(c.className||"").match(b)||[];g=g?k[k.length-1]===g:!!k.length}if(g)break a;c=c.parentNode}c=null}return c}a:{e=b.nodeName;for(f=d;f--&& c&&"BODY"!==c.nodeName;){if(a(c.nodeName,e))break a;c=c.parentNode}c=null}return c}}(); wysihtml5.dom.getStyle=function(){function a(a){return a.replace(b,function(a){return a.charAt(1).toUpperCase()})}var c={"float":"styleFloat"in document.createElement("div").style?"styleFloat":"cssFloat"},b=/\-[a-z]/g;return function(b){return{from:function(e){if(e.nodeType===wysihtml5.ELEMENT_NODE){var f=e.ownerDocument,g=c[b]||a(b),k=e.style,h=e.currentStyle,l=k[g];if(l)return l;if(h)try{return h[g]}catch(p){}var g=f.defaultView||f.parentWindow,f=("height"===b||"width"===b)&&"TEXTAREA"===e.nodeName, n;if(g.getComputedStyle)return f&&(n=k.overflow,k.overflow="hidden"),e=g.getComputedStyle(e,null).getPropertyValue(b),f&&(k.overflow=n||""),e}}}}}();wysihtml5.dom.hasElementWithTagName=function(){var a={},c=1;return function(b,d){var e=(b._wysihtml5_identifier||(b._wysihtml5_identifier=c++))+":"+d,f=a[e];f||(f=a[e]=b.getElementsByTagName(d));return 0<f.length}}(); (function(a){var c={},b=1;a.dom.hasElementWithClassName=function(d,e){if(!a.browser.supportsNativeGetElementsByClassName())return!!d.querySelector("."+e);var f=(d._wysihtml5_identifier||(d._wysihtml5_identifier=b++))+":"+e,g=c[f];g||(g=c[f]=d.getElementsByClassName(e));return 0<g.length}})(wysihtml5);wysihtml5.dom.insert=function(a){return{after:function(c){c.parentNode.insertBefore(a,c.nextSibling)},before:function(c){c.parentNode.insertBefore(a,c)},into:function(c){c.appendChild(a)}}}; wysihtml5.dom.insertCSS=function(a){a=a.join("\n");return{into:function(c){var b=c.createElement("style");b.type="text/css";b.styleSheet?b.styleSheet.cssText=a:b.appendChild(c.createTextNode(a));var d=c.querySelector("head link");d?d.parentNode.insertBefore(b,d):(c=c.querySelector("head"))&&c.appendChild(b)}}}; wysihtml5.dom.observe=function(a,c,b){c="string"===typeof c?[c]:c;for(var d,e,f=0,g=c.length;f<g;f++)e=c[f],a.addEventListener?a.addEventListener(e,b,!1):(d=function(c){"target"in c||(c.target=c.srcElement);c.preventDefault=c.preventDefault||function(){this.returnValue=!1};c.stopPropagation=c.stopPropagation||function(){this.cancelBubble=!0};b.call(a,c)},a.attachEvent("on"+e,d));return{stop:function(){for(var e,h=0,l=c.length;h<l;h++)e=c[h],a.removeEventListener?a.removeEventListener(e,b,!1):a.detachEvent("on"+ e,d)}}}; wysihtml5.dom.parse=function(){function a(c,e){var h=c.childNodes,l=h.length,f=b[c.nodeType],g=0,p,f=f&&f(c);if(!f)return null;for(g=0;g<l;g++)(p=a(h[g],e))&&f.appendChild(p);if(e&&!(f.nodeName.toLowerCase()!==d||f.childNodes.length&&f.attributes.length)){for(h=f.ownerDocument.createDocumentFragment();f.firstChild;)h.appendChild(f.firstChild);return h}return f}function c(a,b){b=b.toLowerCase();var c;if(c="IMG"==a.nodeName)if(c="src"==b){var d;a:{try{d=a.complete&&!a.mozMatchesSelector(":-moz-broken");break a}catch(e){if(a.complete&& "complete"===a.readyState){d=!0;break a}}d=void 0}c=!0===d}return c?a.src:k&&"outerHTML"in a?-1!=a.outerHTML.toLowerCase().indexOf(" "+b+"=")?a.getAttribute(b):null:a.getAttribute(b)}var b={1:function(a){var b,h,f=g.tags;h=a.nodeName.toLowerCase();b=a.scopeName;if(a._wysihtml5)return null;a._wysihtml5=1;if("wysihtml5-temp"===a.className)return null;b&&"HTML"!=b&&(h=b+":"+h);"outerHTML"in a&&(wysihtml5.browser.autoClosesUnclosedTags()||("P"!==a.nodeName||"</p>"===a.outerHTML.slice(-4).toLowerCase())|| (h="div"));if(h in f){b=f[h];if(!b||b.remove)return null;b="string"===typeof b?{rename_tag:b}:b}else if(a.firstChild)b={rename_tag:d};else return null;h=a.ownerDocument.createElement(b.rename_tag||h);var f={},k=b.set_class,s=b.add_class,v=b.set_attributes,t=b.check_attributes,w=g.classes,A=0,z=[];b=[];var E=[],y=[],B;v&&(f=wysihtml5.lang.object(v).clone());if(t)for(B in t)if(v=l[t[B]])v=v(c(a,B)),"string"===typeof v&&(f[B]=v);k&&z.push(k);if(s)for(B in s)if(v=p[s[B]])k=v(c(a,B)),"string"===typeof k&& z.push(k);w["_wysihtml5-temp-placeholder"]=1;(y=a.getAttribute("class"))&&(z=z.concat(y.split(e)));for(s=z.length;A<s;A++)a=z[A],w[a]&&b.push(a);for(w=b.length;w--;)a=b[w],wysihtml5.lang.array(E).contains(a)||E.unshift(a);E.length&&(f["class"]=E.join(" "));for(B in f)try{h.setAttribute(B,f[B])}catch(x){}f.src&&("undefined"!==typeof f.width&&h.setAttribute("width",f.width),"undefined"!==typeof f.height&&h.setAttribute("height",f.height));return h},3:function(a){var b=a.nextSibling;if(b&&b.nodeType=== wysihtml5.TEXT_NODE)b.data=a.data+b.data;else return b=a.data.replace(h,""),a.ownerDocument.createTextNode(b)}},d="span",e=/\s+/,f={tags:{},classes:{}},g={},k=!wysihtml5.browser.supportsGetAttributeCorrectly(),h=/\uFEFF/g,l={url:function(){var a=/^https?:\/\//i;return function(b){return b&&b.match(a)?b.replace(a,function(a){return a.toLowerCase()}):null}}(),src:function(){var a=/^(\/|https?:\/\/)/i;return function(b){return b&&b.match(a)?b.replace(a,function(a){return a.toLowerCase()}):null}}(),href:function(){var a= /^(\/|https?:\/\/|mailto:)/i;return function(b){return b&&b.match(a)?b.replace(a,function(a){return a.toLowerCase()}):null}}(),alt:function(){var a=/[^ a-z0-9_\-]/gi;return function(b){return b?b.replace(a,""):""}}(),numbers:function(){var a=/\D/g;return function(b){return(b=(b||"").replace(a,""))||null}}()},p={align_img:function(){var a={left:"wysiwyg-float-left",right:"wysiwyg-float-right"};return function(b){return a[String(b).toLowerCase()]}}(),align_text:function(){var a={left:"wysiwyg-text-align-left", right:"wysiwyg-text-align-right",center:"wysiwyg-text-align-center",justify:"wysiwyg-text-align-justify"};return function(b){return a[String(b).toLowerCase()]}}(),clear_br:function(){var a={left:"wysiwyg-clear-left",right:"wysiwyg-clear-right",both:"wysiwyg-clear-both",all:"wysiwyg-clear-both"};return function(b){return a[String(b).toLowerCase()]}}(),size_font:function(){var a={1:"wysiwyg-font-size-xx-small",2:"wysiwyg-font-size-small",3:"wysiwyg-font-size-medium",4:"wysiwyg-font-size-large",5:"wysiwyg-font-size-x-large", 6:"wysiwyg-font-size-xx-large",7:"wysiwyg-font-size-xx-large","-":"wysiwyg-font-size-smaller","+":"wysiwyg-font-size-larger"};return function(b){return a[String(b).charAt(0)]}}()};return function(b,c,d,e){wysihtml5.lang.object(g).merge(f).merge(c).get();d=d||b.ownerDocument||document;c=d.createDocumentFragment();var h="string"===typeof b,l;for(b=h?wysihtml5.dom.getAsDom(b,d):b;b.firstChild;)l=b.firstChild,d=a(l,e),b.removeChild(l),d&&c.appendChild(d);b.innerHTML="";b.appendChild(c);return h?wysihtml5.quirks.getCorrectInnerHTML(b): b}}();wysihtml5.dom.removeEmptyTextNodes=function(a){for(var c=wysihtml5.lang.array(a.childNodes).get(),b=c.length,d=0;d<b;d++)a=c[d],a.nodeType===wysihtml5.TEXT_NODE&&""===a.data&&a.parentNode.removeChild(a)};wysihtml5.dom.renameElement=function(a,c){for(var b=a.ownerDocument.createElement(c),d;d=a.firstChild;)b.appendChild(d);wysihtml5.dom.copyAttributes(["align","className"]).from(a).to(b);a.parentNode.replaceChild(b,a);return b}; wysihtml5.dom.replaceWithChildNodes=function(a){if(a.parentNode)if(a.firstChild){for(var c=a.ownerDocument.createDocumentFragment();a.firstChild;)c.appendChild(a.firstChild);a.parentNode.replaceChild(c,a)}else a.parentNode.removeChild(a)}; (function(a){function c(a){var c=a.ownerDocument.createElement("br");a.appendChild(c)}a.resolveList=function(b,d){if(b.nodeName.match(/^(MENU|UL|OL)$/)){var e=b.ownerDocument,f=e.createDocumentFragment(),g=b.previousElementSibling||b.previousSibling,k,h;if(d)for(g&&"block"!==a.getStyle("display").from(g)&&c(f);h=b.firstElementChild||b.firstChild;){for(e=h.lastChild;g=h.firstChild;)k=(k=g===e)&&"block"!==a.getStyle("display").from(g)&&"BR"!==g.nodeName,f.appendChild(g),k&&c(f);h.parentNode.removeChild(h)}else for(;h= b.firstElementChild||b.firstChild;){if(h.querySelector&&h.querySelector("div, p, ul, ol, menu, blockquote, h1, h2, h3, h4, h5, h6"))for(;g=h.firstChild;)f.appendChild(g);else{for(k=e.createElement("p");g=h.firstChild;)k.appendChild(g);f.appendChild(k)}h.parentNode.removeChild(h)}b.parentNode.replaceChild(f,b)}}})(wysihtml5.dom); (function(a){var c=document,b="parent top opener frameElement frames localStorage globalStorage sessionStorage indexedDB".split(" "),d="open close openDialog showModalDialog alert confirm prompt openDatabase postMessage XMLHttpRequest XDomainRequest".split(" "),e=["referrer","write","open","close"];a.dom.Sandbox=Base.extend({constructor:function(b,c){this.callback=b||a.EMPTY_FUNCTION;this.config=a.lang.object({}).merge(c).get();this.iframe=this._createIframe()},insertInto:function(a){"string"===typeof a&& (a=c.getElementById(a));a.appendChild(this.iframe)},getIframe:function(){return this.iframe},getWindow:function(){this._readyError()},getDocument:function(){this._readyError()},destroy:function(){var a=this.getIframe();a.parentNode.removeChild(a)},_readyError:function(){throw Error("wysihtml5.Sandbox: Sandbox iframe isn't loaded yet");},_createIframe:function(){var b=this,d=c.createElement("iframe");d.className="wysihtml5-sandbox";a.dom.setAttributes({security:"restricted",allowtransparency:"true", frameborder:0,width:0,height:0,marginwidth:0,marginheight:0}).on(d);a.browser.throwsMixedContentWarningWhenIframeSrcIsEmpty()&&(d.src="javascript:'<html></html>'");d.onload=function(){d.onreadystatechange=d.onload=null;b._onLoadIframe(d)};d.onreadystatechange=function(){/loaded|complete/.test(d.readyState)&&(d.onreadystatechange=d.onload=null,b._onLoadIframe(d))};return d},_onLoadIframe:function(f){if(a.dom.contains(c.documentElement,f)){var g=this,k=f.contentWindow,h=f.contentWindow.document,l=this._getHtml({charset:c.characterSet|| c.charset||"utf-8",stylesheets:this.config.stylesheets});h.open("text/html","replace");h.write(l);h.close();this.getWindow=function(){return f.contentWindow};this.getDocument=function(){return f.contentWindow.document};k.onerror=function(a,b,c){throw Error("wysihtml5.Sandbox: "+a,b,c);};if(!a.browser.supportsSandboxedIframes()){var p,l=0;for(p=b.length;l<p;l++)this._unset(k,b[l]);l=0;for(p=d.length;l<p;l++)this._unset(k,d[l],a.EMPTY_FUNCTION);l=0;for(p=e.length;l<p;l++)this._unset(h,e[l]);this._unset(h, "cookie","",!0)}this.loaded=!0;setTimeout(function(){g.callback(g)},0)}},_getHtml:function(b){var c=b.stylesheets,d="",e=0,l;if(c="string"===typeof c?[c]:c)for(l=c.length;e<l;e++)d+='<link rel="stylesheet" href="'+c[e]+'">';b.stylesheets=d;return a.lang.string('<!DOCTYPE html><html><head><meta charset="#{charset}">#{stylesheets}</head><body></body></html>').interpolate(b)},_unset:function(b,c,d,e){try{b[c]=d}catch(l){}try{b.__defineGetter__(c,function(){return d})}catch(p){}if(e)try{b.__defineSetter__(c, function(){})}catch(n){}if(!a.browser.crashesWhenDefineProperty(c))try{var u={get:function(){return d}};e&&(u.set=function(){});Object.defineProperty(b,c,u)}catch(D){}}})})(wysihtml5);(function(){var a={className:"class"};wysihtml5.dom.setAttributes=function(c){return{on:function(b){for(var d in c)b.setAttribute(a[d]||d,c[d])}}}})(); wysihtml5.dom.setStyles=function(a){return{on:function(c){c=c.style;if("string"===typeof a)c.cssText+=";"+a;else for(var b in a)"float"===b?(c.cssFloat=a[b],c.styleFloat=a[b]):c[b]=a[b]}}}; (function(a){a.simulatePlaceholder=function(c,b,d){var e=function(){b.hasPlaceholderSet()&&b.clear();b.placeholderSet=!1;a.removeClass(b.element,"placeholder")},f=function(){b.isEmpty()&&(b.placeholderSet=!0,b.setValue(d),a.addClass(b.element,"placeholder"))};c.on("set_placeholder",f).on("unset_placeholder",e).on("focus:composer",e).on("paste:composer",e).on("blur:composer",f);f()}})(wysihtml5.dom); (function(a){var c=document.documentElement;"textContent"in c?(a.setTextContent=function(a,c){a.textContent=c},a.getTextContent=function(a){return a.textContent}):"innerText"in c?(a.setTextContent=function(a,c){a.innerText=c},a.getTextContent=function(a){return a.innerText}):(a.setTextContent=function(a,c){a.nodeValue=c},a.getTextContent=function(a){return a.nodeValue})})(wysihtml5.dom); wysihtml5.quirks.cleanPastedHTML=function(){var a={"a u":wysihtml5.dom.replaceWithChildNodes};return function(c,b,d){b=b||a;d=d||c.ownerDocument||document;var e="string"===typeof c,f,g,k,h=0;c=e?wysihtml5.dom.getAsDom(c,d):c;for(k in b)for(f=c.querySelectorAll(k),d=b[k],g=f.length;h<g;h++)d(f[h]);return e?c.innerHTML:c}}(); wysihtml5.quirks.ensureProperClearing=function(){var a=function(){var a=this;setTimeout(function(){var b=a.innerHTML.toLowerCase();if("<p> </p>"==b||"<p> </p><p> </p>"==b)a.innerHTML=""},0)};return function(c){wysihtml5.dom.observe(c.element,["cut","keydown"],a)}}(); (function(a){a.quirks.getCorrectInnerHTML=function(c){var b=c.innerHTML;if(-1===b.indexOf("%7E"))return b;c=c.querySelectorAll("[href*='~'], [src*='~']");var d,e,f,g;g=0;for(f=c.length;g<f;g++)d=c[g].href||c[g].src,e=a.lang.string(d).replace("~").by("%7E"),b=a.lang.string(b).replace(e).by(d);return b}})(wysihtml5); (function(a){a.quirks.redraw=function(c){a.dom.addClass(c,"wysihtml5-quirks-redraw");a.dom.removeClass(c,"wysihtml5-quirks-redraw");try{var b=c.ownerDocument;b.execCommand("italic",!1,null);b.execCommand("italic",!1,null)}catch(d){}}})(wysihtml5); (function(a){var c=a.dom;a.Selection=Base.extend({constructor:function(a){window.rangy.init();this.editor=a;this.composer=a.composer;this.doc=this.composer.doc},getBookmark:function(){var a=this.getRange();return a&&a.cloneRange()},setBookmark:function(a){a&&this.setSelection(a)},setBefore:function(a){var c=rangy.createRange(this.doc);c.setStartBefore(a);c.setEndBefore(a);return this.setSelection(c)},setAfter:function(a){var c=rangy.createRange(this.doc);c.setStartAfter(a);c.setEndAfter(a);return this.setSelection(c)}, selectNode:function(b,d){var e=rangy.createRange(this.doc),f=b.nodeType===a.ELEMENT_NODE,g="canHaveHTML"in b?b.canHaveHTML:"IMG"!==b.nodeName,k=f?b.innerHTML:b.data,k=""===k||k===a.INVISIBLE_SPACE,h=c.getStyle("display").from(b),h="block"===h||"list-item"===h;if(k&&f&&g&&!d)try{b.innerHTML=a.INVISIBLE_SPACE}catch(l){}g?e.selectNodeContents(b):e.selectNode(b);g&&k&&f?e.collapse(h):g&&k&&(e.setStartAfter(b),e.setEndAfter(b));this.setSelection(e)},getSelectedNode:function(a){if(a&&this.doc.selection&& "Control"===this.doc.selection.type&&(a=this.doc.selection.createRange())&&a.length)return a.item(0);a=this.getSelection(this.doc);return a.focusNode===a.anchorNode?a.focusNode:(a=this.getRange(this.doc))?a.commonAncestorContainer:this.doc.body},executeAndRestore:function(b,d){var e=this.doc.body,f=d&&e.scrollTop,g=d&&e.scrollLeft,k='<span class="_wysihtml5-temp-placeholder">'+a.INVISIBLE_SPACE+"</span>",h=this.getRange(this.doc),l;if(h){a.browser.hasInsertNodeIssue()?this.doc.execCommand("insertHTML", !1,k):(k=h.createContextualFragment(k),h.insertNode(k));try{b(h.startContainer,h.endContainer)}catch(p){setTimeout(function(){throw p;},0)}(h=this.doc.querySelector("._wysihtml5-temp-placeholder"))?(k=rangy.createRange(this.doc),l=h.nextSibling,a.browser.hasInsertNodeIssue()&&l&&"BR"===l.nodeName?(l=this.doc.createTextNode(a.INVISIBLE_SPACE),c.insert(l).after(h),k.setStartBefore(l),k.setEndBefore(l)):(k.selectNode(h),k.deleteContents()),this.setSelection(k)):e.focus();d&&(e.scrollTop=f,e.scrollLeft= g);try{h.parentNode.removeChild(h)}catch(n){}}else b(e,e)},executeAndRestoreSimple:function(a){var c,e,f=this.getRange(),g=this.doc.body,k;if(f){c=f.getNodes([3]);g=c[0]||f.startContainer;k=c[c.length-1]||f.endContainer;c=g===f.startContainer?f.startOffset:0;e=k===f.endContainer?f.endOffset:k.length;try{a(f.startContainer,f.endContainer)}catch(h){setTimeout(function(){throw h;},0)}a=rangy.createRange(this.doc);try{a.setStart(g,c)}catch(l){}try{a.setEnd(k,e)}catch(p){}try{this.setSelection(a)}catch(n){}}else a(g, g)},set:function(a,c){var e=rangy.createRange(this.doc);e.setStart(a,c||0);this.setSelection(e)},insertHTML:function(a){a=rangy.createRange(this.doc).createContextualFragment(a);var c=a.lastChild;this.insertNode(a);c&&this.setAfter(c)},insertNode:function(a){var c=this.getRange();c&&c.insertNode(a)},surround:function(a){var c=this.getRange();if(c)try{c.surroundContents(a),this.selectNode(a)}catch(e){a.appendChild(c.extractContents()),c.insertNode(a)}},scrollIntoView:function(){var b=this.doc,c=b.documentElement.scrollHeight> b.documentElement.offsetHeight,e;(e=b._wysihtml5ScrollIntoViewElement)||(e=b.createElement("span"),e.innerHTML=a.INVISIBLE_SPACE);e=b._wysihtml5ScrollIntoViewElement=e;if(c){this.insertNode(e);var c=e,f=0;if(c.parentNode){do f+=c.offsetTop||0,c=c.offsetParent;while(c)}c=f;e.parentNode.removeChild(e);c>=b.body.scrollTop+b.documentElement.offsetHeight-5&&(b.body.scrollTop=c)}},selectLine:function(){a.browser.supportsSelectionModify()?this._selectLine_W3C():this.doc.selection&&this._selectLine_MSIE()}, _selectLine_W3C:function(){var a=this.doc.defaultView.getSelection();a.modify("extend","left","lineboundary");a.modify("extend","right","lineboundary")},_selectLine_MSIE:function(){var a=this.doc.selection.createRange(),c=a.boundingTop,e=this.doc.body.scrollWidth,f;if(a.moveToPoint){0===c&&(f=this.doc.createElement("span"),this.insertNode(f),c=f.offsetTop,f.parentNode.removeChild(f));c+=1;for(f=-10;f<e;f+=2)try{a.moveToPoint(f,c);break}catch(g){}for(f=this.doc.selection.createRange();0<=e;e--)try{f.moveToPoint(e, c);break}catch(k){}a.setEndPoint("EndToEnd",f);a.select()}},getText:function(){var a=this.getSelection();return a?a.toString():""},getNodes:function(a,c){var e=this.getRange();return e?e.getNodes([a],c):[]},getRange:function(){var a=this.getSelection();return a&&a.rangeCount&&a.getRangeAt(0)},getSelection:function(){return rangy.getSelection(this.doc.defaultView||this.doc.parentWindow)},setSelection:function(a){return rangy.getSelection(this.doc.defaultView||this.doc.parentWindow).setSingleRange(a)}})})(wysihtml5); (function(a,c){function b(a,b){return c.dom.isCharacterDataNode(a)?0==b?!!a.previousSibling:b==a.length?!!a.nextSibling:!0:0<b&&b<a.childNodes.length}function d(a,b,e){var f;c.dom.isCharacterDataNode(b)&&(0==e?(e=c.dom.getNodeIndex(b),b=b.parentNode):e==b.length?(e=c.dom.getNodeIndex(b)+1,b=b.parentNode):f=c.dom.splitDataNode(b,e));if(!f){f=b.cloneNode(!1);f.id&&f.removeAttribute("id");for(var g;g=b.childNodes[e];)f.appendChild(g);c.dom.insertAfter(f,b)}return b==a?f:d(a,f.parentNode,c.dom.getNodeIndex(f))} function e(b){this.firstTextNode=(this.isElementMerge=b.nodeType==a.ELEMENT_NODE)?b.lastChild:b;this.textNodes=[this.firstTextNode]}function f(a,b,c,d){this.tagNames=a||[g];this.cssClass=b||"";this.similarClassRegExp=c;this.normalize=d;this.applyToAnyTagName=!1}var g="span",k=/\s+/g;e.prototype={doMerge:function(){for(var a=[],b,c,d=0,e=this.textNodes.length;d<e;++d)b=this.textNodes[d],c=b.parentNode,a[d]=b.data,d&&(c.removeChild(b),c.hasChildNodes()||c.parentNode.removeChild(c));return this.firstTextNode.data= a=a.join("")},getLength:function(){for(var a=this.textNodes.length,b=0;a--;)b+=this.textNodes[a].length;return b},toString:function(){for(var a=[],b=0,c=this.textNodes.length;b<c;++b)a[b]="'"+this.textNodes[b].data+"'";return"[Merge("+a.join(",")+")]"}};f.prototype={getAncestorWithClass:function(b){for(var d;b;){if(this.cssClass)if(d=this.cssClass,b.className){var e=b.className.match(this.similarClassRegExp)||[];d=e[e.length-1]===d}else d=!1;else d=!0;if(b.nodeType==a.ELEMENT_NODE&&c.dom.arrayContains(this.tagNames, b.tagName.toLowerCase())&&d)return b;b=b.parentNode}return!1},postApply:function(a,b){for(var c=a[0],d=a[a.length-1],f=[],g,k=c,r=d,s=0,v=d.length,t,w,A=0,z=a.length;A<z;++A)t=a[A],(w=this.getAdjacentMergeableTextNode(t.parentNode,!1))?(g||(g=new e(w),f.push(g)),g.textNodes.push(t),t===c&&(k=g.firstTextNode,s=k.length),t===d&&(r=g.firstTextNode,v=g.getLength())):g=null;if(c=this.getAdjacentMergeableTextNode(d.parentNode,!0))g||(g=new e(d),f.push(g)),g.textNodes.push(c);if(f.length){A=0;for(z=f.length;A< z;++A)f[A].doMerge();b.setStart(k,s);b.setEnd(r,v)}},getAdjacentMergeableTextNode:function(b,c){var d=b.nodeType==a.TEXT_NODE,e=d?b.parentNode:b,f=c?"nextSibling":"previousSibling";if(d){if((d=b[f])&&d.nodeType==a.TEXT_NODE)return d}else if((d=e[f])&&this.areElementsMergeable(b,d))return d[c?"firstChild":"lastChild"];return null},areElementsMergeable:function(a,b){var d;if(d=c.dom.arrayContains(this.tagNames,(a.tagName||"").toLowerCase()))if(d=c.dom.arrayContains(this.tagNames,(b.tagName||"").toLowerCase()))if(d= a.className.replace(k," ")==b.className.replace(k," "))a:if(a.attributes.length!=b.attributes.length)d=!1;else{d=0;for(var e=a.attributes.length,f,g;d<e;++d)if(f=a.attributes[d],g=f.name,"class"!=g&&(g=b.attributes.getNamedItem(g),f.specified!=g.specified||f.specified&&f.nodeValue!==g.nodeValue)){d=!1;break a}d=!0}return d},createContainer:function(a){a=a.createElement(this.tagNames[0]);this.cssClass&&(a.className=this.cssClass);return a},applyToTextNode:function(a){var b=a.parentNode;1==b.childNodes.length&& c.dom.arrayContains(this.tagNames,b.tagName.toLowerCase())?this.cssClass&&(a=this.cssClass,b.className?(b.className&&(b.className=b.className.replace(this.similarClassRegExp,"")),b.className+=" "+a):b.className=a):(b=this.createContainer(c.dom.getDocument(a)),a.parentNode.insertBefore(b,a),b.appendChild(a))},isRemovable:function(b){return c.dom.arrayContains(this.tagNames,b.tagName.toLowerCase())&&a.lang.string(b.className).trim()==this.cssClass},undoToTextNode:function(a,c,e){c.containsNode(e)|| (a=c.cloneRange(),a.selectNode(e),a.isPointInRange(c.endContainer,c.endOffset)&&b(c.endContainer,c.endOffset)&&(d(e,c.endContainer,c.endOffset),c.setEndAfter(e)),a.isPointInRange(c.startContainer,c.startOffset)&&b(c.startContainer,c.startOffset)&&(e=d(e,c.startContainer,c.startOffset)));this.similarClassRegExp&&e.className&&(e.className=e.className.replace(this.similarClassRegExp,""));if(this.isRemovable(e)){c=e;for(e=c.parentNode;c.firstChild;)e.insertBefore(c.firstChild,c);e.removeChild(c)}},applyToRange:function(b){var c= b.getNodes([a.TEXT_NODE]);if(!c.length)try{var d=this.createContainer(b.endContainer.ownerDocument);b.surroundContents(d);this.selectNode(b,d);return}catch(e){}b.splitBoundaries();c=b.getNodes([a.TEXT_NODE]);if(c.length){for(var f=0,g=c.length;f<g;++f)d=c[f],this.getAncestorWithClass(d)||this.applyToTextNode(d);b.setStart(c[0],0);d=c[c.length-1];b.setEnd(d,d.length);this.normalize&&this.postApply(c,b)}},undoToRange:function(b){var c=b.getNodes([a.TEXT_NODE]),d,e;c.length?(b.splitBoundaries(),c=b.getNodes([a.TEXT_NODE])): (c=b.endContainer.ownerDocument.createTextNode(a.INVISIBLE_SPACE),b.insertNode(c),b.selectNode(c),c=[c]);for(var f=0,g=c.length;f<g;++f)d=c[f],(e=this.getAncestorWithClass(d))&&this.undoToTextNode(d,b,e);1==g?this.selectNode(b,c[0]):(b.setStart(c[0],0),d=c[c.length-1],b.setEnd(d,d.length),this.normalize&&this.postApply(c,b))},selectNode:function(b,c){var d=c.nodeType===a.ELEMENT_NODE,e="canHaveHTML"in c?c.canHaveHTML:!0,f=d?c.innerHTML:c.data;if((f=""===f||f===a.INVISIBLE_SPACE)&&d&&e)try{c.innerHTML= a.INVISIBLE_SPACE}catch(g){}b.selectNodeContents(c);f&&d?b.collapse(!1):f&&(b.setStartAfter(c),b.setEndAfter(c))},getTextSelectedByRange:function(a,b){var c=b.cloneRange();c.selectNodeContents(a);var d=c.intersection(b),d=d?d.toString():"";c.detach();return d},isAppliedToRange:function(b){var c=[],d,e=b.getNodes([a.TEXT_NODE]);if(!e.length)return(d=this.getAncestorWithClass(b.startContainer))?[d]:!1;for(var f=0,g=e.length,k;f<g;++f)if(k=this.getTextSelectedByRange(e[f],b),d=this.getAncestorWithClass(e[f]), ""==k||d)c.push(d);else return!1;return c},toggleRange:function(a){this.isAppliedToRange(a)?this.undoToRange(a):this.applyToRange(a)}};a.selection.HTMLApplier=f})(wysihtml5,rangy); wysihtml5.Commands=Base.extend({constructor:function(a){this.editor=a;this.composer=a.composer;this.doc=this.composer.doc},support:function(a){return wysihtml5.browser.supportsCommand(this.doc,a)},exec:function(a,c){var b=wysihtml5.commands[a],d=wysihtml5.lang.array(arguments).get(),e=b&&b.exec,f=null;this.editor.fire("beforecommand:composer");if(e)d.unshift(this.composer),f=e.apply(b,d);else try{f=this.doc.execCommand(a,!1,c)}catch(g){}this.editor.fire("aftercommand:composer");return f},state:function(a, c){var b=wysihtml5.commands[a],d=wysihtml5.lang.array(arguments).get(),e=b&&b.state;if(e)return d.unshift(this.composer),e.apply(b,d);try{return this.doc.queryCommandState(a)}catch(f){return!1}}});wysihtml5.commands.bold={exec:function(a,c){return wysihtml5.commands.formatInline.exec(a,c,"b")},state:function(a,c){return wysihtml5.commands.formatInline.state(a,c,"b")}}; (function(a){function c(c,g){var k=c.doc,h="_wysihtml5-temp-"+ +new Date,l=0,p,n,u;a.commands.formatInline.exec(c,b,d,h,/non-matching-class/g);p=k.querySelectorAll(d+"."+h);for(h=p.length;l<h;l++)for(u in n=p[l],n.removeAttribute("class"),g)n.setAttribute(u,g[u]);l=n;1===h&&(u=e.getTextContent(n),h=!!n.querySelector("*"),u=""===u||u===a.INVISIBLE_SPACE,!h&&u&&(e.setTextContent(n,g.text||n.href),k=k.createTextNode(" "),c.selection.setAfter(n),e.insert(k).after(n),l=k));c.selection.setAfter(l)}var b, d="A",e=a.dom;a.commands.createLink={exec:function(a,b,d){var h=this.state(a,b);h?a.selection.executeAndRestore(function(){for(var a=h.length,b=0,c,d,f;b<a;b++)c=h[b],d=e.getParentElement(c,{nodeName:"code"}),f=e.getTextContent(c),f.match(e.autoLink.URL_REG_EXP)&&!d?e.renameElement(c,"code"):e.replaceWithChildNodes(c)}):(d="object"===typeof d?d:{href:d},c(a,d))},state:function(b,c){return a.commands.formatInline.state(b,c,"A")}}})(wysihtml5); (function(a){var c=/wysiwyg-font-size-[0-9a-z\-]+/g;a.commands.fontSize={exec:function(b,d,e){return a.commands.formatInline.exec(b,d,"span","wysiwyg-font-size-"+e,c)},state:function(b,d,e){return a.commands.formatInline.state(b,d,"span","wysiwyg-font-size-"+e,c)}}})(wysihtml5); (function(a){var c=/wysiwyg-color-[0-9a-z]+/g;a.commands.foreColor={exec:function(b,d,e){return a.commands.formatInline.exec(b,d,"span","wysiwyg-color-"+e,c)},state:function(b,d,e){return a.commands.formatInline.state(b,d,"span","wysiwyg-color-"+e,c)}}})(wysihtml5); (function(a){function c(b){for(b=b.previousSibling;b&&b.nodeType===a.TEXT_NODE&&!a.lang.string(b.data).trim();)b=b.previousSibling;return b}function b(b){for(b=b.nextSibling;b&&b.nodeType===a.TEXT_NODE&&!a.lang.string(b.data).trim();)b=b.nextSibling;return b}function d(a){return"BR"===a.nodeName||"block"===g.getStyle("display").from(a)?!0:!1}function e(b,c,d,e){if(e)var f=g.observe(b,"DOMNodeInserted",function(b){b=b.target;var c;b.nodeType===a.ELEMENT_NODE&&(c=g.getStyle("display").from(b),"inline"!== c.substr(0,6)&&(b.className+=" "+e))});b.execCommand(c,!1,d);f&&f.stop()}function f(d,e){d.selection.selectLine();d.selection.surround(e);var f=b(e),g=c(e);f&&"BR"===f.nodeName&&f.parentNode.removeChild(f);g&&"BR"===g.nodeName&&g.parentNode.removeChild(g);(f=e.lastChild)&&"BR"===f.nodeName&&f.parentNode.removeChild(f);d.selection.selectNode(e,a.browser.displaysCaretInEmptyContentEditableCorrectly())}var g=a.dom,k="H1 H2 H3 H4 H5 H6 P BLOCKQUOTE DIV".split(" ");a.commands.formatBlock={exec:function(h, l,p,n,u){var D=h.doc,q=this.state(h,l,p,n,u),r=h.config.useLineBreaks,s=r?"DIV":"P",v;p="string"===typeof p?p.toUpperCase():p;if(q)h.selection.executeAndRestoreSimple(function(){u&&(q.className=q.className.replace(u,""));if(a.lang.string(q.className).trim()||!r&&"P"!==p)g.renameElement(q,"P"===p?"DIV":s);else{var e=q,f=e.ownerDocument,h=b(e),l=c(e);h&&!d(h)&&e.parentNode.insertBefore(f.createElement("br"),h);l&&!d(l)&&e.parentNode.insertBefore(f.createElement("br"),e);g.replaceWithChildNodes(q)}}); else{if(null===p||a.lang.array(k).contains(p))if(v=h.selection.getSelectedNode(),q=g.getParentElement(v,{nodeName:k})){h.selection.executeAndRestore(function(){p&&(q=g.renameElement(q,p));if(n){var a=q;a.className?(a.className=a.className.replace(u,""),a.className+=" "+n):a.className=n}});return}h.commands.support(l)?e(D,l,p||s,n):(q=D.createElement(p||s),n&&(q.className=n),f(h,q))}},state:function(a,b,c,d,e){c="string"===typeof c?c.toUpperCase():c;a=a.selection.getSelectedNode();return g.getParentElement(a, {nodeName:c,className:d,classRegExp:e})}}})(wysihtml5); (function(a){function c(c,f,g){var k=c+":"+f;if(!d[k]){var h=d,l=a.selection.HTMLApplier,p=b[c];c=p?[c.toLowerCase(),p.toLowerCase()]:[c.toLowerCase()];h[k]=new l(c,f,g,!0)}return d[k]}var b={strong:"b",em:"i",b:"strong",i:"em"},d={};a.commands.formatInline={exec:function(a,b,d,k,h){b=a.selection.getRange();if(!b)return!1;c(d,k,h).toggleRange(b);a.selection.setSelection(b)},state:function(d,f,g,k,h){f=d.doc;var l=b[g]||g;return!a.dom.hasElementWithTagName(f,g)&&!a.dom.hasElementWithTagName(f,l)|| k&&!a.dom.hasElementWithClassName(f,k)?!1:(d=d.selection.getRange())?c(g,k,h).isAppliedToRange(d):!1}}})(wysihtml5);wysihtml5.commands.insertHTML={exec:function(a,c,b){a.commands.support(c)?a.doc.execCommand(c,!1,b):a.selection.insertHTML(b)},state:function(){return!1}}; (function(a){a.commands.insertImage={exec:function(c,b,d){d="object"===typeof d?d:{src:d};var e=c.doc;if(b=this.state(c))c.selection.setBefore(b),d=b.parentNode,d.removeChild(b),a.dom.removeEmptyTextNodes(d),"A"!==d.nodeName||d.firstChild||(c.selection.setAfter(d),d.parentNode.removeChild(d)),a.quirks.redraw(c.element);else{b=e.createElement("IMG");for(var f in d)b.setAttribute("className"===f?"class":f,d[f]);c.selection.insertNode(b);a.browser.hasProblemsSettingCaretAfterImg()?(d=e.createTextNode(a.INVISIBLE_SPACE), c.selection.insertNode(d),c.selection.setAfter(d)):c.selection.setAfter(b)}},state:function(c){var b;if(!a.dom.hasElementWithTagName(c.doc,"IMG"))return!1;b=c.selection.getSelectedNode();if(!b)return!1;if("IMG"===b.nodeName)return b;if(b.nodeType!==a.ELEMENT_NODE)return!1;b=c.selection.getText();if(b=a.lang.string(b).trim())return!1;c=c.selection.getNodes(a.ELEMENT_NODE,function(a){return"IMG"===a.nodeName});return 1!==c.length?!1:c[0]}}})(wysihtml5); (function(a){var c="<br>"+(a.browser.needsSpaceAfterLineBreak()?" ":"");a.commands.insertLineBreak={exec:function(b,d){b.commands.support(d)?(b.doc.execCommand(d,!1,null),a.browser.autoScrollsToCaret()||b.selection.scrollIntoView()):b.commands.exec("insertHTML",c)},state:function(){return!1}}})(wysihtml5); wysihtml5.commands.insertOrderedList={exec:function(a,c){var b=a.doc,d=a.selection.getSelectedNode(),e=wysihtml5.dom.getParentElement(d,{nodeName:"OL"}),f=wysihtml5.dom.getParentElement(d,{nodeName:"UL"}),d="_wysihtml5-temp-"+(new Date).getTime(),g;e||f||!a.commands.support(c)?e?a.selection.executeAndRestore(function(){wysihtml5.dom.resolveList(e,a.config.useLineBreaks)}):f?a.selection.executeAndRestore(function(){wysihtml5.dom.renameElement(f,"ol")}):(a.commands.exec("formatBlock","div",d),g=b.querySelector("."+ d),b=""===g.innerHTML||g.innerHTML===wysihtml5.INVISIBLE_SPACE||"<br>"===g.innerHTML,a.selection.executeAndRestore(function(){e=wysihtml5.dom.convertToList(g,"ol")}),b&&a.selection.selectNode(e.querySelector("li"),!0)):b.execCommand(c,!1,null)},state:function(a){a=a.selection.getSelectedNode();return wysihtml5.dom.getParentElement(a,{nodeName:"OL"})}}; wysihtml5.commands.insertUnorderedList={exec:function(a,c){var b=a.doc,d=a.selection.getSelectedNode(),e=wysihtml5.dom.getParentElement(d,{nodeName:"UL"}),f=wysihtml5.dom.getParentElement(d,{nodeName:"OL"}),d="_wysihtml5-temp-"+(new Date).getTime(),g;e||f||!a.commands.support(c)?e?a.selection.executeAndRestore(function(){wysihtml5.dom.resolveList(e,a.config.useLineBreaks)}):f?a.selection.executeAndRestore(function(){wysihtml5.dom.renameElement(f,"ul")}):(a.commands.exec("formatBlock","div",d),g=b.querySelector("."+ d),b=""===g.innerHTML||g.innerHTML===wysihtml5.INVISIBLE_SPACE||"<br>"===g.innerHTML,a.selection.executeAndRestore(function(){e=wysihtml5.dom.convertToList(g,"ul")}),b&&a.selection.selectNode(e.querySelector("li"),!0)):b.execCommand(c,!1,null)},state:function(a){a=a.selection.getSelectedNode();return wysihtml5.dom.getParentElement(a,{nodeName:"UL"})}}; wysihtml5.commands.italic={exec:function(a,c){return wysihtml5.commands.formatInline.exec(a,c,"i")},state:function(a,c){return wysihtml5.commands.formatInline.state(a,c,"i")}};(function(a){var c=/wysiwyg-text-align-[0-9a-z]+/g;a.commands.justifyCenter={exec:function(b,d){return a.commands.formatBlock.exec(b,"formatBlock",null,"wysiwyg-text-align-center",c)},state:function(b,d){return a.commands.formatBlock.state(b,"formatBlock",null,"wysiwyg-text-align-center",c)}}})(wysihtml5); (function(a){var c=/wysiwyg-text-align-[0-9a-z]+/g;a.commands.justifyLeft={exec:function(b,d){return a.commands.formatBlock.exec(b,"formatBlock",null,"wysiwyg-text-align-left",c)},state:function(b,d){return a.commands.formatBlock.state(b,"formatBlock",null,"wysiwyg-text-align-left",c)}}})(wysihtml5); (function(a){var c=/wysiwyg-text-align-[0-9a-z]+/g;a.commands.justifyRight={exec:function(b,d){return a.commands.formatBlock.exec(b,"formatBlock",null,"wysiwyg-text-align-right",c)},state:function(b,d){return a.commands.formatBlock.state(b,"formatBlock",null,"wysiwyg-text-align-right",c)}}})(wysihtml5); (function(a){var c=/wysiwyg-text-align-[0-9a-z]+/g;a.commands.justifyFull={exec:function(b,d){return a.commands.formatBlock.exec(b,"formatBlock",null,"wysiwyg-text-align-justify",c)},state:function(b,d){return a.commands.formatBlock.state(b,"formatBlock",null,"wysiwyg-text-align-justify",c)}}})(wysihtml5);wysihtml5.commands.redo={exec:function(a){return a.undoManager.redo()},state:function(a){return!1}}; wysihtml5.commands.underline={exec:function(a,c){return wysihtml5.commands.formatInline.exec(a,c,"u")},state:function(a,c){return wysihtml5.commands.formatInline.state(a,c,"u")}};wysihtml5.commands.undo={exec:function(a){return a.undoManager.undo()},state:function(a){return!1}}; (function(a){var c='<span id="_wysihtml5-undo" class="_wysihtml5-temp">'+a.INVISIBLE_SPACE+"</span>",b='<span id="_wysihtml5-redo" class="_wysihtml5-temp">'+a.INVISIBLE_SPACE+"</span>",d=a.dom;a.UndoManager=a.lang.Dispatcher.extend({constructor:function(a){this.editor=a;this.composer=a.composer;this.element=this.composer.element;this.position=0;this.historyStr=[];this.historyDom=[];this.transact();this._observe()},_observe:function(){var e=this,f=this.composer.sandbox.getDocument(),g;d.observe(this.element, "keydown",function(a){if(!a.altKey&&(a.ctrlKey||a.metaKey)){var b=a.keyCode,c=90===b&&a.shiftKey||89===b;90!==b||a.shiftKey?c&&(e.redo(),a.preventDefault()):(e.undo(),a.preventDefault())}});d.observe(this.element,"keydown",function(a){a=a.keyCode;a!==g&&(g=a,8!==a&&46!==a||e.transact())});if(a.browser.hasUndoInContextMenu()){var k,h,l=function(){for(var a;a=f.querySelector("._wysihtml5-temp");)a.parentNode.removeChild(a);clearInterval(k)};d.observe(this.element,"contextmenu",function(){l();e.composer.selection.executeAndRestoreSimple(function(){e.element.lastChild&& e.composer.selection.setAfter(e.element.lastChild);f.execCommand("insertHTML",!1,c);f.execCommand("insertHTML",!1,b);f.execCommand("undo",!1,null)});k=setInterval(function(){f.getElementById("_wysihtml5-redo")?(l(),e.redo()):f.getElementById("_wysihtml5-undo")||(l(),e.undo())},400);h||(h=!0,d.observe(document,"mousedown",l),d.observe(f,["mousedown","paste","cut","copy"],l))})}this.editor.on("newword:composer",function(){e.transact()}).on("beforecommand:composer",function(){e.transact()})},transact:function(){var b= this.historyStr[this.position-1],c=this.composer.getValue();if(c!==b){25<(this.historyStr.length=this.historyDom.length=this.position)&&(this.historyStr.shift(),this.historyDom.shift(),this.position--);this.position++;var d=this.composer.selection.getRange(),b=d.startContainer||this.element,k=d.startOffset||0,h;b.nodeType===a.ELEMENT_NODE?d=b:(d=b.parentNode,h=this.getChildNodeIndex(d,b));d.setAttribute("data-wysihtml5-selection-offset",k);"undefined"!==typeof h&&d.setAttribute("data-wysihtml5-selection-node", h);h=this.element.cloneNode(!!c);this.historyDom.push(h);this.historyStr.push(c);d.removeAttribute("data-wysihtml5-selection-offset");d.removeAttribute("data-wysihtml5-selection-node")}},undo:function(){this.transact();this.undoPossible()&&(this.set(this.historyDom[--this.position-1]),this.editor.fire("undo:composer"))},redo:function(){this.redoPossible()&&(this.set(this.historyDom[++this.position-1]),this.editor.fire("redo:composer"))},undoPossible:function(){return 1<this.position},redoPossible:function(){return this.position< this.historyStr.length},set:function(a){this.element.innerHTML="";for(var b=0,c=a.childNodes,d=a.childNodes.length;b<d;b++)this.element.appendChild(c[b].cloneNode(!0));a.hasAttribute("data-wysihtml5-selection-offset")?(b=a.getAttribute("data-wysihtml5-selection-offset"),c=a.getAttribute("data-wysihtml5-selection-node"),a=this.element):(a=this.element.querySelector("[data-wysihtml5-selection-offset]")||this.element,b=a.getAttribute("data-wysihtml5-selection-offset"),c=a.getAttribute("data-wysihtml5-selection-node"), a.removeAttribute("data-wysihtml5-selection-offset"),a.removeAttribute("data-wysihtml5-selection-node"));null!==c&&(a=this.getChildNodeByIndex(a,+c));this.composer.selection.set(a,b)},getChildNodeIndex:function(a,b){for(var c=0,d=a.childNodes,h=d.length;c<h;c++)if(d[c]===b)return c},getChildNodeByIndex:function(a,b){return a.childNodes[b]}})})(wysihtml5); wysihtml5.views.View=Base.extend({constructor:function(a,c,b){this.parent=a;this.element=c;this.config=b;this._observeViewChange()},_observeViewChange:function(){var a=this;this.parent.on("beforeload",function(){a.parent.on("change_view",function(c){c===a.name?(a.parent.currentView=a,a.show(),setTimeout(function(){a.focus()},0)):a.hide()})})},focus:function(){if(this.element.ownerDocument.querySelector(":focus")!==this.element)try{this.element.focus()}catch(a){}},hide:function(){this.element.style.display= "none"},show:function(){this.element.style.display=""},disable:function(){this.element.setAttribute("disabled","disabled")},enable:function(){this.element.removeAttribute("disabled")}}); (function(a){var c=a.dom,b=a.browser;a.views.Composer=a.views.View.extend({name:"composer",CARET_HACK:"<br>",constructor:function(a,b,c){this.base(a,b,c);this.textarea=this.parent.textarea;this._initSandbox()},clear:function(){this.element.innerHTML=b.displaysCaretInEmptyContentEditableCorrectly()?"":this.CARET_HACK},getValue:function(b){var c=this.isEmpty()?"":a.quirks.getCorrectInnerHTML(this.element);b&&(c=this.parent.parse(c));return c},setValue:function(a,b){b&&(a=this.parent.parse(a));try{this.element.innerHTML= a}catch(c){this.element.innerText=a}},show:function(){this.iframe.style.display=this._displayStyle||"";this.textarea.element.disabled||(this.disable(),this.enable())},hide:function(){this._displayStyle=c.getStyle("display").from(this.iframe);"none"===this._displayStyle&&(this._displayStyle=null);this.iframe.style.display="none"},disable:function(){this.parent.fire("disable:composer");this.element.removeAttribute("contentEditable")},enable:function(){this.parent.fire("enable:composer");this.element.setAttribute("contentEditable", "true")},focus:function(b){a.browser.doesAsyncFocus()&&this.hasPlaceholderSet()&&this.clear();this.base();var c=this.element.lastChild;b&&c&&("BR"===c.nodeName?this.selection.setBefore(this.element.lastChild):this.selection.setAfter(this.element.lastChild))},getTextContent:function(){return c.getTextContent(this.element)},hasPlaceholderSet:function(){return this.getTextContent()==this.textarea.element.getAttribute("placeholder")&&this.placeholderSet},isEmpty:function(){var a=this.element.innerHTML.toLowerCase(); return""===a||"<br>"===a||"<p></p>"===a||"<p><br></p>"===a||this.hasPlaceholderSet()},_initSandbox:function(){var a=this;this.sandbox=new c.Sandbox(function(){a._create()},{stylesheets:this.config.stylesheets});this.iframe=this.sandbox.getIframe();var b=this.textarea.element;c.insert(this.iframe).after(b);if(b.form){var f=document.createElement("input");f.type="hidden";f.name="_wysihtml5_mode";f.value=1;c.insert(f).after(b)}},_create:function(){var d=this;this.doc=this.sandbox.getDocument();this.element= this.doc.body;this.textarea=this.parent.textarea;this.element.innerHTML=this.textarea.getValue(!0);this.selection=new a.Selection(this.parent);this.commands=new a.Commands(this.parent);c.copyAttributes("className spellcheck title lang dir accessKey".split(" ")).from(this.textarea.element).to(this.element);c.addClass(this.element,this.config.composerClassName);this.config.style&&this.style();this.observe();var e=this.config.name;e&&(c.addClass(this.element,e),c.addClass(this.iframe,e));this.enable(); this.textarea.element.disabled&&this.disable();(e="string"===typeof this.config.placeholder?this.config.placeholder:this.textarea.element.getAttribute("placeholder"))&&c.simulatePlaceholder(this.parent,this,e);this.commands.exec("styleWithCSS",!1);this._initAutoLinking();this._initObjectResizing();this._initUndoManager();this._initLineBreaking();!this.textarea.element.hasAttribute("autofocus")&&document.querySelector(":focus")!=this.textarea.element||b.isIos()||setTimeout(function(){d.focus(!0)}, 100);b.clearsContentEditableCorrectly()||a.quirks.ensureProperClearing(this);this.initSync&&this.config.sync&&this.initSync();this.textarea.hide();this.parent.fire("beforeload").fire("load")},_initAutoLinking:function(){var d=this,e=b.canDisableAutoLinking(),f=b.doesAutoLinkingInContentEditable();e&&this.commands.exec("autoUrlDetect",!1);if(this.config.autoLink){if(!f||f&&e)this.parent.on("newword:composer",function(){c.getTextContent(d.element).match(c.autoLink.URL_REG_EXP)&&d.selection.executeAndRestore(function(a, b){c.autoLink(b.parentNode)})}),c.observe(this.element,"blur",function(){c.autoLink(d.element)});var g=this.sandbox.getDocument().getElementsByTagName("a"),k=c.autoLink.URL_REG_EXP,h=function(b){b=a.lang.string(c.getTextContent(b)).trim();"www."===b.substr(0,4)&&(b="http://"+b);return b};c.observe(this.element,"keydown",function(a){if(g.length){a=d.selection.getSelectedNode(a.target.ownerDocument);var b=c.getParentElement(a,{nodeName:"A"},4),e;b&&(e=h(b),setTimeout(function(){var a=h(b);a!==e&&a.match(k)&& b.setAttribute("href",a)},0))}})}},_initObjectResizing:function(){this.commands.exec("enableObjectResizing",!0);if(b.supportsEvent("resizeend")){var d=["width","height"],e=d.length,f=this.element;c.observe(f,"resizeend",function(b){b=b.target||b.srcElement;var c=b.style,h=0,l;if("IMG"===b.nodeName){for(;h<e;h++)l=d[h],c[l]&&(b.setAttribute(l,parseInt(c[l],10)),c[l]="");a.quirks.redraw(f)}})}},_initUndoManager:function(){this.undoManager=new a.UndoManager(this.parent)},_initLineBreaking:function(){function d(a){var b= c.getParentElement(a,{nodeName:["P","DIV"]},2);b&&e.selection.executeAndRestore(function(){e.config.useLineBreaks?c.replaceWithChildNodes(b):"P"!==b.nodeName&&c.renameElement(b,"p")})}var e=this,f="LI P H1 H2 H3 H4 H5 H6".split(" "),g=["UL","OL","MENU"];this.config.useLineBreaks||c.observe(this.element,["focus","keydown"],function(){if(e.isEmpty()){var a=e.doc.createElement("P");e.element.innerHTML="";e.element.appendChild(a);b.displaysCaretInEmptyContentEditableCorrectly()?e.selection.selectNode(a, !0):(a.innerHTML="<br>",e.selection.setBefore(a.firstChild))}});b.createsNestedInvalidMarkupAfterPaste()&&c.observe(this.element,"paste",function(b){b=e.doc.createTextNode(a.INVISIBLE_SPACE);e.selection.insertNode(b)});c.observe(this.doc,"keydown",function(b){var h=b.keyCode;if(!b.shiftKey&&(h===a.ENTER_KEY||h===a.BACKSPACE_KEY)){var l=c.getParentElement(e.selection.getSelectedNode(),{nodeName:f},4);l?setTimeout(function(){var b=e.selection.getSelectedNode(),f;if("LI"===l.nodeName){if(!b)return;(f= c.getParentElement(b,{nodeName:g},2))||d(b)}h===a.ENTER_KEY&&l.nodeName.match(/^H[1-6]$/)&&d(b)},0):e.config.useLineBreaks&&(h===a.ENTER_KEY&&!a.browser.insertsLineBreaksOnReturn())&&(e.commands.exec("insertLineBreak"),b.preventDefault())}})}})})(wysihtml5); (function(a){var c=a.dom,b=document,d=window,e=b.createElement("div"),f="background-color color cursor font-family font-size font-style font-variant font-weight line-height letter-spacing text-align text-decoration text-indent text-rendering word-break word-wrap word-spacing".split(" "),g="background-color border-collapse border-bottom-color border-bottom-style border-bottom-width border-left-color border-left-style border-left-width border-right-color border-right-style border-right-width border-top-color border-top-style border-top-width clear display float margin-bottom margin-left margin-right margin-top outline-color outline-offset outline-width outline-style padding-left padding-right padding-top padding-bottom position top left right bottom z-index vertical-align text-align -webkit-box-sizing -moz-box-sizing -ms-box-sizing box-sizing -webkit-box-shadow -moz-box-shadow -ms-box-shadow box-shadow -webkit-border-top-right-radius -moz-border-radius-topright border-top-right-radius -webkit-border-bottom-right-radius -moz-border-radius-bottomright border-bottom-right-radius -webkit-border-bottom-left-radius -moz-border-radius-bottomleft border-bottom-left-radius -webkit-border-top-left-radius -moz-border-radius-topleft border-top-left-radius width height".split(" "), k=["html { height: 100%; }","body { height: 100%; padding: 1px 0 0 0; margin: -1px 0 0 0; }","body > p:first-child { margin-top: 0; }","._wysihtml5-temp { display: none; }",a.browser.isGecko?"body.placeholder { color: graytext !important; }":"body.placeholder { color: #a9a9a9 !important; }","img:-moz-broken { -moz-force-broken-image-icon: 1; height: 24px; width: 24px; }"],h=function(a){if(a.setActive)try{a.setActive()}catch(e){}else{var f=a.style,h=b.documentElement.scrollTop|| b.body.scrollTop,g=b.documentElement.scrollLeft||b.body.scrollLeft,f={position:f.position,top:f.top,left:f.left,WebkitUserSelect:f.WebkitUserSelect};c.setStyles({position:"absolute",top:"-99999px",left:"-99999px",WebkitUserSelect:"none"}).on(a);a.focus();c.setStyles(f).on(a);d.scrollTo&&d.scrollTo(g,h)}};a.views.Composer.prototype.style=function(){var d=this,p=b.querySelector(":focus"),n=this.textarea.element,u=n.hasAttribute("placeholder"),D=u&&n.getAttribute("placeholder"),q=n.style.display,r=n.disabled, s;this.focusStylesHost=e.cloneNode(!1);this.blurStylesHost=e.cloneNode(!1);this.disabledStylesHost=e.cloneNode(!1);u&&n.removeAttribute("placeholder");n===p&&n.blur();n.disabled=!1;n.style.display=s="none";if(n.getAttribute("rows")&&"auto"===c.getStyle("height").from(n)||n.getAttribute("cols")&&"auto"===c.getStyle("width").from(n))n.style.display=s=q;c.copyStyles(g).from(n).to(this.iframe).andTo(this.blurStylesHost);c.copyStyles(f).from(n).to(this.element).andTo(this.blurStylesHost);c.insertCSS(k).into(this.element.ownerDocument); n.disabled=!0;c.copyStyles(g).from(n).to(this.disabledStylesHost);c.copyStyles(f).from(n).to(this.disabledStylesHost);n.disabled=r;n.style.display=q;h(n);n.style.display=s;c.copyStyles(g).from(n).to(this.focusStylesHost);c.copyStyles(f).from(n).to(this.focusStylesHost);n.style.display=q;c.copyStyles(["display"]).from(n).to(this.iframe);var v=a.lang.array(g).without(["display"]);p?p.focus():n.blur();u&&n.setAttribute("placeholder",D);this.parent.on("focus:composer",function(){c.copyStyles(v).from(d.focusStylesHost).to(d.iframe); c.copyStyles(f).from(d.focusStylesHost).to(d.element)});this.parent.on("blur:composer",function(){c.copyStyles(v).from(d.blurStylesHost).to(d.iframe);c.copyStyles(f).from(d.blurStylesHost).to(d.element)});this.parent.observe("disable:composer",function(){c.copyStyles(v).from(d.disabledStylesHost).to(d.iframe);c.copyStyles(f).from(d.disabledStylesHost).to(d.element)});this.parent.observe("enable:composer",function(){c.copyStyles(v).from(d.blurStylesHost).to(d.iframe);c.copyStyles(f).from(d.blurStylesHost).to(d.element)}); return this}})(wysihtml5); (function(a){var c=a.dom,b=a.browser,d={66:"bold",73:"italic",85:"underline"};a.views.Composer.prototype.observe=function(){var e=this,f=this.getValue(),g=this.sandbox.getIframe(),k=this.element,h=b.supportsEventsInIframeCorrectly()?k:this.sandbox.getWindow();c.observe(g,"DOMNodeRemoved",function(){clearInterval(l);e.parent.fire("destroy:composer")});var l=setInterval(function(){c.contains(document.documentElement,g)||(clearInterval(l),e.parent.fire("destroy:composer"))},250);c.observe(h,"focus", function(){e.parent.fire("focus").fire("focus:composer");setTimeout(function(){f=e.getValue()},0)});c.observe(h,"blur",function(){f!==e.getValue()&&e.parent.fire("change").fire("change:composer");e.parent.fire("blur").fire("blur:composer")});c.observe(k,"dragenter",function(){e.parent.fire("unset_placeholder")});c.observe(k,["drop","paste"],function(){setTimeout(function(){e.parent.fire("paste").fire("paste:composer")},0)});c.observe(k,"keyup",function(b){b=b.keyCode;b!==a.SPACE_KEY&&b!==a.ENTER_KEY|| e.parent.fire("newword:composer")});this.parent.on("paste:composer",function(){setTimeout(function(){e.parent.fire("newword:composer")},0)});b.canSelectImagesInContentEditable()||c.observe(k,"mousedown",function(a){var b=a.target;"IMG"===b.nodeName&&(e.selection.selectNode(b),a.preventDefault())});b.hasHistoryIssue()&&b.supportsSelectionModify()&&c.observe(k,"keydown",function(a){if(a.metaKey||a.ctrlKey){var b=a.keyCode,c=k.ownerDocument.defaultView.getSelection();if(37===b||39===b)37===b&&(c.modify("extend", "left","lineboundary"),a.shiftKey||c.collapseToStart()),39===b&&(c.modify("extend","right","lineboundary"),a.shiftKey||c.collapseToEnd()),a.preventDefault()}});c.observe(k,"keydown",function(a){var b=d[a.keyCode];(a.ctrlKey||a.metaKey)&&(!a.altKey&&b)&&(e.commands.exec(b),a.preventDefault())});c.observe(k,"keydown",function(b){var c=e.selection.getSelectedNode(!0),d=b.keyCode;!c||("IMG"!==c.nodeName||d!==a.BACKSPACE_KEY&&d!==a.DELETE_KEY)||(d=c.parentNode,d.removeChild(c),"A"!==d.nodeName||d.firstChild|| d.parentNode.removeChild(d),setTimeout(function(){a.quirks.redraw(k)},0),b.preventDefault())});b.hasIframeFocusIssue()&&(c.observe(this.iframe,"focus",function(){setTimeout(function(){e.doc.querySelector(":focus")!==e.element&&e.focus()},0)}),c.observe(this.element,"blur",function(){setTimeout(function(){e.selection.getSelection().removeAllRanges()},0)}));var p={IMG:"Image: ",A:"Link: "};c.observe(k,"mouseover",function(a){a=a.target;var b=a.nodeName;"A"!==b&&"IMG"!==b||a.hasAttribute("title")||(b= p[b]+(a.getAttribute("href")||a.getAttribute("src")),a.setAttribute("title",b))})}})(wysihtml5); (function(a){a.views.Synchronizer=Base.extend({constructor:function(a,b,d){this.editor=a;this.textarea=b;this.composer=d;this._observe()},fromComposerToTextarea:function(c){this.textarea.setValue(a.lang.string(this.composer.getValue()).trim(),c)},fromTextareaToComposer:function(a){var b=this.textarea.getValue();b?this.composer.setValue(b,a):(this.composer.clear(),this.editor.fire("set_placeholder"))},sync:function(a){"textarea"===this.editor.currentView.name?this.fromTextareaToComposer(a):this.fromComposerToTextarea(a)}, _observe:function(){var c,b=this,d=this.textarea.element.form,e=function(){c=setInterval(function(){b.fromComposerToTextarea()},400)},f=function(){clearInterval(c);c=null};e();d&&(a.dom.observe(d,"submit",function(){b.sync(!0)}),a.dom.observe(d,"reset",function(){setTimeout(function(){b.fromTextareaToComposer()},0)}));this.editor.on("change_view",function(a){"composer"!==a||c?"textarea"===a&&(b.fromComposerToTextarea(!0),f()):(b.fromTextareaToComposer(!0),e())});this.editor.on("destroy:composer", f)}})})(wysihtml5); wysihtml5.views.Textarea=wysihtml5.views.View.extend({name:"textarea",constructor:function(a,c,b){this.base(a,c,b);this._observe()},clear:function(){this.element.value=""},getValue:function(a){var c=this.isEmpty()?"":this.element.value;a&&(c=this.parent.parse(c));return c},setValue:function(a,c){c&&(a=this.parent.parse(a));this.element.value=a},hasPlaceholderSet:function(){var a=wysihtml5.browser.supportsPlaceholderAttributeOn(this.element),c=this.element.getAttribute("placeholder")||null,b=this.element.value; return a&&!b||b===c},isEmpty:function(){return!wysihtml5.lang.string(this.element.value).trim()||this.hasPlaceholderSet()},_observe:function(){var a=this.element,c=this.parent,b={focusin:"focus",focusout:"blur"},d=wysihtml5.browser.supportsEvent("focusin")?["focusin","focusout","change"]:["focus","blur","change"];c.on("beforeload",function(){wysihtml5.dom.observe(a,d,function(a){a=b[a.type]||a.type;c.fire(a).fire(a+":textarea")});wysihtml5.dom.observe(a,["paste","drop"],function(){setTimeout(function(){c.fire("paste").fire("paste:textarea")}, 0)})})}}); (function(a){var c=a.dom;a.toolbar.Dialog=a.lang.Dispatcher.extend({constructor:function(a,c){this.link=a;this.container=c},_observe:function(){if(!this._observed){var b=this,d=function(a){var c=b._serialize();c==b.elementToChange?b.fire("edit",c):b.fire("save",c);b.hide();a.preventDefault();a.stopPropagation()};c.observe(b.link,"click",function(){c.hasClass(b.link,"wysihtml5-command-dialog-opened")&&setTimeout(function(){b.hide()},0)});c.observe(this.container,"keydown",function(c){var e=c.keyCode; e===a.ENTER_KEY&&d(c);e===a.ESCAPE_KEY&&(b.fire("cancel"),b.hide())});c.delegate(this.container,"[data-wysihtml5-dialog-action=save]","click",d);c.delegate(this.container,"[data-wysihtml5-dialog-action=cancel]","click",function(a){b.fire("cancel");b.hide();a.preventDefault();a.stopPropagation()});for(var e=this.container.querySelectorAll("input, select, textarea"),f=0,g=e.length,k=function(){clearInterval(b.interval)};f<g;f++)c.observe(e[f],"change",k);this._observed=!0}},_serialize:function(){for(var a= this.elementToChange||{},c=this.container.querySelectorAll("[data-wysihtml5-dialog-field]"),e=c.length,f=0;f<e;f++)a[c[f].getAttribute("data-wysihtml5-dialog-field")]=c[f].value;return a},_interpolate:function(a){for(var c,e,f=document.querySelector(":focus"),g=this.container.querySelectorAll("[data-wysihtml5-dialog-field]"),k=g.length,h=0;h<k;h++)c=g[h],c===f||a&&"hidden"===c.type||(e=c.getAttribute("data-wysihtml5-dialog-field"),e=this.elementToChange?this.elementToChange[e]||"":c.defaultValue, c.value=e)},show:function(a){if(!c.hasClass(this.link,"wysihtml5-command-dialog-opened")){var d=this,e=this.container.querySelector("input, select, textarea");this.elementToChange=a;this._observe();this._interpolate();a&&(this.interval=setInterval(function(){d._interpolate(!0)},500));c.addClass(this.link,"wysihtml5-command-dialog-opened");this.container.style.display="";this.fire("show");if(e&&!a)try{e.focus()}catch(f){}}},hide:function(){clearInterval(this.interval);this.elementToChange=null;c.removeClass(this.link, "wysihtml5-command-dialog-opened");this.container.style.display="none";this.fire("hide")}})})(wysihtml5); (function(a){var c=a.dom,b={position:"relative"},d={left:0,margin:0,opacity:0,overflow:"hidden",padding:0,position:"absolute",top:0,zIndex:1},e={cursor:"inherit",fontSize:"50px",height:"50px",marginTop:"-25px",outline:0,padding:0,position:"absolute",right:"-4px",top:"50%"},f={"x-webkit-speech":"",speech:""};a.toolbar.Speech=function(g,k){var h=document.createElement("input");if(a.browser.supportsSpeechApiOn(h)){var l=g.editor.textarea.element.getAttribute("lang");l&&(f.lang=l);l=document.createElement("div"); a.lang.object(d).merge({width:k.offsetWidth+"px",height:k.offsetHeight+"px"});c.insert(h).into(l);c.insert(l).into(k);c.setStyles(e).on(h);c.setAttributes(f).on(h);c.setStyles(d).on(l);c.setStyles(b).on(k);c.observe(h,"onwebkitspeechchange"in h?"webkitspeechchange":"speechchange",function(){g.execCommand("insertText",h.value);h.value=""});c.observe(h,"click",function(a){c.hasClass(k,"wysihtml5-command-disabled")&&a.preventDefault();a.stopPropagation()})}else k.style.display="none"}})(wysihtml5); (function(a){var c=a.dom;a.toolbar.Toolbar=Base.extend({constructor:function(b,c){this.editor=b;this.container="string"===typeof c?document.getElementById(c):c;this.composer=b.composer;this._getLinks("command");this._getLinks("action");this._observe();this.show();for(var e=this.container.querySelectorAll("[data-wysihtml5-command=insertSpeech]"),f=e.length,g=0;g<f;g++)new a.toolbar.Speech(this,e[g])},_getLinks:function(b){for(var c=this[b+"Links"]=a.lang.array(this.container.querySelectorAll("[data-wysihtml5-"+ b+"]")).get(),e=c.length,f=0,g=this[b+"Mapping"]={},k,h,l,p,n;f<e;f++)k=c[f],l=k.getAttribute("data-wysihtml5-"+b),p=k.getAttribute("data-wysihtml5-"+b+"-value"),h=this.container.querySelector("[data-wysihtml5-"+b+"-group='"+l+"']"),n=this._getDialog(k,l),g[l+":"+p]={link:k,group:h,name:l,value:p,dialog:n,state:!1}},_getDialog:function(b,c){var e=this,f=this.container.querySelector("[data-wysihtml5-dialog='"+c+"']"),g,k;f&&(g=new a.toolbar.Dialog(b,f),g.on("show",function(){k=e.composer.selection.getBookmark(); e.editor.fire("show:dialog",{command:c,dialogContainer:f,commandLink:b})}),g.on("save",function(a){k&&e.composer.selection.setBookmark(k);e._execCommand(c,a);e.editor.fire("save:dialog",{command:c,dialogContainer:f,commandLink:b})}),g.on("cancel",function(){e.editor.focus(!1);e.editor.fire("cancel:dialog",{command:c,dialogContainer:f,commandLink:b})}));return g},execCommand:function(a,c){if(!this.commandsDisabled){var e=this.commandMapping[a+":"+c];e&&e.dialog&&!e.state?e.dialog.show():this._execCommand(a, c)}},_execCommand:function(a,c){this.editor.focus(!1);this.composer.commands.exec(a,c);this._updateLinkStates()},execAction:function(a){var c=this.editor;"change_view"===a&&(c.currentView===c.textarea?c.fire("change_view","composer"):c.fire("change_view","textarea"))},_observe:function(){for(var a=this,d=this.editor,e=this.container,f=this.commandLinks.concat(this.actionLinks),g=f.length,k=0;k<g;k++)if("A"===f[k].nodeName)c.setAttributes({href:"javascript:;",unselectable:"on"}).on(f[k]);else c.setAttributes({unselectable:"on"}).on(f[k]); c.delegate(e,"[data-wysihtml5-command], [data-wysihtml5-action]","mousedown",function(a){a.preventDefault()});c.delegate(e,"[data-wysihtml5-command]","click",function(c){var d=this.getAttribute("data-wysihtml5-command"),e=this.getAttribute("data-wysihtml5-command-value");a.execCommand(d,e);c.preventDefault()});c.delegate(e,"[data-wysihtml5-action]","click",function(c){var d=this.getAttribute("data-wysihtml5-action");a.execAction(d);c.preventDefault()});d.on("focus:composer",function(){a.bookmark= null;clearInterval(a.interval);a.interval=setInterval(function(){a._updateLinkStates()},500)});d.on("blur:composer",function(){clearInterval(a.interval)});d.on("destroy:composer",function(){clearInterval(a.interval)});d.on("change_view",function(d){setTimeout(function(){a.commandsDisabled="composer"!==d;a._updateLinkStates();a.commandsDisabled?c.addClass(e,"wysihtml5-commands-disabled"):c.removeClass(e,"wysihtml5-commands-disabled")},0)})},_updateLinkStates:function(){var b=this.commandMapping,d= this.actionMapping,e,f,g;for(e in b)g=b[e],this.commandsDisabled?(f=!1,c.removeClass(g.link,"wysihtml5-command-active"),g.group&&c.removeClass(g.group,"wysihtml5-command-active"),g.dialog&&g.dialog.hide()):(f=this.composer.commands.state(g.name,g.value),a.lang.object(f).isArray()&&(f=1===f.length?f[0]:!0),c.removeClass(g.link,"wysihtml5-command-disabled"),g.group&&c.removeClass(g.group,"wysihtml5-command-disabled")),g.state!==f&&((g.state=f)?(c.addClass(g.link,"wysihtml5-command-active"),g.group&& c.addClass(g.group,"wysihtml5-command-active"),g.dialog&&("object"===typeof f?g.dialog.show(f):g.dialog.hide())):(c.removeClass(g.link,"wysihtml5-command-active"),g.group&&c.removeClass(g.group,"wysihtml5-command-active"),g.dialog&&g.dialog.hide()));for(e in d)b=d[e],"change_view"===b.name&&(b.state=this.editor.currentView===this.editor.textarea,b.state?c.addClass(b.link,"wysihtml5-action-active"):c.removeClass(b.link,"wysihtml5-action-active"))},show:function(){this.container.style.display=""},hide:function(){this.container.style.display= "none"}})})(wysihtml5); (function(a){var c={name:void 0,style:!0,toolbar:void 0,autoLink:!0,parserRules:{tags:{br:{},span:{},div:{},p:{}},classes:{}},parser:a.dom.parse,composerClassName:"wysihtml5-editor",bodyClassName:"wysihtml5-supported",useLineBreaks:!0,stylesheets:[],placeholderText:void 0,supportTouchDevices:!0,cleanUp:!0};a.Editor=a.lang.Dispatcher.extend({constructor:function(b,d){this.textareaElement="string"===typeof b?document.getElementById(b):b;this.config=a.lang.object({}).merge(c).merge(d).get();this.currentView= this.textarea=new a.views.Textarea(this,this.textareaElement,this.config);this._isCompatible=a.browser.supported();if(!this._isCompatible||!this.config.supportTouchDevices&&a.browser.isTouchDevice()){var e=this;setTimeout(function(){e.fire("beforeload").fire("load")},0)}else{a.dom.addClass(document.body,this.config.bodyClassName);this.currentView=this.composer=new a.views.Composer(this,this.textareaElement,this.config);"function"===typeof this.config.parser&&this._initParser();this.on("beforeload", function(){this.synchronizer=new a.views.Synchronizer(this,this.textarea,this.composer);this.config.toolbar&&(this.toolbar=new a.toolbar.Toolbar(this,this.config.toolbar))});try{console.log("Heya! This page is using wysihtml5 for rich text editing. Check out https://github.com/xing/wysihtml5")}catch(f){}}},isCompatible:function(){return this._isCompatible},clear:function(){this.currentView.clear();return this},getValue:function(a){return this.currentView.getValue(a)},setValue:function(a,c){this.fire("unset_placeholder"); if(!a)return this.clear();this.currentView.setValue(a,c);return this},focus:function(a){this.currentView.focus(a);return this},disable:function(){this.currentView.disable();return this},enable:function(){this.currentView.enable();return this},isEmpty:function(){return this.currentView.isEmpty()},hasPlaceholderSet:function(){return this.currentView.hasPlaceholderSet()},parse:function(b){var c=this.config.parser(b,this.config.parserRules,this.composer.sandbox.getDocument(),this.config.cleanUp);"object"=== typeof b&&a.quirks.redraw(b);return c},_initParser:function(){this.on("paste:composer",function(){var b=this;b.composer.selection.executeAndRestore(function(){a.quirks.cleanPastedHTML(b.composer.element);b.parse(b.composer.element)},!0)})}})})(wysihtml5); /** * Full HTML5 compatibility rule set * These rules define which tags and css classes are supported and which tags should be specially treated. * * Examples based on this rule set: * * <a href="http://foobar.com">foo</a> * ... becomes ... * <a href="http://foobar.com" target="_blank" rel="nofollow">foo</a> * * <img align="left" src="http://foobar.com/image.png"> * ... becomes ... * <img class="wysiwyg-float-left" src="http://foobar.com/image.png" alt=""> * * <div>foo<script>alert(document.cookie)</script></div> * ... becomes ... * <div>foo</div> * * <marquee>foo</marquee> * ... becomes ... * <span>foo</marquee> * * foo <br clear="both"> bar * ... becomes ... * foo <br class="wysiwyg-clear-both"> bar * * <div>hello <iframe src="http://google.com"></iframe></div> * ... becomes ... * <div>hello </div> * * <center>hello</center> * ... becomes ... * <div class="wysiwyg-text-align-center">hello</div> */ var wysihtml5ParserRules = { /** * CSS Class white-list * Following css classes won't be removed when parsed by the wysihtml5 html parser */ "classes": { "wysiwyg-clear-both": 1, "wysiwyg-clear-left": 1, "wysiwyg-clear-right": 1, "wysiwyg-color-aqua": 1, "wysiwyg-color-black": 1, "wysiwyg-color-blue": 1, "wysiwyg-color-fuchsia": 1, "wysiwyg-color-gray": 1, "wysiwyg-color-green": 1, "wysiwyg-color-lime": 1, "wysiwyg-color-maroon": 1, "wysiwyg-color-navy": 1, "wysiwyg-color-olive": 1, "wysiwyg-color-purple": 1, "wysiwyg-color-red": 1, "wysiwyg-color-silver": 1, "wysiwyg-color-teal": 1, "wysiwyg-color-white": 1, "wysiwyg-color-yellow": 1, "wysiwyg-float-left": 1, "wysiwyg-float-right": 1, "wysiwyg-font-size-large": 1, "wysiwyg-font-size-larger": 1, "wysiwyg-font-size-medium": 1, "wysiwyg-font-size-small": 1, "wysiwyg-font-size-smaller": 1, "wysiwyg-font-size-x-large": 1, "wysiwyg-font-size-x-small": 1, "wysiwyg-font-size-xx-large": 1, "wysiwyg-font-size-xx-small": 1, "wysiwyg-text-align-center": 1, "wysiwyg-text-align-justify": 1, "wysiwyg-text-align-left": 1, "wysiwyg-text-align-right": 1 }, /** * Tag list * * Following options are available: * * - add_class: converts and deletes the given HTML4 attribute (align, clear, ...) via the given method to a css class * The following methods are implemented in wysihtml5.dom.parse: * - align_text: converts align attribute values (right/left/center/justify) to their corresponding css class "wysiwyg-text-align-*") <p align="center">foo</p> ... becomes ... <p> class="wysiwyg-text-align-center">foo</p> * - clear_br: converts clear attribute values left/right/all/both to their corresponding css class "wysiwyg-clear-*" * <br clear="all"> ... becomes ... <br class="wysiwyg-clear-both"> * - align_img: converts align attribute values (right/left) on <img> to their corresponding css class "wysiwyg-float-*" * * - remove: removes the element and it's content * * - rename_tag: renames the element to the given tag * * - set_class: adds the given class to the element (note: make sure that the class is in the "classes" white list above) * * - set_attributes: sets/overrides the given attributes * * - check_attributes: checks the given HTML attribute via the given method * - url: checks whether the given string is an url, deletes the attribute if not * - alt: strips unwanted characters. if the attribute is not set, then it gets set (to ensure valid and compatible HTML) * - numbers: ensures that the attribute only contains numeric characters */ "tags": { "tr": { "add_class": { "align": "align_text" } }, "strike": { "remove": 1 }, "form": { "rename_tag": "div" }, "rt": { "rename_tag": "span" }, "code": {}, "acronym": { "rename_tag": "span" }, "br": { "add_class": { "clear": "clear_br" } }, "details": { "rename_tag": "div" }, "h4": { "add_class": { "align": "align_text" } }, "em": {}, "title": { "remove": 1 }, "multicol": { "rename_tag": "div" }, "figure": { "rename_tag": "div" }, "xmp": { "rename_tag": "span" }, "small": { "rename_tag": "span", "set_class": "wysiwyg-font-size-smaller" }, "area": { "remove": 1 }, "time": { "rename_tag": "span" }, "dir": { "rename_tag": "ul" }, "bdi": { "rename_tag": "span" }, "command": { "remove": 1 }, "ul": {}, "progress": { "rename_tag": "span" }, "dfn": { "rename_tag": "span" }, "iframe": { "remove": 1 }, "figcaption": { "rename_tag": "div" }, "a": { "check_attributes": { "href": "url" }, "set_attributes": { "rel": "nofollow", "target": "_self" } }, "img": { "check_attributes": { "width": "numbers", "alt": "alt", "src": "url", "height": "numbers" }, "add_class": { "align": "align_img" } }, "rb": { "rename_tag": "span" }, "footer": { "rename_tag": "div" }, "noframes": { "remove": 1 }, "abbr": { "rename_tag": "span" }, "u": {}, "bgsound": { "remove": 1 }, "sup": { "rename_tag": "span" }, "address": { "rename_tag": "div" }, "basefont": { "remove": 1 }, "nav": { "rename_tag": "div" }, "h1": { "add_class": { "align": "align_text" } }, "head": { "remove": 1 }, "tbody": { "add_class": { "align": "align_text" } }, "dd": { "rename_tag": "div" }, "s": { "rename_tag": "span" }, "li": {}, "td": { "check_attributes": { "rowspan": "numbers", "colspan": "numbers" }, "add_class": { "align": "align_text" } }, "object": { "remove": 1 }, "div": { "add_class": { "align": "align_text" } }, "option": { "rename_tag": "span" }, "select": { "rename_tag": "span" }, "i": {}, "track": { "remove": 1 }, "wbr": { "remove": 1 }, "fieldset": { "rename_tag": "div" }, "big": { "rename_tag": "span", "set_class": "wysiwyg-font-size-larger" }, "button": { "rename_tag": "span" }, "noscript": { "remove": 1 }, "svg": { "remove": 1 }, "input": { "remove": 1 }, "table": {}, "keygen": { "remove": 1 }, "h5": { "add_class": { "align": "align_text" } }, "meta": { "remove": 1 }, "map": { "rename_tag": "div" }, "isindex": { "remove": 1 }, "mark": { "rename_tag": "span" }, "caption": { "add_class": { "align": "align_text" } }, "tfoot": { "add_class": { "align": "align_text" } }, "base": { "remove": 1 }, "video": { "remove": 1 }, "strong": {}, "canvas": { "remove": 1 }, "output": { "rename_tag": "span" }, "marquee": { "rename_tag": "span" }, "b": {}, "q": { "check_attributes": { "cite": "url" } }, "applet": { "remove": 1 }, "span": {}, "rp": { "rename_tag": "span" }, "spacer": { "remove": 1 }, "source": { "remove": 1 }, "aside": { "rename_tag": "div" }, "frame": { "remove": 1 }, "section": { "rename_tag": "div" }, "body": { "rename_tag": "div" }, "ol": {}, "nobr": { "rename_tag": "span" }, "html": { "rename_tag": "div" }, "summary": { "rename_tag": "span" }, "var": { "rename_tag": "span" }, "del": { "remove": 1 }, "blockquote": { "check_attributes": { "cite": "url" } }, "style": { "remove": 1 }, "device": { "remove": 1 }, "meter": { "rename_tag": "span" }, "h3": { "add_class": { "align": "align_text" } }, "textarea": { "rename_tag": "span" }, "embed": { "remove": 1 }, "hgroup": { "rename_tag": "div" }, "font": { "rename_tag": "span", "add_class": { "size": "size_font" } }, "tt": { "rename_tag": "span" }, "noembed": { "remove": 1 }, "thead": { "add_class": { "align": "align_text" } }, "blink": { "rename_tag": "span" }, "plaintext": { "rename_tag": "span" }, "xml": { "remove": 1 }, "h6": { "add_class": { "align": "align_text" } }, "param": { "remove": 1 }, "th": { "check_attributes": { "rowspan": "numbers", "colspan": "numbers" }, "add_class": { "align": "align_text" } }, "legend": { "rename_tag": "span" }, "hr": {}, "label": { "rename_tag": "span" }, "dl": { "rename_tag": "div" }, "kbd": { "rename_tag": "span" }, "listing": { "rename_tag": "div" }, "dt": { "rename_tag": "span" }, "nextid": { "remove": 1 }, "pre": {}, "center": { "rename_tag": "div", "set_class": "wysiwyg-text-align-center" }, "audio": { "remove": 1 }, "datalist": { "rename_tag": "span" }, "samp": { "rename_tag": "span" }, "col": { "remove": 1 }, "article": { "rename_tag": "div" }, "cite": {}, "link": { "remove": 1 }, "script": { "remove": 1 }, "bdo": { "rename_tag": "span" }, "menu": { "rename_tag": "ul" }, "colgroup": { "remove": 1 }, "ruby": { "rename_tag": "span" }, "h2": { "add_class": { "align": "align_text" } }, "ins": { "rename_tag": "span" }, "p": { "add_class": { "align": "align_text" } }, "sub": { "rename_tag": "span" }, "comment": { "remove": 1 }, "frameset": { "remove": 1 }, "optgroup": { "rename_tag": "span" }, "header": { "rename_tag": "div" } } }; (function() { var toggleSwitch; $.fn.spinaSwitch = function() { return this.each(function() { var input, klass; if (!$(this).attr('data-plugin-switch')) { input = $(this); input.attr('data-plugin-switch', true); input.hide(); if (input.is(':checked')) { klass = "switch active"; } else { klass = "switch"; } return input.after('<a href="#' + input.attr("id") + '" class="' + klass + '"> <span class="knob"></span> </a>'); } }); }; $(document).on('click', 'a.switch', function(e) { return toggleSwitch(e); }); $(document).on('touchend', 'a.switch', function(e) { return toggleSwitch(e); }); toggleSwitch = function(e) { var checkbox, input; checkbox = $(e.currentTarget); input = $(checkbox.attr("href")); if (checkbox.hasClass('activated') || checkbox.hasClass('active')) { checkbox.removeClass('active'); checkbox.removeClass('activated'); checkbox.addClass('deactivated'); input.prop("checked", false); } else { checkbox.addClass('activated'); checkbox.removeClass('deactivated'); input.prop("checked", true); } return false; }; }).call(this); (function() { var hideModal, showModal; $.hideModal = function() { return hideModal(); }; $.fn.modal = function() { return showModal($(this)); }; $(document).on('click', 'a[data-toggle="modal"]', function() { var link, modal; link = $(this); modal = $(link.attr('href')); return showModal(modal); }); $(document).on('click', 'body.overlay', function() { return hideModal(); }); $(document).on('click', '[data-dismiss="modal"]', function() { return hideModal(); }); $(document).on('keyup', 'body.overlay', function(e) { if (e.keyCode === 27) { return hideModal(); } }); $(document).on('click', '.modal', function(e) { return e.stopPropagation(); }); hideModal = function() { $('body').removeClass('overlay'); $('#overlay .modal').addClass('flyOut'); $('#overlay').fadeOut(300, function() { return $(this).remove(); }); return false; }; showModal = function(element) { var maxheight, modal; modal = element.clone(); modal.addClass('animated flyIn'); if ($('#overlay').length < 1) { $('body').append('<div id="overlay"></div>'); } else { $('#overlay').html(''); } maxheight = window.innerHeight - (window.innerHeight / 8) - 150; modal.css({ "margin-top": window.innerHeight / 8 }); modal.find('section').css({ "max-height": maxheight }); modal.appendTo('#overlay'); $('#overlay').fadeIn(400); modal.show(); modal.find('input[type="file"][data-customfileinput]').customFileInput(); modal.find('.new_photo').uploadPhoto(); $('body').addClass('overlay'); return false; }; }).call(this); (function() { $(document).on('click', '.tabs li a[href^="#"]', function() { var link, tabs; link = $(this); tabs = link.parents('.tabs'); $('.tab-content').removeClass('active'); tabs.find('li').removeClass('active'); link.parent('li').addClass('active'); $(link.attr('href')).addClass('active'); return false; }); }).call(this); (function() { $(document).on('click', '.structure-form-menu ul li a', function(e) { var $structureForm; $structureForm = $(this).parents('.structure-form'); $(this).parent('li').siblings().removeClass('active'); $(this).parent('li').addClass('active'); $structureForm.find('.structure-form-pane').hide(); $($(this).attr('href')).show(); return e.preventDefault(); }); }).call(this); (function() { var closeDropdown; $(document).on('click', 'body.dropdown', function() { return closeDropdown(); }); $(document).on('click', '[data-trigger="dropdown"]', function() { var body, dropdown, trigger; trigger = $(this); dropdown = $(trigger.attr('data-target')); body = $('body'); if (body.hasClass('dropdown')) { trigger.removeClass('button-active'); body.removeClass('dropdown'); dropdown.removeClass('animated fadeInDown'); } else { trigger.addClass('button-active'); body.addClass('dropdown'); dropdown.addClass('animated fadeInDown'); } return false; }); $(document).on('click', '[data-dropdown] ul, [data-dropdown] .sliding-dropdown', function(e) { return e.stopPropagation(); }); $(document).on('click', '.slide-controls .previous, .slide-controls .next', function(e) { var active_title, next, previous, sliding_dropdown, target; e.preventDefault(); sliding_dropdown = $(this).parents('.sliding-dropdown'); active_title = sliding_dropdown.find('.slide-title.active'); previous = active_title.prev('.slide-title'); next = active_title.next('.slide-title'); if ($(this).hasClass('previous') && previous.length > 0) { sliding_dropdown.find('.slide-title').removeClass('active'); previous.addClass('active'); target = previous.data('target'); sliding_dropdown.find('.slide').removeClass('active'); $(target).addClass('active'); } else if ($(this).hasClass('next') && next.length > 0) { sliding_dropdown.find('.slide-title').removeClass('active'); next.addClass('active'); target = next.data('target'); sliding_dropdown.find('.slide').removeClass('active'); $(target).addClass('active'); } if (sliding_dropdown.find('.slide-title.active').next('.slide-title').length > 0) { sliding_dropdown.find('.next').removeClass('muted'); } else { sliding_dropdown.find('.next').addClass('muted'); } if (sliding_dropdown.find('.slide-title.active').prev('.slide-title').length > 0) { return sliding_dropdown.find('.previous').removeClass('muted'); } else { return sliding_dropdown.find('.previous').addClass('muted'); } }); closeDropdown = function() { $('body').removeClass('dropdown'); $('[data-dropdown] ul, [data-dropdown] .sliding-dropdown').removeClass('animated fadeInDown'); $('[data-trigger="dropdown"]').removeClass('button-active'); return false; }; }).call(this); (function() { $(document).on('click', '.gallery .item', function() { var checkbox, gallery; gallery = $(this).parents('.gallery'); if (gallery.data('multiselect') !== void 0) { $(this).toggleClass('selected'); checkbox = $(this).find('input:checkbox'); return checkbox.prop("checked", !checkbox.prop("checked")); } else { gallery.find('.item').removeClass('selected'); gallery.find('.item input').prop('checked', false); $(this).toggleClass('selected'); return $(this).find('input').prop('checked', true); } }); }).call(this); (function() { $.fn.uploadPhoto = function() { return $(this).fileupload({ dataType: "script", singleFileUploads: true, dropZone: $(this).find('.photo-field'), maxNumberOfFiles: 1, add: function(e, data) { var file, types; types = /(\.|\/)(gif|jpe?g|png)$/i; file = data.files[0]; if (types.test(file.type) || types.test(file.name)) { NProgress.start(); $(this).find('.customfile').addClass('loading'); return data.submit(); } else { return alert(file.name + " is geen gif-, jpeg- of png-bestand"); } }, progress: function(e, data) { if (data.context) { return NProgress.set(data.loaded / data.total); } }, done: function(e, data) { $(this).find('.customfile').removeClass('loading'); return NProgress.done(); } }); }; $.fn.uploadDocument = function() { return $(this).fileupload({ dataType: "script", singleFileUploads: true, dropZone: $(this).find('.attachment-field'), maxNumberOfFiles: 1, add: function(e, data) { var file, types; types = /(\.|\/)(pdf|docx?|rtf|txt)$/i; file = data.files[0]; if (types.test(file.type) || types.test(file.name)) { NProgress.start(); $(this).find('.customfile').addClass('loading'); return data.submit(); } else { return alert(file.name + " is geen pdf-, word-, txt- of rtf-bestand"); } }, progress: function(e, data) { if (data.context) { return NProgress.set(data.loaded / data.total); } }, done: function(e, data) { $(this).find('.customfile').removeClass('loading'); return NProgress.done(); } }); }; }).call(this); (function() { var ready; $(document).on('page:fetch', function() { return NProgress.start(); }); $(document).on('page:change', function() { return NProgress.done(); }); $(document).on('page:restore', function() { return NProgress.remove(); }); $(document).on('click', '.table-clickable tbody tr', function() { var checkbox; checkbox = $(this).find('input[type="checkbox"]:first, input[type="radio"]:first'); return checkbox.prop("checked", !checkbox.prop("checked")); }); $(document).on('keyup', '.search-input input', function(e) { $(this).parent().removeClass('animated small-shake'); if ($(this).val() === "") { $(this).parent().find('.clear-input').fadeOut(200); if (e.keyCode === 13) { return $(this).parent().addClass('animated small-shake'); } } else { return $(this).parent().find('.clear-input').fadeIn(200); } }); $(document).on('click', '.clear-input', function() { var input, link; link = $(this); input = link.siblings('input'); input.val(""); input.focus(); input.trigger("keyup"); link.fadeOut(200); return false; }); $(document).on('keyup + change', '.table-container .search-input input', function() { var datatable; datatable = $(this).parent().parent().find('table.datatable').dataTable(); return datatable.fnFilter($(this).val()); }); $(document).on('change', '.dd', function() { var serialized, sort_url; serialized = $(this).nestable('serialize'); sort_url = $(this).data('sort-url'); return $.post(sort_url, { list: serialized }); }); ready = function() { $('input[type="file"][data-customfileinput]:visible').each(function() { return $(this).customFileInput(); }); $('.new_photo').uploadPhoto(); $('.colorpicker').each(function() { var colorpicker, field; colorpicker = $(this).find('.colorpicker-container'); field = $(this).find('input'); return $.farbtastic(colorpicker, function(color) { field.val(color); return field.css('color', color); }); }); $('.colorpicker input').focus(function() { var colorpicker, container; container = $(this).parent(); colorpicker = container.find('.colorpicker-container'); $.farbtastic(colorpicker).setColor($(this).val()); return container.find('.farbtastic').show(); }); $('.colorpicker input').blur(function() { var container; container = $(this).parent(); return container.find('.farbtastic').hide(); }); $('.new_document').uploadDocument(); $('#login_wrapper').css('margin-top', $(document).innerHeight() / 8); $('.wysihtml5-container').each(function() { var container, editor, textarea, toolbar; container = $(this); textarea = container.find('textarea'); toolbar = container.find('.toolbar'); editor = new wysihtml5.Editor(textarea.attr('id'), { toolbar: toolbar.attr('id'), useLineBreaks: false, parserRules: wysihtml5ParserRules, stylesheets: ["/assets/spina/wysihtml5_textarea.css"] }); editor.on("load", function() { return container.data("wysihtml5", editor); }); editor.on("focus", function() { return container.find(".choose-text-type").fadeIn(100); }); return editor.on("blur", function() { return container.find(".choose-text-type").fadeOut(100); }); }); $(".dd").nestable({ maxDepth: 3 }); $(".structure-form-menu ul").sortable({ handle: '.sortable-handle' }); if ($('input[data-switch]').length > 0) { $('input[data-switch]').spinaSwitch(); } if ($('.datepicker').length > 0) { $('.datepicker').datepicker(); } if ($('.datatable').length > 0) { return $('table.datatable').dataTable({ "bLengthChange": false, "oLanguage": { "sProcessing": "Bezig...", "sLengthMenu": "_MENU_ resultaten weergeven", "sZeroRecords": "Geen resultaten gevonden", "sInfo": "_START_ tot _END_ van _TOTAL_ resultaten", "sInfoEmpty": "Geen resultaten om weer te geven", "sInfoFiltered": " (gefilterd uit _MAX_ resultaten)", "sInfoPostFix": "", "sSearch": "Zoeken:", "sEmptyTable": "Geen resultaten aanwezig in de tabel", "sInfoThousands": ".", "sLoadingRecords": "Een moment geduld aub - bezig met laden...", "oPaginate": { "sFirst": "Eerste", "sLast": "Laatste", "sNext": "Volgende", "sPrevious": "Vorige" } } }); } }; $(document).ready(ready); $(document).on('page:load', ready); }).call(this); (function() { var featherEditor, launchEditor; featherEditor = new Aviary.Feather({ apiKey: 'e7a5e1c28334eb7a', apiVersion: 3, theme: 'light', language: 'nl', minimumStyling: true, tools: 'crop,enhance,contrast,sharpness,text,whiten,effects,warmth,orientation,brightness,saturation,redeye,blemish', appendTo: '', onSave: function(imageID, newURL) { var img; img = $('#' + imageID); img.attr('src', newURL); return $.post(img.attr('data-posturl'), { new_image: newURL }); }, onError: function(errorObj) { return alert(errorObj.message); } }); launchEditor = function(id, src) { featherEditor.launch({ image: id, url: src }); return false; }; $(document).on('click', '[data-aviary]', function(e) { var image; e.preventDefault(); image = $(this).parents('.item').find('img'); return launchEditor(image.attr('id'), image.attr('data-image')); }); }).call(this); (function() { var ready, show_page_parts; ready = function() { var page_parts; if ($('.page-template').length > 0) { page_parts = $('.page-template').data('page-parts'); show_page_parts(page_parts); } $('.sortable-grid').sortable().bind('sortupdate', function(e) { var position_array; position_array = []; $(e.target).find('li.image').each(function(index) { return position_array.push($(this).data('photo-id')); }); return $(e.target).parents('td').find('.photo-positions').val(position_array.join(",")); }); return $('.structure-form-menu ul').sortable().bind('sortupdate', function(e) { return $(e.target).find('li').each(function(index) { var id; id = $(this).data('structure-item-id'); return $(".structure_form_pane_" + id + "_position").val(index); }); }); }; $(document).on('ready page:load', ready); $(document).on('change', '.page-template select', function() { var page_parts; page_parts = $(this).find('option:selected').data('page-parts').split(" "); return show_page_parts(page_parts); }); show_page_parts = function(page_parts) { var i, len, page_part, results; $('tr.page-part').hide(); results = []; for (i = 0, len = page_parts.length; i < len; i++) { page_part = page_parts[i]; results.push($('tr.page-part[data-name=' + page_part + ']').show()); } return results; }; $(document).on('click', 'form .add_fields', function(event) { var regexp, time; time = new Date().getTime(); regexp = new RegExp($(this).data('id'), 'g'); $(this).before($(this).data('fields').replace(regexp, time)); return event.preventDefault(); }); $(document).on('click', 'form .remove_fields', function(event) { $(this).prev('input[type=hidden]').val('1'); $(this).closest('fieldset').slideUp(); return event.preventDefault(); }); $(document).on('click', 'form .add_structure', function(event) { var $fields, $link, $structureForm, regexp, time; $structureForm = $(this).parents('.structure-form'); time = new Date().getTime(); regexp = new RegExp($(this).data('id'), 'g'); $fields = $($(this).data('fields').replace(regexp, time)); $(this).before($fields); $link = $("<li><a href='#structure_form_pane_" + time + "'><i data-icon='7'></i> </a></li>"); $structureForm.find('.structure-form-menu ul').append($link); $fields.attr('id', "structure_form_pane_" + time); $link.find('a').click(); return event.preventDefault(); }); $(document).on('click', 'form .remove-structure-item-fields', function(event) { var $pane; $(this).prev('input[type=hidden]').val('1'); $pane = $(this).closest('.structure-form-pane'); console.log($pane.attr('id')); $("a[href='#" + ($pane.attr('id')) + "']").parents('li').hide(); $pane.hide(); return event.preventDefault(); }); $(document).on('click', '.sort-switch', function(event) { $($(this).attr('href') + ' .dd-item-inner').toggleClass('dd-handle'); if ($(this).attr('data-icon') === 'j') { $(this).attr('data-icon', '8'); $(this).removeClass('button-success'); $(this).text($(this).data('change-order')); } else { $(this).attr('data-icon', 'j'); $(this).addClass('button-success'); $(this).text($(this).data('done-changing-order')); } return false; }); $(document).on('submit', 'form.edit_page', function(event) { var $submitButton; $submitButton = $(this).find('button[type="submit"]'); $submitButton.addClass('button-saving'); return $submitButton.attr('data-icon', 'f'); }); }).call(this); (function() { var ready, show_layout_parts; ready = function() { var layout_parts; if ($('.account-theme').length > 0) { layout_parts = $('.account-theme').data('layout-parts'); return show_layout_parts(layout_parts); } }; $(document).on('ready page:load', ready); $(document).on('change', '.account-theme select', function() { var layout_parts; layout_parts = $(this).find('option:selected').data('layout-parts').split(" "); return show_layout_parts(layout_parts); }); show_layout_parts = function(layout_parts) { var i, layout_part, len, results; $('tr.layout-part').hide(); results = []; for (i = 0, len = layout_parts.length; i < len; i++) { layout_part = layout_parts[i]; results.push($('tr.layout-part[data-name=' + layout_part + ']').show()); } return results; }; }).call(this); (function() { $.rails.allowAction = function(element) { var $link, message, modal_html; message = element.data('confirm'); if (!message) { return true; } $link = element.clone().removeAttr('data-confirm').removeAttr('data-icon').removeAttr('class'); $link.addClass('primary'); $link.html("<i data-icon=\"j\"></i> Ja, dat weet ik zeker"); modal_html = "<div id=\"modal\" class=\"modal\"><header class=\"big-header\">\n <a href=\"#\" class=\"close_modal\" data-dismiss=\"modal\"><i class=\"icon-only\" data-icon=\"m\"></i></a>\n <h3>" + message + "</h3>\n</header>\n\n<footer>\n <a href=\"#\" data-dismiss=\"modal\">Nee, annuleren</a>\n</footer></div>"; $(modal_html).modal(); $('#modal footer').append($link); return false; }; }).call(this); ;�TI"required_assets_digest;�TI"%a9161781a8a51f7dc5b4e6a8cc3022e5;�FI" _version;�TI"%64e62ddc273c2f5847f30d698ca14b67;�F