1/*! 2 * jQuery JavaScript Library v1.9.1 3 * http://jquery.com/ 4 * 5 * Includes Sizzle.js 6 * http://sizzlejs.com/ 7 * 8 * Copyright 2005, 2012 jQuery Foundation, Inc. and other contributors 9 * Released under the MIT license 10 * http://jquery.org/license 11 * 12 * Date: 2013-2-4 13 */ 14(function( window, undefined ) { 15 16// Can't do this because several apps including ASP.NET trace 17// the stack via arguments.caller.callee and Firefox dies if 18// you try to trace through "use strict" call chains. (#13335) 19// Support: Firefox 18+ 20//"use strict"; 21var 22 // The deferred used on DOM ready 23 readyList, 24 25 // A central reference to the root jQuery(document) 26 rootjQuery, 27 28 // Support: IE<9 29 // For `typeof node.method` instead of `node.method !== undefined` 30 core_strundefined = typeof undefined, 31 32 // Use the correct document accordingly with window argument (sandbox) 33 document = window.document, 34 location = window.location, 35 36 // Map over jQuery in case of overwrite 37 _jQuery = window.jQuery, 38 39 // Map over the $ in case of overwrite 40 _$ = window.$, 41 42 // [[Class]] -> type pairs 43 class2type = {}, 44 45 // List of deleted data cache ids, so we can reuse them 46 core_deletedIds = [], 47 48 core_version = "1.9.1", 49 50 // Save a reference to some core methods 51 core_concat = core_deletedIds.concat, 52 core_push = core_deletedIds.push, 53 core_slice = core_deletedIds.slice, 54 core_indexOf = core_deletedIds.indexOf, 55 core_toString = class2type.toString, 56 core_hasOwn = class2type.hasOwnProperty, 57 core_trim = core_version.trim, 58 59 // Define a local copy of jQuery 60 jQuery = function( selector, context ) { 61 // The jQuery object is actually just the init constructor 'enhanced' 62 return new jQuery.fn.init( selector, context, rootjQuery ); 63 }, 64 65 // Used for matching numbers 66 core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, 67 68 // Used for splitting on whitespace 69 core_rnotwhite = /\S+/g, 70 71 // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE) 72 rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, 73 74 // A simple way to check for HTML strings 75 // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) 76 // Strict HTML recognition (#11290: must start with <) 77 rquickExpr = /^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/, 78 79 // Match a standalone tag 80 rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, 81 82 // JSON RegExp 83 rvalidchars = /^[\],:{}\s]*$/, 84 rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, 85 rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, 86 rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g, 87 88 // Matches dashed string for camelizing 89 rmsPrefix = /^-ms-/, 90 rdashAlpha = /-([\da-z])/gi, 91 92 // Used by jQuery.camelCase as callback to replace() 93 fcamelCase = function( all, letter ) { 94 return letter.toUpperCase(); 95 }, 96 97 // The ready event handler 98 completed = function( event ) { 99 100 // readyState === "complete" is good enough for us to call the dom ready in oldIE 101 if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { 102 detach(); 103 jQuery.ready(); 104 } 105 }, 106 // Clean-up method for dom ready events 107 detach = function() { 108 if ( document.addEventListener ) { 109 document.removeEventListener( "DOMContentLoaded", completed, false ); 110 window.removeEventListener( "load", completed, false ); 111 112 } else { 113 document.detachEvent( "onreadystatechange", completed ); 114 window.detachEvent( "onload", completed ); 115 } 116 }; 117 118jQuery.fn = jQuery.prototype = { 119 // The current version of jQuery being used 120 jquery: core_version, 121 122 constructor: jQuery, 123 init: function( selector, context, rootjQuery ) { 124 var match, elem; 125 126 // HANDLE: $(""), $(null), $(undefined), $(false) 127 if ( !selector ) { 128 return this; 129 } 130 131 // Handle HTML strings 132 if ( typeof selector === "string" ) { 133 if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { 134 // Assume that strings that start and end with <> are HTML and skip the regex check 135 match = [ null, selector, null ]; 136 137 } else { 138 match = rquickExpr.exec( selector ); 139 } 140 141 // Match html or make sure no context is specified for #id 142 if ( match && (match[1] || !context) ) { 143 144 // HANDLE: $(html) -> $(array) 145 if ( match[1] ) { 146 context = context instanceof jQuery ? context[0] : context; 147 148 // scripts is true for back-compat 149 jQuery.merge( this, jQuery.parseHTML( 150 match[1], 151 context && context.nodeType ? context.ownerDocument || context : document, 152 true 153 ) ); 154 155 // HANDLE: $(html, props) 156 if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { 157 for ( match in context ) { 158 // Properties of context are called as methods if possible 159 if ( jQuery.isFunction( this[ match ] ) ) { 160 this[ match ]( context[ match ] ); 161 162 // ...and otherwise set as attributes 163 } else { 164 this.attr( match, context[ match ] ); 165 } 166 } 167 } 168 169 return this; 170 171 // HANDLE: $(#id) 172 } else { 173 elem = document.getElementById( match[2] ); 174 175 // Check parentNode to catch when Blackberry 4.6 returns 176 // nodes that are no longer in the document #6963 177 if ( elem && elem.parentNode ) { 178 // Handle the case where IE and Opera return items 179 // by name instead of ID 180 if ( elem.id !== match[2] ) { 181 return rootjQuery.find( selector ); 182 } 183 184 // Otherwise, we inject the element directly into the jQuery object 185 this.length = 1; 186 this[0] = elem; 187 } 188 189 this.context = document; 190 this.selector = selector; 191 return this; 192 } 193 194 // HANDLE: $(expr, $(...)) 195 } else if ( !context || context.jquery ) { 196 return ( context || rootjQuery ).find( selector ); 197 198 // HANDLE: $(expr, context) 199 // (which is just equivalent to: $(context).find(expr) 200 } else { 201 return this.constructor( context ).find( selector ); 202 } 203 204 // HANDLE: $(DOMElement) 205 } else if ( selector.nodeType ) { 206 this.context = this[0] = selector; 207 this.length = 1; 208 return this; 209 210 // HANDLE: $(function) 211 // Shortcut for document ready 212 } else if ( jQuery.isFunction( selector ) ) { 213 return rootjQuery.ready( selector ); 214 } 215 216 if ( selector.selector !== undefined ) { 217 this.selector = selector.selector; 218 this.context = selector.context; 219 } 220 221 return jQuery.makeArray( selector, this ); 222 }, 223 224 // Start with an empty selector 225 selector: "", 226 227 // The default length of a jQuery object is 0 228 length: 0, 229 230 // The number of elements contained in the matched element set 231 size: function() { 232 return this.length; 233 }, 234 235 toArray: function() { 236 return core_slice.call( this ); 237 }, 238 239 // Get the Nth element in the matched element set OR 240 // Get the whole matched element set as a clean array 241 get: function( num ) { 242 return num == null ? 243 244 // Return a 'clean' array 245 this.toArray() : 246 247 // Return just the object 248 ( num < 0 ? this[ this.length + num ] : this[ num ] ); 249 }, 250 251 // Take an array of elements and push it onto the stack 252 // (returning the new matched element set) 253 pushStack: function( elems ) { 254 255 // Build a new jQuery matched element set 256 var ret = jQuery.merge( this.constructor(), elems ); 257 258 // Add the old object onto the stack (as a reference)
259 ret.prevObject = this; 260 ret.context = this.context; 261 262 // Return the newly-formed element set 263 return ret; 264 }, 265 266 // Execute a callback for every element in the matched set. 267 // (You can seed the arguments with an array of args, but this is 268 // only used internally.) 269 each: function( callback, args ) { 270 return jQuery.each( this, callback, args ); 271 }, 272 273 ready: function( fn ) { 274 // Add the callback 275 jQuery.ready.promise().done( fn ); 276 277 return this; 278 }, 279 280 slice: function() { 281 return this.pushStack( core_slice.apply( this, arguments ) ); 282 }, 283 284 first: function() { 285 return this.eq( 0 ); 286 }, 287 288 last: function() { 289 return this.eq( -1 ); 290 }, 291 292 eq: function( i ) { 293 var len = this.length, 294 j = +i + ( i < 0 ? len : 0 ); 295 return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); 296 }, 297 298 map: function( callback ) { 299 return this.pushStack( jQuery.map(this, function( elem, i ) { 300 return callback.call( elem, i, elem ); 301 })); 302 }, 303 304 end: function() { 305 return this.prevObject || this.constructor(null); 306 }, 307 308 // For internal use only. 309 // Behaves like an Array's method, not like a jQuery method. 310 push: core_push, 311 sort: [].sort, 312 splice: [].splice 313}; 314 315// Give the init function the jQuery prototype for later instantiation 316jQuery.fn.init.prototype = jQuery.fn; 317 318jQuery.extend = jQuery.fn.extend = function() { 319 var src, copyIsArray, copy, name, options, clone, 320 target = arguments[0] || {}, 321 i = 1, 322 length = arguments.length, 323 deep = false; 324 325 // Handle a deep copy situation 326 if ( typeof target === "boolean" ) { 327 deep = target; 328 target = arguments[1] || {}; 329 // skip the boolean and the target 330 i = 2; 331 } 332 333 // Handle case when target is a string or something (possible in deep copy) 334 if ( typeof target !== "object" && !jQuery.isFunction(target) ) { 335 target = {}; 336 } 337 338 // extend jQuery itself if only one argument is passed 339 if ( length === i ) { 340 target = this; 341 --i; 342 } 343 344 for ( ; i < length; i++ ) { 345 // Only deal with non-null/undefined values 346 if ( (options = arguments[ i ]) != null ) { 347 // Extend the base object 348 for ( name in options ) { 349 src = target[ name ]; 350 copy = options[ name ]; 351 352 // Prevent never-ending loop 353 if ( target === copy ) { 354 continue; 355 } 356 357 // Recurse if we're merging plain objects or arrays 358 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { 359 if ( copyIsArray ) { 360 copyIsArray = false; 361 clone = src && jQuery.isArray(src) ? src : []; 362 363 } else { 364 clone = src && jQuery.isPlainObject(src) ? src : {}; 365 } 366 367 // Never move original objects, clone them 368 target[ name ] = jQuery.extend( deep, clone, copy ); 369 370 // Don't bring in undefined values 371 } else if ( copy !== undefined ) { 372 target[ name ] = copy; 373 } 374 } 375 } 376 } 377 378 // Return the modified object 379 return target; 380}; 381 382jQuery.extend({ 383 noConflict: function( deep ) { 384 if ( window.$ === jQuery ) { 385 window.$ = _$; 386 } 387 388 if ( deep && window.jQuery === jQuery ) { 389 window.jQuery = _jQuery; 390 } 391 392 return jQuery; 393 }, 394 395 // Is the DOM ready to be used? Set to true once it occurs. 396 isReady: false, 397 398 // A counter to track how many items to wait for before 399 // the ready event fires. See #6781 400 readyWait: 1, 401 402 // Hold (or release) the ready event 403 holdReady: function( hold ) { 404 if ( hold ) { 405 jQuery.readyWait++; 406 } else { 407 jQuery.ready( true ); 408 } 409 }, 410 411 // Handle when the DOM is ready 412 ready: function( wait ) { 413 414 // Abort if there are pending holds or we're already ready 415 if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { 416 return; 417 } 418 419 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). 420 if ( !document.body ) { 421 return setTimeout( jQuery.ready ); 422 } 423 424 // Remember that the DOM is ready 425 jQuery.isReady = true; 426 427 // If a normal DOM Ready event fired, decrement, and wait if need be 428 if ( wait !== true && --jQuery.readyWait > 0 ) { 429 return; 430 } 431 432 // If there are functions bound, to execute 433 readyList.resolveWith( document, [ jQuery ] ); 434 435 // Trigger any bound ready events 436 if ( jQuery.fn.trigger ) { 437 jQuery( document ).trigger("ready").off("ready"); 438 } 439 }, 440 441 // See test/unit/core.js for details concerning isFunction. 442 // Since version 1.3, DOM methods and functions like alert 443 // aren't supported. They return false on IE (#2968). 444 isFunction: function( obj ) { 445 return jQuery.type(obj) === "function"; 446 }, 447 448 isArray: Array.isArray || function( obj ) { 449 return jQuery.type(obj) === "array"; 450 }, 451 452 isWindow: function( obj ) { 453 return obj != null && obj == obj.window; 454 }, 455 456 isNumeric: function( obj ) { 457 return !isNaN( parseFloat(obj) ) && isFinite( obj ); 458 }, 459 460 type: function( obj ) { 461 if ( obj == null ) { 462 return String( obj ); 463 } 464 return typeof obj === "object" || typeof obj === "function" ? 465 class2type[ core_toString.call(obj) ] || "object" : 466 typeof obj; 467 }, 468 469 isPlainObject: function( obj ) { 470 // Must be an Object. 471 // Because of IE, we also have to check the presence of the constructor property. 472 // Make sure that DOM nodes and window objects don't pass through, as well 473 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { 474 return false;
475 } 476 477 try { 478 // Not own constructor property must be Object 479 if ( obj.constructor && 480 !core_hasOwn.call(obj, "constructor") && 481 !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { 482 return false; 483 } 484 } catch ( e ) { 485 // IE8,9 Will throw exceptions on certain host objects #9897 486 return false; 487 } 488 489 // Own properties are enumerated firstly, so to speed up, 490 // if last one is own, then all properties are own. 491 492 var key; 493 for ( key in obj ) {} 494 495 return key === undefined || core_hasOwn.call( obj, key ); 496 }, 497 498 isEmptyObject: function( obj ) { 499 var name; 500 for ( name in obj ) { 501 return false; 502 } 503 return true; 504 }, 505 506 error: function( msg ) { 507 throw new Error( msg ); 508 }, 509 510 // data: string of html 511 // context (optional): If specified, the fragment will be created in this context, defaults to document 512 // keepScripts (optional): If true, will include scripts passed in the html string 513 parseHTML: function( data, context, keepScripts ) { 514 if ( !data || typeof data !== "string" ) { 515 return null; 516 } 517 if ( typeof context === "boolean" ) { 518 keepScripts = context; 519 context = false; 520 } 521 context = context || document; 522 523 var parsed = rsingleTag.exec( data ), 524 scripts = !keepScripts && []; 525 526 // Single tag 527 if ( parsed ) { 528 return [ context.createElement( parsed[1] ) ]; 529 } 530 531 parsed = jQuery.buildFragment( [ data ], context, scripts ); 532 if ( scripts ) { 533 jQuery( scripts ).remove(); 534 } 535 return jQuery.merge( [], parsed.childNodes ); 536 }, 537 538 parseJSON: function( data ) { 539 // Attempt to parse using the native JSON parser first 540 if ( window.JSON && window.JSON.parse ) { 541 return window.JSON.parse( data ); 542 } 543 544 if ( data === null ) { 545 return data; 546 } 547 548 if ( typeof data === "string" ) { 549 550 // Make sure leading/trailing whitespace is removed (IE can't handle it) 551 data = jQuery.trim( data ); 552 553 if ( data ) { 554 // Make sure the incoming data is actual JSON 555 // Logic borrowed from http://json.org/json2.js 556 if ( rvalidchars.test( data.replace( rvalidescape, "@" ) 557 .replace( rvalidtokens, "]" ) 558 .replace( rvalidbraces, "")) ) { 559 560 return ( new Function( "return " + data ) )(); 561 } 562 } 563 } 564 565 jQuery.error( "Invalid JSON: " + data ); 566 }, 567 568 // Cross-browser xml parsing 569 parseXML: function( data ) { 570 var xml, tmp; 571 if ( !data || typeof data !== "string" ) { 572 return null; 573 } 574 try { 575 if ( window.DOMParser ) { // Standard 576 tmp = new DOMParser(); 577 xml = tmp.parseFromString( data , "text/xml" ); 578 } else { // IE 579 xml = new ActiveXObject( "Microsoft.XMLDOM" ); 580 xml.async = "false"; 581 xml.loadXML( data ); 582 } 583 } catch( e ) { 584 xml = undefined; 585 } 586 if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { 587 jQuery.error( "Invalid XML: " + data ); 588 } 589 return xml; 590 }, 591 592 noop: function() {}, 593 594 // Evaluates a script in a global context 595 // Workarounds based on findings by Jim Driscoll 596 // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context 597 globalEval: function( data ) { 598 if ( data && jQuery.trim( data ) ) { 599 // We use execScript on Internet Explorer 600 // We use an anonymous function so that context is window 601 // rather than jQuery in Firefox 602 ( window.execScript || function( data ) { 603 window[ "eval" ].call( window, data ); 604 } )( data ); 605 } 606 }, 607 608 // Convert dashed to camelCase; used by the css and data modules 609 // Microsoft forgot to hump their vendor prefix (#9572) 610 camelCase: function( string ) { 611 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); 612 }, 613
614 nodeName: function( elem, name ) { 615 return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); 616 }, 617 618 // args is for internal usage only 619 each: function( obj, callback, args ) { 620 var value, 621 i = 0, 622 length = obj.length, 623 isArray = isArraylike( obj ); 624 625 if ( args ) { 626 if ( isArray ) { 627 for ( ; i < length; i++ ) { 628 value = callback.apply( obj[ i ], args ); 629 630 if ( value === false ) { 631 break; 632 } 633 } 634 } else { 635 for ( i in obj ) { 636 value = callback.apply( obj[ i ], args ); 637 638 if ( value === false ) { 639 break; 640 } 641 } 642 } 643 644 // A special, fast, case for the most common use of each 645 } else { 646 if ( isArray ) { 647 for ( ; i < length; i++ ) { 648 value = callback.call( obj[ i ], i, obj[ i ] ); 649 650 if ( value === false ) { 651 break; 652 } 653 } 654 } else { 655 for ( i in obj ) { 656 value = callback.call( obj[ i ], i, obj[ i ] ); 657 658 if ( value === false ) { 659 break; 660 } 661 } 662 } 663 } 664 665 return obj; 666 }, 667 668 // Use native String.trim function wherever possible 669 trim: core_trim && !core_trim.call("\uFEFF\xA0") ? 670 function( text ) { 671 return text == null ? 672 "" : 673 core_trim.call( text ); 674 } : 675 676 // Otherwise use our own trimming functionality 677 function( text ) { 678 return text == null ? 679 "" : 680 ( text + "" ).replace( rtrim, "" ); 681 }, 682 683 // results is for internal usage only 684 makeArray: function( arr, results ) { 685 var ret = results || []; 686 687 if ( arr != null ) { 688 if ( isArraylike( Object(arr) ) ) { 689 jQuery.merge( ret, 690 typeof arr === "string" ? 691 [ arr ] : arr 692 ); 693 } else { 694 core_push.call( ret, arr ); 695 } 696 } 697 698 return ret; 699 }, 700 701 inArray: function( elem, arr, i ) { 702 var len; 703 704 if ( arr ) { 705 if ( core_indexOf ) { 706 return core_indexOf.call( arr, elem, i ); 707 } 708 709 len = arr.length; 710 i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; 711 712 for ( ; i < len; i++ ) { 713 // Skip accessing in sparse arrays 714 if ( i in arr && arr[ i ] === elem ) { 715 return i; 716 } 717 } 718 } 719 720 return -1; 721 }, 722 723 merge: function( first, second ) { 724 var l = second.length, 725 i = first.length, 726 j = 0; 727 728 if ( typeof l === "number" ) { 729 for ( ; j < l; j++ ) { 730 first[ i++ ] = second[ j ]; 731 } 732 } else { 733 while ( second[j] !== undefined ) { 734 first[ i++ ] = second[ j++ ]; 735 } 736 } 737 738 first.length = i; 739 740 return first; 741 }, 742 743 grep: function( elems, callback, inv ) { 744 var retVal, 745 ret = [], 746 i = 0, 747 length = elems.length; 748 inv = !!inv; 749 750 // Go through the array, only saving the items 751 // that pass the validator function 752 for ( ; i < length; i++ ) { 753 retVal = !!callback( elems[ i ], i ); 754 if ( inv !== retVal ) { 755 ret.push( elems[ i ] ); 756 } 757 } 758 759 return ret; 760 }, 761 762 // arg is for internal usage only 763 map: function( elems, callback, arg ) { 764 var value, 765 i = 0, 766 length = elems.length, 767 isArray = isArraylike( elems ), 768 ret = []; 769 770 // Go through the array, translating each of the items to their 771 if ( isArray ) { 772 for ( ; i < length; i++ ) { 773 value = callback( elems[ i ], i, arg ); 774 775 if ( value != null ) { 776 ret[ ret.length ] = value; 777 } 778 } 779 780 // Go through every key on the object, 781 } else { 782 for ( i in elems ) { 783 value = callback( elems[ i ], i, arg ); 784 785 if ( value != null ) { 786 ret[ ret.length ] = value; 787 } 788 } 789 } 790 791 // Flatten any nested arrays 792 return core_concat.apply( [], ret ); 793 }, 794 795 // A global GUID counter for objects 796 guid: 1, 797 798 // Bind a function to a context, optionally partially applying any 799 // arguments. 800 proxy: function( fn, context ) { 801 var args, proxy, tmp; 802 803 if ( typeof context === "string" ) { 804 tmp = fn[ context ]; 805 context = fn; 806 fn = tmp; 807 } 808 809 // Quick check to determine if target is callable, in the spec 810 // this throws a TypeError, but we will just return undefined. 811 if ( !jQuery.isFunction( fn ) ) { 812 return undefined; 813 } 814 815 // Simulated bind 816 args = core_slice.call( arguments, 2 ); 817 proxy = function() { 818 return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) ); 819 }; 820 821 // Set the guid of unique handler to the same of original handler, so it can be removed 822 proxy.guid = fn.guid = fn.guid || jQuery.guid++; 823 824 return proxy; 825 }, 826 827 // Multifunctional method to get and set values of a collection 828 // The value/s can optionally be executed if it's a function 829 access: function( elems, fn, key, value, chainable, emptyGet, raw ) { 830 var i = 0, 831 length = elems.length, 832 bulk = key == null; 833 834 // Sets many values 835 if ( jQuery.type( key ) === "object" ) { 836 chainable = true; 837 for ( i in key ) { 838 jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); 839 } 840 841 // Sets one value 842 } else if ( value !== undefined ) { 843 chainable = true; 844 845 if ( !jQuery.isFunction( value ) ) { 846 raw = true; 847 } 848 849 if ( bulk ) { 850 // Bulk operations run against the entire set 851 if ( raw ) { 852 fn.call( elems, value ); 853 fn = null; 854 855 // ...except when executing function values 856 } else { 857 bulk = fn; 858 fn = function( elem, key, value ) {
859 return bulk.call( jQuery( elem ), value ); 860 }; 861 } 862 } 863 864 if ( fn ) { 865 for ( ; i < length; i++ ) { 866 fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); 867 } 868 } 869 } 870 871 return chainable ? 872 elems : 873 874 // Gets 875 bulk ? 876 fn.call( elems ) : 877 length ? fn( elems[0], key ) : emptyGet; 878 }, 879 880 now: function() { 881 return ( new Date() ).getTime(); 882 } 883}); 884 885jQuery.ready.promise = function( obj ) { 886 if ( !readyList ) { 887 888 readyList = jQuery.Deferred(); 889 890 // Catch cases where $(document).ready() is called after the browser event has already occurred. 891 // we once tried to use readyState "interactive" here, but it caused issues like the one 892 // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 893 if ( document.readyState === "complete" ) { 894 // Handle it asynchronously to allow scripts the opportunity to delay ready 895 setTimeout( jQuery.ready ); 896 897 // Standards-based browsers support DOMContentLoaded 898 } else if ( document.addEventListener ) { 899 // Use the handy event callback 900 document.addEventListener( "DOMContentLoaded", completed, false ); 901 902 // A fallback to window.onload, that will always work 903 window.addEventListener( "load", completed, false ); 904 905 // If IE event model is used 906 } else { 907 // Ensure firing before onload, maybe late but safe also for iframes 908 document.attachEvent( "onreadystatechange", completed ); 909 910 // A fallback to window.onload, that will always work 911 window.attachEvent( "onload", completed ); 912 913 // If IE and not a frame 914 // continually check to see if the document is ready 915 var top = false; 916 917 try { 918 top = window.frameElement == null && document.documentElement; 919 } catch(e) {} 920 921 if ( top && top.doScroll ) { 922 (function doScrollCheck() { 923 if ( !jQuery.isReady ) { 924 925 try { 926 // Use the trick by Diego Perini 927 // http://javascript.nwbox.com/IEContentLoaded/ 928 top.doScroll("left"); 929 } catch(e) { 930 return setTimeout( doScrollCheck, 50 ); 931 } 932 933 // detach all dom ready events 934 detach(); 935 936 // and execute any waiting functions 937 jQuery.ready(); 938 } 939 })(); 940 } 941 } 942 } 943 return readyList.promise( obj ); 944}; 945 946// Populate the class2type map 947jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { 948 class2type[ "[object " + name + "]" ] = name.toLowerCase(); 949}); 950 951function isArraylike( obj ) { 952 var length = obj.length, 953 type = jQuery.type( obj ); 954 955 if ( jQuery.isWindow( obj ) ) { 956 return false; 957 } 958 959 if ( obj.nodeType === 1 && length ) { 960 return true; 961 } 962 963 return type === "array" || type !== "function" && 964 ( length === 0 || 965 typeof length === "number" && length > 0 && ( length - 1 ) in obj ); 966} 967 968// All jQuery objects should point back to these 969rootjQuery = jQuery(document); 970// String to Object options format cache 971var optionsCache = {}; 972 973// Convert String-formatted options into Object-formatted ones and store in cache 974function createOptions( options ) { 975 var object = optionsCache[ options ] = {}; 976 jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) { 977 object[ flag ] = true; 978 }); 979 return object; 980} 981 982/* 983 * Create a callback list using the following parameters: 984 * 985 * options: an optional list of space-separated options that will change how 986 * the callback list behaves or a more traditional option object 987 * 988 * By default a callback list will act like an event callback list and can be 989 * "fired" multiple times. 990 * 991 * Possible options: 992 * 993 * once: will ensure the callback list can only be fired once (like a Deferred) 994 * 995 * memory: will keep track of previous values and will call any callback added 996 * after the list has been fired right away with the latest "memorized" 997 * values (like a Deferred) 998 * 999 * unique: will ensure a callback can only be added once (no duplicate in the list) 1000 * 1001 * stopOnFalse: interrupt callings when a callback returns false 1002 * 1003 */ 1004jQuery.Callbacks = function( options ) { 1005 1006 // Convert options from String-formatted to Object-formatted if needed 1007 // (we check in cache first) 1008 options = typeof options === "string" ? 1009 ( optionsCache[ options ] || createOptions( options ) ) : 1010 jQuery.extend( {}, options ); 1011 1012 var // Flag to know if list is currently firing 1013 firing, 1014 // Last fire value (for non-forgettable lists) 1015 memory, 1016 // Flag to know if list was already fired 1017 fired, 1018 // End of the loop when firing 1019 firingLength, 1020 // Index of currently firing callback (modified by remove if needed) 1021 firingIndex, 1022 // First callback to fire (used internally by add and fireWith) 1023 firingStart, 1024 // Actual callback list 1025 list = [],
1026 // Stack of fire calls for repeatable lists 1027 stack = !options.once && [], 1028 // Fire callbacks 1029 fire = function( data ) { 1030 memory = options.memory && data; 1031 fired = true; 1032 firingIndex = firingStart || 0; 1033 firingStart = 0; 1034 firingLength = list.length; 1035 firing = true; 1036 for ( ; list && firingIndex < firingLength; firingIndex++ ) { 1037 if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { 1038 memory = false; // To prevent further calls using add 1039 break; 1040 } 1041 } 1042 firing = false; 1043 if ( list ) { 1044 if ( stack ) { 1045 if ( stack.length ) { 1046 fire( stack.shift() ); 1047 } 1048 } else if ( memory ) { 1049 list = []; 1050 } else { 1051 self.disable(); 1052 } 1053 } 1054 }, 1055 // Actual Callbacks object 1056 self = { 1057 // Add a callback or a collection of callbacks to the list 1058 add: function() { 1059 if ( list ) { 1060 // First, we save the current length 1061 var start = list.length; 1062 (function add( args ) { 1063 jQuery.each( args, function( _, arg ) { 1064 var type = jQuery.type( arg ); 1065 if ( type === "function" ) { 1066 if ( !options.unique || !self.has( arg ) ) { 1067 list.push( arg ); 1068 } 1069 } else if ( arg && arg.length && type !== "string" ) { 1070 // Inspect recursively 1071 add( arg ); 1072 } 1073 }); 1074 })( arguments ); 1075 // Do we need to add the callbacks to the 1076 // current firing batch? 1077 if ( firing ) { 1078 firingLength = list.length; 1079 // With memory, if we're not firing then 1080 // we should call right away 1081 } else if ( memory ) { 1082 firingStart = start; 1083 fire( memory ); 1084 } 1085 } 1086 return this; 1087 }, 1088 // Remove a callback from the list 1089 remove: function() { 1090 if ( list ) { 1091 jQuery.each( arguments, function( _, arg ) { 1092 var index; 1093 while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { 1094 list.splice( index, 1 ); 1095 // Handle firing indexes 1096 if ( firing ) { 1097 if ( index <= firingLength ) { 1098 firingLength--; 1099 } 1100 if ( index <= firingIndex ) { 1101 firingIndex--; 1102 } 1103 } 1104 } 1105 }); 1106 } 1107 return this; 1108 }, 1109 // Check if a given callback is in the list. 1110 // If no argument is given, return whether or not list has callbacks attached. 1111 has: function( fn ) { 1112 return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); 1113 }, 1114 // Remove all callbacks from the list 1115 empty: function() { 1116 list = []; 1117 return this; 1118 }, 1119 // Have the list do nothing anymore 1120 disable: function() { 1121 list = stack = memory = undefined; 1122 return this; 1123 }, 1124 // Is it disabled? 1125 disabled: function() { 1126 return !list; 1127 }, 1128 // Lock the list in its current state 1129 lock: function() { 1130 stack = undefined; 1131 if ( !memory ) { 1132 self.disable(); 1133 } 1134 return this; 1135 }, 1136 // Is it locked? 1137 locked: function() { 1138 return !stack; 1139 }, 1140 // Call all callbacks with the given context and arguments 1141 fireWith: function( context, args ) { 1142 args = args || []; 1143 args = [ context, args.slice ? args.slice() : args ]; 1144 if ( list && ( !fired || stack ) ) { 1145 if ( firing ) { 1146 stack.push( args ); 1147 } else { 1148 fire( args ); 1149 } 1150 } 1151 return this; 1152 }, 1153 // Call all the callbacks with the given arguments 1154 fire: function() { 1155 self.fireWith( this, arguments ); 1156 return this; 1157 }, 1158 // To know if the callbacks have already been called at least once 1159 fired: function() { 1160 return !!fired; 1161 } 1162 }; 1163 1164 return self; 1165}; 1166jQuery.extend({ 1167 1168 Deferred: function( func ) { 1169 var tuples = [ 1170 // action, add listener, listener list, final state 1171 [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], 1172 [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], 1173 [ "notify", "progress", jQuery.Callbacks("memory") ] 1174 ], 1175 state = "pending", 1176 promise = { 1177 state: function() { 1178 return state; 1179 }, 1180 always: function() { 1181 deferred.done( arguments ).fail( arguments ); 1182 return this; 1183 }, 1184 then: function( /* fnDone, fnFail, fnProgress */ ) { 1185 var fns = arguments; 1186 return jQuery.Deferred(function( newDefer ) { 1187 jQuery.each( tuples, function( i, tuple ) { 1188 var action = tuple[ 0 ],
1189 fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; 1190 // deferred[ done | fail | progress ] for forwarding actions to newDefer 1191 deferred[ tuple[1] ](function() { 1192 var returned = fn && fn.apply( this, arguments ); 1193 if ( returned && jQuery.isFunction( returned.promise ) ) { 1194 returned.promise() 1195 .done( newDefer.resolve ) 1196 .fail( newDefer.reject ) 1197 .progress( newDefer.notify ); 1198 } else { 1199 newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); 1200 } 1201 }); 1202 }); 1203 fns = null; 1204 }).promise(); 1205 }, 1206 // Get a promise for this deferred 1207 // If obj is provided, the promise aspect is added to the object 1208 promise: function( obj ) { 1209 return obj != null ? jQuery.extend( obj, promise ) : promise; 1210 } 1211 }, 1212 deferred = {}; 1213 1214 // Keep pipe for back-compat 1215 promise.pipe = promise.then; 1216 1217 // Add list-specific methods 1218 jQuery.each( tuples, function( i, tuple ) { 1219 var list = tuple[ 2 ], 1220 stateString = tuple[ 3 ]; 1221 1222 // promise[ done | fail | progress ] = list.add 1223 promise[ tuple[1] ] = list.add; 1224 1225 // Handle state 1226 if ( stateString ) { 1227 list.add(function() { 1228 // state = [ resolved | rejected ] 1229 state = stateString; 1230 1231 // [ reject_list | resolve_list ].disable; progress_list.lock 1232 }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); 1233 } 1234 1235 // deferred[ resolve | reject | notify ] 1236 deferred[ tuple[0] ] = function() { 1237 deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); 1238 return this; 1239 }; 1240 deferred[ tuple[0] + "With" ] = list.fireWith; 1241 }); 1242 1243 // Make the deferred a promise 1244 promise.promise( deferred ); 1245 1246 // Call given func if any 1247 if ( func ) { 1248 func.call( deferred, deferred ); 1249 } 1250 1251 // All done! 1252 return deferred; 1253 }, 1254 1255 // Deferred helper 1256 when: function( subordinate /* , ..., subordinateN */ ) { 1257 var i = 0, 1258 resolveValues = core_slice.call( arguments ), 1259 length = resolveValues.length, 1260 1261 // the count of uncompleted subordinates 1262 remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, 1263 1264 // the master Deferred. If resolveValues consist of only a single Deferred, just use that. 1265 deferred = remaining === 1 ? subordinate : jQuery.Deferred(), 1266 1267 // Update function for both resolve and progress values 1268 updateFunc = function( i, contexts, values ) { 1269 return function( value ) { 1270 contexts[ i ] = this; 1271 values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value; 1272 if( values === progressValues ) { 1273 deferred.notifyWith( contexts, values ); 1274 } else if ( !( --remaining ) ) { 1275 deferred.resolveWith( contexts, values ); 1276 } 1277 }; 1278 }, 1279 1280 progressValues, progressContexts, resolveContexts; 1281 1282 // add listeners to Deferred subordinates; treat others as resolved 1283 if ( length > 1 ) { 1284 progressValues = new Array( length ); 1285 progressContexts = new Array( length ); 1286 resolveContexts = new Array( length ); 1287 for ( ; i < length; i++ ) { 1288 if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { 1289 resolveValues[ i ].promise() 1290 .done( updateFunc( i, resolveContexts, resolveValues ) ) 1291 .fail( deferred.reject ) 1292 .progress( updateFunc( i, progressContexts, progressValues ) ); 1293 } else { 1294 --remaining; 1295 } 1296 } 1297 } 1298 1299 // if we're not waiting on anything, resolve the master 1300 if ( !remaining ) { 1301 deferred.resolveWith( resolveContexts, resolveValues ); 1302 } 1303 1304 return deferred.promise(); 1305 } 1306}); 1307jQuery.support = (function() { 1308 1309 var support, all, a, 1310 input, select, fragment, 1311 opt, eventName, isSupported, i, 1312 div = document.createElement("div"); 1313 1314 // Setup 1315 div.setAttribute( "className", "t" ); 1316 div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>"; 1317 1318 // Support tests won't run in some limited or non-browser environments 1319 all = div.getElementsByTagName("*"); 1320 a = div.getElementsByTagName("a")[ 0 ]; 1321 if ( !all || !a || !all.length ) { 1322 return {}; 1323 } 1324 1325 // First batch of tests 1326 select = document.createElement("select"); 1327 opt = select.appendChild( document.createElement("option") ); 1328 input = div.getElementsByTagName("input")[ 0 ]; 1329 1330 a.style.cssText = "top:1px;float:left;opacity:.5"; 1331 support = { 1332 // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) 1333 getSetAttribute: div.className !== "t", 1334 1335 // IE strips leading whitespace when .innerHTML is used 1336 leadingWhitespace: div.firstChild.nodeType === 3, 1337 1338 // Make sure that tbody elements aren't automatically inserted 1339 // IE will insert them into empty tables 1340 tbody: !div.getElementsByTagName("tbody").length, 1341 1342 // Make sure that link elements get serialized correctly by innerHTML 1343 // This requires a wrapper element in IE 1344 htmlSerialize: !!div.getElementsByTagName("link").length, 1345 1346 // Get the style information from getAttribute 1347 // (IE uses .cssText instead) 1348 style: /top/.test( a.getAttribute("style") ), 1349 1350 // Make sure that URLs aren't manipulated 1351 // (IE normalizes it by default) 1352 hrefNormalized: a.getAttribute("href") === "/a", 1353 1354 // Make sure that element opacity exists 1355 // (IE uses filter instead) 1356 // Use a regex to work around a WebKit issue. See #5145
1357 opacity: /^0.5/.test( a.style.opacity ), 1358 1359 // Verify style float existence 1360 // (IE uses styleFloat instead of cssFloat) 1361 cssFloat: !!a.style.cssFloat, 1362 1363 // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere) 1364 checkOn: !!input.value, 1365 1366 // Make sure that a selected-by-default option has a working selected property. 1367 // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) 1368 optSelected: opt.selected, 1369 1370 // Tests for enctype support on a form (#6743) 1371 enctype: !!document.createElement("form").enctype, 1372 1373 // Makes sure cloning an html5 element does not cause problems 1374 // Where outerHTML is undefined, this still works 1375 html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>", 1376 1377 // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode 1378 boxModel: document.compatMode === "CSS1Compat", 1379 1380 // Will be defined later 1381 deleteExpando: true, 1382 noCloneEvent: true, 1383 inlineBlockNeedsLayout: false, 1384 shrinkWrapBlocks: false, 1385 reliableMarginRight: true, 1386 boxSizingReliable: true, 1387 pixelPosition: false 1388 }; 1389 1390 // Make sure checked status is properly cloned 1391 input.checked = true; 1392 support.noCloneChecked = input.cloneNode( true ).checked; 1393 1394 // Make sure that the options inside disabled selects aren't marked as disabled 1395 // (WebKit marks them as disabled) 1396 select.disabled = true; 1397 support.optDisabled = !opt.disabled; 1398 1399 // Support: IE<9 1400 try { 1401 delete div.test; 1402 } catch( e ) { 1403 support.deleteExpando = false; 1404 } 1405 1406 // Check if we can trust getAttribute("value") 1407 input = document.createElement("input"); 1408 input.setAttribute( "value", "" ); 1409 support.input = input.getAttribute( "value" ) === ""; 1410 1411 // Check if an input maintains its value after becoming a radio 1412 input.value = "t"; 1413 input.setAttribute( "type", "radio" ); 1414 support.radioValue = input.value === "t"; 1415 1416 // #11217 - WebKit loses check when the name is after the checked attribute 1417 input.setAttribute( "checked", "t" ); 1418 input.setAttribute( "name", "t" ); 1419 1420 fragment = document.createDocumentFragment(); 1421 fragment.appendChild( input ); 1422 1423 // Check if a disconnected checkbox will retain its checked 1424 // value of true after appended to the DOM (IE6/7) 1425 support.appendChecked = input.checked; 1426 1427 // WebKit doesn't clone checked state correctly in fragments 1428 support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; 1429 1430 // Support: IE<9 1431 // Opera does not clone events (and typeof div.attachEvent === undefined). 1432 // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() 1433 if ( div.attachEvent ) { 1434 div.attachEvent( "onclick", function() { 1435 support.noCloneEvent = false; 1436 }); 1437 1438 div.cloneNode( true ).click(); 1439 } 1440 1441 // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event) 1442 // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP), test/csp.php 1443 for ( i in { submit: true, change: true, focusin: true }) { 1444 div.setAttribute( eventName = "on" + i, "t" ); 1445
1446 support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false; 1447 } 1448 1449 div.style.backgroundClip = "content-box"; 1450 div.cloneNode( true ).style.backgroundClip = ""; 1451 support.clearCloneStyle = div.style.backgroundClip === "content-box"; 1452 1453 // Run tests that need a body at doc ready 1454 jQuery(function() { 1455 var container, marginDiv, tds, 1456 divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;", 1457 body = document.getElementsByTagName("body")[0]; 1458 1459 if ( !body ) { 1460 // Return for frameset docs that don't have a body 1461 return; 1462 } 1463 1464 container = document.createElement("div"); 1465 container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px"; 1466 1467 body.appendChild( container ).appendChild( div ); 1468 1469 // Support: IE8 1470 // Check if table cells still have offsetWidth/Height when they are set 1471 // to display:none and there are still other visible table cells in a 1472 // table row; if so, offsetWidth/Height are not reliable for use when 1473 // determining if an element has been hidden directly using 1474 // display:none (it is still safe to use offsets if a parent element is 1475 // hidden; don safety goggles and see bug #4512 for more information). 1476 div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>"; 1477 tds = div.getElementsByTagName("td"); 1478 tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none"; 1479 isSupported = ( tds[ 0 ].offsetHeight === 0 ); 1480 1481 tds[ 0 ].style.display = ""; 1482 tds[ 1 ].style.display = "none"; 1483 1484 // Support: IE8 1485 // Check if empty table cells still have offsetWidth/Height 1486 support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); 1487 1488 // Check box-sizing and margin behavior 1489 div.innerHTML = ""; 1490 div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;"; 1491 support.boxSizing = ( div.offsetWidth === 4 ); 1492 support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 ); 1493 1494 // Use window.getComputedStyle because jsdom on node.js will break without it. 1495 if ( window.getComputedStyle ) { 1496 support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%"; 1497 support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px"; 1498 1499 // Check if div with explicit width and no margin-right incorrectly 1500 // gets computed margin-right based on width of container. (#3333) 1501 // Fails in WebKit before Feb 2011 nightlies 1502 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right 1503 marginDiv = div.appendChild( document.createElement("div") ); 1504 marginDiv.style.cssText = div.style.cssText = divReset; 1505 marginDiv.style.marginRight = marginDiv.style.width = "0"; 1506 div.style.width = "1px"; 1507 1508 support.reliableMarginRight = 1509 !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight ); 1510 } 1511 1512 if ( typeof div.style.zoom !== core_strundefined ) { 1513 // Support: IE<8 1514 // Check if natively block-level elements act like inline-block 1515 // elements when setting their display to 'inline' and giving 1516 // them layout 1517 div.innerHTML = ""; 1518 div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1"; 1519 support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); 1520 1521 // Support: IE6 1522 // Check if elements with layout shrink-wrap their children 1523 div.style.display = "block"; 1524 div.innerHTML = "<div></div>"; 1525 div.firstChild.style.width = "5px"; 1526 support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); 1527 1528 if ( support.inlineBlockNeedsLayout ) { 1529 // Prevent IE 6 from affecting layout for positioned elements #11048 1530 // Prevent IE from shrinking the body in IE 7 mode #12869 1531 // Support: IE<8 1532 body.style.zoom = 1; 1533 } 1534 } 1535 1536 body.removeChild( container ); 1537 1538 // Null elements to avoid leaks in IE 1539 container = div = tds = marginDiv = null; 1540 }); 1541 1542 // Null elements to avoid leaks in IE 1543 all = select = fragment = opt = a = input = null; 1544 1545 return support; 1546})(); 1547 1548var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, 1549 rmultiDash = /([A-Z])/g; 1550 1551function internalData( elem, name, data, pvt /* Internal Use Only */ ){ 1552 if ( !jQuery.acceptData( elem ) ) { 1553 return; 1554 } 1555 1556 var thisCache, ret, 1557 internalKey = jQuery.expando, 1558 getByName = typeof name === "string", 1559 1560 // We have to handle DOM nodes and JS objects differently because IE6-7 1561 // can't GC object references properly across the DOM-JS boundary 1562 isNode = elem.nodeType, 1563 1564 // Only DOM nodes need the global jQuery cache; JS object data is 1565 // attached directly to the object so GC can occur automatically 1566 cache = isNode ? jQuery.cache : elem, 1567 1568 // Only defining an ID for JS objects if its cache already exists allows 1569 // the code to shortcut on the same path as a DOM node with no cache 1570 id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; 1571 1572 // Avoid doing any more work than we need to when trying to get data on an 1573 // object that has no data at all 1574 if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) { 1575 return; 1576 } 1577 1578 if ( !id ) { 1579 // Only DOM nodes need a new unique ID for each element since their data 1580 // ends up in the global cache 1581 if ( isNode ) { 1582 elem[ internalKey ] = id = core_deletedIds.pop() || jQuery.guid++; 1583 } else { 1584 id = internalKey; 1585 } 1586 } 1587 1588 if ( !cache[ id ] ) { 1589 cache[ id ] = {}; 1590 1591 // Avoids exposing jQuery metadata on plain JS objects when the object 1592 // is serialized using JSON.stringify 1593 if ( !isNode ) { 1594 cache[ id ].toJSON = jQuery.noop; 1595 } 1596 } 1597
1598 // An object can be passed to jQuery.data instead of a key/value pair; this gets 1599 // shallow copied over onto the existing cache 1600 if ( typeof name === "object" || typeof name === "function" ) { 1601 if ( pvt ) { 1602 cache[ id ] = jQuery.extend( cache[ id ], name ); 1603 } else { 1604 cache[ id ].data = jQuery.extend( cache[ id ].data, name ); 1605 } 1606 } 1607 1608 thisCache = cache[ id ]; 1609 1610 // jQuery data() is stored in a separate object inside the object's internal data 1611 // cache in order to avoid key collisions between internal data and user-defined 1612 // data. 1613 if ( !pvt ) { 1614 if ( !thisCache.data ) { 1615 thisCache.data = {}; 1616 } 1617 1618 thisCache = thisCache.data; 1619 } 1620 1621 if ( data !== undefined ) { 1622 thisCache[ jQuery.camelCase( name ) ] = data; 1623 } 1624 1625 // Check for both converted-to-camel and non-converted data property names 1626 // If a data property was specified 1627 if ( getByName ) { 1628 1629 // First Try to find as-is property data 1630 ret = thisCache[ name ]; 1631 1632 // Test for null|undefined property data 1633 if ( ret == null ) { 1634 1635 // Try to find the camelCased property 1636 ret = thisCache[ jQuery.camelCase( name ) ]; 1637 } 1638 } else { 1639 ret = thisCache; 1640 } 1641 1642 return ret; 1643} 1644 1645function internalRemoveData( elem, name, pvt ) { 1646 if ( !jQuery.acceptData( elem ) ) { 1647 return; 1648 } 1649 1650 var i, l, thisCache, 1651 isNode = elem.nodeType, 1652 1653 // See jQuery.data for more information 1654 cache = isNode ? jQuery.cache : elem, 1655 id = isNode ? elem[ jQuery.expando ] : jQuery.expando; 1656 1657 // If there is already no cache entry for this object, there is no 1658 // purpose in continuing 1659 if ( !cache[ id ] ) { 1660 return; 1661 } 1662 1663 if ( name ) { 1664 1665 thisCache = pvt ? cache[ id ] : cache[ id ].data; 1666 1667 if ( thisCache ) { 1668 1669 // Support array or space separated string names for data keys 1670 if ( !jQuery.isArray( name ) ) { 1671 1672 // try the string as a key before any manipulation 1673 if ( name in thisCache ) { 1674 name = [ name ]; 1675 } else { 1676 1677 // split the camel cased version by spaces unless a key with the spaces exists 1678 name = jQuery.camelCase( name ); 1679 if ( name in thisCache ) { 1680 name = [ name ]; 1681 } else { 1682 name = name.split(" "); 1683 } 1684 } 1685 } else { 1686 // If "name" is an array of keys... 1687 // When data is initially created, via ("key", "val") signature, 1688 // keys will be converted to camelCase. 1689 // Since there is no way to tell _how_ a key was added, remove 1690 // both plain key and camelCase key. #12786 1691 // This will only penalize the array argument path. 1692 name = name.concat( jQuery.map( name, jQuery.camelCase ) ); 1693 } 1694 1695 for ( i = 0, l = name.length; i < l; i++ ) { 1696 delete thisCache[ name[i] ]; 1697 } 1698 1699 // If there is no data left in the cache, we want to continue 1700 // and let the cache object itself get destroyed 1701 if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { 1702 return; 1703 } 1704 } 1705 } 1706 1707 // See jQuery.data for more information 1708 if ( !pvt ) { 1709 delete cache[ id ].data; 1710 1711 // Don't destroy the parent cache unless the internal data object 1712 // had been the only thing left in it 1713 if ( !isEmptyDataObject( cache[ id ] ) ) { 1714 return; 1715 } 1716 } 1717 1718 // Destroy the cache 1719 if ( isNode ) { 1720 jQuery.cleanData( [ elem ], true ); 1721 1722 // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) 1723 } else if ( jQuery.support.deleteExpando || cache != cache.window ) { 1724 delete cache[ id ]; 1725 1726 // When all else fails, null 1727 } else { 1728 cache[ id ] = null; 1729 } 1730} 1731 1732jQuery.extend({ 1733 cache: {}, 1734 1735 // Unique for each copy of jQuery on the page 1736 // Non-digits removed to match rinlinejQuery 1737 expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ), 1738 1739 // The following elements throw uncatchable exceptions if you 1740 // attempt to add expando properties to them. 1741 noData: { 1742 "embed": true, 1743 // Ban all objects except for Flash (which handle expandos) 1744 "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", 1745 "applet": true 1746 }, 1747 1748 hasData: function( elem ) { 1749 elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; 1750 return !!elem && !isEmptyDataObject( elem ); 1751 }, 1752 1753 data: function( elem, name, data ) { 1754 return internalData( elem, name, data ); 1755 }, 1756 1757 removeData: function( elem, name ) { 1758 return internalRemoveData( elem, name ); 1759 }, 1760 1761 // For internal use only. 1762 _data: function( elem, name, data ) { 1763 return internalData( elem, name, data, true ); 1764 }, 1765 1766 _removeData: function( elem, name ) { 1767 return internalRemoveData( elem, name, true ); 1768 }, 1769 1770 // A method for determining if a DOM node can handle the data expando 1771 acceptData: function( elem ) {
1772 // Do not set data on non-element because it will not be cleared (#8335). 1773 if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) { 1774 return false; 1775 } 1776 1777 var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ]; 1778 1779 // nodes accept data unless otherwise specified; rejection can be conditional 1780 return !noData || noData !== true && elem.getAttribute("classid") === noData; 1781 } 1782}); 1783 1784jQuery.fn.extend({ 1785 data: function( key, value ) { 1786 var attrs, name, 1787 elem = this[0], 1788 i = 0, 1789 data = null; 1790 1791 // Gets all values 1792 if ( key === undefined ) { 1793 if ( this.length ) { 1794 data = jQuery.data( elem ); 1795 1796 if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { 1797 attrs = elem.attributes; 1798 for ( ; i < attrs.length; i++ ) { 1799 name = attrs[i].name; 1800 1801 if ( !name.indexOf( "data-" ) ) { 1802 name = jQuery.camelCase( name.slice(5) ); 1803 1804 dataAttr( elem, name, data[ name ] ); 1805 } 1806 } 1807 jQuery._data( elem, "parsedAttrs", true ); 1808 } 1809 } 1810 1811 return data; 1812 } 1813 1814 // Sets multiple values 1815 if ( typeof key === "object" ) { 1816 return this.each(function() { 1817 jQuery.data( this, key ); 1818 }); 1819 } 1820 1821 return jQuery.access( this, function( value ) { 1822 1823 if ( value === undefined ) { 1824 // Try to fetch any internally stored data first 1825 return elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null; 1826 } 1827 1828 this.each(function() { 1829 jQuery.data( this, key, value ); 1830 }); 1831 }, null, value, arguments.length > 1, null, true ); 1832 }, 1833 1834 removeData: function( key ) { 1835 return this.each(function() { 1836 jQuery.removeData( this, key ); 1837 }); 1838 } 1839}); 1840 1841function dataAttr( elem, key, data ) { 1842 // If nothing was found internally, try to fetch any 1843 // data from the HTML5 data-* attribute 1844 if ( data === undefined && elem.nodeType === 1 ) { 1845 1846 var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); 1847 1848 data = elem.getAttribute( name ); 1849 1850 if ( typeof data === "string" ) { 1851 try { 1852 data = data === "true" ? true : 1853 data === "false" ? false : 1854 data === "null" ? null : 1855 // Only convert to a number if it doesn't change the string 1856 +data + "" === data ? +data : 1857 rbrace.test( data ) ? jQuery.parseJSON( data ) : 1858 data; 1859 } catch( e ) {} 1860 1861 // Make sure we set the data so it isn't changed later 1862 jQuery.data( elem, key, data ); 1863 1864 } else { 1865 data = undefined; 1866 } 1867 } 1868 1869 return data; 1870} 1871 1872// checks a cache object for emptiness 1873function isEmptyDataObject( obj ) { 1874 var name; 1875 for ( name in obj ) { 1876 1877 // if the public data object is empty, the private is still empty 1878 if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { 1879 continue; 1880 } 1881 if ( name !== "toJSON" ) { 1882 return false; 1883 } 1884 } 1885 1886 return true; 1887} 1888jQuery.extend({ 1889 queue: function( elem, type, data ) { 1890 var queue; 1891 1892 if ( elem ) { 1893 type = ( type || "fx" ) + "queue"; 1894 queue = jQuery._data( elem, type ); 1895 1896 // Speed up dequeue by getting out quickly if this is just a lookup 1897 if ( data ) { 1898 if ( !queue || jQuery.isArray(data) ) { 1899 queue = jQuery._data( elem, type, jQuery.makeArray(data) ); 1900 } else { 1901 queue.push( data ); 1902 } 1903 } 1904 return queue || []; 1905 } 1906 }, 1907 1908 dequeue: function( elem, type ) { 1909 type = type || "fx"; 1910 1911 var queue = jQuery.queue( elem, type ), 1912 startLength = queue.length, 1913 fn = queue.shift(), 1914 hooks = jQuery._queueHooks( elem, type ), 1915 next = function() { 1916 jQuery.dequeue( elem, type ); 1917 }; 1918 1919 // If the fx queue is dequeued, always remove the progress sentinel 1920 if ( fn === "inprogress" ) { 1921 fn = queue.shift(); 1922 startLength--; 1923 } 1924 1925 hooks.cur = fn; 1926 if ( fn ) { 1927 1928 // Add a progress sentinel to prevent the fx queue from being 1929 // automatically dequeued 1930 if ( type === "fx" ) { 1931 queue.unshift( "inprogress" ); 1932 } 1933 1934 // clear up the last queue stop function 1935 delete hooks.stop; 1936 fn.call( elem, next, hooks ); 1937 } 1938 1939 if ( !startLength && hooks ) { 1940 hooks.empty.fire(); 1941 } 1942 }, 1943 1944 // not intended for public consumption - generates a queueHooks object, or returns the current one 1945 _queueHooks: function( elem, type ) { 1946 var key = type + "queueHooks"; 1947 return jQuery._data( elem, key ) || jQuery._data( elem, key, { 1948 empty: jQuery.Callbacks("once memory").add(function() { 1949 jQuery._removeData( elem, type + "queue" ); 1950 jQuery._removeData( elem, key ); 1951 }) 1952 }); 1953 } 1954}); 1955 1956jQuery.fn.extend({ 1957 queue: function( type, data ) { 1958 var setter = 2; 1959 1960 if ( typeof type !== "string" ) { 1961 data = type; 1962 type = "fx"; 1963 setter--; 1964 } 1965 1966 if ( arguments.length < setter ) { 1967 return jQuery.queue( this[0], type ); 1968 } 1969 1970 return data === undefined ?
1971 this : 1972 this.each(function() { 1973 var queue = jQuery.queue( this, type, data ); 1974 1975 // ensure a hooks for this queue 1976 jQuery._queueHooks( this, type ); 1977 1978 if ( type === "fx" && queue[0] !== "inprogress" ) { 1979 jQuery.dequeue( this, type ); 1980 } 1981 }); 1982 }, 1983 dequeue: function( type ) { 1984 return this.each(function() { 1985 jQuery.dequeue( this, type ); 1986 }); 1987 }, 1988 // Based off of the plugin by Clint Helfers, with permission. 1989 // http://blindsignals.com/index.php/2009/07/jquery-delay/ 1990 delay: function( time, type ) { 1991 time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; 1992 type = type || "fx"; 1993 1994 return this.queue( type, function( next, hooks ) { 1995 var timeout = setTimeout( next, time ); 1996 hooks.stop = function() { 1997 clearTimeout( timeout ); 1998 }; 1999 }); 2000 }, 2001 clearQueue: function( type ) { 2002 return this.queue( type || "fx", [] ); 2003 }, 2004 // Get a promise resolved when queues of a certain type 2005 // are emptied (fx is the type by default) 2006 promise: function( type, obj ) { 2007 var tmp, 2008 count = 1, 2009 defer = jQuery.Deferred(), 2010 elements = this, 2011 i = this.length, 2012 resolve = function() { 2013 if ( !( --count ) ) { 2014 defer.resolveWith( elements, [ elements ] ); 2015 } 2016 }; 2017 2018 if ( typeof type !== "string" ) { 2019 obj = type; 2020 type = undefined; 2021 } 2022 type = type || "fx"; 2023 2024 while( i-- ) { 2025 tmp = jQuery._data( elements[ i ], type + "queueHooks" ); 2026 if ( tmp && tmp.empty ) { 2027 count++; 2028 tmp.empty.add( resolve ); 2029 } 2030 } 2031 resolve(); 2032 return defer.promise( obj ); 2033 } 2034}); 2035var nodeHook, boolHook, 2036 rclass = /[\t\r\n]/g, 2037 rreturn = /\r/g, 2038 rfocusable = /^(?:input|select|textarea|button|object)$/i, 2039 rclickable = /^(?:a|area)$/i, 2040 rboolean = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i, 2041 ruseDefault = /^(?:checked|selected)$/i, 2042 getSetAttribute = jQuery.support.getSetAttribute, 2043 getSetInput = jQuery.support.input; 2044 2045jQuery.fn.extend({ 2046 attr: function( name, value ) { 2047 return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); 2048 }, 2049 2050 removeAttr: function( name ) { 2051 return this.each(function() { 2052 jQuery.removeAttr( this, name ); 2053 }); 2054 }, 2055 2056 prop: function( name, value ) { 2057 return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); 2058 }, 2059 2060 removeProp: function( name ) { 2061 name = jQuery.propFix[ name ] || name; 2062 return this.each(function() { 2063 // try/catch handles cases where IE balks (such as removing a property on window) 2064 try { 2065 this[ name ] = undefined; 2066 delete this[ name ]; 2067 } catch( e ) {} 2068 }); 2069 }, 2070 2071 addClass: function( value ) { 2072 var classes, elem, cur, clazz, j, 2073 i = 0, 2074 len = this.length, 2075 proceed = typeof value === "string" && value; 2076 2077 if ( jQuery.isFunction( value ) ) { 2078 return this.each(function( j ) { 2079 jQuery( this ).addClass( value.call( this, j, this.className ) ); 2080 }); 2081 } 2082 2083 if ( proceed ) { 2084 // The disjunction here is for better compressibility (see removeClass) 2085 classes = ( value || "" ).match( core_rnotwhite ) || []; 2086 2087 for ( ; i < len; i++ ) { 2088 elem = this[ i ]; 2089 cur = elem.nodeType === 1 && ( elem.className ? 2090 ( " " + elem.className + " " ).replace( rclass, " " ) : 2091 " " 2092 ); 2093 2094 if ( cur ) { 2095 j = 0; 2096 while ( (clazz = classes[j++]) ) { 2097 if ( cur.indexOf( " " + clazz + " " ) < 0 ) { 2098 cur += clazz + " "; 2099 } 2100 } 2101 elem.className = jQuery.trim( cur ); 2102 2103 } 2104 } 2105 } 2106 2107 return this; 2108 }, 2109 2110 removeClass: function( value ) { 2111 var classes, elem, cur, clazz, j, 2112 i = 0, 2113 len = this.length, 2114 proceed = arguments.length === 0 || typeof value === "string" && value; 2115 2116 if ( jQuery.isFunction( value ) ) { 2117 return this.each(function( j ) { 2118 jQuery( this ).removeClass( value.call( this, j, this.className ) ); 2119 }); 2120 } 2121 if ( proceed ) { 2122 classes = ( value || "" ).match( core_rnotwhite ) || []; 2123 2124 for ( ; i < len; i++ ) { 2125 elem = this[ i ]; 2126 // This expression is here for better compressibility (see addClass) 2127 cur = elem.nodeType === 1 && ( elem.className ? 2128 ( " " + elem.className + " " ).replace( rclass, " " ) : 2129 "" 2130 ); 2131 2132 if ( cur ) { 2133 j = 0; 2134 while ( (clazz = classes[j++]) ) {
2135 // Remove *all* instances 2136 while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { 2137 cur = cur.replace( " " + clazz + " ", " " ); 2138 } 2139 } 2140 elem.className = value ? jQuery.trim( cur ) : ""; 2141 } 2142 } 2143 } 2144 2145 return this; 2146 }, 2147 2148 toggleClass: function( value, stateVal ) { 2149 var type = typeof value, 2150 isBool = typeof stateVal === "boolean"; 2151 2152 if ( jQuery.isFunction( value ) ) { 2153 return this.each(function( i ) { 2154 jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); 2155 }); 2156 } 2157 2158 return this.each(function() { 2159 if ( type === "string" ) { 2160 // toggle individual class names 2161 var className, 2162 i = 0, 2163 self = jQuery( this ), 2164 state = stateVal, 2165 classNames = value.match( core_rnotwhite ) || []; 2166 2167 while ( (className = classNames[ i++ ]) ) { 2168 // check each className given, space separated list 2169 state = isBool ? state : !self.hasClass( className ); 2170 self[ state ? "addClass" : "removeClass" ]( className ); 2171 } 2172 2173 // Toggle whole class name 2174 } else if ( type === core_strundefined || type === "boolean" ) { 2175 if ( this.className ) { 2176 // store className if set 2177 jQuery._data( this, "__className__", this.className ); 2178 } 2179 2180 // If the element has a class name or if we're passed "false", 2181 // then remove the whole classname (if there was one, the above saved it). 2182 // Otherwise bring back whatever was previously saved (if anything), 2183 // falling back to the empty string if nothing was stored. 2184 this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; 2185 } 2186 }); 2187 }, 2188 2189 hasClass: function( selector ) { 2190 var className = " " + selector + " ", 2191 i = 0, 2192 l = this.length; 2193 for ( ; i < l; i++ ) { 2194 if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { 2195 return true; 2196 } 2197 } 2198 2199 return false; 2200 }, 2201 2202 val: function( value ) { 2203 var ret, hooks, isFunction, 2204 elem = this[0]; 2205 2206 if ( !arguments.length ) { 2207 if ( elem ) { 2208 hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; 2209 2210 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { 2211 return ret; 2212 } 2213 2214 ret = elem.value; 2215 2216 return typeof ret === "string" ? 2217 // handle most common string cases 2218 ret.replace(rreturn, "") : 2219 // handle cases where value is null/undef or number 2220 ret == null ? "" : ret; 2221 } 2222 2223 return; 2224 } 2225 2226 isFunction = jQuery.isFunction( value ); 2227 2228 return this.each(function( i ) { 2229 var val, 2230 self = jQuery(this); 2231 2232 if ( this.nodeType !== 1 ) { 2233 return; 2234 } 2235 2236 if ( isFunction ) { 2237 val = value.call( this, i, self.val() ); 2238 } else { 2239 val = value; 2240 } 2241 2242 // Treat null/undefined as ""; convert numbers to string 2243 if ( val == null ) { 2244 val = ""; 2245 } else if ( typeof val === "number" ) { 2246 val += ""; 2247 } else if ( jQuery.isArray( val ) ) { 2248 val = jQuery.map(val, function ( value ) { 2249 return value == null ? "" : value + ""; 2250 }); 2251 } 2252 2253 hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; 2254 2255 // If set returns undefined, fall back to normal setting 2256 if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { 2257 this.value = val; 2258 } 2259 }); 2260 } 2261}); 2262 2263jQuery.extend({ 2264 valHooks: { 2265 option: { 2266 get: function( elem ) { 2267 // attributes.value is undefined in Blackberry 4.7 but 2268 // uses .value. See #6932 2269 var val = elem.attributes.value; 2270 return !val || val.specified ? elem.value : elem.text; 2271 } 2272 }, 2273 select: { 2274 get: function( elem ) { 2275 var value, option, 2276 options = elem.options, 2277 index = elem.selectedIndex, 2278 one = elem.type === "select-one" || index < 0, 2279 values = one ? null : [], 2280 max = one ? index + 1 : options.length, 2281 i = index < 0 ? 2282 max : 2283 one ? index : 0; 2284 2285 // Loop through all the selected options 2286 for ( ; i < max; i++ ) { 2287 option = options[ i ]; 2288 2289 // oldIE doesn't update selected after form reset (#2551) 2290 if ( ( option.selected || i === index ) && 2291 // Don't return options that are disabled or in a disabled optgroup 2292 ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && 2293 ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { 2294 2295 // Get the specific value for the option 2296 value = jQuery( option ).val(); 2297 2298 // We don't need an array for one selects 2299 if ( one ) { 2300 return value; 2301 } 2302 2303 // Multi-Selects return an array 2304 values.push( value ); 2305 } 2306 } 2307 2308 return values; 2309 }, 2310 2311 set: function( elem, value ) { 2312 var values = jQuery.makeArray( value ); 2313 2314 jQuery(elem).find("option").each(function() { 2315 this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; 2316 }); 2317 2318 if ( !values.length ) { 2319 elem.selectedIndex = -1; 2320 } 2321 return values; 2322 } 2323 } 2324 }, 2325 2326 attr: function( elem, name, value ) { 2327 var hooks, notxml, ret, 2328 nType = elem.nodeType; 2329 2330 // don't get/set attributes on text, comment and attribute nodes 2331 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { 2332 return; 2333 } 2334 2335 // Fallback to prop when attributes are not supported 2336 if ( typeof elem.getAttribute === core_strundefined ) { 2337 return jQuery.prop( elem, name, value ); 2338 } 2339 2340 notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); 2341 2342 // All attributes are lowercase 2343 // Grab necessary hook if one is defined 2344 if ( notxml ) { 2345 name = name.toLowerCase(); 2346 hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); 2347 } 2348 2349 if ( value !== undefined ) { 2350 2351 if ( value === null ) { 2352 jQuery.removeAttr( elem, name ); 2353 2354 } else if ( hooks && notxml && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { 2355 return ret; 2356 2357 } else { 2358 elem.setAttribute( name, value + "" ); 2359 return value; 2360 } 2361 2362 } else if ( hooks && notxml && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { 2363 return ret; 2364 2365 } else { 2366 2367 // In IE9+, Flash objects don't have .getAttribute (#12945)
2368 // Support: IE9+ 2369 if ( typeof elem.getAttribute !== core_strundefined ) { 2370 ret = elem.getAttribute( name ); 2371 } 2372 2373 // Non-existent attributes return null, we normalize to undefined 2374 return ret == null ? 2375 undefined : 2376 ret; 2377 } 2378 }, 2379 2380 removeAttr: function( elem, value ) { 2381 var name, propName, 2382 i = 0, 2383 attrNames = value && value.match( core_rnotwhite ); 2384 2385 if ( attrNames && elem.nodeType === 1 ) { 2386 while ( (name = attrNames[i++]) ) { 2387 propName = jQuery.propFix[ name ] || name; 2388 2389 // Boolean attributes get special treatment (#10870) 2390 if ( rboolean.test( name ) ) { 2391 // Set corresponding property to false for boolean attributes 2392 // Also clear defaultChecked/defaultSelected (if appropriate) for IE<8 2393 if ( !getSetAttribute && ruseDefault.test( name ) ) { 2394 elem[ jQuery.camelCase( "default-" + name ) ] = 2395 elem[ propName ] = false; 2396 } else { 2397 elem[ propName ] = false; 2398 } 2399 2400 // See #9699 for explanation of this approach (setting first, then removal) 2401 } else { 2402 jQuery.attr( elem, name, "" ); 2403 } 2404 2405 elem.removeAttribute( getSetAttribute ? name : propName ); 2406 } 2407 } 2408 }, 2409 2410 attrHooks: { 2411 type: { 2412 set: function( elem, value ) { 2413 if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { 2414 // Setting the type on a radio button after the value resets the value in IE6-9 2415 // Reset value to default in case type is set after value during creation 2416 var val = elem.value; 2417 elem.setAttribute( "type", value ); 2418 if ( val ) { 2419 elem.value = val; 2420 } 2421 return value; 2422 } 2423 } 2424 } 2425 }, 2426 2427 propFix: { 2428 tabindex: "tabIndex", 2429 readonly: "readOnly", 2430 "for": "htmlFor", 2431 "class": "className", 2432 maxlength: "maxLength", 2433 cellspacing: "cellSpacing", 2434 cellpadding: "cellPadding", 2435 rowspan: "rowSpan", 2436 colspan: "colSpan", 2437 usemap: "useMap", 2438 frameborder: "frameBorder", 2439 contenteditable: "contentEditable" 2440 }, 2441 2442 prop: function( elem, name, value ) { 2443 var ret, hooks, notxml, 2444 nType = elem.nodeType; 2445 2446 // don't get/set properties on text, comment and attribute nodes 2447 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { 2448 return; 2449 } 2450 2451 notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); 2452 2453 if ( notxml ) { 2454 // Fix name and attach hooks 2455 name = jQuery.propFix[ name ] || name; 2456 hooks = jQuery.propHooks[ name ]; 2457 } 2458 2459 if ( value !== undefined ) { 2460 if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { 2461 return ret; 2462 2463 } else { 2464 return ( elem[ name ] = value ); 2465 } 2466 2467 } else { 2468 if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { 2469 return ret; 2470 2471 } else { 2472 return elem[ name ]; 2473 } 2474 } 2475 }, 2476 2477 propHooks: { 2478 tabIndex: { 2479 get: function( elem ) { 2480 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set 2481 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ 2482 var attributeNode = elem.getAttributeNode("tabindex"); 2483 2484 return attributeNode && attributeNode.specified ? 2485 parseInt( attributeNode.value, 10 ) : 2486 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? 2487 0 : 2488 undefined; 2489 } 2490 } 2491 } 2492}); 2493 2494// Hook for boolean attributes 2495boolHook = { 2496 get: function( elem, name ) { 2497 var 2498 // Use .prop to determine if this attribute is understood as boolean 2499 prop = jQuery.prop( elem, name ), 2500 2501 // Fetch it accordingly 2502 attr = typeof prop === "boolean" && elem.getAttribute( name ), 2503 detail = typeof prop === "boolean" ? 2504 2505 getSetInput && getSetAttribute ? 2506 attr != null : 2507 // oldIE fabricates an empty string for missing boolean attributes 2508 // and conflates checked/selected into attroperties 2509 ruseDefault.test( name ) ? 2510 elem[ jQuery.camelCase( "default-" + name ) ] : 2511 !!attr : 2512 2513 // fetch an attribute node for properties not recognized as boolean 2514 elem.getAttributeNode( name ); 2515 2516 return detail && detail.value !== false ? 2517 name.toLowerCase() : 2518 undefined; 2519 }, 2520 set: function( elem, value, name ) { 2521 if ( value === false ) { 2522 // Remove boolean attributes when set to false 2523 jQuery.removeAttr( elem, name ); 2524 } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
2525 // IE<8 needs the *property* name 2526 elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name ); 2527 2528 // Use defaultChecked and defaultSelected for oldIE 2529 } else { 2530 elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true; 2531 } 2532 2533 return name; 2534 } 2535}; 2536 2537// fix oldIE value attroperty 2538if ( !getSetInput || !getSetAttribute ) { 2539 jQuery.attrHooks.value = { 2540 get: function( elem, name ) { 2541 var ret = elem.getAttributeNode( name ); 2542 return jQuery.nodeName( elem, "input" ) ? 2543 2544 // Ignore the value *property* by using defaultValue 2545 elem.defaultValue : 2546 2547 ret && ret.specified ? ret.value : undefined; 2548 }, 2549 set: function( elem, value, name ) { 2550 if ( jQuery.nodeName( elem, "input" ) ) { 2551 // Does not return so that setAttribute is also used 2552 elem.defaultValue = value; 2553 } else { 2554 // Use nodeHook if defined (#1954); otherwise setAttribute is fine 2555 return nodeHook && nodeHook.set( elem, value, name ); 2556 } 2557 } 2558 }; 2559} 2560 2561// IE6/7 do not support getting/setting some attributes with get/setAttribute 2562if ( !getSetAttribute ) { 2563 2564 // Use this for any attribute in IE6/7 2565 // This fixes almost every IE6/7 issue 2566 nodeHook = jQuery.valHooks.button = { 2567 get: function( elem, name ) { 2568 var ret = elem.getAttributeNode( name ); 2569 return ret && ( name === "id" || name === "name" || name === "coords" ? ret.value !== "" : ret.specified ) ? 2570 ret.value : 2571 undefined; 2572 }, 2573 set: function( elem, value, name ) { 2574 // Set the existing or create a new attribute node 2575 var ret = elem.getAttributeNode( name ); 2576 if ( !ret ) { 2577 elem.setAttributeNode( 2578 (ret = elem.ownerDocument.createAttribute( name )) 2579 ); 2580 } 2581 2582 ret.value = value += ""; 2583 2584 // Break association with cloned elements by also using setAttribute (#9646) 2585 return name === "value" || value === elem.getAttribute( name ) ? 2586 value : 2587 undefined; 2588 } 2589 }; 2590 2591 // Set contenteditable to false on removals(#10429) 2592 // Setting to empty string throws an error as an invalid value 2593 jQuery.attrHooks.contenteditable = { 2594 get: nodeHook.get, 2595 set: function( elem, value, name ) { 2596 nodeHook.set( elem, value === "" ? false : value, name ); 2597 } 2598 }; 2599 2600 // Set width and height to auto instead of 0 on empty string( Bug #8150 ) 2601 // This is for removals 2602 jQuery.each([ "width", "height" ], function( i, name ) { 2603 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { 2604 set: function( elem, value ) { 2605 if ( value === "" ) { 2606 elem.setAttribute( name, "auto" ); 2607 return value; 2608 } 2609 } 2610 }); 2611 }); 2612} 2613 2614 2615// Some attributes require a special call on IE 2616// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx 2617if ( !jQuery.support.hrefNormalized ) { 2618 jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { 2619 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { 2620 get: function( elem ) { 2621 var ret = elem.getAttribute( name, 2 ); 2622 return ret == null ? undefined : ret; 2623 } 2624 }); 2625 }); 2626 2627 // href/src property should get the full normalized URL (#10299/#12915) 2628 jQuery.each([ "href", "src" ], function( i, name ) { 2629 jQuery.propHooks[ name ] = { 2630 get: function( elem ) { 2631 return elem.getAttribute( name, 4 ); 2632 } 2633 }; 2634 }); 2635} 2636 2637if ( !jQuery.support.style ) { 2638 jQuery.attrHooks.style = { 2639 get: function( elem ) { 2640 // Return undefined in the case of empty string 2641 // Note: IE uppercases css property names, but if we were to .toLowerCase() 2642 // .cssText, that would destroy case senstitivity in URL's, like in "background" 2643 return elem.style.cssText || undefined; 2644 }, 2645 set: function( elem, value ) { 2646 return ( elem.style.cssText = value + "" ); 2647 } 2648 }; 2649} 2650 2651// Safari mis-reports the default selected property of an option 2652// Accessing the parent's selectedIndex property fixes it 2653if ( !jQuery.support.optSelected ) { 2654 jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { 2655 get: function( elem ) { 2656 var parent = elem.parentNode; 2657 2658 if ( parent ) { 2659 parent.selectedIndex; 2660 2661 // Make sure that it also works with optgroups, see #5701 2662 if ( parent.parentNode ) { 2663 parent.parentNode.selectedIndex; 2664 } 2665 } 2666 return null; 2667 } 2668 }); 2669} 2670 2671// IE6/7 call enctype encoding 2672if ( !jQuery.support.enctype ) { 2673 jQuery.propFix.enctype = "encoding"; 2674} 2675 2676// Radios and checkboxes getter/setter 2677if ( !jQuery.support.checkOn ) { 2678 jQuery.each([ "radio", "checkbox" ], function() { 2679 jQuery.valHooks[ this ] = { 2680 get: function( elem ) { 2681 // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified 2682 return elem.getAttribute("value") === null ? "on" : elem.value; 2683 } 2684 }; 2685 }); 2686} 2687jQuery.each([ "radio", "checkbox" ], function() { 2688 jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { 2689 set: function( elem, value ) { 2690 if ( jQuery.isArray( value ) ) { 2691 return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); 2692 } 2693 } 2694 }); 2695}); 2696var rformElems = /^(?:input|select|textarea)$/i,
2697 rkeyEvent = /^key/, 2698 rmouseEvent = /^(?:mouse|contextmenu)|click/, 2699 rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, 2700 rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; 2701 2702function returnTrue() { 2703 return true; 2704} 2705 2706function returnFalse() { 2707 return false; 2708} 2709 2710/* 2711 * Helper functions for managing events -- not part of the public interface. 2712 * Props to Dean Edwards' addEvent library for many of the ideas. 2713 */ 2714jQuery.event = { 2715 2716 global: {}, 2717 2718 add: function( elem, types, handler, data, selector ) { 2719 var tmp, events, t, handleObjIn, 2720 special, eventHandle, handleObj, 2721 handlers, type, namespaces, origType, 2722 elemData = jQuery._data( elem ); 2723 2724 // Don't attach events to noData or text/comment nodes (but allow plain objects) 2725 if ( !elemData ) { 2726 return; 2727 } 2728 2729 // Caller can pass in an object of custom data in lieu of the handler 2730 if ( handler.handler ) { 2731 handleObjIn = handler; 2732 handler = handleObjIn.handler; 2733 selector = handleObjIn.selector; 2734 } 2735 2736 // Make sure that the handler has a unique ID, used to find/remove it later 2737 if ( !handler.guid ) { 2738 handler.guid = jQuery.guid++; 2739 } 2740 2741 // Init the element's event structure and main handler, if this is the first 2742 if ( !(events = elemData.events) ) { 2743 events = elemData.events = {}; 2744 } 2745 if ( !(eventHandle = elemData.handle) ) { 2746 eventHandle = elemData.handle = function( e ) { 2747 // Discard the second event of a jQuery.event.trigger() and 2748 // when an event is called after a page has unloaded 2749 return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ? 2750 jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : 2751 undefined; 2752 }; 2753 // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events 2754 eventHandle.elem = elem; 2755 } 2756 2757 // Handle multiple events separated by a space 2758 // jQuery(...).bind("mouseover mouseout", fn); 2759 types = ( types || "" ).match( core_rnotwhite ) || [""]; 2760 t = types.length; 2761 while ( t-- ) { 2762 tmp = rtypenamespace.exec( types[t] ) || []; 2763 type = origType = tmp[1]; 2764 namespaces = ( tmp[2] || "" ).split( "." ).sort(); 2765 2766 // If event changes its type, use the special event handlers for the changed type 2767 special = jQuery.event.special[ type ] || {}; 2768 2769 // If selector defined, determine special event api type, otherwise given type 2770 type = ( selector ? special.delegateType : special.bindType ) || type; 2771 2772 // Update special based on newly reset type 2773 special = jQuery.event.special[ type ] || {}; 2774 2775 // handleObj is passed to all event handlers 2776 handleObj = jQuery.extend({ 2777 type: type, 2778 origType: origType, 2779 data: data, 2780 handler: handler, 2781 guid: handler.guid, 2782 selector: selector, 2783 needsContext: selector && jQuery.expr.match.needsContext.test( selector ), 2784 namespace: namespaces.join(".") 2785 }, handleObjIn ); 2786 2787 // Init the event handler queue if we're the first 2788 if ( !(handlers = events[ type ]) ) { 2789 handlers = events[ type ] = []; 2790 handlers.delegateCount = 0; 2791 2792 // Only use addEventListener/attachEvent if the special events handler returns false 2793 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { 2794 // Bind the global event handler to the element 2795 if ( elem.addEventListener ) { 2796 elem.addEventListener( type, eventHandle, false ); 2797 2798 } else if ( elem.attachEvent ) { 2799 elem.attachEvent( "on" + type, eventHandle ); 2800 } 2801 } 2802 } 2803 2804 if ( special.add ) { 2805 special.add.call( elem, handleObj ); 2806 2807 if ( !handleObj.handler.guid ) { 2808 handleObj.handler.guid = handler.guid; 2809 } 2810 } 2811 2812 // Add to the element's handler list, delegates in front 2813 if ( selector ) { 2814 handlers.splice( handlers.delegateCount++, 0, handleObj ); 2815 } else { 2816 handlers.push( handleObj ); 2817 } 2818 2819 // Keep track of which events have ever been used, for event optimization 2820 jQuery.event.global[ type ] = true; 2821 } 2822 2823 // Nullify elem to prevent memory leaks in IE 2824 elem = null; 2825 }, 2826 2827 // Detach an event or set of events from an element 2828 remove: function( elem, types, handler, selector, mappedTypes ) { 2829 var j, handleObj, tmp, 2830 origCount, t, events, 2831 special, handlers, type, 2832 namespaces, origType, 2833 elemData = jQuery.hasData( elem ) && jQuery._data( elem ); 2834 2835 if ( !elemData || !(events = elemData.events) ) { 2836 return; 2837 } 2838
vendor: 8,375 bytes, lines 2839-3101
2839 // Once for each type.namespace in types; type may be omitted 2840 types = ( types || "" ).match( core_rnotwhite ) || [""]; 2841 t = types.length; 2842 while ( t-- ) { 2843 tmp = rtypenamespace.exec( types[t] ) || []; 2844 type = origType = tmp[1]; 2845 namespaces = ( tmp[2] || "" ).split( "." ).sort(); 2846 2847 // Unbind all events (on this namespace, if provided) for the element 2848 if ( !type ) { 2849 for ( type in events ) { 2850 jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); 2851 } 2852 continue; 2853 } 2854 2855 special = jQuery.event.special[ type ] || {}; 2856 type = ( selector ? special.delegateType : special.bindType ) || type; 2857 handlers = events[ type ] || []; 2858 tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); 2859 2860 // Remove matching events 2861 origCount = j = handlers.length; 2862 while ( j-- ) { 2863 handleObj = handlers[ j ]; 2864 2865 if ( ( mappedTypes || origType === handleObj.origType ) && 2866 ( !handler || handler.guid === handleObj.guid ) && 2867 ( !tmp || tmp.test( handleObj.namespace ) ) && 2868 ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { 2869 handlers.splice( j, 1 ); 2870 2871 if ( handleObj.selector ) { 2872 handlers.delegateCount--; 2873 } 2874 if ( special.remove ) { 2875 special.remove.call( elem, handleObj ); 2876 } 2877 } 2878 } 2879 2880 // Remove generic event handler if we removed something and no more handlers exist 2881 // (avoids potential for endless recursion during removal of special event handlers) 2882 if ( origCount && !handlers.length ) { 2883 if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { 2884 jQuery.removeEvent( elem, type, elemData.handle ); 2885 } 2886 2887 delete events[ type ]; 2888 } 2889 } 2890 2891 // Remove the expando if it's no longer used 2892 if ( jQuery.isEmptyObject( events ) ) { 2893 delete elemData.handle; 2894 2895 // removeData also checks for emptiness and clears the expando if empty 2896 // so use it instead of delete 2897 jQuery._removeData( elem, "events" ); 2898 } 2899 }, 2900 2901 trigger: function( event, data, elem, onlyHandlers ) { 2902 var handle, ontype, cur, 2903 bubbleType, special, tmp, i, 2904 eventPath = [ elem || document ], 2905 type = core_hasOwn.call( event, "type" ) ? event.type : event, 2906 namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; 2907 2908 cur = tmp = elem = elem || document; 2909 2910 // Don't do events on text and comment nodes 2911 if ( elem.nodeType === 3 || elem.nodeType === 8 ) { 2912 return; 2913 } 2914 2915 // focus/blur morphs to focusin/out; ensure we're not firing them right now 2916 if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { 2917 return; 2918 } 2919 2920 if ( type.indexOf(".") >= 0 ) { 2921 // Namespaced trigger; create a regexp to match event type in handle() 2922 namespaces = type.split("."); 2923 type = namespaces.shift(); 2924 namespaces.sort(); 2925 } 2926 ontype = type.indexOf(":") < 0 && "on" + type; 2927 2928 // Caller can pass in a jQuery.Event object, Object, or just an event type string 2929 event = event[ jQuery.expando ] ? 2930 event : 2931 new jQuery.Event( type, typeof event === "object" && event ); 2932 2933 event.isTrigger = true; 2934 event.namespace = namespaces.join("."); 2935 event.namespace_re = event.namespace ? 2936 new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : 2937 null; 2938 2939 // Clean up the event in case it is being reused 2940 event.result = undefined; 2941 if ( !event.target ) { 2942 event.target = elem; 2943 } 2944 2945 // Clone any incoming data and prepend the event, creating the handler arg list 2946 data = data == null ? 2947 [ event ] : 2948 jQuery.makeArray( data, [ event ] ); 2949 2950 // Allow special events to draw outside the lines 2951 special = jQuery.event.special[ type ] || {}; 2952 if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { 2953 return; 2954 } 2955 2956 // Determine event propagation path in advance, per W3C events spec (#9951) 2957 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) 2958 if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { 2959 2960 bubbleType = special.delegateType || type; 2961 if ( !rfocusMorph.test( bubbleType + type ) ) { 2962 cur = cur.parentNode; 2963 } 2964 for ( ; cur; cur = cur.parentNode ) { 2965 eventPath.push( cur ); 2966 tmp = cur; 2967 } 2968 2969 // Only add window if we got to document (e.g., not plain obj or detached DOM) 2970 if ( tmp === (elem.ownerDocument || document) ) { 2971 eventPath.push( tmp.defaultView || tmp.parentWindow || window ); 2972 } 2973 } 2974 2975 // Fire handlers on the event path 2976 i = 0; 2977 while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { 2978 2979 event.type = i > 1 ? 2980 bubbleType : 2981 special.bindType || type; 2982 2983 // jQuery handler 2984 handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); 2985 if ( handle ) { 2986 handle.apply( cur, data ); 2987 } 2988 2989 // Native handler 2990 handle = ontype && cur[ ontype ]; 2991 if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) { 2992 event.preventDefault(); 2993 } 2994 } 2995 event.type = type; 2996 2997 // If nobody prevented the default action, do it now 2998 if ( !onlyHandlers && !event.isDefaultPrevented() ) { 2999 3000 if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && 3001 !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { 3002 3003 // Call a native DOM method on the target with the same name name as the event. 3004 // Can't use an .isFunction() check here because IE6/7 fails that test. 3005 // Don't do default actions on window, that's where global variables be (#6170) 3006 if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { 3007 3008 // Don't re-trigger an onFOO event when we call its FOO() method 3009 tmp = elem[ ontype ]; 3010 3011 if ( tmp ) { 3012 elem[ ontype ] = null; 3013 } 3014 3015 // Prevent re-triggering of the same event, since we already bubbled it above 3016 jQuery.event.triggered = type; 3017 try { 3018 elem[ type ](); 3019 } catch ( e ) { 3020 // IE<9 dies on focus/blur to hidden element (#1486,#12518) 3021 // only reproducible on winXP IE8 native, not IE9 in IE8 mode 3022 } 3023 jQuery.event.triggered = undefined; 3024 3025 if ( tmp ) { 3026 elem[ ontype ] = tmp; 3027 } 3028 } 3029 } 3030 } 3031 3032 return event.result; 3033 }, 3034 3035 dispatch: function( event ) { 3036 3037 // Make a writable jQuery.Event from the native event object 3038 event = jQuery.event.fix( event ); 3039 3040 var i, ret, handleObj, matched, j, 3041 handlerQueue = [], 3042 args = core_slice.call( arguments ), 3043 handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], 3044 special = jQuery.event.special[ event.type ] || {}; 3045 3046 // Use the fix-ed jQuery.Event rather than the (read-only) native event 3047 args[0] = event; 3048 event.delegateTarget = this; 3049 3050 // Call the preDispatch hook for the mapped type, and let it bail if desired 3051 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { 3052 return; 3053 } 3054 3055 // Determine handlers 3056 handlerQueue = jQuery.event.handlers.call( this, event, handlers ); 3057 3058 // Run delegates first; they may want to stop propagation beneath us 3059 i = 0; 3060 while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { 3061 event.currentTarget = matched.elem; 3062 3063 j = 0; 3064 while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { 3065 3066 // Triggered event must either 1) have no namespace, or 3067 // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). 3068 if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { 3069 3070 event.handleObj = handleObj; 3071 event.data = handleObj.data; 3072 3073 ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) 3074 .apply( matched.elem, args ); 3075 3076 if ( ret !== undefined ) { 3077 if ( (event.result = ret) === false ) { 3078 event.preventDefault(); 3079 event.stopPropagation(); 3080 } 3081 } 3082 } 3083 } 3084 } 3085 3086 // Call the postDispatch hook for the mapped type 3087 if ( special.postDispatch ) { 3088 special.postDispatch.call( this, event ); 3089 } 3090 3091 return event.result; 3092 }, 3093 3094 handlers: function( event, handlers ) { 3095 var sel, handleObj, matches, i, 3096 handlerQueue = [], 3097 delegateCount = handlers.delegateCount, 3098 cur = event.target; 3099 3100 // Find delegate handlers 3101 // Black-hole SVG <use> instance trees (#13180)
3102 // Avoid non-left-click bubbling in Firefox (#3861) 3103 if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { 3104 3105 for ( ; cur != this; cur = cur.parentNode || this ) { 3106 3107 // Don't check non-elements (#13208) 3108 // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) 3109 if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) { 3110 matches = []; 3111 for ( i = 0; i < delegateCount; i++ ) { 3112 handleObj = handlers[ i ]; 3113 3114 // Don't conflict with Object.prototype properties (#13203) 3115 sel = handleObj.selector + " "; 3116 3117 if ( matches[ sel ] === undefined ) { 3118 matches[ sel ] = handleObj.needsContext ? 3119 jQuery( sel, this ).index( cur ) >= 0 : 3120 jQuery.find( sel, this, null, [ cur ] ).length; 3121 } 3122 if ( matches[ sel ] ) { 3123 matches.push( handleObj ); 3124 } 3125 } 3126 if ( matches.length ) { 3127 handlerQueue.push({ elem: cur, handlers: matches }); 3128 } 3129 } 3130 } 3131 } 3132 3133 // Add the remaining (directly-bound) handlers 3134 if ( delegateCount < handlers.length ) { 3135 handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); 3136 } 3137 3138 return handlerQueue; 3139 }, 3140 3141 fix: function( event ) { 3142 if ( event[ jQuery.expando ] ) { 3143 return event; 3144 } 3145 3146 // Create a writable copy of the event object and normalize some properties 3147 var i, prop, copy, 3148 type = event.type, 3149 originalEvent = event, 3150 fixHook = this.fixHooks[ type ]; 3151 3152 if ( !fixHook ) { 3153 this.fixHooks[ type ] = fixHook = 3154 rmouseEvent.test( type ) ? this.mouseHooks : 3155 rkeyEvent.test( type ) ? this.keyHooks : 3156 {}; 3157 } 3158 copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; 3159 3160 event = new jQuery.Event( originalEvent ); 3161 3162 i = copy.length; 3163 while ( i-- ) { 3164 prop = copy[ i ]; 3165 event[ prop ] = originalEvent[ prop ]; 3166 } 3167 3168 // Support: IE<9 3169 // Fix target property (#1925) 3170 if ( !event.target ) { 3171 event.target = originalEvent.srcElement || document; 3172 } 3173 3174 // Support: Chrome 23+, Safari? 3175 // Target should not be a text node (#504, #13143) 3176 if ( event.target.nodeType === 3 ) { 3177 event.target = event.target.parentNode; 3178 } 3179 3180 // Support: IE<9 3181 // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) 3182 event.metaKey = !!event.metaKey; 3183 3184 return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; 3185 }, 3186 3187 // Includes some event props shared by KeyEvent and MouseEvent 3188 props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), 3189 3190 fixHooks: {}, 3191 3192 keyHooks: { 3193 props: "char charCode key keyCode".split(" "), 3194 filter: function( event, original ) { 3195 3196 // Add which for key events 3197 if ( event.which == null ) { 3198 event.which = original.charCode != null ? original.charCode : original.keyCode; 3199 } 3200 3201 return event; 3202 } 3203 }, 3204 3205 mouseHooks: { 3206 props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), 3207 filter: function( event, original ) { 3208 var body, eventDoc, doc, 3209 button = original.button, 3210 fromElement = original.fromElement; 3211 3212 // Calculate pageX/Y if missing and clientX/Y available 3213 if ( event.pageX == null && original.clientX != null ) { 3214 eventDoc = event.target.ownerDocument || document; 3215 doc = eventDoc.documentElement; 3216 body = eventDoc.body; 3217 3218 event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); 3219 event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); 3220 } 3221 3222 // Add relatedTarget, if necessary 3223 if ( !event.relatedTarget && fromElement ) { 3224 event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; 3225 } 3226 3227 // Add which for click: 1 === left; 2 === middle; 3 === right 3228 // Note: button is not normalized, so don't use it 3229 if ( !event.which && button !== undefined ) { 3230 event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); 3231 } 3232 3233 return event; 3234 } 3235 }, 3236 3237 special: { 3238 load: { 3239 // Prevent triggered image.load events from bubbling to window.load 3240 noBubble: true 3241 }, 3242 click: { 3243 // For checkbox, fire native event so checked state will be right 3244 trigger: function() { 3245 if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { 3246 this.click(); 3247 return false;
3248 } 3249 } 3250 }, 3251 focus: { 3252 // Fire native event if possible so blur/focus sequence is correct 3253 trigger: function() { 3254 if ( this !== document.activeElement && this.focus ) { 3255 try { 3256 this.focus(); 3257 return false; 3258 } catch ( e ) { 3259 // Support: IE<9 3260 // If we error on focus to hidden element (#1486, #12518), 3261 // let .trigger() run the handlers 3262 } 3263 } 3264 }, 3265 delegateType: "focusin" 3266 }, 3267 blur: { 3268 trigger: function() { 3269 if ( this === document.activeElement && this.blur ) { 3270 this.blur(); 3271 return false; 3272 } 3273 }, 3274 delegateType: "focusout" 3275 }, 3276 3277 beforeunload: { 3278 postDispatch: function( event ) { 3279 3280 // Even when returnValue equals to undefined Firefox will still show alert 3281 if ( event.result !== undefined ) { 3282 event.originalEvent.returnValue = event.result; 3283 } 3284 } 3285 } 3286 }, 3287 3288 simulate: function( type, elem, event, bubble ) { 3289 // Piggyback on a donor event to simulate a different one. 3290 // Fake originalEvent to avoid donor's stopPropagation, but if the 3291 // simulated event prevents default then we do the same on the donor. 3292 var e = jQuery.extend( 3293 new jQuery.Event(), 3294 event, 3295 { type: type, 3296 isSimulated: true, 3297 originalEvent: {} 3298 } 3299 ); 3300 if ( bubble ) { 3301 jQuery.event.trigger( e, null, elem ); 3302 } else { 3303 jQuery.event.dispatch.call( elem, e ); 3304 } 3305 if ( e.isDefaultPrevented() ) { 3306 event.preventDefault(); 3307 } 3308 } 3309}; 3310 3311jQuery.removeEvent = document.removeEventListener ? 3312 function( elem, type, handle ) { 3313 if ( elem.removeEventListener ) { 3314 elem.removeEventListener( type, handle, false ); 3315 } 3316 } : 3317 function( elem, type, handle ) { 3318 var name = "on" + type; 3319 3320 if ( elem.detachEvent ) { 3321 3322 // #8545, #7054, preventing memory leaks for custom events in IE6-8 3323 // detachEvent needed property on element, by name of that event, to properly expose it to GC 3324 if ( typeof elem[ name ] === core_strundefined ) { 3325 elem[ name ] = null; 3326 } 3327 3328 elem.detachEvent( name, handle ); 3329 } 3330 }; 3331 3332jQuery.Event = function( src, props ) { 3333 // Allow instantiation without the 'new' keyword 3334 if ( !(this instanceof jQuery.Event) ) { 3335 return new jQuery.Event( src, props ); 3336 } 3337 3338 // Event object 3339 if ( src && src.type ) { 3340 this.originalEvent = src; 3341 this.type = src.type; 3342 3343 // Events bubbling up the document may have been marked as prevented 3344 // by a handler lower down the tree; reflect the correct value. 3345 this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || 3346 src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; 3347 3348 // Event type 3349 } else { 3350 this.type = src; 3351 } 3352 3353 // Put explicitly provided properties onto the event object 3354 if ( props ) { 3355 jQuery.extend( this, props ); 3356 } 3357 3358 // Create a timestamp if incoming event doesn't have one 3359 this.timeStamp = src && src.timeStamp || jQuery.now(); 3360 3361 // Mark it as fixed 3362 this[ jQuery.expando ] = true; 3363}; 3364 3365// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding 3366// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html 3367jQuery.Event.prototype = { 3368 isDefaultPrevented: returnFalse, 3369 isPropagationStopped: returnFalse, 3370 isImmediatePropagationStopped: returnFalse, 3371 3372 preventDefault: function() { 3373 var e = this.originalEvent; 3374 3375 this.isDefaultPrevented = returnTrue; 3376 if ( !e ) { 3377 return; 3378 } 3379 3380 // If preventDefault exists, run it on the original event 3381 if ( e.preventDefault ) { 3382 e.preventDefault(); 3383 3384 // Support: IE 3385 // Otherwise set the returnValue property of the original event to false 3386 } else { 3387 e.returnValue = false; 3388 } 3389 }, 3390 stopPropagation: function() { 3391 var e = this.originalEvent; 3392 3393 this.isPropagationStopped = returnTrue; 3394 if ( !e ) { 3395 return; 3396 } 3397 // If stopPropagation exists, run it on the original event 3398 if ( e.stopPropagation ) { 3399 e.stopPropagation(); 3400 } 3401 3402 // Support: IE 3403 // Set the cancelBubble property of the original event to true 3404 e.cancelBubble = true; 3405 }, 3406 stopImmediatePropagation: function() { 3407 this.isImmediatePropagationStopped = returnTrue; 3408 this.stopPropagation(); 3409 } 3410}; 3411 3412// Create mouseenter/leave events using mouseover/out and event-time checks 3413jQuery.each({ 3414 mouseenter: "mouseover", 3415 mouseleave: "mouseout" 3416}, function( orig, fix ) { 3417 jQuery.event.special[ orig ] = { 3418 delegateType: fix, 3419 bindType: fix, 3420 3421 handle: function( event ) { 3422 var ret, 3423 target = this, 3424 related = event.relatedTarget, 3425 handleObj = event.handleObj; 3426 3427 // For mousenter/leave call the handler if related is outside the target. 3428 // NB: No relatedTarget if the mouse left/entered the browser window 3429 if ( !related || (related !== target && !jQuery.contains( target, related )) ) { 3430 event.type = handleObj.origType; 3431 ret = handleObj.handler.apply( this, arguments ); 3432 event.type = fix; 3433 } 3434 return ret; 3435 } 3436 }; 3437}); 3438 3439// IE submit delegation 3440if ( !jQuery.support.submitBubbles ) { 3441 3442 jQuery.event.special.submit = { 3443 setup: function() { 3444 // Only need this for delegated form submit events 3445 if ( jQuery.nodeName( this, "form" ) ) { 3446 return false;
3447 } 3448 3449 // Lazy-add a submit handler when a descendant form may potentially be submitted 3450 jQuery.event.add( this, "click._submit keypress._submit", function( e ) { 3451 // Node name check avoids a VML-related crash in IE (#9807) 3452 var elem = e.target, 3453 form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; 3454 if ( form && !jQuery._data( form, "submitBubbles" ) ) { 3455 jQuery.event.add( form, "submit._submit", function( event ) { 3456 event._submit_bubble = true; 3457 }); 3458 jQuery._data( form, "submitBubbles", true ); 3459 } 3460 }); 3461 // return undefined since we don't need an event listener 3462 }, 3463 3464 postDispatch: function( event ) { 3465 // If form was submitted by the user, bubble the event up the tree 3466 if ( event._submit_bubble ) { 3467 delete event._submit_bubble; 3468 if ( this.parentNode && !event.isTrigger ) { 3469 jQuery.event.simulate( "submit", this.parentNode, event, true ); 3470 } 3471 } 3472 }, 3473 3474 teardown: function() { 3475 // Only need this for delegated form submit events 3476 if ( jQuery.nodeName( this, "form" ) ) { 3477 return false; 3478 } 3479 3480 // Remove delegated handlers; cleanData eventually reaps submit handlers attached above 3481 jQuery.event.remove( this, "._submit" ); 3482 } 3483 }; 3484} 3485 3486// IE change delegation and checkbox/radio fix 3487if ( !jQuery.support.changeBubbles ) { 3488 3489 jQuery.event.special.change = { 3490 3491 setup: function() { 3492 3493 if ( rformElems.test( this.nodeName ) ) { 3494 // IE doesn't fire change on a check/radio until blur; trigger it on click 3495 // after a propertychange. Eat the blur-change in special.change.handle. 3496 // This still fires onchange a second time for check/radio after blur. 3497 if ( this.type === "checkbox" || this.type === "radio" ) { 3498 jQuery.event.add( this, "propertychange._change", function( event ) { 3499 if ( event.originalEvent.propertyName === "checked" ) { 3500 this._just_changed = true; 3501 } 3502 }); 3503 jQuery.event.add( this, "click._change", function( event ) { 3504 if ( this._just_changed && !event.isTrigger ) { 3505 this._just_changed = false; 3506 } 3507 // Allow triggered, simulated change events (#11500) 3508 jQuery.event.simulate( "change", this, event, true ); 3509 }); 3510 } 3511 return false; 3512 } 3513 // Delegated event; lazy-add a change handler on descendant inputs 3514 jQuery.event.add( this, "beforeactivate._change", function( e ) { 3515 var elem = e.target; 3516 3517 if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { 3518 jQuery.event.add( elem, "change._change", function( event ) { 3519 if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { 3520 jQuery.event.simulate( "change", this.parentNode, event, true ); 3521 } 3522 }); 3523 jQuery._data( elem, "changeBubbles", true ); 3524 } 3525 }); 3526 }, 3527 3528 handle: function( event ) { 3529 var elem = event.target; 3530 3531 // Swallow native change events from checkbox/radio, we already triggered them above 3532 if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { 3533 return event.handleObj.handler.apply( this, arguments ); 3534 } 3535 }, 3536 3537 teardown: function() { 3538 jQuery.event.remove( this, "._change" ); 3539 3540 return !rformElems.test( this.nodeName ); 3541 } 3542 }; 3543} 3544 3545// Create "bubbling" focus and blur events 3546if ( !jQuery.support.focusinBubbles ) { 3547 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { 3548 3549 // Attach a single capturing handler while someone wants focusin/focusout 3550 var attaches = 0, 3551 handler = function( event ) { 3552 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); 3553 }; 3554 3555 jQuery.event.special[ fix ] = { 3556 setup: function() { 3557 if ( attaches++ === 0 ) { 3558 document.addEventListener( orig, handler, true ); 3559 } 3560 }, 3561 teardown: function() { 3562 if ( --attaches === 0 ) { 3563 document.removeEventListener( orig, handler, true ); 3564 } 3565 } 3566 }; 3567 }); 3568} 3569 3570jQuery.fn.extend({ 3571 3572 on: function( types, selector, data, fn, /*INTERNAL*/ one ) { 3573 var type, origFn; 3574 3575 // Types can be a map of types/handlers 3576 if ( typeof types === "object" ) { 3577 // ( types-Object, selector, data ) 3578 if ( typeof selector !== "string" ) { 3579 // ( types-Object, data ) 3580 data = data || selector; 3581 selector = undefined; 3582 } 3583 for ( type in types ) { 3584 this.on( type, selector, data, types[ type ], one ); 3585 } 3586 return this; 3587 } 3588 3589 if ( data == null && fn == null ) { 3590 // ( types, fn ) 3591 fn = selector; 3592 data = selector = undefined; 3593 } else if ( fn == null ) { 3594 if ( typeof selector === "string" ) { 3595 // ( types, selector, fn ) 3596 fn = data; 3597 data = undefined; 3598 } else { 3599 // ( types, data, fn ) 3600 fn = data; 3601 data = selector; 3602 selector = undefined; 3603 } 3604 } 3605 if ( fn === false ) { 3606 fn = returnFalse; 3607 } else if ( !fn ) { 3608 return this; 3609 } 3610 3611 if ( one === 1 ) { 3612 origFn = fn; 3613 fn = function( event ) { 3614 // Can use an empty set, since event contains the info 3615 jQuery().off( event ); 3616 return origFn.apply( this, arguments ); 3617 }; 3618 // Use same guid so caller can remove using origFn 3619 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); 3620 } 3621 return this.each( function() { 3622 jQuery.event.add( this, types, fn, data, selector ); 3623 }); 3624 }, 3625 one: function( types, selector, data, fn ) { 3626 return this.on( types, selector, data, fn, 1 ); 3627 }, 3628 off: function( types, selector, fn ) { 3629 var handleObj, type; 3630 if ( types && types.preventDefault && types.handleObj ) { 3631 // ( event ) dispatched jQuery.Event 3632 handleObj = types.handleObj; 3633 jQuery( types.delegateTarget ).off( 3634 handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, 3635 handleObj.selector, 3636 handleObj.handler 3637 ); 3638 return this; 3639 } 3640 if ( typeof types === "object" ) { 3641 // ( types-object [, selector] ) 3642 for ( type in types ) { 3643 this.off( type, selector, types[ type ] ); 3644 } 3645 return this; 3646 } 3647 if ( selector === false || typeof selector === "function" ) { 3648 // ( types [, fn] ) 3649 fn = selector; 3650 selector = undefined; 3651 } 3652 if ( fn === false ) { 3653 fn = returnFalse; 3654 } 3655 return this.each(function() { 3656 jQuery.event.remove( this, types, fn, selector ); 3657 }); 3658 }, 3659 3660 bind: function( types, data, fn ) { 3661 return this.on( types, null, data, fn ); 3662 }, 3663 unbind: function( types, fn ) { 3664 return this.off( types, null, fn ); 3665 }, 3666 3667 delegate: function( selector, types, data, fn ) { 3668 return this.on( types, selector, data, fn ); 3669 }, 3670 undelegate: function( selector, types, fn ) { 3671 // ( namespace ) or ( selector, types [, fn] ) 3672 return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn ); 3673 }, 3674 3675 trigger: function( type, data ) { 3676 return this.each(function() { 3677 jQuery.event.trigger( type, data, this ); 3678 }); 3679 }, 3680 triggerHandler: function( type, data ) { 3681 var elem = this[0]; 3682 if ( elem ) { 3683 return jQuery.event.trigger( type, data, elem, true ); 3684 } 3685 } 3686}); 3687/*! 3688 * Sizzle CSS Selector Engine 3689 * Copyright 2012 jQuery Foundation and other contributors 3690 * Released under the MIT license 3691 * http://sizzlejs.com/ 3692 */ 3693(function( window, undefined ) { 3694 3695var i,
3696 cachedruns, 3697 Expr, 3698 getText, 3699 isXML, 3700 compile, 3701 hasDuplicate, 3702 outermostContext, 3703 3704 // Local document vars 3705 setDocument, 3706 document, 3707 docElem, 3708 documentIsXML, 3709 rbuggyQSA, 3710 rbuggyMatches, 3711 matches, 3712 contains, 3713 sortOrder, 3714 3715 // Instance-specific data 3716 expando = "sizzle" + -(new Date()), 3717 preferredDoc = window.document, 3718 support = {}, 3719 dirruns = 0, 3720 done = 0, 3721 classCache = createCache(), 3722 tokenCache = createCache(), 3723 compilerCache = createCache(), 3724 3725 // General-purpose constants 3726 strundefined = typeof undefined, 3727 MAX_NEGATIVE = 1 << 31, 3728 3729 // Array methods 3730 arr = [], 3731 pop = arr.pop, 3732 push = arr.push, 3733 slice = arr.slice, 3734 // Use a stripped-down indexOf if we can't use a native one 3735 indexOf = arr.indexOf || function( elem ) { 3736 var i = 0, 3737 len = this.length; 3738 for ( ; i < len; i++ ) { 3739 if ( this[i] === elem ) { 3740 return i; 3741 } 3742 } 3743 return -1; 3744 }, 3745 3746 3747 // Regular expressions 3748 3749 // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace 3750 whitespace = "[\\x20\\t\\r\\n\\f]", 3751 // http://www.w3.org/TR/css3-syntax/#characters 3752 characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", 3753 3754 // Loosely modeled on CSS identifier characters 3755 // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors 3756 // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier 3757 identifier = characterEncoding.replace( "w", "w#" ), 3758 3759 // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors 3760 operators = "([*^$|!~]?=)", 3761 attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + 3762 "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", 3763 3764 // Prefer arguments quoted, 3765 // then not containing pseudos/brackets, 3766 // then attribute selectors/non-parenthetical expressions, 3767 // then anything else 3768 // These preferences are here to reduce the number of selectors 3769 // needing tokenize in the PSEUDO preFilter 3770 pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)", 3771 3772 // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter 3773 rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), 3774 3775 rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), 3776 rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ), 3777 rpseudo = new RegExp( pseudos ), 3778 ridentifier = new RegExp( "^" + identifier + "$" ), 3779 3780 matchExpr = { 3781 "ID": new RegExp( "^#(" + characterEncoding + ")" ), 3782 "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), 3783 "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ), 3784 "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), 3785 "ATTR": new RegExp( "^" + attributes ), 3786 "PSEUDO": new RegExp( "^" + pseudos ), 3787 "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + 3788 "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + 3789 "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), 3790 // For use in libraries implementing .is() 3791 // We use this for POS matching in `select` 3792 "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + 3793 whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) 3794 }, 3795 3796 rsibling = /[\x20\t\r\n\f]*[+~]/, 3797 3798 rnative = /^[^{]+\{\s*\[native code/, 3799 3800 // Easily-parseable/retrievable ID or TAG or CLASS selectors 3801 rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, 3802 3803 rinputs = /^(?:input|select|textarea|button)$/i, 3804 rheader = /^h\d$/i, 3805 3806 rescape = /'|\\/g, 3807 rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g, 3808 3809 // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters 3810 runescape = /\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g, 3811 funescape = function( _, escaped ) { 3812 var high = "0x" + escaped - 0x10000; 3813 // NaN means non-codepoint 3814 return high !== high ? 3815 escaped : 3816 // BMP codepoint 3817 high < 0 ? 3818 String.fromCharCode( high + 0x10000 ) : 3819 // Supplemental Plane codepoint (surrogate pair) 3820 String.fromCharCode( high >>
3820 10 | 0xD800, high & 0x3FF | 0xDC00 ); 3821 }; 3822 3823// Use a stripped-down slice if we can't use a native one 3824try { 3825 slice.call( preferredDoc.documentElement.childNodes, 0 )[0].nodeType; 3826} catch ( e ) { 3827 slice = function( i ) { 3828 var elem, 3829 results = []; 3830 while ( (elem = this[i++]) ) { 3831 results.push( elem ); 3832 } 3833 return results; 3834 }; 3835} 3836 3837/** 3838 * For feature detection 3839 * @param {Function} fn The function to test for native support 3840 */ 3841function isNative( fn ) { 3842 return rnative.test( fn + "" ); 3843} 3844 3845/** 3846 * Create key-value caches of limited size 3847 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with 3848 * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) 3849 * deleting the oldest entry 3850 */ 3851function createCache() { 3852 var cache, 3853 keys = []; 3854 3855 return (cache = function( key, value ) { 3856 // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) 3857 if ( keys.push( key += " " ) > Expr.cacheLength ) { 3858 // Only keep the most recent entries 3859 delete cache[ keys.shift() ]; 3860 } 3861 return (cache[ key ] = value); 3862 }); 3863} 3864 3865/** 3866 * Mark a function for special use by Sizzle 3867 * @param {Function} fn The function to mark 3868 */ 3869function markFunction( fn ) { 3870 fn[ expando ] = true; 3871 return fn; 3872} 3873 3874/** 3875 * Support testing using an element 3876 * @param {Function} fn Passed the created div and expects a boolean result 3877 */ 3878function assert( fn ) { 3879 var div = document.createElement("div"); 3880 3881 try { 3882 return fn( div ); 3883 } catch (e) { 3884 return false; 3885 } finally { 3886 // release memory in IE 3887 div = null; 3888 } 3889} 3890 3891function Sizzle( selector, context, results, seed ) { 3892 var match, elem, m, nodeType, 3893 // QSA vars 3894 i, groups, old, nid, newContext, newSelector; 3895 3896 if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { 3897 setDocument( context ); 3898 } 3899 3900 context = context || document; 3901 results = results || []; 3902 3903 if ( !selector || typeof selector !== "string" ) { 3904 return results; 3905 } 3906 3907 if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { 3908 return []; 3909 } 3910 3911 if ( !documentIsXML && !seed ) { 3912 3913 // Shortcuts 3914 if ( (match = rquickExpr.exec( selector )) ) { 3915 // Speed-up: Sizzle("#ID") 3916 if ( (m = match[1]) ) { 3917 if ( nodeType === 9 ) { 3918 elem = context.getElementById( m ); 3919 // Check parentNode to catch when Blackberry 4.6 returns 3920 // nodes that are no longer in the document #6963 3921 if ( elem && elem.parentNode ) { 3922 // Handle the case where IE, Opera, and Webkit return items 3923 // by name instead of ID 3924 if ( elem.id === m ) { 3925 results.push( elem ); 3926 return results; 3927 } 3928 } else { 3929 return results; 3930 } 3931 } else { 3932 // Context is not a document 3933 if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && 3934 contains( context, elem ) && elem.id === m ) { 3935 results.push( elem ); 3936 return results; 3937 } 3938 } 3939 3940 // Speed-up: Sizzle("TAG") 3941 } else if ( match[2] ) { 3942 push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) ); 3943 return results; 3944 3945 // Speed-up: Sizzle(".CLASS") 3946 } else if ( (m = match[3]) && support.getByClassName && context.getElementsByClassName ) { 3947 push.apply( results, slice.call(context.getElementsByClassName( m ), 0) ); 3948 return results; 3949 } 3950 } 3951 3952 // QSA path 3953 if ( support.qsa && !rbuggyQSA.test(selector) ) { 3954 old = true; 3955 nid = expando; 3956 newContext = context; 3957 newSelector = nodeType === 9 && selector; 3958 3959 // qSA works strangely on Element-rooted queries 3960 // We can work around this by specifying an extra ID on the root 3961 // and working up from there (Thanks to Andrew Dupont for the technique) 3962 // IE 8 doesn't work on object elements 3963 if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { 3964 groups = tokenize( selector ); 3965 3966 if ( (old = context.getAttribute("id")) ) { 3967 nid = old.replace( rescape, "\\$&" ); 3968 } else { 3969 context.setAttribute( "id", nid ); 3970 } 3971 nid = "[id='" + nid + "'] "; 3972 3973 i = groups.length; 3974 while ( i-- ) { 3975 groups[i] = nid + toSelector( groups[i] ); 3976 } 3977 newContext = rsibling.test( selector ) && context.parentNode || context; 3978 newSelector = groups.join(","); 3979 } 3980 3981 if ( newSelector ) { 3982 try { 3983 push.apply( results, slice.call( newContext.querySelectorAll( 3984 newSelector 3985 ), 0 ) ); 3986 return results; 3987 } catch(qsaError) { 3988 } finally { 3989 if ( !old ) { 3990 context.removeAttribute("id"); 3991 } 3992 } 3993 } 3994 } 3995 } 3996 3997 // All others 3998 return select( selector.replace( rtrim, "$1" ), context, results, seed ); 3999} 4000 4001/** 4002 * Detect xml
4003 * @param {Element|Object} elem An element or a document 4004 */ 4005isXML = Sizzle.isXML = function( elem ) { 4006 // documentElement is verified for cases where it doesn't yet exist 4007 // (such as loading iframes in IE - #4833) 4008 var documentElement = elem && (elem.ownerDocument || elem).documentElement; 4009 return documentElement ? documentElement.nodeName !== "HTML" : false; 4010}; 4011 4012/** 4013 * Sets document-related variables once based on the current document 4014 * @param {Element|Object} [doc] An element or document object to use to set the document 4015 * @returns {Object} Returns the current document 4016 */ 4017setDocument = Sizzle.setDocument = function( node ) { 4018 var doc = node ? node.ownerDocument || node : preferredDoc; 4019 4020 // If no document and documentElement is available, return 4021 if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { 4022 return document; 4023 } 4024 4025 // Set our document 4026 document = doc; 4027 docElem = doc.documentElement; 4028 4029 // Support tests 4030 documentIsXML = isXML( doc ); 4031 4032 // Check if getElementsByTagName("*") returns only elements 4033 support.tagNameNoComments = assert(function( div ) { 4034 div.appendChild( doc.createComment("") ); 4035 return !div.getElementsByTagName("*").length; 4036 }); 4037 4038 // Check if attributes should be retrieved by attribute nodes 4039 support.attributes = assert(function( div ) { 4040 div.innerHTML = "<select></select>";
4041 var type = typeof div.lastChild.getAttribute("multiple"); 4042 // IE8 returns a string for some attributes even when not present 4043 return type !== "boolean" && type !== "string"; 4044 }); 4045 4046 // Check if getElementsByClassName can be trusted 4047 support.getByClassName = assert(function( div ) { 4048 // Opera can't find a second classname (in 9.6) 4049 div.innerHTML = "<div class='hidden e'></div><div class='hidden'></div>"; 4050 if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) { 4051 return false; 4052 } 4053 4054 // Safari 3.2 caches class attributes and doesn't catch changes 4055 div.lastChild.className = "e"; 4056 return div.getElementsByClassName("e").length === 2; 4057 }); 4058 4059 // Check if getElementById returns elements by name 4060 // Check if getElementsByName privileges form controls or returns elements by ID 4061 support.getByName = assert(function( div ) { 4062 // Inject content 4063 div.id = expando + 0; 4064 div.innerHTML = "<a name='" + expando + "'></a><div name='" + expando + "'></div>"; 4065 docElem.insertBefore( div, docElem.firstChild ); 4066 4067 // Test 4068 var pass = doc.getElementsByName && 4069 // buggy browsers will return fewer than the correct 2 4070 doc.getElementsByName( expando ).length === 2 + 4071 // buggy browsers will return more than the correct 0 4072 doc.getElementsByName( expando + 0 ).length; 4073 support.getIdNotName = !doc.getElementById( expando ); 4074 4075 // Cleanup 4076 docElem.removeChild( div ); 4077 4078 return pass; 4079 }); 4080 4081 // IE6/7 return modified attributes 4082 Expr.attrHandle = assert(function( div ) { 4083 div.innerHTML = "<a href='#'></a>"; 4084 return div.firstChild && typeof div.firstChild.getAttribute !== strundefined && 4085 div.firstChild.getAttribute("href") === "#"; 4086 }) ? 4087 {} : 4088 { 4089 "href": function( elem ) { 4090 return elem.getAttribute( "href", 2 ); 4091 }, 4092 "type": function( elem ) { 4093 return elem.getAttribute("type"); 4094 } 4095 }; 4096 4097 // ID find and filter 4098 if ( support.getIdNotName ) { 4099 Expr.find["ID"] = function( id, context ) { 4100 if ( typeof context.getElementById !== strundefined && !documentIsXML ) { 4101 var m = context.getElementById( id ); 4102 // Check parentNode to catch when Blackberry 4.6 returns 4103 // nodes that are no longer in the document #6963 4104 return m && m.parentNode ? [m] : []; 4105 } 4106 }; 4107 Expr.filter["ID"] = function( id ) { 4108 var attrId = id.replace( runescape, funescape ); 4109 return function( elem ) { 4110 return elem.getAttribute("id") === attrId; 4111 }; 4112 }; 4113 } else { 4114 Expr.find["ID"] = function( id, context ) { 4115 if ( typeof context.getElementById !== strundefined && !documentIsXML ) { 4116 var m = context.getElementById( id ); 4117 4118 return m ? 4119 m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ? 4120 [m] : 4121 undefined : 4122 []; 4123 } 4124 }; 4125 Expr.filter["ID"] = function( id ) { 4126 var attrId = id.replace( runescape, funescape ); 4127 return function( elem ) { 4128 var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); 4129 return node && node.value === attrId; 4130 }; 4131 }; 4132 } 4133 4134 // Tag 4135 Expr.find["TAG"] = support.tagNameNoComments ? 4136 function( tag, context ) { 4137 if ( typeof context.getElementsByTagName !== strundefined ) { 4138 return context.getElementsByTagName( tag ); 4139 } 4140 } : 4141 function( tag, context ) { 4142 var elem, 4143 tmp = [], 4144 i = 0, 4145 results = context.getElementsByTagName( tag ); 4146 4147 // Filter out possible comments 4148 if ( tag === "*" ) { 4149 while ( (elem = results[i++]) ) { 4150 if ( elem.nodeType === 1 ) { 4151 tmp.push( elem ); 4152 } 4153 } 4154 4155 return tmp; 4156 } 4157 return results; 4158 }; 4159 4160 // Name 4161 Expr.find["NAME"] = support.getByName && function( tag, context ) { 4162 if ( typeof context.getElementsByName !== strundefined ) { 4163 return context.getElementsByName( name ); 4164 } 4165 }; 4166 4167 // Class 4168 Expr.find["CLASS"] = support.getByClassName && function( className, context ) { 4169 if ( typeof context.getElementsByClassName !== strundefined && !documentIsXML ) { 4170 return context.getElementsByClassName( className ); 4171 } 4172 }; 4173 4174 // QSA and matchesSelector support 4175 4176 // matchesSelector(:active) reports false when true (IE9/Opera 11.5) 4177 rbuggyMatches = []; 4178 4179 // qSa(:focus) reports false when true (Chrome 21),
4180 // no need to also add to buggyMatches since matches checks buggyQSA 4181 // A support test would require too much code (would include document ready) 4182 rbuggyQSA = [ ":focus" ]; 4183 4184 if ( (support.qsa = isNative(doc.querySelectorAll)) ) { 4185 // Build QSA regex 4186 // Regex strategy adopted from Diego Perini 4187 assert(function( div ) { 4188 // Select is set to empty string on purpose 4189 // This is to test IE's treatment of not explictly 4190 // setting a boolean content attribute, 4191 // since its presence should be enough 4192 // http://bugs.jquery.com/ticket/12359 4193 div.innerHTML = "<select><option selected=''></option></select>"; 4194 4195 // IE8 - Some boolean attributes are not treated correctly 4196 if ( !div.querySelectorAll("[selected]").length ) { 4197 rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" ); 4198 } 4199 4200 // Webkit/Opera - :checked should return selected option elements 4201 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked 4202 // IE8 throws error here and will not see later tests 4203 if ( !div.querySelectorAll(":checked").length ) { 4204 rbuggyQSA.push(":checked"); 4205 } 4206 }); 4207 4208 assert(function( div ) { 4209 4210 // Opera 10-12/IE8 - ^= $= *= and empty values 4211 // Should not select anything 4212 div.innerHTML = "<input type='hidden' i=''/>"; 4213 if ( div.querySelectorAll("[i^='']").length ) { 4214 rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" ); 4215 } 4216 4217 // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) 4218 // IE8 throws error here and will not see later tests 4219 if ( !div.querySelectorAll(":enabled").length ) { 4220 rbuggyQSA.push( ":enabled", ":disabled" ); 4221 } 4222 4223 // Opera 10-11 does not throw on post-comma invalid pseudos 4224 div.querySelectorAll("*,:x"); 4225 rbuggyQSA.push(",.*:"); 4226 }); 4227 } 4228 4229 if ( (support.matchesSelector = isNative( (matches = docElem.matchesSelector || 4230 docElem.mozMatchesSelector || 4231 docElem.webkitMatchesSelector || 4232 docElem.oMatchesSelector || 4233 docElem.msMatchesSelector) )) ) { 4234 4235 assert(function( div ) { 4236 // Check to see if it's possible to do matchesSelector 4237 // on a disconnected node (IE 9) 4238 support.disconnectedMatch = matches.call( div, "div" ); 4239 4240 // This should fail with an exception 4241 // Gecko does not error, returns false instead 4242 matches.call( div, "[s!='']:x" ); 4243 rbuggyMatches.push( "!=", pseudos ); 4244 }); 4245 } 4246 4247 rbuggyQSA = new RegExp( rbuggyQSA.join("|") ); 4248 rbuggyMatches = new RegExp( rbuggyMatches.join("|") ); 4249 4250 // Element contains another 4251 // Purposefully does not implement inclusive descendent 4252 // As in, an element does not contain itself 4253 contains = isNative(docElem.contains) || docElem.compareDocumentPosition ? 4254 function( a, b ) { 4255 var adown = a.nodeType === 9 ? a.documentElement : a, 4256 bup = b && b.parentNode; 4257 return a === bup || !!( bup && bup.nodeType === 1 && ( 4258 adown.contains ? 4259 adown.contains( bup ) : 4260 a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 4261 )); 4262 } : 4263 function( a, b ) { 4264 if ( b ) { 4265 while ( (b = b.parentNode) ) { 4266 if ( b === a ) { 4267 return true; 4268 } 4269 } 4270 } 4271 return false; 4272 }; 4273 4274 // Document order sorting 4275 sortOrder = docElem.compareDocumentPosition ? 4276 function( a, b ) { 4277 var compare; 4278 4279 if ( a === b ) { 4280 hasDuplicate = true; 4281 return 0; 4282 } 4283 4284 if ( (compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b )) ) { 4285 if ( compare & 1 || a.parentNode && a.parentNode.nodeType === 11 ) { 4286 if ( a === doc || contains( preferredDoc, a ) ) { 4287 return -1; 4288 } 4289 if ( b === doc || contains( preferredDoc, b ) ) { 4290 return 1; 4291 } 4292 return 0; 4293 } 4294 return compare & 4 ? -1 : 1; 4295 } 4296 4297 return a.compareDocumentPosition ? -1 : 1; 4298 } : 4299 function( a, b ) { 4300 var cur, 4301 i = 0, 4302 aup = a.parentNode, 4303 bup = b.parentNode, 4304 ap = [ a ], 4305 bp = [ b ]; 4306 4307 // Exit early if the nodes are identical 4308 if ( a === b ) { 4309 hasDuplicate = true; 4310 return 0; 4311 4312 // Parentless nodes are either documents or disconnected 4313 } else if ( !aup || !bup ) { 4314 return a === doc ? -1 : 4315 b === doc ? 1 : 4316 aup ? -1 : 4317 bup ? 1 : 4318 0; 4319 4320 // If the nodes are siblings, we can do a quick check 4321 } else if ( aup === bup ) { 4322 return siblingCheck( a, b ); 4323 } 4324 4325 // Otherwise we need full lists of their ancestors for comparison 4326 cur = a; 4327 while ( (cur = cur.parentNode) ) { 4328 ap.unshift( cur ); 4329 } 4330 cur = b; 4331 while ( (cur = cur.parentNode) ) { 4332 bp.unshift( cur ); 4333 } 4334 4335 // Walk down the tree looking for a discrepancy 4336 while ( ap[i] === bp[i] ) { 4337 i++; 4338 } 4339 4340 return i ? 4341 // Do a sibling check if the nodes have a common ancestor 4342 siblingCheck( ap[i], bp[i] ) : 4343 4344 // Otherwise nodes in our document sort first 4345 ap[i] === preferredDoc ? -1 : 4346 bp[i] === preferredDoc ? 1 : 4347 0; 4348 }; 4349 4350 // Always assume the presence of duplicates if sort doesn't 4351 // pass them to our comparison function (as in Google Chrome). 4352 hasDuplicate = false;
4353 [0, 0].sort( sortOrder ); 4354 support.detectDuplicates = hasDuplicate; 4355 4356 return document; 4357}; 4358 4359Sizzle.matches = function( expr, elements ) { 4360 return Sizzle( expr, null, null, elements ); 4361}; 4362 4363Sizzle.matchesSelector = function( elem, expr ) { 4364 // Set document vars if needed 4365 if ( ( elem.ownerDocument || elem ) !== document ) { 4366 setDocument( elem ); 4367 } 4368 4369 // Make sure that attribute selectors are quoted 4370 expr = expr.replace( rattributeQuotes, "='$1']" ); 4371 4372 // rbuggyQSA always contains :focus, so no need for an existence check 4373 if ( support.matchesSelector && !documentIsXML && (!rbuggyMatches || !rbuggyMatches.test(expr)) && !rbuggyQSA.test(expr) ) { 4374 try { 4375 var ret = matches.call( elem, expr ); 4376 4377 // IE 9's matchesSelector returns false on disconnected nodes 4378 if ( ret || support.disconnectedMatch || 4379 // As well, disconnected nodes are said to be in a document 4380 // fragment in IE 9 4381 elem.document && elem.document.nodeType !== 11 ) { 4382 return ret; 4383 } 4384 } catch(e) {} 4385 } 4386 4387 return Sizzle( expr, document, null, [elem] ).length > 0; 4388}; 4389 4390Sizzle.contains = function( context, elem ) { 4391 // Set document vars if needed 4392 if ( ( context.ownerDocument || context ) !== document ) { 4393 setDocument( context ); 4394 } 4395 return contains( context, elem ); 4396}; 4397 4398Sizzle.attr = function( elem, name ) { 4399 var val; 4400 4401 // Set document vars if needed 4402 if ( ( elem.ownerDocument || elem ) !== document ) { 4403 setDocument( elem ); 4404 } 4405 4406 if ( !documentIsXML ) { 4407 name = name.toLowerCase(); 4408 } 4409 if ( (val = Expr.attrHandle[ name ]) ) { 4410 return val( elem ); 4411 } 4412 if ( documentIsXML || support.attributes ) { 4413 return elem.getAttribute( name ); 4414 } 4415 return ( (val = elem.getAttributeNode( name )) || elem.getAttribute( name ) ) && elem[ name ] === true ? 4416 name : 4417 val && val.specified ? val.value : null; 4418}; 4419 4420Sizzle.error = function( msg ) { 4421 throw new Error( "Syntax error, unrecognized expression: " + msg ); 4422}; 4423 4424// Document sorting and removing duplicates 4425Sizzle.uniqueSort = function( results ) { 4426 var elem, 4427 duplicates = [], 4428 i = 1, 4429 j = 0; 4430 4431 // Unless we *know* we can detect duplicates, assume their presence 4432 hasDuplicate = !support.detectDuplicates; 4433 results.sort( sortOrder ); 4434 4435 if ( hasDuplicate ) { 4436 for ( ; (elem = results[i]); i++ ) { 4437 if ( elem === results[ i - 1 ] ) { 4438 j = duplicates.push( i ); 4439 } 4440 } 4441 while ( j-- ) { 4442 results.splice( duplicates[ j ], 1 ); 4443 } 4444 } 4445 4446 return results; 4447}; 4448 4449function siblingCheck( a, b ) { 4450 var cur = b && a, 4451 diff = cur && ( ~b.sourceIndex || MAX_NEGATIVE ) - ( ~a.sourceIndex || MAX_NEGATIVE ); 4452 4453 // Use IE sourceIndex if available on both nodes 4454 if ( diff ) { 4455 return diff; 4456 } 4457 4458 // Check if b follows a 4459 if ( cur ) { 4460 while ( (cur = cur.nextSibling) ) { 4461 if ( cur === b ) { 4462 return -1; 4463 } 4464 } 4465 } 4466 4467 return a ? 1 : -1; 4468} 4469 4470// Returns a function to use in pseudos for input types 4471function createInputPseudo( type ) { 4472 return function( elem ) { 4473 var name = elem.nodeName.toLowerCase(); 4474 return name === "input" && elem.type === type; 4475 }; 4476} 4477 4478// Returns a function to use in pseudos for buttons 4479function createButtonPseudo( type ) { 4480 return function( elem ) { 4481 var name = elem.nodeName.toLowerCase(); 4482 return (name === "input" || name === "button") && elem.type === type; 4483 }; 4484} 4485 4486// Returns a function to use in pseudos for positionals 4487function createPositionalPseudo( fn ) { 4488 return markFunction(function( argument ) { 4489 argument = +argument; 4490 return markFunction(function( seed, matches ) { 4491 var j, 4492 matchIndexes = fn( [], seed.length, argument ), 4493 i = matchIndexes.length; 4494 4495 // Match elements found at the specified indexes 4496 while ( i-- ) { 4497 if ( seed[ (j = matchIndexes[i]) ] ) { 4498 seed[j] = !(matches[j] = seed[j]); 4499 } 4500 } 4501 }); 4502 }); 4503} 4504 4505/** 4506 * Utility function for retrieving the text value of an array of DOM nodes 4507 * @param {Array|Element} elem 4508 */ 4509getText = Sizzle.getText = function( elem ) { 4510 var node, 4511 ret = "", 4512 i = 0, 4513 nodeType = elem.nodeType; 4514 4515 if ( !nodeType ) { 4516 // If no nodeType, this is expected to be an array 4517 for ( ; (node = elem[i]); i++ ) { 4518 // Do not traverse comment nodes 4519 ret += getText( node ); 4520 } 4521 } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { 4522 // Use textContent for elements 4523 // innerText usage removed for consistency of new lines (see #11153) 4524 if ( typeof elem.textContent === "string" ) { 4525 return elem.textContent; 4526 } else { 4527 // Traverse its children 4528 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { 4529 ret += getText( elem ); 4530 } 4531 } 4532 } else if ( nodeType === 3 || nodeType === 4 ) { 4533 return elem.nodeValue; 4534 } 4535 // Do not include comment or processing instruction nodes 4536 4537 return ret; 4538}; 4539 4540Expr = Sizzle.selectors = { 4541
vendor: 20,551 bytes, lines 4542-5272
4542 // Can be adjusted by the user 4543 cacheLength: 50, 4544 4545 createPseudo: markFunction, 4546 4547 match: matchExpr, 4548 4549 find: {}, 4550 4551 relative: { 4552 ">": { dir: "parentNode", first: true }, 4553 " ": { dir: "parentNode" }, 4554 "+": { dir: "previousSibling", first: true }, 4555 "~": { dir: "previousSibling" } 4556 }, 4557 4558 preFilter: { 4559 "ATTR": function( match ) { 4560 match[1] = match[1].replace( runescape, funescape ); 4561 4562 // Move the given value to match[3] whether quoted or unquoted 4563 match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape ); 4564 4565 if ( match[2] === "~=" ) { 4566 match[3] = " " + match[3] + " "; 4567 } 4568 4569 return match.slice( 0, 4 ); 4570 }, 4571 4572 "CHILD": function( match ) { 4573 /* matches from matchExpr["CHILD"] 4574 1 type (only|nth|...) 4575 2 what (child|of-type) 4576 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) 4577 4 xn-component of xn+y argument ([+-]?\d*n|) 4578 5 sign of xn-component 4579 6 x of xn-component 4580 7 sign of y-component 4581 8 y of y-component 4582 */ 4583 match[1] = match[1].toLowerCase(); 4584 4585 if ( match[1].slice( 0, 3 ) === "nth" ) { 4586 // nth-* requires argument 4587 if ( !match[3] ) { 4588 Sizzle.error( match[0] ); 4589 } 4590 4591 // numeric x and y parameters for Expr.filter.CHILD 4592 // remember that false/true cast respectively to 0/1 4593 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); 4594 match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); 4595 4596 // other types prohibit arguments 4597 } else if ( match[3] ) { 4598 Sizzle.error( match[0] ); 4599 } 4600 4601 return match; 4602 }, 4603 4604 "PSEUDO": function( match ) { 4605 var excess, 4606 unquoted = !match[5] && match[2]; 4607 4608 if ( matchExpr["CHILD"].test( match[0] ) ) { 4609 return null; 4610 } 4611 4612 // Accept quoted arguments as-is 4613 if ( match[4] ) { 4614 match[2] = match[4]; 4615 4616 // Strip excess characters from unquoted arguments 4617 } else if ( unquoted && rpseudo.test( unquoted ) && 4618 // Get excess from tokenize (recursively) 4619 (excess = tokenize( unquoted, true )) && 4620 // advance to the next closing parenthesis 4621 (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { 4622 4623 // excess is a negative index 4624 match[0] = match[0].slice( 0, excess ); 4625 match[2] = unquoted.slice( 0, excess ); 4626 } 4627 4628 // Return only captures needed by the pseudo filter method (type and argument) 4629 return match.slice( 0, 3 ); 4630 } 4631 }, 4632 4633 filter: { 4634 4635 "TAG": function( nodeName ) { 4636 if ( nodeName === "*" ) { 4637 return function() { return true; }; 4638 } 4639 4640 nodeName = nodeName.replace( runescape, funescape ).toLowerCase(); 4641 return function( elem ) { 4642 return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; 4643 }; 4644 }, 4645 4646 "CLASS": function( className ) { 4647 var pattern = classCache[ className + " " ]; 4648 4649 return pattern || 4650 (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && 4651 classCache( className, function( elem ) { 4652 return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" ); 4653 }); 4654 }, 4655 4656 "ATTR": function( name, operator, check ) { 4657 return function( elem ) { 4658 var result = Sizzle.attr( elem, name ); 4659 4660 if ( result == null ) { 4661 return operator === "!="; 4662 } 4663 if ( !operator ) { 4664 return true; 4665 } 4666 4667 result += ""; 4668 4669 return operator === "=" ? result === check : 4670 operator === "!=" ? result !== check : 4671 operator === "^=" ? check && result.indexOf( check ) === 0 : 4672 operator === "*=" ? check && result.indexOf( check ) > -1 : 4673 operator === "$=" ? check && result.slice( -check.length ) === check : 4674 operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : 4675 operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : 4676 false; 4677 }; 4678 }, 4679 4680 "CHILD": function( type, what, argument, first, last ) { 4681 var simple = type.slice( 0, 3 ) !== "nth", 4682 forward = type.slice( -4 ) !== "last", 4683 ofType = what === "of-type"; 4684 4685 return first === 1 && last === 0 ? 4686 4687 // Shortcut for :nth-*(n) 4688 function( elem ) { 4689 return !!elem.parentNode; 4690 } : 4691 4692 function( elem, context, xml ) { 4693 var cache, outerCache, node, diff, nodeIndex, start, 4694 dir = simple !== forward ? "nextSibling" : "previousSibling", 4695 parent = elem.parentNode, 4696 name = ofType && elem.nodeName.toLowerCase(), 4697 useCache = !xml && !ofType; 4698 4699 if ( parent ) { 4700 4701 // :(first|last|only)-(child|of-type) 4702 if ( simple ) { 4703 while ( dir ) { 4704 node = elem; 4705 while ( (node = node[ dir ]) ) { 4706 if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { 4707 return false; 4708 } 4709 } 4710 // Reverse direction for :only-* (if we haven't yet done so) 4711 start = dir = type === "only" && !start && "nextSibling"; 4712 } 4713 return true; 4714 } 4715 4716 start = [ forward ? parent.firstChild : parent.lastChild ]; 4717 4718 // non-xml :nth-child(...) stores cache data on `parent` 4719 if ( forward && useCache ) { 4720 // Seek `elem` from a previously-cached index 4721 outerCache = parent[ expando ] || (parent[ expando ] = {}); 4722 cache = outerCache[ type ] || []; 4723 nodeIndex = cache[0] === dirruns && cache[1]; 4724 diff = cache[0] === dirruns && cache[2]; 4725 node = nodeIndex && parent.childNodes[ nodeIndex ]; 4726 4727 while ( (node = ++nodeIndex && node && node[ dir ] || 4728 4729 // Fallback to seeking `elem` from the start 4730 (diff = nodeIndex = 0) || start.pop()) ) { 4731 4732 // When found, cache indexes on `parent` and break 4733 if ( node.nodeType === 1 && ++diff && node === elem ) { 4734 outerCache[ type ] = [ dirruns, nodeIndex, diff ]; 4735 break; 4736 } 4737 } 4738 4739 // Use previously-cached element index if available 4740 } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { 4741 diff = cache[1]; 4742 4743 // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) 4744 } else { 4745 // Use the same loop as above to seek `elem` from the start 4746 while ( (node = ++nodeIndex && node && node[ dir ] || 4747 (diff = nodeIndex = 0) || start.pop()) ) { 4748 4749 if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { 4750 // Cache the index of each encountered element 4751 if ( useCache ) { 4752 (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; 4753 } 4754 4755 if ( node === elem ) { 4756 break; 4757 } 4758 } 4759 } 4760 } 4761 4762 // Incorporate the offset, then check against cycle size 4763 diff -= last; 4764 return diff === first || ( diff % first === 0 && diff / first >= 0 ); 4765 } 4766 }; 4767 }, 4768 4769 "PSEUDO": function( pseudo, argument ) { 4770 // pseudo-class names are case-insensitive 4771 // http://www.w3.org/TR/selectors/#pseudo-classes 4772 // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters 4773 // Remember that setFilters inherits from pseudos 4774 var args, 4775 fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || 4776 Sizzle.error( "unsupported pseudo: " + pseudo ); 4777 4778 // The user may use createPseudo to indicate that 4779 // arguments are needed to create the filter function 4780 // just as Sizzle does 4781 if ( fn[ expando ] ) { 4782 return fn( argument ); 4783 } 4784 4785 // But maintain support for old signatures 4786 if ( fn.length > 1 ) { 4787 args = [ pseudo, pseudo, "", argument ]; 4788 return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? 4789 markFunction(function( seed, matches ) { 4790 var idx, 4791 matched = fn( seed, argument ), 4792 i = matched.length; 4793 while ( i-- ) { 4794 idx = indexOf.call( seed, matched[i] ); 4795 seed[ idx ] = !( matches[ idx ] = matched[i] ); 4796 } 4797 }) : 4798 function( elem ) { 4799 return fn( elem, 0, args ); 4800 }; 4801 } 4802 4803 return fn; 4804 } 4805 }, 4806 4807 pseudos: { 4808 // Potentially complex pseudos 4809 "not": markFunction(function( selector ) { 4810 // Trim the selector passed to compile 4811 // to avoid treating leading and trailing 4812 // spaces as combinators 4813 var input = [], 4814 results = [], 4815 matcher = compile( selector.replace( rtrim, "$1" ) ); 4816 4817 return matcher[ expando ] ? 4818 markFunction(function( seed, matches, context, xml ) { 4819 var elem, 4820 unmatched = matcher( seed, null, xml, [] ), 4821 i = seed.length; 4822 4823 // Match elements unmatched by `matcher` 4824 while ( i-- ) { 4825 if ( (elem = unmatched[i]) ) { 4826 seed[i] = !(matches[i] = elem); 4827 } 4828 } 4829 }) : 4830 function( elem, context, xml ) { 4831 input[0] = elem; 4832 matcher( input, null, xml, results ); 4833 return !results.pop(); 4834 }; 4835 }), 4836 4837 "has": markFunction(function( selector ) { 4838 return function( elem ) { 4839 return Sizzle( selector, elem ).length > 0; 4840 }; 4841 }), 4842 4843 "contains": markFunction(function( text ) { 4844 return function( elem ) { 4845 return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; 4846 }; 4847 }), 4848 4849 // "Whether an element is represented by a :lang() selector 4850 // is based solely on the element's language value 4851 // being equal to the identifier C, 4852 // or beginning with the identifier C immediately followed by "-". 4853 // The matching of C against the element's language value is performed case-insensitively. 4854 // The identifier C does not have to be a valid language name." 4855 // http://www.w3.org/TR/selectors/#lang-pseudo 4856 "lang": markFunction( function( lang ) { 4857 // lang value must be a valid identifider 4858 if ( !ridentifier.test(lang || "") ) { 4859 Sizzle.error( "unsupported lang: " + lang ); 4860 } 4861 lang = lang.replace( runescape, funescape ).toLowerCase(); 4862 return function( elem ) { 4863 var elemLang; 4864 do { 4865 if ( (elemLang = documentIsXML ? 4866 elem.getAttribute("xml:lang") || elem.getAttribute("lang") : 4867 elem.lang) ) { 4868 4869 elemLang = elemLang.toLowerCase(); 4870 return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; 4871 } 4872 } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); 4873 return false; 4874 }; 4875 }), 4876 4877 // Miscellaneous 4878 "target": function( elem ) { 4879 var hash = window.location && window.location.hash; 4880 return hash && hash.slice( 1 ) === elem.id; 4881 }, 4882 4883 "root": function( elem ) { 4884 return elem === docElem; 4885 }, 4886 4887 "focus": function( elem ) { 4888 return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); 4889 }, 4890 4891 // Boolean properties 4892 "enabled": function( elem ) { 4893 return elem.disabled === false; 4894 }, 4895 4896 "disabled": function( elem ) { 4897 return elem.disabled === true; 4898 }, 4899 4900 "checked": function( elem ) { 4901 // In CSS3, :checked should return both checked and selected elements 4902 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked 4903 var nodeName = elem.nodeName.toLowerCase(); 4904 return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); 4905 }, 4906 4907 "selected": function( elem ) { 4908 // Accessing this property makes selected-by-default 4909 // options in Safari work properly 4910 if ( elem.parentNode ) { 4911 elem.parentNode.selectedIndex; 4912 } 4913 4914 return elem.selected === true; 4915 }, 4916 4917 // Contents 4918 "empty": function( elem ) { 4919 // http://www.w3.org/TR/selectors/#empty-pseudo 4920 // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), 4921 // not comment, processing instructions, or others 4922 // Thanks to Diego Perini for the nodeName shortcut 4923 // Greater than "@" means alpha characters (specifically not starting with "#" or "?") 4924 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { 4925 if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) { 4926 return false; 4927 } 4928 } 4929 return true; 4930 }, 4931 4932 "parent": function( elem ) { 4933 return !Expr.pseudos["empty"]( elem ); 4934 }, 4935 4936 // Element/input types 4937 "header": function( elem ) { 4938 return rheader.test( elem.nodeName ); 4939 }, 4940 4941 "input": function( elem ) { 4942 return rinputs.test( elem.nodeName ); 4943 }, 4944 4945 "button": function( elem ) { 4946 var name = elem.nodeName.toLowerCase(); 4947 return name === "input" && elem.type === "button" || name === "button"; 4948 }, 4949 4950 "text": function( elem ) { 4951 var attr; 4952 // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) 4953 // use getAttribute instead to test this case 4954 return elem.nodeName.toLowerCase() === "input" && 4955 elem.type === "text" && 4956 ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type ); 4957 }, 4958 4959 // Position-in-collection 4960 "first": createPositionalPseudo(function() { 4961 return [ 0 ]; 4962 }), 4963 4964 "last": createPositionalPseudo(function( matchIndexes, length ) { 4965 return [ length - 1 ]; 4966 }), 4967 4968 "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { 4969 return [ argument < 0 ? argument + length : argument ]; 4970 }), 4971 4972 "even": createPositionalPseudo(function( matchIndexes, length ) { 4973 var i = 0; 4974 for ( ; i < length; i += 2 ) { 4975 matchIndexes.push( i ); 4976 } 4977 return matchIndexes; 4978 }), 4979 4980 "odd": createPositionalPseudo(function( matchIndexes, length ) { 4981 var i = 1; 4982 for ( ; i < length; i += 2 ) { 4983 matchIndexes.push( i ); 4984 } 4985 return matchIndexes; 4986 }), 4987 4988 "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { 4989 var i = argument < 0 ? argument + length : argument; 4990 for ( ; --i >= 0; ) { 4991 matchIndexes.push( i ); 4992 } 4993 return matchIndexes; 4994 }), 4995 4996 "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { 4997 var i = argument < 0 ? argument + length : argument; 4998 for ( ; ++i < length; ) { 4999 matchIndexes.push( i ); 5000 } 5001 return matchIndexes; 5002 }) 5003 } 5004}; 5005 5006// Add button/input type pseudos 5007for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { 5008 Expr.pseudos[ i ] = createInputPseudo( i ); 5009} 5010for ( i in { submit: true, reset: true } ) { 5011 Expr.pseudos[ i ] = createButtonPseudo( i ); 5012} 5013 5014function tokenize( selector, parseOnly ) { 5015 var matched, match, tokens, type, 5016 soFar, groups, preFilters, 5017 cached = tokenCache[ selector + " " ]; 5018 5019 if ( cached ) { 5020 return parseOnly ? 0 : cached.slice( 0 ); 5021 } 5022 5023 soFar = selector; 5024 groups = []; 5025 preFilters = Expr.preFilter; 5026 5027 while ( soFar ) { 5028 5029 // Comma and first run 5030 if ( !matched || (match = rcomma.exec( soFar )) ) { 5031 if ( match ) { 5032 // Don't consume trailing commas as valid 5033 soFar = soFar.slice( match[0].length ) || soFar; 5034 } 5035 groups.push( tokens = [] ); 5036 } 5037 5038 matched = false; 5039 5040 // Combinators 5041 if ( (match = rcombinators.exec( soFar )) ) { 5042 matched = match.shift(); 5043 tokens.push( { 5044 value: matched, 5045 // Cast descendant combinators to space 5046 type: match[0].replace( rtrim, " " ) 5047 } ); 5048 soFar = soFar.slice( matched.length ); 5049 } 5050 5051 // Filters 5052 for ( type in Expr.filter ) { 5053 if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || 5054 (match = preFilters[ type ]( match ))) ) { 5055 matched = match.shift(); 5056 tokens.push( { 5057 value: matched, 5058 type: type, 5059 matches: match 5060 } ); 5061 soFar = soFar.slice( matched.length ); 5062 } 5063 } 5064 5065 if ( !matched ) { 5066 break; 5067 } 5068 } 5069 5070 // Return the length of the invalid excess 5071 // if we're just parsing 5072 // Otherwise, throw an error or return tokens 5073 return parseOnly ? 5074 soFar.length : 5075 soFar ? 5076 Sizzle.error( selector ) : 5077 // Cache the tokens 5078 tokenCache( selector, groups ).slice( 0 ); 5079} 5080 5081function toSelector( tokens ) { 5082 var i = 0, 5083 len = tokens.length, 5084 selector = ""; 5085 for ( ; i < len; i++ ) { 5086 selector += tokens[i].value; 5087 } 5088 return selector; 5089} 5090 5091function addCombinator( matcher, combinator, base ) { 5092 var dir = combinator.dir, 5093 checkNonElements = base && dir === "parentNode", 5094 doneName = done++; 5095 5096 return combinator.first ? 5097 // Check against closest ancestor/preceding element 5098 function( elem, context, xml ) { 5099 while ( (elem = elem[ dir ]) ) { 5100 if ( elem.nodeType === 1 || checkNonElements ) { 5101 return matcher( elem, context, xml ); 5102 } 5103 } 5104 } : 5105 5106 // Check against all ancestor/preceding elements 5107 function( elem, context, xml ) { 5108 var data, cache, outerCache, 5109 dirkey = dirruns + " " + doneName; 5110 5111 // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching 5112 if ( xml ) { 5113 while ( (elem = elem[ dir ]) ) { 5114 if ( elem.nodeType === 1 || checkNonElements ) { 5115 if ( matcher( elem, context, xml ) ) { 5116 return true; 5117 } 5118 } 5119 } 5120 } else { 5121 while ( (elem = elem[ dir ]) ) { 5122 if ( elem.nodeType === 1 || checkNonElements ) { 5123 outerCache = elem[ expando ] || (elem[ expando ] = {}); 5124 if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) { 5125 if ( (data = cache[1]) === true || data === cachedruns ) { 5126 return data === true; 5127 } 5128 } else { 5129 cache = outerCache[ dir ] = [ dirkey ]; 5130 cache[1] = matcher( elem, context, xml ) || cachedruns; 5131 if ( cache[1] === true ) { 5132 return true; 5133 } 5134 } 5135 } 5136 } 5137 } 5138 }; 5139} 5140 5141function elementMatcher( matchers ) { 5142 return matchers.length > 1 ? 5143 function( elem, context, xml ) { 5144 var i = matchers.length; 5145 while ( i-- ) { 5146 if ( !matchers[i]( elem, context, xml ) ) { 5147 return false; 5148 } 5149 } 5150 return true; 5151 } : 5152 matchers[0]; 5153} 5154 5155function condense( unmatched, map, filter, context, xml ) { 5156 var elem, 5157 newUnmatched = [], 5158 i = 0, 5159 len = unmatched.length, 5160 mapped = map != null; 5161 5162 for ( ; i < len; i++ ) { 5163 if ( (elem = unmatched[i]) ) { 5164 if ( !filter || filter( elem, context, xml ) ) { 5165 newUnmatched.push( elem ); 5166 if ( mapped ) { 5167 map.push( i ); 5168 } 5169 } 5170 } 5171 } 5172 5173 return newUnmatched; 5174} 5175 5176function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { 5177 if ( postFilter && !postFilter[ expando ] ) { 5178 postFilter = setMatcher( postFilter ); 5179 } 5180 if ( postFinder && !postFinder[ expando ] ) { 5181 postFinder = setMatcher( postFinder, postSelector ); 5182 } 5183 return markFunction(function( seed, results, context, xml ) { 5184 var temp, i, elem, 5185 preMap = [], 5186 postMap = [], 5187 preexisting = results.length, 5188 5189 // Get initial elements from seed or context 5190 elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), 5191 5192 // Prefilter to get matcher input, preserving a map for seed-results synchronization 5193 matcherIn = preFilter && ( seed || !selector ) ? 5194 condense( elems, preMap, preFilter, context, xml ) : 5195 elems, 5196 5197 matcherOut = matcher ? 5198 // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, 5199 postFinder || ( seed ? preFilter : preexisting || postFilter ) ? 5200 5201 // ...intermediate processing is necessary 5202 [] : 5203 5204 // ...otherwise use results directly 5205 results : 5206 matcherIn; 5207 5208 // Find primary matches 5209 if ( matcher ) { 5210 matcher( matcherIn, matcherOut, context, xml ); 5211 } 5212 5213 // Apply postFilter 5214 if ( postFilter ) { 5215 temp = condense( matcherOut, postMap ); 5216 postFilter( temp, [], context, xml ); 5217 5218 // Un-match failing elements by moving them back to matcherIn 5219 i = temp.length; 5220 while ( i-- ) { 5221 if ( (elem = temp[i]) ) { 5222 matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); 5223 } 5224 } 5225 } 5226 5227 if ( seed ) { 5228 if ( postFinder || preFilter ) { 5229 if ( postFinder ) { 5230 // Get the final matcherOut by condensing this intermediate into postFinder contexts 5231 temp = []; 5232 i = matcherOut.length; 5233 while ( i-- ) { 5234 if ( (elem = matcherOut[i]) ) { 5235 // Restore matcherIn since elem is not yet a final match 5236 temp.push( (matcherIn[i] = elem) ); 5237 } 5238 } 5239 postFinder( null, (matcherOut = []), temp, xml ); 5240 } 5241 5242 // Move matched elements from seed to results to keep them synchronized 5243 i = matcherOut.length; 5244 while ( i-- ) { 5245 if ( (elem = matcherOut[i]) && 5246 (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { 5247 5248 seed[temp] = !(results[temp] = elem); 5249 } 5250 } 5251 } 5252 5253 // Add elements to results, through postFinder if defined 5254 } else { 5255 matcherOut = condense( 5256 matcherOut === results ? 5257 matcherOut.splice( preexisting, matcherOut.length ) : 5258 matcherOut 5259 ); 5260 if ( postFinder ) { 5261 postFinder( null, results, matcherOut, xml ); 5262 } else { 5263 push.apply( results, matcherOut ); 5264 } 5265 } 5266 }); 5267} 5268 5269function matcherFromTokens( tokens ) { 5270 var checkContext, matcher, j, 5271 len = tokens.length, 5272 leadingRelative = Expr.relative[ tokens[0].type ],
5273 implicitRelative = leadingRelative || Expr.relative[" "], 5274 i = leadingRelative ? 1 : 0, 5275 5276 // The foundational matcher ensures that elements are reachable from top-level context(s) 5277 matchContext = addCombinator( function( elem ) { 5278 return elem === checkContext; 5279 }, implicitRelative, true ), 5280 matchAnyContext = addCombinator( function( elem ) { 5281 return indexOf.call( checkContext, elem ) > -1; 5282 }, implicitRelative, true ), 5283 matchers = [ function( elem, context, xml ) { 5284 return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( 5285 (checkContext = context).nodeType ? 5286 matchContext( elem, context, xml ) : 5287 matchAnyContext( elem, context, xml ) ); 5288 } ]; 5289 5290 for ( ; i < len; i++ ) { 5291 if ( (matcher = Expr.relative[ tokens[i].type ]) ) { 5292 matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; 5293 } else { 5294 matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); 5295 5296 // Return special upon seeing a positional matcher 5297 if ( matcher[ expando ] ) { 5298 // Find the next relative operator (if any) for proper handling 5299 j = ++i; 5300 for ( ; j < len; j++ ) { 5301 if ( Expr.relative[ tokens[j].type ] ) { 5302 break; 5303 } 5304 } 5305 return setMatcher( 5306 i > 1 && elementMatcher( matchers ), 5307 i > 1 && toSelector( tokens.slice( 0, i - 1 ) ).replace( rtrim, "$1" ), 5308 matcher, 5309 i < j && matcherFromTokens( tokens.slice( i, j ) ), 5310 j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), 5311 j < len && toSelector( tokens ) 5312 ); 5313 } 5314 matchers.push( matcher ); 5315 } 5316 } 5317 5318 return elementMatcher( matchers ); 5319} 5320 5321function matcherFromGroupMatchers( elementMatchers, setMatchers ) { 5322 // A counter to specify which element is currently being matched 5323 var matcherCachedRuns = 0, 5324 bySet = setMatchers.length > 0, 5325 byElement = elementMatchers.length > 0, 5326 superMatcher = function( seed, context, xml, results, expandContext ) { 5327 var elem, j, matcher, 5328 setMatched = [], 5329 matchedCount = 0, 5330 i = "0", 5331 unmatched = seed && [], 5332 outermost = expandContext != null, 5333 contextBackup = outermostContext, 5334 // We must always have either seed elements or context 5335 elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), 5336 // Use integer dirruns iff this is the outermost matcher 5337 dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1); 5338 5339 if ( outermost ) { 5340 outermostContext = context !== document && context; 5341 cachedruns = matcherCachedRuns; 5342 } 5343 5344 // Add elements passing elementMatchers directly to results 5345 // Keep `i` a string if there are no elements so `matchedCount` will be "00" below 5346 for ( ; (elem = elems[i]) != null; i++ ) { 5347 if ( byElement && elem ) { 5348 j = 0; 5349 while ( (matcher = elementMatchers[j++]) ) { 5350 if ( matcher( elem, context, xml ) ) { 5351 results.push( elem ); 5352 break; 5353 } 5354 } 5355 if ( outermost ) { 5356 dirruns = dirrunsUnique; 5357 cachedruns = ++matcherCachedRuns; 5358 } 5359 } 5360 5361 // Track unmatched elements for set filters 5362 if ( bySet ) { 5363 // They will have gone through all possible matchers 5364 if ( (elem = !matcher && elem) ) { 5365 matchedCount--; 5366 } 5367 5368 // Lengthen the array for every element, matched or not 5369 if ( seed ) { 5370 unmatched.push( elem ); 5371 } 5372 } 5373 } 5374 5375 // Apply set filters to unmatched elements 5376 matchedCount += i; 5377 if ( bySet && i !== matchedCount ) { 5378 j = 0; 5379 while ( (matcher = setMatchers[j++]) ) { 5380 matcher( unmatched, setMatched, context, xml ); 5381 } 5382 5383 if ( seed ) { 5384 // Reintegrate element matches to eliminate the need for sorting 5385 if ( matchedCount > 0 ) { 5386 while ( i-- ) { 5387 if ( !(unmatched[i] || setMatched[i]) ) { 5388 setMatched[i] = pop.call( results ); 5389 } 5390 } 5391 } 5392 5393 // Discard index placeholder values to get only actual matches 5394 setMatched = condense( setMatched ); 5395 } 5396 5397 // Add matches to results 5398 push.apply( results, setMatched ); 5399 5400 // Seedless set matches succeeding multiple successful matchers stipulate sorting 5401 if ( outermost && !seed && setMatched.length > 0 && 5402 ( matchedCount + setMatchers.length ) > 1 ) { 5403 5404 Sizzle.uniqueSort( results ); 5405 } 5406 } 5407 5408 // Override manipulation of globals by nested matchers 5409 if ( outermost ) { 5410 dirruns = dirrunsUnique; 5411 outermostContext = contextBackup; 5412 } 5413 5414 return unmatched; 5415 }; 5416 5417 return bySet ? 5418 markFunction( superMatcher ) : 5419 superMatcher; 5420} 5421 5422compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { 5423 var i, 5424 setMatchers = [], 5425 elementMatchers = [], 5426 cached = compilerCache[ selector + " " ]; 5427 5428 if ( !cached ) { 5429 // Generate a function of recursive functions that can be used to check each element 5430 if ( !group ) { 5431 group = tokenize( selector ); 5432 } 5433 i = group.length; 5434 while ( i-- ) { 5435 cached = matcherFromTokens( group[i] ); 5436 if ( cached[ expando ] ) { 5437 setMatchers.push( cached ); 5438 } else { 5439 elementMatchers.push( cached ); 5440 } 5441 } 5442 5443 // Cache the compiled function 5444 cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); 5445 } 5446 return cached; 5447}; 5448 5449function multipleContexts( selector, contexts, results ) { 5450 var i = 0, 5451 len = contexts.length; 5452 for ( ; i < len; i++ ) { 5453 Sizzle( selector, contexts[i], results ); 5454 } 5455 return results; 5456} 5457 5458function select( selector, context, results, seed ) { 5459 var i, tokens, token, type, find, 5460 match = tokenize( selector ); 5461 5462 if ( !seed ) { 5463 // Try to minimize operations if there is only one group 5464 if ( match.length === 1 ) { 5465 5466 // Take a shortcut and set the context if the root selector is an ID 5467 tokens = match[0] = match[0].slice( 0 ); 5468 if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && 5469 context.nodeType === 9 && !documentIsXML && 5470 Expr.relative[ tokens[1].type ] ) { 5471 5472 context = Expr.find["ID"]( token.matches[0].replace( runescape, funescape ), context )[0]; 5473 if ( !context ) { 5474 return results; 5475 } 5476 5477 selector = selector.slice( tokens.shift().value.length ); 5478 } 5479 5480 // Fetch a seed set for right-to-left matching 5481 i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; 5482 while ( i-- ) { 5483 token = tokens[i]; 5484 5485 // Abort if we hit a combinator 5486 if ( Expr.relative[ (type = token.type) ] ) { 5487 break; 5488 } 5489 if ( (find = Expr.find[ type ]) ) { 5490 // Search, expanding context for leading sibling combinators 5491 if ( (seed = find( 5492 token.matches[0].replace( runescape, funescape ), 5493 rsibling.test( tokens[0].type ) && context.parentNode || context 5494 )) ) { 5495 5496 // If seed is empty or no tokens remain, we can return early 5497 tokens.splice( i, 1 ); 5498 selector = seed.length && toSelector( tokens ); 5499 if ( !selector ) { 5500 push.apply( results, slice.call( seed, 0 ) ); 5501 return results; 5502 } 5503 5504 break; 5505 } 5506 } 5507 } 5508 } 5509 } 5510 5511 // Compile and execute a filtering function 5512 // Provide `match` to avoid retokenization if we modified the selector above 5513 compile( selector, match )( 5514 seed, 5515 context, 5516 documentIsXML, 5517 results, 5518 rsibling.test( selector ) 5519 ); 5520 return results; 5521} 5522 5523// Deprecated 5524Expr.pseudos["nth"] = Expr.pseudos["eq"]; 5525 5526// Easy API for creating new setFilters 5527function setFilters() {} 5528Expr.filters = setFilters.prototype = Expr.pseudos; 5529Expr.setFilters = new setFilters(); 5530 5531// Initialize with the default document 5532setDocument(); 5533 5534// Override sizzle attribute retrieval 5535Sizzle.attr = jQuery.attr; 5536jQuery.find = Sizzle; 5537jQuery.expr = Sizzle.selectors; 5538jQuery.expr[":"] = jQuery.expr.pseudos; 5539jQuery.unique = Sizzle.uniqueSort; 5540jQuery.text = Sizzle.getText; 5541jQuery.isXMLDoc = Sizzle.isXML; 5542jQuery.contains = Sizzle.contains; 5543 5544 5545})( window ); 5546var runtil = /Until$/, 5547 rparentsprev = /^(?:parents|prev(?:Until|All))/, 5548 isSimple = /^.[^:#\[\.,]*$/, 5549 rneedsContext = jQuery.expr.match.needsContext, 5550 // methods guaranteed to produce a unique set when starting from a unique set 5551 guaranteedUnique = { 5552 children: true, 5553 contents: true, 5554 next: true, 5555 prev: true 5556 }; 5557 5558jQuery.fn.extend({ 5559 find: function( selector ) { 5560 var i, ret, self, 5561 len = this.length; 5562 5563 if ( typeof selector !== "string" ) { 5564 self = this;
5565 return this.pushStack( jQuery( selector ).filter(function() { 5566 for ( i = 0; i < len; i++ ) { 5567 if ( jQuery.contains( self[ i ], this ) ) { 5568 return true; 5569 } 5570 } 5571 }) ); 5572 } 5573 5574 ret = []; 5575 for ( i = 0; i < len; i++ ) { 5576 jQuery.find( selector, this[ i ], ret ); 5577 } 5578 5579 // Needed because $( selector, context ) becomes $( context ).find( selector ) 5580 ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); 5581 ret.selector = ( this.selector ? this.selector + " " : "" ) + selector; 5582 return ret; 5583 }, 5584 5585 has: function( target ) { 5586 var i, 5587 targets = jQuery( target, this ), 5588 len = targets.length; 5589 5590 return this.filter(function() { 5591 for ( i = 0; i < len; i++ ) { 5592 if ( jQuery.contains( this, targets[i] ) ) { 5593 return true; 5594 } 5595 } 5596 }); 5597 }, 5598 5599 not: function( selector ) { 5600 return this.pushStack( winnow(this, selector, false) ); 5601 }, 5602 5603 filter: function( selector ) { 5604 return this.pushStack( winnow(this, selector, true) ); 5605 }, 5606 5607 is: function( selector ) { 5608 return !!selector && ( 5609 typeof selector === "string" ? 5610 // If this is a positional/relative selector, check membership in the returned set 5611 // so $("p:first").is("p:last") won't return true for a doc with two "p". 5612 rneedsContext.test( selector ) ? 5613 jQuery( selector, this.context ).index( this[0] ) >= 0 : 5614 jQuery.filter( selector, this ).length > 0 : 5615 this.filter( selector ).length > 0 ); 5616 }, 5617 5618 closest: function( selectors, context ) { 5619 var cur, 5620 i = 0, 5621 l = this.length, 5622 ret = [], 5623 pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? 5624 jQuery( selectors, context || this.context ) : 5625 0; 5626 5627 for ( ; i < l; i++ ) { 5628 cur = this[i]; 5629 5630 while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) { 5631 if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { 5632 ret.push( cur ); 5633 break; 5634 } 5635 cur = cur.parentNode; 5636 } 5637 } 5638 5639 return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret ); 5640 }, 5641 5642 // Determine the position of an element within 5643 // the matched set of elements 5644 index: function( elem ) { 5645 5646 // No argument, return index in parent 5647 if ( !elem ) { 5648 return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; 5649 } 5650 5651 // index in selector 5652 if ( typeof elem === "string" ) { 5653 return jQuery.inArray( this[0], jQuery( elem ) ); 5654 } 5655 5656 // Locate the position of the desired element 5657 return jQuery.inArray( 5658 // If it receives a jQuery object, the first element is used 5659 elem.jquery ? elem[0] : elem, this ); 5660 }, 5661 5662 add: function( selector, context ) { 5663 var set = typeof selector === "string" ? 5664 jQuery( selector, context ) : 5665 jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), 5666 all = jQuery.merge( this.get(), set ); 5667 5668 return this.pushStack( jQuery.unique(all) ); 5669 }, 5670 5671 addBack: function( selector ) { 5672 return this.add( selector == null ? 5673 this.prevObject : this.prevObject.filter(selector) 5674 ); 5675 } 5676}); 5677 5678jQuery.fn.andSelf = jQuery.fn.addBack; 5679 5680function sibling( cur, dir ) { 5681 do { 5682 cur = cur[ dir ]; 5683 } while ( cur && cur.nodeType !== 1 ); 5684 5685 return cur; 5686} 5687 5688jQuery.each({ 5689 parent: function( elem ) { 5690 var parent = elem.parentNode; 5691 return parent && parent.nodeType !== 11 ? parent : null; 5692 }, 5693 parents: function( elem ) { 5694 return jQuery.dir( elem, "parentNode" ); 5695 }, 5696 parentsUntil: function( elem, i, until ) { 5697 return jQuery.dir( elem, "parentNode", until ); 5698 }, 5699 next: function( elem ) { 5700 return sibling( elem, "nextSibling" ); 5701 }, 5702 prev: function( elem ) { 5703 return sibling( elem, "previousSibling" ); 5704 }, 5705 nextAll: function( elem ) { 5706 return jQuery.dir( elem, "nextSibling" ); 5707 }, 5708 prevAll: function( elem ) { 5709 return jQuery.dir( elem, "previousSibling" ); 5710 }, 5711 nextUntil: function( elem, i, until ) { 5712 return jQuery.dir( elem, "nextSibling", until ); 5713 }, 5714 prevUntil: function( elem, i, until ) { 5715 return jQuery.dir( elem, "previousSibling", until ); 5716 }, 5717 siblings: function( elem ) { 5718 return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); 5719 }, 5720 children: function( elem ) { 5721 return jQuery.sibling( elem.firstChild ); 5722 }, 5723 contents: function( elem ) { 5724 return jQuery.nodeName( elem, "iframe" ) ? 5725 elem.contentDocument || elem.contentWindow.document : 5726 jQuery.merge( [], elem.childNodes ); 5727 } 5728}, function( name, fn ) { 5729 jQuery.fn[ name ] = function( until, selector ) { 5730 var ret = jQuery.map( this, fn, until ); 5731 5732 if ( !runtil.test( name ) ) { 5733 selector = until; 5734 } 5735 5736 if ( selector && typeof selector === "string" ) { 5737 ret = jQuery.filter( selector, ret ); 5738 } 5739 5740 ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; 5741 5742 if ( this.length > 1 && rparentsprev.test( name ) ) { 5743 ret = ret.reverse(); 5744 } 5745 5746 return this.pushStack( ret ); 5747 }; 5748}); 5749 5750jQuery.extend({ 5751 filter: function( expr, elems, not ) { 5752 if ( not ) { 5753 expr = ":not(" + expr + ")"; 5754 } 5755 5756 return elems.length === 1 ? 5757 jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : 5758 jQuery.find.matches(expr, elems); 5759 }, 5760 5761 dir: function( elem, dir, until ) { 5762 var matched = [], 5763 cur = elem[ dir ]; 5764 5765 while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { 5766 if ( cur.nodeType === 1 ) { 5767 matched.push( cur ); 5768 } 5769 cur = cur[dir]; 5770 } 5771 return matched; 5772 }, 5773 5774 sibling: function( n, elem ) { 5775 var r = []; 5776 5777 for ( ; n; n = n.nextSibling ) { 5778 if ( n.nodeType === 1 && n !== elem ) { 5779 r.push( n ); 5780 } 5781 } 5782 5783 return r; 5784 } 5785}); 5786 5787// Implement the identical functionality for filter and not 5788function winnow( elements, qualifier, keep ) { 5789 5790 // Can't pass null or undefined to indexOf in Firefox 4 5791 // Set to 0 to skip string check 5792 qualifier = qualifier || 0; 5793 5794 if ( jQuery.isFunction( qualifier ) ) { 5795 return jQuery.grep(elements, function( elem, i ) { 5796 var retVal = !!qualifier.call( elem, i, elem ); 5797 return retVal === keep; 5798 }); 5799 5800 } else if ( qualifier.nodeType ) { 5801 return jQuery.grep(elements, function( elem ) { 5802 return ( elem === qualifier ) === keep; 5803 }); 5804 5805 } else if ( typeof qualifier === "string" ) { 5806 var filtered = jQuery.grep(elements, function( elem ) { 5807 return elem.nodeType === 1; 5808 }); 5809 5810 if ( isSimple.test( qualifier ) ) { 5811 return jQuery.filter(qualifier, filtered, !keep); 5812 } else { 5813 qualifier = jQuery.filter( qualifier, filtered ); 5814 } 5815 } 5816 5817 return jQuery.grep(elements, function( elem ) { 5818 return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; 5819 }); 5820} 5821function createSafeFragment( document ) { 5822 var list = nodeNames.split( "|" ), 5823 safeFrag = document.createDocumentFragment(); 5824 5825 if ( safeFrag.createElement ) { 5826 while ( list.length ) { 5827 safeFrag.createElement( 5828 list.pop() 5829 ); 5830 } 5831 } 5832 return safeFrag; 5833} 5834 5835var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + 5836 "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", 5837 rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, 5838 rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), 5839 rleadingWhitespace = /^\s+/, 5840 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, 5841 rtagName = /<([\w:]+)/, 5842 rtbody = /<tbody/i,
5843 rhtml = /<|&#?\w+;/, 5844 rnoInnerhtml = /<(?:script|style|link)/i, 5845 manipulation_rcheckableType = /^(?:checkbox|radio)$/i, 5846 // checked="checked" or checked 5847 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, 5848 rscriptType = /^$|\/(?:java|ecma)script/i, 5849 rscriptTypeMasked = /^true\/(.*)/, 5850 rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g, 5851 5852 // We have to close these tags to support XHTML (#13200) 5853 wrapMap = { 5854 option: [ 1, "<select multiple='multiple'>", "</select>" ], 5855 legend: [ 1, "<fieldset>", "</fieldset>" ], 5856 area: [ 1, "<map>", "</map>" ], 5857 param: [ 1, "<object>", "</object>" ], 5858 thead: [ 1, "<table>", "</table>" ], 5859 tr: [ 2, "<table><tbody>", "</tbody></table>" ], 5860 col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ], 5861 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], 5862 5863 // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, 5864 // unless wrapped in a div with non-breaking characters in front of it. 5865 _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>" ] 5866 }, 5867 safeFragment = createSafeFragment( document ), 5868 fragmentDiv = safeFragment.appendChild( document.createElement("div") ); 5869 5870wrapMap.optgroup = wrapMap.option; 5871wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; 5872wrapMap.th = wrapMap.td; 5873 5874jQuery.fn.extend({ 5875 text: function( value ) { 5876 return jQuery.access( this, function( value ) { 5877 return value === undefined ? 5878 jQuery.text( this ) : 5879 this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); 5880 }, null, value, arguments.length ); 5881 }, 5882 5883 wrapAll: function( html ) { 5884 if ( jQuery.isFunction( html ) ) { 5885 return this.each(function(i) { 5886 jQuery(this).wrapAll( html.call(this, i) ); 5887 }); 5888 } 5889 5890 if ( this[0] ) { 5891 // The elements to wrap the target around 5892 var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); 5893 5894 if ( this[0].parentNode ) { 5895 wrap.insertBefore( this[0] ); 5896 } 5897 5898 wrap.map(function() { 5899 var elem = this; 5900 5901 while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { 5902 elem = elem.firstChild; 5903 } 5904 5905 return elem; 5906 }).append( this ); 5907 } 5908 5909 return this; 5910 }, 5911 5912 wrapInner: function( html ) { 5913 if ( jQuery.isFunction( html ) ) { 5914 return this.each(function(i) { 5915 jQuery(this).wrapInner( html.call(this, i) ); 5916 }); 5917 } 5918 5919 return this.each(function() { 5920 var self = jQuery( this ), 5921 contents = self.contents(); 5922 5923 if ( contents.length ) { 5924 contents.wrapAll( html ); 5925 5926 } else { 5927 self.append( html ); 5928 } 5929 }); 5930 }, 5931 5932 wrap: function( html ) { 5933 var isFunction = jQuery.isFunction( html ); 5934 5935 return this.each(function(i) { 5936 jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); 5937 }); 5938 }, 5939 5940 unwrap: function() { 5941 return this.parent().each(function() { 5942 if ( !jQuery.nodeName( this, "body" ) ) { 5943 jQuery( this ).replaceWith( this.childNodes ); 5944 } 5945 }).end(); 5946 }, 5947 5948 append: function() { 5949 return this.domManip(arguments, true, function( elem ) { 5950 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { 5951 this.appendChild( elem ); 5952 } 5953 }); 5954 }, 5955
5956 prepend: function() { 5957 return this.domManip(arguments, true, function( elem ) { 5958 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { 5959 this.insertBefore( elem, this.firstChild ); 5960 } 5961 }); 5962 }, 5963 5964 before: function() { 5965 return this.domManip( arguments, false, function( elem ) { 5966 if ( this.parentNode ) { 5967 this.parentNode.insertBefore( elem, this ); 5968 } 5969 }); 5970 }, 5971 5972 after: function() { 5973 return this.domManip( arguments, false, function( elem ) { 5974 if ( this.parentNode ) { 5975 this.parentNode.insertBefore( elem, this.nextSibling ); 5976 } 5977 }); 5978 }, 5979 5980 // keepData is for internal use only--do not document 5981 remove: function( selector, keepData ) { 5982 var elem, 5983 i = 0; 5984 5985 for ( ; (elem = this[i]) != null; i++ ) { 5986 if ( !selector || jQuery.filter( selector, [ elem ] ).length > 0 ) { 5987 if ( !keepData && elem.nodeType === 1 ) { 5988 jQuery.cleanData( getAll( elem ) ); 5989 } 5990 5991 if ( elem.parentNode ) { 5992 if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { 5993 setGlobalEval( getAll( elem, "script" ) ); 5994 } 5995 elem.parentNode.removeChild( elem ); 5996 } 5997 } 5998 } 5999 6000 return this; 6001 }, 6002 6003 empty: function() { 6004 var elem, 6005 i = 0; 6006 6007 for ( ; (elem = this[i]) != null; i++ ) { 6008 // Remove element nodes and prevent memory leaks 6009 if ( elem.nodeType === 1 ) { 6010 jQuery.cleanData( getAll( elem, false ) ); 6011 } 6012 6013 // Remove any remaining nodes 6014 while ( elem.firstChild ) { 6015 elem.removeChild( elem.firstChild ); 6016 } 6017 6018 // If this is a select, ensure that it displays empty (#12336) 6019 // Support: IE<9 6020 if ( elem.options && jQuery.nodeName( elem, "select" ) ) { 6021 elem.options.length = 0; 6022 } 6023 } 6024 6025 return this; 6026 }, 6027 6028 clone: function( dataAndEvents, deepDataAndEvents ) { 6029 dataAndEvents = dataAndEvents == null ? false : dataAndEvents; 6030 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; 6031 6032 return this.map( function () { 6033 return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); 6034 }); 6035 }, 6036 6037 html: function( value ) { 6038 return jQuery.access( this, function( value ) { 6039 var elem = this[0] || {}, 6040 i = 0, 6041 l = this.length; 6042 6043 if ( value === undefined ) { 6044 return elem.nodeType === 1 ? 6045 elem.innerHTML.replace( rinlinejQuery, "" ) : 6046 undefined; 6047 } 6048 6049 // See if we can take a shortcut and just use innerHTML 6050 if ( typeof value === "string" && !rnoInnerhtml.test( value ) && 6051 ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) && 6052 ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && 6053 !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) { 6054 6055 value = value.replace( rxhtmlTag, "<$1></$2>" ); 6056 6057 try { 6058 for (; i < l; i++ ) { 6059 // Remove element nodes and prevent memory leaks 6060 elem = this[i] || {}; 6061 if ( elem.nodeType === 1 ) { 6062 jQuery.cleanData( getAll( elem, false ) ); 6063 elem.innerHTML = value; 6064 } 6065 } 6066 6067 elem = 0; 6068 6069 // If using innerHTML throws an exception, use the fallback method 6070 } catch(e) {} 6071 } 6072 6073 if ( elem ) { 6074 this.empty().append( value ); 6075 } 6076 }, null, value, arguments.length ); 6077 }, 6078 6079 replaceWith: function( value ) { 6080 var isFunc = jQuery.isFunction( value ); 6081 6082 // Make sure that the elements are removed from the DOM before they are inserted 6083 // this can help fix replacing a parent with child elements 6084 if ( !isFunc && typeof value !== "string" ) { 6085 value = jQuery( value ).not( this ).detach(); 6086 } 6087 6088 return this.domManip( [ value ], true, function( elem ) { 6089 var next = this.nextSibling, 6090 parent = this.parentNode; 6091 6092 if ( parent ) { 6093 jQuery( this ).remove(); 6094 parent.insertBefore( elem, next ); 6095 } 6096 }); 6097 }, 6098 6099 detach: function( selector ) { 6100 return this.remove( selector, true ); 6101 }, 6102 6103 domManip: function( args, table, callback ) { 6104 6105 // Flatten any nested arrays 6106 args = core_concat.apply( [], args ); 6107 6108 var first, node, hasScripts, 6109 scripts, doc, fragment, 6110 i = 0, 6111 l = this.length, 6112 set = this, 6113 iNoClone = l - 1, 6114 value = args[0], 6115 isFunction = jQuery.isFunction( value ); 6116 6117 // We can't cloneNode fragments that contain checked, in WebKit 6118 if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) { 6119 return this.each(function( index ) { 6120 var self = set.eq( index ); 6121 if ( isFunction ) { 6122 args[0] = value.call( this, index, table ? self.html() : undefined ); 6123 } 6124 self.domManip( args, table, callback ); 6125 }); 6126 } 6127 6128 if ( l ) { 6129 fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); 6130 first = fragment.firstChild; 6131 6132 if ( fragment.childNodes.length === 1 ) { 6133 fragment = first; 6134 } 6135 6136 if ( first ) { 6137 table = table && jQuery.nodeName( first, "tr" ); 6138 scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); 6139 hasScripts = scripts.length; 6140 6141 // Use the original fragment for the last item instead of the first because it can end up 6142 // being emptied incorrectly in certain situations (#8070). 6143 for ( ; i < l; i++ ) { 6144 node = fragment; 6145 6146 if ( i !== iNoClone ) { 6147 node = jQuery.clone( node, true, true ); 6148 6149 // Keep references to cloned scripts for later restoration 6150 if ( hasScripts ) { 6151 jQuery.merge( scripts, getAll( node, "script" ) ); 6152 } 6153 } 6154 6155 callback.call( 6156 table && jQuery.nodeName( this[i], "table" ) ? 6157 findOrAppend( this[i], "tbody" ) : 6158 this[i], 6159 node, 6160 i 6161 ); 6162 } 6163 6164 if ( hasScripts ) { 6165 doc = scripts[ scripts.length - 1 ].ownerDocument; 6166 6167 // Reenable scripts 6168 jQuery.map( scripts, restoreScript ); 6169 6170 // Evaluate executable scripts on first document insertion 6171 for ( i = 0; i < hasScripts; i++ ) { 6172 node = scripts[ i ]; 6173 if ( rscriptType.test( node.type || "" ) && 6174 !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { 6175 6176 if ( node.src ) { 6177 // Hope ajax is available... 6178 jQuery.ajax({ 6179 url: node.src, 6180 type: "GET", 6181 dataType: "script", 6182 async: false, 6183 global: false, 6184 "throws": true 6185 }); 6186 } else { 6187 jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); 6188 } 6189 } 6190 } 6191 } 6192 6193 // Fix #11809: Avoid leaking memory 6194 fragment = first = null; 6195 } 6196 } 6197 6198 return this; 6199 } 6200}); 6201 6202function findOrAppend( elem, tag ) { 6203 return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) ); 6204} 6205 6206// Replace/restore the type attribute of script elements for safe DOM manipulation 6207function disableScript( elem ) { 6208 var attr = elem.getAttributeNode("type"); 6209 elem.type = ( attr && attr.specified ) + "/" + elem.type; 6210 return elem; 6211} 6212function restoreScript( elem ) { 6213 var match = rscriptTypeMasked.exec( elem.type ); 6214 if ( match ) { 6215 elem.type = match[1]; 6216 } else { 6217 elem.removeAttribute("type"); 6218 } 6219 return elem; 6220} 6221 6222// Mark scripts as having already been evaluated 6223function setGlobalEval( elems, refElements ) { 6224 var elem, 6225 i = 0; 6226 for ( ; (elem = elems[i]) != null; i++ ) { 6227 jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); 6228 } 6229} 6230 6231function cloneCopyEvent( src, dest ) { 6232
6233 if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { 6234 return; 6235 } 6236 6237 var type, i, l, 6238 oldData = jQuery._data( src ), 6239 curData = jQuery._data( dest, oldData ), 6240 events = oldData.events; 6241 6242 if ( events ) { 6243 delete curData.handle; 6244 curData.events = {}; 6245 6246 for ( type in events ) { 6247 for ( i = 0, l = events[ type ].length; i < l; i++ ) { 6248 jQuery.event.add( dest, type, events[ type ][ i ] ); 6249 } 6250 } 6251 } 6252 6253 // make the cloned public data object a copy from the original 6254 if ( curData.data ) { 6255 curData.data = jQuery.extend( {}, curData.data ); 6256 } 6257} 6258 6259function fixCloneNodeIssues( src, dest ) { 6260 var nodeName, e, data; 6261 6262 // We do not need to do anything for non-Elements 6263 if ( dest.nodeType !== 1 ) { 6264 return; 6265 } 6266 6267 nodeName = dest.nodeName.toLowerCase(); 6268 6269 // IE6-8 copies events bound via attachEvent when using cloneNode. 6270 if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) { 6271 data = jQuery._data( dest ); 6272 6273 for ( e in data.events ) { 6274 jQuery.removeEvent( dest, e, data.handle ); 6275 } 6276 6277 // Event data gets referenced instead of copied if the expando gets copied too 6278 dest.removeAttribute( jQuery.expando ); 6279 } 6280 6281 // IE blanks contents when cloning scripts, and tries to evaluate newly-set text 6282 if ( nodeName === "script" && dest.text !== src.text ) { 6283 disableScript( dest ).text = src.text; 6284 restoreScript( dest ); 6285 6286 // IE6-10 improperly clones children of object elements using classid. 6287 // IE10 throws NoModificationAllowedError if parent is null, #12132. 6288 } else if ( nodeName === "object" ) { 6289 if ( dest.parentNode ) { 6290 dest.outerHTML = src.outerHTML; 6291 } 6292 6293 // This path appears unavoidable for IE9. When cloning an object 6294 // element in IE9, the outerHTML strategy above is not sufficient. 6295 // If the src has innerHTML and the destination does not, 6296 // copy the src.innerHTML into the dest.innerHTML. #10324 6297 if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { 6298 dest.innerHTML = src.innerHTML; 6299 } 6300 6301 } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) { 6302 // IE6-8 fails to persist the checked state of a cloned checkbox 6303 // or radio button. Worse, IE6-7 fail to give the cloned element 6304 // a checked appearance if the defaultChecked value isn't also set 6305 6306 dest.defaultChecked = dest.checked = src.checked; 6307 6308 // IE6-7 get confused and end up setting the value of a cloned 6309 // checkbox/radio button to an empty string instead of "on" 6310 if ( dest.value !== src.value ) { 6311 dest.value = src.value; 6312 } 6313 6314 // IE6-8 fails to return the selected option to the default selected 6315 // state when cloning options 6316 } else if ( nodeName === "option" ) { 6317 dest.defaultSelected = dest.selected = src.defaultSelected; 6318 6319 // IE6-8 fails to set the defaultValue to the correct value when 6320 // cloning other types of input fields 6321 } else if ( nodeName === "input" || nodeName === "textarea" ) { 6322 dest.defaultValue = src.defaultValue; 6323 } 6324} 6325 6326jQuery.each({ 6327 appendTo: "append", 6328 prependTo: "prepend", 6329 insertBefore: "before", 6330 insertAfter: "after", 6331 replaceAll: "replaceWith" 6332}, function( name, original ) { 6333 jQuery.fn[ name ] = function( selector ) { 6334 var elems, 6335 i = 0, 6336 ret = [], 6337 insert = jQuery( selector ), 6338 last = insert.length - 1; 6339 6340 for ( ; i <= last; i++ ) { 6341 elems = i === last ? this : this.clone(true); 6342 jQuery( insert[i] )[ original ]( elems ); 6343 6344 // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() 6345 core_push.apply( ret, elems.get() ); 6346 } 6347 6348 return this.pushStack( ret ); 6349 }; 6350}); 6351 6352function getAll( context, tag ) { 6353 var elems, elem, 6354 i = 0, 6355 found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) : 6356 typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) : 6357 undefined; 6358 6359 if ( !found ) { 6360 for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { 6361 if ( !tag || jQuery.nodeName( elem, tag ) ) { 6362 found.push( elem ); 6363 } else { 6364 jQuery.merge( found, getAll( elem, tag ) ); 6365 } 6366 } 6367 } 6368 6369 return tag === undefined || tag && jQuery.nodeName( context, tag ) ? 6370 jQuery.merge( [ context ], found ) : 6371 found; 6372} 6373 6374// Used in buildFragment, fixes the defaultChecked property 6375function fixDefaultChecked( elem ) { 6376 if ( manipulation_rcheckableType.test( elem.type ) ) { 6377 elem.defaultChecked = elem.checked; 6378 } 6379} 6380 6381jQuery.extend({ 6382 clone: function( elem, dataAndEvents, deepDataAndEvents ) { 6383 var destElements, node, clone, i, srcElements, 6384 inPage = jQuery.contains( elem.ownerDocument, elem ); 6385 6386 if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { 6387 clone = elem.cloneNode( true ); 6388 6389 // IE<=8 does not properly clone detached, unknown element nodes 6390 } else { 6391 fragmentDiv.innerHTML = elem.outerHTML; 6392 fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); 6393 } 6394 6395 if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && 6396 (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { 6397 6398 // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 6399 destElements = getAll( clone ); 6400 srcElements = getAll( elem ); 6401 6402 // Fix all IE cloning issues 6403 for ( i = 0; (node = srcElements[i]) != null; ++i ) { 6404 // Ensure that the destination node is not null; Fixes #9587 6405 if ( destElements[i] ) {
6406 fixCloneNodeIssues( node, destElements[i] ); 6407 } 6408 } 6409 } 6410 6411 // Copy the events from the original to the clone 6412 if ( dataAndEvents ) { 6413 if ( deepDataAndEvents ) { 6414 srcElements = srcElements || getAll( elem ); 6415 destElements = destElements || getAll( clone ); 6416 6417 for ( i = 0; (node = srcElements[i]) != null; i++ ) { 6418 cloneCopyEvent( node, destElements[i] ); 6419 } 6420 } else { 6421 cloneCopyEvent( elem, clone ); 6422 } 6423 } 6424 6425 // Preserve script evaluation history 6426 destElements = getAll( clone, "script" ); 6427 if ( destElements.length > 0 ) { 6428 setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); 6429 } 6430 6431 destElements = srcElements = node = null; 6432 6433 // Return the cloned set 6434 return clone; 6435 }, 6436 6437 buildFragment: function( elems, context, scripts, selection ) { 6438 var j, elem, contains, 6439 tmp, tag, tbody, wrap, 6440 l = elems.length, 6441 6442 // Ensure a safe fragment 6443 safe = createSafeFragment( context ), 6444 6445 nodes = [], 6446 i = 0; 6447 6448 for ( ; i < l; i++ ) { 6449 elem = elems[ i ]; 6450 6451 if ( elem || elem === 0 ) { 6452 6453 // Add nodes directly 6454 if ( jQuery.type( elem ) === "object" ) { 6455 jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); 6456 6457 // Convert non-html into a text node 6458 } else if ( !rhtml.test( elem ) ) { 6459 nodes.push( context.createTextNode( elem ) ); 6460 6461 // Convert html into DOM nodes 6462 } else { 6463 tmp = tmp || safe.appendChild( context.createElement("div") ); 6464 6465 // Deserialize a standard representation 6466 tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(); 6467 wrap = wrapMap[ tag ] || wrapMap._default; 6468 6469 tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2]; 6470 6471 // Descend through wrappers to the right content 6472 j = wrap[0]; 6473 while ( j-- ) { 6474 tmp = tmp.lastChild; 6475 } 6476 6477 // Manually add leading whitespace removed by IE 6478 if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { 6479 nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); 6480 } 6481 6482 // Remove IE's autoinserted <tbody> from table fragments 6483 if ( !jQuery.support.tbody ) { 6484 6485 // String was a <table>, *may* have spurious <tbody> 6486 elem = tag === "table" && !rtbody.test( elem ) ? 6487 tmp.firstChild : 6488 6489 // String was a bare <thead> or <tfoot> 6490 wrap[1] === "<table>" && !rtbody.test( elem ) ? 6491 tmp : 6492 0; 6493 6494 j = elem && elem.childNodes.length; 6495 while ( j-- ) { 6496 if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { 6497 elem.removeChild( tbody ); 6498 } 6499 } 6500 } 6501 6502 jQuery.merge( nodes, tmp.childNodes ); 6503 6504 // Fix #12392 for WebKit and IE > 9 6505 tmp.textContent = ""; 6506 6507 // Fix #12392 for oldIE 6508 while ( tmp.firstChild ) { 6509 tmp.removeChild( tmp.firstChild ); 6510 } 6511 6512 // Remember the top-level container for proper cleanup 6513 tmp = safe.lastChild; 6514 } 6515 } 6516 } 6517 6518 // Fix #11356: Clear elements from fragment 6519 if ( tmp ) { 6520 safe.removeChild( tmp ); 6521 } 6522 6523 // Reset defaultChecked for any radios and checkboxes 6524 // about to be appended to the DOM in IE 6/7 (#8060) 6525 if ( !jQuery.support.appendChecked ) { 6526 jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); 6527 } 6528 6529 i = 0; 6530 while ( (elem = nodes[ i++ ]) ) { 6531 6532 // #4087 - If origin and destination elements are the same, and this is 6533 // that element, do not do anything 6534 if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { 6535 continue; 6536 } 6537 6538 contains = jQuery.contains( elem.ownerDocument, elem ); 6539 6540 // Append to fragment 6541 tmp = getAll( safe.appendChild( elem ), "script" ); 6542 6543 // Preserve script evaluation history 6544 if ( contains ) { 6545 setGlobalEval( tmp ); 6546 } 6547 6548 // Capture executables 6549 if ( scripts ) { 6550 j = 0; 6551 while ( (elem = tmp[ j++ ]) ) { 6552 if ( rscriptType.test( elem.type || "" ) ) { 6553 scripts.push( elem ); 6554 } 6555 } 6556 } 6557 } 6558 6559 tmp = null; 6560 6561 return safe; 6562 }, 6563 6564 cleanData: function( elems, /* internal */ acceptData ) { 6565 var elem, type, id, data, 6566 i = 0, 6567 internalKey = jQuery.expando, 6568 cache = jQuery.cache, 6569 deleteExpando = jQuery.support.deleteExpando, 6570 special = jQuery.event.special; 6571 6572 for ( ; (elem = elems[i]) != null; i++ ) { 6573 6574 if ( acceptData || jQuery.acceptData( elem ) ) { 6575 6576 id = elem[ internalKey ];
6577 data = id && cache[ id ]; 6578 6579 if ( data ) { 6580 if ( data.events ) { 6581 for ( type in data.events ) { 6582 if ( special[ type ] ) { 6583 jQuery.event.remove( elem, type ); 6584 6585 // This is a shortcut to avoid jQuery.event.remove's overhead 6586 } else { 6587 jQuery.removeEvent( elem, type, data.handle ); 6588 } 6589 } 6590 } 6591 6592 // Remove cache only if it was not already removed by jQuery.event.remove 6593 if ( cache[ id ] ) { 6594 6595 delete cache[ id ]; 6596 6597 // IE does not allow us to delete expando properties from nodes, 6598 // nor does it have a removeAttribute function on Document nodes; 6599 // we must handle all of these cases 6600 if ( deleteExpando ) { 6601 delete elem[ internalKey ]; 6602 6603 } else if ( typeof elem.removeAttribute !== core_strundefined ) { 6604 elem.removeAttribute( internalKey ); 6605 6606 } else { 6607 elem[ internalKey ] = null; 6608 } 6609 6610 core_deletedIds.push( id ); 6611 } 6612 } 6613 } 6614 } 6615 } 6616}); 6617var iframe, getStyles, curCSS, 6618 ralpha = /alpha\([^)]*\)/i, 6619 ropacity = /opacity\s*=\s*([^)]*)/, 6620 rposition = /^(top|right|bottom|left)$/, 6621 // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" 6622 // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display 6623 rdisplayswap = /^(none|table(?!-c[ea]).+)/, 6624 rmargin = /^margin/, 6625 rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ), 6626 rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ), 6627 rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ), 6628 elemdisplay = { BODY: "block" }, 6629 6630 cssShow = { position: "absolute", visibility: "hidden", display: "block" }, 6631 cssNormalTransform = { 6632 letterSpacing: 0, 6633 fontWeight: 400 6634 }, 6635 6636 cssExpand = [ "Top", "Right", "Bottom", "Left" ], 6637 cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; 6638 6639// return a css property mapped to a potentially vendor prefixed property 6640function vendorPropName( style, name ) { 6641 6642 // shortcut for names that are not vendor prefixed 6643 if ( name in style ) { 6644 return name; 6645 } 6646 6647 // check for vendor prefixed names 6648 var capName = name.charAt(0).toUpperCase() + name.slice(1), 6649 origName = name, 6650 i = cssPrefixes.length; 6651 6652 while ( i-- ) { 6653 name = cssPrefixes[ i ] + capName; 6654 if ( name in style ) { 6655 return name; 6656 } 6657 } 6658 6659 return origName; 6660} 6661 6662function isHidden( elem, el ) { 6663 // isHidden might be called from jQuery#filter function; 6664 // in that case, element will be second argument 6665 elem = el || elem; 6666 return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); 6667} 6668 6669function showHide( elements, show ) { 6670 var display, elem, hidden, 6671 values = [], 6672 index = 0, 6673 length = elements.length; 6674 6675 for ( ; index < length; index++ ) { 6676 elem = elements[ index ]; 6677 if ( !elem.style ) { 6678 continue; 6679 } 6680 6681 values[ index ] = jQuery._data( elem, "olddisplay" ); 6682 display = elem.style.display; 6683 if ( show ) { 6684 // Reset the inline display of this element to learn if it is 6685 // being hidden by cascaded rules or not 6686 if ( !values[ index ] && display === "none" ) { 6687 elem.style.display = ""; 6688 } 6689 6690 // Set elements which have been overridden with display: none 6691 // in a stylesheet to whatever the default browser style is 6692 // for such an element 6693 if ( elem.style.display === "" && isHidden( elem ) ) { 6694 values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) ); 6695 } 6696 } else { 6697 6698 if ( !values[ index ] ) { 6699 hidden = isHidden( elem ); 6700 6701 if ( display && display !== "none" || !hidden ) { 6702 jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) ); 6703 } 6704 } 6705 } 6706 } 6707 6708 // Set the display of most of the elements in a second loop 6709 // to avoid the constant reflow 6710 for ( index = 0; index < length; index++ ) { 6711 elem = elements[ index ]; 6712 if ( !elem.style ) { 6713 continue; 6714 } 6715 if ( !show || elem.style.display === "none" || elem.style.display === "" ) { 6716 elem.style.display = show ? values[ index ] || "" : "none"; 6717 } 6718 } 6719 6720 return elements; 6721} 6722 6723jQuery.fn.extend({ 6724 css: function( name, value ) { 6725 return jQuery.access( this, function( elem, name, value ) { 6726 var len, styles, 6727 map = {}, 6728 i = 0; 6729 6730 if ( jQuery.isArray( name ) ) { 6731 styles = getStyles( elem ); 6732 len = name.length; 6733 6734 for ( ; i < len; i++ ) { 6735 map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); 6736 } 6737 6738 return map; 6739 } 6740 6741 return value !== undefined ? 6742 jQuery.style( elem, name, value ) : 6743 jQuery.css( elem, name ); 6744 }, name, value, arguments.length > 1 ); 6745 }, 6746 show: function() { 6747 return showHide( this, true ); 6748 }, 6749 hide: function() { 6750 return showHide( this ); 6751 }, 6752 toggle: function( state ) { 6753 var bool = typeof state === "boolean"; 6754 6755 return this.each(function() { 6756 if ( bool ? state : isHidden( this ) ) { 6757 jQuery( this ).show(); 6758 } else { 6759 jQuery( this ).hide(); 6760 } 6761 }); 6762 } 6763}); 6764 6765jQuery.extend({ 6766 // Add in style property hooks for overriding the default 6767 // behavior of getting and setting a style property 6768 cssHooks: { 6769 opacity: { 6770 get: function( elem, computed ) { 6771 if ( computed ) { 6772 // We should always get a number back from opacity 6773 var ret = curCSS( elem, "opacity" ); 6774 return ret === "" ? "1" : ret; 6775 } 6776 } 6777 } 6778 }, 6779 6780 // Exclude the following css properties to add px 6781 cssNumber: { 6782 "columnCount": true, 6783 "fillOpacity": true, 6784 "fontWeight": true, 6785 "lineHeight": true, 6786 "opacity": true, 6787 "orphans": true, 6788 "widows": true, 6789 "zIndex": true, 6790 "zoom": true 6791 }, 6792 6793 // Add in properties whose names you wish to fix before 6794 // setting or getting the value 6795 cssProps: { 6796 // normalize float css property 6797 "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" 6798 }, 6799 6800 // Get and set the style property on a DOM Node 6801 style: function( elem, name, value, extra ) { 6802 // Don't set styles on text and comment nodes 6803 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { 6804 return; 6805 } 6806 6807 // Make sure that we're working with the right name 6808 var ret, type, hooks, 6809 origName = jQuery.camelCase( name ), 6810 style = elem.style; 6811 6812 name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); 6813 6814 // gets hook for the prefixed version 6815 // followed by the unprefixed version 6816 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; 6817 6818 // Check if we're setting a value 6819 if ( value !== undefined ) { 6820 type = typeof value; 6821 6822 // convert relative number strings (+= or -=) to relative numbers. #7345 6823 if ( type === "string" && (ret = rrelNum.exec( value )) ) { 6824 value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); 6825 // Fixes bug #9237 6826 type = "number"; 6827 } 6828 6829 // Make sure that NaN and null values aren't set. See: #7116 6830 if ( value == null || type === "number" && isNaN( value ) ) { 6831 return; 6832 } 6833 6834 // If a number was passed in, add 'px' to the (except for certain CSS properties) 6835 if ( type === "number" && !jQuery.cssNumber[ origName ] ) { 6836 value += "px"; 6837 } 6838 6839 // Fixes #8908, it can be done more correctly by specifing setters in cssHooks, 6840 // but it would mean to define eight (for every problematic property) identical functions 6841 if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) { 6842 style[ name ] = "inherit"; 6843 } 6844 6845 // If a hook was provided, use that value, otherwise just set the specified value 6846 if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { 6847
6848 // Wrapped to prevent IE from throwing errors when 'invalid' values are provided 6849 // Fixes bug #5509 6850 try { 6851 style[ name ] = value; 6852 } catch(e) {} 6853 } 6854 6855 } else { 6856 // If a hook was provided get the non-computed value from there 6857 if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { 6858 return ret; 6859 } 6860 6861 // Otherwise just get the value from the style object 6862 return style[ name ]; 6863 } 6864 }, 6865 6866 css: function( elem, name, extra, styles ) { 6867 var num, val, hooks, 6868 origName = jQuery.camelCase( name ); 6869 6870 // Make sure that we're working with the right name 6871 name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); 6872 6873 // gets hook for the prefixed version 6874 // followed by the unprefixed version 6875 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; 6876 6877 // If a hook was provided get the computed value from there 6878 if ( hooks && "get" in hooks ) { 6879 val = hooks.get( elem, true, extra ); 6880 } 6881 6882 // Otherwise, if a way to get the computed value exists, use that 6883 if ( val === undefined ) { 6884 val = curCSS( elem, name, styles ); 6885 } 6886 6887 //convert "normal" to computed value 6888 if ( val === "normal" && name in cssNormalTransform ) { 6889 val = cssNormalTransform[ name ]; 6890 } 6891 6892 // Return, converting to number if forced or a qualifier was provided and val looks numeric 6893 if ( extra === "" || extra ) { 6894 num = parseFloat( val ); 6895 return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; 6896 } 6897 return val; 6898 }, 6899 6900 // A method for quickly swapping in/out CSS properties to get correct calculations 6901 swap: function( elem, options, callback, args ) { 6902 var ret, name, 6903 old = {}; 6904 6905 // Remember the old values, and insert the new ones 6906 for ( name in options ) { 6907 old[ name ] = elem.style[ name ]; 6908 elem.style[ name ] = options[ name ]; 6909 } 6910 6911 ret = callback.apply( elem, args || [] ); 6912 6913 // Revert the old values 6914 for ( name in options ) { 6915 elem.style[ name ] = old[ name ]; 6916 } 6917 6918 return ret; 6919 } 6920}); 6921 6922// NOTE: we've included the "window" in window.getComputedStyle 6923// because jsdom on node.js will break without it. 6924if ( window.getComputedStyle ) { 6925 getStyles = function( elem ) { 6926 return window.getComputedStyle( elem, null ); 6927 }; 6928 6929 curCSS = function( elem, name, _computed ) { 6930 var width, minWidth, maxWidth, 6931 computed = _computed || getStyles( elem ), 6932 6933 // getPropertyValue is only needed for .css('filter') in IE9, see #12537 6934 ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined, 6935 style = elem.style; 6936 6937 if ( computed ) { 6938 6939 if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { 6940 ret = jQuery.style( elem, name ); 6941 } 6942 6943 // A tribute to the "awesome hack by Dean Edwards" 6944 // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right 6945 // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels 6946 // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values 6947 if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { 6948 6949 // Remember the original values 6950 width = style.width; 6951 minWidth = style.minWidth; 6952 maxWidth = style.maxWidth; 6953 6954 // Put in the new values to get a computed value out 6955 style.minWidth = style.maxWidth = style.width = ret; 6956 ret = computed.width; 6957 6958 // Revert the changed values 6959 style.width = width; 6960 style.minWidth = minWidth; 6961 style.maxWidth = maxWidth; 6962 } 6963 } 6964 6965 return ret; 6966 }; 6967} else if ( document.documentElement.currentStyle ) { 6968 getStyles = function( elem ) { 6969 return elem.currentStyle; 6970 }; 6971 6972 curCSS = function( elem, name, _computed ) { 6973 var left, rs, rsLeft, 6974 computed = _computed || getStyles( elem ), 6975 ret = computed ? computed[ name ] : undefined, 6976 style = elem.style; 6977 6978 // Avoid setting ret to empty string here 6979 // so we don't default to auto 6980 if ( ret == null && style && style[ name ] ) { 6981 ret = style[ name ]; 6982 } 6983 6984 // From the awesome hack by Dean Edwards 6985 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 6986 6987 // If we're not dealing with a regular pixel number 6988 // but a number that has a weird ending, we need to convert it to pixels 6989 // but not position css attributes, as those are proportional to the parent element instead 6990 // and we can't measure the parent instead because it might trigger a "stacking dolls" problem 6991 if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) { 6992 6993 // Remember the original values 6994 left = style.left; 6995 rs = elem.runtimeStyle; 6996 rsLeft = rs && rs.left; 6997 6998 // Put in the new values to get a computed value out 6999 if ( rsLeft ) { 7000 rs.left = elem.currentStyle.left; 7001 } 7002 style.left = name === "fontSize" ? "1em" : ret; 7003 ret = style.pixelLeft + "px"; 7004 7005 // Revert the changed values 7006 style.left = left; 7007 if ( rsLeft ) { 7008 rs.left = rsLeft; 7009 } 7010 } 7011 7012 return ret === "" ? "auto" : ret; 7013 }; 7014} 7015 7016function setPositiveNumber( elem, value, subtract ) { 7017 var matches = rnumsplit.exec( value ); 7018 return matches ? 7019 // Guard against undefined "subtract", e.g., when used as in cssHooks 7020 Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : 7021 value; 7022} 7023 7024function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { 7025 var i = extra === ( isBorderBox ? "border" : "content" ) ? 7026 // If we already have the right measurement, avoid augmentation 7027 4 : 7028 // Otherwise initialize for horizontal or vertical properties 7029 name === "width" ? 1 : 0, 7030 7031 val = 0; 7032 7033 for ( ; i < 4; i += 2 ) { 7034 // both box models exclude margin, so add it if we want it 7035 if ( extra === "margin" ) { 7036 val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); 7037 } 7038 7039 if ( isBorderBox ) { 7040 // border-box includes padding, so remove it if we want content 7041 if ( extra === "content" ) { 7042 val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); 7043 } 7044 7045 // at this point, extra isn't border nor margin, so remove border 7046 if ( extra !== "margin" ) { 7047 val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); 7048 } 7049 } else { 7050 // at this point, extra isn't content, so add padding 7051 val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); 7052 7053 // at this point, extra isn't content nor padding, so add border 7054 if ( extra !== "padding" ) { 7055 val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); 7056 } 7057 } 7058 } 7059 7060 return val; 7061} 7062 7063function getWidthOrHeight( elem, name, extra ) { 7064 7065 // Start with offset property, which is equivalent to the border-box value 7066 var valueIsBorderBox = true, 7067 val = name === "width" ? elem.offsetWidth : elem.offsetHeight, 7068 styles = getStyles( elem ), 7069 isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; 7070 7071 // some non-html elements return undefined for offsetWidth, so check for null/undefined 7072 // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 7073 // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 7074 if ( val <= 0 || val == null ) { 7075 // Fall back to computed then uncomputed css if necessary 7076 val = curCSS( elem, name, styles ); 7077 if ( val < 0 || val == null ) { 7078 val = elem.style[ name ]; 7079 } 7080 7081 // Computed unit is not pixels. Stop here and return. 7082 if ( rnumnonpx.test(val) ) { 7083 return val; 7084 } 7085 7086 // we need the check for style in case a browser which returns unreliable values 7087 // for getComputedStyle silently falls back to the reliable elem.style 7088 valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] ); 7089 7090 // Normalize "", auto, and prepare for extra 7091 val = parseFloat( val ) || 0; 7092 } 7093 7094 // use the active box-sizing model to add/subtract irrelevant styles 7095 return ( val + 7096 augmentWidthOrHeight( 7097 elem, 7098 name, 7099 extra || ( isBorderBox ? "border" : "content" ), 7100 valueIsBorderBox, 7101 styles 7102 ) 7103 ) + "px"; 7104} 7105 7106// Try to determine the default display value of an element 7107function css_defaultDisplay( nodeName ) { 7108 var doc = document, 7109 display = elemdisplay[ nodeName ]; 7110 7111 if ( !display ) { 7112 display = actualDisplay( nodeName, doc ); 7113 7114 // If the simple way fails, read from inside an iframe 7115 if ( display === "none" || !display ) { 7116 // Use the already-created iframe if possible 7117 iframe = ( iframe || 7118 jQuery("<iframe frameborder='0' width='0' height='0'/>") 7119 .css( "cssText", "display:block !important" ) 7120 ).appendTo( doc.documentElement ); 7121
7122 // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse 7123 doc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document; 7124 doc.write("<!doctype html><html><body>"); 7125 doc.close(); 7126 7127 display = actualDisplay( nodeName, doc ); 7128 iframe.detach(); 7129 } 7130 7131 // Store the correct default display 7132 elemdisplay[ nodeName ] = display; 7133 } 7134 7135 return display; 7136} 7137 7138// Called ONLY from within css_defaultDisplay 7139function actualDisplay( name, doc ) { 7140 var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), 7141 display = jQuery.css( elem[0], "display" ); 7142 elem.remove(); 7143 return display; 7144} 7145 7146jQuery.each([ "height", "width" ], function( i, name ) { 7147 jQuery.cssHooks[ name ] = { 7148 get: function( elem, computed, extra ) { 7149 if ( computed ) { 7150 // certain elements can have dimension info if we invisibly show them 7151 // however, it must have a current display style that would benefit from this 7152 return elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ? 7153 jQuery.swap( elem, cssShow, function() { 7154 return getWidthOrHeight( elem, name, extra ); 7155 }) : 7156 getWidthOrHeight( elem, name, extra ); 7157 } 7158 }, 7159 7160 set: function( elem, value, extra ) { 7161 var styles = extra && getStyles( elem ); 7162 return setPositiveNumber( elem, value, extra ? 7163 augmentWidthOrHeight( 7164 elem, 7165 name, 7166 extra, 7167 jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box", 7168 styles 7169 ) : 0 7170 ); 7171 } 7172 }; 7173}); 7174 7175if ( !jQuery.support.opacity ) { 7176 jQuery.cssHooks.opacity = { 7177 get: function( elem, computed ) { 7178 // IE uses filters for opacity 7179 return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ? 7180 ( 0.01 * parseFloat( RegExp.$1 ) ) + "" : 7181 computed ? "1" : ""; 7182 }, 7183 7184 set: function( elem, value ) { 7185 var style = elem.style, 7186 currentStyle = elem.currentStyle, 7187 opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "", 7188 filter = currentStyle && currentStyle.filter || style.filter || ""; 7189 7190 // IE has trouble with opacity if it does not have layout 7191 // Force it by setting the zoom level 7192 style.zoom = 1; 7193 7194 // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652 7195 // if value === "", then remove inline opacity #12685 7196 if ( ( value >= 1 || value === "" ) && 7197 jQuery.trim( filter.replace( ralpha, "" ) ) === "" && 7198 style.removeAttribute ) { 7199 7200 // Setting style.filter to null, "" & " " still leave "filter:" in the cssText 7201 // if "filter:" is present at all, clearType is disabled, we want to avoid this 7202 // style.removeAttribute is IE Only, but so apparently is this code path... 7203 style.removeAttribute( "filter" ); 7204 7205 // if there is no filter style applied in a css rule or unset inline opacity, we are done 7206 if ( value === "" || currentStyle && !currentStyle.filter ) { 7207 return; 7208 } 7209 } 7210 7211 // otherwise, set new filter values 7212 style.filter = ralpha.test( filter ) ? 7213 filter.replace( ralpha, opacity ) : 7214 filter + " " + opacity; 7215 } 7216 }; 7217} 7218 7219// These hooks cannot be added until DOM ready because the support test 7220// for it is not run until after DOM ready 7221jQuery(function() { 7222 if ( !jQuery.support.reliableMarginRight ) { 7223 jQuery.cssHooks.marginRight = { 7224 get: function( elem, computed ) { 7225 if ( computed ) { 7226 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right 7227 // Work around by temporarily setting element display to inline-block 7228 return jQuery.swap( elem, { "display": "inline-block" }, 7229 curCSS, [ elem, "marginRight" ] ); 7230 } 7231 } 7232 }; 7233 } 7234 7235 // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084 7236 // getComputedStyle returns percent when specified for top/left/bottom/right 7237 // rather than make the css module depend on the offset module, we just check for it here 7238 if ( !jQuery.support.pixelPosition && jQuery.fn.position ) { 7239 jQuery.each( [ "top", "left" ], function( i, prop ) { 7240 jQuery.cssHooks[ prop ] = { 7241 get: function( elem, computed ) { 7242 if ( computed ) { 7243 computed = curCSS( elem, prop ); 7244 // if curCSS returns percentage, fallback to offset 7245 return rnumnonpx.test( computed ) ? 7246 jQuery( elem ).position()[ prop ] + "px" : 7247 computed; 7248 } 7249 } 7250 }; 7251 }); 7252 } 7253 7254}); 7255 7256if ( jQuery.expr && jQuery.expr.filters ) { 7257 jQuery.expr.filters.hidden = function( elem ) {
7258 // Support: Opera <= 12.12 7259 // Opera reports offsetWidths and offsetHeights less than zero on some elements 7260 return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 || 7261 (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none"); 7262 }; 7263 7264 jQuery.expr.filters.visible = function( elem ) { 7265 return !jQuery.expr.filters.hidden( elem ); 7266 }; 7267} 7268 7269// These hooks are used by animate to expand properties 7270jQuery.each({ 7271 margin: "", 7272 padding: "", 7273 border: "Width" 7274}, function( prefix, suffix ) { 7275 jQuery.cssHooks[ prefix + suffix ] = { 7276 expand: function( value ) { 7277 var i = 0, 7278 expanded = {}, 7279 7280 // assumes a single number if not a string 7281 parts = typeof value === "string" ? value.split(" ") : [ value ]; 7282 7283 for ( ; i < 4; i++ ) { 7284 expanded[ prefix + cssExpand[ i ] + suffix ] = 7285 parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; 7286 } 7287 7288 return expanded; 7289 } 7290 }; 7291 7292 if ( !rmargin.test( prefix ) ) { 7293 jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; 7294 } 7295}); 7296var r20 = /%20/g, 7297 rbracket = /\[\]$/, 7298 rCRLF = /\r?\n/g, 7299 rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, 7300 rsubmittable = /^(?:input|select|textarea|keygen)/i; 7301 7302jQuery.fn.extend({ 7303 serialize: function() { 7304 return jQuery.param( this.serializeArray() ); 7305 }, 7306 serializeArray: function() { 7307 return this.map(function(){ 7308 // Can add propHook for "elements" to filter or add form elements 7309 var elements = jQuery.prop( this, "elements" ); 7310 return elements ? jQuery.makeArray( elements ) : this; 7311 }) 7312 .filter(function(){ 7313 var type = this.type; 7314 // Use .is(":disabled") so that fieldset[disabled] works 7315 return this.name && !jQuery( this ).is( ":disabled" ) && 7316 rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && 7317 ( this.checked || !manipulation_rcheckableType.test( type ) ); 7318 }) 7319 .map(function( i, elem ){ 7320 var val = jQuery( this ).val(); 7321 7322 return val == null ? 7323 null : 7324 jQuery.isArray( val ) ? 7325 jQuery.map( val, function( val ){ 7326 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; 7327 }) : 7328 { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; 7329 }).get(); 7330 } 7331}); 7332 7333//Serialize an array of form elements or a set of 7334//key/values into a query string 7335jQuery.param = function( a, traditional ) { 7336 var prefix, 7337 s = [], 7338 add = function( key, value ) { 7339 // If value is a function, invoke it and return its value 7340 value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value ); 7341 s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value ); 7342 }; 7343 7344 // Set traditional to true for jQuery <= 1.3.2 behavior. 7345 if ( traditional === undefined ) { 7346 traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional; 7347 } 7348 7349 // If an array was passed in, assume that it is an array of form elements. 7350 if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { 7351 // Serialize the form elements 7352 jQuery.each( a, function() { 7353 add( this.name, this.value ); 7354 }); 7355 7356 } else { 7357 // If traditional, encode the "old" way (the way 1.3.2 or older 7358 // did it), otherwise encode params recursively. 7359 for ( prefix in a ) { 7360 buildParams( prefix, a[ prefix ], traditional, add ); 7361 } 7362 } 7363 7364 // Return the resulting serialization 7365 return s.join( "&" ).replace( r20, "+" ); 7366}; 7367 7368function buildParams( prefix, obj, traditional, add ) { 7369 var name; 7370 7371 if ( jQuery.isArray( obj ) ) { 7372 // Serialize array item. 7373 jQuery.each( obj, function( i, v ) { 7374 if ( traditional || rbracket.test( prefix ) ) { 7375 // Treat each array item as a scalar. 7376 add( prefix, v ); 7377 7378 } else { 7379 // Item is non-scalar (array or object), encode its numeric index. 7380 buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add ); 7381 } 7382 }); 7383 7384 } else if ( !traditional && jQuery.type( obj ) === "object" ) { 7385 // Serialize object item. 7386 for ( name in obj ) { 7387 buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); 7388 } 7389 7390 } else { 7391 // Serialize scalar item. 7392 add( prefix, obj ); 7393 } 7394} 7395jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + 7396 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + 7397 "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { 7398 7399 // Handle event binding 7400 jQuery.fn[ name ] = function( data, fn ) { 7401 return arguments.length > 0 ? 7402 this.on( name, null, data, fn ) : 7403 this.trigger( name ); 7404 }; 7405}); 7406 7407jQuery.fn.hover = function( fnOver, fnOut ) { 7408 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); 7409}; 7410var 7411 // Document location 7412 ajaxLocParts, 7413 ajaxLocation, 7414 ajax_nonce = jQuery.now(), 7415 7416 ajax_rquery = /\?/, 7417 rhash = /#.*$/, 7418 rts = /([?&])_=[^&]*/, 7419 rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
7420 // #7653, #8125, #8152: local protocol detection 7421 rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, 7422 rnoContent = /^(?:GET|HEAD)$/, 7423 rprotocol = /^\/\//, 7424 rurl = /^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/, 7425 7426 // Keep a copy of the old load method 7427 _load = jQuery.fn.load, 7428 7429 /* Prefilters 7430 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) 7431 * 2) These are called: 7432 * - BEFORE asking for a transport 7433 * - AFTER param serialization (s.data is a string if s.processData is true) 7434 * 3) key is the dataType 7435 * 4) the catchall symbol "*" can be used 7436 * 5) execution will start with transport dataType and THEN continue down to "*" if needed 7437 */ 7438 prefilters = {}, 7439 7440 /* Transports bindings 7441 * 1) key is the dataType 7442 * 2) the catchall symbol "*" can be used 7443 * 3) selection will start with transport dataType and THEN go to "*" if needed 7444 */ 7445 transports = {}, 7446 7447 // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression 7448 allTypes = "*/".concat("*"); 7449 7450// #8138, IE may throw an exception when accessing 7451// a field from window.location if document.domain has been set 7452try { 7453 ajaxLocation = location.href; 7454} catch( e ) { 7455 // Use the href attribute of an A element 7456 // since IE will modify it given document.location 7457 ajaxLocation = document.createElement( "a" ); 7458 ajaxLocation.href = ""; 7459 ajaxLocation = ajaxLocation.href; 7460} 7461 7462// Segment location into parts 7463ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || []; 7464 7465// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport 7466function addToPrefiltersOrTransports( structure ) { 7467 7468 // dataTypeExpression is optional and defaults to "*" 7469 return function( dataTypeExpression, func ) { 7470 7471 if ( typeof dataTypeExpression !== "string" ) { 7472 func = dataTypeExpression; 7473 dataTypeExpression = "*"; 7474 } 7475 7476 var dataType, 7477 i = 0, 7478 dataTypes = dataTypeExpression.toLowerCase().match( core_rnotwhite ) || []; 7479 7480 if ( jQuery.isFunction( func ) ) { 7481 // For each dataType in the dataTypeExpression 7482 while ( (dataType = dataTypes[i++]) ) { 7483 // Prepend if requested 7484 if ( dataType[0] === "+" ) { 7485 dataType = dataType.slice( 1 ) || "*"; 7486 (structure[ dataType ] = structure[ dataType ] || []).unshift( func ); 7487 7488 // Otherwise append 7489 } else { 7490 (structure[ dataType ] = structure[ dataType ] || []).push( func ); 7491 } 7492 } 7493 } 7494 }; 7495} 7496 7497// Base inspection function for prefilters and transports 7498function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { 7499 7500 var inspected = {}, 7501 seekingTransport = ( structure === transports ); 7502 7503 function inspect( dataType ) { 7504 var selected; 7505 inspected[ dataType ] = true; 7506 jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { 7507 var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); 7508 if( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) { 7509 options.dataTypes.unshift( dataTypeOrTransport ); 7510 inspect( dataTypeOrTransport ); 7511 return false; 7512 } else if ( seekingTransport ) { 7513 return !( selected = dataTypeOrTransport ); 7514 } 7515 }); 7516 return selected; 7517 } 7518 7519 return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); 7520} 7521 7522// A special extend for ajax options 7523// that takes "flat" options (not to be deep extended) 7524// Fixes #9887 7525function ajaxExtend( target, src ) { 7526 var deep, key, 7527 flatOptions = jQuery.ajaxSettings.flatOptions || {}; 7528 7529 for ( key in src ) { 7530 if ( src[ key ] !== undefined ) { 7531 ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ]; 7532 } 7533 } 7534 if ( deep ) { 7535 jQuery.extend( true, target, deep ); 7536 } 7537 7538 return target; 7539} 7540 7541jQuery.fn.load = function( url, params, callback ) { 7542 if ( typeof url !== "string" && _load ) { 7543 return _load.apply( this, arguments ); 7544 } 7545 7546 var selector, response, type, 7547 self = this, 7548 off = url.indexOf(" "); 7549 7550 if ( off >= 0 ) { 7551 selector = url.slice( off, url.length ); 7552 url = url.slice( 0, off ); 7553 } 7554 7555 // If it's a function 7556 if ( jQuery.isFunction( params ) ) { 7557 7558 // We assume that it's the callback 7559 callback = params; 7560 params = undefined; 7561 7562 // Otherwise, build a param string 7563 } else if ( params && typeof params === "object" ) {
7564 type = "POST"; 7565 } 7566 7567 // If we have elements to modify, make the request 7568 if ( self.length > 0 ) { 7569 jQuery.ajax({ 7570 url: url, 7571 7572 // if "type" variable is undefined, then "GET" method will be used 7573 type: type, 7574 dataType: "html", 7575 data: params 7576 }).done(function( responseText ) { 7577 7578 // Save response for use in complete callback 7579 response = arguments; 7580 7581 self.html( selector ? 7582 7583 // If a selector was specified, locate the right elements in a dummy div 7584 // Exclude scripts to avoid IE 'Permission Denied' errors 7585 jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) : 7586 7587 // Otherwise use the full result 7588 responseText ); 7589 7590 }).complete( callback && function( jqXHR, status ) { 7591 self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] ); 7592 }); 7593 } 7594 7595 return this; 7596}; 7597 7598// Attach a bunch of functions for handling common AJAX events 7599jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ){ 7600 jQuery.fn[ type ] = function( fn ){ 7601 return this.on( type, fn ); 7602 }; 7603}); 7604 7605jQuery.each( [ "get", "post" ], function( i, method ) { 7606 jQuery[ method ] = function( url, data, callback, type ) { 7607 // shift arguments if data argument was omitted 7608 if ( jQuery.isFunction( data ) ) { 7609 type = type || callback; 7610 callback = data; 7611 data = undefined; 7612 } 7613 7614 return jQuery.ajax({ 7615 url: url, 7616 type: method, 7617 dataType: type, 7618 data: data, 7619 success: callback 7620 }); 7621 }; 7622}); 7623 7624jQuery.extend({ 7625 7626 // Counter for holding the number of active queries 7627 active: 0, 7628 7629 // Last-Modified header cache for next request 7630 lastModified: {}, 7631 etag: {}, 7632 7633 ajaxSettings: { 7634 url: ajaxLocation, 7635 type: "GET", 7636 isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ), 7637 global: true, 7638 processData: true, 7639 async: true, 7640 contentType: "application/x-www-form-urlencoded; charset=UTF-8", 7641 /* 7642 timeout: 0, 7643 data: null, 7644 dataType: null, 7645 username: null, 7646 password: null, 7647 cache: null, 7648 throws: false, 7649 traditional: false, 7650 headers: {}, 7651 */ 7652 7653 accepts: { 7654 "*": allTypes, 7655 text: "text/plain", 7656 html: "text/html", 7657 xml: "application/xml, text/xml", 7658 json: "application/json, text/javascript" 7659 }, 7660 7661 contents: { 7662 xml: /xml/, 7663 html: /html/, 7664 json: /json/ 7665 }, 7666 7667 responseFields: { 7668 xml: "responseXML", 7669 text: "responseText" 7670 }, 7671 7672 // Data converters 7673 // Keys separate source (or catchall "*") and destination types with a single space 7674 converters: { 7675 7676 // Convert anything to text 7677 "* text": window.String, 7678 7679 // Text to html (true = no transformation) 7680 "text html": true, 7681 7682 // Evaluate text as a json expression 7683 "text json": jQuery.parseJSON, 7684 7685 // Parse text as xml 7686 "text xml": jQuery.parseXML 7687 }, 7688 7689 // For options that shouldn't be deep extended: 7690 // you can add your own custom options here if 7691 // and when you create one that shouldn't be 7692 // deep extended (see ajaxExtend) 7693 flatOptions: { 7694 url: true, 7695 context: true 7696 } 7697 }, 7698 7699 // Creates a full fledged settings object into target 7700 // with both ajaxSettings and settings fields. 7701 // If target is omitted, writes into ajaxSettings. 7702 ajaxSetup: function( target, settings ) { 7703 return settings ? 7704 7705 // Building a settings object 7706 ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : 7707 7708 // Extending ajaxSettings 7709 ajaxExtend( jQuery.ajaxSettings, target ); 7710 }, 7711 7712 ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), 7713 ajaxTransport: addToPrefiltersOrTransports( transports ), 7714 7715 // Main method 7716 ajax: function( url, options ) { 7717 7718 // If url is an object, simulate pre-1.5 signature 7719 if ( typeof url === "object" ) { 7720 options = url; 7721 url = undefined; 7722 } 7723 7724 // Force options to be an object 7725 options = options || {}; 7726 7727 var // Cross-domain detection vars 7728 parts, 7729 // Loop variable 7730 i, 7731 // URL without anti-cache param 7732 cacheURL, 7733 // Response headers as string 7734 responseHeadersString, 7735 // timeout handle 7736 timeoutTimer, 7737 7738 // To know if global events are to be dispatched 7739 fireGlobals, 7740 7741 transport, 7742 // Response headers 7743 responseHeaders, 7744 // Create the final options object 7745 s = jQuery.ajaxSetup( {}, options ), 7746 // Callbacks context 7747 callbackContext = s.context || s, 7748 // Context for global events is callbackContext if it is a DOM node or jQuery collection 7749 globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ? 7750 jQuery( callbackContext ) : 7751 jQuery.event, 7752 // Deferreds 7753 deferred = jQuery.Deferred(), 7754 completeDeferred = jQuery.Callbacks("once memory"), 7755 // Status-dependent callbacks 7756 statusCode = s.statusCode || {}, 7757 // Headers (they are sent all at once) 7758 requestHeaders = {}, 7759 requestHeadersNames = {}, 7760 // The jqXHR state 7761 state = 0, 7762 // Default abort message 7763 strAbort = "canceled", 7764 // Fake xhr 7765 jqXHR = { 7766 readyState: 0, 7767 7768 // Builds headers hashtable if needed 7769 getResponseHeader: function( key ) { 7770 var match; 7771 if ( state === 2 ) { 7772 if ( !responseHeaders ) { 7773 responseHeaders = {}; 7774 while ( (match = rheaders.exec( responseHeadersString )) ) { 7775 responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; 7776 } 7777 } 7778 match = responseHeaders[ key.toLowerCase() ]; 7779 } 7780 return match == null ? null : match; 7781 }, 7782 7783 // Raw string 7784 getAllResponseHeaders: function() { 7785 return state === 2 ? responseHeadersString : null; 7786 }, 7787 7788 // Caches the header 7789 setRequestHeader: function( name, value ) { 7790 var lname = name.toLowerCase(); 7791 if ( !state ) { 7792 name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; 7793 requestHeaders[ name ] = value; 7794 } 7795 return this; 7796 }, 7797 7798 // Overrides response content-type header 7799 overrideMimeType: function( type ) { 7800 if ( !state ) { 7801 s.mimeType = type; 7802 } 7803 return this; 7804 }, 7805 7806 // Status-dependent callbacks 7807 statusCode: function( map ) { 7808 var code; 7809 if ( map ) { 7810 if ( state < 2 ) { 7811 for ( code in map ) { 7812 // Lazy-add the new callback in a way that preserves old ones 7813 statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; 7814 } 7815 } else { 7816 // Execute the appropriate callbacks 7817 jqXHR.always( map[ jqXHR.status ] ); 7818 } 7819 } 7820 return this; 7821 }, 7822 7823 // Cancel the request 7824 abort: function( statusText ) { 7825 var finalText = statusText || strAbort; 7826 if ( transport ) { 7827 transport.abort( finalText ); 7828 } 7829 done( 0, finalText ); 7830 return this; 7831 } 7832 }; 7833 7834 // Attach deferreds 7835 deferred.promise( jqXHR ).complete = completeDeferred.add; 7836 jqXHR.success = jqXHR.done; 7837 jqXHR.error = jqXHR.fail; 7838 7839 // Remove hash character (#7531: and string promotion) 7840 // Add protocol if not provided (#5866: IE7 issue with protocol-less urls) 7841 // Handle falsy url in the settings object (#10093: consistency with old signature) 7842 // We also use the url parameter if available 7843 s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); 7844 7845 // Alias method option to type as per ticket #12004 7846 s.type = options.method || options.type || s.method || s.type; 7847 7848 // Extract dataTypes list 7849 s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( core_rnotwhite ) || [""]; 7850 7851 // A cross-domain request is in order when we have a protocol:host:port mismatch 7852 if ( s.crossDomain == null ) { 7853 parts = rurl.exec( s.url.toLowerCase() ); 7854 s.crossDomain = !!( parts && 7855 ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] || 7856 ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) != 7857 ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) ) 7858 ); 7859 } 7860 7861 // Convert data if not already a string 7862 if ( s.data && s.processData && typeof s.data !== "string" ) { 7863 s.data = jQuery.param( s.data, s.traditional ); 7864 } 7865 7866 // Apply prefilters 7867 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); 7868 7869 // If request was aborted inside a prefilter, stop there 7870 if ( state === 2 ) { 7871 return jqXHR; 7872 } 7873 7874 // We can fire global events as of now if asked to 7875 fireGlobals = s.global; 7876 7877 // Watch for a new set of requests 7878 if ( fireGlobals && jQuery.active++ === 0 ) { 7879 jQuery.event.trigger("ajaxStart"); 7880 } 7881 7882 // Uppercase the type 7883 s.type = s.type.toUpperCase(); 7884 7885 // Determine if request has content 7886 s.hasContent = !rnoContent.test( s.type ); 7887 7888 // Save the URL in case we're toying with the If-Modified-Since 7889 // and/or If-None-Match header later on 7890 cacheURL = s.url; 7891 7892 // More options handling for requests with no content 7893 if ( !s.hasContent ) { 7894 7895 // If data is available, append data to url 7896 if ( s.data ) {
7897 cacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + s.data ); 7898 // #9682: remove data so that it's not used in an eventual retry 7899 delete s.data; 7900 } 7901 7902 // Add anti-cache in url if needed 7903 if ( s.cache === false ) { 7904 s.url = rts.test( cacheURL ) ? 7905 7906 // If there is already a '_' parameter, set its value 7907 cacheURL.replace( rts, "$1_=" + ajax_nonce++ ) : 7908 7909 // Otherwise add one to the end 7910 cacheURL + ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ajax_nonce++; 7911 } 7912 } 7913 7914 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. 7915 if ( s.ifModified ) { 7916 if ( jQuery.lastModified[ cacheURL ] ) { 7917 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); 7918 } 7919 if ( jQuery.etag[ cacheURL ] ) { 7920 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); 7921 } 7922 } 7923 7924 // Set the correct header, if data is being sent 7925 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { 7926 jqXHR.setRequestHeader( "Content-Type", s.contentType ); 7927 } 7928 7929 // Set the Accepts header for the server, depending on the dataType 7930 jqXHR.setRequestHeader( 7931 "Accept", 7932 s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? 7933 s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : 7934 s.accepts[ "*" ] 7935 ); 7936 7937 // Check for headers option 7938 for ( i in s.headers ) { 7939 jqXHR.setRequestHeader( i, s.headers[ i ] ); 7940 } 7941 7942 // Allow custom headers/mimetypes and early abort 7943 if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { 7944 // Abort if not done already and return 7945 return jqXHR.abort(); 7946 } 7947 7948 // aborting is no longer a cancellation 7949 strAbort = "abort"; 7950 7951 // Install callbacks on deferreds 7952 for ( i in { success: 1, error: 1, complete: 1 } ) { 7953 jqXHR[ i ]( s[ i ] ); 7954 } 7955 7956 // Get transport 7957 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); 7958 7959 // If no transport, we auto-abort 7960 if ( !transport ) { 7961 done( -1, "No Transport" ); 7962 } else { 7963 jqXHR.readyState = 1; 7964 7965 // Send global event 7966 if ( fireGlobals ) { 7967 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); 7968 } 7969 // Timeout 7970 if ( s.async && s.timeout > 0 ) { 7971 timeoutTimer = setTimeout(function() { 7972 jqXHR.abort("timeout"); 7973 }, s.timeout ); 7974 } 7975 7976 try { 7977 state = 1; 7978 transport.send( requestHeaders, done ); 7979 } catch ( e ) { 7980 // Propagate exception as error if not done 7981 if ( state < 2 ) { 7982 done( -1, e ); 7983 // Simply rethrow otherwise 7984 } else { 7985 throw e; 7986 } 7987 } 7988 } 7989 7990 // Callback for when everything is done 7991 function done( status, nativeStatusText, responses, headers ) { 7992 var isSuccess, success, error, response, modified, 7993 statusText = nativeStatusText; 7994 7995 // Called once 7996 if ( state === 2 ) { 7997 return; 7998 } 7999 8000 // State is "done" now 8001 state = 2; 8002 8003 // Clear timeout if it exists 8004 if ( timeoutTimer ) { 8005 clearTimeout( timeoutTimer ); 8006 } 8007 8008 // Dereference transport for early garbage collection 8009 // (no matter how long the jqXHR object will be used) 8010 transport = undefined; 8011 8012 // Cache response headers 8013 responseHeadersString = headers || ""; 8014 8015 // Set readyState 8016 jqXHR.readyState = status > 0 ? 4 : 0; 8017 8018 // Get response data 8019 if ( responses ) { 8020 response = ajaxHandleResponses( s, jqXHR, responses ); 8021 } 8022 8023 // If successful, handle type chaining 8024 if ( status >= 200 && status < 300 || status === 304 ) { 8025 8026 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. 8027 if ( s.ifModified ) { 8028 modified = jqXHR.getResponseHeader("Last-Modified"); 8029 if ( modified ) { 8030 jQuery.lastModified[ cacheURL ] = modified; 8031 } 8032 modified = jqXHR.getResponseHeader("etag"); 8033 if ( modified ) { 8034 jQuery.etag[ cacheURL ] = modified; 8035 } 8036 } 8037 8038 // if no content 8039 if ( status === 204 ) { 8040 isSuccess = true; 8041 statusText = "nocontent"; 8042 8043 // if not modified 8044 } else if ( status === 304 ) { 8045 isSuccess = true; 8046 statusText = "notmodified"; 8047 8048 // If we have data, let's convert it 8049 } else { 8050 isSuccess = ajaxConvert( s, response ); 8051 statusText = isSuccess.state; 8052 success = isSuccess.data; 8053 error = isSuccess.error; 8054 isSuccess = !error; 8055 } 8056 } else { 8057 // We extract error from statusText 8058 // then normalize statusText and status for non-aborts 8059 error = statusText; 8060 if ( status || !statusText ) { 8061 statusText = "error"; 8062 if ( status < 0 ) { 8063 status = 0; 8064 } 8065 } 8066 } 8067 8068 // Set data for the fake xhr object 8069 jqXHR.status = status; 8070 jqXHR.statusText = ( nativeStatusText || statusText ) + ""; 8071 8072 // Success/Error 8073 if ( isSuccess ) { 8074 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); 8075 } else { 8076 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); 8077 } 8078 8079 // Status-dependent callbacks 8080 jqXHR.statusCode( statusCode ); 8081 statusCode = undefined; 8082 8083 if ( fireGlobals ) { 8084 globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", 8085 [ jqXHR, s, isSuccess ? success : error ] ); 8086 } 8087 8088 // Complete 8089 completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); 8090 8091 if ( fireGlobals ) { 8092 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); 8093 // Handle the global AJAX counter 8094 if ( !( --jQuery.active ) ) { 8095 jQuery.event.trigger("ajaxStop"); 8096 } 8097 } 8098 } 8099 8100 return jqXHR; 8101 }, 8102 8103 getScript: function( url, callback ) { 8104 return jQuery.get( url, undefined, callback, "script" ); 8105 }, 8106 8107 getJSON: function( url, data, callback ) { 8108 return jQuery.get( url, data, callback, "json" ); 8109 } 8110}); 8111 8112/* Handles responses to an ajax request: 8113 * - sets all responseXXX fields accordingly 8114 * - finds the right dataType (mediates between content-type and expected dataType) 8115 * - returns the corresponding response 8116 */ 8117function ajaxHandleResponses( s, jqXHR, responses ) { 8118 var firstDataType, ct, finalDataType, type, 8119 contents = s.contents, 8120 dataTypes = s.dataTypes, 8121 responseFields = s.responseFields; 8122 8123 // Fill responseXXX fields 8124 for ( type in responseFields ) { 8125 if ( type in responses ) { 8126 jqXHR[ responseFields[type] ] = responses[ type ]; 8127 } 8128 } 8129 8130 // Remove auto dataType and get content-type in the process 8131 while( dataTypes[ 0 ] === "*" ) { 8132 dataTypes.shift(); 8133 if ( ct === undefined ) { 8134 ct = s.mimeType || jqXHR.getResponseHeader("Content-Type"); 8135 } 8136 } 8137 8138 // Check if we're dealing with a known content-type 8139 if ( ct ) { 8140 for ( type in contents ) { 8141 if ( contents[ type ] && contents[ type ].test( ct ) ) { 8142 dataTypes.unshift( type ); 8143 break; 8144 } 8145 } 8146 } 8147 8148 // Check to see if we have a response for the expected dataType 8149 if ( dataTypes[ 0 ] in responses ) { 8150 finalDataType = dataTypes[ 0 ]; 8151 } else {
8152 // Try convertible dataTypes 8153 for ( type in responses ) { 8154 if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) { 8155 finalDataType = type; 8156 break; 8157 } 8158 if ( !firstDataType ) { 8159 firstDataType = type; 8160 } 8161 } 8162 // Or just use first one 8163 finalDataType = finalDataType || firstDataType; 8164 } 8165 8166 // If we found a dataType 8167 // We add the dataType to the list if needed 8168 // and return the corresponding response 8169 if ( finalDataType ) { 8170 if ( finalDataType !== dataTypes[ 0 ] ) { 8171 dataTypes.unshift( finalDataType ); 8172 } 8173 return responses[ finalDataType ]; 8174 } 8175} 8176 8177// Chain conversions given the request and the original response 8178function ajaxConvert( s, response ) { 8179 var conv2, current, conv, tmp, 8180 converters = {}, 8181 i = 0, 8182 // Work with a copy of dataTypes in case we need to modify it for conversion 8183 dataTypes = s.dataTypes.slice(), 8184 prev = dataTypes[ 0 ]; 8185 8186 // Apply the dataFilter if provided 8187 if ( s.dataFilter ) { 8188 response = s.dataFilter( response, s.dataType ); 8189 } 8190 8191 // Create converters map with lowercased keys 8192 if ( dataTypes[ 1 ] ) { 8193 for ( conv in s.converters ) { 8194 converters[ conv.toLowerCase() ] = s.converters[ conv ]; 8195 } 8196 } 8197 8198 // Convert to each sequential dataType, tolerating list modification 8199 for ( ; (current = dataTypes[++i]); ) { 8200 8201 // There's only work to do if current dataType is non-auto 8202 if ( current !== "*" ) { 8203 8204 // Convert response if prev dataType is non-auto and differs from current 8205 if ( prev !== "*" && prev !== current ) { 8206 8207 // Seek a direct converter 8208 conv = converters[ prev + " " + current ] || converters[ "* " + current ]; 8209 8210 // If none found, seek a pair 8211 if ( !conv ) { 8212 for ( conv2 in converters ) { 8213 8214 // If conv2 outputs current 8215 tmp = conv2.split(" "); 8216 if ( tmp[ 1 ] === current ) { 8217 8218 // If prev can be converted to accepted input 8219 conv = converters[ prev + " " + tmp[ 0 ] ] || 8220 converters[ "* " + tmp[ 0 ] ]; 8221 if ( conv ) { 8222 // Condense equivalence converters 8223 if ( conv === true ) { 8224 conv = converters[ conv2 ]; 8225 8226 // Otherwise, insert the intermediate dataType 8227 } else if ( converters[ conv2 ] !== true ) { 8228 current = tmp[ 0 ]; 8229 dataTypes.splice( i--, 0, current ); 8230 } 8231 8232 break; 8233 } 8234 } 8235 } 8236 } 8237 8238 // Apply converter (if not an equivalence) 8239 if ( conv !== true ) { 8240 8241 // Unless errors are allowed to bubble, catch and return them 8242 if ( conv && s["throws"] ) { 8243 response = conv( response ); 8244 } else { 8245 try { 8246 response = conv( response ); 8247 } catch ( e ) { 8248 return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current }; 8249 } 8250 } 8251 } 8252 } 8253 8254 // Update prev for next iteration 8255 prev = current; 8256 } 8257 } 8258 8259 return { state: "success", data: response }; 8260} 8261// Install script dataType 8262jQuery.ajaxSetup({ 8263 accepts: { 8264 script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" 8265 }, 8266 contents: { 8267 script: /(?:java|ecma)script/ 8268 }, 8269 converters: { 8270 "text script": function( text ) { 8271 jQuery.globalEval( text ); 8272 return text; 8273 } 8274 } 8275}); 8276 8277// Handle cache's special case and global 8278jQuery.ajaxPrefilter( "script", function( s ) { 8279 if ( s.cache === undefined ) { 8280 s.cache = false; 8281 } 8282 if ( s.crossDomain ) { 8283 s.type = "GET"; 8284 s.global = false; 8285 } 8286}); 8287 8288// Bind script tag hack transport 8289jQuery.ajaxTransport( "script", function(s) { 8290 8291 // This transport only deals with cross domain requests 8292 if ( s.crossDomain ) { 8293 8294 var script, 8295 head = document.head || jQuery("head")[0] || document.documentElement; 8296 8297 return { 8298 8299 send: function( _, callback ) { 8300 8301 script = document.createElement("script"); 8302 8303 script.async = true; 8304 8305 if ( s.scriptCharset ) { 8306 script.charset = s.scriptCharset; 8307 } 8308 8309 script.src = s.url; 8310 8311 // Attach handlers for all browsers 8312 script.onload = script.onreadystatechange = function( _, isAbort ) { 8313 8314 if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) { 8315 8316 // Handle memory leak in IE 8317 script.onload = script.onreadystatechange = null; 8318 8319 // Remove the script 8320 if ( script.parentNode ) { 8321 script.parentNode.removeChild( script ); 8322 } 8323 8324 // Dereference the script 8325 script = null; 8326 8327 // Callback if not abort 8328 if ( !isAbort ) { 8329 callback( 200, "success" ); 8330 } 8331 } 8332 }; 8333 8334 // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending 8335 // Use native DOM manipulation to avoid our domManip AJAX trickery 8336 head.insertBefore( script, head.firstChild ); 8337 }, 8338 8339 abort: function() { 8340 if ( script ) { 8341 script.onload( undefined, true ); 8342 } 8343 } 8344 }; 8345 } 8346}); 8347var oldCallbacks = [], 8348 rjsonp = /(=)\?(?=&|$)|\?\?/; 8349 8350// Default jsonp settings 8351jQuery.ajaxSetup({ 8352 jsonp: "callback", 8353 jsonpCallback: function() { 8354 var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) ); 8355 this[ callback ] = true; 8356 return callback; 8357 } 8358}); 8359 8360// Detect, normalize options and install callbacks for jsonp requests 8361jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { 8362 8363 var callbackName, overwritten, responseContainer, 8364 jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ? 8365 "url" : 8366 typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data" 8367 ); 8368 8369 // Handle iff the expected data type is "jsonp" or we have a parameter to set 8370 if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) { 8371 8372 // Get callback name, remembering preexisting value associated with it 8373 callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ? 8374 s.jsonpCallback() : 8375 s.jsonpCallback; 8376 8377 // Insert callback into url or form data 8378 if ( jsonProp ) { 8379 s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName ); 8380 } else if ( s.jsonp !== false ) { 8381 s.url += ( ajax_rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; 8382 } 8383 8384 // Use data converter to retrieve json after script execution 8385 s.converters["script json"] = function() { 8386 if ( !responseContainer ) { 8387 jQuery.error( callbackName + " was not called" ); 8388 } 8389 return responseContainer[ 0 ]; 8390 }; 8391 8392 // force json dataType 8393 s.dataTypes[ 0 ] = "json"; 8394 8395 // Install callback 8396 overwritten = window[ callbackName ]; 8397 window[ callbackName ] = function() { 8398 responseContainer = arguments; 8399 }; 8400 8401 // Clean-up function (fires after converters) 8402 jqXHR.always(function() { 8403 // Restore preexisting value 8404 window[ callbackName ] = overwritten; 8405 8406 // Save back as free 8407 if ( s[ callbackName ] ) { 8408 // make sure that re-using the options doesn't screw things around 8409 s.jsonpCallback = originalSettings.jsonpCallback; 8410 8411 // save the callback name for future use 8412 oldCallbacks.push( callbackName ); 8413 } 8414 8415 // Call if it was a function and we have a response 8416 if ( responseContainer && jQuery.isFunction( overwritten ) ) { 8417 overwritten( responseContainer[ 0 ] ); 8418 } 8419 8420 responseContainer = overwritten = undefined; 8421 }); 8422 8423 // Delegate to script 8424 return "script"; 8425 } 8426}); 8427var xhrCallbacks, xhrSupported, 8428 xhrId = 0, 8429 // #5280: Internet Explorer will keep connections alive if we don't abort on unload 8430 xhrOnUnloadAbort = window.ActiveXObject && function() { 8431 // Abort all pending requests 8432 var key;
8433 for ( key in xhrCallbacks ) { 8434 xhrCallbacks[ key ]( undefined, true ); 8435 } 8436 }; 8437 8438// Functions to create xhrs 8439function createStandardXHR() { 8440 try { 8441 return new window.XMLHttpRequest(); 8442 } catch( e ) {} 8443} 8444 8445function createActiveXHR() { 8446 try { 8447 return new window.ActiveXObject("Microsoft.XMLHTTP"); 8448 } catch( e ) {} 8449} 8450 8451// Create the request object 8452// (This is still attached to ajaxSettings for backward compatibility) 8453jQuery.ajaxSettings.xhr = window.ActiveXObject ? 8454 /* Microsoft failed to properly 8455 * implement the XMLHttpRequest in IE7 (can't request local files), 8456 * so we use the ActiveXObject when it is available 8457 * Additionally XMLHttpRequest can be disabled in IE7/IE8 so 8458 * we need a fallback. 8459 */ 8460 function() { 8461 return !this.isLocal && createStandardXHR() || createActiveXHR(); 8462 } : 8463 // For all other browsers, use the standard XMLHttpRequest object 8464 createStandardXHR; 8465 8466// Determine support properties 8467xhrSupported = jQuery.ajaxSettings.xhr(); 8468jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); 8469xhrSupported = jQuery.support.ajax = !!xhrSupported; 8470 8471// Create transport if the browser can provide an xhr 8472if ( xhrSupported ) { 8473 8474 jQuery.ajaxTransport(function( s ) { 8475 // Cross domain only allowed if supported through XMLHttpRequest 8476 if ( !s.crossDomain || jQuery.support.cors ) { 8477 8478 var callback; 8479 8480 return { 8481 send: function( headers, complete ) { 8482 8483 // Get a new xhr 8484 var handle, i, 8485 xhr = s.xhr(); 8486 8487 // Open the socket 8488 // Passing null username, generates a login popup on Opera (#2865) 8489 if ( s.username ) { 8490 xhr.open( s.type, s.url, s.async, s.username, s.password ); 8491 } else { 8492 xhr.open( s.type, s.url, s.async ); 8493 } 8494 8495 // Apply custom fields if provided 8496 if ( s.xhrFields ) { 8497 for ( i in s.xhrFields ) { 8498 xhr[ i ] = s.xhrFields[ i ]; 8499 } 8500 } 8501 8502 // Override mime type if needed 8503 if ( s.mimeType && xhr.overrideMimeType ) { 8504 xhr.overrideMimeType( s.mimeType ); 8505 } 8506 8507 // X-Requested-With header 8508 // For cross-domain requests, seeing as conditions for a preflight are 8509 // akin to a jigsaw puzzle, we simply never set it to be sure. 8510 // (it can always be set on a per-request basis or even using ajaxSetup)
8511 // For same-domain requests, won't change header if already provided. 8512 if ( !s.crossDomain && !headers["X-Requested-With"] ) { 8513 headers["X-Requested-With"] = "XMLHttpRequest"; 8514 } 8515 8516 // Need an extra try/catch for cross domain requests in Firefox 3 8517 try { 8518 for ( i in headers ) { 8519 xhr.setRequestHeader( i, headers[ i ] ); 8520 } 8521 } catch( err ) {} 8522 8523 // Do send the request 8524 // This may raise an exception which is actually 8525 // handled in jQuery.ajax (so no try/catch here) 8526 xhr.send( ( s.hasContent && s.data ) || null ); 8527 8528 // Listener 8529 callback = function( _, isAbort ) { 8530 var status, responseHeaders, statusText, responses; 8531 8532 // Firefox throws exceptions when accessing properties 8533 // of an xhr when a network error occurred 8534 // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE) 8535 try { 8536 8537 // Was never called and is aborted or complete 8538 if ( callback && ( isAbort || xhr.readyState === 4 ) ) { 8539 8540 // Only called once 8541 callback = undefined; 8542 8543 // Do not keep as active anymore 8544 if ( handle ) { 8545 xhr.onreadystatechange = jQuery.noop; 8546 if ( xhrOnUnloadAbort ) { 8547 delete xhrCallbacks[ handle ]; 8548 } 8549 } 8550 8551 // If it's an abort 8552 if ( isAbort ) { 8553 // Abort it manually if needed 8554 if ( xhr.readyState !== 4 ) { 8555 xhr.abort(); 8556 } 8557 } else { 8558 responses = {}; 8559 status = xhr.status; 8560 responseHeaders = xhr.getAllResponseHeaders(); 8561 8562 // When requesting binary data, IE6-9 will throw an exception 8563 // on any attempt to access responseText (#11426) 8564 if ( typeof xhr.responseText === "string" ) { 8565 responses.text = xhr.responseText; 8566 } 8567 8568 // Firefox throws an exception when accessing 8569 // statusText for faulty cross-domain requests 8570 try { 8571 statusText = xhr.statusText; 8572 } catch( e ) { 8573 // We normalize with Webkit giving an empty statusText 8574 statusText = ""; 8575 } 8576 8577 // Filter status for non standard behaviors 8578 8579 // If the request is local and we have data: assume a success 8580 // (success with no data won't get notified, that's the best we 8581 // can do given current implementations) 8582 if ( !status && s.isLocal && !s.crossDomain ) { 8583 status = responses.text ? 200 : 404; 8584 // IE - #1450: sometimes returns 1223 when it should be 204 8585 } else if ( status === 1223 ) { 8586 status = 204; 8587 } 8588 } 8589 } 8590 } catch( firefoxAccessException ) { 8591 if ( !isAbort ) { 8592 complete( -1, firefoxAccessException ); 8593 } 8594 } 8595 8596 // Call complete if needed 8597 if ( responses ) { 8598 complete( status, statusText, responses, responseHeaders ); 8599 } 8600 }; 8601 8602 if ( !s.async ) { 8603 // if we're in sync mode we fire the callback 8604 callback(); 8605 } else if ( xhr.readyState === 4 ) { 8606 // (IE6 & IE7) if it's in cache and has been 8607 // retrieved directly we need to fire the callback 8608 setTimeout( callback ); 8609 } else { 8610 handle = ++xhrId; 8611 if ( xhrOnUnloadAbort ) { 8612 // Create the active xhrs callbacks list if needed 8613 // and attach the unload handler 8614 if ( !xhrCallbacks ) { 8615 xhrCallbacks = {}; 8616 jQuery( window ).unload( xhrOnUnloadAbort ); 8617 } 8618 // Add to list of active xhrs callbacks 8619 xhrCallbacks[ handle ] = callback; 8620 } 8621 xhr.onreadystatechange = callback; 8622 } 8623 }, 8624 8625 abort: function() { 8626 if ( callback ) { 8627 callback( undefined, true ); 8628 } 8629 } 8630 }; 8631 } 8632 }); 8633} 8634var fxNow, timerId, 8635 rfxtypes = /^(?:toggle|show|hide)$/, 8636 rfxnum = new RegExp( "^(?:([+-])=|)(" + core_pnum + ")([a-z%]*)$", "i" ), 8637 rrun = /queueHooks$/, 8638 animationPrefilters = [ defaultPrefilter ], 8639 tweeners = { 8640 "*": [function( prop, value ) { 8641 var end, unit, 8642 tween = this.createTween( prop, value ), 8643 parts = rfxnum.exec( value ), 8644 target = tween.cur(), 8645 start = +target || 0, 8646 scale = 1, 8647 maxIterations = 20; 8648 8649 if ( parts ) { 8650 end = +parts[2]; 8651 unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" ); 8652 8653 // We need to compute starting value 8654 if ( unit !== "px" && start ) { 8655 // Iteratively approximate from a nonzero starting point 8656 // Prefer the current property, because this process will be trivial if it uses the same units
8657 // Fallback to end or a simple constant 8658 start = jQuery.css( tween.elem, prop, true ) || end || 1; 8659 8660 do { 8661 // If previous iteration zeroed out, double until we get *something* 8662 // Use a string for doubling factor so we don't accidentally see scale as unchanged below 8663 scale = scale || ".5"; 8664 8665 // Adjust and apply 8666 start = start / scale; 8667 jQuery.style( tween.elem, prop, start + unit ); 8668 8669 // Update scale, tolerating zero or NaN from tween.cur() 8670 // And breaking the loop if scale is unchanged or perfect, or if we've just had enough 8671 } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations ); 8672 } 8673 8674 tween.unit = unit; 8675 tween.start = start; 8676 // If a +=/-= token was provided, we're doing a relative animation 8677 tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end; 8678 } 8679 return tween; 8680 }] 8681 }; 8682 8683// Animations created synchronously will run synchronously 8684function createFxNow() { 8685 setTimeout(function() { 8686 fxNow = undefined; 8687 }); 8688 return ( fxNow = jQuery.now() ); 8689} 8690 8691function createTweens( animation, props ) { 8692 jQuery.each( props, function( prop, value ) { 8693 var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ), 8694 index = 0, 8695 length = collection.length; 8696 for ( ; index < length; index++ ) { 8697 if ( collection[ index ].call( animation, prop, value ) ) { 8698 8699 // we're done with this property 8700 return; 8701 } 8702 } 8703 }); 8704} 8705 8706function Animation( elem, properties, options ) { 8707 var result, 8708 stopped, 8709 index = 0, 8710 length = animationPrefilters.length, 8711 deferred = jQuery.Deferred().always( function() { 8712 // don't match elem in the :animated selector 8713 delete tick.elem; 8714 }), 8715 tick = function() { 8716 if ( stopped ) { 8717 return false; 8718 } 8719 var currentTime = fxNow || createFxNow(), 8720 remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), 8721 // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497) 8722 temp = remaining / animation.duration || 0, 8723 percent = 1 - temp, 8724 index = 0, 8725 length = animation.tweens.length; 8726 8727 for ( ; index < length ; index++ ) { 8728 animation.tweens[ index ].run( percent ); 8729 } 8730 8731 deferred.notifyWith( elem, [ animation, percent, remaining ]); 8732 8733 if ( percent < 1 && length ) { 8734 return remaining; 8735 } else { 8736 deferred.resolveWith( elem, [ animation ] ); 8737 return false; 8738 } 8739 }, 8740 animation = deferred.promise({ 8741 elem: elem, 8742 props: jQuery.extend( {}, properties ), 8743 opts: jQuery.extend( true, { specialEasing: {} }, options ), 8744 originalProperties: properties, 8745 originalOptions: options, 8746 startTime: fxNow || createFxNow(), 8747 duration: options.duration, 8748 tweens: [], 8749 createTween: function( prop, end ) { 8750 var tween = jQuery.Tween( elem, animation.opts, prop, end, 8751 animation.opts.specialEasing[ prop ] || animation.opts.easing ); 8752 animation.tweens.push( tween ); 8753 return tween; 8754 }, 8755 stop: function( gotoEnd ) { 8756 var index = 0, 8757 // if we are going to the end, we want to run all the tweens 8758 // otherwise we skip this part 8759 length = gotoEnd ? animation.tweens.length : 0; 8760 if ( stopped ) { 8761 return this; 8762 } 8763 stopped = true; 8764 for ( ; index < length ; index++ ) { 8765 animation.tweens[ index ].run( 1 ); 8766 } 8767 8768 // resolve when we played the last frame 8769 // otherwise, reject 8770 if ( gotoEnd ) { 8771 deferred.resolveWith( elem, [ animation, gotoEnd ] ); 8772 } else { 8773 deferred.rejectWith( elem, [ animation, gotoEnd ] ); 8774 } 8775 return this; 8776 } 8777 }), 8778 props = animation.props; 8779 8780 propFilter( props, animation.opts.specialEasing ); 8781 8782 for ( ; index < length ; index++ ) { 8783 result = animationPrefilters[ index ].call( animation, elem, props, animation.opts ); 8784 if ( result ) { 8785 return result; 8786 } 8787 } 8788 8789 createTweens( animation, props ); 8790 8791 if ( jQuery.isFunction( animation.opts.start ) ) { 8792 animation.opts.start.call( elem, animation ); 8793 } 8794 8795 jQuery.fx.timer( 8796 jQuery.extend( tick, { 8797 elem: elem, 8798 anim: animation, 8799 queue: animation.opts.queue 8800 }) 8801 ); 8802 8803 // attach callbacks from options 8804 return animation.progress( animation.opts.progress ) 8805 .done( animation.opts.done, animation.opts.complete ) 8806 .fail( animation.opts.fail ) 8807 .always( animation.opts.always ); 8808} 8809 8810function propFilter( props, specialEasing ) { 8811 var value, name, index, easing, hooks; 8812 8813 // camelCase, specialEasing and expand cssHook pass 8814 for ( index in props ) { 8815 name = jQuery.camelCase( index ); 8816 easing = specialEasing[ name ]; 8817 value = props[ index ]; 8818 if ( jQuery.isArray( value ) ) { 8819 easing = value[ 1 ]; 8820 value = props[ index ] = value[ 0 ]; 8821 } 8822 8823 if ( index !== name ) { 8824 props[ name ] = value; 8825 delete props[ index ]; 8826 } 8827 8828 hooks = jQuery.cssHooks[ name ]; 8829 if ( hooks && "expand" in hooks ) { 8830 value = hooks.expand( value ); 8831 delete props[ name ]; 8832 8833 // not quite $.extend, this wont overwrite keys already present. 8834 // also - reusing 'index' from above because we have the correct "name" 8835 for ( index in value ) { 8836 if ( !( index in props ) ) { 8837 props[ index ] = value[ index ]; 8838 specialEasing[ index ] = easing; 8839 } 8840 } 8841 } else { 8842 specialEasing[ name ] = easing; 8843 } 8844 } 8845} 8846 8847jQuery.Animation = jQuery.extend( Animation, { 8848 8849 tweener: function( props, callback ) { 8850 if ( jQuery.isFunction( props ) ) { 8851 callback = props; 8852 props = [ "*" ]; 8853 } else { 8854 props = props.split(" "); 8855 } 8856 8857 var prop, 8858 index = 0, 8859 length = props.length; 8860 8861 for ( ; index < length ; index++ ) { 8862 prop = props[ index ]; 8863 tweeners[ prop ] = tweeners[ prop ] || []; 8864 tweeners[ prop ].unshift( callback ); 8865 } 8866 }, 8867 8868 prefilter: function( callback, prepend ) { 8869 if ( prepend ) { 8870 animationPrefilters.unshift( callback ); 8871 } else { 8872 animationPrefilters.push( callback ); 8873 } 8874 } 8875}); 8876 8877function defaultPrefilter( elem, props, opts ) { 8878 /*jshint validthis:true */ 8879 var prop, index, length, 8880 value, dataShow, toggle, 8881 tween, hooks, oldfire, 8882 anim = this, 8883 style = elem.style, 8884 orig = {}, 8885 handled = [], 8886 hidden = elem.nodeType && isHidden( elem ); 8887 8888 // handle queue: false promises 8889 if ( !opts.queue ) { 8890 hooks = jQuery._queueHooks( elem, "fx" ); 8891 if ( hooks.unqueued == null ) { 8892 hooks.unqueued = 0; 8893 oldfire = hooks.empty.fire; 8894 hooks.empty.fire = function() { 8895 if ( !hooks.unqueued ) { 8896 oldfire(); 8897 } 8898 }; 8899 } 8900 hooks.unqueued++; 8901 8902 anim.always(function() { 8903 // doing this makes sure that the complete handler will be called 8904 // before this completes 8905 anim.always(function() { 8906 hooks.unqueued--; 8907 if ( !jQuery.queue( elem, "fx" ).length ) { 8908 hooks.empty.fire(); 8909 } 8910 }); 8911 }); 8912 } 8913 8914 // height/width overflow pass 8915 if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) { 8916 // Make sure that nothing sneaks out 8917 // Record all 3 overflow attributes because IE does not 8918 // change the overflow attribute when overflowX and 8919 // overflowY are set to the same value 8920 opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; 8921 8922 // Set display property to inline-block for height/width 8923 // animations on inline elements that are having width/height animated
8924 if ( jQuery.css( elem, "display" ) === "inline" && 8925 jQuery.css( elem, "float" ) === "none" ) { 8926 8927 // inline-level elements accept inline-block; 8928 // block-level elements need to be inline with layout 8929 if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) { 8930 style.display = "inline-block"; 8931 8932 } else { 8933 style.zoom = 1; 8934 } 8935 } 8936 } 8937 8938 if ( opts.overflow ) { 8939 style.overflow = "hidden"; 8940 if ( !jQuery.support.shrinkWrapBlocks ) { 8941 anim.always(function() { 8942 style.overflow = opts.overflow[ 0 ]; 8943 style.overflowX = opts.overflow[ 1 ]; 8944 style.overflowY = opts.overflow[ 2 ]; 8945 }); 8946 } 8947 } 8948 8949 8950 // show/hide pass 8951 for ( index in props ) { 8952 value = props[ index ]; 8953 if ( rfxtypes.exec( value ) ) { 8954 delete props[ index ]; 8955 toggle = toggle || value === "toggle"; 8956 if ( value === ( hidden ? "hide" : "show" ) ) { 8957 continue; 8958 } 8959 handled.push( index ); 8960 } 8961 } 8962 8963 length = handled.length; 8964 if ( length ) { 8965 dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} ); 8966 if ( "hidden" in dataShow ) { 8967 hidden = dataShow.hidden; 8968 } 8969 8970 // store state if its toggle - enables .stop().toggle() to "reverse" 8971 if ( toggle ) { 8972 dataShow.hidden = !hidden; 8973 } 8974 if ( hidden ) { 8975 jQuery( elem ).show(); 8976 } else { 8977 anim.done(function() { 8978 jQuery( elem ).hide(); 8979 }); 8980 } 8981 anim.done(function() { 8982 var prop; 8983 jQuery._removeData( elem, "fxshow" ); 8984 for ( prop in orig ) { 8985 jQuery.style( elem, prop, orig[ prop ] ); 8986 } 8987 }); 8988 for ( index = 0 ; index < length ; index++ ) { 8989 prop = handled[ index ]; 8990 tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 ); 8991 orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop ); 8992 8993 if ( !( prop in dataShow ) ) { 8994 dataShow[ prop ] = tween.start; 8995 if ( hidden ) { 8996 tween.end = tween.start; 8997 tween.start = prop === "width" || prop === "height" ? 1 : 0; 8998 } 8999 } 9000 } 9001 } 9002} 9003 9004function Tween( elem, options, prop, end, easing ) { 9005 return new Tween.prototype.init( elem, options, prop, end, easing ); 9006} 9007jQuery.Tween = Tween; 9008 9009Tween.prototype = { 9010 constructor: Tween, 9011 init: function( elem, options, prop, end, easing, unit ) { 9012 this.elem = elem; 9013 this.prop = prop; 9014 this.easing = easing || "swing"; 9015 this.options = options; 9016 this.start = this.now = this.cur(); 9017 this.end = end; 9018 this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); 9019 }, 9020 cur: function() { 9021 var hooks = Tween.propHooks[ this.prop ]; 9022 9023 return hooks && hooks.get ? 9024 hooks.get( this ) : 9025 Tween.propHooks._default.get( this ); 9026 }, 9027 run: function( percent ) { 9028 var eased, 9029 hooks = Tween.propHooks[ this.prop ]; 9030 9031 if ( this.options.duration ) { 9032 this.pos = eased = jQuery.easing[ this.easing ]( 9033 percent, this.options.duration * percent, 0, 1, this.options.duration 9034 ); 9035 } else { 9036 this.pos = eased = percent; 9037 } 9038 this.now = ( this.end - this.start ) * eased + this.start; 9039 9040 if ( this.options.step ) { 9041 this.options.step.call( this.elem, this.now, this ); 9042 } 9043 9044 if ( hooks && hooks.set ) { 9045 hooks.set( this ); 9046 } else { 9047 Tween.propHooks._default.set( this ); 9048 } 9049 return this; 9050 } 9051}; 9052 9053Tween.prototype.init.prototype = Tween.prototype; 9054 9055Tween.propHooks = { 9056 _default: { 9057 get: function( tween ) { 9058 var result; 9059 9060 if ( tween.elem[ tween.prop ] != null && 9061 (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) { 9062 return tween.elem[ tween.prop ]; 9063 } 9064 9065 // passing an empty string as a 3rd parameter to .css will automatically 9066 // attempt a parseFloat and fallback to a string if the parse fails 9067 // so, simple values such as "10px" are parsed to Float. 9068 // complex values such as "rotate(1rad)" are returned as is. 9069 result = jQuery.css( tween.elem, tween.prop, "" ); 9070 // Empty strings, null, undefined and "auto" are converted to 0. 9071 return !result || result === "auto" ? 0 : result; 9072 }, 9073 set: function( tween ) { 9074 // use step hook for back compat - use cssHook if its there - use .style if its 9075 // available and use plain properties where available 9076 if ( jQuery.fx.step[ tween.prop ] ) { 9077 jQuery.fx.step[ tween.prop ]( tween ); 9078 } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) { 9079 jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); 9080 } else { 9081 tween.elem[ tween.prop ] = tween.now; 9082 } 9083 } 9084 } 9085}; 9086
9087// Remove in 2.0 - this supports IE8's panic based approach 9088// to setting things on disconnected nodes 9089 9090Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { 9091 set: function( tween ) { 9092 if ( tween.elem.nodeType && tween.elem.parentNode ) { 9093 tween.elem[ tween.prop ] = tween.now; 9094 } 9095 } 9096}; 9097 9098jQuery.each([ "toggle", "show", "hide" ], function( i, name ) { 9099 var cssFn = jQuery.fn[ name ]; 9100 jQuery.fn[ name ] = function( speed, easing, callback ) { 9101 return speed == null || typeof speed === "boolean" ? 9102 cssFn.apply( this, arguments ) : 9103 this.animate( genFx( name, true ), speed, easing, callback ); 9104 }; 9105}); 9106 9107jQuery.fn.extend({ 9108 fadeTo: function( speed, to, easing, callback ) { 9109 9110 // show any hidden elements after setting opacity to 0 9111 return this.filter( isHidden ).css( "opacity", 0 ).show() 9112 9113 // animate to the value specified 9114 .end().animate({ opacity: to }, speed, easing, callback ); 9115 }, 9116 animate: function( prop, speed, easing, callback ) { 9117 var empty = jQuery.isEmptyObject( prop ), 9118 optall = jQuery.speed( speed, easing, callback ), 9119 doAnimation = function() { 9120 // Operate on a copy of prop so per-property easing won't be lost 9121 var anim = Animation( this, jQuery.extend( {}, prop ), optall ); 9122 doAnimation.finish = function() { 9123 anim.stop( true ); 9124 }; 9125 // Empty animations, or finishing resolves immediately 9126 if ( empty || jQuery._data( this, "finish" ) ) { 9127 anim.stop( true ); 9128 } 9129 }; 9130 doAnimation.finish = doAnimation; 9131 9132 return empty || optall.queue === false ? 9133 this.each( doAnimation ) : 9134 this.queue( optall.queue, doAnimation ); 9135 }, 9136 stop: function( type, clearQueue, gotoEnd ) { 9137 var stopQueue = function( hooks ) { 9138 var stop = hooks.stop; 9139 delete hooks.stop; 9140 stop( gotoEnd ); 9141 }; 9142 9143 if ( typeof type !== "string" ) { 9144 gotoEnd = clearQueue; 9145 clearQueue = type; 9146 type = undefined; 9147 } 9148 if ( clearQueue && type !== false ) { 9149 this.queue( type || "fx", [] ); 9150 } 9151 9152 return this.each(function() { 9153 var dequeue = true, 9154 index = type != null && type + "queueHooks", 9155 timers = jQuery.timers, 9156 data = jQuery._data( this ); 9157 9158 if ( index ) { 9159 if ( data[ index ] && data[ index ].stop ) { 9160 stopQueue( data[ index ] ); 9161 } 9162 } else { 9163 for ( index in data ) { 9164 if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { 9165 stopQueue( data[ index ] ); 9166 } 9167 } 9168 } 9169 9170 for ( index = timers.length; index--; ) { 9171 if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) { 9172 timers[ index ].anim.stop( gotoEnd ); 9173 dequeue = false; 9174 timers.splice( index, 1 ); 9175 } 9176 } 9177 9178 // start the next in the queue if the last step wasn't forced 9179 // timers currently will call their complete callbacks, which will dequeue 9180 // but only if they were gotoEnd 9181 if ( dequeue || !gotoEnd ) { 9182 jQuery.dequeue( this, type ); 9183 } 9184 }); 9185 }, 9186 finish: function( type ) { 9187 if ( type !== false ) { 9188 type = type || "fx"; 9189 } 9190 return this.each(function() { 9191 var index, 9192 data = jQuery._data( this ), 9193 queue = data[ type + "queue" ], 9194 hooks = data[ type + "queueHooks" ], 9195 timers = jQuery.timers, 9196 length = queue ? queue.length : 0; 9197 9198 // enable finishing flag on private data 9199 data.finish = true; 9200 9201 // empty the queue first 9202 jQuery.queue( this, type, [] ); 9203 9204 if ( hooks && hooks.cur && hooks.cur.finish ) { 9205 hooks.cur.finish.call( this ); 9206 } 9207 9208 // look for any active animations, and finish them 9209 for ( index = timers.length; index--; ) { 9210 if ( timers[ index ].elem === this && timers[ index ].queue === type ) { 9211 timers[ index ].anim.stop( true ); 9212 timers.splice( index, 1 ); 9213 } 9214 } 9215 9216 // look for any animations in the old queue and finish them 9217 for ( index = 0; index < length; index++ ) { 9218 if ( queue[ index ] && queue[ index ].finish ) { 9219 queue[ index ].finish.call( this ); 9220 } 9221 } 9222 9223 // turn off finishing flag 9224 delete data.finish; 9225 }); 9226 } 9227}); 9228 9229// Generate parameters to create a standard animation 9230function genFx( type, includeWidth ) { 9231 var which, 9232 attrs = { height: type }, 9233 i = 0; 9234 9235 // if we include width, step value is 1 to do all cssExpand values, 9236 // if we don't include width, step value is 2 to skip over Left and Right 9237 includeWidth = includeWidth? 1 : 0; 9238 for( ; i < 4 ; i += 2 - includeWidth ) { 9239 which = cssExpand[ i ]; 9240 attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; 9241 } 9242 9243 if ( includeWidth ) { 9244 attrs.opacity = attrs.width = type; 9245 } 9246 9247 return attrs; 9248} 9249 9250// Generate shortcuts for custom animations 9251jQuery.each({ 9252 slideDown: genFx("show"), 9253 slideUp: genFx("hide"), 9254 slideToggle: genFx("toggle"), 9255 fadeIn: { opacity: "show" }, 9256 fadeOut: { opacity: "hide" }, 9257 fadeToggle: { opacity: "toggle" } 9258}, function( name, props ) { 9259 jQuery.fn[ name ] = function( speed, easing, callback ) { 9260 return this.animate( props, speed, easing, callback ); 9261 }; 9262}); 9263 9264jQuery.speed = function( speed, easing, fn ) { 9265 var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { 9266 complete: fn || !fn && easing || 9267 jQuery.isFunction( speed ) && speed, 9268 duration: speed, 9269 easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing 9270 }; 9271 9272 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : 9273 opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default; 9274 9275 // normalize opt.queue - true/undefined/null -> "fx" 9276 if ( opt.queue == null || opt.queue === true ) { 9277 opt.queue = "fx"; 9278 } 9279 9280 // Queueing 9281 opt.old = opt.complete; 9282 9283 opt.complete = function() { 9284 if ( jQuery.isFunction( opt.old ) ) { 9285 opt.old.call( this ); 9286 } 9287 9288 if ( opt.queue ) { 9289 jQuery.dequeue( this, opt.queue ); 9290 } 9291 }; 9292 9293 return opt; 9294}; 9295 9296jQuery.easing = { 9297 linear: function( p ) { 9298 return p; 9299 }, 9300 swing: function( p ) { 9301 return 0.5 - Math.cos( p*Math.PI ) / 2; 9302 } 9303}; 9304 9305jQuery.timers = []; 9306jQuery.fx = Tween.prototype.init; 9307jQuery.fx.tick = function() { 9308 var timer, 9309 timers = jQuery.timers, 9310 i = 0; 9311 9312 fxNow = jQuery.now(); 9313 9314 for ( ; i < timers.length; i++ ) { 9315 timer = timers[ i ]; 9316 // Checks the timer has not already been removed 9317 if ( !timer() && timers[ i ] === timer ) { 9318 timers.splice( i--, 1 ); 9319 } 9320 } 9321 9322 if ( !timers.length ) { 9323 jQuery.fx.stop(); 9324 } 9325 fxNow = undefined; 9326}; 9327 9328jQuery.fx.timer = function( timer ) { 9329 if ( timer() && jQuery.timers.push( timer ) ) { 9330 jQuery.fx.start(); 9331 } 9332}; 9333 9334jQuery.fx.interval = 13; 9335 9336jQuery.fx.start = function() { 9337 if ( !timerId ) { 9338 timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval ); 9339 } 9340}; 9341 9342jQuery.fx.stop = function() { 9343 clearInterval( timerId ); 9344 timerId = null; 9345}; 9346 9347jQuery.fx.speeds = { 9348 slow: 600, 9349 fast: 200, 9350 // Default speed 9351 _default: 400 9352}; 9353 9354// Back Compat <1.8 extension point 9355jQuery.fx.step = {}; 9356 9357if ( jQuery.expr && jQuery.expr.filters ) { 9358 jQuery.expr.filters.animated = function( elem ) { 9359 return jQuery.grep(jQuery.timers, function( fn ) { 9360 return elem === fn.elem; 9361 }).length; 9362 }; 9363} 9364jQuery.fn.offset = function( options ) { 9365 if ( arguments.length ) { 9366 return options === undefined ?
9367 this : 9368 this.each(function( i ) { 9369 jQuery.offset.setOffset( this, options, i ); 9370 }); 9371 } 9372 9373 var docElem, win, 9374 box = { top: 0, left: 0 }, 9375 elem = this[ 0 ], 9376 doc = elem && elem.ownerDocument; 9377 9378 if ( !doc ) { 9379 return; 9380 } 9381 9382 docElem = doc.documentElement; 9383 9384 // Make sure it's not a disconnected DOM node 9385 if ( !jQuery.contains( docElem, elem ) ) { 9386 return box; 9387 } 9388 9389 // If we don't have gBCR, just use 0,0 rather than error 9390 // BlackBerry 5, iOS 3 (original iPhone) 9391 if ( typeof elem.getBoundingClientRect !== core_strundefined ) { 9392 box = elem.getBoundingClientRect(); 9393 } 9394 win = getWindow( doc ); 9395 return { 9396 top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ), 9397 left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 ) 9398 }; 9399}; 9400 9401jQuery.offset = { 9402 9403 setOffset: function( elem, options, i ) { 9404 var position = jQuery.css( elem, "position" ); 9405 9406 // set position first, in-case top/left are set even on static elem 9407 if ( position === "static" ) { 9408 elem.style.position = "relative"; 9409 } 9410 9411 var curElem = jQuery( elem ), 9412 curOffset = curElem.offset(), 9413 curCSSTop = jQuery.css( elem, "top" ), 9414 curCSSLeft = jQuery.css( elem, "left" ), 9415 calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1, 9416 props = {}, curPosition = {}, curTop, curLeft; 9417 9418 // need to be able to calculate position if either top or left is auto and position is either absolute or fixed 9419 if ( calculatePosition ) { 9420 curPosition = curElem.position(); 9421 curTop = curPosition.top; 9422 curLeft = curPosition.left; 9423 } else { 9424 curTop = parseFloat( curCSSTop ) || 0; 9425 curLeft = parseFloat( curCSSLeft ) || 0; 9426 } 9427 9428 if ( jQuery.isFunction( options ) ) { 9429 options = options.call( elem, i, curOffset ); 9430 } 9431 9432 if ( options.top != null ) { 9433 props.top = ( options.top - curOffset.top ) + curTop; 9434 } 9435 if ( options.left != null ) { 9436 props.left = ( options.left - curOffset.left ) + curLeft; 9437 } 9438 9439 if ( "using" in options ) { 9440 options.using.call( elem, props ); 9441 } else { 9442 curElem.css( props ); 9443 } 9444 } 9445}; 9446 9447 9448jQuery.fn.extend({ 9449 9450 position: function() { 9451 if ( !this[ 0 ] ) { 9452 return; 9453 } 9454 9455 var offsetParent, offset, 9456 parentOffset = { top: 0, left: 0 }, 9457 elem = this[ 0 ]; 9458 9459 // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent 9460 if ( jQuery.css( elem, "position" ) === "fixed" ) { 9461 // we assume that getBoundingClientRect is available when computed position is fixed 9462 offset = elem.getBoundingClientRect(); 9463 } else { 9464 // Get *real* offsetParent 9465 offsetParent = this.offsetParent(); 9466 9467 // Get correct offsets 9468 offset = this.offset(); 9469 if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) { 9470 parentOffset = offsetParent.offset(); 9471 } 9472 9473 // Add offsetParent borders 9474 parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ); 9475 parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true ); 9476 } 9477 9478 // Subtract parent offsets and element margins 9479 // note: when an element has margin: auto the offsetLeft and marginLeft 9480 // are the same in Safari causing offset.left to incorrectly be 0 9481 return { 9482 top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ), 9483 left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true) 9484 }; 9485 }, 9486 9487 offsetParent: function() { 9488 return this.map(function() { 9489 var offsetParent = this.offsetParent || document.documentElement; 9490 while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) { 9491 offsetParent = offsetParent.offsetParent; 9492 } 9493 return offsetParent || document.documentElement; 9494 }); 9495 } 9496}); 9497 9498 9499// Create scrollLeft and scrollTop methods 9500jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) { 9501 var top = /Y/.test( prop ); 9502 9503 jQuery.fn[ method ] = function( val ) { 9504 return jQuery.access( this, function( elem, method, val ) { 9505 var win = getWindow( elem ); 9506 9507 if ( val === undefined ) { 9508 return win ? (prop in win) ? win[ prop ] : 9509 win.document.documentElement[ method ] : 9510 elem[ method ]; 9511 } 9512 9513 if ( win ) { 9514 win.scrollTo( 9515 !top ? val : jQuery( win ).scrollLeft(), 9516 top ? val : jQuery( win ).scrollTop() 9517 ); 9518 9519 } else { 9520 elem[ method ] = val; 9521 } 9522 }, method, val, arguments.length, null ); 9523 }; 9524}); 9525 9526function getWindow( elem ) { 9527 return jQuery.isWindow( elem ) ? 9528 elem : 9529 elem.nodeType === 9 ? 9530 elem.defaultView || elem.parentWindow : 9531 false; 9532} 9533// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods 9534jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
9535 jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) { 9536 // margin is only for outerHeight, outerWidth 9537 jQuery.fn[ funcName ] = function( margin, value ) { 9538 var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ), 9539 extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" ); 9540 9541 return jQuery.access( this, function( elem, type, value ) { 9542 var doc; 9543 9544 if ( jQuery.isWindow( elem ) ) { 9545 // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there 9546 // isn't a whole lot we can do. See pull request at this URL for discussion: 9547 // https://github.com/jquery/jquery/pull/764 9548 return elem.document.documentElement[ "client" + name ]; 9549 } 9550 9551 // Get document width or height 9552 if ( elem.nodeType === 9 ) { 9553 doc = elem.documentElement; 9554 9555 // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest 9556 // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it. 9557 return Math.max( 9558 elem.body[ "scroll" + name ], doc[ "scroll" + name ], 9559 elem.body[ "offset" + name ], doc[ "offset" + name ], 9560 doc[ "client" + name ] 9561 ); 9562 } 9563 9564 return value === undefined ? 9565 // Get width or height on the element, requesting but not forcing parseFloat 9566 jQuery.css( elem, type, extra ) : 9567 9568 // Set width or height on the element 9569 jQuery.style( elem, type, value, extra ); 9570 }, type, chainable ? margin : undefined, chainable, null ); 9571 }; 9572 }); 9573}); 9574// Limit scope pollution from any deprecated API 9575// (function() { 9576 9577// })(); 9578// Expose jQuery to the global object 9579window.jQuery = window.$ = jQuery; 9580 9581// Expose jQuery as an AMD module, but only for AMD loaders that 9582// understand the issues with loading multiple versions of jQuery 9583// in a page that all might call define(). The loader will indicate 9584// they have special allowances for multiple jQuery versions by 9585// specifying define.amd.jQuery = true. Register as a named module, 9586// since jQuery can be concatenated with other files that may use define, 9587// but not use a proper concatenation script that understands anonymous 9588// AMD modules. A named AMD is safest and most robust way to register. 9589// Lowercase jquery is used because AMD module names are derived from 9590// file names, and jQuery is normally delivered in a lowercase file name. 9591// Do this after creating the global so that if an AMD module wants to call 9592// noConflict to hide this version of jQuery, it will work. 9593if ( typeof define === "function" && define.amd && define.amd.jQuery ) { 9594 define( "jquery", [], function () { return jQuery; } ); 9595} 9596 9597})( window ); 9598/*! 9599 * Modernizr v2.8.0 9600 * www.modernizr.com 9601 * 9602 * Copyright (c) Faruk Ates, Paul Irish, Alex Sexton 9603 * Available under the BSD and MIT licenses: www.modernizr.com/license/ 9604 */ 9605 9606/* 9607 * Modernizr tests which native CSS3 and HTML5 features are available in 9608 * the current UA and makes the results available to you in two ways: 9609 * as properties on a global Modernizr object, and as classes on the 9610 * <html> element. This information allows you to progressively enhance 9611 * your pages with a granular level of control over the experience. 9612 * 9613 * Modernizr has an optional (not included) conditional resource loader 9614 * called Modernizr.load(), based on Yepnope.js (yepnopejs.com). 9615 * To get a build that includes Modernizr.load(), as well as choosing 9616 * which tests to include, go to www.modernizr.com/download/ 9617 * 9618 * Authors Faruk Ates, Paul Irish, Alex Sexton 9619 * Contributors Ryan Seddon, Ben Alman 9620 */ 9621 9622window.Modernizr = (function( window, document, undefined ) { 9623 9624 var version = '2.8.0', 9625 9626 Modernizr = {}, 9627 9628 /*>>cssclasses*/ 9629 // option for enabling the HTML classes to be added 9630 enableClasses = true, 9631 /*>>cssclasses*/ 9632 9633 docElement = document.documentElement, 9634 9635 /** 9636 * Create our "modernizr" element that we do most feature tests on. 9637 */ 9638 mod = 'modernizr', 9639 modElem = document.createElement(mod), 9640 mStyle = modElem.style, 9641 9642 /** 9643 * Create the input element for various Web Forms feature tests. 9644 */ 9645 inputElem /*>>inputelem*/ = document.createElement('input') /*>>inputelem*/ , 9646 9647 /*>>smile*/ 9648 smile = ':)', 9649 /*>>smile*/ 9650 9651 toString = {}.toString, 9652 9653 // TODO :: make the prefixes more granular 9654 /*>>prefixes*/ 9655 // List of property values to set for css tests. See ticket #21 9656 prefixes = ' -webkit- -moz- -o- -ms- '.split(' '), 9657 /*>>prefixes*/ 9658 9659 /*>>domprefixes*/ 9660 // Following spec is to expose vendor-specific style properties as: 9661 // elem.style.WebkitBorderRadius 9662 // and the following would be incorrect: 9663 // elem.style.webkitBorderRadius 9664 9665 // Webkit ghosts their properties in lowercase but Opera & Moz do not. 9666 // Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+ 9667 // erik.eae.net/archives/2008/03/10/21.48.10/ 9668 9669 // More here: github.com/Modernizr/Modernizr/issues/issue/21 9670 omPrefixes = 'Webkit Moz O ms', 9671 9672 cssomPrefixes = omPrefixes.split(' '), 9673 9674 domPrefixes = omPrefixes.toLowerCase().split(' '), 9675 /*>>domprefixes*/ 9676 9677 /*>>ns*/ 9678 ns = {'svg': 'http://www.w3.org/2000/svg'}, 9679 /*>>ns*/ 9680 9681 tests = {}, 9682 inputs = {}, 9683 attrs = {}, 9684 9685 classes = [], 9686 9687 slice = classes.slice, 9688 9689 featureName, // used in testing loop 9690 9691 9692 /*>>
9692teststyles*/ 9693 // Inject element with style element and some CSS rules 9694 injectElementWithStyles = function( rule, callback, nodes, testnames ) { 9695 9696 var style, ret, node, docOverflow, 9697 div = document.createElement('div'), 9698 // After page load injecting a fake body doesn't work so check if body exists 9699 body = document.body, 9700 // IE6 and 7 won't return offsetWidth or offsetHeight unless it's in the body element, so we fake it. 9701 fakeBody = body || document.createElement('body'); 9702 9703 if ( parseInt(nodes, 10) ) { 9704 // In order not to give false positives we create a node for each test 9705 // This also allows the method to scale for unspecified uses 9706 while ( nodes-- ) { 9707 node = document.createElement('div'); 9708 node.id = testnames ? testnames[nodes] : mod + (nodes + 1); 9709 div.appendChild(node); 9710 } 9711 } 9712 9713 // <style> elements in IE6-9 are considered 'NoScope' elements and therefore will be removed 9714 // when injected with innerHTML. To get around this you need to prepend the 'NoScope' element 9715 // with a 'scoped' element, in our case the soft-hyphen entity as it won't mess with our measurements. 9716 // msdn.microsoft.com/en-us/library/ms533897%28VS.85%29.aspx 9717 // Documents served as xml will throw if using ­ so use xml friendly encoded version. See issue #277 9718 style = ['­','<style id="s', mod, '">', rule, '</style>'].join(''); 9719 div.id = mod; 9720 // IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody. 9721 // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270 9722 (body ? div : fakeBody).innerHTML += style; 9723 fakeBody.appendChild(div); 9724 if ( !body ) { 9725 //avoid crashing IE8, if background image is used 9726 fakeBody.style.background = ''; 9727 //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible 9728 fakeBody.style.overflow = 'hidden'; 9729 docOverflow = docElement.style.overflow; 9730 docElement.style.overflow = 'hidden'; 9731 docElement.appendChild(fakeBody); 9732 } 9733 9734 ret = callback(div, rule); 9735 // If this is done after page load we don't want to remove the body so check if body exists 9736 if ( !body ) { 9737 fakeBody.parentNode.removeChild(fakeBody); 9738 docElement.style.overflow = docOverflow; 9739 } else { 9740 div.parentNode.removeChild(div); 9741 } 9742 9743 return !!ret; 9744 9745 }, 9746 /*>>teststyles*/ 9747 9748 /*>>mq*/ 9749 // adapted from matchMedia polyfill 9750 // by Scott Jehl and Paul Irish 9751 // gist.github.com/786768 9752 testMediaQuery = function( mq ) { 9753 9754 var matchMedia = window.matchMedia || window.msMatchMedia; 9755 if ( matchMedia ) { 9756 return matchMedia(mq) && matchMedia(mq).matches || false; 9757 } 9758 9759 var bool; 9760 9761 injectElementWithStyles('@media ' + mq + ' { #' + mod + ' { position: absolute; } }', function( node ) { 9762 bool = (window.getComputedStyle ? 9763 getComputedStyle(node, null) : 9764 node.currentStyle)['position'] == 'absolute'; 9765 }); 9766 9767 return bool; 9768 9769 }, 9770 /*>>mq*/ 9771 9772 9773 /*>>hasevent*/ 9774 // 9775 // isEventSupported determines if a given element supports the given event 9776 // kangax.github.com/iseventsupported/ 9777 // 9778 // The following results are known incorrects: 9779 // Modernizr.hasEvent("webkitTransitionEnd", elem) // false negative 9780 // Modernizr.hasEvent("textInput") // in Webkit. github.com/Modernizr/Modernizr/issues/333 9781 // ... 9782 isEventSupported = (function() { 9783 9784 var TAGNAMES = { 9785 'select': 'input', 'change': 'input', 9786 'submit': 'form', 'reset': 'form', 9787 'error': 'img', 'load': 'img', 'abort': 'img' 9788 }; 9789 9790 function isEventSupported( eventName, element ) { 9791 9792 element = element || document.createElement(TAGNAMES[eventName] || 'div'); 9793 eventName = 'on' + eventName; 9794 9795 // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those 9796 var isSupported = eventName in element; 9797 9798 if ( !isSupported ) { 9799 // If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element 9800 if ( !element.setAttribute ) { 9801 element = document.createElement('div'); 9802 } 9803 if ( element.setAttribute && element.removeAttribute ) { 9804 element.setAttribute(eventName, ''); 9805 isSupported = is(element[eventName], 'function'); 9806 9807 // If property was created, "remove it" (by setting value to `undefined`) 9808 if ( !is(element[eventName], 'undefined') ) { 9809 element[eventName] = undefined; 9810 } 9811 element.removeAttribute(eventName); 9812 } 9813 } 9814 9815 element = null; 9816 return isSupported; 9817 } 9818 return isEventSupported; 9819 })(), 9820 /*>>hasevent*/ 9821 9822 // TODO :: Add flag for hasownprop ? didn't last time 9823 9824 // hasOwnProperty shim by kangax needed for Safari 2.0 support 9825 _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp; 9826 9827 if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) { 9828 hasOwnProp = function (object, property) { 9829 return _hasOwnProperty.call(object, property); 9830 }; 9831 } 9832 else { 9833 hasOwnProp = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */ 9834 return ((property in object) && is(object.constructor.prototype[property], 'undefined')); 9835 }; 9836 } 9837 9838 // Adapted from ES5-shim https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js 9839 // es5.github.com/#x15.3.4.5 9840 9841 if (!Function.prototype.bind) { 9842 Function.prototype.bind = function bind(that) { 9843 9844 var target = this; 9845 9846 if (typeof target != "function") { 9847 throw new TypeError(); 9848 } 9849 9850 var args = slice.call(arguments, 1), 9851 bound = function () { 9852 9853 if (this instanceof bound) { 9854 9855 var F = function(){}; 9856 F.prototype = target.prototype; 9857 var self = new F(); 9858 9859 var result = target.apply( 9860 self, 9861 args.concat(slice.call(arguments)) 9862 ); 9863 if (Object(result) === result) { 9864 return result; 9865 } 9866 return self; 9867 9868 } else { 9869 9870 return target.apply( 9871 that, 9872 args.concat(slice.call(arguments)) 9873 ); 9874 9875 } 9876 9877 }; 9878 9879 return bound; 9880 }; 9881 } 9882 9883 /** 9884 * setCss applies given styles to the Modernizr DOM node. 9885 */ 9886 function setCss( str ) { 9887 mStyle.cssText = str; 9888 } 9889 9890 /** 9891 * setCssAll extrapolates all vendor-specific css strings. 9892 */ 9893 function setCssAll( str1, str2 ) { 9894 return setCss(prefixes.join(str1 + ';') + ( str2 || '' )); 9895 } 9896 9897 /** 9898 * is returns a boolean for if typeof obj is exactly type. 9899 */ 9900 function is( obj, type ) { 9901 return typeof obj === type; 9902 } 9903 9904 /** 9905 * contains returns a boolean for if substr is found within str. 9906 */ 9907 function contains( str, substr ) {
9908 return !!~('' + str).indexOf(substr); 9909 } 9910 9911 /*>>testprop*/ 9912 9913 // testProps is a generic CSS / DOM property test. 9914 9915 // In testing support for a given CSS property, it's legit to test: 9916 // `elem.style[styleName] !== undefined` 9917 // If the property is supported it will return an empty string, 9918 // if unsupported it will return undefined. 9919 9920 // We'll take advantage of this quick test and skip setting a style 9921 // on our modernizr element, but instead just testing undefined vs 9922 // empty string. 9923 9924 // Because the testing of the CSS property names (with "-", as 9925 // opposed to the camelCase DOM properties) is non-portable and 9926 // non-standard but works in WebKit and IE (but not Gecko or Opera), 9927 // we explicitly reject properties with dashes so that authors 9928 // developing in WebKit or IE first don't end up with 9929 // browser-specific content by accident. 9930 9931 function testProps( props, prefixed ) { 9932 for ( var i in props ) { 9933 var prop = props[i]; 9934 if ( !contains(prop, "-") && mStyle[prop] !== undefined ) { 9935 return prefixed == 'pfx' ? prop : true; 9936 } 9937 } 9938 return false; 9939 } 9940 /*>>testprop*/ 9941 9942 // TODO :: add testDOMProps 9943 /** 9944 * testDOMProps is a generic DOM property test; if a browser supports 9945 * a certain property, it won't return undefined for it. 9946 */ 9947 function testDOMProps( props, obj, elem ) { 9948 for ( var i in props ) { 9949 var item = obj[props[i]]; 9950 if ( item !== undefined) { 9951 9952 // return the property name as a string 9953 if (elem === false) return props[i]; 9954 9955 // let's bind a function 9956 if (is(item, 'function')){ 9957 // default to autobind unless override 9958 return item.bind(elem || obj); 9959 } 9960 9961 // return the unbound function or obj or value 9962 return item; 9963 } 9964 } 9965 return false; 9966 } 9967 9968 /*>>testallprops*/ 9969 /** 9970 * testPropsAll tests a list of DOM properties we want to check against. 9971 * We specify literally ALL possible (known and/or likely) properties on 9972 * the element including the non-vendor prefixed one, for forward- 9973 * compatibility. 9974 */ 9975 function testPropsAll( prop, prefixed, elem ) { 9976 9977 var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1), 9978 props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' '); 9979 9980 // did they call .prefixed('boxSizing') or are we just testing a prop? 9981 if(is(prefixed, "string") || is(prefixed, "undefined")) { 9982 return testProps(props, prefixed); 9983 9984 // otherwise, they called .prefixed('requestAnimationFrame', window[, elem]) 9985 } else { 9986 props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' '); 9987 return testDOMProps(props, prefixed, elem); 9988 } 9989 } 9990 /*>>testallprops*/ 9991 9992 9993 /** 9994 * Tests 9995 * ----- 9996 */ 9997 9998 // The *new* flexbox 9999 // dev.w3.org/csswg/css3-flexbox 10000 10001 tests['flexbox'] = function() { 10002 return testPropsAll('flexWrap'); 10003 }; 10004 10005 // The *old* flexbox 10006 // www.w3.org/TR/2009/WD-css3-flexbox-20090723/ 10007 10008 tests['flexboxlegacy'] = function() { 10009 return testPropsAll('boxDirection'); 10010 }; 10011 10012 // On the S60 and BB Storm, getContext exists, but always returns undefined 10013 // so we actually have to call getContext() to verify 10014 // github.com/Modernizr/Modernizr/issues/issue/97/ 10015 10016 tests['canvas'] = function() { 10017 var elem = document.createElement('canvas'); 10018 return !!(elem.getContext && elem.getContext('2d')); 10019 }; 10020 10021 tests['canvastext'] = function() { 10022 return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function')); 10023 }; 10024 10025 // webk.it/70117 is tracking a legit WebGL feature detect proposal 10026 10027 // We do a soft detect which may false positive in order to avoid 10028 // an expensive context creation: bugzil.la/732441 10029 10030 tests['webgl'] = function() { 10031 return !!window.WebGLRenderingContext; 10032 }; 10033 10034 /* 10035 * The Modernizr.touch test only indicates if the browser supports 10036 * touch events, which does not necessarily reflect a touchscreen 10037 * device, as evidenced by tablets running Windows 7 or, alas, 10038 * the Palm Pre / WebOS (touch) phones. 10039 * 10040 * Additionally, Chrome (desktop) used to lie about its support on this, 10041 * but that has since been rectified: crbug.com/36415 10042 * 10043 * We also test for Firefox 4 Multitouch Support. 10044 * 10045 * For more info, see: modernizr.github.com/Modernizr/touch.html 10046 */ 10047 10048 tests['touch'] = function() { 10049 var bool; 10050 10051 if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) { 10052 bool = true; 10053 } else { 10054 injectElementWithStyles(['@media (',prefixes.join('touch-enabled),('),mod,')','{#modernizr{top:9px;position:absolute}}'].join(''), function( node ) { 10055 bool = node.offsetTop === 9; 10056 }); 10057 } 10058 10059 return bool; 10060 }; 10061 10062 10063 // geolocation is often considered a trivial feature detect... 10064 // Turns out, it's quite tricky to get right: 10065 // 10066 // Using !!navigator.geolocation does two things we don't want. It: 10067 // 1. Leaks memory in IE9: github.com/Modernizr/Modernizr/issues/513 10068 // 2. Disables page caching in WebKit: webk.it/43956 10069 // 10070 // Meanwhile, in Firefox < 8, an about:config setting could expose 10071 // a false positive that would throw an exception: bugzil.la/688158 10072 10073 tests['geolocation'] = function() { 10074 return 'geolocation' in navigator; 10075 }; 10076 10077 10078 tests['postmessage'] = function() { 10079 return !!window.postMessage; 10080 }; 10081 10082 10083 // Chrome incognito mode used to throw an exception when using openDatabase 10084 // It doesn't anymore. 10085 tests['websqldatabase'] = function() {
10086 return !!window.openDatabase; 10087 }; 10088 10089 // Vendors had inconsistent prefixing with the experimental Indexed DB: 10090 // - Webkit's implementation is accessible through webkitIndexedDB 10091 // - Firefox shipped moz_indexedDB before FF4b9, but since then has been mozIndexedDB 10092 // For speed, we don't test the legacy (and beta-only) indexedDB 10093 tests['indexedDB'] = function() { 10094 return !!testPropsAll("indexedDB", window); 10095 }; 10096 10097 // documentMode logic from YUI to filter out IE8 Compat Mode 10098 // which false positives. 10099 tests['hashchange'] = function() { 10100 return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7); 10101 }; 10102 10103 // Per 1.6: 10104 // This used to be Modernizr.historymanagement but the longer 10105 // name has been deprecated in favor of a shorter and property-matching one. 10106 // The old API is still available in 1.6, but as of 2.0 will throw a warning, 10107 // and in the first release thereafter disappear entirely. 10108 tests['history'] = function() { 10109 return !!(window.history && history.pushState); 10110 }; 10111 10112 tests['draganddrop'] = function() { 10113 var div = document.createElement('div'); 10114 return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div); 10115 }; 10116 10117 // FF3.6 was EOL'ed on 4/24/12, but the ESR version of FF10 10118 // will be supported until FF19 (2/12/13), at which time, ESR becomes FF17. 10119 // FF10 still uses prefixes, so check for it until then. 10120 // for more ESR info, see: mozilla.org/en-US/firefox/organizations/faq/ 10121 tests['websockets'] = function() { 10122 return 'WebSocket' in window || 'MozWebSocket' in window; 10123 }; 10124 10125 10126 // css-tricks.com/rgba-browser-support/ 10127 tests['rgba'] = function() { 10128 // Set an rgba() color and check the returned value 10129 10130 setCss('background-color:rgba(150,255,150,.5)'); 10131 10132 return contains(mStyle.backgroundColor, 'rgba'); 10133 }; 10134 10135 tests['hsla'] = function() { 10136 // Same as rgba(), in fact, browsers re-map hsla() to rgba() internally, 10137 // except IE9 who retains it as hsla 10138 10139 setCss('background-color:hsla(120,40%,100%,.5)'); 10140 10141 return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla'); 10142 }; 10143 10144 tests['multiplebgs'] = function() { 10145 // Setting multiple images AND a color on the background shorthand property 10146 // and then querying the style.background property value for the number of 10147 // occurrences of "url(" is a reliable method for detecting ACTUAL support for this! 10148 10149 setCss('background:url(https://),url(https://),red url(https://)'); 10150 10151 // If the UA supports multiple backgrounds, there should be three occurrences 10152 // of the string "url(" in the return value for elemStyle.background 10153 10154 return (/(url\s*\(.*?){3}/).test(mStyle.background); 10155 }; 10156 10157 10158 10159 // this will false positive in Opera Mini 10160 // github.com/Modernizr/Modernizr/issues/396 10161 10162 tests['backgroundsize'] = function() { 10163 return testPropsAll('backgroundSize'); 10164 }; 10165 10166 tests['borderimage'] = function() { 10167 return testPropsAll('borderImage'); 10168 }; 10169 10170 10171 // Super comprehensive table about all the unique implementations of 10172 // border-radius: muddledramblings.com/table-of-css3-border-radius-compliance 10173
10174 tests['borderradius'] = function() { 10175 return testPropsAll('borderRadius'); 10176 }; 10177 10178 // WebOS unfortunately false positives on this test. 10179 tests['boxshadow'] = function() { 10180 return testPropsAll('boxShadow'); 10181 }; 10182 10183 // FF3.0 will false positive on this test 10184 tests['textshadow'] = function() { 10185 return document.createElement('div').style.textShadow === ''; 10186 }; 10187 10188 10189 tests['opacity'] = function() { 10190 // Browsers that actually have CSS Opacity implemented have done so 10191 // according to spec, which means their return values are within the 10192 // range of [0.0,1.0] - including the leading zero. 10193 10194 setCssAll('opacity:.55'); 10195 10196 // The non-literal . in this regex is intentional: 10197 // German Chrome returns this value as 0,55 10198 // github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632 10199 return (/^0.55$/).test(mStyle.opacity); 10200 }; 10201 10202 10203 // Note, Android < 4 will pass this test, but can only animate 10204 // a single property at a time 10205 // goo.gl/v3V4Gp 10206 tests['cssanimations'] = function() { 10207 return testPropsAll('animationName'); 10208 }; 10209 10210 10211 tests['csscolumns'] = function() { 10212 return testPropsAll('columnCount'); 10213 }; 10214 10215 10216 tests['cssgradients'] = function() { 10217 /** 10218 * For CSS Gradients syntax, please see: 10219 * webkit.org/blog/175/introducing-css-gradients/ 10220 * developer.mozilla.org/en/CSS/-moz-linear-gradient 10221 * developer.mozilla.org/en/CSS/-moz-radial-gradient 10222 * dev.w3.org/csswg/css3-images/#gradients- 10223 */ 10224 10225 var str1 = 'background-image:', 10226 str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));', 10227 str3 = 'linear-gradient(left top,#9f9, white);'; 10228 10229 setCss( 10230 // legacy webkit syntax (FIXME: remove when syntax not in use anymore) 10231 (str1 + '-webkit- '.split(' ').join(str2 + str1) + 10232 // standard syntax // trailing 'background-image:' 10233 prefixes.join(str3 + str1)).slice(0, -str1.length) 10234 ); 10235 10236 return contains(mStyle.backgroundImage, 'gradient'); 10237 }; 10238 10239 10240 tests['cssreflections'] = function() { 10241 return testPropsAll('boxReflect'); 10242 }; 10243 10244 10245 tests['csstransforms'] = function() { 10246 return !!testPropsAll('transform'); 10247 }; 10248 10249 10250 tests['csstransforms3d'] = function() { 10251 10252 var ret = !!testPropsAll('perspective'); 10253 10254 // Webkit's 3D transforms are passed off to the browser's own graphics renderer. 10255 // It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in 10256 // some conditions. As a result, Webkit typically recognizes the syntax but 10257 // will sometimes throw a false positive, thus we must do a more thorough check: 10258 if ( ret && 'webkitPerspective' in docElement.style ) { 10259 10260 // Webkit allows this media query to succeed only if the feature is enabled. 10261 // `@media (transform-3d),(-webkit-transform-3d){ ... }` 10262 injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function( node, rule ) { 10263 ret = node.offsetLeft === 9 && node.offsetHeight === 3; 10264 }); 10265 } 10266 return ret; 10267 }; 10268 10269 10270 tests['csstransitions'] = function() { 10271 return testPropsAll('transition'); 10272 }; 10273 10274 10275 /*>>fontface*/ 10276 // @font-face detection routine by Diego Perini 10277 // javascript.nwbox.com/CSSSupport/ 10278 10279 // false positives: 10280 // WebOS github.com/Modernizr/Modernizr/issues/342 10281 // WP7 github.com/Modernizr/Modernizr/issues/538 10282 tests['fontface'] = function() { 10283 var bool; 10284 10285 injectElementWithStyles('@font-face {font-family:"font";src:url("https://")}', function( node, rule ) { 10286 var style = document.getElementById('smodernizr'), 10287 sheet = style.sheet || style.styleSheet, 10288 cssText = sheet ? (sheet.cssRules && sheet.cssRules[0] ? sheet.cssRules[0].cssText : sheet.cssText || '') : ''; 10289 10290 bool = /src/i.test(cssText) && cssText.indexOf(rule.split(' ')[0]) === 0; 10291 }); 10292 10293 return bool; 10294 }; 10295 /*>>fontface*/ 10296 10297 // CSS generated content detection 10298 tests['generatedcontent'] = function() { 10299 var bool; 10300 10301 injectElementWithStyles(['#',mod,'{font:0/0 a}
10301#',mod,':after{content:"',smile,'";visibility:hidden;font:3px/1 a}'].join(''), function( node ) { 10302 bool = node.offsetHeight >= 3; 10303 }); 10304 10305 return bool; 10306 }; 10307 10308 10309 10310 // These tests evaluate support of the video/audio elements, as well as 10311 // testing what types of content they support. 10312 // 10313 // We're using the Boolean constructor here, so that we can extend the value 10314 // e.g. Modernizr.video // true 10315 // Modernizr.video.ogg // 'probably' 10316 // 10317 // Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845 10318 // thx to NielsLeenheer and zcorpan 10319 10320 // Note: in some older browsers, "no" was a return value instead of empty string. 10321 // It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2 10322 // It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5 10323 10324 tests['video'] = function() { 10325 var elem = document.createElement('video'), 10326 bool = false; 10327 10328 // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224 10329 try { 10330 if ( bool = !!elem.canPlayType ) { 10331 bool = new Boolean(bool); 10332 bool.ogg = elem.canPlayType('video/ogg; codecs="theora"') .replace(/^no$/,''); 10333
10334 // Without QuickTime, this value will be `undefined`. github.com/Modernizr/Modernizr/issues/546 10335 bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"') .replace(/^no$/,''); 10336 10337 bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,''); 10338 } 10339 10340 } catch(e) { } 10341 10342 return bool; 10343 }; 10344 10345 tests['audio'] = function() { 10346 var elem = document.createElement('audio'), 10347 bool = false; 10348 10349 try { 10350 if ( bool = !!elem.canPlayType ) { 10351 bool = new Boolean(bool); 10352 bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,''); 10353 bool.mp3 = elem.canPlayType('audio/mpeg;') .replace(/^no$/,''); 10354 10355 // Mimetypes accepted: 10356 // developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements 10357 // bit.ly/iphoneoscodecs 10358 bool.wav = elem.canPlayType('audio/wav; codecs="1"') .replace(/^no$/,''); 10359 bool.m4a = ( elem.canPlayType('audio/x-m4a;') || 10360 elem.canPlayType('audio/aac;')) .replace(/^no$/,''); 10361 } 10362 } catch(e) { } 10363 10364 return bool; 10365 }; 10366 10367 10368 // In FF4, if disabled, window.localStorage should === null. 10369 10370 // Normally, we could not test that directly and need to do a 10371 // `('localStorage' in window) && ` test first because otherwise Firefox will 10372 // throw bugzil.la/365772 if cookies are disabled 10373 10374 // Also in iOS5 Private Browsing mode, attempting to use localStorage.setItem 10375 // will throw the exception: 10376 // QUOTA_EXCEEDED_ERRROR DOM Exception 22. 10377 // Peculiarly, getItem and removeItem calls do not throw. 10378 10379 // Because we are forced to try/catch this, we'll go aggressive. 10380 10381 // Just FWIW: IE8 Compat mode supports these features completely: 10382 // www.quirksmode.org/dom/html5.html 10383 // But IE8 doesn't support either with local files 10384 10385 tests['localstorage'] = function() { 10386 try { 10387 localStorage.setItem(mod, mod); 10388 localStorage.removeItem(mod); 10389 return true; 10390 } catch(e) { 10391 return false; 10392 } 10393 }; 10394 10395 tests['sessionstorage'] = function() { 10396 try { 10397 sessionStorage.setItem(mod, mod); 10398 sessionStorage.removeItem(mod); 10399 return true; 10400 } catch(e) { 10401 return false; 10402 } 10403 }; 10404 10405 10406 tests['webworkers'] = function() { 10407 return !!window.Worker; 10408 }; 10409 10410 10411 tests['applicationcache'] = function() { 10412 return !!window.applicationCache; 10413 }; 10414 10415 10416 // Thanks to Erik Dahlstrom 10417 tests['svg'] = function() { 10418 return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect; 10419 }; 10420 10421 // specifically for SVG inline in HTML, not within XHTML 10422 // test page: paulirish.com/demo/inline-svg 10423 tests['inlinesvg'] = function() { 10424 var div = document.createElement('div'); 10425 div.innerHTML = '<svg/>'; 10426 return (div.firstChild && div.firstChild.namespaceURI) == ns.svg; 10427 }; 10428 10429 // SVG SMIL animation 10430 tests['smil'] = function() { 10431 return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS(ns.svg, 'animate'))); 10432 }; 10433 10434 // This test is only for clip paths in SVG proper, not clip paths on HTML content 10435 // demo: srufaculty.sru.edu/david.dailey/svg/newstuff/clipPath4.svg 10436 10437 // However read the comments to dig into applying SVG clippaths to HTML content here: 10438 // github.com/Modernizr/Modernizr/issues/213#issuecomment-1149491 10439 tests['svgclippaths'] = function() { 10440 return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath'))); 10441 }; 10442 10443 /*>>webforms*/ 10444 // input features and input types go directly onto the ret object, bypassing the tests loop. 10445 // Hold this guy to execute in a moment. 10446 function webforms() { 10447 /*>>input*/ 10448 // Run through HTML5's new input attributes to see if the UA understands any. 10449 // We're using f which is the <input> element created early on 10450 // Mike Taylr has created a comprehensive resource for testing these attributes 10451 // when applied to all input types: 10452 // miketaylr.com/code/input-type-attr.html 10453 // spec: www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary 10454 10455 // Only input placeholder is tested while textarea's placeholder is not. 10456 // Currently Safari 4 and Opera 11 have support only for the input placeholder 10457 // Both tests are available in feature-detects/forms-placeholder.js 10458 Modernizr['input'] = (function( props ) { 10459 for ( var i = 0, len = props.length; i < len; i++ ) { 10460 attrs[ props[i] ] = !!(props[i] in inputElem); 10461 } 10462 if (attrs.list){ 10463 // safari false positive's on datalist: webk.it/74252 10464 // see also github.com/Modernizr/Modernizr/issues/146 10465 attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement); 10466 } 10467 return attrs; 10468 })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' ')); 10469 /*>>input*/ 10470 10471 /*>>inputtypes*/ 10472 // Run through HTML5's new input types to see if the UA understands any. 10473 // This is put behind the tests runloop because it doesn't return a 10474 // true/false like all the other tests; instead, it returns an object 10475 // containing each input type with its corresponding true/false value 10476 10477 // Big thanks to @miketaylr for the html5 forms expertise. miketaylr.com/ 10478 Modernizr['inputtypes'] = (function(props) { 10479 10480 for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) { 10481 10482 inputElem.setAttribute('type', inputElemType = props[i]); 10483 bool = inputElem.type !== 'text'; 10484 10485 // We first check to see if the type we give it sticks.. 10486 // If the type does, we feed it a textual value, which shouldn't be val
10486id. 10487 // If the value doesn't stick, we know there's input sanitization which infers a custom UI 10488 if ( bool ) { 10489 10490 inputElem.value = smile; 10491 inputElem.style.cssText = 'position:absolute;visibility:hidden;'; 10492 10493 if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) { 10494 10495 docElement.appendChild(inputElem); 10496 defaultView = document.defaultView; 10497 10498 // Safari 2-4 allows the smiley as a value, despite making a slider 10499 bool = defaultView.getComputedStyle && 10500 defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' && 10501 // Mobile android web browser has false positive, so must 10502 // check the height to see if the widget is actually there. 10503 (inputElem.offsetHeight !== 0); 10504 10505 docElement.removeChild(inputElem); 10506 10507 } else if ( /^(search|tel)$/.test(inputElemType) ){ 10508 // Spec doesn't define any special parsing or detectable UI 10509 // behaviors so we pass these through as true 10510 10511 // Interestingly, opera fails the earlier test, so it doesn't 10512 // even make it here. 10513 10514 } else if ( /^(url|email)$/.test(inputElemType) ) { 10515 // Real url and email support comes with prebaked validation. 10516 bool = inputElem.checkValidity && inputElem.checkValidity() === false; 10517 10518 } else { 10519 // If the upgraded input compontent rejects the :) text, we got a winner 10520 bool = inputElem.value != smile; 10521 } 10522 } 10523 10524 inputs[ props[i] ] = !!bool; 10525 } 10526 return inputs; 10527 })('search tel url email datetime date month week time datetime-local number range color'.split(' ')); 10528 /*>>inputtypes*/ 10529 } 10530 /*>>webforms*/ 10531 10532 10533 // End of test definitions 10534 // ----------------------- 10535 10536 10537 10538 // Run through all tests and detect their support in the current UA. 10539 // todo: hypothetically we could be doing an array of tests and use a basic loop here. 10540 for ( var feature in tests ) { 10541 if ( hasOwnProp(tests, feature) ) { 10542 // run the test, throw the return value into the Modernizr, 10543 // then based on that boolean, define an appropriate className 10544 // and push it into an array of classes we'll join later. 10545 featureName = feature.toLowerCase(); 10546 Modernizr[featureName] = tests[feature](); 10547 10548 classes.push((Modernizr[featureName] ? '' : 'no-') + featureName); 10549 } 10550 } 10551 10552 /*>>webforms*/ 10553 // input tests need to run. 10554 Modernizr.input || webforms(); 10555 /*>>webforms*/ 10556 10557 10558 /** 10559 * addTest allows the user to define their own feature tests 10560 * the result will be added onto the Modernizr object, 10561 * as well as an appropriate className set on the html element 10562 * 10563 * @param feature - String naming the feature 10564 * @param test - Function returning true if feature is supported, false if not 10565 */ 10566 Modernizr.addTest = function ( feature, test ) { 10567 if ( typeof feature == 'object' ) { 10568 for ( var key in feature ) { 10569 if ( hasOwnProp( feature, key ) ) { 10570 Modernizr.addTest( key, feature[ key ] ); 10571 } 10572 } 10573 } else { 10574 10575 feature = feature.toLowerCase(); 10576 10577 if ( Modernizr[feature] !== undefined ) { 10578 // we're going to quit if you're trying to overwrite an existing test 10579 // if we were to allow it, we'd do this: 10580 // var re = new RegExp("\\b(no-)?" + feature + "\\b"); 10581 // docElement.className = docElement.className.replace( re, '' ); 10582 // but, no rly, stuff 'em. 10583 return Modernizr; 10584 } 10585 10586 test = typeof test == 'function' ? test() : test; 10587 10588 if (typeof enableClasses !== "undefined" && enableClasses) { 10589 docElement.className += ' ' + (test ? '' : 'no-') + feature; 10590 } 10591 Modernizr[feature] = test; 10592 10593 } 10594 10595 return Modernizr; // allow chaining. 10596 }; 10597 10598 10599 // Reset modElem.cssText to nothing to reduce memory footprint. 10600 setCss(''); 10601 modElem = inputElem = null; 10602 10603 /*>>shiv*/ 10604 /** 10605 * @preserve HTML5 Shiv prev3.7.1 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 10606 */ 10607 ;(function(window, document) { 10608 /*jshint evil:true */ 10609 /** version */ 10610 var version = '3.7.0'; 10611 10612 /** Preset options */ 10613 var options = window.html5 || {}; 10614 10615 /** Used to skip problem elements */ 10616 var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i; 10617 10618 /** Not all elements can be cloned in IE **/ 10619 var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i; 10620 10621 /** Detect whether the browser supports default html5 styles */ 10622 var supportsHtml5Styles; 10623 10624 /** Name of the expando, to work with multiple documents or to re-shiv one document */ 10625 var expando = '_html5shiv'; 10626 10627 /** The id for the the documents expando */ 10628 var expanID = 0; 10629 10630 /** Cached data for each document */ 10631 var expandoData = {}; 10632 10633 /** Detect whether the browser supports unknown elements */ 10634 var supportsUnknownElements; 10635 10636 (function() { 10637 try { 10638 var a = document.createElement('a'); 10639 a.innerHTML = '<xyz></xyz>'; 10640 //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles 10641 supportsHtml5Styles = ('hidden' in a); 10642 10643 supportsUnknownElements = a.childNodes.length == 1 || (function() { 10644 // assign a false positive if unable to shiv 10645 (document.createElement)('a'); 10646 var frag = document.createDocumentFragment(); 10647 return ( 10648 typeof frag.cloneNode == 'undefined' || 10649 typeof frag.createDocumentFragment == 'undefined' || 10650 typeof frag.createElement == 'undefined' 10651 ); 10652 }()); 10653 } catch(e) { 10654 // assign a false positive if detection fails => unable to shiv 10655 supportsHtml5Styles = true; 10656 supportsUnknownElements = true; 10657 } 10658 10659 }()); 10660 10661 /*--------------------------------------------------------------------------*/ 10662 10663 /** 10664 * Creates a style sheet with the given CSS text and adds it to the document. 10665 * @private 10666 * @param {Document} ownerDocument The document. 10667 * @param {String} cssText The CSS text. 10668 * @returns {StyleSheet} The style element. 10669 */ 10670 function addStyleSheet(ownerDocument, cssText) { 10671 var p = ownerDocument.createElement('p'), 10672 parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement; 10673 10674 p.innerHTML = 'x<style>' + cssText + '</style>'; 10675 return parent.insertBefore(p.lastChild, parent.firstChild); 10676 } 10677 10678 /** 10679 * Returns the value of `html5.elements` as an array.
vendor: 5,515 bytes, lines 10680-10819
10680 * @private 10681 * @returns {Array} An array of shived element node names. 10682 */ 10683 function getElements() { 10684 var elements = html5.elements; 10685 return typeof elements == 'string' ? elements.split(' ') : elements; 10686 } 10687 10688 /** 10689 * Returns the data associated to the given document 10690 * @private 10691 * @param {Document} ownerDocument The document. 10692 * @returns {Object} An object of data. 10693 */ 10694 function getExpandoData(ownerDocument) { 10695 var data = expandoData[ownerDocument[expando]]; 10696 if (!data) { 10697 data = {}; 10698 expanID++; 10699 ownerDocument[expando] = expanID; 10700 expandoData[expanID] = data; 10701 } 10702 return data; 10703 } 10704 10705 /** 10706 * returns a shived element for the given nodeName and document 10707 * @memberOf html5 10708 * @param {String} nodeName name of the element 10709 * @param {Document} ownerDocument The context document. 10710 * @returns {Object} The shived element. 10711 */ 10712 function createElement(nodeName, ownerDocument, data){ 10713 if (!ownerDocument) { 10714 ownerDocument = document; 10715 } 10716 if(supportsUnknownElements){ 10717 return ownerDocument.createElement(nodeName); 10718 } 10719 if (!data) { 10720 data = getExpandoData(ownerDocument); 10721 } 10722 var node; 10723 10724 if (data.cache[nodeName]) { 10725 node = data.cache[nodeName].cloneNode(); 10726 } else if (saveClones.test(nodeName)) { 10727 node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode(); 10728 } else { 10729 node = data.createElem(nodeName); 10730 } 10731 10732 // Avoid adding some elements to fragments in IE < 9 because 10733 // * Attributes like `name` or `type` cannot be set/changed once an element 10734 // is inserted into a document/fragment 10735 // * Link elements with `src` attributes that are inaccessible, as with 10736 // a 403 response, will cause the tab/window to crash 10737 // * Script elements appended to fragments will execute when their `src` 10738 // or `text` property is set 10739 return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node; 10740 } 10741 10742 /** 10743 * returns a shived DocumentFragment for the given document 10744 * @memberOf html5 10745 * @param {Document} ownerDocument The context document. 10746 * @returns {Object} The shived DocumentFragment. 10747 */ 10748 function createDocumentFragment(ownerDocument, data){ 10749 if (!ownerDocument) { 10750 ownerDocument = document; 10751 } 10752 if(supportsUnknownElements){ 10753 return ownerDocument.createDocumentFragment(); 10754 } 10755 data = data || getExpandoData(ownerDocument); 10756 var clone = data.frag.cloneNode(), 10757 i = 0, 10758 elems = getElements(), 10759 l = elems.length; 10760 for(;i<l;i++){ 10761 clone.createElement(elems[i]); 10762 } 10763 return clone; 10764 } 10765 10766 /** 10767 * Shivs the `createElement` and `createDocumentFragment` methods of the document. 10768 * @private 10769 * @param {Document|DocumentFragment} ownerDocument The document. 10770 * @param {Object} data of the document. 10771 */ 10772 function shivMethods(ownerDocument, data) { 10773 if (!data.cache) { 10774 data.cache = {}; 10775 data.createElem = ownerDocument.createElement; 10776 data.createFrag = ownerDocument.createDocumentFragment; 10777 data.frag = data.createFrag(); 10778 } 10779 10780 10781 ownerDocument.createElement = function(nodeName) { 10782 //abort shiv 10783 if (!html5.shivMethods) { 10784 return data.createElem(nodeName); 10785 } 10786 return createElement(nodeName, ownerDocument, data); 10787 }; 10788 10789 ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' + 10790 'var n=f.cloneNode(),c=n.createElement;' + 10791 'h.shivMethods&&(' + 10792 // unroll the `createElement` calls 10793 getElements().join().replace(/[\w\-]+/g, function(nodeName) { 10794 data.createElem(nodeName); 10795 data.frag.createElement(nodeName); 10796 return 'c("' + nodeName + '")'; 10797 }) + 10798 ');return n}' 10799 )(html5, data.frag); 10800 } 10801 10802 /*--------------------------------------------------------------------------*/ 10803 10804 /** 10805 * Shivs the given document. 10806 * @memberOf html5 10807 * @param {Document} ownerDocument The document to shiv. 10808 * @returns {Document} The shived document. 10809 */ 10810 function shivDocument(ownerDocument) { 10811 if (!ownerDocument) { 10812 ownerDocument = document; 10813 } 10814 var data = getExpandoData(ownerDocument); 10815 10816 if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) { 10817 data.hasCSS = !!addStyleSheet(ownerDocument, 10818 // corrects block display not defined in IE6/7/8/9 10819 'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{dis
10819play:block}' + 10820 // adds styling not present in IE6/7/8/9 10821 'mark{background:#FF0;color:#000}' + 10822 // hides non-rendered elements 10823 'template{display:none}' 10824 ); 10825 } 10826 if (!supportsUnknownElements) { 10827 shivMethods(ownerDocument, data); 10828 } 10829 return ownerDocument; 10830 } 10831 10832 /*--------------------------------------------------------------------------*/ 10833 10834 /** 10835 * The `html5` object is exposed so that more elements can be shived and 10836 * existing shiving can be detected on iframes. 10837 * @type Object 10838 * @example 10839 * 10840 * // options can be changed before the script is included 10841 * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false }; 10842 */ 10843 var html5 = { 10844 10845 /** 10846 * An array or space separated string of node names of the elements to shiv. 10847 * @memberOf html5 10848 * @type Array|String 10849 */ 10850 'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video', 10851 10852 /** 10853 * current version of html5shiv 10854 */ 10855 'version': version, 10856 10857 /** 10858 * A flag to indicate that the HTML5 style sheet should be inserted. 10859 * @memberOf html5 10860 * @type Boolean 10861 */ 10862 'shivCSS': (options.shivCSS !== false), 10863 10864 /** 10865 * Is equal to true if a browser supports creating unknown/HTML5 elements 10866 * @memberOf html5 10867 * @type boolean 10868 */ 10869 'supportsUnknownElements': supportsUnknownElements, 10870 10871 /** 10872 * A flag to indicate that the document's `createElement` and `createDocumentFragment` 10873 * methods should be overwritten. 10874 * @memberOf html5 10875 * @type Boolean 10876 */ 10877 'shivMethods': (options.shivMethods !== false), 10878 10879 /** 10880 * A string to describe the type of `html5` object ("default" or "default print"). 10881 * @memberOf html5
10882 * @type String 10883 */ 10884 'type': 'default', 10885 10886 // shivs the document according to the specified `html5` object options 10887 'shivDocument': shivDocument, 10888 10889 //creates a shived element 10890 createElement: createElement, 10891 10892 //creates a shived documentFragment 10893 createDocumentFragment: createDocumentFragment 10894 }; 10895 10896 /*--------------------------------------------------------------------------*/ 10897 10898 // expose html5 10899 window.html5 = html5; 10900 10901 // shiv the document 10902 shivDocument(document); 10903 10904 }(this, document)); 10905 /*>>shiv*/ 10906 10907 // Assign private properties to the return object with prefix 10908 Modernizr._version = version; 10909 10910 // expose these for the plugin API. Look in the source for how to join() them against your input 10911 /*>>prefixes*/ 10912 Modernizr._prefixes = prefixes; 10913 /*>>prefixes*/ 10914 /*>>domprefixes*/ 10915 Modernizr._domPrefixes = domPrefixes; 10916 Modernizr._cssomPrefixes = cssomPrefixes; 10917 /*>>domprefixes*/ 10918 10919 /*>>mq*/ 10920 // Modernizr.mq tests a given media query, live against the current state of the window 10921 // A few important notes: 10922 // * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false 10923 // * A max-width or orientation query will be evaluated against the current state, which may change later. 10924 // * You must specify values. Eg. If you are testing support for the min-width media query use: 10925 // Modernizr.mq('(min-width:0)') 10926 // usage: 10927 // Modernizr.mq('only screen and (max-width:768)') 10928 Modernizr.mq = testMediaQuery; 10929 /*>>mq*/ 10930 10931 /*>>hasevent*/ 10932 // Modernizr.hasEvent() detects support for a given event, with an optional element to test on 10933 // Modernizr.hasEvent('gesturestart', elem) 10934 Modernizr.hasEvent = isEventSupported; 10935 /*>>hasevent*/ 10936 10937 /*>>testprop*/ 10938 // Modernizr.testProp() investigates whether a given style property is recognized 10939 // Note that the property names must be provided in the camelCase variant. 10940 // Modernizr.testProp('pointerEvents') 10941 Modernizr.testProp = function(prop){ 10942 return testProps([prop]); 10943 }; 10944 /*>>testprop*/ 10945 10946 /*>>testallprops*/ 10947 // Modernizr.testAllProps() investigates whether a given style property, 10948 // or any of its vendor-prefixed variants, is recognized 10949 // Note that the property names must be provided in the camelCase variant. 10950 // Modernizr.testAllProps('boxSizing') 10951 Modernizr.testAllProps = testPropsAll; 10952 /*>>testallprops*/ 10953 10954 10955 /*>>teststyles*/ 10956 // Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards 10957 // Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... }) 10958 Modernizr.testStyles = injectElementWithStyles; 10959 /*>>teststyles*/ 10960 10961 10962 /*>>prefixed*/ 10963 // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input 10964 // Modernizr.prefixed('boxSizing') // 'MozBoxSizing' 10965 10966 // Properties must be passed as dom-style camelcase, rather than `box-sizing` hypentated style. 10967 // Return values will also be the camelCase variant, if you need to translate that to hypenated style use: 10968 // 10969 // str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-'); 10970 10971 // If you're trying to ascertain which transition end event to bind to, you might do something like... 10972 // 10973 // var transEndEventNames = { 10974 // 'WebkitTransition' : 'webkitTransitionEnd', 10975 // 'MozTransition' : 'transitionend', 10976 // 'OTransition' : 'oTransitionEnd', 10977 // 'msTransition' : 'MSTransitionEnd', 10978 // 'transition' : 'transitionend' 10979 // }, 10980 // transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ]; 10981 10982 Modernizr.prefixed = function(prop, obj, elem){ 10983 if(!obj) { 10984 return testPropsAll(prop, 'pfx'); 10985 } else { 10986 // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame' 10987 return testPropsAll(prop, obj, elem); 10988 } 10989 }; 10990 /*>>prefixed*/ 10991 10992 10993 /*>>cssclasses*/ 10994 // Remove "no-js" class from <html> element, if it exists: 10995 docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') + 10996 10997 // Add the new classes to the <html> element. 10998 (enableClasses ? ' js ' + classes.join(' ') : ''); 10999 /*>>cssclasses*/ 11000 11001 return Modernizr; 11002 11003})(this, this.document); 11004 11005/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */ 11006/*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */ 11007 11008window.respond_staus = "pending"; 11009window.matchMedia = window.matchMedia || (function( doc, undefined ) { 11010 "use strict"; 11011 11012 var bool, 11013 docElem = doc.documentElement, 11014 refNode = docElem.firstElementChild || docElem.firstChild, 11015 // fakeBody required for <FF4 when executed in <head> 11016 fakeBody = doc.createElement( "body" ), 11017 div = doc.createElement( "div" ); 11018 11019 div.id = "mq-test-1"; 11020 div.style.cssText = "position:absolute;top:-100em"; 11021 fakeBody.style.background = "none"; 11022 fakeBody.appendChild(div); 11023 11024 return function(q){ 11025 11026 div.innerHTML = "­<style media=\"" + q + "\"> #mq-test-1 { width: 42px; }</style>"; 11027
11028 docElem.insertBefore( fakeBody, refNode ); 11029 bool = div.offsetWidth === 42; 11030 docElem.removeChild( fakeBody ); 11031 11032 return { 11033 matches: bool, 11034 media: q 11035 }; 11036 11037 }; 11038 11039}( document )); 11040 11041 11042 11043 11044 11045/*! Respond.js v1.3.0: min/max-width media query polyfill. (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs */ 11046(function ( win ){ 11047 11048 "use strict"; 11049 11050 //exposed namespace 11051 var respond = {}; 11052 win.respond = respond; 11053 11054 //define update even in native-mq-supporting browsers, to avoid errors 11055 respond.update = function(){ }; 11056 11057 //expose media query support flag for external use 11058 respond.mediaQueriesSupported = win.matchMedia && win.matchMedia( "only all" ).matches; 11059 11060 //if media queries are supported, exit here 11061 if( respond.mediaQueriesSupported ){ 11062 return; 11063 } 11064 11065 //define vars 11066 var doc = win.document, 11067 docElem = doc.documentElement, 11068 mediastyles = [], 11069 rules = [], 11070 appendedEls = [], 11071 parsedSheets = {}, 11072 resizeThrottle = 30, 11073 head = doc.getElementsByTagName( "head" )[0] || docElem, 11074 base = doc.getElementsByTagName( "base" )[0], 11075 links = head.getElementsByTagName( "link" ), 11076 requestQueue = [], 11077 11078 //loop stylesheets, send text content to translate 11079 ripCSS = function(){ 11080 11081 for( var i = 0; i < links.length; i++ ){ 11082 var sheet = links[ i ], 11083 href = sheet.href, 11084 media = sheet.media, 11085 isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet"; 11086 11087 //only links plz and prevent re-parsing 11088 if( !!href && isCSS && !parsedSheets[ href ] ){ 11089 // selectivizr exposes css through the rawCssText expando 11090 if (sheet.styleSheet && sheet.styleSheet.rawCssText) { 11091 translate( sheet.styleSheet.rawCssText, href, media ); 11092 parsedSheets[ href ] = true; 11093 } else { 11094 if( (!/^([a-zA-Z:]*\/\/)/.test( href ) && !base) || 11095 href.replace( RegExp.$1, "" ).split( "/" )[0] === win.location.host ){ 11096 requestQueue.push( { 11097 href: href, 11098 media: media 11099 } ); 11100 } 11101 } 11102 } 11103 } 11104 makeRequests(); 11105 }, 11106 11107 //recurse through request queue, get css text 11108 makeRequests = function(){ 11109 if( requestQueue.length ){ 11110 var thisRequest = requestQueue.shift(); 11111 11112 ajax( thisRequest.href, function( styles ){ 11113 translate( styles, thisRequest.href, thisRequest.media ); 11114 parsedSheets[ thisRequest.href ] = true; 11115 11116 // by wrapping recursive function call in setTimeout 11117 // we prevent "Stack overflow" error in IE7 11118 win.setTimeout(function(){ makeRequests(); },0); 11119 }); 11120 } else { 11121 $(window).trigger("onRespondFinish"); 11122 } 11123 }, 11124 11125 //find media blocks in css text, convert to style blocks 11126 translate = function( styles, href, media ){ 11127 var qs = styles.match( /@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi ), 11128 ql = qs && qs.length || 0; 11129 11130 //try to get CSS path 11131 href = href.substring( 0, href.lastIndexOf( "/" ) ); 11132 11133 var repUrls = function( css ){ 11134 return css.replace( /(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g, "$1" + href + "$2$3" ); 11135 }, 11136 useMedia = !ql && media; 11137 11138 //if path exists, tack on trailing slash 11139 if( href.length ){ href += "/"; } 11140 11141 //if no internal queries exist, but media attr does, use that 11142 //note: this currently lacks support for situations where a media attr is specified on a link AND 11143 //its associated stylesheet has internal CSS media queries. 11144 //In those cases, the media attribute will currently be ignored. 11145 if( useMedia ){ 11146 ql = 1; 11147 } 11148 11149 for( var i = 0; i < ql; i++ ){ 11150 var fullq, thisq, eachq, eql; 11151 11152 //media attr 11153 if( useMedia ){ 11154 fullq = media; 11155 rules.push( repUrls( styles ) ); 11156 } 11157 //parse for styles 11158 else{ 11159 fullq = qs[ i ].match( /@media *([^\{]+)\{([\S\s]+?)$/ ) && RegExp.$1; 11160 rules.push( RegExp.$2 && repUrls( RegExp.$2 ) ); 11161 } 11162 11163 eachq = fullq.split( "," ); 11164 eql = eachq.length; 11165 11166 for( var j = 0; j < eql; j++ ){ 11167 thisq = eachq[ j ]; 11168 mediastyles.push( { 11169 media : thisq.split( "(" )[ 0 ].match( /(only\s+)?([a-zA-Z]+)\s?/ ) && RegExp.$2 || "all", 11170 rules : rules.length - 1, 11171 hasquery : thisq.indexOf("(") > -1, 11172 minw : thisq.match( /\(\s*min\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ), 11173 maxw : thisq.match( /\(\s*max\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ) 11174 } ); 11175 } 11176 } 11177 11178 applyMedia(); 11179 }, 11180 11181 lastCall, 11182 11183 resizeDefer, 11184 11185 // returns the value of 1em in pixels 11186 getEmValue = function() { 11187 var ret, 11188 div = doc.createElement('div'), 11189 body = doc.body, 11190 fakeUsed = false;
11191 11192 div.style.cssText = "position:absolute;font-size:1em;width:1em"; 11193 11194 if( !body ){ 11195 body = fakeUsed = doc.createElement( "body" ); 11196 body.style.background = "none"; 11197 } 11198 11199 body.appendChild( div ); 11200 11201 docElem.insertBefore( body, docElem.firstChild ); 11202 11203 ret = div.offsetWidth; 11204 11205 if( fakeUsed ){ 11206 docElem.removeChild( body ); 11207 } 11208 else { 11209 body.removeChild( div ); 11210 } 11211 11212 //also update eminpx before returning 11213 ret = eminpx = parseFloat(ret); 11214 11215 return ret; 11216 }, 11217 11218 //cached container for 1em value, populated the first time it's needed 11219 eminpx, 11220 11221 //enable/disable styles 11222 applyMedia = function( fromResize ){ 11223 var name = "clientWidth", 11224 docElemProp = docElem[ name ], 11225 currWidth = doc.compatMode === "CSS1Compat" && docElemProp || doc.body[ name ] || docElemProp, 11226 styleBlocks = {}, 11227 lastLink = links[ links.length-1 ], 11228 now = (new Date()).getTime(); 11229 11230 //throttle resize calls 11231 if( fromResize && lastCall && now - lastCall < resizeThrottle ){ 11232 win.clearTimeout( resizeDefer ); 11233 resizeDefer = win.setTimeout( applyMedia, resizeThrottle ); 11234 return; 11235 } 11236 else { 11237 lastCall = now; 11238 } 11239 11240 for( var i in mediastyles ){ 11241 if( mediastyles.hasOwnProperty( i ) ){ 11242 var thisstyle = mediastyles[ i ], 11243 min = thisstyle.minw, 11244 max = thisstyle.maxw, 11245 minnull = min === null, 11246 maxnull = max === null, 11247 em = "em"; 11248 11249 if( !!min ){ 11250 min = parseFloat( min ) * ( min.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 ); 11251 } 11252 if( !!max ){ 11253 max = parseFloat( max ) * ( max.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 ); 11254 } 11255 11256 // if there's no media query at all (the () part), or min or max is not null, and if either is present, they're true 11257 if( !thisstyle.hasquery || ( !minnull || !maxnull ) && ( minnull || currWidth >= min ) && ( maxnull || currWidth <= max ) ){ 11258 if( !styleBlocks[ thisstyle.media ] ){ 11259 styleBlocks[ thisstyle.media ] = []; 11260 } 11261 styleBlocks[ thisstyle.media ].push( rules[ thisstyle.rules ] ); 11262 } 11263 } 11264 } 11265 11266 //remove any existing respond style element(s) 11267 for( var j in appendedEls ){ 11268 if( appendedEls.hasOwnProperty( j ) ){ 11269 if( appendedEls[ j ] && appendedEls[ j ].parentNode === head ){ 11270 head.removeChild( appendedEls[ j ] ); 11271 } 11272 } 11273 } 11274 11275 //inject active styles, grouped by media type 11276 for( var k in styleBlocks ){ 11277 if( styleBlocks.hasOwnProperty( k ) ){ 11278 var ss = doc.createElement( "style" ), 11279 css = styleBlocks[ k ].join( "\n" ); 11280 11281 ss.type = "text/css"; 11282 ss.media = k; 11283 11284 //originally, ss was appended to a documentFragment and sheets were appended in bulk. 11285 //this caused crashes in IE in a number of circumstances, such as when the HTML element had a bg image set, so appending beforehand seems best. Thanks to @dvelyk for the initial research on this one! 11286 head.insertBefore( ss, lastLink.nextSibling ); 11287 11288 if ( ss.styleSheet ){ 11289 ss.styleSheet.cssText = css; 11290 } 11291 else { 11292 ss.appendChild( doc.createTextNode( css ) ); 11293 } 11294 11295 //push to appendedEls to track for later removal 11296 appendedEls.push( ss ); 11297 } 11298 } 11299 }, 11300 //tweaked Ajax functions from Quirksmode 11301 ajax = function( url, callback ) { 11302 var req = xmlHttp(); 11303 if (!req){ 11304 return; 11305 } 11306 req.open( "GET", url, true ); 11307 req.onreadystatechange = function () { 11308 if ( req.readyState !== 4 || req.status !== 200 && req.status !== 304 ){ 11309 return; 11310 } 11311 callback( req.responseText ); 11312 }; 11313 if ( req.readyState === 4 ){ 11314 return; 11315 } 11316 req.send( null ); 11317 }, 11318 //define ajax obj 11319 xmlHttp = (function() { 11320 var xmlhttpmethod = false; 11321 try { 11322 xmlhttpmethod = new win.XMLHttpRequest(); 11323 } 11324 catch( e ){ 11325 xmlhttpmethod = new win.ActiveXObject( "Microsoft.XMLHTTP" ); 11326 } 11327 return function(){ 11328 return xmlhttpmethod; 11329 }; 11330 })(); 11331 11332 //translate CSS 11333 // ripCSS(); 11334 11335 //expose update for re-running respond later on 11336 respond.update = ripCSS; 11337 11338 //adjust on resize 11339 function callMedia(){ 11340 applyMedia( true ); 11341 } 11342 if( win.addEventListener ){ 11343 win.addEventListener( "resize", callMedia, false ); 11344 } 11345 else if( win.attachEvent ){ 11346 win.attachEvent( "onresize", callMedia ); 11347 } 11348})(this); 11349 11350// hide content until everything is loaded -> this requires jQuery 11351$(document).ready(function(){ 11352 if (!respond.mediaQueriesSupported) { 11353 // var body = document.getElementsByTagName("body")[0]; 11354 // body.style.cssText = "display: none !important"; 11355 } 11356}); 11357 11358var split_css_queue = []; 11359$(document).ready(function(){ 11360 11361 if (bowser.version != undefined) { 11362 var browser = ""; 11363 version = bowser.version.split(".")[0]; 11364 if (bowser.msie === true) { 11365 browser = "msie"; 11366 } 11367 11368 // if there is an IE 11369 if(browser == "msie" && (version == "8" || version == "9")) { 11370 11371 // find css file 11372 var paths = [ 11373 "bme2014.css" 11374 ]; 11375 var stylesheets = $("head").find("link"); 11376 11377 $(paths).each(function(){ 11378 style = this.toString(); 11379 11380 stylesheets.each(function(){ 11381 $styletag = $(this); 11382 href = $(this).attr("href").toString(); 11383 filename = href.match(/.*\/(.*)$/)[1]; 11384 cleared_filename = filename.split("?")[0]; 11385 filepath = href.replace(filename, ""); 11386 filename_wo_extension = cleared_filename.replace(".css", ""); 11387 11388 // replace stylesheets 11389 if (cleared_filename == style.toString()) { 11390 // check the file url 11391 if (filepath.indexOf("//") > -1) { 11392 toolbox = true; 11393 } else { 11394 toolbox = false;
11395 } 11396 fetch_stylesheets(cleared_filename, filename_wo_extension, filepath, toolbox, 0); 11397 } 11398 }); 11399 }); 11400 } 11401 } 11402}); 11403 11404 11405function fetch_stylesheets(filename, filename_wo_extension, filepath, toolbox, iterator) { 11406 origin = window.location.protocol + "//" + window.location.host; 11407 11408 if (toolbox) { 11409 if (iterator === 0) { 11410 path = filepath + "split_" + filename; 11411 } else { 11412 path = filepath + "split_" + filename_wo_extension + "-blessed" + iterator + ".css"; 11413 } 11414 } else { 11415 if (iterator === 0) { 11416 path = origin + filepath + "split_" + filename; 11417 } else { 11418 path = origin + filepath + "split_" + filename_wo_extension + "-blessed" + iterator + ".css"; 11419 } 11420 } 11421 11422 iterator++; 11423 11424 if (iterator <= 2) { 11425 split_css_queue.push(path); 11426 fetch_stylesheets(filename, filename_wo_extension, filepath, toolbox, iterator); 11427 } else { 11428 inject_css_to_head(); 11429 } 11430} 11431 11432function inject_css_to_head(){ 11433 split_css_queue.reverse(); 11434 11435 $(split_css_queue).each(function(){ 11436 path = this; 11437 11438 $("head link[rel='stylesheet']").last().after("<link rel='stylesheet' href='" + path + "' type='text/css' media='screen' data-proxy='true'>"); 11439 }); 11440 11441 window.respond_staus = "ready"; 11442 window.respond.update(); 11443} 11444 11445 11446function clear_params(url) { 11447 var oldURL = style.toString(); 11448 var index = 0; 11449 var newURL = oldURL; 11450 index = oldURL.indexOf('?'); 11451 if(index == -1){ 11452 index = oldURL.indexOf('#'); 11453 } 11454 if(index != -1){ 11455 newURL = oldURL.substring(0, index); 11456 } 11457 return newURL; 11458} 11459 11460/*! 11461 * Bowser - a browser detector 11462 * https://github.com/ded/bowser 11463 * MIT License | (c) Dustin Diaz 2014 11464 */ 11465 11466!function (name, definition) { 11467 if (typeof module != 'undefined' && module.exports) module.exports['browser'] = definition() 11468 else if (typeof define == 'function' && define.amd) define(definition) 11469 else this[name] = definition() 11470}('bowser', function () { 11471 /** 11472 * See useragents.js for examples of navigator.userAgent 11473 */ 11474 11475 var t = true 11476 11477 function detect(ua) { 11478 11479 function getFirstMatch(regex) { 11480 var match = ua.match(regex); 11481 return (match && match.length > 1 && match[1]) || ''; 11482 } 11483 11484 var iosdevice = getFirstMatch(/(ipod|iphone|ipad)/i).toLowerCase() 11485 , likeAndroid = /like android/i.test(ua) 11486 , android = !likeAndroid && /android/i.test(ua) 11487 , versionIdentifier = getFirstMatch(/version\/(\d+(\.\d+)?)/i) 11488 , tablet = /tablet/i.test(ua) 11489 , mobile = !tablet && /[^-]mobi/i.test(ua) 11490 , result 11491 11492 if (/opera|opr/i.test(ua)) { 11493 result = { 11494 name: 'Opera' 11495 , opera: t 11496 , version: versionIdentifier || getFirstMatch(/(?:opera|opr)[\s\/](\d+(\.\d+)?)/i) 11497 } 11498 } 11499 else if (/windows phone/i.test(ua)) { 11500 result = { 11501 name: 'Windows Phone' 11502 , windowsphone: t 11503 , msie: t 11504 , version: getFirstMatch(/iemobile\/(\d+(\.\d+)?)/i) 11505 } 11506 } 11507 else if (/msie|trident/i.test(ua)) { 11508 result = { 11509 name: 'Internet Explorer' 11510 , msie: t 11511 , version: getFirstMatch(/(?:msie |rv:)(\d+(\.\d+)?)/i) 11512 } 11513 } 11514 else if (/chrome|crios|crmo/i.test(ua)) { 11515 result = { 11516 name: 'Chrome' 11517 , chrome: t 11518 , version: getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.\d+)?)/i) 11519 } 11520 } 11521 else if (iosdevice) { 11522 result = { 11523 name : iosdevice == 'iphone' ? 'iPhone' : iosdevice == 'ipad' ? 'iPad' : 'iPod' 11524 } 11525 // WTF: version is not part of user agent in web apps 11526 if (versionIdentifier) { 11527 result.version = versionIdentifier 11528 } 11529 } 11530 else if (/sailfish/i.test(ua)) { 11531 result = { 11532 name: 'Sailfish' 11533 , sailfish: t 11534 , version: getFirstMatch(/sailfish\s?browser\/(\d+(\.\d+)?)/i) 11535 } 11536 } 11537 else if (/seamonkey\//i.test(ua)) { 11538 result = { 11539 name: 'SeaMonkey' 11540 , seamonkey: t 11541 , version: getFirstMatch(/seamonkey\/(\d+(\.\d+)?)/i) 11542 } 11543 } 11544 else if (/firefox|iceweasel/i.test(ua)) { 11545 result = { 11546 name: 'Firefox' 11547 , firefox: t 11548 , version: getFirstMatch(/(?:firefox|iceweasel)[ \/](\d+(\.\d+)?)/i) 11549 } 11550 if (/\((mobile|tablet);[^\)]*rv:[\d\.]+\)/i.test(ua)) { 11551 result.firefoxos = t 11552 } 11553 } 11554 else if (/silk/i.test(ua)) { 11555 result = { 11556 name: 'Amazon Silk' 11557 , silk: t 11558 , version : getFirstMatch(/silk\/(\d+(\.\d+)?)/i) 11559 } 11560 } 11561 else if (android) { 11562 result = { 11563 name: 'Android' 11564 , version: versionIdentifier 11565 } 11566 } 11567 else if (/phantom/i.test(ua)) { 11568 result = { 11569 name: 'PhantomJS' 11570 , phantom: t 11571 , version: getFirstMatch(/phantomjs\/(\d+(\.\d+)?)/i) 11572 } 11573 } 11574 else if (/blackberry|\bbb\d+/i.test(ua) || /rim\stablet/i.test(ua)) { 11575 result = { 11576 name: 'BlackBerry' 11577 , blackberry: t 11578 , version: versionIdentifier || getFirstMatch(/blackberry[\d]+\/(\d+(\.\d+)?)/i) 11579 } 11580 } 11581 else if (/(web|hpw)os/i.test(ua)) { 11582 result = { 11583 name: 'WebOS' 11584 , webos: t 11585 , version: versionIdentifier || getFirstMatch(/w(?:eb)?osbrowser\/(\d+(\.\d+)?)/i) 11586 }; 11587 /touchpad\//i.test(ua) && (result.touchpad = t) 11588 } 11589 else if (/bada/i.test(ua)) { 11590 result = { 11591 name: 'Bada' 11592 , bada: t 11593 , version: getFirstMatch(/dolfin\/(\d+(\.\d+)?)/i) 11594 }; 11595 } 11596 else if (/tizen/i.test(ua)) { 11597 result = { 11598 name: 'Tizen' 11599 , tizen: t 11600 , version: getFirstMatch(/(?:tizen\s?)?browser\/(\d+(\.\d+)?)/i) || versionIdentifier 11601 }; 11602 } 11603 else if (/safari/i.test(ua)) { 11604 result = { 11605 name: 'Safari' 11606 , safari: t 11607 , version: versionIdentifier 11608 } 11609 } 11610 else result = {} 11611 11612 // set webkit or gecko flag for browsers based on these engines 11613 if (/(apple)?webkit/i.test(ua)) { 11614 result.name = result.name || "Webkit" 11615 result.webkit = t 11616 if (!result.version && versionIdentifier) { 11617 result.version = versionIdentifier 11618 } 11619 } else if (!result.opera && /gecko\//i.test(ua)) { 11620 result.name = result.name || "Gecko" 11621 result.gecko = t 11622 result.version = result.version || getFirstMatch(/gecko\/(\d+(\.\d+)?)/i) 11623 } 11624 11625 // set OS flags for platforms that have multiple browsers 11626 if (android || result.silk) { 11627 result.android = t 11628 } else if (iosdevice) { 11629 result[iosdevice] = t 11630 result.ios = t 11631 } 11632 11633 // OS version extraction 11634 var osVersion = ''; 11635 if (iosdevice) { 11636 osVersion = getFirstMatch(/os (\d+([_\s]\d+)*) like mac os x/i); 11637 osVersion = osVersion.replace(/[_\s]/g, '.'); 11638 } else if (android) { 11639 osVersion = getFirstMatch(/android[ \/-](\d+(\.\d+)*)/i); 11640 } else if (result.windowsphone) { 11641 osVersion = getFirstMatch(/windows phone (?:os)?\s?(\d+(\.\d+)*)/i); 11642 } else if (result.webos) { 11643 osVersion = getFirstMatch(/(?:web|hpw)os\/(\d+(\.\d+)*)/i); 11644 } else if (result.blackberry) { 11645 osVersion = getFirstMatch(/rim\stablet\sos\s(\d+(\.\d+)*)/i); 11646 } else if (result.bada) { 11647 osVersion = getFirstMatch(/bada\/(\d+(\.\d+)*)/i); 11648 } else if (result.tizen) { 11649 osVersion = getFirstMatch(/tizen[\/\s](\d+(\.\d+)*)/i); 11650 } 11651 if (osVersion) { 11652 result.osversion = osVersion; 11653 } 11654 11655 // device type extraction 11656 var osMajorVersion = osVersion.split('.')[0]; 11657 if (tablet || iosdevice == 'ipad' || (android && (osMajorVersion == 3 || (osMajorVersion == 4 && !mobile))) || result.silk) { 11658 result.tablet = t 11659 } else if (mobile || iosdevice == 'iphone' || iosdevice == 'ipod' || android || result.blackberry || result.webos || result.bada) { 11660 result.mobile = t 11661 } 11662 11663 // Graded Browser Support
11664 // http://developer.yahoo.com/yui/articles/gbs 11665 if ((result.msie && result.version >= 10) || 11666 (result.chrome && result.version >= 20) || 11667 (result.firefox && result.version >= 20.0) || 11668 (result.safari && result.version >= 6) || 11669 (result.opera && result.version >= 10.0) || 11670 (result.ios && result.osversion && result.osversion.split(".")[0] >= 6) || 11671 (result.blackberry && result.version >= 10.1) 11672 ) { 11673 result.a = t; 11674 } 11675 else if ((result.msie && result.version < 10) || 11676 (result.chrome && result.version < 20) || 11677 (result.firefox && result.version < 20.0) || 11678 (result.safari && result.version < 6) || 11679 (result.opera && result.version < 10.0) || 11680 (result.ios && result.osversion && result.osversion.split(".")[0] < 6) 11681 ) { 11682 result.c = t 11683 } else result.x = t 11684 11685 return result 11686 } 11687 11688 var bowser = detect(typeof navigator !== 'undefined' ? navigator.userAgent : '') 11689 11690 11691 /* 11692 * Set our detect method to the main bowser object so we can 11693 * reuse it to test other user agents. 11694 * This is needed to implement future tests. 11695 */ 11696 bowser._detect = detect; 11697 11698 return bowser 11699}); 11700 11701$(document).ready(function(){ 11702 11703 window.bodyclasses = "undefinedBrowser"; 11704 11705 // check if bowser is included 11706 if (typeof bowser == 'undefined') { 11707 console.log("you need to include bowser https://github.com/ded/bowser"); 11708 } else { 11709 11710 if (bowser.version != undefined) { 11711 if (bowser.safari === true) { 11712 window.bodyclasses = "safari"; 11713 } else if (bowser.msie === true) { 11714 window.bodyclasses = "msie"; 11715 } else if (bowser.firefox === true) { 11716 window.bodyclasses = "firefox"; 11717 } else if (bowser.chrome === true) { 11718 window.bodyclasses = "chrome"; 11719 } else if (bowser.opera === true) { 11720 window.bodyclasses = "opera"; 11721 } else if (bowser.iphone) { 11722 window.bodyclasses = "iphone"; 11723 } else if (bowser.android) { 11724 window.bodyclasses = "android"; 11725 } else if (bowser.ipad) { 11726 window.bodyclasses = "ipad"; 11727 } 11728 window.bodyclasses += " " + window.bodyclasses + bowser.version.split(".")[0]; 11729 11730 // mobile 11731 if(bowser.mobile != undefined && bowser.mobile === true) { 11732 window.bodyclasses = window.bodyclasses + " mobile"; 11733 } 11734 11735 // tablet 11736 if(bowser.tablet != undefined && bowser.tablet === true) { 11737 window.bodyclasses = window.bodyclasses + " tablet"; 11738 } 11739 11740 // desktop 11741 if(bowser.tablet == undefined && bowser.mobile == undefined) { 11742 window.bodyclasses = window.bodyclasses + " desktop"; 11743 } 11744 } 11745 11746 $("body").addClass(window.bodyclasses); 11747 } 11748}); 11749 11750(function($) { 11751 11752 $.fn.sharpness = function( options ) { 11753 11754 // Establish our default settings 11755 var settings = $.extend({ 11756 browsers: null, 11757 attribute: 'data-hires', 11758 start: null, 11759 complete: null 11760 }, options); 11761 11762 return this.each( function() { 11763 // start everthing 11764 if ( $.isFunction( settings.start ) ) { 11765 settings.start.call( this ); 11766 } 11767 11768 if (settings.browsers === null) { 11769 prepare_swap($(this), settings); 11770 } else { 11771 // check if we got everything 11772 if (typeof bowser === 'undefined') { 11773 console.log("you need to include bowser https://github.com/ded/bowser"); 11774 } else if(typeof window.bodyclasses === 'undefined') { 11775 console.log("you need to include demography https://github.com/andrezimpel/demography"); 11776 } else { 11777 match = false; 11778 classversion = window.bodyclasses.split(" "); 11779 11780 $(classversion).each(function(index){ 11781 brws_class = classversion[index]; 11782 result = jQuery.inArray( brws_class, settings.browsers ); 11783 if (result !== -1) { 11784 match = true; 11785 } 11786 }); 11787 11788 if (!match) { 11789 prepare_swap($(this), settings); 11790 } 11791 } 11792 } 11793 11794 // set the callback 11795 if ( $.isFunction( settings.complete ) ) { 11796 settings.complete.call( this ); 11797 } 11798 }); 11799 } 11800}(jQuery)); 11801 11802// function 11803function prepare_swap(elem, settings) {
11804 $this = elem; 11805 var hires_src = $this.attr(settings.attribute); 11806 var src = $this.attr("src"); 11807 var img = $this; 11808 11809 var img_call = $.ajax(hires_src) 11810 .success(function() { 11811 11812 // swap image if the hires alternative is available 11813 swap_hires_image(img, hires_src, src); 11814 }); 11815} 11816 11817// replace images 11818function swap_hires_image(element, hires_src, src) { 11819 $(element).attr("src", null); 11820 $(element).attr("src", hires_src); 11821 $(element).attr("data-original-src", src); 11822} 11823 11824/* ======================================================================== 11825 * Bootstrap: transition.js v3.0.2 11826 * http://getbootstrap.com/javascript/#transitions 11827 * ======================================================================== 11828 * Copyright 2013 Twitter, Inc. 11829 * 11830 * Licensed under the Apache License, Version 2.0 (the "License"); 11831 * you may not use this file except in compliance with the License. 11832 * You may obtain a copy of the License at 11833 * 11834 * http://www.apache.org/licenses/LICENSE-2.0 11835 * 11836 * Unless required by applicable law or agreed to in writing, software 11837 * distributed under the License is distributed on an "AS IS" BASIS, 11838 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11839 * See the License for the specific language governing permissions and 11840 * limitations under the License. 11841 * ======================================================================== */ 11842 11843 11844+function ($) { "use strict"; 11845 11846 // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) 11847 // ============================================================ 11848 11849 function transitionEnd() { 11850 var el = document.createElement('bootstrap') 11851 11852 var transEndEventNames = { 11853 'WebkitTransition' : 'webkitTransitionEnd' 11854 , 'MozTransition' : 'transitionend' 11855 , 'OTransition' : 'oTransitionEnd otransitionend' 11856 , 'transition' : 'transitionend' 11857 } 11858 11859 for (var name in transEndEventNames) { 11860 if (el.style[name] !== undefined) { 11861 return { end: transEndEventNames[name] } 11862 } 11863 } 11864 } 11865 11866 // http://blog.alexmaccaw.com/css-transitions 11867 $.fn.emulateTransitionEnd = function (duration) { 11868 var called = false, $el = this 11869 $(this).one($.support.transition.end, function () { called = true }) 11870 var callback = function () { if (!called) $($el).trigger($.support.transition.end) } 11871 setTimeout(callback, duration) 11872 return this 11873 } 11874 11875 $(function () { 11876 $.support.transition = transitionEnd() 11877 }) 11878 11879}(jQuery); 11880 11881/* ======================================================================== 11882 * Bootstrap: alert.js v3.0.2 11883 * http://getbootstrap.com/javascript/#alerts 11884 * ======================================================================== 11885 * Copyright 2013 Twitter, Inc. 11886 * 11887 * Licensed under the Apache License, Version 2.0 (the "License"); 11888 * you may not use this file except in compliance with the License. 11889 * You may obtain a copy of the License at 11890 * 11891 * http://www.apache.org/licenses/LICENSE-2.0 11892 * 11893 * Unless required by applicable law or agreed to in writing, software 11894 * distributed under the License is distributed on an "AS IS" BASIS, 11895 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11896 * See the License for the specific language governing permissions and 11897 * limitations under the License. 11898 * ======================================================================== */ 11899 11900 11901+function ($) { "use strict"; 11902 11903 // ALERT CLASS DEFINITION 11904 // ====================== 11905 11906 var dismiss = '[data-dismiss="alert"]' 11907 var Alert = function (el) { 11908 $(el).on('click', dismiss, this.close) 11909 } 11910 11911 Alert.prototype.close = function (e) { 11912 var $this = $(this) 11913 var selector = $this.attr('data-target') 11914 11915 if (!selector) { 11916 selector = $this.attr('href') 11917 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 11918 } 11919 11920 var $parent = $(selector) 11921 11922 if (e) e.preventDefault() 11923 11924 if (!$parent.length) { 11925 $parent = $this.hasClass('alert') ? $this : $this.parent() 11926 } 11927 11928 $parent.trigger(e = $.Event('close.bs.alert')) 11929 11930 if (e.isDefaultPrevented()) return 11931 11932 $parent.removeClass('in') 11933 11934 function removeElement() { 11935 $parent.trigger('closed.bs.alert').remove() 11936 } 11937 11938 $.support.transition && $parent.hasClass('fade') ? 11939 $parent 11940 .one($.support.transition.end, removeElement) 11941 .emulateTransitionEnd(150) : 11942 removeElement() 11943 } 11944 11945 11946 // ALERT PLUGIN DEFINITION 11947 // ======================= 11948 11949 var old = $.fn.alert 11950 11951 $.fn.alert = function (option) { 11952 return this.each(function () { 11953 var $this = $(this) 11954 var data = $this.data('bs.alert') 11955
11956 if (!data) $this.data('bs.alert', (data = new Alert(this))) 11957 if (typeof option == 'string') data[option].call($this) 11958 }) 11959 } 11960 11961 $.fn.alert.Constructor = Alert 11962 11963 11964 // ALERT NO CONFLICT 11965 // ================= 11966 11967 $.fn.alert.noConflict = function () { 11968 $.fn.alert = old 11969 return this 11970 } 11971 11972 11973 // ALERT DATA-API 11974 // ============== 11975 11976 $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) 11977 11978}(jQuery); 11979 11980/* ======================================================================== 11981 * Bootstrap: button.js v3.0.2 11982 * http://getbootstrap.com/javascript/#buttons 11983 * ======================================================================== 11984 * Copyright 2013 Twitter, Inc. 11985 * 11986 * Licensed under the Apache License, Version 2.0 (the "License"); 11987 * you may not use this file except in compliance with the License. 11988 * You may obtain a copy of the License at 11989 * 11990 * http://www.apache.org/licenses/LICENSE-2.0 11991 * 11992 * Unless required by applicable law or agreed to in writing, software 11993 * distributed under the License is distributed on an "AS IS" BASIS, 11994 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11995 * See the License for the specific language governing permissions and 11996 * limitations under the License. 11997 * ======================================================================== */ 11998 11999 12000+function ($) { "use strict"; 12001 12002 // BUTTON PUBLIC CLASS DEFINITION 12003 // ============================== 12004 12005 var Button = function (element, options) { 12006 this.$element = $(element) 12007 this.options = $.extend({}, Button.DEFAULTS, options) 12008 } 12009 12010 Button.DEFAULTS = { 12011 loadingText: 'loading...' 12012 } 12013 12014 Button.prototype.setState = function (state) { 12015 var d = 'disabled' 12016 var $el = this.$element 12017 var val = $el.is('input') ? 'val' : 'html' 12018 var data = $el.data() 12019 12020 state = state + 'Text' 12021 12022 if (!data.resetText) $el.data('resetText', $el[val]()) 12023 12024 $el[val](data[state] || this.options[state]) 12025 12026 // push to event loop to allow forms to submit 12027 setTimeout(function () { 12028 state == 'loadingText' ? 12029 $el.addClass(d).attr(d, d) : 12030 $el.removeClass(d).removeAttr(d); 12031 }, 0) 12032 } 12033 12034 Button.prototype.toggle = function () { 12035 var $parent = this.$element.closest('[data-toggle="buttons"]') 12036 12037 if ($parent.length) { 12038 var $input = this.$element.find('input') 12039 .prop('checked', !this.$element.hasClass('active')) 12040 .trigger('change') 12041 if ($input.prop('type') === 'radio') $parent.find('.active').removeClass('active') 12042 } 12043 12044 this.$element.toggleClass('active') 12045 } 12046 12047 12048 // BUTTON PLUGIN DEFINITION 12049 // ======================== 12050 12051 var old = $.fn.button 12052 12053 $.fn.button = function (option) { 12054 return this.each(function () { 12055 var $this = $(this) 12056 var data = $this.data('bs.button') 12057 var options = typeof option == 'object' && option 12058 12059 if (!data) $this.data('bs.button', (data = new Button(this, options))) 12060 12061 if (option == 'toggle') data.toggle() 12062 else if (option) data.setState(option) 12063 }) 12064 } 12065 12066 $.fn.button.Constructor = Button 12067 12068 12069 // BUTTON NO CONFLICT 12070 // ================== 12071 12072 $.fn.button.noConflict = function () { 12073 $.fn.button = old 12074 return this 12075 } 12076 12077 12078 // BUTTON DATA-API 12079 // =============== 12080 12081 $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) { 12082 var $btn = $(e.target) 12083 if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') 12084 $btn.button('toggle') 12085 e.preventDefault() 12086 }) 12087 12088}(jQuery); 12089 12090/* ======================================================================== 12091 * Bootstrap: carousel.js v3.0.2 12092 * http://getbootstrap.com/javascript/#carousel 12093 * ======================================================================== 12094 * Copyright 2013 Twitter, Inc. 12095 * 12096 * Licensed under the Apache License, Version 2.0 (the "License"); 12097 * you may not use this file except in compliance with the License. 12098 * You may obtain a copy of the License at 12099 * 12100 * http://www.apache.org/licenses/LICENSE-2.0 12101 * 12102 * Unless required by applicable law or agreed to in writing, software 12103 * distributed under the License is distributed on an "AS IS" BASIS, 12104 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12105 * See the License for the specific language governing permissions and 12106 * limitations under the License. 12107 * ======================================================================== */ 12108 12109 12110+function ($) { "use strict"; 12111 12112 // CAROUSEL CLASS DEFINITION 12113 // ========================= 12114 12115 var Carousel = function (element, options) { 12116 this.$element = $(element) 12117 this.$indicators = this.$element.find('.carousel-indicators') 12118 this.options = options 12119 this.paused = 12120 this.sliding = 12121 this.interval = 12122 this.$active = 12123 this.$items = null 12124 12125 this.options.pause == 'hover' && this.$element 12126 .on('mouseenter', $.proxy(this.pause, this)) 12127 .on('mouseleave', $.proxy(this.cycle, this)) 12128 } 12129 12130 Carousel.DEFAULTS = { 12131 interval: 5000 12132 , pause: 'hover' 12133 , wrap: true 12134 } 12135 12136 Carousel.prototype.cycle = function (e) { 12137 e || (this.paused = false) 12138 12139 this.interval && clearInterval(this.interval) 12140 12141 this.options.interval 12142 && !this.paused 12143 && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) 12144 12145 return this 12146 } 12147 12148 Carousel.prototype.getActiveIndex = function () { 12149 this.$active = this.$element.find('.item.active') 12150 this.$items = this.$active.parent().children() 12151 12152 return this.$items.index(this.$active) 12153 } 12154 12155 Carousel.prototype.to = function (pos) { 12156 var that = this 12157 var activeIndex = this.getActiveIndex() 12158 12159 if (pos > (this.$items.length - 1) || pos < 0) return 12160 12161 if (this.sliding) return this.$element.one('slid', function () { that.to(pos) }) 12162 if (activeIndex == pos) return this.pause().cycle() 12163 12164 return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) 12165 } 12166 12167 Carousel.prototype.pause = function (e) { 12168 e || (this.paused = true) 12169 12170 if (this.$element.find('.next, .prev').length && $.support.transition.end) { 12171 this.$element.trigger($.support.transition.end) 12172 this.cycle(true) 12173 } 12174 12175 this.interval = clearInterval(this.interval) 12176 12177 return this 12178 } 12179 12180 Carousel.prototype.next = function () { 12181 if (this.sliding) return 12182 return this.slide('next') 12183 } 12184 12185 Carousel.prototype.prev = function () { 12186 if (this.sliding) return 12187 return this.slide('prev') 12188 } 12189 12190 Carousel.prototype.slide = function (type, next) { 12191 var $active = this.$element.find('.item.active') 12192 var $next = next || $active[type]() 12193 var isCycling = this.interval 12194 var direction = type == 'next' ? 'left' : 'right' 12195 var fallback = type == 'next' ? 'first' : 'last' 12196 var that = this 12197 12198 if (!$next.length) { 12199 if (!this.options.wrap) return 12200 $next = this.$element.find('.item')[fallback]() 12201 } 12202 12203 this.sliding = true 12204 12205 isCycling && this.pause() 12206 12207 var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction }) 12208 12209 if ($next.hasClass('active')) return 12210 12211 if (this.$indicators.length) { 12212 this.$indicators.find('.active').removeClass('active') 12213 this.$element.one('slid', function () { 12214 var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) 12215 $nextIndicator && $nextIndicator.addClass('active') 12216 }) 12217 } 12218
12219 if ($.support.transition && this.$element.hasClass('slide')) { 12220 this.$element.trigger(e) 12221 if (e.isDefaultPrevented()) return 12222 $next.addClass(type) 12223 $next[0].offsetWidth // force reflow 12224 $active.addClass(direction) 12225 $next.addClass(direction) 12226 $active 12227 .one($.support.transition.end, function () { 12228 $next.removeClass([type, direction].join(' ')).addClass('active') 12229 $active.removeClass(['active', direction].join(' ')) 12230 that.sliding = false 12231 setTimeout(function () { that.$element.trigger('slid') }, 0) 12232 }) 12233 .emulateTransitionEnd(600) 12234 } else { 12235 this.$element.trigger(e) 12236 if (e.isDefaultPrevented()) return 12237 $active.removeClass('active') 12238 $next.addClass('active') 12239 this.sliding = false 12240 this.$element.trigger('slid') 12241 } 12242 12243 isCycling && this.cycle() 12244 12245 return this 12246 } 12247 12248 12249 // CAROUSEL PLUGIN DEFINITION 12250 // ========================== 12251 12252 var old = $.fn.carousel 12253 12254 $.fn.carousel = function (option) { 12255 return this.each(function () { 12256 var $this = $(this) 12257 var data = $this.data('bs.carousel') 12258 var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) 12259 var action = typeof option == 'string' ? option : options.slide 12260 12261 if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) 12262 if (typeof option == 'number') data.to(option) 12263 else if (action) data[action]() 12264 else if (options.interval) data.pause().cycle() 12265 }) 12266 } 12267 12268 $.fn.carousel.Constructor = Carousel 12269 12270 12271 // CAROUSEL NO CONFLICT 12272 // ==================== 12273 12274 $.fn.carousel.noConflict = function () { 12275 $.fn.carousel = old 12276 return this 12277 } 12278 12279 12280 // CAROUSEL DATA-API 12281 // ================= 12282 12283 $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { 12284 var $this = $(this), href 12285 var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 12286 var options = $.extend({}, $target.data(), $this.data()) 12287 var slideIndex = $this.attr('data-slide-to') 12288 if (slideIndex) options.interval = false 12289 12290 $target.carousel(options) 12291 12292 if (slideIndex = $this.attr('data-slide-to')) { 12293 $target.data('bs.carousel').to(slideIndex) 12294 } 12295 12296 e.preventDefault() 12297 }) 12298 12299 $(window).on('load', function () { 12300 $('[data-ride="carousel"]').each(function () { 12301 var $carousel = $(this) 12302 $carousel.carousel($carousel.data()) 12303 }) 12304 }) 12305 12306}(jQuery); 12307 12308/* ======================================================================== 12309 * Bootstrap: collapse.js v3.0.2 12310 * http://getbootstrap.com/javascript/#collapse 12311 * ======================================================================== 12312 * Copyright 2013 Twitter, Inc. 12313 * 12314 * Licensed under the Apache License, Version 2.0 (the "License"); 12315 * you may not use this file except in compliance with the License. 12316 * You may obtain a copy of the License at 12317 * 12318 * http://www.apache.org/licenses/LICENSE-2.0 12319 * 12320 * Unless required by applicable law or agreed to in writing, software 12321 * distributed under the License is distributed on an "AS IS" BASIS, 12322 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12323 * See the License for the specific language governing permissions and 12324 * limitations under the License. 12325 * ======================================================================== */ 12326 12327 12328+function ($) { "use strict"; 12329 12330 // COLLAPSE PUBLIC CLASS DEFINITION 12331 // ================================ 12332 12333 var Collapse = function (element, options) { 12334 this.$element = $(element) 12335 this.options = $.extend({}, Collapse.DEFAULTS, options) 12336 this.transitioning = null 12337 12338 if (this.options.parent) this.$parent = $(this.options.parent) 12339 if (this.options.toggle) this.toggle() 12340 } 12341 12342 Collapse.DEFAULTS = { 12343 toggle: true 12344 } 12345 12346 Collapse.prototype.dimension = function () { 12347 var hasWidth = this.$element.hasClass('width') 12348 return hasWidth ? 'width' : 'height' 12349 } 12350 12351 Collapse.prototype.show = function () { 12352 if (this.transitioning || this.$element.hasClass('in')) return 12353 12354 var startEvent = $.Event('show.bs.collapse') 12355 this.$element.trigger(startEvent) 12356 if (startEvent.isDefaultPrevented()) return 12357 12358 var actives = this.$parent && this.$parent.find('> .panel > .in') 12359 12360 if (actives && actives.length) { 12361 var hasData = actives.data('bs.collapse') 12362 if (hasData && hasData.transitioning) return 12363 actives.collapse('hide') 12364 hasData || actives.data('bs.collapse', null) 12365 } 12366 12367 var dimension = this.dimension() 12368 12369 this.$element 12370 .removeClass('collapse') 12371 .addClass('collapsing') 12372 [dimension](0) 12373 12374 this.transitioning = 1 12375 12376 var complete = function () { 12377 this.$element 12378 .removeClass('collapsing') 12379 .addClass('in') 12380 [dimension]('auto') 12381 this.transitioning = 0 12382 this.$element.trigger('shown.bs.collapse') 12383 } 12384 12385 if (!$.support.transition) return complete.call(this) 12386 12387 var scrollSize = $.camelCase(['scroll', dimension].join('-')) 12388 12389 this.$element 12390 .one($.support.transition.end, $.proxy(complete, this)) 12391 .emulateTransitionEnd(350) 12392 [dimension](this.$element[0][scrollSize]) 12393 } 12394 12395 Collapse.prototype.hide = function () { 12396 if (this.transitioning || !this.$element.hasClass('in')) return 12397 12398 var startEvent = $.Event('hide.bs.collapse') 12399 this.$element.trigger(startEvent) 12400 if (startEvent.isDefaultPrevented()) return 12401 12402 var dimension = this.dimension() 12403 12404 this.$element 12405 [dimension](this.$element[dimension]()) 12406 [0].offsetHeight 12407 12408 this.$element 12409 .addClass('collapsing') 12410 .removeClass('collapse') 12411 .removeClass('in') 12412 12413 this.transitioning = 1 12414 12415 var complete = function () { 12416 this.transitioning = 0 12417 this.$element 12418 .trigger('hidden.bs.collapse') 12419 .removeClass('collapsing') 12420 .addClass('collapse') 12421 } 12422 12423 if (!$.support.transition) return complete.call(this) 12424 12425 this.$element 12426 [dimension](0) 12427 .one($.support.transition.end, $.proxy(complete, this)) 12428 .emulateTransitionEnd(350) 12429 } 12430 12431 Collapse.prototype.toggle = function () { 12432 this[this.$element.hasClass('in') ? 'hide' : 'show']() 12433 } 12434 12435 12436 // COLLAPSE PLUGIN DEFINITION 12437 // ========================== 12438 12439 var old = $.fn.collapse 12440 12441 $.fn.collapse = function (option) { 12442 return this.each(function () { 12443 var $this = $(this) 12444 var data = $this.data('bs.collapse') 12445 var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) 12446 12447 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) 12448 if (typeof option == 'string') data[option]() 12449 }) 12450 } 12451 12452 $.fn.collapse.Constructor = Collapse 12453 12454 12455 // COLLAPSE NO CONFLICT 12456 // ==================== 12457 12458 $.fn.collapse.noConflict = function () { 12459 $.fn.collapse = old 12460 return this 12461 } 12462 12463 12464 // COLLAPSE DATA-API 12465 // ================= 12466 12467 $(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) { 12468 var $this = $(this), href 12469 var target = $this.attr('data-target') 12470 || e.preventDefault() 12471 || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 12472 var $target = $(target) 12473 var data = $target.data('bs.collapse') 12474 var option = data ? 'toggle' : $this.data() 12475 var parent = $this.attr('data-parent') 12476 var $parent = parent && $(parent) 12477 12478 if (!data || !data.transitioning) { 12479 if ($parent) $parent.find('[data-toggle=collapse][data-parent="' + parent + '"]').not($this).addClass('collapsed') 12480 $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') 12481 } 12482 12483 $target.collapse(option) 12484 }) 12485 12486}(jQuery); 12487 12488/* ======================================================================== 12489 * Bootstrap: dropdown.js v3.0.2 12490 * http://getbootstrap.com/javascript/#dropdowns 12491 * ======================================================================== 12492 * Copyright 2013 Twitter, Inc. 12493 * 12494 * Licensed under the Apache License, Version 2.0 (the "License");
12495 * you may not use this file except in compliance with the License. 12496 * You may obtain a copy of the License at 12497 * 12498 * http://www.apache.org/licenses/LICENSE-2.0 12499 * 12500 * Unless required by applicable law or agreed to in writing, software 12501 * distributed under the License is distributed on an "AS IS" BASIS, 12502 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12503 * See the License for the specific language governing permissions and 12504 * limitations under the License. 12505 * ======================================================================== */ 12506 12507 12508+function ($) { "use strict"; 12509 12510 // DROPDOWN CLASS DEFINITION 12511 // ========================= 12512 12513 var backdrop = '.dropdown-backdrop' 12514 var toggle = '[data-toggle=dropdown]' 12515 var Dropdown = function (element) { 12516 var $el = $(element).on('click.bs.dropdown', this.toggle) 12517 } 12518 12519 Dropdown.prototype.toggle = function (e) { 12520 var $this = $(this) 12521 12522 if ($this.is('.disabled, :disabled')) return 12523 12524 var $parent = getParent($this) 12525 var isActive = $parent.hasClass('open') 12526 12527 clearMenus() 12528 12529 if (!isActive) { 12530 if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { 12531 // if mobile we we use a backdrop because click events don't delegate 12532 $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus) 12533 } 12534 12535 $parent.trigger(e = $.Event('show.bs.dropdown')) 12536 12537 if (e.isDefaultPrevented()) return 12538 12539 $parent 12540 .toggleClass('open') 12541 .trigger('shown.bs.dropdown') 12542 12543 $this.focus() 12544 } 12545 12546 return false 12547 } 12548 12549 Dropdown.prototype.keydown = function (e) { 12550 if (!/(38|40|27)/.test(e.keyCode)) return 12551 12552 var $this = $(this) 12553 12554 e.preventDefault() 12555 e.stopPropagation() 12556 12557 if ($this.is('.disabled, :disabled')) return 12558 12559 var $parent = getParent($this) 12560 var isActive = $parent.hasClass('open') 12561 12562 if (!isActive || (isActive && e.keyCode == 27)) { 12563 if (e.which == 27) $parent.find(toggle).focus() 12564 return $this.click() 12565 } 12566 12567 var $items = $('[role=menu] li:not(.divider):visible a', $parent) 12568 12569 if (!$items.length) return 12570 12571 var index = $items.index($items.filter(':focus')) 12572 12573 if (e.keyCode == 38 && index > 0) index-- // up 12574 if (e.keyCode == 40 && index < $items.length - 1) index++ // down 12575 if (!~index) index=0 12576 12577 $items.eq(index).focus() 12578 } 12579 12580 function clearMenus() { 12581 $(backdrop).remove() 12582 $(toggle).each(function (e) { 12583 var $parent = getParent($(this)) 12584 if (!$parent.hasClass('open')) return 12585 $parent.trigger(e = $.Event('hide.bs.dropdown')) 12586 if (e.isDefaultPrevented()) return 12587 $parent.removeClass('open').trigger('hidden.bs.dropdown') 12588 }) 12589 } 12590 12591 function getParent($this) { 12592 var selector = $this.attr('data-target') 12593 12594 if (!selector) { 12595 selector = $this.attr('href') 12596 selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 12597 } 12598 12599 var $parent = selector && $(selector) 12600 12601 return $parent && $parent.length ? $parent : $this.parent() 12602 } 12603 12604 12605 // DROPDOWN PLUGIN DEFINITION 12606 // ========================== 12607 12608 var old = $.fn.dropdown 12609 12610 $.fn.dropdown = function (option) { 12611 return this.each(function () { 12612 var $this = $(this) 12613 var data = $this.data('dropdown') 12614 12615 if (!data) $this.data('dropdown', (data = new Dropdown(this))) 12616 if (typeof option == 'string') data[option].call($this) 12617 }) 12618 } 12619 12620 $.fn.dropdown.Constructor = Dropdown 12621 12622 12623 // DROPDOWN NO CONFLICT 12624 // ==================== 12625 12626 $.fn.dropdown.noConflict = function () { 12627 $.fn.dropdown = old 12628 return this 12629 } 12630 12631 12632 // APPLY TO STANDARD DROPDOWN ELEMENTS 12633 // =================================== 12634 12635 $(document) 12636 .on('click.bs.dropdown.data-api', clearMenus) 12637 .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) 12638 .on('click.bs.dropdown.data-api' , toggle, Dropdown.prototype.toggle) 12639 .on('keydown.bs.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown) 12640 12641}(jQuery); 12642 12643/* ======================================================================== 12644 * Bootstrap: modal.js v3.0.2 12645 * http://getbootstrap.com/javascript/#modals 12646 * ======================================================================== 12647 * Copyright 2013 Twitter, Inc. 12648 * 12649 * Licensed under the Apache License, Version 2.0 (the "License");
12650 * you may not use this file except in compliance with the License. 12651 * You may obtain a copy of the License at 12652 * 12653 * http://www.apache.org/licenses/LICENSE-2.0 12654 * 12655 * Unless required by applicable law or agreed to in writing, software 12656 * distributed under the License is distributed on an "AS IS" BASIS, 12657 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12658 * See the License for the specific language governing permissions and 12659 * limitations under the License. 12660 * ======================================================================== */ 12661 12662 12663+function ($) { "use strict"; 12664 12665 // MODAL CLASS DEFINITION 12666 // ====================== 12667 12668 var Modal = function (element, options) { 12669 this.options = options 12670 this.$element = $(element) 12671 this.$backdrop = 12672 this.isShown = null 12673 12674 if (this.options.remote) this.$element.load(this.options.remote) 12675 } 12676 12677 Modal.DEFAULTS = { 12678 backdrop: true 12679 , keyboard: true 12680 , show: true 12681 } 12682 12683 Modal.prototype.toggle = function (_relatedTarget) { 12684 return this[!this.isShown ? 'show' : 'hide'](_relatedTarget) 12685 } 12686 12687 Modal.prototype.show = function (_relatedTarget) { 12688 var that = this 12689 var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget }) 12690 12691 this.$element.trigger(e) 12692 12693 if (this.isShown || e.isDefaultPrevented()) return 12694 12695 this.isShown = true 12696 12697 this.escape() 12698 12699 this.$element.on('click.dismiss.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) 12700 12701 this.backdrop(function () { 12702 var transition = $.support.transition && that.$element.hasClass('fade') 12703 12704 if (!that.$element.parent().length) { 12705 that.$element.appendTo(document.body) // don't move modals dom position 12706 } 12707 12708 that.$element.show() 12709 12710 if (transition) { 12711 that.$element[0].offsetWidth // force reflow 12712 } 12713 12714 that.$element 12715 .addClass('in') 12716 .attr('aria-hidden', false) 12717 12718 that.enforceFocus() 12719 12720 var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) 12721 12722 transition ? 12723 that.$element.find('.modal-dialog') // wait for modal to slide in 12724 .one($.support.transition.end, function () { 12725 that.$element.focus().trigger(e) 12726 }) 12727 .emulateTransitionEnd(300) : 12728 that.$element.focus().trigger(e) 12729 }) 12730 } 12731 12732 Modal.prototype.hide = function (e) { 12733 if (e) e.preventDefault() 12734 12735 e = $.Event('hide.bs.modal') 12736 12737 this.$element.trigger(e) 12738 12739 if (!this.isShown || e.isDefaultPrevented()) return 12740 12741 this.isShown = false 12742 12743 this.escape() 12744 12745 $(document).off('focusin.bs.modal') 12746 12747 this.$element 12748 .removeClass('in') 12749 .attr('aria-hidden', true) 12750 .off('click.dismiss.modal') 12751 12752 $.support.transition && this.$element.hasClass('fade') ? 12753 this.$element 12754 .one($.support.transition.end, $.proxy(this.hideModal, this)) 12755 .emulateTransitionEnd(300) : 12756 this.hideModal() 12757 } 12758 12759 Modal.prototype.enforceFocus = function () { 12760 $(document) 12761 .off('focusin.bs.modal') // guard against infinite focus loop 12762 .on('focusin.bs.modal', $.proxy(function (e) { 12763 if (this.$element[0] !== e.target && !this.$element.has(e.target).length) { 12764 this.$element.focus() 12765 } 12766 }, this)) 12767 } 12768 12769 Modal.prototype.escape = function () { 12770 if (this.isShown && this.options.keyboard) { 12771 this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) { 12772 e.which == 27 && this.hide() 12773 }, this)) 12774 } else if (!this.isShown) { 12775 this.$element.off('keyup.dismiss.bs.modal') 12776 } 12777 } 12778 12779 Modal.prototype.hideModal = function () { 12780 var that = this 12781 this.$element.hide() 12782 this.backdrop(function () { 12783 that.removeBackdrop() 12784 that.$element.trigger('hidden.bs.modal') 12785 }) 12786 } 12787 12788 Modal.prototype.removeBackdrop = function () { 12789 this.$backdrop && this.$backdrop.remove() 12790 this.$backdrop = null 12791 } 12792 12793 Modal.prototype.backdrop = function (callback) { 12794 var that = this 12795 var animate = this.$element.hasClass('fade') ? 'fade' : '' 12796 12797 if (this.isShown && this.options.backdrop) { 12798 var doAnimate = $.support.transition && animate 12799 12800 this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />') 12801 .appendTo(document.body) 12802 12803 this.$element.on('click.dismiss.modal', $.proxy(function (e) { 12804 if (e.target !== e.currentTarget) return 12805 this.options.backdrop == 'static' 12806 ? this.$element[0].focus.call(this.$element[0]) 12807 : this.hide.call(this) 12808 }, this)) 12809 12810 if (doAnimate) this.$backdrop[0].offsetWidth // force reflow 12811 12812 this.$backdrop.addClass('in') 12813 12814 if (!callback) return 12815 12816 doAnimate ? 12817 this.$backdrop 12818 .one($.support.transition.end, callback) 12819 .emulateTransitionEnd(150) : 12820 callback() 12821 12822 } else if (!this.isShown && this.$backdrop) { 12823 this.$backdrop.removeClass('in') 12824 12825 $.support.transition && this.$element.hasClass('fade')? 12826 this.$backdrop 12827 .one($.support.transition.end, callback) 12828 .emulateTransitionEnd(150) : 12829 callback() 12830 12831 } else if (callback) { 12832 callback() 12833 } 12834 } 12835 12836 12837 // MODAL PLUGIN DEFINITION 12838 // ======================= 12839 12840 var old = $.fn.modal 12841 12842 $.fn.modal = function (option, _relatedTarget) { 12843 return this.each(function () { 12844 var $this = $(this) 12845 var data = $this.data('bs.modal') 12846 var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) 12847 12848 if (!data) $this.data('bs.modal', (data = new Modal(this, options))) 12849 if (typeof option == 'string') data[option](_relatedTarget) 12850 else if (options.show) data.show(_relatedTarget) 12851 }) 12852 } 12853 12854 $.fn.modal.Constructor = Modal 12855 12856 12857 // MODAL NO CONFLICT 12858 // ================= 12859 12860 $.fn.modal.noConflict = function () { 12861 $.fn.modal = old 12862 return this 12863 } 12864 12865 12866 // MODAL DATA-API 12867 // ============== 12868 12869 $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { 12870 var $this = $(this) 12871 var href = $this.attr('href') 12872 var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7 12873 var option = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) 12874 12875 e.preventDefault() 12876 12877 $target 12878 .modal(option, this) 12879 .one('hide', function () { 12880 $this.is(':visible') && $this.focus() 12881 }) 12882 }) 12883 12884 $(document) 12885 .on('show.bs.modal', '.modal', function () { $(document.body).addClass('modal-open') }) 12886 .on('hidden.bs.modal', '.modal', function () { $(document.body).removeClass('modal-open') }) 12887 12888}(jQuery); 12889 12890/* ======================================================================== 12891 * Bootstrap: tooltip.js v3.0.2 12892 * http://getbootstrap.com/javascript/#tooltip 12893 * Inspired by the original jQuery.tipsy by Jason Frame 12894 * ======================================================================== 12895 * Copyright 2013 Twitter, Inc. 12896 * 12897 * Licensed under the Apache License, Version 2.0 (the "License");
12898 * you may not use this file except in compliance with the License. 12899 * You may obtain a copy of the License at 12900 * 12901 * http://www.apache.org/licenses/LICENSE-2.0 12902 * 12903 * Unless required by applicable law or agreed to in writing, software 12904 * distributed under the License is distributed on an "AS IS" BASIS, 12905 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12906 * See the License for the specific language governing permissions and 12907 * limitations under the License. 12908 * ======================================================================== */ 12909 12910 12911+function ($) { "use strict"; 12912 12913 // TOOLTIP PUBLIC CLASS DEFINITION 12914 // =============================== 12915 12916 var Tooltip = function (element, options) { 12917 this.type = 12918 this.options = 12919 this.enabled = 12920 this.timeout = 12921 this.hoverState = 12922 this.$element = null 12923 12924 this.init('tooltip', element, options) 12925 } 12926 12927 Tooltip.DEFAULTS = { 12928 animation: true 12929 , placement: 'top' 12930 , selector: false 12931 , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>' 12932 , trigger: 'hover focus' 12933 , title: '' 12934 , delay: 0 12935 , html: false 12936 , container: false 12937 } 12938 12939 Tooltip.prototype.init = function (type, element, options) { 12940 this.enabled = true 12941 this.type = type 12942 this.$element = $(element) 12943 this.options = this.getOptions(options) 12944 12945 var triggers = this.options.trigger.split(' ') 12946 12947 for (var i = triggers.length; i--;) { 12948 var trigger = triggers[i] 12949 12950 if (trigger == 'click') { 12951 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) 12952 } else if (trigger != 'manual') { 12953 var eventIn = trigger == 'hover' ? 'mouseenter' : 'focus' 12954 var eventOut = trigger == 'hover' ? 'mouseleave' : 'blur' 12955 12956 this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) 12957 this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) 12958 } 12959 } 12960 12961 this.options.selector ? 12962 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : 12963 this.fixTitle() 12964 } 12965 12966 Tooltip.prototype.getDefaults = function () { 12967 return Tooltip.DEFAULTS 12968 } 12969 12970 Tooltip.prototype.getOptions = function (options) { 12971 options = $.extend({}, this.getDefaults(), this.$element.data(), options) 12972 12973 if (options.delay && typeof options.delay == 'number') { 12974 options.delay = { 12975 show: options.delay 12976 , hide: options.delay 12977 } 12978 } 12979 12980 return options 12981 } 12982 12983 Tooltip.prototype.getDelegateOptions = function () { 12984 var options = {} 12985 var defaults = this.getDefaults() 12986 12987 this._options && $.each(this._options, function (key, value) { 12988 if (defaults[key] != value) options[key] = value 12989 }) 12990 12991 return options 12992 } 12993 12994 Tooltip.prototype.enter = function (obj) { 12995 var self = obj instanceof this.constructor ? 12996 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 12997 12998 clearTimeout(self.timeout) 12999 13000 self.hoverState = 'in' 13001 13002 if (!self.options.delay || !self.options.delay.show) return self.show() 13003 13004 self.timeout = setTimeout(function () { 13005 if (self.hoverState == 'in') self.show() 13006 }, self.options.delay.show) 13007 } 13008 13009 Tooltip.prototype.leave = function (obj) { 13010 var self = obj instanceof this.constructor ? 13011 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 13012 13013 clearTimeout(self.timeout) 13014 13015 self.hoverState = 'out' 13016 13017 if (!self.options.delay || !self.options.delay.hide) return self.hide() 13018 13019 self.timeout = setTimeout(function () { 13020 if (self.hoverState == 'out') self.hide() 13021 }, self.options.delay.hide) 13022 } 13023 13024 Tooltip.prototype.show = function () { 13025 var e = $.Event('show.bs.'+ this.type) 13026 13027 if (this.hasContent() && this.enabled) { 13028 this.$element.trigger(e) 13029 13030 if (e.isDefaultPrevented()) return 13031 13032 var $tip = this.tip() 13033 13034 this.setContent() 13035 13036 if (this.options.animation) $tip.addClass('fade') 13037 13038 var placement = typeof this.options.placement == 'function' ? 13039 this.options.placement.call(this, $tip[0], this.$element[0]) : 13040 this.options.placement 13041 13042 var autoToken = /\s?auto?\s?/i 13043 var autoPlace = autoToken.test(placement) 13044 if (autoPlace) placement = placement.replace(autoToken, '') || 'top' 13045 13046 $tip 13047 .detach() 13048 .css({ top: 0, left: 0, display: 'block' }) 13049 .addClass(placement) 13050 13051 this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) 13052 13053 var pos = this.getPosition() 13054 var actualWidth = $tip[0].offsetWidth 13055 var actualHeight = $tip[0].offsetHeight 13056 13057 if (autoPlace) { 13058 var $parent = this.$element.parent() 13059 13060 var orgPlacement = placement 13061 var docScroll = document.documentElement.scrollTop || document.body.scrollTop 13062 var parentWidth = this.options.container == 'body' ? window.innerWidth : $parent.outerWidth() 13063 var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight() 13064 var parentLeft = this.options.container == 'body' ? 0 : $parent.offset().left 13065 13066 placement = placement == 'bottom' && pos.top + pos.height + actualHeight - docScroll > parentHeight ? 'top' : 13067 placement == 'top' && pos.top - docScroll - actualHeight < 0 ? 'bottom' : 13068 placement == 'right' && pos.right + actualWidth > parentWidth ? 'left' : 13069 placement == 'left' && pos.left - actualWidth < parentLeft ? 'right' : 13070 placement 13071 13072 $tip 13073 .removeClass(orgPlacement) 13074 .addClass(placement) 13075 } 13076 13077 var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) 13078 13079 this.applyPlacement(calculatedOffset, placement) 13080 this.$element.trigger('shown.bs.' + this.type) 13081 } 13082 } 13083 13084 Tooltip.prototype.applyPlacement = function(offset, placement) { 13085 var replace 13086 var $tip = this.tip() 13087 var width = $tip[0].offsetWidth 13088 var height = $tip[0].offsetHeight 13089 13090 // manually read margins because getBoundingClientRect includes difference 13091 var marginTop = parseInt($tip.css('margin-top'), 10) 13092 var marginLeft = parseInt($tip.css('margin-left'), 10) 13093 13094 // we must check for NaN for ie 8/9 13095 if (isNaN(marginTop)) marginTop = 0 13096 if (isNaN(marginLeft)) marginLeft = 0 13097 13098 offset.top = offset.top + marginTop 13099 offset.left = offset.left + marginLeft 13100 13101 $tip 13102 .offset(offset) 13103 .addClass('in') 13104 13105 // check to see if placing tip in new offset caused the tip to resize itself 13106 var actualWidth = $tip[0].offsetWidth 13107 var actualHeight = $tip[0].offsetHeight 13108 13109 if (placement == 'top' && actualHeight != height) { 13110 replace = true 13111 offset.top = offset.top + height - actualHeight 13112 } 13113 13114 if (/bottom|top/.test(placement)) { 13115 var delta = 0 13116 13117 if (offset.left < 0) { 13118 delta = offset.left * -2 13119 offset.left = 0 13120 13121 $tip.offset(offset) 13122 13123 actualWidth = $tip[0].offsetWidth 13124 actualHeight = $tip[0].offsetHeight 13125 } 13126 13127 this.replaceArrow(delta - width + actualWidth, actualWidth, 'left') 13128 } else { 13129 this.replaceArrow(actualHeight - height, actualHeight, 'top') 13130 } 13131 13132 if (replace) $tip.offset(offset) 13133 } 13134 13135 Tooltip.prototype.replaceArrow = function(delta, dimension, position) { 13136 this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + "%") : '') 13137 } 13138 13139 Tooltip.prototype.setContent = function () { 13140 var $tip = this.tip() 13141 var title = this.getTitle() 13142 13143 $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) 13144 $tip.removeClass('fade in top bottom left right') 13145 } 13146 13147 Tooltip.prototype.hide = function () { 13148 var that = this 13149 var $tip = this.tip() 13150 var e = $.Event('hide.bs.' + this.type) 13151 13152 function complete() { 13153 if (that.hoverState != 'in') $tip.detach() 13154 } 13155 13156 this.$element.trigger(e) 13157 13158 if (e.isDefaultPrevented()) return 13159 13160 $tip.removeClass('in') 13161 13162 $.support.transition && this.$tip.hasClass('fade') ? 13163 $tip 13164 .one($.support.transition.end, complete) 13165 .emulateTransitionEnd(150) : 13166 complete() 13167 13168 this.$element.trigger('hidden.bs.' + this.type) 13169 13170 return this 13171 } 13172 13173 Tooltip.prototype.fixTitle = function () { 13174 var $e = this.$element 13175 if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { 13176 $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') 13177 } 13178 } 13179 13180 Tooltip.prototype.hasContent = function () { 13181 return this.getTitle() 13182 } 13183 13184 Tooltip.prototype.getPosition = function () { 13185 var el = this.$element[0] 13186 return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : { 13187 width: el.offsetWidth 13188 , height: el.offsetHeight 13189 }, this.$element.offset()) 13190 } 13191 13192 Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { 13193 return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : 13194 placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : 13195 placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : 13196 /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } 13197 } 13198 13199 Tooltip.prototype.getTitle = function () { 13200 var title 13201 var $e = this.$element 13202 var o = this.options 13203 13204 title = $e.attr('data-original-title') 13205 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) 13206 13207 return title 13208 } 13209 13210 Tooltip.prototype.tip = function () { 13211 return this.$tip = this.$tip || $(this.options.template) 13212 } 13213 13214 Tooltip.prototype.arrow = function () { 13215 return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow') 13216 } 13217 13218 Tooltip.prototype.validate = function () { 13219 if (!this.$element[0].parentNode) { 13220 this.hide() 13221 this.$element = null 13222 this.options = null 13223 } 13224 } 13225 13226 Tooltip.prototype.enable = function () { 13227 this.enabled = true 13228 } 13229 13230 Tooltip.prototype.disable = function () { 13231 this.enabled = false 13232 } 13233 13234 Tooltip.prototype.toggleEnabled = function () { 13235 this.enabled = !this.enabled 13236 } 13237 13238 Tooltip.prototype.toggle = function (e) { 13239 var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this 13240 self.tip().hasClass('in') ? self.leave(self) : self.enter(self) 13241 } 13242 13243 Tooltip.prototype.destroy = function () { 13244 this.hide().$element.off('.' + this.type).removeData('bs.' + this.type) 13245 } 13246 13247 13248 // TOOLTIP PLUGIN DEFINITION 13249 // ========================= 13250 13251 var old = $.fn.tooltip 13252 13253 $.fn.tooltip = function (option) { 13254 return this.each(function () { 13255 var $this = $(this) 13256 var data = $this.data('bs.tooltip') 13257 var options = typeof option == 'object' && option 13258 13259 if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) 13260 if (typeof option == 'string') data[option]() 13261 }) 13262 } 13263 13264 $.fn.tooltip.Constructor = Tooltip 13265 13266 13267 // TOOLTIP NO CONFLICT 13268 // =================== 13269 13270 $.fn.tooltip.noConflict = function () { 13271 $.fn.tooltip = old 13272 return this 13273 } 13274 13275}(jQuery); 13276 13277/* ======================================================================== 13278 * Bootstrap: popover.js v3.0.2 13279 * http://getbootstrap.com/javascript/#popovers 13280 * ======================================================================== 13281 * Copyright 2013 Twitter, Inc. 13282 * 13283 * Licensed under the Apache License, Version 2.0 (the "License");
13284 * you may not use this file except in compliance with the License. 13285 * You may obtain a copy of the License at 13286 * 13287 * http://www.apache.org/licenses/LICENSE-2.0 13288 * 13289 * Unless required by applicable law or agreed to in writing, software 13290 * distributed under the License is distributed on an "AS IS" BASIS, 13291 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13292 * See the License for the specific language governing permissions and 13293 * limitations under the License. 13294 * ======================================================================== */ 13295 13296 13297+function ($) { "use strict"; 13298 13299 // POPOVER PUBLIC CLASS DEFINITION 13300 // =============================== 13301 13302 var Popover = function (element, options) { 13303 this.init('popover', element, options) 13304 } 13305 13306 if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') 13307 13308 Popover.DEFAULTS = $.extend({} , $.fn.tooltip.Constructor.DEFAULTS, { 13309 placement: 'right' 13310 , trigger: 'click' 13311 , content: '' 13312 , template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>' 13313 }) 13314 13315 13316 // NOTE: POPOVER EXTENDS tooltip.js 13317 // ================================ 13318 13319 Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype) 13320 13321 Popover.prototype.constructor = Popover 13322 13323 Popover.prototype.getDefaults = function () { 13324 return Popover.DEFAULTS 13325 } 13326 13327 Popover.prototype.setContent = function () { 13328 var $tip = this.tip() 13329 var title = this.getTitle() 13330 var content = this.getContent() 13331 13332 $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title) 13333 $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content) 13334 13335 $tip.removeClass('fade top bottom left right in') 13336 13337 // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do 13338 // this manually by checking the contents. 13339 if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide() 13340 } 13341 13342 Popover.prototype.hasContent = function () { 13343 return this.getTitle() || this.getContent() 13344 } 13345 13346 Popover.prototype.getContent = function () { 13347 var $e = this.$element 13348 var o = this.options 13349 13350 return $e.attr('data-content') 13351 || (typeof o.content == 'function' ? 13352 o.content.call($e[0]) : 13353 o.content) 13354 } 13355 13356 Popover.prototype.arrow = function () { 13357 return this.$arrow = this.$arrow || this.tip().find('.arrow') 13358 } 13359 13360 Popover.prototype.tip = function () { 13361 if (!this.$tip) this.$tip = $(this.options.template) 13362 return this.$tip 13363 } 13364 13365 13366 // POPOVER PLUGIN DEFINITION 13367 // ========================= 13368 13369 var old = $.fn.popover 13370 13371 $.fn.popover = function (option) { 13372 return this.each(function () { 13373 var $this = $(this) 13374 var data = $this.data('bs.popover') 13375 var options = typeof option == 'object' && option 13376 13377 if (!data) $this.data('bs.popover', (data = new Popover(this, options))) 13378 if (typeof option == 'string') data[option]() 13379 }) 13380 } 13381 13382 $.fn.popover.Constructor = Popover 13383 13384 13385 // POPOVER NO CONFLICT 13386 // =================== 13387 13388 $.fn.popover.noConflict = function () { 13389 $.fn.popover = old 13390 return this 13391 } 13392 13393}(jQuery); 13394 13395/* ======================================================================== 13396 * Bootstrap: scrollspy.js v3.0.2 13397 * http://getbootstrap.com/javascript/#scrollspy 13398 * ======================================================================== 13399 * Copyright 2013 Twitter, Inc. 13400 * 13401 * Licensed under the Apache License, Version 2.0 (the "License"); 13402 * you may not use this file except in compliance with the License. 13403 * You may obtain a copy of the License at 13404 * 13405 * http://www.apache.org/licenses/LICENSE-2.0 13406 * 13407 * Unless required by applicable law or agreed to in writing, software 13408 * distributed under the License is distributed on an "AS IS" BASIS, 13409 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13410 * See the License for the specific language governing permissions and 13411 * limitations under the License. 13412 * ======================================================================== */ 13413 13414 13415+function ($) { "use strict"; 13416 13417 // SCROLLSPY CLASS DEFINITION 13418 // ========================== 13419 13420 function ScrollSpy(element, options) { 13421 var href 13422 var process = $.proxy(this.process, this) 13423 13424 this.$element = $(element).is('body') ? $(window) : $(element) 13425 this.$body = $('body') 13426 this.$scrollElement = this.$element.on('scroll.bs.scroll-spy.data-api', process) 13427 this.options = $.extend({}, ScrollSpy.DEFAULTS, options) 13428 this.selector = (this.options.target 13429 || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 13430 || '') + ' .nav li > a' 13431 this.offsets = $([]) 13432 this.targets = $([]) 13433 this.activeTarget = null 13434 13435 this.refresh() 13436 this.process() 13437 } 13438 13439 ScrollSpy.DEFAULTS = { 13440 offset: 10 13441 } 13442 13443 ScrollSpy.prototype.refresh = function () { 13444 var offsetMethod = this.$element[0] == window ? 'offset' : 'position' 13445 13446 this.offsets = $([]) 13447 this.targets = $([]) 13448 13449 var self = this 13450 var $targets = this.$body 13451 .find(this.selector) 13452 .map(function () { 13453 var $el = $(this) 13454 var href = $el.data('target') || $el.attr('href') 13455 var $href = /^#\w/.test(href) && $(href) 13456 13457 return ($href 13458 && $href.length 13459 && [[ $href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]]) || null 13460 }) 13461 .sort(function (a, b) { return a[0] - b[0] }) 13462 .each(function () { 13463 self.offsets.push(this[0]) 13464 self.targets.push(this[1]) 13465 }) 13466 } 13467 13468 ScrollSpy.prototype.process = function () { 13469 var scrollTop = this.$scrollElement.scrollTop() + this.options.offset 13470 var scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight 13471 var maxScroll = scrollHeight - this.$scrollElement.height() 13472 var offsets = this.offsets 13473 var targets = this.targets 13474 var activeTarget = this.activeTarget 13475 var i 13476 13477 if (scrollTop >= maxScroll) { 13478 return activeTarget != (i = targets.last()[0]) && this.activate(i) 13479 } 13480 13481 for (i = offsets.length; i--;) { 13482 activeTarget != targets[i] 13483 && scrollTop >= offsets[i] 13484 && (!offsets[i + 1] || scrollTop <= offsets[i + 1]) 13485 && this.activate( targets[i] ) 13486 } 13487 } 13488 13489 ScrollSpy.prototype.activate = function (target) { 13490 this.activeTarget = target 13491 13492 $(this.selector) 13493 .parents('.active') 13494 .removeClass('active') 13495 13496 var selector = this.selector 13497 + '[data-target="' + target + '"],' 13498 + this.selector + '[href="' + target + '"]' 13499 13500 var active = $(selector) 13501 .parents('li') 13502 .addClass('active') 13503 13504 if (active.parent('.dropdown-menu').length) { 13505 active = active 13506 .closest('li.dropdown') 13507 .addClass('active') 13508 } 13509 13510 active.trigger('activate') 13511 } 13512 13513 13514 // SCROLLSPY PLUGIN DEFINITION 13515 // =========================== 13516 13517 var old = $.fn.scrollspy 13518 13519 $.fn.scrollspy = function (option) { 13520 return this.each(function () { 13521 var $this = $(this) 13522 var data = $this.data('bs.scrollspy') 13523 var options = typeof option == 'object' && option 13524 13525 if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))) 13526 if (typeof option == 'string') data[option]() 13527 }) 13528 } 13529 13530 $.fn.scrollspy.Constructor = ScrollSpy 13531 13532 13533 // SCROLLSPY NO CONFLICT 13534 // ===================== 13535 13536 $.fn.scrollspy.noConflict = function () { 13537 $.fn.scrollspy = old 13538 return this 13539 } 13540 13541 13542 // SCROLLSPY DATA-API 13543 // ================== 13544 13545 $(window).on('load', function () { 13546 $('[data-spy="scroll"]').each(function () { 13547 var $spy = $(this) 13548 $spy.scrollspy($spy.data()) 13549 }) 13550 }) 13551 13552}(jQuery); 13553 13554/* ======================================================================== 13555 * Bootstrap: tab.js v3.0.2 13556 * http://getbootstrap.com/javascript/#tabs 13557 * ======================================================================== 13558 * Copyright 2013 Twitter, Inc. 13559 * 13560 * Licensed under the Apache License, Version 2.0 (the "License");
13561 * you may not use this file except in compliance with the License. 13562 * You may obtain a copy of the License at 13563 * 13564 * http://www.apache.org/licenses/LICENSE-2.0 13565 * 13566 * Unless required by applicable law or agreed to in writing, software 13567 * distributed under the License is distributed on an "AS IS" BASIS, 13568 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13569 * See the License for the specific language governing permissions and 13570 * limitations under the License. 13571 * ======================================================================== */ 13572 13573 13574+function ($) { "use strict"; 13575 13576 // TAB CLASS DEFINITION 13577 // ==================== 13578 13579 var Tab = function (element) { 13580 this.element = $(element) 13581 } 13582 13583 Tab.prototype.show = function () { 13584 var $this = this.element 13585 var $ul = $this.closest('ul:not(.dropdown-menu)') 13586 var selector = $this.data('target') 13587 13588 if (!selector) { 13589 selector = $this.attr('href') 13590 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 13591 } 13592 13593 if ($this.parent('li').hasClass('active')) return 13594 13595 var previous = $ul.find('.active:last a')[0] 13596 var e = $.Event('show.bs.tab', { 13597 relatedTarget: previous 13598 }) 13599 13600 $this.trigger(e) 13601 13602 if (e.isDefaultPrevented()) return 13603 13604 var $target = $(selector) 13605 13606 this.activate($this.parent('li'), $ul) 13607 this.activate($target, $target.parent(), function () { 13608 $this.trigger({ 13609 type: 'shown.bs.tab' 13610 , relatedTarget: previous 13611 }) 13612 }) 13613 } 13614 13615 Tab.prototype.activate = function (element, container, callback) { 13616 var $active = container.find('> .active') 13617 var transition = callback 13618 && $.support.transition 13619 && $active.hasClass('fade') 13620 13621 function next() { 13622 $active 13623 .removeClass('active') 13624 .find('> .dropdown-menu > .active') 13625 .removeClass('active') 13626 13627 element.addClass('active') 13628 13629 if (transition) { 13630 element[0].offsetWidth // reflow for transition 13631 element.addClass('in') 13632 } else { 13633 element.removeClass('fade') 13634 } 13635 13636 if (element.parent('.dropdown-menu')) { 13637 element.closest('li.dropdown').addClass('active') 13638 } 13639 13640 callback && callback() 13641 } 13642 13643 transition ? 13644 $active 13645 .one($.support.transition.end, next) 13646 .emulateTransitionEnd(150) : 13647 next() 13648 13649 $active.removeClass('in') 13650 } 13651 13652 13653 // TAB PLUGIN DEFINITION 13654 // ===================== 13655 13656 var old = $.fn.tab 13657 13658 $.fn.tab = function ( option ) { 13659 return this.each(function () { 13660 var $this = $(this) 13661 var data = $this.data('bs.tab') 13662 13663 if (!data) $this.data('bs.tab', (data = new Tab(this))) 13664 if (typeof option == 'string') data[option]() 13665 }) 13666 } 13667 13668 $.fn.tab.Constructor = Tab 13669 13670 13671 // TAB NO CONFLICT 13672 // =============== 13673 13674 $.fn.tab.noConflict = function () { 13675 $.fn.tab = old 13676 return this 13677 } 13678 13679 13680 // TAB DATA-API 13681 // ============ 13682 13683 $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { 13684 e.preventDefault() 13685 $(this).tab('show') 13686 }) 13687 13688}(jQuery); 13689 13690/* ======================================================================== 13691 * Bootstrap: affix.js v3.2.0 13692 * http://getbootstrap.com/javascript/#affix 13693 * ======================================================================== 13694 * Copyright 2011-2014 Twitter, Inc. 13695 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 13696 * ======================================================================== */ 13697 13698 13699+function ($) { 13700 'use strict'; 13701 13702 // AFFIX CLASS DEFINITION 13703 // ====================== 13704 13705 var Affix = function (element, options) { 13706 this.options = $.extend({}, Affix.DEFAULTS, options) 13707 13708 this.$target = $(this.options.target) 13709 .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this)) 13710 .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this)) 13711 13712 this.$element = $(element) 13713 this.affixed = 13714 this.unpin = 13715 this.pinnedOffset = null 13716 13717 this.checkPosition() 13718 } 13719 13720 Affix.VERSION = '3.2.0' 13721 13722 Affix.RESET = 'affix affix-top affix-bottom' 13723 13724 Affix.DEFAULTS = { 13725 offset: 0, 13726 target: window 13727 } 13728 13729 Affix.prototype.getPinnedOffset = function () { 13730 if (this.pinnedOffset) return this.pinnedOffset 13731 this.$element.removeClass(Affix.RESET).addClass('affix') 13732 var scrollTop = this.$target.scrollTop() 13733 var position = this.$element.offset() 13734 return (this.pinnedOffset = position.top - scrollTop) 13735 } 13736 13737 Affix.prototype.checkPositionWithEventLoop = function () { 13738 setTimeout($.proxy(this.checkPosition, this), 1) 13739 } 13740 13741 Affix.prototype.checkPosition = function () { 13742 if (!this.$element.is(':visible')) return 13743 13744 var scrollHeight = $(document).height() 13745 var scrollTop = this.$target.scrollTop() 13746 var position = this.$element.offset() 13747 var offset = this.options.offset 13748 var offsetTop = offset.top 13749 var offsetBottom = offset.bottom 13750 13751 if (typeof offset != 'object') offsetBottom = offsetTop = offset 13752 if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element) 13753 if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element) 13754 13755 var affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ? false : 13756 offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' : 13757 offsetTop != null && (scrollTop <= offsetTop) ? 'top' : false 13758 13759 if (this.affixed === affix) return 13760 if (this.unpin != null) this.$element.css('top', '') 13761 13762 var affixType = 'affix' + (affix ? '-' + affix : '') 13763 var e = $.Event(affixType + '.bs.affix') 13764 13765 this.$element.trigger(e) 13766 13767 if (e.isDefaultPrevented()) return 13768 13769 this.affixed = affix 13770 this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null 13771 13772 this.$element 13773 .removeClass(Affix.RESET) 13774 .addClass(affixType) 13775 .trigger($.Event(affixType.replace('affix', 'affixed'))) 13776 13777 13778 if (affix == 'bottom') { 13779 this.$element.offset({ 13780 top: scrollHeight - this.$element.height() - offsetBottom 13781 }) 13782 } 13783 } 13784 13785 13786 // AFFIX PLUGIN DEFINITION 13787 // ======================= 13788 13789 function Plugin(option) { 13790 return this.each(function () { 13791 var $this = $(this) 13792 var data = $this.data('bs.affix') 13793 var options = typeof option == 'object' && option 13794 13795 if (!data) $this.data('bs.affix', (data = new Affix(this, options))) 13796 if (typeof option == 'string') data[option]() 13797 }) 13798 } 13799 13800 var old = $.fn.affix 13801 13802 $.fn.affix = Plugin 13803 $.fn.affix.Constructor = Affix 13804 13805 13806 // AFFIX NO CONFLICT 13807 // ================= 13808 13809 $.fn.affix.noConflict = function () { 13810 $.fn.affix = old 13811 return this 13812 } 13813 13814 13815 // AFFIX DATA-API 13816 // ============== 13817 13818 $(window).on('load', function () { 13819 $('[data-spy="affix"]').each(function () { 13820 var $spy = $(this) 13821 var data = $spy.data() 13822 13823 data.offset = data.offset || {} 13824 13825 if (data.offsetBottom) data.offset.bottom = data.offsetBottom 13826 if (data.offsetTop) data.offset.top = data.offsetTop 13827 13828 Plugin.call($spy, data) 13829 }) 13830 }) 13831 13832}(jQuery); 13833 13834/* 13835 * blueimp Gallery JS 2.14.0 13836 * https://github.com/blueimp/Gallery 13837 * 13838 * Copyright 2013, Sebastian Tschan 13839 * https://blueimp.net 13840 * 13841 * Swipe implementation based on 13842 * https://github.com/bradbirdsall/Swipe 13843 * 13844 * Licensed under the MIT license: 13845 * http://www.opensource.org/licenses/MIT 13846 */ 13847 13848/* global define, window, document, DocumentTouch */ 13849 13850(function (factory) { 13851 'use strict'; 13852 if (typeof define === 'function' && define.amd) { 13853 // Register as an anonymous AMD module: 13854 define(['./blueimp-helper'], factory); 13855 } else { 13856 // Browser globals: 13857 window.blueimp = window.blueimp || {}; 13858 window.blueimp.Gallery = factory( 13859 window.blueimp.helper || window.jQuery 13860 ); 13861 } 13862}(function ($) { 13863 'use strict'; 13864 13865 function Gallery(list, options) { 13866 if (document.body.style.maxHeight === undefined) { 13867 // document.body.style.maxHeight is undefined on IE6 and lower 13868 return null; 13869 } 13870 if (!this || this.options !== Gallery.prototype.options) { 13871 // Called as function instead of as constructor, 13872 // so we simply return a new instance: 13873 return new Gallery(list, options); 13874 } 13875 if (!list || !list.length) { 13876 this.console.log( 13877 'blueimp Gallery: No or empty list provided as first argument.', 13878 list 13879 ); 13880 return; 13881 } 13882 this.list = list; 13883 this.num = list.length; 13884 this.initOptions(options); 13885 this.initialize(); 13886 } 13887 13888 $.extend(Gallery.prototype, { 13889 13890 options: { 13891 // The Id, element or querySelector of the gallery widget: 13892 container: '#blueimp-gallery', 13893 // The tag name, Id, element or querySelector of the slides container: 13894 slidesContainer: 'div', 13895 // The tag name, Id, element or querySelector of the title element: 13896 titleElement: 'h3', 13897 // The class to add when the gallery is visible: 13898 displayClass: 'blueimp-gallery-display', 13899 // The class to add when the gallery controls are visible: 13900 controlsClass: 'blueimp-gallery-controls', 13901 // The class to add when the gallery only displays one element: 13902 singleClass: 'blueimp-gallery-single', 13903 // The class to add when the left edge has been reached: 13904 leftEdgeClass: 'blueimp-gallery-left', 13905 // The class to add when the right edge has been reached: 13906 rightEdgeClass: 'blueimp-gallery-right', 13907 // The class to add when the automatic slideshow is active: 13908 playingClass: 'blueimp-gallery-playing', 13909 // The class for all slides: 13910 slideClass: 'slide', 13911 // The slide class for loading elements: 13912 slideLoadingClass: 'slide-loading', 13913 // The slide class for elements that failed to load: 13914 slideErrorClass: 'slide-error', 13915 // The class for the content element loaded into each slide: 13916 slideContentClass: 'slide-content', 13917 // The class for the "toggle" control: 13918 toggleClass: 'toggle', 13919 // The class for the "prev" control: 13920 prevClass: 'prev', 13921 // The class for the "next" control: 13922 nextClass: 'next', 13923 // The class for the "close" control: 13924 closeClass: 'close', 13925 // The class for the "play-pause" toggle control: 13926 playPauseClass: 'play-pause', 13927 // The list object property (or data attribute) with the object type: 13928 typeProperty: 'type', 13929 // The list object property (or data attribute) with the object title: 13930 titleProperty: 'title', 13931 // The list object property (or data attribute) with the object URL: 13932 urlProperty: 'href', 13933 // The gallery listens for transitionend events before triggering the 13934 // opened and closed events, unless the following option is set to false: 13935 displayTransition: true, 13936 // Defines if the gallery slides are cleared from the gallery modal, 13937 // or reused for the next gallery initialization: 13938 clearSlides: true, 13939 // Defines if images should be stretched to fill the available space, 13940 // while maintaining their aspect ratio (will only be enabled for browsers 13941 // supporting background-size="contain", which excludes IE < 9). 13942 // Set to "cover", to make images cover all available space (requires 13943 // support for background-size="cover", which excludes IE < 9): 13944 stretchImages: false, 13945 // Toggle the controls on pressing the Return key: 13946 toggleControlsOnReturn: true, 13947 // Toggle the automatic slideshow interval on pressing the Space key: 13948 toggleSlideshowOnSpace: true, 13949 // Navigate the gallery by pressing left and right on the keyboard: 13950 enableKeyboardNavigation: true, 13951 // Close the gallery on pressing the Esc key: 13952 closeOnEscape: true, 13953 // Close the gallery when clicking on an empty slide area: 13954 closeOnSlideClick: true, 13955 // Close the gallery by swiping up or down: 13956 closeOnSwipeUpOrDown: true, 13957 // Emulate touch events on mouse-pointer devices such as desktop browsers: 13958 emulateTouchEvents: true, 13959 // Stop touch events from bubbling up to ancestor elements of the Gallery: 13960 stopTouchEventsPropagation: false, 13961 // Hide the page scrollbars: 13962 hidePageScrollbars: true, 13963 // Stops any touches on the container from scrolling the page: 13964 disableScroll: true, 13965 // Carousel mode (shortcut for carousel specific options): 13966 carousel: false, 13967 // Allow continuous navigation, moving from last to first 13968 // and from first to last slide: 13969 continuous: true, 13970 // Remove elements outside of the preload range from the DOM: 13971 unloadElements: true, 13972 // Start with the automatic slideshow: 13973 startSlideshow: false, 13974 // Delay in milliseconds between slides for the automatic slideshow: 13975 slideshowInterval: 5000, 13976 // The starting index as integer. 13977 // Can also be an object of the given list, 13978 // or an equal object with the same url property: 13979 index: 0, 13980 // The number of elements to load around the current index: 13981 preloadRange: 2, 13982 // The transition speed between slide changes in milliseconds: 13983 transitionSpeed: 400, 13984 // The transition speed for automatic slide changes, set to an integer 13985 // greater 0 to override the default transition speed: 13986 slideshowTransitionSpeed: undefined, 13987 // The event object for which the default action will be canceled 13988 // on Gallery initialization (e.g. the click event to open the Gallery): 13989 event: undefined, 13990 // Callback function executed when the Gallery is initialized. 13991 // Is called with the gallery instance as "this" object: 13992 onopen: undefined, 13993 // Callback function executed when the Gallery has been initialized 13994 // and the initialization transition has been completed. 13995 // Is called with the gallery instance as "this" object: 13996 onopened: undefined, 13997 // Callback function executed on slide change. 13998 // Is called with the gallery instance as "this" object and the 13999 // current index and slide as arguments: 14000 onslide: undefined, 14001 // Callback function executed after the slide change transition. 14002 // Is called with the gallery instance as "this" object and the 14003 // current index and slide as arguments: 14004 onslideend: undefined, 14005 // Callback function executed on slide content load. 14006 // Is called with the gallery instance as "this" object and the 14007 // slide index and slide element as arguments: 14008 onslidecomplete: undefined, 14009 // Callback function executed when the Gallery is about to be closed. 14010 // Is called with the gallery instance as "this" object: 14011 onclose: undefined, 14012 // Callback function executed when the Gallery has been closed 14013 // and the closing transition has been completed. 14014 // Is called with the gallery instance as "this" object: 14015 onclosed: undefined 14016 }, 14017 14018 carouselOptions: { 14019 hidePageScrollbars: false, 14020 toggleControlsOnReturn: false, 14021 toggleSlideshowOnSpace: false, 14022 enableKeyboardNavigation: false, 14023 closeOnEscape: false, 14024 closeOnSlideClick: false, 14025 closeOnSwipeUpOrDown: false, 14026 disableScroll: false, 14027 startSlideshow: true 14028 }, 14029 14030 console: window.console && typeof window.console.log === 'function' ? 14031 window.console
14031 : 14032 {log: function () {}}, 14033 14034 // Detect touch, transition, transform and background-size support: 14035 support: (function (element) { 14036 var support = { 14037 touch: window.ontouchstart !== undefined || 14038 (window.DocumentTouch && document instanceof DocumentTouch) 14039 }, 14040 transitions = { 14041 webkitTransition: { 14042 end: 'webkitTransitionEnd', 14043 prefix: '-webkit-' 14044 }, 14045 MozTransition: { 14046 end: 'transitionend', 14047 prefix: '-moz-' 14048 }, 14049 OTransition: { 14050 end: 'otransitionend', 14051 prefix: '-o-' 14052 }, 14053 transition: { 14054 end: 'transitionend', 14055 prefix: '' 14056 } 14057 }, 14058 elementTests = function () { 14059 var transition = support.transition, 14060 prop, 14061 translateZ; 14062 document.body.appendChild(element); 14063 if (transition) { 14064 prop = transition.name.slice(0, -9) + 'ransform'; 14065 if (element.style[prop] !== undefined) { 14066 element.style[prop] = 'translateZ(0)'; 14067 translateZ = window.getComputedStyle(element) 14068 .getPropertyValue(transition.prefix + 'transform'); 14069 support.transform = { 14070 prefix: transition.prefix, 14071 name: prop, 14072 translate: true, 14073 translateZ: !!translateZ && translateZ !== 'none' 14074 }; 14075 } 14076 } 14077 if (element.style.backgroundSize !== undefined) { 14078 support.backgroundSize = {}; 14079 element.style.backgroundSize = 'contain'; 14080 support.backgroundSize.contain = window 14081 .getComputedStyle(element) 14082 .getPropertyValue('background-size') === 'contain'; 14083 element.style.backgroundSize = 'cover'; 14084 support.backgroundSize.cover = window 14085 .getComputedStyle(element) 14086 .getPropertyValue('background-size') === 'cover'; 14087 } 14088 document.body.removeChild(element); 14089 }; 14090 (function (support, transitions) { 14091 var prop; 14092 for (prop in transitions) { 14093 if (transitions.hasOwnProperty(prop) && 14094 element.style[prop] !== undefined) { 14095 support.transition = transitions[prop]; 14096 support.transition.name = prop; 14097 break; 14098 } 14099 } 14100 }(support, transitions)); 14101 if (document.body) { 14102 elementTests(); 14103 } else { 14104 $(document).on('DOMContentLoaded', elementTests); 14105 } 14106 return support; 14107 // Test element, has to be standard HTML and must not be hidden 14108 // for the CSS3 tests using window.getComputedStyle to be applicable: 14109 }(document.createElement('div'))), 14110 14111 requestAnimationFrame: window.requestAnimationFrame || 14112 window.webkitRequestAnimationFrame || 14113 window.mozRequestAnimationFrame, 14114 14115 initialize: function () { 14116 this.initStartIndex(); 14117 if (this.initWidget() === false) { 14118 return false; 14119 } 14120 this.initEventListeners(); 14121 // Load the slide at the given index: 14122 this.onslide(this.index); 14123 // Manually trigger the slideend event for the initial slide: 14124 this.ontransitionend(); 14125 // Start the automatic slideshow if applicable: 14126 if (this.options.startSlideshow) { 14127 this.play(); 14128 } 14129 }, 14130 14131 slide: function (to, speed) { 14132 window.clearTimeout(this.timeout); 14133 var index = this.index, 14134 direction, 14135 naturalDirection, 14136 diff; 14137 if (index === to || this.num === 1) { 14138 return; 14139 } 14140 if (!speed) { 14141 speed = this.options.transitionSpeed; 14142 } 14143 if (this.support.transition) { 14144 if (!this.options.continuous) { 14145 to = this.circle(to); 14146 } 14147 // 1: backward, -1: forward: 14148 direction = Math.abs(index - to) / (index - to); 14149 // Get the actual position of the slide: 14150 if (this.options.continuous) { 14151 naturalDirection = direction; 14152 direction = -this.positions[this.circle(to)] / this.slideWidth; 14153 // If going forward but to < index, use to = slides.length + to 14154 // If going backward but to > index, use to = -slides.length + to 14155 if (direction !== naturalDirection) { 14156 to = -direction * this.num + to; 14157 } 14158 } 14159 diff = Math.abs(index - to) - 1; 14160 // Move all the slides between index and to in the right direction: 14161 while (diff) { 14162 diff -= 1; 14163 this.move( 14164 this.circle((to > index ? to : index) - diff - 1), 14165 this.slideWidth * direction, 14166 0 14167 ); 14168 } 14169 to = this.circle(to); 14170 this.move(index, this.slideWidth * direction, speed); 14171 this.move(to, 0, speed); 14172 if (this.options.continuous) { 14173 this.move( 14174 this.circle(to - direction), 14175 -(this.slideWidth * direction), 14176 0 14177 ); 14178 } 14179 } else { 14180 to = this.circle(to); 14181 this.animate(index * -this.slideWidth, to * -this.slideWidth, speed); 14182 } 14183 this.onslide(to); 14184 }, 14185 14186 getIndex: function () { 14187 return this.index; 14188 }, 14189 14190 getNumber: function () { 14191 return this.num; 14192 }, 14193 14194 prev: function () { 14195 if (this.options.continuous || this.index) { 14196 this.slide(this.index - 1); 14197 } 14198 }, 14199 14200 next: function () { 14201 if (this.options.continuous || this.index < this.num - 1) { 14202 this.slide(this.index + 1); 14203 } 14204 }, 14205 14206 play: function (time) { 14207 var that = this; 14208 window.clearTimeout(this.timeout); 14209 this.interval = time || this.options.slideshowInterval; 14210 if (this.elements[this.index] > 1) { 14211 this.timeout = this.setTimeout( 14212 (!this.requestAnimationFrame && this.slide) || function (to, speed) { 14213 that.animationFrameId = that.requestAnimationFrame.call( 14214 window, 14215 function () { 14216 that.slide(to, speed); 14217 } 14218 ); 14219 }, 14220 [this.index + 1, this.options.slideshowTransitionSpeed], 14221 this.interval 14222 ); 14223 } 14224 this.container.addClass(this.options.playingClass); 14225 }, 14226 14227 pause: function () { 14228 window.clearTimeout(this.timeout); 14229 this.interval = null; 14230 this.container.removeClass(this.options.playingClass); 14231 }, 14232 14233 add: function (list) { 14234 var i; 14235 if (!list.concat) { 14236 // Make a real array out of the list to add: 14237 list = Array.prototype.slice.call(list); 14238 } 14239 if (!this.list.concat) { 14240 // Make a real array out of the Gallery list: 14241 this.list = Array.prototype.slice.call(this.list); 14242 } 14243 this.list = this.list.concat(list); 14244 this.num = this.list.length; 14245 if (this.num > 2 && this.options.continuous === null) { 14246 this.options.continuous = true; 14247 this.container.removeClass(this.options.leftEdgeClass); 14248 } 14249 this.container 14250 .removeClass(this.options.rightEdgeClass) 14251 .removeClass(this.options.singleClass); 14252 for (i = this.num - list.length; i < this.num; i += 1) { 14253 this.addSlide(i); 14254 this.positionSlide(i); 14255 } 14256 this.positions.length = this.num; 14257 this.initSlides(true); 14258 }, 14259 14260 resetSlides: function () { 14261 this.slidesContainer.empty(); 14262 this.slides = []; 14263 }, 14264 14265 handleClose: function () { 14266 var options = this.options; 14267 this.destroyEventListeners(); 14268 // Cancel the slideshow: 14269 this.pause(); 14270 this.container[0].style.display = 'none'; 14271 this.container 14272 .removeClass(options.displayClass) 14273 .removeClass(options.singleClass) 14274 .removeClass(options.leftEdgeClass) 14275 .removeClass(options.rightEdgeClass); 14276 if (options.hidePageScrollbars) { 14277 document.body.style.overflow = this.bodyOverflowStyle; 14278 } 14279 if (this.options.clearSlides) { 14280 this.resetSlides(); 14281 } 14282 if (this.options.onclosed) { 14283 this.options.onclosed.call(this); 14284 } 14285 }, 14286 14287 close: function () { 14288 var that = this, 14289 closeHandler = function (event) { 14290 if (event.target === that.container[0]) { 14291 that.container.off( 14292 that.support.transition.end, 14293 closeHandler 14294 ); 14295 that.handleClose(); 14296 } 14297 }; 14298 if (this.options.onclose) { 14299 this.options.onclose.call(this); 14300 } 14301 if (this.support.transition && this.options.displayTransition) { 14302 this.container.on( 14303 this.support.transition.end, 14304 closeHandler 14305 ); 14306 this.container.removeClass(this.options.displayClass); 14307 } else { 14308 this.handleClose(); 14309 } 14310 }, 14311 14312 circle: function (index) { 14313 // Always return a number inside of the slides index range: 14314 return (this.num + (index % this.num)) % this.num; 14315 }, 14316 14317 move: function (index, dist, speed) { 14318 this.translateX(index, dist, speed); 14319 this.positions[index] = dist; 14320 }, 14321 14322 translate: function (index, x, y, speed) { 14323 var style = this.slides[index].style, 14324 transition = this.support.transition, 14325 transform = this.support.transform; 14326 style[transition.name + 'Duration'] = speed + 'ms'; 14327 style[transform.name] = 'translate(' + x + 'px, ' + y + 'px)' + 14328 (transform.translateZ ? ' translateZ(0)' : ''); 14329 }, 14330 14331 translateX: function (index, x, speed) { 14332 this.translate(index, x, 0, speed); 14333 }, 14334 14335 translateY: function (index, y, speed) { 14336 this.translate(index, 0, y, speed); 14337 }, 14338 14339 animate: function (from, to, speed) { 14340 if (!speed) { 14341 this.slidesContainer[0].style.left = to + 'px'; 14342 return; 14343 } 14344 var that = this, 14345 start = new Date().getTime(), 14346 timer = window.setInterval(function () { 14347 var timeElap = new Date().getTime() - start; 14348 if (timeElap > speed) { 14349 that.slidesContainer[0].style.left = to + 'px'; 14350 that.ontransitionend(); 14351 window.clearInterval(timer); 14352 return; 14353 } 14354 that.slidesContainer[0].style.left = (((to - from) * 14355 (Math.floor((timeElap / speed) * 100) / 100)) + 14356 from) + 'px'; 14357 }, 4); 14358 }, 14359 14360 preventDefault: function (event) { 14361 if (event.preventDefault) { 14362 event.preventDefault(); 14363 } else { 14364 event.returnValue = false;
14365 } 14366 }, 14367 14368 stopPropagation: function (event) { 14369 if (event.stopPropagation) { 14370 event.stopPropagation(); 14371 } else { 14372 event.cancelBubble = true; 14373 } 14374 }, 14375 14376 onresize: function () { 14377 this.initSlides(true); 14378 }, 14379 14380 onmousedown: function (event) { 14381 // Trigger on clicks of the left mouse button only 14382 // and exclude video elements: 14383 if (event.which && event.which === 1 && 14384 event.target.nodeName !== 'VIDEO') { 14385 // Preventing the default mousedown action is required 14386 // to make touch emulation work with Firefox: 14387 event.preventDefault(); 14388 (event.originalEvent || event).touches = [{ 14389 pageX: event.pageX, 14390 pageY: event.pageY 14391 }]; 14392 this.ontouchstart(event); 14393 } 14394 }, 14395 14396 onmousemove: function (event) { 14397 if (this.touchStart) { 14398 (event.originalEvent || event).touches = [{ 14399 pageX: event.pageX, 14400 pageY: event.pageY 14401 }]; 14402 this.ontouchmove(event); 14403 } 14404 }, 14405 14406 onmouseup: function (event) { 14407 if (this.touchStart) { 14408 this.ontouchend(event); 14409 delete this.touchStart; 14410 } 14411 }, 14412 14413 onmouseout: function (event) { 14414 if (this.touchStart) { 14415 var target = event.target, 14416 related = event.relatedTarget; 14417 if (!related || (related !== target && 14418 !$.contains(target, related))) { 14419 this.onmouseup(event); 14420 } 14421 } 14422 }, 14423 14424 ontouchstart: function (event) { 14425 if (this.options.stopTouchEventsPropagation) { 14426 this.stopPropagation(event); 14427 } 14428 // jQuery doesn't copy touch event properties by default, 14429 // so we have to access the originalEvent object: 14430 var touches = (event.originalEvent || event).touches[0]; 14431 this.touchStart = { 14432 // Remember the initial touch coordinates: 14433 x: touches.pageX, 14434 y: touches.pageY, 14435 // Store the time to determine touch duration: 14436 time: Date.now() 14437 }; 14438 // Helper variable to detect scroll movement: 14439 this.isScrolling = undefined; 14440 // Reset delta values: 14441 this.touchDelta = {}; 14442 }, 14443 14444 ontouchmove: function (event) { 14445 if (this.options.stopTouchEventsPropagation) { 14446 this.stopPropagation(event); 14447 } 14448 // jQuery doesn't copy touch event properties by default, 14449 // so we have to access the originalEvent object: 14450 var touches = (event.originalEvent || event).touches[0], 14451 scale = (event.originalEvent || event).scale, 14452 index = this.index, 14453 touchDeltaX, 14454 indices; 14455 // Ensure this is a one touch swipe and not, e.g. a pinch: 14456 if (touches.length > 1 || (scale && scale !== 1)) { 14457 return; 14458 } 14459 if (this.options.disableScroll) { 14460 event.preventDefault(); 14461 } 14462 // Measure change in x and y coordinates: 14463 this.touchDelta = { 14464 x: touches.pageX - this.touchStart.x, 14465 y: touches.pageY - this.touchStart.y 14466 }; 14467 touchDeltaX = this.touchDelta.x; 14468 // Detect if this is a vertical scroll movement (run only once per touch): 14469 if (this.isScrolling === undefined) { 14470 this.isScrolling = this.isScrolling || 14471 Math.abs(touchDeltaX) < Math.abs(this.touchDelta.y); 14472 } 14473 if (!this.isScrolling) { 14474 // Always prevent horizontal scroll: 14475 event.preventDefault(); 14476 // Stop the slideshow: 14477 window.clearTimeout(this.timeout); 14478 if (this.options.continuous) { 14479 indices = [ 14480 this.circle(index + 1), 14481 index, 14482 this.circle(index - 1) 14483 ]; 14484 } else { 14485 // Increase resistance if first slide and sliding left 14486 // or last slide and sliding right: 14487 this.touchDelta.x = touchDeltaX = 14488 touchDeltaX / 14489 (((!index && touchDeltaX > 0) || 14490 (index === this.num - 1 && touchDeltaX < 0)) ? 14491 (Math.abs(touchDeltaX) / this.slideWidth + 1) : 1); 14492 indices = [index]; 14493 if (index) { 14494 indices.push(index - 1); 14495 } 14496 if (index < this.num - 1) { 14497 indices.unshift(index + 1); 14498 } 14499 } 14500 while (indices.length) { 14501 index = indices.pop(); 14502 this.translateX(index, touchDeltaX + this.positions[index], 0
14502); 14503 } 14504 } else if (this.options.closeOnSwipeUpOrDown) { 14505 this.translateY(index, this.touchDelta.y + this.positions[index], 0); 14506 } 14507 }, 14508 14509 ontouchend: function (event) { 14510 if (this.options.stopTouchEventsPropagation) { 14511 this.stopPropagation(event); 14512 } 14513 var index = this.index, 14514 speed = this.options.transitionSpeed, 14515 slideWidth = this.slideWidth, 14516 isShortDuration = Number(Date.now() - this.touchStart.time) < 250, 14517 // Determine if slide attempt triggers next/prev slide: 14518 isValidSlide = (isShortDuration && Math.abs(this.touchDelta.x) > 20) || 14519 Math.abs(this.touchDelta.x) > slideWidth / 2, 14520 // Determine if slide attempt is past start or end: 14521 isPastBounds = (!index && this.touchDelta.x > 0) || 14522 (index === this.num - 1 && this.touchDelta.x < 0), 14523 isValidClose = !isValidSlide && this.options.closeOnSwipeUpOrDown && 14524 ((isShortDuration && Math.abs(this.touchDelta.y) > 20) || 14525 Math.abs(this.touchDelta.y) > this.slideHeight / 2), 14526 direction, 14527 indexForward, 14528 indexBackward, 14529 distanceForward, 14530 distanceBackward; 14531 if (this.options.continuous) { 14532 isPastBounds = false; 14533 } 14534 // Determine direction of swipe (true: right, false: left): 14535 direction = this.touchDelta.x < 0 ? -1 : 1; 14536 if (!this.isScrolling) { 14537 if (isValidSlide && !isPastBounds) { 14538 indexForward = index + direction; 14539 indexBackward = index - direction; 14540 distanceForward = slideWidth * direction; 14541 distanceBackward = -slideWidth * direction; 14542 if (this.options.continuous) { 14543 this.move(this.circle(indexForward), distanceForward, 0); 14544 this.move(this.circle(index - 2 * direction), distanceBackward, 0); 14545 } else if (indexForward >= 0 && 14546 indexForward < this.num) { 14547 this.move(indexForward, distanceForward, 0); 14548 } 14549 this.move(index, this.positions[index] + distanceForward, speed); 14550 this.move( 14551 this.circle(indexBackward), 14552 this.positions[this.circle(indexBackward)] + distanceForward, 14553 speed 14554 ); 14555 index = this.circle(indexBackward); 14556 this.onslide(index); 14557 } else { 14558 // Move back into position 14559 if (this.options.continuous) { 14560 this.move(this.circle(index - 1), -slideWidth, speed); 14561 this.move(index, 0, speed); 14562 this.move(this.circle(index + 1), slideWidth, speed); 14563 } else { 14564 if (index) { 14565 this.move(index - 1, -slideWidth, speed); 14566 } 14567 this.move(index, 0, speed); 14568 if (index < this.num - 1) { 14569 this.move(index + 1, slideWidth, speed); 14570 } 14571 } 14572 } 14573 } else { 14574 if (isValidClose) { 14575 this.close(); 14576 } else { 14577 // Move back into position 14578 this.translateY(index, 0, speed); 14579 } 14580 } 14581 }, 14582 14583 ontouchcancel: function (event) { 14584 if (this.touchStart) { 14585 this.ontouchend(event); 14586 delete this.touchStart; 14587 } 14588 }, 14589 14590 ontransitionend: function (event) { 14591 var slide = this.slides[this.index]; 14592 if (!event || slide === event.target) { 14593 if (this.interval) { 14594 this.play(); 14595 } 14596 this.setTimeout( 14597 this.options.onslideend, 14598 [this.index, slide] 14599 ); 14600 } 14601 }, 14602 14603 oncomplete: function (event) { 14604 var target = event.target || event.srcElement, 14605 parent = target && target.parentNode, 14606 index; 14607 if (!target || !parent) { 14608 return; 14609 } 14610 index = this.getNodeIndex(parent); 14611 $(parent).removeClass(this.options.slideLoadingClass); 14612 if (event.type === 'error') { 14613 $(parent).addClass(this.options.slideErrorClass); 14614 this.elements[index] = 3; // Fail 14615 } else { 14616 this.elements[index] = 2; // Done 14617 } 14618 // Fix for IE7's lack of support for percentage max-height: 14619 if (target.clientHeight > this.container[0].clientHeight) { 14620 target.style.maxHeight = this.container[0].clientHeight; 14621 } 14622 if (this.interval && this.slides[this.index] === parent) { 14623 this.play(); 14624 } 14625 this.setTimeout( 14626 this.options.onslidecomplete, 14627 [index, parent] 14628 ); 14629 }, 14630 14631 onload: function (event) { 14632 this.oncomplete(event); 14633 }, 14634 14635 onerror: function (event) { 14636 this.oncomplete(event); 14637 }, 14638 14639 onkeydown: function (event) { 14640 switch (event.which || event.keyCode) { 14641 case 13: // Return 14642 if (this.options.toggleControlsOnReturn) { 14643 this.preventDefault(event); 14644 this.toggleControls(); 14645 } 14646 break; 14647 case 27: // Esc 14648 if (this.options.closeOnEscape) { 14649 this.close(); 14650 } 14651 break; 14652 case 32: // Space 14653 if (this.options.toggleSlideshowOnSpace) { 14654 this.preventDefault(event); 14655 this.toggleSlideshow(); 14656 } 14657 break; 14658 case 37: // Left 14659 if (this.options.enableKeyboardNavigation) { 14660 this.preventDefault(event); 14661 this.prev(); 14662 } 14663 break; 14664 case 39: // Right 14665 if (this.options.enableKeyboardNavigation) { 14666 this.preventDefault(event); 14667 this.next(); 14668 } 14669 break; 14670 } 14671 }, 14672 14673 handleClick: function (event) { 14674 var options = this.options, 14675 target = event.target || event.srcElement, 14676 parent = target.parentNode, 14677 isTarget = function (className) { 14678 return $(target).hasClass(className) || 14679 $(parent).hasClass(className); 14680 }; 14681 if (isTarget(options.toggleClass)) { 14682 // Click on "toggle" control 14683 this.preventDefault(event); 14684 this.toggleControls(); 14685 } else if (isTarget(options.prevClass)) { 14686 // Click on "prev" control 14687 this.preventDefault(event); 14688 this.prev(); 14689 } else if (isTarget(options.nextClass)) { 14690 // Click on "next" control 14691 this.preventDefault(event); 14692 this.next(); 14693 } else if (isTarget(options.closeClass)) { 14694 // Click on "close" control 14695 this.preventDefault(event); 14696 this.close(); 14697 } else if (isTarget(options.playPauseClass)) { 14698 // Click on "play-pause" control 14699 this.preventDefault(event); 14700 this.toggleSlideshow(); 14701 } else if (parent === this.slidesContainer[0]) { 14702 // Click on slide background 14703 this.preventDefault(event); 14704 if (options.closeOnSlideClick) { 14705 this.close(); 14706 } else { 14707 this.toggleControls(); 14708 } 14709 } else if (parent.parentNode && 14710 parent.parentNode === this.slidesContainer[0]) { 14711 // Click on displayed element 14712 this.preventDefault(event); 14713 this.toggleControls(); 14714 } 14715 }, 14716 14717 onclick: function (event) { 14718 if (this.options.emulateTouchEvents && 14719 this.touchDelta && (Math.abs(this.touchDelta.x) > 20 || 14720 Math.abs(this.touchDelta.y) >
14720 20)) { 14721 delete this.touchDelta; 14722 return; 14723 } 14724 return this.handleClick(event); 14725 }, 14726 14727 updateEdgeClasses: function (index) { 14728 if (!index) { 14729 this.container.addClass(this.options.leftEdgeClass); 14730 } else { 14731 this.container.removeClass(this.options.leftEdgeClass); 14732 } 14733 if (index === this.num - 1) { 14734 this.container.addClass(this.options.rightEdgeClass); 14735 } else { 14736 this.container.removeClass(this.options.rightEdgeClass); 14737 } 14738 }, 14739 14740 handleSlide: function (index) { 14741 if (!this.options.continuous) { 14742 this.updateEdgeClasses(index); 14743 } 14744 this.loadElements(index); 14745 if (this.options.unloadElements) { 14746 this.unloadElements(index); 14747 } 14748 this.setTitle(index); 14749 }, 14750 14751 onslide: function (index) { 14752 this.index = index; 14753 this.handleSlide(index); 14754 this.setTimeout(this.options.onslide, [index, this.slides[index]]); 14755 }, 14756 14757 setTitle: function (index) { 14758 var text = this.slides[index].firstChild.title, 14759 titleElement = this.titleElement; 14760 if (titleElement.length) { 14761 this.titleElement.empty(); 14762 if (text) { 14763 titleElement[0].appendChild(document.createTextNode(text)); 14764 } 14765 } 14766 }, 14767 14768 setTimeout: function (func, args, wait) { 14769 var that = this; 14770 return func && window.setTimeout(function () { 14771 func.apply(that, args || []); 14772 }, wait || 0); 14773 }, 14774 14775 imageFactory: function (obj, callback) { 14776 var that = this, 14777 img = this.imagePrototype.cloneNode(false), 14778 url = obj, 14779 backgroundSize = this.options.stretchImages, 14780 called, 14781 element, 14782 callbackWrapper = function (event) { 14783 if (!called) { 14784 event = { 14785 type: event.type, 14786 target: element 14787 }; 14788 if (!element.parentNode) { 14789 // Fix for IE7 firing the load event for 14790 // cached images before the element could 14791 // be added to the DOM: 14792 return that.setTimeout(callbackWrapper, [event]); 14793 } 14794 called = true; 14795 $(img).off('load error', callbackWrapper); 14796 if (backgroundSize) { 14797 if (event.type === 'load') { 14798 element.style.background = 'url("' + url + 14799 '") center no-repeat'; 14800 element.style.backgroundSize = backgroundSize; 14801 } 14802 } 14803 callback(event); 14804 } 14805 }, 14806 title; 14807 if (typeof url !== 'string') { 14808 url = this.getItemProperty(obj, this.options.urlProperty); 14809 title = this.getItemProperty(obj, this.options.titleProperty); 14810 } 14811 if (backgroundSize === true) { 14812 backgroundSize = 'contain'; 14813 } 14814 backgroundSize = this.support.backgroundSize && 14815 this.support.backgroundSize[backgroundSize] && backgroundSize; 14816 if (backgroundSize) { 14817 element = this.elementPrototype.cloneNode(false); 14818 } else { 14819 element = img; 14820 img.draggable = false; 14821 } 14822 if (title) { 14823 element.title = title; 14824 } 14825 $(img).on('load error', callbackWrapper); 14826 img.src = url; 14827 return element; 14828 }, 14829 14830 createElement: function (obj, callback) { 14831 var type = obj && this.getItemProperty(obj, this.options.typeProperty), 14832 factory = (type && this[type.split('/')[0] + 'Factory']) || 14833 this.imageFactory, 14834 element = obj && factory.call(this, obj, callback); 14835 if (!element) { 14836 element = this.elementPrototype.cloneNode(false); 14837 this.setTimeout(callback, [{ 14838 type: 'error', 14839 target: element 14840 }]); 14841 } 14842 $(element).addClass(this.options.slideContentClass); 14843 return element; 14844 }, 14845 14846 loadElement: function (index) { 14847 if (!this.elements[index]) { 14848 if (this.slides[index].firstChild) { 14849 this.elements[index] = $(this.slides[index]) 14850 .hasClass(this.options.slideErrorClass) ? 3 : 2; 14851 } else { 14852 this.elements[index] = 1; // Loading 14853 $(this.slides[index]).addClass(this.options.slideLoadingClass); 14854 this.slides[index].appendChild(this.createElement( 14855 this.list[index], 14856 this.proxyListener 14857 )); 14858 } 14859 } 14860 }, 14861 14862 loadElements: function (index) { 14863 var limit = Math.min(this.num, this.options.preloadRange * 2 + 1), 14864 j = index, 14865 i; 14866 for (i = 0; i < limit; i += 1) { 14867 // First load the current slide element (0), 14868 // then the next one (+1), 14869 // then the previous one (-2), 14870 // then the next after next (+2), etc.: 14871 j += i * (i % 2 === 0 ? -1 : 1); 14872 // Connect the ends of the list to load slide elements for 14873 // continuous navigation: 14874 j = this.circle(j); 14875 this.loadElement(j); 14876 } 14877 }, 14878 14879 unloadElements: function (index) { 14880 var i, 14881 slide, 14882 diff; 14883 for (i in this.elements) { 14884 if (this.elements.hasOwnProperty(i)) { 14885 diff = Math.abs(index - i); 14886 if (diff > this.options.preloadRange && 14887 diff + this.options.preloadRange < this.num) { 14888 slide = this.slides[i]; 14889 slide.removeChild(slide.firstChild); 14890 delete this.elements[i]; 14891 } 14892 } 14893 } 14894 }, 14895 14896 addSlide: function (index) { 14897 var slide = this.slidePrototype.cloneNode(false); 14898 slide.setAttribute('data-index', index); 14899 this.slidesContainer[0].appendChild(slide); 14900 this.slides.push(slide); 14901 }, 14902 14903 positionSlide: function (index) { 14904 var slide = this.slides[index]; 14905 slide.style.width = this.slideWidth + 'px'; 14906 if (this.support.transition) { 14907 slide.style.left = (index * -this.slideWidth) + 'px'; 14908 this.move(index, this.index > index ? -this.slideWidth : 14909 (this.index < index ? this.slideWidth : 0), 0); 14910 } 14911 }, 14912 14913 initSlides: function (reload) { 14914 var clearSlides, 14915 i; 14916 if (!reload) { 14917 this.positions = []; 14918 this.positions.length = this.num; 14919 this.elements = {}; 14920 this.imagePrototype = document.createElement('img'); 14921 this.elementPrototype = document.createElement('div'); 14922 this.slidePrototype = document.createElement('div'); 14923 $(this.slidePrototype).addClass(this.options.slideClass); 14924 this.slides = this.slidesContainer[0].children; 14925 clearSlides = this.options.clearSlides || 14926 this.slides.length !== this.num; 14927 } 14928 this.slideWidth = this.container[0].offsetWidth; 14929 this.slideHeight = this.container[0].offsetHeight; 14930 this.slidesContainer[0].style.width = 14931 (this.num * this.slideWidth) + 'px'; 14932 if (clearSlides) { 14933 this.resetSlides(); 14934 } 14935 for (i = 0; i < this.num; i += 1) { 14936 if (clearSlides) { 14937 this.addSlide(i); 14938 } 14939 this.positionSlide(i); 14940 } 14941 // Reposition the slides before and after the given index: 14942 if (this.options.continuous && this.support.transition) { 14943 this.move(this.circle(this.index - 1), -this.slideWidth, 0); 14944 this.move(this.circle(this.index + 1), this.slideWidth, 0); 14945 } 14946 if (!this.support.transition) { 14947 this.slidesContainer[0].style.left = 14948 (this.index * -this.slideWidth) + 'px'; 14949 } 14950 }, 14951 14952 toggleControls: function () { 14953 var controlsClass = this.options.controlsClass; 14954 if (this.container.hasClass(controlsClass)) { 14955 this.container.removeClass(controlsClass); 14956 } else { 14957 this.container.addClass(controlsClass); 14958 } 14959 }, 14960 14961 toggleSlideshow: function () { 14962 if (!this.interval) { 14963 this.play(); 14964 } else { 14965 this.pause(); 14966 } 14967 }, 14968 14969 getNodeIndex: function (element) { 14970 return parseInt(element.getAttribute('data-index'), 10); 14971 }, 14972 14973 getNestedProperty: function (obj, property) { 14974 property.replace( 14975 // Matches native JavaScript notation in a String, 14976 // e.g. '["doubleQuoteProp"].dotProp[2]' 14977 /\[(?:'([^']+)'|"([^"]+)"|(\d+))\]|(?:(?:^|\.)([^\.\[]+))/g, 14978 function (str, singleQuoteProp, doubleQuoteProp, arrayIndex, dotProp) { 14979 var prop = dotProp || singleQuoteProp || doubleQuoteProp || 14980 (arrayIndex && parseInt(arrayIndex, 10)); 14981 if (str && obj) { 14982 obj = obj[prop]; 14983 } 14984 } 14985 ); 14986 return obj; 14987 }, 14988 14989 getDataProperty: function (obj, property) { 14990 if (obj.getAttribute) { 14991 var prop = obj.getAttribute('data-' + 14992 property.replace(/([A-Z])/g, '-$1').toLowerCase()); 14993 if (typeof prop === 'string') { 14994 if (/^(true|false|null|-?\d+(\.\d+)?|\{[\s\S]*\}|\[[\s\S]*\])$/ 14995 .test(prop)) { 14996 try { 14997 return $.parseJSON(prop); 14998 } catch (ignore) {} 14999 } 15000 return prop; 15001 } 15002 } 15003 }, 15004 15005 getItemProperty: function (obj, property) { 15006 var prop = obj[property]; 15007 if (prop === undefined) { 15008 prop = this.getDataProperty(obj, property); 15009 if (prop === undefined) { 15010 prop = this.getNestedProperty(obj, property); 15011 } 15012 } 15013 return prop; 15014 }, 15015 15016 initStartIndex: function () { 15017 var index = this.options.index, 15018 urlProperty = this.options.urlProperty, 15019 i; 15020 // Check if the index is given as a list object: 15021 if (index && typeof index !== 'number') { 15022 for (i = 0; i < this.num; i += 1) { 15023 if (this.list[i] === index || 15024 this.getItemProperty(this.list[i], urlProperty) === 15025 this.getItemProperty(index, urlProperty)) { 15026 index = i; 15027 break; 15028 } 15029 } 15030 } 15031 // Make sure the index is in the list range: 15032 this.index = this.circle(parseInt(index, 10) || 0); 15033 }, 15034 15035 initEventListeners: function () { 15036 var that = this, 15037 slidesContainer = this.slidesContainer, 15038 proxyListener = function (event) { 15039 var type = that.support.transition && 15040 that.support.transition.end === event.type ? 15041 'transitionend' : event.type; 15042 that['on' + type](event); 15043 }; 15044 $(window).on('resize', proxyListener); 15045 $(document.body).on('keydown', proxyListener); 15046 this.container.on('click', proxyListener); 15047 if (this.support.touch) { 15048 slidesContainer 15049 .on('touchstart touchmove touchend touchcancel', proxyListener); 15050 } else if (this.options.emulateTouchEvents && 15051 this.support.transition) { 15052 slidesContainer 15053 .on('mousedown mousemove mouseup mouseout', proxyListener); 15054 } 15055 if (this.support.transition) { 15056 slidesContainer.on( 15057 this.support.transition.end, 15058 proxyListener 15059 ); 15060 } 15061 this.proxyListener = proxyListener; 15062 }, 15063 15064 destroyEventListeners: function () { 15065 var slidesContainer = this.slidesContainer, 15066 proxyListener = this.proxyListener; 15067 $(window).off('resize', proxyListener); 15068 $(document.body).off('keydown', proxyListener); 15069 this.container.off('click', proxyListener); 15070 if (this.support.touch) { 15071 slidesContainer 15072 .off('touchstart touchmove touchend touchcancel', proxyListener); 15073 } else if (this.options.emulateTouchEvents && 15074 this.support.transition) { 15075 slidesContainer 15076 .off('mousedown mousemove mouseup mouseout', proxyListener); 15077 } 15078 if (this.support.transition) { 15079 slidesContainer.off( 15080 this.support.transition.end, 15081 proxyListener 15082 ); 15083 } 15084 }, 15085 15086 handleOpen: function () { 15087 if (this.options.onopened) { 15088 this.options.onopened.call(this); 15089 } 15090 }, 15091 15092 initWidget: function () { 15093 var that = this, 15094 openHandler = function (event) { 15095 if (event.target === that.container[0]) { 15096 that.container.off( 15097 that.support.transition.end, 15098 openHandler 15099 ); 15100 that.handleOpen(); 15101 } 15102 }; 15103 this.container = $(this.options.container); 15104 if (!this.container.length) { 15105 this.console.log( 15106 'blueimp Gallery: Widget container not found.', 15107 this.options.container 15108 ); 15109 return false;
15110 } 15111 this.slidesContainer = this.container.find( 15112 this.options.slidesContainer 15113 ).first(); 15114 if (!this.slidesContainer.length) { 15115 this.console.log( 15116 'blueimp Gallery: Slides container not found.', 15117 this.options.slidesContainer 15118 ); 15119 return false; 15120 } 15121 this.titleElement = this.container.find( 15122 this.options.titleElement 15123 ).first(); 15124 if (this.num === 1) { 15125 this.container.addClass(this.options.singleClass); 15126 } 15127 if (this.options.onopen) { 15128 this.options.onopen.call(this); 15129 } 15130 if (this.support.transition && this.options.displayTransition) { 15131 this.container.on( 15132 this.support.transition.end, 15133 openHandler 15134 ); 15135 } else { 15136 this.handleOpen(); 15137 } 15138 if (this.options.hidePageScrollbars) { 15139 // Hide the page scrollbars: 15140 this.bodyOverflowStyle = document.body.style.overflow; 15141 document.body.style.overflow = 'hidden'; 15142 } 15143 this.container[0].style.display = 'block'; 15144 this.initSlides(); 15145 this.container.addClass(this.options.displayClass); 15146 }, 15147 15148 initOptions: function (options) { 15149 // Create a copy of the prototype options: 15150 this.options = $.extend({}, this.options); 15151 // Check if carousel mode is enabled: 15152 if ((options && options.carousel) || 15153 (this.options.carousel && (!options || options.carousel !== false))) { 15154 $.extend(this.options, this.carouselOptions); 15155 } 15156 // Override any given options: 15157 $.extend(this.options, options); 15158 if (this.num < 3) { 15159 // 1 or 2 slides cannot be displayed continuous, 15160 // remember the original option by setting to null instead of false: 15161 this.options.continuous = this.options.continuous ? null : false; 15162 } 15163 if (!this.support.transition) { 15164 this.options.emulateTouchEvents = false; 15165 } 15166 if (this.options.event) { 15167 this.preventDefault(this.options.event); 15168 } 15169 } 15170 15171 }); 15172 15173 return Gallery; 15174})); 15175 15176/* 15177 * blueimp Gallery Indicator JS 1.1.0 15178 * https://github.com/blueimp/Gallery 15179 * 15180 * Copyright 2013, Sebastian Tschan 15181 * https://blueimp.net 15182 * 15183 * Licensed under the MIT license: 15184 * http://www.opensource.org/licenses/MIT 15185 */ 15186 15187/* global define, window, document */ 15188 15189(function (factory) { 15190 'use strict'; 15191 if (typeof define === 'function' && define.amd) { 15192 // Register as an anonymous AMD module: 15193 define([ 15194 './blueimp-helper', 15195 './blueimp-gallery' 15196 ], factory); 15197 } else { 15198 // Browser globals: 15199 factory( 15200 window.blueimp.helper || window.jQuery, 15201 window.blueimp.Gallery 15202 ); 15203 } 15204}(function ($, Gallery) { 15205 'use strict'; 15206 15207 $.extend(Gallery.prototype.options, { 15208 // The tag name, Id, element or querySelector of the indicator container: 15209 indicatorContainer: 'ol', 15210 // The class for the active indicator: 15211 activeIndicatorClass: 'active', 15212 // The list object property (or data attribute) with the thumbnail URL, 15213 // used as alternative to a thumbnail child element: 15214 thumbnailProperty: 'thumbnail', 15215 // Defines if the gallery indicators should display a thumbnail: 15216 thumbnailIndicators: true 15217 }); 15218 15219 var initSlides = Gallery.prototype.initSlides, 15220 addSlide = Gallery.prototype.addSlide, 15221 resetSlides = Gallery.prototype.resetSlides, 15222 handleClick = Gallery.prototype.handleClick, 15223 handleSlide = Gallery.prototype.handleSlide, 15224 handleClose = Gallery.prototype.handleClose; 15225 15226 $.extend(Gallery.prototype, { 15227 15228 createIndicator: function (obj) { 15229 var indicator = this.indicatorPrototype.cloneNode(false), 15230 title = this.getItemProperty(obj, this.options.titleProperty), 15231 thumbnailProperty = this.options.thumbnailProperty, 15232 thumbnailUrl, 15233 thumbnail; 15234 if (this.options.thumbnailIndicators) { 15235 thumbnail = obj.getElementsByTagName && $(obj).find('img')[0]; 15236 if (thumbnail) { 15237 thumbnailUrl = thumbnail.src; 15238 } else if (thumbnailProperty) { 15239 thumbnailUrl = this.getItemProperty(obj, thumbnailProperty); 15240 } 15241 if (thumbnailUrl) { 15242 indicator.style.backgroundImage = 'url("' + thumbnailUrl + '")'; 15243 } 15244 } 15245 if (title) { 15246 indicator.title = title; 15247 } 15248 return indicator; 15249 }, 15250 15251 addIndicator: function (index) { 15252 if (this.indicatorContainer.length) { 15253 var indicator = this.createIndicator(this.list[index]); 15254 indicator.setAttribute('data-index', index); 15255 this.indicatorContainer[0].appendChild(indicator); 15256 this.indicators.push(indicator); 15257 } 15258 }, 15259
15260 setActiveIndicator: function (index) { 15261 if (this.indicators) { 15262 if (this.activeIndicator) { 15263 this.activeIndicator 15264 .removeClass(this.options.activeIndicatorClass); 15265 } 15266 this.activeIndicator = $(this.indicators[index]); 15267 this.activeIndicator 15268 .addClass(this.options.activeIndicatorClass); 15269 } 15270 }, 15271 15272 initSlides: function (reload) { 15273 if (!reload) { 15274 this.indicatorContainer = this.container.find( 15275 this.options.indicatorContainer 15276 ); 15277 if (this.indicatorContainer.length) { 15278 this.indicatorPrototype = document.createElement('li'); 15279 this.indicators = this.indicatorContainer[0].children; 15280 } 15281 } 15282 initSlides.call(this, reload); 15283 }, 15284 15285 addSlide: function (index) { 15286 addSlide.call(this, index); 15287 this.addIndicator(index); 15288 }, 15289 15290 resetSlides: function () { 15291 resetSlides.call(this); 15292 this.indicatorContainer.empty(); 15293 this.indicators = []; 15294 }, 15295 15296 handleClick: function (event) { 15297 var target = event.target || event.srcElement, 15298 parent = target.parentNode; 15299 if (parent === this.indicatorContainer[0]) { 15300 // Click on indicator element 15301 this.preventDefault(event); 15302 this.slide(this.getNodeIndex(target)); 15303 } else if (parent.parentNode === this.indicatorContainer[0]) { 15304 // Click on indicator child element 15305 this.preventDefault(event); 15306 this.slide(this.getNodeIndex(parent)); 15307 } else { 15308 return handleClick.call(this, event); 15309 } 15310 }, 15311 15312 handleSlide: function (index) { 15313 handleSlide.call(this, index); 15314 this.setActiveIndicator(index); 15315 }, 15316 15317 handleClose: function () { 15318 if (this.activeIndicator) { 15319 this.activeIndicator 15320 .removeClass(this.options.activeIndicatorClass); 15321 } 15322 handleClose.call(this); 15323 } 15324 15325 }); 15326 15327 return Gallery; 15328})); 15329 15330/* 15331 * blueimp Gallery jQuery plugin 1.2.2 15332 * https://github.com/blueimp/Gallery 15333 * 15334 * Copyright 2013, Sebastian Tschan 15335 * https://blueimp.net 15336 * 15337 * Licensed under the MIT license: 15338 * http://www.opensource.org/licenses/MIT 15339 */ 15340 15341/* global define, window, document */ 15342 15343(function (factory) { 15344 'use strict'; 15345 if (typeof define === 'function' && define.amd) { 15346 define([ 15347 'jquery', 15348 './blueimp-gallery' 15349 ], factory); 15350 } else { 15351 factory( 15352 window.jQuery, 15353 window.blueimp.Gallery 15354 ); 15355 } 15356}(function ($, Gallery) { 15357 'use strict'; 15358 15359 // Global click handler to open links with data-gallery attribute 15360 // in the Gallery lightbox: 15361 $(document).on('click', '[data-gallery]', function (event) { 15362 // Get the container id from the data-gallery attribute: 15363 var id = $(this).data('gallery'), 15364 widget = $(id), 15365 container = (widget.length && widget) || 15366 $(Gallery.prototype.options.container), 15367 callbacks = { 15368 onopen: function () { 15369 container 15370 .data('gallery', this) 15371 .trigger('open'); 15372 }, 15373 onopened: function () { 15374 container.trigger('opened'); 15375 }, 15376 onslide: function () { 15377 container.trigger('slide', arguments); 15378 }, 15379 onslideend: function () { 15380 container.trigger('slideend', arguments); 15381 }, 15382 onslidecomplete: function () { 15383 container.trigger('slidecomplete', arguments); 15384 }, 15385 onclose: function () { 15386 container.trigger('close'); 15387 }, 15388 onclosed: function () { 15389 container 15390 .trigger('closed') 15391 .removeData('gallery'); 15392 } 15393 }, 15394 options = $.extend( 15395 // Retrieve custom options from data-attributes 15396 // on the Gallery widget: 15397 container.data(), 15398 { 15399 container: container[0], 15400 index: this, 15401 event: event 15402 }, 15403 callbacks 15404 ), 15405 // Select all links with the same data-gallery attribute: 15406 links = $('[data-gallery="' + id + '"]'); 15407 if (options.filter) { 15408 links = links.filter(options.filter); 15409 } 15410 return new Gallery(links, options); 15411 }); 15412 15413})); 15414 15415/* 15416 * Bootstrap Image Gallery 3.0.1 15417 * https://github.com/blueimp/Bootstrap-Image-Gallery 15418 * 15419 * Copyright 2013, Sebastian Tschan 15420 * https://blueimp.net 15421 * 15422 * Licensed under the MIT license: 15423 * http://www.opensource.org/licenses/MIT 15424 */ 15425 15426/*global define, window */ 15427 15428(function (factory) { 15429 'use strict'; 15430 if (typeof define === 'function' && define.amd) { 15431 define([ 15432 'jquery', 15433 './blueimp-gallery' 15434 ], factory); 15435 } else { 15436 factory( 15437 window.jQuery, 15438 window.blueimp.Gallery 15439 ); 15440 } 15441}(function ($, Gallery) { 15442 'use strict'; 15443 15444 $.extend(Gallery.prototype.options, { 15445 useBootstrapModal: true 15446 }); 15447 15448 var close = Gallery.prototype.close, 15449 imageFactory = Gallery.prototype.imageFactory, 15450 videoFactory = Gallery.prototype.videoFactory, 15451 textFactory = Gallery.prototype.textFactory; 15452 15453 $.extend(Gallery.prototype, { 15454 15455 modalFactory: function (obj, callback, factoryInterface, factory) { 15456 if (!this.options.useBootstrapModal || factoryInterface) { 15457 return factory.call(this, obj, callback, factoryInterface); 15458 } 15459 var that = this, 15460 modalTemplate = this.container.children('.modal'), 15461 modal = modalTemplate.clone().show() 15462 .on('click', function (event) { 15463 // Close modal if click is outside of modal-content: 15464 if (event.target === modal[0] || 15465 event.target === modal.children()[0]) { 15466 event.preventDefault(); 15467 event.stopPropagation(); 15468 that.close(); 15469 } 15470 }), 15471 element = factory.call(this, obj, function (event) { 15472 callback({ 15473 type: event.type, 15474 target: modal[0] 15475 }); 15476 modal.addClass('in'); 15477 }, factoryInterface);
15478 modal.find('.modal-title').text(element.title || String.fromCharCode(160)); 15479 modal.find('.modal-body').append(element); 15480 return modal[0]; 15481 }, 15482 15483 imageFactory: function (obj, callback, factoryInterface) { 15484 return this.modalFactory(obj, callback, factoryInterface, imageFactory); 15485 }, 15486 15487 videoFactory: function (obj, callback, factoryInterface) { 15488 return this.modalFactory(obj, callback, factoryInterface, videoFactory); 15489 }, 15490 15491 textFactory: function (obj, callback, factoryInterface) { 15492 return this.modalFactory(obj, callback, factoryInterface, textFactory); 15493 }, 15494 15495 close: function () { 15496 this.container.find('.modal').removeClass('in'); 15497 close.call(this); 15498 } 15499 15500 }); 15501 15502})); 15503 15504/*! 15505 * typeahead.js 0.10.5 15506 * https://github.com/twitter/typeahead.js 15507 * Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT 15508 */ 15509 15510(function($) { 15511 var _ = function() { 15512 "use strict"; 15513 return { 15514 isMsie: function() { 15515 return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false; 15516 }, 15517 isBlankString: function(str) { 15518 return !str || /^\s*$/.test(str); 15519 }, 15520 escapeRegExChars: function(str) { 15521 return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); 15522 }, 15523 isString: function(obj) { 15524 return typeof obj === "string"; 15525 }, 15526 isNumber: function(obj) { 15527 return typeof obj === "number"; 15528 }, 15529 isArray: $.isArray, 15530 isFunction: $.isFunction, 15531 isObject: $.isPlainObject, 15532 isUndefined: function(obj) { 15533 return typeof obj === "undefined"; 15534 }, 15535 toStr: function toStr(s) { 15536 return _.isUndefined(s) || s === null ? "" : s + ""; 15537 }, 15538 bind: $.proxy, 15539 each: function(collection, cb) { 15540 $.each(collection, reverseArgs); 15541 function reverseArgs(index, value) { 15542 return cb(value, index); 15543 } 15544 }, 15545 map: $.map, 15546 filter: $.grep, 15547 every: function(obj, test) { 15548 var result = true; 15549 if (!obj) { 15550 return result; 15551 } 15552 $.each(obj, function(key, val) { 15553 if (!(result = test.call(null, val, key, obj))) { 15554 return false; 15555 } 15556 }); 15557 return !!result; 15558 }, 15559 some: function(obj, test) { 15560 var result = false;
vendor: 6,556 bytes, lines 15561-15750
15561 if (!obj) { 15562 return result; 15563 } 15564 $.each(obj, function(key, val) { 15565 if (result = test.call(null, val, key, obj)) { 15566 return false; 15567 } 15568 }); 15569 return !!result; 15570 }, 15571 mixin: $.extend, 15572 getUniqueId: function() { 15573 var counter = 0; 15574 return function() { 15575 return counter++; 15576 }; 15577 }(), 15578 templatify: function templatify(obj) { 15579 return $.isFunction(obj) ? obj : template; 15580 function template() { 15581 return String(obj); 15582 } 15583 }, 15584 defer: function(fn) { 15585 setTimeout(fn, 0); 15586 }, 15587 debounce: function(func, wait, immediate) { 15588 var timeout, result; 15589 return function() { 15590 var context = this, args = arguments, later, callNow; 15591 later = function() { 15592 timeout = null; 15593 if (!immediate) { 15594 result = func.apply(context, args); 15595 } 15596 }; 15597 callNow = immediate && !timeout; 15598 clearTimeout(timeout); 15599 timeout = setTimeout(later, wait); 15600 if (callNow) { 15601 result = func.apply(context, args); 15602 } 15603 return result; 15604 }; 15605 }, 15606 throttle: function(func, wait) { 15607 var context, args, timeout, result, previous, later; 15608 previous = 0; 15609 later = function() { 15610 previous = new Date(); 15611 timeout = null; 15612 result = func.apply(context, args); 15613 }; 15614 return function() { 15615 var now = new Date(), remaining = wait - (now - previous); 15616 context = this; 15617 args = arguments; 15618 if (remaining <= 0) { 15619 clearTimeout(timeout); 15620 timeout = null; 15621 previous = now; 15622 result = func.apply(context, args); 15623 } else if (!timeout) { 15624 timeout = setTimeout(later, remaining); 15625 } 15626 return result; 15627 }; 15628 }, 15629 noop: function() {} 15630 }; 15631 }(); 15632 var VERSION = "0.10.5"; 15633 var tokenizers = function() { 15634 "use strict"; 15635 return { 15636 nonword: nonword, 15637 whitespace: whitespace, 15638 obj: { 15639 nonword: getObjTokenizer(nonword), 15640 whitespace: getObjTokenizer(whitespace) 15641 } 15642 }; 15643 function whitespace(str) { 15644 str = _.toStr(str); 15645 return str ? str.split(/\s+/) : []; 15646 } 15647 function nonword(str) { 15648 str = _.toStr(str); 15649 return str ? str.split(/\W+/) : []; 15650 } 15651 function getObjTokenizer(tokenizer) { 15652 return function setKey() { 15653 var args = [].slice.call(arguments, 0); 15654 return function tokenize(o) { 15655 var tokens = []; 15656 _.each(args, function(k) { 15657 tokens = tokens.concat(tokenizer(_.toStr(o[k]))); 15658 }); 15659 return tokens; 15660 }; 15661 }; 15662 } 15663 }(); 15664 var LruCache = function() { 15665 "use strict"; 15666 function LruCache(maxSize) { 15667 this.maxSize = _.isNumber(maxSize) ? maxSize : 100; 15668 this.reset(); 15669 if (this.maxSize <= 0) { 15670 this.set = this.get = $.noop; 15671 } 15672 } 15673 _.mixin(LruCache.prototype, { 15674 set: function set(key, val) { 15675 var tailItem = this.list.tail, node; 15676 if (this.size >= this.maxSize) { 15677 this.list.remove(tailItem); 15678 delete this.hash[tailItem.key]; 15679 } 15680 if (node = this.hash[key]) { 15681 node.val = val; 15682 this.list.moveToFront(node); 15683 } else { 15684 node = new Node(key, val); 15685 this.list.add(node); 15686 this.hash[key] = node; 15687 this.size++; 15688 } 15689 }, 15690 get: function get(key) { 15691 var node = this.hash[key]; 15692 if (node) { 15693 this.list.moveToFront(node); 15694 return node.val; 15695 } 15696 }, 15697 reset: function reset() { 15698 this.size = 0; 15699 this.hash = {}; 15700 this.list = new List(); 15701 } 15702 }); 15703 function List() { 15704 this.head = this.tail = null; 15705 } 15706 _.mixin(List.prototype, { 15707 add: function add(node) { 15708 if (this.head) { 15709 node.next = this.head; 15710 this.head.prev = node; 15711 } 15712 this.head = node; 15713 this.tail = this.tail || node; 15714 }, 15715 remove: function remove(node) { 15716 node.prev ? node.prev.next = node.next : this.head = node.next; 15717 node.next ? node.next.prev = node.prev : this.tail = node.prev; 15718 }, 15719 moveToFront: function(node) { 15720 this.remove(node); 15721 this.add(node); 15722 } 15723 }); 15724 function Node(key, val) { 15725 this.key = key; 15726 this.val = val; 15727 this.prev = this.next = null; 15728 } 15729 return LruCache; 15730 }(); 15731 var PersistentStorage = function() { 15732 "use strict"; 15733 var ls, methods; 15734 try { 15735 ls = window.localStorage; 15736 ls.setItem("~~~", "!"); 15737 ls.removeItem("~~~"); 15738 } catch (err) { 15739 ls = null; 15740 } 15741 function PersistentStorage(namespace) { 15742 this.prefix = [ "__", namespace, "__" ].join(""); 15743 this.ttlKey = "__ttl__"; 15744 this.keyMatcher = new RegExp("^" + _.escapeRegExChars(this.prefix)); 15745 } 15746 if (ls && window.JSON) { 15747 methods = { 15748 _prefix: function(key) { 15749 return this.prefix + key; 15750 },
15751 _ttlKey: function(key) { 15752 return this._prefix(key) + this.ttlKey; 15753 }, 15754 get: function(key) { 15755 if (this.isExpired(key)) { 15756 this.remove(key); 15757 } 15758 return decode(ls.getItem(this._prefix(key))); 15759 }, 15760 set: function(key, val, ttl) { 15761 if (_.isNumber(ttl)) { 15762 ls.setItem(this._ttlKey(key), encode(now() + ttl)); 15763 } else { 15764 ls.removeItem(this._ttlKey(key)); 15765 } 15766 return ls.setItem(this._prefix(key), encode(val)); 15767 }, 15768 remove: function(key) { 15769 ls.removeItem(this._ttlKey(key)); 15770 ls.removeItem(this._prefix(key)); 15771 return this; 15772 }, 15773 clear: function() { 15774 var i, key, keys = [], len = ls.length; 15775 for (i = 0; i < len; i++) { 15776 if ((key = ls.key(i)).match(this.keyMatcher)) { 15777 keys.push(key.replace(this.keyMatcher, "")); 15778 } 15779 } 15780 for (i = keys.length; i--; ) { 15781 this.remove(keys[i]); 15782 } 15783 return this; 15784 }, 15785 isExpired: function(key) { 15786 var ttl = decode(ls.getItem(this._ttlKey(key))); 15787 return _.isNumber(ttl) && now() > ttl ? true : false; 15788 } 15789 }; 15790 } else { 15791 methods = { 15792 get: _.noop, 15793 set: _.noop, 15794 remove: _.noop, 15795 clear: _.noop, 15796 isExpired: _.noop 15797 }; 15798 } 15799 _.mixin(PersistentStorage.prototype, methods); 15800 return PersistentStorage; 15801 function now() { 15802 return new Date().getTime(); 15803 } 15804 function encode(val) { 15805 return JSON.stringify(_.isUndefined(val) ? null : val); 15806 } 15807 function decode(val) { 15808 return JSON.parse(val); 15809 } 15810 }(); 15811 var Transport = function() { 15812 "use strict"; 15813 var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, sharedCache = new LruCache(10); 15814 function Transport(o) { 15815 o = o || {}; 15816 this.cancelled = false; 15817 this.lastUrl = null; 15818 this._send = o.transport ? callbackToDeferred(o.transport) : $.ajax; 15819 this._get = o.rateLimiter ? o.rateLimiter(this._get) : this._get; 15820 this._cache = o.cache === false ? new LruCache(0) : sharedCache; 15821 } 15822 Transport.setMaxPendingRequests = function setMaxPendingRequests(num) { 15823 maxPendingRequests = num; 15824 }; 15825 Transport.resetCache = function resetCache() { 15826 sharedCache.reset(); 15827 }; 15828 _.mixin(Transport.prototype, { 15829 _get: function(url, o, cb) { 15830 var that = this, jqXhr; 15831 if (this.cancelled || url !== this.lastUrl) { 15832 return; 15833 } 15834 if (jqXhr = pendingRequests[url]) { 15835 jqXhr.done(done).fail(fail); 15836 } else if (pendingRequestsCount < maxPendingRequests) { 15837 pendingRequestsCount++; 15838 pendingRequests[url] = this._send(url, o).done(done).fail(fail).always(always); 15839 } else { 15840 this.onDeckRequestArgs = [].slice.call(arguments, 0); 15841 } 15842 function done(resp) { 15843 cb && cb(null, resp); 15844 that._cache.set(url, resp); 15845 } 15846 function fail() { 15847 cb && cb(true); 15848 } 15849 function always() { 15850 pendingRequestsCount--; 15851 delete pendingRequests[url]; 15852 if (that.onDeckRequestArgs) { 15853 that._get.apply(that, that.onDeckRequestArgs); 15854 that.onDeckRequestArgs = null; 15855 } 15856 } 15857 }, 15858 get: function(url, o, cb) { 15859 var resp; 15860 if (_.isFunction(o)) { 15861 cb = o; 15862 o = {}; 15863 } 15864 this.cancelled = false;
15865 this.lastUrl = url; 15866 if (resp = this._cache.get(url)) { 15867 _.defer(function() { 15868 cb && cb(null, resp); 15869 }); 15870 } else { 15871 this._get(url, o, cb); 15872 } 15873 return !!resp; 15874 }, 15875 cancel: function() { 15876 this.cancelled = true; 15877 } 15878 }); 15879 return Transport; 15880 function callbackToDeferred(fn) { 15881 return function customSendWrapper(url, o) { 15882 var deferred = $.Deferred(); 15883 fn(url, o, onSuccess, onError); 15884 return deferred; 15885 function onSuccess(resp) { 15886 _.defer(function() { 15887 deferred.resolve(resp); 15888 }); 15889 } 15890 function onError(err) { 15891 _.defer(function() { 15892 deferred.reject(err); 15893 }); 15894 } 15895 }; 15896 } 15897 }(); 15898 var SearchIndex = function() { 15899 "use strict"; 15900 function SearchIndex(o) { 15901 o = o || {}; 15902 if (!o.datumTokenizer || !o.queryTokenizer) { 15903 $.error("datumTokenizer and queryTokenizer are both required"); 15904 } 15905 this.datumTokenizer = o.datumTokenizer; 15906 this.queryTokenizer = o.queryTokenizer; 15907 this.reset(); 15908 } 15909 _.mixin(SearchIndex.prototype, { 15910 bootstrap: function bootstrap(o) { 15911 this.datums = o.datums; 15912 this.trie = o.trie; 15913 }, 15914 add: function(data) { 15915 var that = this; 15916 data = _.isArray(data) ? data : [ data ]; 15917 _.each(data, function(datum) { 15918 var id, tokens; 15919 id = that.datums.push(datum) - 1; 15920 tokens = normalizeTokens(that.datumTokenizer(datum)); 15921 _.each(tokens, function(token) { 15922 var node, chars, ch; 15923 node = that.trie; 15924 chars = token.split(""); 15925 while (ch = chars.shift()) { 15926 node = node.children[ch] || (node.children[ch] = newNode()); 15927 node.ids.push(id); 15928 } 15929 }); 15930 }); 15931 }, 15932 get: function get(query) { 15933 var that = this, tokens, matches; 15934 tokens = normalizeTokens(this.queryTokenizer(query)); 15935 _.each(tokens, function(token) { 15936 var node, chars, ch, ids; 15937 if (matches && matches.length === 0) { 15938 return false; 15939 } 15940 node = that.trie; 15941 chars = token.split(""); 15942 while (node && (ch = chars.shift())) { 15943 node = node.children[ch]; 15944 } 15945 if (node && chars.length === 0) { 15946 ids = node.ids.slice(0); 15947 matches = matches ? getIntersection(matches, ids) : ids; 15948 } else { 15949 matches = []; 15950 return false; 15951 } 15952 }); 15953 return matches ? _.map(unique(matches), function(id) { 15954 return that.datums[id]; 15955 }) : []; 15956 }, 15957 reset: function reset() { 15958 this.datums = []; 15959 this.trie = newNode(); 15960 }, 15961 serialize: function serialize() { 15962 return { 15963 datums: this.datums, 15964 trie: this.trie 15965 }; 15966 } 15967 }); 15968 return SearchIndex; 15969 function normalizeTokens(tokens) { 15970 tokens = _.filter(tokens, function(token) { 15971 return !!token; 15972 }); 15973 tokens = _.map(tokens, function(token) { 15974 return token.toLowerCase(); 15975 }); 15976 return tokens; 15977 } 15978 function newNode() { 15979 return { 15980 ids: [], 15981 children: {} 15982 }; 15983 } 15984 function unique(array) { 15985 var seen = {}, uniques = []; 15986 for (var i = 0, len = array.length; i < len; i++) { 15987 if (!seen[array[i]]) { 15988 seen[array[i]] = true; 15989 uniques.push(array[i]); 15990 } 15991 } 15992 return uniques; 15993 } 15994 function getIntersection(arrayA, arrayB) { 15995 var ai = 0, bi = 0, intersection = []; 15996 arrayA = arrayA.sort(compare); 15997 arrayB = arrayB.sort(compare); 15998 var lenArrayA = arrayA.length, lenArrayB = arrayB.length; 15999 while (ai < lenArrayA && bi < lenArrayB) { 16000 if (arrayA[ai] < arrayB[bi]) { 16001 ai++; 16002 } else if (arrayA[ai] > arrayB[bi]) { 16003 bi++; 16004 } else { 16005 intersection.push(arrayA[ai]); 16006 ai++; 16007 bi++; 16008 } 16009 } 16010 return intersection; 16011 function compare(a, b) { 16012 return a - b; 16013 } 16014 } 16015 }(); 16016 var oParser = function() { 16017 "use strict"; 16018 return { 16019 local: getLocal, 16020 prefetch: getPrefetch, 16021 remote: getRemote 16022 }; 16023 function getLocal(o) { 16024 return o.local || null; 16025 } 16026 function getPrefetch(o) { 16027 var prefetch, defaults; 16028 defaults = { 16029 url: null, 16030 thumbprint: "", 16031 ttl: 24 * 60 * 60 * 1e3, 16032 filter: null, 16033 ajax: {} 16034 }; 16035 if (prefetch = o.prefetch || null) { 16036 prefetch = _.isString(prefetch) ? { 16037 url: prefetch 16038 } : prefetch; 16039 prefetch = _.mixin(defaults, prefetch); 16040 prefetch.thumbprint = VERSION + prefetch.thumbprint; 16041 prefetch.ajax.type = prefetch.ajax.type || "GET"; 16042 prefetch.ajax.dataType = prefetch.ajax.dataType || "json"; 16043 !prefetch.url && $.error("prefetch requires url to be set"); 16044 } 16045 return prefetch; 16046 } 16047 function getRemote(o) { 16048 var remote, defaults; 16049 defaults = { 16050 url: null, 16051 cache: true, 16052 wildcard: "%QUERY", 16053 replace: null, 16054 rateLimitBy: "debounce", 16055 rateLimitWait: 300, 16056 send: null, 16057 filter: null, 16058 ajax: {} 16059 }; 16060 if (remote = o.remote || null) { 16061 remote = _.isString(remote) ? { 16062 url: remote 16063 } : remote; 16064 remote = _.mixin(defaults, remote); 16065 remote.rateLimiter = /^throttle$/i.test(remote.rateLimitBy) ? byThrottle(remote.rateLimitWait) : byDebounce(remote.rateLimitWait); 16066 remote.ajax.type = remote.ajax.type || "GET"; 16067 remote.ajax.dataType = remote.ajax.dataType || "json"; 16068 delete remote.rateLimitBy; 16069 delete remote.rateLimitWait; 16070 !remote.url && $.error("remote requires url to be set"); 16071 } 16072 return remote; 16073 function byDebounce(wait) { 16074 return function(fn) { 16075 return _.debounce(fn, wait); 16076 }; 16077 } 16078 function byThrottle(wait) { 16079 return function(fn) { 16080 return _.throttle(fn, wait); 16081 }; 16082 } 16083 } 16084 }(); 16085 (function(root) { 16086 "use strict"; 16087 var old, keys; 16088 old = root.Bloodhound; 16089 keys = { 16090 data: "data", 16091 protocol: "protocol", 16092 thumbprint: "thumbprint" 16093 }; 16094 root.Bloodhound = Bloodhound; 16095 function Bloodhound(o) { 16096 if (!o || !o.local && !o.prefetch && !o.remote) { 16097 $.error("one of local, prefetch, or remote is required"); 16098 } 16099 this.limit = o.limit || 5; 16100 this.sorter = getSorter(o.sorter); 16101 this.dupDetector = o.dupDetector || ignoreDuplicates; 16102 this.local = oParser.local(o); 16103 this.prefetch = oParser.prefetch(o); 16104 this.remote = oParser.remote(o); 16105 this.cacheKey = this.prefetch ? this.prefetch.cacheKey || this.prefetch.url : null; 16106 this.index = new SearchIndex({ 16107 datumTokenizer: o.datumTokenizer, 16108 queryTokenizer: o.queryTokenizer 16109 }); 16110 this.storage = this.cacheKey ? new PersistentStorage(this.cacheKey) : null; 16111 } 16112 Bloodhound.noConflict = function noConflict() { 16113 root.Bloodhound = old; 16114 return Bloodhound; 16115 }; 16116 Bloodhound.tokenizers = tokenizers; 16117 _.mixin(Bloodhound.prototype, { 16118 _loadPrefetch: function loadPrefetch(o) { 16119 var that = this, serialized, deferred; 16120 if (serialized = this._readFromStorage(o.thumbprint)) { 16121 this.index.bootstrap(serialized); 16122 deferred = $.Deferred().resolve(); 16123 } else { 16124 deferred = $.ajax(o.url, o.ajax).done(handlePrefetchResponse); 16125 } 16126 return deferred; 16127 function handlePrefetchResponse(resp) { 16128 that.clear(); 16129 that.add(o.filter ? o.filter(resp) : resp); 16130 that._saveToStorage(that.index.serialize(), o.thumbprint, o.ttl); 16131 } 16132 }, 16133 _getFromRemote: function getFromRemote(query, cb) { 16134 var that = this, url, uriEncodedQuery; 16135 if (!this.transport) { 16136 return; 16137 } 16138 query = query || ""; 16139 uriEncodedQuery = encodeURIComponent(query); 16140 url = this.remote.replace ? this.remote.replace(this.remote.url, query) : this.remote.url.replace(this.remote.wildcard, uriEncodedQuery); 16141 return this.transport.get(url, this.remote.ajax, handleRemoteResponse); 16142 function handleRemoteResponse(err, resp) { 16143 err ? cb([]) : cb(that.remote.filter ? that.remote.filter(resp) : resp); 16144 } 16145 }, 16146 _cancelLastRemoteRequest: function cancelLastRemoteRequest() { 16147 this.transport && this.transport.cancel(); 16148 }, 16149 _saveToStorage: function saveToStorage(data, thumbprint, ttl) { 16150 if (this.storage) { 16151 this.storage.set(keys.data, data, ttl); 16152 this.storage.set(keys.protocol, location.protocol, ttl); 16153 this.storage.set(keys.thumbprint, thumbprint, ttl); 16154 } 16155 }, 16156 _readFromStorage: function readFromStorage(thumbprint) { 16157 var stored = {}, isExpired; 16158 if (this.storage) { 16159 stored.data = this.storage.get(keys.data); 16160 stored.protocol = this.storage.get(keys.protocol); 16161 stored.thumbprint = this.storage.get(keys.thumbprint); 16162 } 16163 isExpired = stored.thumbprint !== thumbprint || stored.protocol !== location.protocol; 16164 return stored.data && !isExpired ? stored.data : null; 16165 }, 16166 _initialize: function initialize() { 16167 var that = this, local = this.local, deferred; 16168 deferred = this.prefetch ? this._loadPrefetch(this.prefetch) : $.Deferred().resolve(); 16169 local && deferred.done(addLocalToIndex); 16170 this.transport = this.remote ? new Transport(this.remote) : null; 16171 return this.initPromise = deferred.promise(); 16172 function addLocalToIndex() { 16173 that.add(_.isFunction(local) ? local() : local); 16174 } 16175 }, 16176 initialize: function initialize(force) { 16177 return !this.initPromise || force ? this._initialize() : this.initPromise; 16178 }, 16179 add: function add(data) { 16180 this.index.add(data); 16181 }, 16182 get: function get(query, cb) { 16183 var that = this, matches = [], cacheHit = false;
16184 matches = this.index.get(query); 16185 matches = this.sorter(matches).slice(0, this.limit); 16186 matches.length < this.limit ? cacheHit = this._getFromRemote(query, returnRemoteMatches) : this._cancelLastRemoteRequest(); 16187 if (!cacheHit) { 16188 (matches.length > 0 || !this.transport) && cb && cb(matches); 16189 } 16190 function returnRemoteMatches(remoteMatches) { 16191 var matchesWithBackfill = matches.slice(0); 16192 _.each(remoteMatches, function(remoteMatch) { 16193 var isDuplicate; 16194 isDuplicate = _.some(matchesWithBackfill, function(match) { 16195 return that.dupDetector(remoteMatch, match); 16196 }); 16197 !isDuplicate && matchesWithBackfill.push(remoteMatch); 16198 return matchesWithBackfill.length < that.limit; 16199 }); 16200 cb && cb(that.sorter(matchesWithBackfill)); 16201 } 16202 }, 16203 clear: function clear() { 16204 this.index.reset(); 16205 }, 16206 clearPrefetchCache: function clearPrefetchCache() { 16207 this.storage && this.storage.clear(); 16208 }, 16209 clearRemoteCache: function clearRemoteCache() { 16210 this.transport && Transport.resetCache(); 16211 },
16212 ttAdapter: function ttAdapter() { 16213 return _.bind(this.get, this); 16214 } 16215 }); 16216 return Bloodhound; 16217 function getSorter(sortFn) { 16218 return _.isFunction(sortFn) ? sort : noSort; 16219 function sort(array) { 16220 return array.sort(sortFn); 16221 } 16222 function noSort(array) { 16223 return array; 16224 } 16225 } 16226 function ignoreDuplicates() { 16227 return false; 16228 } 16229 })(this); 16230})(window.jQuery); 16231/*! 16232 16233 handlebars v2.0.0 16234 16235Copyright (C) 2011-2014 by Yehuda Katz 16236 16237Permission is hereby granted, free of charge, to any person obtaining a copy 16238of this software and associated documentation files (the "Software"), to deal 16239in the Software without restriction, including without limitation the rights 16240to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16241copies of the Software, and to permit persons to whom the Software is 16242furnished to do so, subject to the following conditions: 16243 16244The above copyright notice and this permission notice shall be included in 16245all copies or substantial portions of the Software. 16246 16247THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16248IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16249FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16250AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16251LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16252OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 16253THE SOFTWARE. 16254 16255@license 16256*/ 16257/* exported Handlebars */ 16258(function (root, factory) { 16259 if (typeof define === 'function' && define.amd) { 16260 define([], factory); 16261 } else if (typeof exports === 'object') { 16262 module.exports = factory(); 16263 } else { 16264 root.Handlebars = root.Handlebars || factory(); 16265 } 16266}(this, function () {
16267// handlebars/safe-string.js 16268var __module4__ = (function() { 16269 "use strict"; 16270 var __exports__; 16271 // Build out our basic SafeString type 16272 function SafeString(string) { 16273 this.string = string; 16274 } 16275 16276 SafeString.prototype.toString = function() { 16277 return "" + this.string; 16278 }; 16279 16280 __exports__ = SafeString; 16281 return __exports__; 16282})(); 16283
16284// handlebars/utils.js 16285var __module3__ = (function(__dependency1__) { 16286 "use strict"; 16287 var __exports__ = {}; 16288 /*jshint -W004 */ 16289 var SafeString = __dependency1__; 16290 16291 var escape = { 16292 "&": "&", 16293 "<": "<", 16294 ">": ">", 16295 '"': """, 16296 "'": "'", 16297 "`": "`" 16298 }; 16299 16300 var badChars = /[&<>"'`]/g; 16301 var possible = /[&<>"'`]/; 16302 16303 function escapeChar(chr) { 16304 return escape[chr]; 16305 } 16306 16307 function extend(obj /* , ...source */) { 16308 for (var i = 1; i < arguments.length; i++) { 16309 for (var key in arguments[i]) { 16310 if (Object.prototype.hasOwnProperty.call(arguments[i], key)) { 16311 obj[key] = arguments[i][key]; 16312 } 16313 } 16314 } 16315 16316 return obj; 16317 } 16318 16319 __exports__.extend = extend;var toString = Object.prototype.toString; 16320 __exports__.toString = toString; 16321 // Sourced from lodash 16322 // https://github.com/bestiejs/lodash/blob/master/LICENSE.txt 16323 var isFunction = function(value) { 16324 return typeof value === 'function'; 16325 }; 16326 // fallback for older versions of Chrome and Safari 16327 /* istanbul ignore next */ 16328 if (isFunction(/x/)) { 16329 isFunction = function(value) { 16330 return typeof value === 'function' && toString.call(value) === '[object Function]'; 16331 }; 16332 } 16333 var isFunction; 16334 __exports__.isFunction = isFunction; 16335 /* istanbul ignore next */ 16336 var isArray = Array.isArray || function(value) { 16337 return (value && typeof value === 'object') ? toString.call(value) === '[object Array]' : false; 16338 }; 16339 __exports__.isArray = isArray; 16340 16341 function escapeExpression(string) { 16342 // don't escape SafeStrings, since they're already safe 16343 if (string instanceof SafeString) { 16344 return string.toString(); 16345 } else if (string == null) { 16346 return ""; 16347 } else if (!string) { 16348 return string + ''; 16349 } 16350 16351 // Force a string conversion as this will be done by the append regardless and 16352 // the regex test will do this transparently behind the scenes, causing issues if 16353 // an object's to string has escaped characters in it. 16354 string = "" + string; 16355 16356 if(!possible.test(string)) { return string; } 16357 return string.replace(badChars, escapeChar); 16358 } 16359 16360 __exports__.escapeExpression = escapeExpression;function isEmpty(value) { 16361 if (!value && value !== 0) { 16362 return true; 16363 } else if (isArray(value) && value.length === 0) { 16364 return true; 16365 } else { 16366 return false; 16367 } 16368 } 16369 16370 __exports__.isEmpty = isEmpty;function appendContextPath(contextPath, id) { 16371 return (contextPath ? contextPath + '.' : '') + id; 16372 } 16373 16374 __exports__.appendContextPath = appendContextPath; 16375 return __exports__; 16376})(__module4__); 16377
16378// handlebars/exception.js 16379var __module5__ = (function() { 16380 "use strict"; 16381 var __exports__; 16382 16383 var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack']; 16384 16385 function Exception(message, node) { 16386 var line; 16387 if (node && node.firstLine) { 16388 line = node.firstLine; 16389 16390 message += ' - ' + line + ':' + node.firstColumn; 16391 } 16392 16393 var tmp = Error.prototype.constructor.call(this, message); 16394 16395 // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work. 16396 for (var idx = 0; idx < errorProps.length; idx++) { 16397 this[errorProps[idx]] = tmp[errorProps[idx]]; 16398 } 16399 16400 if (line) { 16401 this.lineNumber = line; 16402 this.column = node.firstColumn; 16403 } 16404 } 16405 16406 Exception.prototype = new Error(); 16407 16408 __exports__ = Exception; 16409 return __exports__; 16410})(); 16411
16412// handlebars/base.js 16413var __module2__ = (function(__dependency1__, __dependency2__) { 16414 "use strict"; 16415 var __exports__ = {}; 16416 var Utils = __dependency1__; 16417 var Exception = __dependency2__; 16418 16419 var VERSION = "2.0.0"; 16420 __exports__.VERSION = VERSION;var COMPILER_REVISION = 6; 16421 __exports__.COMPILER_REVISION = COMPILER_REVISION; 16422 var REVISION_CHANGES = { 16423 1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it 16424 2: '== 1.0.0-rc.3', 16425 3: '== 1.0.0-rc.4', 16426 4: '== 1.x.x', 16427 5: '== 2.0.0-alpha.x', 16428 6: '>= 2.0.0-beta.1' 16429 }; 16430 __exports__.REVISION_CHANGES = REVISION_CHANGES; 16431 var isArray = Utils.isArray, 16432 isFunction = Utils.isFunction, 16433 toString = Utils.toString, 16434 objectType = '[object Object]'; 16435 16436 function HandlebarsEnvironment(helpers, partials) { 16437 this.helpers = helpers || {}; 16438 this.partials = partials || {}; 16439 16440 registerDefaultHelpers(this); 16441 } 16442 16443 __exports__.HandlebarsEnvironment = HandlebarsEnvironment;HandlebarsEnvironment.prototype = { 16444 constructor: HandlebarsEnvironment, 16445 16446 logger: logger, 16447 log: log, 16448 16449 registerHelper: function(name, fn) { 16450 if (toString.call(name) === objectType) { 16451 if (fn) { throw new Exception('Arg not supported with multiple helpers'); } 16452 Utils.extend(this.helpers, name); 16453 } else { 16454 this.helpers[name] = fn; 16455 } 16456 }, 16457 unregisterHelper: function(name) { 16458 delete this.helpers[name]; 16459 }, 16460 16461 registerPartial: function(name, partial) { 16462 if (toString.call(name) === objectType) { 16463 Utils.extend(this.partials, name); 16464 } else { 16465 this.partials[name] = partial; 16466 } 16467 }, 16468 unregisterPartial: function(name) { 16469 delete this.partials[name]; 16470 } 16471 }; 16472 16473 function registerDefaultHelpers(instance) { 16474 instance.registerHelper('helperMissing', function(/* [args, ]options */) { 16475 if(arguments.length === 1) { 16476 // A missing field in a {{foo}} constuct. 16477 return undefined; 16478 } else { 16479 // Someone is actually trying to call something, blow up. 16480 throw new Exception("Missing helper: '" + arguments[arguments.length-1].name + "'"); 16481 } 16482 }); 16483 16484 instance.registerHelper('blockHelperMissing', function(context, options) { 16485 var inverse = options.inverse, 16486 fn = options.fn; 16487 16488 if(context === true) { 16489 return fn(this); 16490 } else if(context === false || context == null) { 16491 return inverse(this); 16492 } else if (isArray(context)) { 16493 if(context.length > 0) { 16494 if (options.ids) { 16495 options.ids = [options.name]; 16496 } 16497 16498 return instance.helpers.each(context, options); 16499 } else { 16500 return inverse(this); 16501 } 16502 } else { 16503 if (options.data && options.ids) { 16504 var data = createFrame(options.data); 16505 data.contextPath = Utils.appendContextPath(options.data.contextPath, options.name); 16506 options = {data: data}; 16507 } 16508 16509 return fn(context, options); 16510 } 16511 }); 16512 16513 instance.registerHelper('each', function(context, options) { 16514 if (!options) { 16515 throw new Exception('Must pass iterator to #each'); 16516 } 16517 16518 var fn = options.fn, inverse = options.inverse; 16519 var i = 0, ret = "", data; 16520 16521 var contextPath; 16522 if (options.data && options.ids) { 16523 contextPath = Utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.'; 16524 } 16525 16526 if (isFunction(context)) { context = context.call(this); } 16527 16528 if (options.data) { 16529 data = createFrame(options.data); 16530 } 16531 16532 if(context && typeof context === 'object') { 16533 if (isArray(context)) { 16534 for(var j = context.length; i<j; i++) { 16535 if (data) { 16536 data.index = i; 16537 data.first = (i === 0); 16538 data.last = (i === (context.length-1)); 16539 16540 if (contextPath) { 16541 data.contextPath = contextPath + i; 16542 } 16543 } 16544 ret = ret + fn(context[i], { data: data }); 16545 } 16546 } else { 16547 for(var key in context) { 16548 if(context.hasOwnProperty(key)) { 16549 if(data) { 16550 data.key = key; 16551 data.index = i; 16552 data.first = (i === 0); 16553 16554 if (contextPath) { 16555 data.contextPath = contextPath + key; 16556 } 16557 } 16558 ret = ret + fn(context[key], {data: data}); 16559 i++; 16560 } 16561 } 16562 } 16563 } 16564 16565 if(i === 0){ 16566 ret = inverse(this); 16567 } 16568 16569 return ret; 16570 }); 16571 16572 instance.registerHelper('if', function(conditional, options) { 16573 if (isFunction(conditional)) { conditional = conditional.call(this); } 16574 16575 // Default behavior is to render the positive path if the value is truthy and not empty. 16576 // The `includeZero` option may be set to treat the condtional as purely not empty based on the 16577 // behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative. 16578 if ((!options.hash.includeZero && !conditional) || Utils.isEmpty(conditional)) { 16579 return options.inverse(this); 16580 } else { 16581 return options.fn(this); 16582 } 16583 }); 16584 16585 instance.registerHelper('unless', function(conditional, options) { 16586 return instance.helpers['if'].call(this, conditional, {fn: options.inverse, inverse: options.fn, hash: options.hash}); 16587 }); 16588 16589 instance.registerHelper('with', function(context, options) { 16590 if (isFunction(context)) { context = context.call(this); } 16591 16592 var fn = options.fn; 16593 16594 if (!Utils.isEmpty(context)) { 16595 if (options.data && options.ids) { 16596 var data = createFrame(options.data); 16597 data.contextPath = Utils.appendContextPath(options.data.contextPath, options.ids[0]); 16598 options = {data:data}; 16599 } 16600 16601 return fn(context, options); 16602 } else { 16603 return options.inverse(this); 16604 } 16605 }); 16606 16607 instance.registerHelper('log', function(message, options) { 16608 var level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1; 16609 instance.log(level, message); 16610 }); 16611 16612 instance.registerHelper('lookup', function(obj, field) { 16613 return obj && obj[field]; 16614 }); 16615 } 16616 16617 var logger = {
16618 methodMap: { 0: 'debug', 1: 'info', 2: 'warn', 3: 'error' }, 16619 16620 // State enum 16621 DEBUG: 0, 16622 INFO: 1, 16623 WARN: 2, 16624 ERROR: 3, 16625 level: 3, 16626 16627 // can be overridden in the host environment 16628 log: function(level, message) { 16629 if (logger.level <= level) { 16630 var method = logger.methodMap[level]; 16631 if (typeof console !== 'undefined' && console[method]) { 16632 console[method].call(console, message); 16633 } 16634 } 16635 } 16636 }; 16637 __exports__.logger = logger; 16638 var log = logger.log; 16639 __exports__.log = log; 16640 var createFrame = function(object) { 16641 var frame = Utils.extend({}, object); 16642 frame._parent = object; 16643 return frame; 16644 }; 16645 __exports__.createFrame = createFrame; 16646 return __exports__; 16647})(__module3__, __module5__); 16648
16649// handlebars/runtime.js 16650var __module6__ = (function(__dependency1__, __dependency2__, __dependency3__) { 16651 "use strict"; 16652 var __exports__ = {}; 16653 var Utils = __dependency1__; 16654 var Exception = __dependency2__; 16655 var COMPILER_REVISION = __dependency3__.COMPILER_REVISION; 16656 var REVISION_CHANGES = __dependency3__.REVISION_CHANGES; 16657 var createFrame = __dependency3__.createFrame; 16658 16659 function checkRevision(compilerInfo) { 16660 var compilerRevision = compilerInfo && compilerInfo[0] || 1, 16661 currentRevision = COMPILER_REVISION; 16662 16663 if (compilerRevision !== currentRevision) { 16664 if (compilerRevision < currentRevision) { 16665 var runtimeVersions = REVISION_CHANGES[currentRevision], 16666 compilerVersions = REVISION_CHANGES[compilerRevision]; 16667 throw new Exception("Template was precompiled with an older version of Handlebars than the current runtime. "+ 16668 "Please update your precompiler to a newer version ("+runtimeVersions+") or downgrade your runtime to an older version ("+compilerVersions+")."); 16669 } else { 16670 // Use the embedded version info since the runtime doesn't know about this revision yet 16671 throw new Exception("Template was precompiled with a newer version of Handlebars than the current runtime. "+ 16672 "Please update your runtime to a newer version ("+compilerInfo[1]+")."); 16673 } 16674 } 16675 } 16676 16677 __exports__.checkRevision = checkRevision;// TODO: Remove this line and break up compilePartial 16678 16679 function template(templateSpec, env) { 16680 /* istanbul ignore next */ 16681 if (!env) { 16682 throw new Exception("No environment passed to template"); 16683 } 16684 if (!templateSpec || !templateSpec.main) { 16685 throw new Exception('Unknown template object: ' + typeof templateSpec); 16686 } 16687 16688 // Note: Using env.VM references rather than local var references throughout this section to allow 16689 // for external users to override these as psuedo-supported APIs. 16690 env.VM.checkRevision(templateSpec.compiler); 16691 16692 var invokePartialWrapper = function(partial, indent, name, context, hash, helpers, partials, data, depths) { 16693 if (hash) { 16694 context = Utils.extend({}, context, hash); 16695 } 16696 16697 var result = env.VM.invokePartial.call(this, partial, name, context, helpers, partials, data, depths); 16698 16699 if (result == null && env.compile) { 16700 var options = { helpers: helpers, partials: partials, data: data, depths: depths }; 16701 partials[name] = env.compile(partial, { data: data !== undefined, compat: templateSpec.compat }, env); 16702 result = partials[name](context, options); 16703 } 16704 if (result != null) { 16705 if (indent) { 16706 var lines = result.split('\n'); 16707 for (var i = 0, l = lines.length; i < l; i++) { 16708 if (!lines[i] && i + 1 === l) { 16709 break; 16710 } 16711 16712 lines[i] = indent + lines[i]; 16713 } 16714 result = lines.join('\n'); 16715 } 16716 return result; 16717 } else { 16718 throw new Exception("The partial " + name + " could not be compiled when running in runtime-only mode"); 16719 } 16720 }; 16721 16722 // Just add water 16723 var container = { 16724 lookup: function(depths, name) { 16725 var len = depths.length; 16726 for (var i = 0; i < len; i++) { 16727 if (depths[i] && depths[i][name] != null) { 16728 return depths[i][name]; 16729 } 16730 } 16731 }, 16732 lambda: function(current, context) { 16733 return typeof current === 'function' ? current.call(context) : current; 16734 }, 16735 16736 escapeExpression: Utils.escapeExpression, 16737 invokePartial: invokePartialWrapper, 16738 16739 fn: function(i) { 16740 return templateSpec[i]; 16741 }, 16742 16743 programs: [], 16744 program: function(i, data, depths) { 16745 var programWrapper = this.programs[i], 16746 fn = this.fn(i); 16747 if (data || depths) { 16748 programWrapper = program(this, i, fn, data, depths); 16749 } else if (!programWrapper) { 16750 programWrapper = this.programs[i] = program(this, i, fn); 16751 } 16752 return programWrapper; 16753 }, 16754 16755 data: function(data, depth) { 16756 while (data && depth--) { 16757 data = data._parent; 16758 } 16759 return data; 16760 }, 16761 merge: function(param, common) { 16762 var ret = param || common; 16763 16764 if (param && common && (param !== common)) { 16765 ret = Utils.extend({}, common, param); 16766 } 16767 16768 return ret; 16769 }, 16770 16771 noop: env.VM.noop, 16772 compilerInfo: templateSpec.compiler 16773 }; 16774 16775 var ret = function(context, options) { 16776 options = options || {}; 16777 var data = options.data; 16778 16779 ret._setup(options); 16780 if (!options.partial && templateSpec.useData) { 16781 data = initData(context, data); 16782 } 16783 var depths; 16784 if (templateSpec.useDepths) { 16785 depths = options.depths ? [context].concat(options.depths) : [context]; 16786 } 16787 16788 return templateSpec.main.call(container, context, container.helpers, container.partials, data, depths); 16789 }; 16790 ret.isTop = true; 16791 16792 ret._setup = function(options) { 16793 if (!options.partial) { 16794 container.helpers = container.merge(options.helpers, env.helpers); 16795 16796 if (templateSpec.usePartial) { 16797 container.partials = container.merge(options.partials, env.partials); 16798 } 16799 } else { 16800 container.helpers = options.helpers; 16801 container.partials = options.partials; 16802 } 16803 }; 16804 16805 ret._child = function(i, data, depths) { 16806 if (templateSpec.useDepths && !depths) { 16807 throw new Exception('must pass parent depths'); 16808 } 16809 16810 return program(container, i, templateSpec[i], data, depths); 16811 }; 16812 return ret; 16813 } 16814 16815 __exports__.template = template;function program(container, i, fn, data, depths) { 16816 var prog = function(context, options) { 16817 options = options || {}; 16818
16819 return fn.call(container, context, container.helpers, container.partials, options.data || data, depths && [context].concat(depths)); 16820 }; 16821 prog.program = i; 16822 prog.depth = depths ? depths.length : 0; 16823 return prog; 16824 } 16825 16826 __exports__.program = program;function invokePartial(partial, name, context, helpers, partials, data, depths) { 16827 var options = { partial: true, helpers: helpers, partials: partials, data: data, depths: depths }; 16828 16829 if(partial === undefined) { 16830 throw new Exception("The partial " + name + " could not be found"); 16831 } else if(partial instanceof Function) { 16832 return partial(context, options); 16833 } 16834 } 16835 16836 __exports__.invokePartial = invokePartial;function noop() { return ""; } 16837 16838 __exports__.noop = noop;function initData(context, data) { 16839 if (!data || !('root' in data)) { 16840 data = data ? createFrame(data) : {}; 16841 data.root = context; 16842 } 16843 return data; 16844 } 16845 return __exports__; 16846})(__module3__, __module5__, __module2__); 16847 16848// handlebars.runtime.js 16849var __module1__ = (function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__) { 16850 "use strict"; 16851 var __exports__; 16852 /*globals Handlebars: true */ 16853 var base = __dependency1__; 16854 16855 // Each of these augment the Handlebars object. No need to setup here. 16856 // (This is done to easily share code between commonjs and browse envs) 16857 var SafeString = __dependency2__; 16858 var Exception = __dependency3__; 16859 var Utils = __dependency4__; 16860 var runtime = __dependency5__; 16861 16862 // For compatibility and usage outside of module systems, make the Handlebars object a namespace 16863 var create = function() { 16864 var hb = new base.HandlebarsEnvironment(); 16865 16866 Utils.extend(hb, base); 16867 hb.SafeString = SafeString; 16868 hb.Exception = Exception; 16869 hb.Utils = Utils; 16870 hb.escapeExpression = Utils.escapeExpression; 16871 16872 hb.VM = runtime; 16873 hb.template = function(spec) { 16874 return runtime.template(spec, hb); 16875 }; 16876 16877 return hb; 16878 }; 16879 16880 var Handlebars = create(); 16881 Handlebars.create = create; 16882 16883 Handlebars['default'] = Handlebars; 16884 16885 __exports__ = Handlebars; 16886 return __exports__; 16887})(__module2__, __module4__, __module5__, __module3__, __module6__); 16888
16889// handlebars/compiler/ast.js 16890var __module7__ = (function(__dependency1__) { 16891 "use strict"; 16892 var __exports__; 16893 var Exception = __dependency1__; 16894 16895 function LocationInfo(locInfo) { 16896 locInfo = locInfo || {}; 16897 this.firstLine = locInfo.first_line; 16898 this.firstColumn = locInfo.first_column; 16899 this.lastColumn = locInfo.last_column; 16900 this.lastLine = locInfo.last_line; 16901 } 16902 16903 var AST = { 16904 ProgramNode: function(statements, strip, locInfo) { 16905 LocationInfo.call(this, locInfo); 16906 this.type = "program"; 16907 this.statements = statements; 16908 this.strip = strip; 16909 }, 16910 16911 MustacheNode: function(rawParams, hash, open, strip, locInfo) { 16912 LocationInfo.call(this, locInfo); 16913 this.type = "mustache"; 16914 this.strip = strip; 16915 16916 // Open may be a string parsed from the parser or a passed boolean flag 16917 if (open != null && open.charAt) { 16918 // Must use charAt to support IE pre-10 16919 var escapeFlag = open.charAt(3) || open.charAt(2); 16920 this.escaped = escapeFlag !== '{' && escapeFlag !== '&'; 16921 } else { 16922 this.escaped = !!open; 16923 } 16924 16925 if (rawParams instanceof AST.SexprNode) { 16926 this.sexpr = rawParams; 16927 } else { 16928 // Support old AST API 16929 this.sexpr = new AST.SexprNode(rawParams, hash); 16930 } 16931 16932 // Support old AST API that stored this info in MustacheNode 16933 this.id = this.sexpr.id; 16934 this.params = this.sexpr.params; 16935 this.hash = this.sexpr.hash; 16936 this.eligibleHelper = this.sexpr.eligibleHelper; 16937 this.isHelper = this.sexpr.isHelper; 16938 }, 16939 16940 SexprNode: function(rawParams, hash, locInfo) { 16941 LocationInfo.call(this, locInfo); 16942 16943 this.type = "sexpr"; 16944 this.hash = hash; 16945 16946 var id = this.id = rawParams[0]; 16947 var params = this.params = rawParams.slice(1); 16948 16949 // a mustache is definitely a helper if: 16950 // * it is an eligible helper, and 16951 // * it has at least one parameter or hash segment 16952 this.isHelper = !!(params.length || hash); 16953 16954 // a mustache is an eligible helper if: 16955 // * its id is simple (a single part, not `this` or `..`) 16956 this.eligibleHelper = this.isHelper || id.isSimple; 16957 16958 // if a mustache is an eligible helper but not a definite 16959 // helper, it is ambiguous, and will be resolved in a later 16960 // pass or at runtime. 16961 }, 16962 16963 PartialNode: function(partialName, context, hash, strip, locInfo) { 16964 LocationInfo.call(this, locInfo); 16965 this.type = "partial"; 16966 this.partialName = partialName; 16967 this.context = context; 16968 this.hash = hash; 16969 this.strip = strip; 16970 16971 this.strip.inlineStandalone = true; 16972 }, 16973 16974 BlockNode: function(mustache, program, inverse, strip, locInfo) { 16975 LocationInfo.call(this, locInfo); 16976 16977 this.type = 'block'; 16978 this.mustache = mustache; 16979 this.program = program; 16980 this.inverse = inverse; 16981 this.strip = strip; 16982 16983 if (inverse && !program) { 16984 this.isInverse = true; 16985 } 16986 }, 16987 16988 RawBlockNode: function(mustache, content, close, locInfo) { 16989 LocationInfo.call(this, locInfo); 16990 16991 if (mustache.sexpr.id.original !== close) { 16992 throw new Exception(mustache.sexpr.id.original + " doesn't match " + close, this); 16993 } 16994 16995 content = new AST.ContentNode(content, locInfo); 16996 16997 this.type = 'block'; 16998 this.mustache = mustache; 16999 this.program = new AST.ProgramNode([content], {}, locInfo); 17000 }, 17001 17002 ContentNode: function(string, locInfo) { 17003 LocationInfo.call(this, locInfo); 17004 this.type = "content"; 17005 this.original = this.string = string; 17006 }, 17007 17008 HashNode: function(pairs, locInfo) { 17009 LocationInfo.call(this, locInfo); 17010 this.type = "hash"; 17011 this.pairs = pairs; 17012 }, 17013 17014 IdNode: function(parts, locInfo) { 17015 LocationInfo.call(this, locInfo); 17016 this.type = "ID"; 17017 17018 var original = "", 17019 dig = [], 17020 depth = 0, 17021 depthString = ''; 17022 17023 for(var i=0,l=parts.length; i<l; i++) { 17024 var part = parts[i].part; 17025 original += (parts[i].separator || '') + part; 17026 17027 if (part === ".." || part === "." || part === "this") { 17028 if (dig.length > 0) { 17029 throw new Exception("Invalid path: " + original, this); 17030 } else if (part === "..") { 17031 depth++; 17032 depthString += '../'; 17033 } else { 17034 this.isScoped = true; 17035 } 17036 } else { 17037 dig.push(part); 17038 } 17039 } 17040 17041 this.original = original; 17042 this.parts = dig; 17043 this.string = dig.join('.'); 17044 this.depth = depth; 17045 this.idName = depthString + this.string; 17046 17047 // an ID is simple if it only has one part, and that part is not 17048 // `..` or `this`. 17049 this.isSimple = parts.length === 1 && !this.isScoped && depth === 0; 17050 17051 this.stringModeValue = this.string; 17052 }, 17053
17054 PartialNameNode: function(name, locInfo) { 17055 LocationInfo.call(this, locInfo); 17056 this.type = "PARTIAL_NAME"; 17057 this.name = name.original; 17058 }, 17059 17060 DataNode: function(id, locInfo) { 17061 LocationInfo.call(this, locInfo); 17062 this.type = "DATA"; 17063 this.id = id; 17064 this.stringModeValue = id.stringModeValue; 17065 this.idName = '@' + id.stringModeValue; 17066 }, 17067 17068 StringNode: function(string, locInfo) { 17069 LocationInfo.call(this, locInfo); 17070 this.type = "STRING"; 17071 this.original = 17072 this.string = 17073 this.stringModeValue = string; 17074 }, 17075 17076 NumberNode: function(number, locInfo) { 17077 LocationInfo.call(this, locInfo); 17078 this.type = "NUMBER"; 17079 this.original = 17080 this.number = number; 17081 this.stringModeValue = Number(number); 17082 }, 17083 17084 BooleanNode: function(bool, locInfo) { 17085 LocationInfo.call(this, locInfo); 17086 this.type = "BOOLEAN"; 17087 this.bool = bool; 17088 this.stringModeValue = bool === "true"; 17089 }, 17090 17091 CommentNode: function(comment, locInfo) { 17092 LocationInfo.call(this, locInfo); 17093 this.type = "comment"; 17094 this.comment = comment; 17095 17096 this.strip = { 17097 inlineStandalone: true 17098 }; 17099 } 17100 }; 17101 17102 17103 // Must be exported as an object rather than the root of the module as the jison lexer 17104 // most modify the object to operate properly. 17105 __exports__ = AST; 17106 return __exports__; 17107})(__module5__); 17108
17109// handlebars/compiler/parser.js 17110var __module9__ = (function() { 17111 "use strict"; 17112 var __exports__; 17113 /* jshint ignore:start */ 17114 /* istanbul ignore next */ 17115 /* Jison generated parser */ 17116 var handlebars = (function(){ 17117 var parser = {trace: function trace() { }, 17118 yy: {}, 17119 symbols_: {"error":2,"root":3,"program":4,"EOF":5,"program_repetition0":6,"statement":7,"mustache":8,"block":9,"rawBlock":10,"partial":11,"CONTENT":12,"COMMENT":13,"openRawBlock":14,"END_RAW_BLOCK":15,"OPEN_RAW_BLOCK":16,"sexpr":17,"CLOSE_RAW_BLOCK":18,"openBlock":19,"block_option0":20,"closeBlock":21,"openInverse":22,"block_option1":23,"OPEN_BLOCK":24,"CLOSE":25,"OPEN_INVERSE":26,"inverseAndProgram":27,"INVERSE":28,"OPEN_ENDBLOCK":29,"path":30,"OPEN":31,"OPEN_UNESCAPED":32,"CLOSE_UNESCAPED":33,"OPEN_PARTIAL":34,"partialName":35,"param":36,"partial_option0":37,"partial_option1":38,"sexpr_repetition0":39,"sexpr_option0":40,"dataName":41,"STRING":42,"NUMBER":43,"BOOLEAN":44,"OPEN_SEXPR":45,"CLOSE_SEXPR":46,"hash":47,"hash_repetition_plus0":48,"hashSegment":49,"ID":50,"EQUALS":51,"DATA":52,"pathSegments":53,"SEP":54,"$accept":0,"$end":1}, 17120 terminals_: {2:"error",5:"EOF",12:"CONTENT",13:"COMMENT",15:"END_RAW_BLOCK",16:"OPEN_RAW_BLOCK",18:"CLOSE_RAW_BLOCK",24:"OPEN_BLOCK",25:"CLOSE",26:"OPEN_INVERSE",28:"INVERSE",29:"OPEN_ENDBLOCK",31:"OPEN",32:"OPEN_UNESCAPED",33:"CLOSE_UNESCAPED",34:"OPEN_PARTIAL",42:"STRING",43:"NUMBER",44:"BOOLEAN",45:"OPEN_SEXPR",46:"CLOSE_SEXPR",50:"ID",51:"EQUALS",52:"DATA",54:"SEP"}, 17121 productions_: [0,[3,2],[4,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[10,3],[14,3],[9,4],[9,4],[19,3],[22,3],[27,2],[21,3],[8,3],[8,3],[11,5],[11,4],[17,3],[17,1],[36,1],[36,1],[36,1],[36,1],[36,1],[36,3],[47,1],[49,3],[35,1],[35,1],[35,1],[41,2],[30,1],[53,3],[53,1],[6,0],[6,2],[20,0],[20,1],[23,0],[23,1],[37,0],[37,1],[38,0],[38,1],[39,0],[39,2],[40,0],[40,1],[48,1],[48,2]], 17122 performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) { 17123 17124 var $0 = $$.length - 1; 17125 switch (yystate) { 17126 case 1: yy.prepareProgram($$[$0-1].statements, true); return $$[$0-1]; 17127 break; 17128 case 2:this.$ = new yy.ProgramNode(yy.prepareProgram($$[$0]), {}, this._$); 17129 break; 17130 case 3:this.$ = $$[$0]; 17131 break; 17132 case 4:this.$ = $$[$0]; 17133 break; 17134 case 5:this.$ = $$[$0]; 17135 break; 17136 case 6:this.$ = $$[$0]; 17137 break; 17138 case 7:this.$ = new yy.ContentNode($$[$0], this._$); 17139 break; 17140 case 8:this.$ = new yy.CommentNode($$[$0], this._$); 17141 break; 17142 case 9:this.$ = new yy.RawBlockNode($$[$0-2], $$[$0-1], $$[$0], this._$); 17143 break; 17144 case 10:this.$ = new yy.MustacheNode($$[$0-1], null, '', '', this._$); 17145 break; 17146 case 11:this.$ = yy.prepareBlock($$[$0-3], $$[$0-2], $$[$0-1], $$[$0], false, this._$); 17147 break; 17148 case 12:this.$ = yy.prepareBlock($$[$0-3], $$[$0-2], $$[$0-1], $$[$0], true, this._$); 17149 break; 17150 case 13:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], yy.stripFlags($$[$0-2], $$[$0]), this._$); 17151 break; 17152 case 14:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], yy.stripFlags($$[$0-2], $$[$0]), this._$); 17153 break; 17154 case 15:this.$ = { strip: yy.stripFlags($$[$0-1], $$[$0-1]), program: $$[$0] }; 17155 break; 17156 case 16:this.$ = {path: $$[$0-1], strip: yy.stripFlags($$[$0-2], $$[$0])}; 17157 break; 17158 case 17:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], yy.stripFlags($$[$0-2], $$[$0]), this._$); 17159 break; 17160 case 18:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], yy.stripFlags($$[$0-2], $$[$0]), this._$); 17161 break; 17162 case 19:this.$ = new yy.PartialNode($$[$0-3], $$[$0-2], $$[$0-1], yy.stripFlags($$[$0-4], $$[$0]), this._$); 17163 break; 17164 case 20:this.$ = new yy.PartialNode($$[$0-2], undefined, $$[$0-1], yy.stripFlags($$[$0-3], $$[$0]), this._$); 17165 break; 17166 case 21:this.$ = new yy.SexprNode([$$[$0-2]].concat($$[$0-1]), $$[$0], this._$); 17167 break; 17168 case 22:this.$ = new yy.SexprNode([$$[$0]], null, this._$); 17169 break; 17170 case 23:this.$ = $$[$0]; 17171 break; 17172 case 24:this.$ = new yy.StringNode($$[$0], this._$); 17173 break; 17174 case 25:this.$ = new yy.NumberNode($$[$0], this._$); 17175 break; 17176 case 26:this.$ = new yy.BooleanNode($$[$0], this._$); 17177 break; 17178 case 27:this.$ = $$[$0]; 17179 break; 17180 case 28:$$[$0-1].isHelper = true; this.$ = $$[$0-1]; 17181 break; 17182 case 29:this.$ = new yy.HashNode($$[$0], this._$); 17183 break; 17184 case 30:this.$ = [$$[$0-2], $$[$0]]; 17185 break; 17186 case 31:this.$ = new yy.PartialNameNode($$[$0], this._$); 17187 break; 17188 case 32:this.$ = new yy.PartialNameNode(new yy.StringNode($$[$0], this._$), this._$); 17189 break; 17190 case 33:this.$ = new yy.PartialNameNode(new yy.NumberNode($$[$0], this._$)); 17191 break; 17192 case 34:this.$ = new yy.DataNode($$[$0], this._$); 17193 break; 17194 case 35:this.$ = new yy.IdNode($$[$0], this._$); 17195 break; 17196 case 36: $$[$0-2].push({part: $$[$0], separator: $$[$0-1]}); this.$ = $$[$0-2]; 17197 break; 17198 case 37:this.$ = [{part: $$[$0]}]; 17199 break; 17200 case 38:this.$ = []; 17201 break; 17202 case 39:$$[$0-1].push($$[$0]); 17203 break; 17204 case 48:this.$ = []; 17205 break; 17206 case 49:$$[$0-1].push($$[$0]); 17207 break; 17208 case 52:this.$ = [$$[$0]]; 17209 break; 17210 case 53:$$[$0-1].push($$[$0]); 17211 break; 17212 } 17213 }, 17214 table: [{3:1,4:2,5:[2,38],6:3,12:[2,38],13:[2,38],16:[2,38],24:[2,38],26:[2,38],31:[2,38],32:[2,38],34:[2,38]},{1:[3]},{5:[1,4]}
vendor: 10,615 bytes, lines 17214-17335
17214,{5:[2,2],7:5,8:6,9:7,10:8,11:9,12:[1,10],13:[1,11],14:16,16:[1,20],19:14,22:15,24:[1,18],26:[1,19],28:[2,2],29:[2,2],31:[1,12],32:[1,13],34:[1,17]},{1:[2,1]},{5:[2,39],12:[2,39],13:[2,39],16:[2,39],24:[2,39],26:[2,39],28:[2,39],29:[2,39],31:[2,39],32:[2,39],34:[2,39]},{5:[2,3],12:[2,3],13:[2,3],16:[2,3],24:[2,3],26:[2,3],28:[2,3],29:[2,3],31:[2,3],32:[2,3],34:[2,3]},{5:[2,4],12:[2,4],13:[2,4],16:[2,4],24:[2,4],26:[2,4],28:[2,4],29:[2,4],31:[2,4],32:[2,4],34:[2,4]},{5:[2,5],12:[2,5],13:[2,5],16:[2,5],24:[2,5],26:[2,5],28:[2,5],29:[2,5],31:[2,5],32:[2,5],34:[2,5]},{5:[2,6],12:[2,6],13:[2,6],16:[2,6],24:[2,6],26:[2,6],28:[2,6],29:[2,6],31:[2,6],32:[2,6],34:[2,6]},{5:[2,7],12:[2,7],13:[2,7],16:[2,7],24:[2,7],26:[2,7],28:[2,7],29:[2,7],31:[2,7],32:[2,7],34:[2,7]},{5:[2,8],12:[2,8],13:[2,8],16:[2,8],24:[2,8],26:[2,8],28:[2,8],29:[2,8],31:[2,8],32:[2,8],34:[2,8]},{17:21,30:22,41:23,50:[1,26],52:[1,25],53:24},{17:27,30:22,41:23,50:[1,26],52:[1,25],53:24},{4:28,6:3,12:[2,38],13:[2,38],16:[2,38],24:[2,38],26:[2,38],28:[2,38],29:[2,38],31:[2,38],32:[2,38],34:[2,38]},{4:29,6:3,12:[2,38],13:[2,38],16:[2,38],24:[2,38],26:[2,38],28:[2,38],29:[2,38],31:[2,38],32:[2,38],34:[2,38]},{12:[1,30]},{30:32,35:31,42:[1,33],43:[1,34],50:[1,26],53:24},{17:35,30:22,41:23,50:[1,26],52:[1,25],53:24},{17:36,30:22,41:23,50:[1,26],52:[1,25],53:24},{17:37,30:22,41:23,50:[1,26],52:[1,25],53:24},{25:[1,38]},{18:[2,48],25:[2,48],33:[2,48],39:39,42:[2,48],43:[2,48],44:[2,48],45:[2,48],46:[2,48],50:[2,48],52:[2,48]},{18:[2,22],25:[2,22],33:[2,22],46:[2,22]},{18:[2,35],25:[2,35],33:[2,35],42:[2,35],43:[2,35],44:[2,35],45:[2,35],46:[2,35],50:[2,35],52:[2,35],54:[1,40]},{30:41,50:[1,26],53:24},{18:[2,37],25:[2,37],33:[2,37],42:[2,37],43:[2,37],44:[2,37],45:[2,37],46:[2,37],50:[2,37],52:[2,37],54:[2,37]},{33:[1,42]},{20:43,27:44,28:[1,45],29:[2,40]},{23:46,27:47,28:[1,45],29:[2,42]},{15:[1,48]},{25:[2,46],30:51,36:49,38:50,41:55,42:[1,52],43:[1,53],44:[1,54],45:[1,56],47:57,48:58,49:60,50:[1,59],52:[1,25],53:24},{25:[2,31],42:[2,31],43:[2,31],44:[2,31],45:[2,31],50:[2,31],52:[2,31]},{25:[2,32],42:[2,32],43:[2,32],44:[2,32],45:[2,32],50:[2,32],52:[2,32]},{25:[2,33],42:[2,33],43:[2,33],44:[2,33],45:[2,33],50:[2,33],52:[2,33]},{25:[1,61]},{25:[1,62]},{18:[1,63]},{5:[2,17],12:[2,17],13:[2,17],16:[2,17],24:[2,17],26:[2,17],28:[2,17],29:[2,17],31:[2,17],32:[2,17],34:[2,17]},{18:[2,50],25:[2,50],30:51,33:[2,50],36:65,40:64,41:55,42:[1,52],43:[1,53],44:[1,54],45:[1,56],46:[2,50],47:66,48:58,49:60,50:[1,59],52:[1,25],53:24},{50:[1,67]},{18:[2,34],25:[2,34],33:[2,34],42:[2,34],43:[2,34],44:[2,34],45:[2,34],46:[2,34],50:[2,34],52:[2,34]},{5:[2,18],12:[2,18],13:[2,18],16:[2,18],24:[2,18],26:[2,18],28:[2,18],29:[2,18],31:[2,18],32:[2,18],34:[2,18]},{21:68,29:[1,69]},{29:[2,41]},{4:70,6:3,12:[2,38],13:[2,38],16:[2,38],24:[2,38],26:[2,38],29:[2,38],31:[2,38],32:[2,38],34:[2,38]},{21:71,29:[1,69]},{29:[2,43]},{5:[2,9],12:[2,9],13:[2,9],16:[2,9],24:[2,9],26:[2,9],28:[2,9],29:[2,9],31:[2,9],32:[2,9],34:[2,9]},{25:[2,44],37:72,47:73,48:58,49:60,50:[1,74]},{25:[1,75]},{18:[2,23],25:[2,23],33:[2,23],42:[2,23],43:[2,23],44:[2,23],45:[2,23],46:[2,23],50:[2,23],52:[2,23]},{18:[2,24],25:[2,24],33:[2,24],42:[2,24],43:[2,24],44:[2,24],45:[2,24],46:[2,24],50:[2,24],52:[2,24]},{18:[2,25],25:[2,25],33:[2,25],42:[2,25],43:[2,25],44:[2,25],45:[2,25],46:[2,25],50:[2,25],52:[2,25]},{18:[2,26],25:[2,26],33:[2,26],42:[2,26],43:[2,26],44:[2,26],45:[2,26],46:[2,26],50:[2,26],52:[2,26]},{18:[2,27],25:[2,27],33:[2,27],42:[2,27],43:[2,27],44:[2,27],45:[2,27],46:[2,27],50:[2,27],52:[2,27]},{17:76,30:22,41:23,50:[1,26],52:[1,25],53:24},{25:[2,47]},{18:[2,29],25:[2,29],33:[2,29],46:[2,29],49:77,50:[1,74]},{18:[2,37],25:[2,37],33:[2,37],42:[2,37],43:[2,37],44:[2,37],45:[2,37],46:[2,37],50:[2,37],51:[1,78],52:[2,37],54:[2,37]},{18:[2,52],25:[2,52],33:[2,52],46:[2,52],50:[2,52]},{12:[2,13],13:[2,13],16:[2,13],24:[2,13],26:[2,13],28:[2,13],29:[2,13],31:[2,13],32:[2,13],34:[2,13]},{12:[2,14],13:[2,14],16:[2,14],24:[2,14],26:[2,14],28:[2,14],29:[2,14],31:[2,14],32:[2,14],34:[2,14]},{12:[2,10]},{18:[2,21],25:[2,21],33:[2,21],46:[2,21]},{18:[2,49],25:[2,49],33:[2,49],42:[2,49],43:[2,49],44:[2,49],45:[2,49],46:[2,49],50:[2,49],52:[2,49]},{18:[2,51],25:[2,51],33:[2,51],46:[2,51]},{18:[2,36],25:[2,36],33:[2,36],42:[2,36],43:[2,36],44:[2,36],45:[2,36],46:[2,36],50:[2,36],52:[2,36],54:[2,36]},{5:[2,11],12:[2,11],13:[2,11],16:[2,11],24:[2,11],26:[2,11],28:[2,11],29:[2,11],31:[2,11],32:[2,11],34:[2,11]},{30:79,50:[1,26],53:24},{29:[2,15]},{5:[2,12],12:[2,12],13:[2,12],16:[2,12],24:[2,12],26:[2,12],28:[2,12],29:[2,12],31:[2,12],32:[2,12],34:[2,12]},{25:[1,80]},{25:[2,45]},{51:[1,78]},{5:[2,20],12:[2,20],13:[2,20],16:[2,20],24:[2,20],26:[2,20],28:[2,20],29:[2,20],31:[2,20],32:[2,20],34:[2,20]},{46:[1,81]},{18:[2,53],25:[2,53],33:[2,53],46:[2,53],50:[2,53]},{30:51,36:82,41:55,42:[1,52],43:[1,53],44:[1,54],45:[1,56],50:[1,26],52:[1,25],53:24},{25:[1,83]},{5:[2,19],12:[2,19],13:[2,19],16:[2,19],24:[2,19],26:[2,19],28:[2,19],29:[2,19],31:[2,19],32:[2,19],34:[2,19]},{18:[2,28],25:[2,28],33:[2,28],42:[2,28],43:[2,28],44:[2,28],45:[2,28],46:[2,28],50:[2,28],52:[2,28]},{18:[2,30],25:[2,30],33:[2,30],46:[2,30],50:[2,30]},{5:[2,16],12:[2,16],13:[2,16],16:[2,16],24:[2,16],26:[2,16],28:[2,16],29:[2,16],31:[2,16],32:[2,16],34:[2,16]}], 17215 defaultActions: {4:[2,1],44:[2,41],47:[2,43],57:[2,47],63:[2,10],70:[2,15],73:[2,45]}, 17216 parseError: function parseError(str, hash) { 17217 throw new Error(str); 17218 }, 17219 parse: function parse(input) { 17220 var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1; 17221 this.lexer.setInput(input); 17222 this.lexer.yy = this.yy; 17223 this.yy.lexer = this.lexer; 17224 this.yy.parser = this; 17225 if (typeof this.lexer.yylloc == "undefined") 17226 this.lexer.yylloc = {}; 17227 var yyloc = this.lexer.yylloc; 17228 lstack.push(yyloc); 17229 var ranges = this.lexer.options && this.lexer.options.ranges; 17230 if (typeof this.yy.parseError === "function") 17231 this.parseError = this.yy.parseError; 17232 function popStack(n) { 17233 stack.length = stack.length - 2 * n; 17234 vstack.length = vstack.length - n; 17235 lstack.length = lstack.length - n; 17236 } 17237 function lex() { 17238 var token; 17239 token = self.lexer.lex() || 1; 17240 if (typeof token !== "number") { 17241 token = self.symbols_[token] || token; 17242 } 17243 return token; 17244 } 17245 var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected; 17246 while (true) { 17247 state = stack[stack.length - 1]; 17248 if (this.defaultActions[state]) { 17249 action = this.defaultActions[state]; 17250 } else { 17251 if (symbol === null || typeof symbol == "undefined") { 17252 symbol = lex(); 17253 } 17254 action = table[state] && table[state][symbol]; 17255 } 17256 if (typeof action === "undefined" || !action.length || !action[0]) { 17257 var errStr = ""; 17258 if (!recovering) { 17259 expected = []; 17260 for (p in table[state]) 17261 if (this.terminals_[p] && p > 2) { 17262 expected.push("'" + this.terminals_[p] + "'"); 17263 } 17264 if (this.lexer.showPosition) { 17265 errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'"; 17266 } else { 17267 errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1?"end of input":"'" + (this.terminals_[symbol] || symbol) + "'"); 17268 } 17269 this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); 17270 } 17271 } 17272 if (action[0] instanceof Array && action.length > 1) { 17273 throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol); 17274 } 17275 switch (action[0]) { 17276 case 1: 17277 stack.push(symbol); 17278 vstack.push(this.lexer.yytext); 17279 lstack.push(this.lexer.yylloc); 17280 stack.push(action[1]); 17281 symbol = null; 17282 if (!preErrorSymbol) { 17283 yyleng = this.lexer.yyleng; 17284 yytext = this.lexer.yytext; 17285 yylineno = this.lexer.yylineno; 17286 yyloc = this.lexer.yylloc; 17287 if (recovering > 0) 17288 recovering--; 17289 } else { 17290 symbol = preErrorSymbol; 17291 preErrorSymbol = null; 17292 } 17293 break; 17294 case 2: 17295 len = this.productions_[action[1]][1]; 17296 yyval.$ = vstack[vstack.length - len]; 17297 yyval._$ = {first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column}; 17298 if (ranges) { 17299 yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]]; 17300 } 17301 r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); 17302 if (typeof r !== "undefined") { 17303 return r; 17304 } 17305 if (len) { 17306 stack = stack.slice(0, -1 * len * 2); 17307 vstack = vstack.slice(0, -1 * len); 17308 lstack = lstack.slice(0, -1 * len); 17309 } 17310 stack.push(this.productions_[action[1]][0]); 17311 vstack.push(yyval.$); 17312 lstack.push(yyval._$); 17313 newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; 17314 stack.push(newState); 17315 break; 17316 case 3: 17317 return true; 17318 } 17319 } 17320 return true; 17321 } 17322 }; 17323 /* Jison generated lexer */ 17324 var lexer = (function(){ 17325 var lexer = ({EOF:1, 17326 parseError:function parseError(str, hash) { 17327 if (this.yy.parser) { 17328 this.yy.parser.parseError(str, hash); 17329 } else { 17330 throw new Error(str); 17331 } 17332 }, 17333 setInput:function (input) { 17334 this._input = input; 17335 this._more = this._less = this.done = false;
vendor: 4,430 bytes, lines 17336-17453
17336 this.yylineno = this.yyleng = 0; 17337 this.yytext = this.matched = this.match = ''; 17338 this.conditionStack = ['INITIAL']; 17339 this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0}; 17340 if (this.options.ranges) this.yylloc.range = [0,0]; 17341 this.offset = 0; 17342 return this; 17343 }, 17344 input:function () { 17345 var ch = this._input[0]; 17346 this.yytext += ch; 17347 this.yyleng++; 17348 this.offset++; 17349 this.match += ch; 17350 this.matched += ch; 17351 var lines = ch.match(/(?:\r\n?|\n).*/g); 17352 if (lines) { 17353 this.yylineno++; 17354 this.yylloc.last_line++; 17355 } else { 17356 this.yylloc.last_column++; 17357 } 17358 if (this.options.ranges) this.yylloc.range[1]++; 17359 17360 this._input = this._input.slice(1); 17361 return ch; 17362 }, 17363 unput:function (ch) { 17364 var len = ch.length; 17365 var lines = ch.split(/(?:\r\n?|\n)/g); 17366 17367 this._input = ch + this._input; 17368 this.yytext = this.yytext.substr(0, this.yytext.length-len-1); 17369 //this.yyleng -= len; 17370 this.offset -= len; 17371 var oldLines = this.match.split(/(?:\r\n?|\n)/g); 17372 this.match = this.match.substr(0, this.match.length-1); 17373 this.matched = this.matched.substr(0, this.matched.length-1); 17374 17375 if (lines.length-1) this.yylineno -= lines.length-1; 17376 var r = this.yylloc.range; 17377 17378 this.yylloc = {first_line: this.yylloc.first_line, 17379 last_line: this.yylineno+1, 17380 first_column: this.yylloc.first_column, 17381 last_column: lines ? 17382 (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length: 17383 this.yylloc.first_column - len 17384 }; 17385 17386 if (this.options.ranges) { 17387 this.yylloc.range = [r[0], r[0] + this.yyleng - len]; 17388 } 17389 return this; 17390 }, 17391 more:function () { 17392 this._more = true; 17393 return this; 17394 }, 17395 less:function (n) { 17396 this.unput(this.match.slice(n)); 17397 }, 17398 pastInput:function () { 17399 var past = this.matched.substr(0, this.matched.length - this.match.length); 17400 return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); 17401 }, 17402 upcomingInput:function () { 17403 var next = this.match; 17404 if (next.length < 20) { 17405 next += this._input.substr(0, 20-next.length); 17406 } 17407 return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, ""); 17408 }, 17409 showPosition:function () { 17410 var pre = this.pastInput(); 17411 var c = new Array(pre.length + 1).join("-"); 17412 return pre + this.upcomingInput() + "\n" + c+"^"; 17413 }, 17414 next:function () { 17415 if (this.done) { 17416 return this.EOF; 17417 } 17418 if (!this._input) this.done = true; 17419 17420 var token, 17421 match, 17422 tempMatch, 17423 index, 17424 col, 17425 lines; 17426 if (!this._more) { 17427 this.yytext = ''; 17428 this.match = ''; 17429 } 17430 var rules = this._currentRules(); 17431 for (var i=0;i < rules.length; i++) { 17432 tempMatch = this._input.match(this.rules[rules[i]]); 17433 if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { 17434 match = tempMatch; 17435 index = i; 17436 if (!this.options.flex) break; 17437 } 17438 } 17439 if (match) { 17440 lines = match[0].match(/(?:\r\n?|\n).*/g); 17441 if (lines) this.yylineno += lines.length; 17442 this.yylloc = {first_line: this.yylloc.last_line, 17443 last_line: this.yylineno+1, 17444 first_column: this.yylloc.last_column, 17445 last_column: lines ? lines[lines.length-1].length-lines[lines.length-1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length}; 17446 this.yytext += match[0]; 17447 this.match += match[0]; 17448 this.matches = match; 17449 this.yyleng = this.yytext.length; 17450 if (this.options.ranges) { 17451 this.yylloc.range = [this.offset, this.offset += this.yyleng]; 17452 } 17453 this._more = false;
vendor: 5,475 bytes, lines 17454-17607
17454 this._input = this._input.slice(match[0].length); 17455 this.matched += match[0]; 17456 token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]); 17457 if (this.done && this._input) this.done = false; 17458 if (token) return token; 17459 else return; 17460 } 17461 if (this._input === "") { 17462 return this.EOF; 17463 } else { 17464 return this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(), 17465 {text: "", token: null, line: this.yylineno}); 17466 } 17467 }, 17468 lex:function lex() { 17469 var r = this.next(); 17470 if (typeof r !== 'undefined') { 17471 return r; 17472 } else { 17473 return this.lex(); 17474 } 17475 }, 17476 begin:function begin(condition) { 17477 this.conditionStack.push(condition); 17478 }, 17479 popState:function popState() { 17480 return this.conditionStack.pop(); 17481 }, 17482 _currentRules:function _currentRules() { 17483 return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules; 17484 }, 17485 topState:function () { 17486 return this.conditionStack[this.conditionStack.length-2]; 17487 }, 17488 pushState:function begin(condition) { 17489 this.begin(condition); 17490 }}); 17491 lexer.options = {}; 17492 lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { 17493 17494 17495 function strip(start, end) { 17496 return yy_.yytext = yy_.yytext.substr(start, yy_.yyleng-end); 17497 } 17498 17499 17500 var YYSTATE=YY_START 17501 switch($avoiding_name_collisions) { 17502 case 0: 17503 if(yy_.yytext.slice(-2) === "\\\\") { 17504 strip(0,1); 17505 this.begin("mu"); 17506 } else if(yy_.yytext.slice(-1) === "\\") { 17507 strip(0,1); 17508 this.begin("emu"); 17509 } else { 17510 this.begin("mu"); 17511 } 17512 if(yy_.yytext) return 12; 17513 17514 break; 17515 case 1:return 12; 17516 break; 17517 case 2: 17518 this.popState(); 17519 return 12; 17520 17521 break; 17522 case 3: 17523 yy_.yytext = yy_.yytext.substr(5, yy_.yyleng-9); 17524 this.popState(); 17525 return 15; 17526 17527 break; 17528 case 4: return 12; 17529 break; 17530 case 5:strip(0,4); this.popState(); return 13; 17531 break; 17532 case 6:return 45; 17533 break; 17534 case 7:return 46; 17535 break; 17536 case 8: return 16; 17537 break; 17538 case 9: 17539 this.popState(); 17540 this.begin('raw'); 17541 return 18; 17542 17543 break; 17544 case 10:return 34; 17545 break; 17546 case 11:return 24; 17547 break; 17548 case 12:return 29; 17549 break; 17550 case 13:this.popState(); return 28; 17551 break; 17552 case 14:this.popState(); return 28; 17553 break; 17554 case 15:return 26; 17555 break; 17556 case 16:return 26; 17557 break; 17558 case 17:return 32; 17559 break; 17560 case 18:return 31; 17561 break; 17562 case 19:this.popState(); this.begin('com'); 17563 break; 17564 case 20:strip(3,5); this.popState(); return 13; 17565 break; 17566 case 21:return 31; 17567 break; 17568 case 22:return 51; 17569 break; 17570 case 23:return 50; 17571 break; 17572 case 24:return 50; 17573 break; 17574 case 25:return 54; 17575 break; 17576 case 26:// ignore whitespace 17577 break; 17578 case 27:this.popState(); return 33; 17579 break; 17580 case 28:this.popState(); return 25; 17581 break; 17582 case 29:yy_.yytext = strip(1,2).replace(/\\"/g,'"'); return 42; 17583 break; 17584 case 30:yy_.yytext = strip(1,2).replace(/\\'/g,"'"); return 42; 17585 break; 17586 case 31:return 52; 17587 break; 17588 case 32:return 44; 17589 break; 17590 case 33:return 44; 17591 break; 17592 case 34:return 43; 17593 break; 17594 case 35:return 50; 17595 break; 17596 case 36:yy_.yytext = strip(1,2); return 50; 17597 break; 17598 case 37:return 'INVALID'; 17599 break; 17600 case 38:return 5; 17601 break; 17602 } 17603 }; 17604 lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/,/^(?:\{\{\{\{\/[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.])\}\}\}\})/,/^(?:[^\x00]*?(?=(\{\{\{\{\/)))/,/^(?:[\s\S]*?--\}\})/,/^(?:\()/,/^(?:\))/,/^(?:\{\{\{\{)/,/^(?:\}\}\}\})/,/^(?:\{\{(~)?>)/,/^(?:\{\{(~)?#)/,/^(?:\{\{(~)?\/)/,/^(?:\{\{(~)?\^\s*(~)?\}\})/,/^(?:\{\{(~)?\s*else\s*(~)?\}\})/,/^(?:\{\{(~)?\^)/,/^(?:\{\{(~)?\s*else\b)/,/^(?:\{\{(~)?\{)/,/^(?:\{\{(~)?&)/,/^(?:\{\{!--)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{(~)?)/,/^(?:=)/,/^(?:\.\.)/,/^(?:\.(?=([=~}\s\/.)])))/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}(~)?\}\})/,/^(?:(~)?\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@)/,/^(?:true(?=([~}\s)])))/,/^(?:false(?=([~}\s)])))/,/^(?:-?[0-9]+(?:\.[0-9]+)?(?=([~}\s)])))/,/^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)]))))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:$)/]; 17605 lexer.conditions = {"mu":{"rules":[6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"com":{"rules":[5],"inclusive":false},"raw":{"rules":[3,4],"inclusive":false},"INITIAL":{"rules":[0,1,38],"inclusive":true}}; 17606 return lexer;})() 17607 parser.lexer = lexer;
17608 function Parser () { this.yy = {}; }Parser.prototype = parser;parser.Parser = Parser; 17609 return new Parser; 17610 })();__exports__ = handlebars; 17611 /* jshint ignore:end */ 17612 return __exports__; 17613})(); 17614
17615// handlebars/compiler/helpers.js 17616var __module10__ = (function(__dependency1__) { 17617 "use strict"; 17618 var __exports__ = {}; 17619 var Exception = __dependency1__; 17620 17621 function stripFlags(open, close) { 17622 return { 17623 left: open.charAt(2) === '~', 17624 right: close.charAt(close.length-3) === '~' 17625 }; 17626 } 17627 17628 __exports__.stripFlags = stripFlags; 17629 function prepareBlock(mustache, program, inverseAndProgram, close, inverted, locInfo) { 17630 /*jshint -W040 */ 17631 if (mustache.sexpr.id.original !== close.path.original) { 17632 throw new Exception(mustache.sexpr.id.original + ' doesn\'t match ' + close.path.original, mustache); 17633 } 17634 17635 var inverse = inverseAndProgram && inverseAndProgram.program; 17636 17637 var strip = { 17638 left: mustache.strip.left, 17639 right: close.strip.right, 17640 17641 // Determine the standalone candiacy. Basically flag our content as being possibly standalone 17642 // so our parent can determine if we actually are standalone 17643 openStandalone: isNextWhitespace(program.statements), 17644 closeStandalone: isPrevWhitespace((inverse || program).statements) 17645 }; 17646 17647 if (mustache.strip.right) { 17648 omitRight(program.statements, null, true); 17649 } 17650 17651 if (inverse) { 17652 var inverseStrip = inverseAndProgram.strip; 17653 17654 if (inverseStrip.left) { 17655 omitLeft(program.statements, null, true); 17656 } 17657 if (inverseStrip.right) { 17658 omitRight(inverse.statements, null, true); 17659 } 17660 if (close.strip.left) { 17661 omitLeft(inverse.statements, null, true); 17662 } 17663 17664 // Find standalone else statments 17665 if (isPrevWhitespace(program.statements) 17666 && isNextWhitespace(inverse.statements)) { 17667 17668 omitLeft(program.statements); 17669 omitRight(inverse.statements); 17670 } 17671 } else { 17672 if (close.strip.left) { 17673 omitLeft(program.statements, null, true); 17674 } 17675 } 17676 17677 if (inverted) { 17678 return new this.BlockNode(mustache, inverse, program, strip, locInfo); 17679 } else { 17680 return new this.BlockNode(mustache, program, inverse, strip, locInfo); 17681 } 17682 } 17683 17684 __exports__.prepareBlock = prepareBlock; 17685 function prepareProgram(statements, isRoot) { 17686 for (var i = 0, l = statements.length; i < l; i++) { 17687 var current = statements[i], 17688 strip = current.strip; 17689 17690 if (!strip) { 17691 continue; 17692 } 17693 17694 var _isPrevWhitespace = isPrevWhitespace(statements, i, isRoot, current.type === 'partial'), 17695 _isNextWhitespace = isNextWhitespace(statements, i, isRoot), 17696 17697 openStandalone = strip.openStandalone && _isPrevWhitespace, 17698 closeStandalone = strip.closeStandalone && _isNextWhitespace, 17699 inlineStandalone = strip.inlineStandalone && _isPrevWhitespace && _isNextWhitespace; 17700 17701 if (strip.right) { 17702 omitRight(statements, i, true); 17703 } 17704 if (strip.left) { 17705 omitLeft(statements, i, true); 17706 } 17707 17708 if (inlineStandalone) { 17709 omitRight(statements, i); 17710 17711 if (omitLeft(statements, i)) { 17712 // If we are on a standalone node, save the indent info for partials 17713 if (current.type === 'partial') { 17714 current.indent = (/([ \t]+$)/).exec(statements[i-1].original) ? RegExp.$1 : ''; 17715 } 17716 } 17717 } 17718 if (openStandalone) { 17719 omitRight((current.program || current.inverse).statements); 17720 17721 // Strip out the previous content node if it's whitespace only 17722 omitLeft(statements, i); 17723 } 17724 if (closeStandalone) { 17725 // Always strip the next node 17726 omitRight(statements, i); 17727 17728 omitLeft((current.inverse || current.program).statements); 17729 } 17730 } 17731 17732 return statements; 17733 } 17734 17735 __exports__.prepareProgram = prepareProgram;function isPrevWhitespace(statements, i, isRoot) { 17736 if (i === undefined) { 17737 i = statements.length; 17738 } 17739 17740 // Nodes that end with newlines are considered whitespace (but are special 17741 // cased for strip operations) 17742 var prev = statements[i-1], 17743 sibling = statements[i-2]; 17744 if (!prev) { 17745 return isRoot; 17746 } 17747 17748 if (prev.type === 'content') { 17749 return (sibling || !isRoot ? (/\r?\n\s*?$/) : (/(^|\r?\n)\s*?$/)).test(prev.original); 17750 } 17751 } 17752 function isNextWhitespace(statements, i, isRoot) { 17753 if (i === undefined) { 17754 i = -1; 17755 } 17756 17757 var next = statements[i+1], 17758 sibling = statements[i+2]; 17759 if (!next) { 17760 return isRoot; 17761 } 17762 17763 if (next.type === 'content') { 17764 return (sibling || !isRoot ? (/^\s*?\r?\n/) : (/^\s*?(\r?\n|$)/)).test(next.original); 17765 } 17766 } 17767 17768 // Marks the node to the right of the position as omitted. 17769 // I.e. {{foo}}' ' will mark the ' ' node as omitted. 17770 // 17771 // If i is undefined, then the first child will be marked as such. 17772 // 17773 // If mulitple is truthy then all whitespace will be stripped out until non-whitespace 17774 // content is met. 17775 function omitRight(statements, i, multiple) { 17776 var current = statements[i == null ? 0 : i + 1]; 17777 if (!current || current.type !== 'content' || (!multiple && current.rightStripped)) { 17778 return; 17779 } 17780 17781 var original = current.string; 17782 current.string = current.string.replace(multiple ? (/^\s+/) : (/^[ \t]*\r?\n?/), ''); 17783 current.rightStripped = current.string !== original; 17784 } 17785 17786 // Marks the node to the left of the position as omitted. 17787 // I.e. ' '{{foo}} will mark the ' ' node as omitted. 17788 // 17789 // If i is undefined then the last child will be marked as such. 17790 // 17791 // If mulitple is truthy then all whitespace will be stripped out until non-whitespace 17792 // content is met. 17793 function omitLeft(statements, i, multiple) { 17794 var current = statements[i == null ? statements.length - 1 : i - 1]; 17795 if (!current || current.type !== 'content' || (!multiple && current.leftStripped)) { 17796 return; 17797 } 17798 17799 // We omit the last node if it's whitespace only and not preceeded by a non-content node. 17800 var original = current.string; 17801 current.string = current.string.replace(multiple ? (/\s+$/) : (/[ \t]+$/), ''); 17802 current.leftStripped = current.string !== original; 17803 return current.leftStripped; 17804 } 17805 return __exports__; 17806})(__module5__); 17807
17808// handlebars/compiler/base.js 17809var __module8__ = (function(__dependency1__, __dependency2__, __dependency3__, __dependency4__) { 17810 "use strict"; 17811 var __exports__ = {}; 17812 var parser = __dependency1__; 17813 var AST = __dependency2__; 17814 var Helpers = __dependency3__; 17815 var extend = __dependency4__.extend; 17816 17817 __exports__.parser = parser; 17818 17819 var yy = {}; 17820 extend(yy, Helpers, AST); 17821 17822 function parse(input) { 17823 // Just return if an already-compile AST was passed in. 17824 if (input.constructor === AST.ProgramNode) { return input; } 17825 17826 parser.yy = yy; 17827 17828 return parser.parse(input); 17829 } 17830 17831 __exports__.parse = parse; 17832 return __exports__; 17833})(__module9__, __module7__, __module10__, __module3__); 17834
17835// handlebars/compiler/compiler.js 17836var __module11__ = (function(__dependency1__, __dependency2__) { 17837 "use strict"; 17838 var __exports__ = {}; 17839 var Exception = __dependency1__; 17840 var isArray = __dependency2__.isArray; 17841 17842 var slice = [].slice; 17843 17844 function Compiler() {} 17845 17846 __exports__.Compiler = Compiler;// the foundHelper register will disambiguate helper lookup from finding a 17847 // function in a context. This is necessary for mustache compatibility, which 17848 // requires that context functions in blocks are evaluated by blockHelperMissing, 17849 // and then proceed as if the resulting value was provided to blockHelperMissing. 17850 17851 Compiler.prototype = { 17852 compiler: Compiler, 17853 17854 equals: function(other) { 17855 var len = this.opcodes.length; 17856 if (other.opcodes.length !== len) { 17857 return false; 17858 } 17859 17860 for (var i = 0; i < len; i++) { 17861 var opcode = this.opcodes[i], 17862 otherOpcode = other.opcodes[i]; 17863 if (opcode.opcode !== otherOpcode.opcode || !argEquals(opcode.args, otherOpcode.args)) { 17864 return false; 17865 } 17866 } 17867 17868 // We know that length is the same between the two arrays because they are directly tied 17869 // to the opcode behavior above. 17870 len = this.children.length; 17871 for (i = 0; i < len; i++) { 17872 if (!this.children[i].equals(other.children[i])) { 17873 return false; 17874 } 17875 } 17876 17877 return true; 17878 }, 17879 17880 guid: 0, 17881 17882 compile: function(program, options) { 17883 this.opcodes = []; 17884 this.children = []; 17885 this.depths = {list: []}; 17886 this.options = options; 17887 this.stringParams = options.stringParams; 17888 this.trackIds = options.trackIds; 17889 17890 // These changes will propagate to the other compiler components 17891 var knownHelpers = this.options.knownHelpers; 17892 this.options.knownHelpers = { 17893 'helperMissing': true, 17894 'blockHelperMissing': true, 17895 'each': true, 17896 'if': true, 17897 'unless': true, 17898 'with': true, 17899 'log': true, 17900 'lookup': true 17901 }; 17902 if (knownHelpers) { 17903 for (var name in knownHelpers) { 17904 this.options.knownHelpers[name] = knownHelpers[name]; 17905 } 17906 } 17907 17908 return this.accept(program); 17909 }, 17910 17911 accept: function(node) { 17912 return this[node.type](node); 17913 }, 17914 17915 program: function(program) { 17916 var statements = program.statements; 17917 17918 for(var i=0, l=statements.length; i<l; i++) { 17919 this.accept(statements[i]); 17920 } 17921 this.isSimple = l === 1; 17922 17923 this.depths.list = this.depths.list.sort(function(a, b) { 17924 return a - b; 17925 }); 17926 17927 return this; 17928 }, 17929 17930 compileProgram: function(program) { 17931 var result = new this.compiler().compile(program, this.options); 17932 var guid = this.guid++, depth; 17933 17934 this.usePartial = this.usePartial || result.usePartial; 17935 17936 this.children[guid] = result; 17937 17938 for(var i=0, l=result.depths.list.length; i<l; i++) { 17939 depth = result.depths.list[i]; 17940 17941 if(depth < 2) { continue; } 17942 else { this.addDepth(depth - 1); } 17943 } 17944 17945 return guid; 17946 }, 17947 17948 block: function(block) { 17949 var mustache = block.mustache, 17950 program = block.program, 17951 inverse = block.inverse; 17952 17953 if (program) { 17954 program = this.compileProgram(program); 17955 } 17956 17957 if (inverse) { 17958 inverse = this.compileProgram(inverse); 17959 } 17960 17961 var sexpr = mustache.sexpr; 17962 var type = this.classifySexpr(sexpr); 17963 17964 if (type === "helper") { 17965 this.helperSexpr(sexpr, program, inverse); 17966 } else if (type === "simple") { 17967 this.simpleSexpr(sexpr); 17968 17969 // now that the simple mustache is resolved, we need to 17970 // evaluate it by executing `blockHelperMissing` 17971 this.opcode('pushProgram', program); 17972 this.opcode('pushProgram', inverse); 17973 this.opcode('emptyHash'); 17974 this.opcode('blockValue', sexpr.id.original); 17975 } else { 17976 this.ambiguousSexpr(sexpr, program, inverse); 17977 17978 // now that the simple mustache is resolved, we need to 17979 // evaluate it by executing `blockHelperMissing` 17980 this.opcode('pushProgram', program); 17981 this.opcode('pushProgram', inverse); 17982 this.opcode('emptyHash'); 17983 this.opcode('ambiguousBlockValue'); 17984 } 17985 17986 this.opcode('append'); 17987 }, 17988 17989 hash: function(hash) { 17990 var pairs = hash.pairs, i, l; 17991 17992 this.opcode('pushHash'); 17993 17994 for(i=0, l=pairs.length; i<l; i++) { 17995 this.pushParam(pairs[i][1]); 17996 } 17997 while(i--) { 17998 this.opcode('assignToHash', pairs[i][0]); 17999 } 18000 this.opcode('popHash'); 18001 }, 18002 18003 partial: function(partial) { 18004 var partialName = partial.partialName; 18005 this.usePartial = true; 18006 18007 if (partial.hash) { 18008 this.accept(partial.hash); 18009 } else { 18010 this.opcode('push', 'undefined'); 18011 } 18012 18013 if (partial.context) { 18014 this.accept(partial.context); 18015 } else { 18016 this.opcode('getContext', 0); 18017 this.opcode('pushContext'); 18018 } 18019 18020 this.opcode('invokePartial', partialName.name, partial.indent || ''); 18021 this.opcode('append'); 18022 }, 18023 18024 content: function(content) { 18025 if (content.string) { 18026 this.opcode('appendContent', content.string); 18027 } 18028 }, 18029 18030 mustache: function(mustache) { 18031 this.sexpr(mustache.sexpr); 18032 18033 if(mustache.escaped && !this.options.noEscape) { 18034 this.opcode('appendEscaped'); 18035 } else { 18036 this.opcode('append'); 18037 } 18038 }, 18039 18040 ambiguousSexpr: function(sexpr, program, inverse) { 18041 var id = sexpr.id, 18042 name = id.parts[0], 18043 isBlock = program != null || inverse != null; 18044 18045 this.opcode('getContext', id.depth); 18046 18047 this.opcode('pushProgram', program); 18048 this.opcode('pushProgram', inverse); 18049 18050 this.ID(id); 18051 18052 this.opcode('invokeAmbiguous', name, isBlock); 18053 }, 18054
18055 simpleSexpr: function(sexpr) { 18056 var id = sexpr.id; 18057 18058 if (id.type === 'DATA') { 18059 this.DATA(id); 18060 } else if (id.parts.length) { 18061 this.ID(id); 18062 } else { 18063 // Simplified ID for `this` 18064 this.addDepth(id.depth); 18065 this.opcode('getContext', id.depth); 18066 this.opcode('pushContext'); 18067 } 18068 18069 this.opcode('resolvePossibleLambda'); 18070 }, 18071 18072 helperSexpr: function(sexpr, program, inverse) { 18073 var params = this.setupFullMustacheParams(sexpr, program, inverse), 18074 id = sexpr.id, 18075 name = id.parts[0]; 18076 18077 if (this.options.knownHelpers[name]) { 18078 this.opcode('invokeKnownHelper', params.length, name); 18079 } else if (this.options.knownHelpersOnly) { 18080 throw new Exception("You specified knownHelpersOnly, but used the unknown helper " + name, sexpr); 18081 } else { 18082 id.falsy = true; 18083 18084 this.ID(id); 18085 this.opcode('invokeHelper', params.length, id.original, id.isSimple); 18086 } 18087 }, 18088 18089 sexpr: function(sexpr) { 18090 var type = this.classifySexpr(sexpr); 18091 18092 if (type === "simple") { 18093 this.simpleSexpr(sexpr); 18094 } else if (type === "helper") { 18095 this.helperSexpr(sexpr); 18096 } else { 18097 this.ambiguousSexpr(sexpr); 18098 } 18099 }, 18100 18101 ID: function(id) { 18102 this.addDepth(id.depth); 18103 this.opcode('getContext', id.depth); 18104 18105 var name = id.parts[0]; 18106 if (!name) { 18107 // Context reference, i.e. `{{foo .}}` or `{{foo ..}}` 18108 this.opcode('pushContext'); 18109 } else { 18110 this.opcode('lookupOnContext', id.parts, id.falsy, id.isScoped); 18111 } 18112 }, 18113 18114 DATA: function(data) { 18115 this.options.data = true; 18116 this.opcode('lookupData', data.id.depth, data.id.parts); 18117 }, 18118 18119 STRING: function(string) { 18120 this.opcode('pushString', string.string); 18121 }, 18122 18123 NUMBER: function(number) { 18124 this.opcode('pushLiteral', number.number); 18125 }, 18126 18127 BOOLEAN: function(bool) { 18128 this.opcode('pushLiteral', bool.bool); 18129 }, 18130 18131 comment: function() {}, 18132 18133 // HELPERS 18134 opcode: function(name) { 18135 this.opcodes.push({ opcode: name, args: slice.call(arguments, 1) }); 18136 }, 18137 18138 addDepth: function(depth) { 18139 if(depth === 0) { return; } 18140 18141 if(!this.depths[depth]) { 18142 this.depths[depth] = true; 18143 this.depths.list.push(depth); 18144 } 18145 }, 18146 18147 classifySexpr: function(sexpr) { 18148 var isHelper = sexpr.isHelper; 18149 var isEligible = sexpr.eligibleHelper; 18150 var options = this.options; 18151 18152 // if ambiguous, we can possibly resolve the ambiguity now 18153 // An eligible helper is one that does not have a complex path, i.e. `this.foo`, `../foo` etc. 18154 if (isEligible && !isHelper) { 18155 var name = sexpr.id.parts[0]; 18156 18157 if (options.knownHelpers[name]) { 18158 isHelper = true; 18159 } else if (options.knownHelpersOnly) { 18160 isEligible = false; 18161 } 18162 } 18163 18164 if (isHelper) { return "helper"; } 18165 else if (isEligible) { return "ambiguous"; } 18166 else { return "simple"; } 18167 }, 18168 18169 pushParams: function(params) { 18170 for(var i=0, l=params.length; i<l; i++) { 18171 this.pushParam(params[i]); 18172 } 18173 }, 18174 18175 pushParam: function(val) { 18176 if (this.stringParams) { 18177 if(val.depth) { 18178 this.addDepth(val.depth); 18179 } 18180 this.opcode('getContext', val.depth || 0); 18181 this.opcode('pushStringParam', val.stringModeValue, val.type); 18182 18183 if (val.type === 'sexpr') { 18184 // Subexpressions get evaluated and passed in 18185 // in string params mode. 18186 this.sexpr(val); 18187 } 18188 } else { 18189 if (this.trackIds) { 18190 this.opcode('pushId', val.type, val.idName || val.stringModeValue); 18191 } 18192 this.accept(val); 18193 } 18194 }, 18195 18196 setupFullMustacheParams: function(sexpr, program, inverse) { 18197 var params = sexpr.params; 18198 this.pushParams(params); 18199 18200 this.opcode('pushProgram', program); 18201 this.opcode('pushProgram', inverse); 18202 18203 if (sexpr.hash) { 18204 this.hash(sexpr.hash); 18205 } else { 18206 this.opcode('emptyHash'); 18207 } 18208 18209 return params; 18210 } 18211 }; 18212 18213 function precompile(input, options, env) { 18214 if (input == null || (typeof input !== 'string' && input.constructor !== env.AST.ProgramNode)) { 18215 throw new Exception("You must pass a string or Handlebars AST to Handlebars.precompile. You passed " + input); 18216 } 18217 18218 options = options || {}; 18219 if (!('data' in options)) { 18220 options.data = true; 18221 } 18222 if (options.compat) { 18223 options.useDepths = true; 18224 } 18225 18226 var ast = env.parse(input); 18227 var environment = new env.Compiler().compile(ast, options); 18228 return new env.JavaScriptCompiler().compile(environment, options); 18229 } 18230 18231 __exports__.precompile = precompile;function compile(input, options, env) { 18232 if (input == null || (typeof input !== 'string' && input.constructor !== env.AST.ProgramNode)) { 18233 throw new Exception("You must pass a string or Handlebars AST to Handlebars.compile. You passed " + input); 18234 } 18235 18236 options = options || {}; 18237 18238 if (!('data' in options)) { 18239 options.data = true; 18240 } 18241 if (options.compat) { 18242 options.useDepths = true; 18243 } 18244 18245 var compiled; 18246 18247 function compileInput() { 18248 var ast = env.parse(input); 18249 var environment = new env.Compiler().compile(ast, options); 18250 var templateSpec = new env.JavaScriptCompiler().compile(environment, options, undefined, true); 18251 return env.template(templateSpec); 18252 } 18253 18254 // Template is only compiled on first use and cached after that point. 18255 var ret = function(context, options) { 18256 if (!compiled) { 18257 compiled = compileInput(); 18258 } 18259 return compiled.call(this, context, options); 18260 }; 18261 ret._setup = function(options) { 18262 if (!compiled) { 18263 compiled = compileInput(); 18264 } 18265 return compiled._setup(options); 18266 }; 18267 ret._child = function(i, data, depths) { 18268 if (!compiled) { 18269 compiled = compileInput(); 18270 } 18271 return compiled._child(i, data, depths); 18272 }; 18273 return ret; 18274 } 18275 18276 __exports__.compile = compile;function argEquals(a, b) { 18277 if (a === b) { 18278 return true; 18279 } 18280 18281 if (isArray(a) && isArray(b) && a.length === b.length) { 18282 for (var i = 0; i < a.length; i++) { 18283 if (!argEquals(a[i], b[i])) { 18284 return false;
18285 } 18286 } 18287 return true; 18288 } 18289 } 18290 return __exports__; 18291})(__module5__, __module3__); 18292
18293// handlebars/compiler/javascript-compiler.js 18294var __module12__ = (function(__dependency1__, __dependency2__) { 18295 "use strict"; 18296 var __exports__; 18297 var COMPILER_REVISION = __dependency1__.COMPILER_REVISION; 18298 var REVISION_CHANGES = __dependency1__.REVISION_CHANGES; 18299 var Exception = __dependency2__; 18300 18301 function Literal(value) { 18302 this.value = value; 18303 } 18304 18305 function JavaScriptCompiler() {} 18306 18307 JavaScriptCompiler.prototype = { 18308 // PUBLIC API: You can override these methods in a subclass to provide 18309 // alternative compiled forms for name lookup and buffering semantics 18310 nameLookup: function(parent, name /* , type*/) { 18311 if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) { 18312 return parent + "." + name; 18313 } else { 18314 return parent + "['" + name + "']"; 18315 } 18316 }, 18317 depthedLookup: function(name) { 18318 this.aliases.lookup = 'this.lookup'; 18319 18320 return 'lookup(depths, "' + name + '")'; 18321 }, 18322 18323 compilerInfo: function() { 18324 var revision = COMPILER_REVISION, 18325 versions = REVISION_CHANGES[revision]; 18326 return [revision, versions]; 18327 }, 18328 18329 appendToBuffer: function(string) { 18330 if (this.environment.isSimple) { 18331 return "return " + string + ";"; 18332 } else { 18333 return { 18334 appendToBuffer: true, 18335 content: string, 18336 toString: function() { return "buffer += " + string + ";"; } 18337 }; 18338 } 18339 }, 18340 18341 initializeBuffer: function() { 18342 return this.quotedString(""); 18343 }, 18344 18345 namespace: "Handlebars", 18346 // END PUBLIC API 18347 18348 compile: function(environment, options, context, asObject) { 18349 this.environment = environment; 18350 this.options = options; 18351 this.stringParams = this.options.stringParams; 18352 this.trackIds = this.options.trackIds; 18353 this.precompile = !asObject; 18354 18355 this.name = this.environment.name; 18356 this.isChild = !!context; 18357 this.context = context || { 18358 programs: [], 18359 environments: [] 18360 }; 18361 18362 this.preamble(); 18363 18364 this.stackSlot = 0; 18365 this.stackVars = []; 18366 this.aliases = {}; 18367 this.registers = { list: [] }; 18368 this.hashes = []; 18369 this.compileStack = []; 18370 this.inlineStack = []; 18371 18372 this.compileChildren(environment, options); 18373 18374 this.useDepths = this.useDepths || environment.depths.list.length || this.options.compat; 18375 18376 var opcodes = environment.opcodes, 18377 opcode, 18378 i, 18379 l; 18380 18381 for (i = 0, l = opcodes.length; i < l; i++) { 18382 opcode = opcodes[i]; 18383 18384 this[opcode.opcode].apply(this, opcode.args); 18385 } 18386 18387 // Flush any trailing content that might be pending. 18388 this.pushSource(''); 18389 18390 /* istanbul ignore next */ 18391 if (this.stackSlot || this.inlineStack.length || this.compileStack.length) { 18392 throw new Exception('Compile completed with content left on stack'); 18393 } 18394 18395 var fn = this.createFunctionContext(asObject); 18396 if (!this.isChild) { 18397 var ret = { 18398 compiler: this.compilerInfo(), 18399 main: fn 18400 }; 18401 var programs = this.context.programs; 18402 for (i = 0, l = programs.length; i < l; i++) { 18403 if (programs[i]) { 18404 ret[i] = programs[i]; 18405 } 18406 } 18407 18408 if (this.environment.usePartial) { 18409 ret.usePartial = true; 18410 } 18411 if (this.options.data) { 18412 ret.useData = true; 18413 } 18414 if (this.useDepths) { 18415 ret.useDepths = true; 18416 } 18417 if (this.options.compat) { 18418 ret.compat = true; 18419 } 18420 18421 if (!asObject) { 18422 ret.compiler = JSON.stringify(ret.compiler); 18423 ret = this.objectLiteral(ret); 18424 } 18425 18426 return ret; 18427 } else { 18428 return fn; 18429 } 18430 }, 18431 18432 preamble: function() { 18433 // track the last context pushed into place to allow skipping the 18434 // getContext opcode when it would be a noop 18435 this.lastContext = 0; 18436 this.source = []; 18437 }, 18438 18439 createFunctionContext: function(asObject) { 18440 var varDeclarations = ''; 18441 18442 var locals = this.stackVars.concat(this.registers.list); 18443 if(locals.length > 0) { 18444 varDeclarations += ", " + locals.join(", "); 18445 } 18446 18447 // Generate minimizer alias mappings 18448 for (var alias in this.aliases) { 18449 if (this.aliases.hasOwnProperty(alias)) { 18450 varDeclarations += ', ' + alias + '=' + this.aliases[alias]; 18451 } 18452 } 18453 18454 var params = ["depth0", "helpers", "partials", "data"]; 18455 18456 if (this.useDepths) { 18457 params.push('depths'); 18458 } 18459 18460 // Perform a second pass over the output to merge content when possible 18461 var source = this.mergeSource(varDeclarations); 18462 18463 if (asObject) { 18464 params.push(source); 18465 18466 return Function.apply(this, params); 18467 } else {
18468 return 'function(' + params.join(',') + ') {\n ' + source + '}'; 18469 } 18470 }, 18471 mergeSource: function(varDeclarations) { 18472 var source = '', 18473 buffer, 18474 appendOnly = !this.forceBuffer, 18475 appendFirst; 18476 18477 for (var i = 0, len = this.source.length; i < len; i++) { 18478 var line = this.source[i]; 18479 if (line.appendToBuffer) { 18480 if (buffer) { 18481 buffer = buffer + '\n + ' + line.content; 18482 } else { 18483 buffer = line.content; 18484 } 18485 } else { 18486 if (buffer) { 18487 if (!source) { 18488 appendFirst = true; 18489 source = buffer + ';\n '; 18490 } else { 18491 source += 'buffer += ' + buffer + ';\n '; 18492 } 18493 buffer = undefined; 18494 } 18495 source += line + '\n '; 18496 18497 if (!this.environment.isSimple) { 18498 appendOnly = false; 18499 } 18500 } 18501 } 18502 18503 if (appendOnly) { 18504 if (buffer || !source) { 18505 source += 'return ' + (buffer || '""') + ';\n'; 18506 } 18507 } else { 18508 varDeclarations += ", buffer = " + (appendFirst ? '' : this.initializeBuffer()); 18509 if (buffer) { 18510 source += 'return buffer + ' + buffer + ';\n'; 18511 } else { 18512 source += 'return buffer;\n'; 18513 } 18514 } 18515 18516 if (varDeclarations) { 18517 source = 'var ' + varDeclarations.substring(2) + (appendFirst ? '' : ';\n ') + source; 18518 } 18519 18520 return source; 18521 }, 18522 18523 // [blockValue] 18524 // 18525 // On stack, before: hash, inverse, program, value 18526 // On stack, after: return value of blockHelperMissing 18527 // 18528 // The purpose of this opcode is to take a block of the form 18529 // `{{#this.foo}}...{{/this.foo}}`, resolve the value of `foo`, and 18530 // replace it on the stack with the result of properly 18531 // invoking blockHelperMissing. 18532 blockValue: function(name) { 18533 this.aliases.blockHelperMissing = 'helpers.blockHelperMissing'; 18534 18535 var params = [this.contextName(0)]; 18536 this.setupParams(name, 0, params); 18537 18538 var blockName = this.popStack(); 18539 params.splice(1, 0, blockName); 18540 18541 this.push('blockHelperMissing.call(' + params.join(', ') + ')'); 18542 }, 18543 18544 // [ambiguousBlockValue] 18545 // 18546 // On stack, before: hash, inverse, program, value 18547 // Compiler value, before: lastHelper=value of last found helper, if any 18548 // On stack, after, if no lastHelper: same as [blockValue] 18549 // On stack, after, if lastHelper: value 18550 ambiguousBlockValue: function() { 18551 this.aliases.blockHelperMissing = 'helpers.blockHelperMissing'; 18552 18553 // We're being a bit cheeky and reusing the options value from the prior exec 18554 var params = [this.contextName(0)]; 18555 this.setupParams('', 0, params, true); 18556 18557 this.flushInline(); 18558 18559 var current = this.topStack(); 18560 params.splice(1, 0, current); 18561 18562 this.pushSource("if (!" + this.lastHelper + ") { " + current + " = blockHelperMissing.call(" + params.join(", ") + "); }"); 18563 }, 18564 18565 // [appendContent] 18566 // 18567 // On stack, before: ... 18568 // On stack, after: ... 18569 // 18570 // Appends the string value of `content` to the current buffer 18571 appendContent: function(content) { 18572 if (this.pendingContent) { 18573 content = this.pendingContent + content; 18574 } 18575 18576 this.pendingContent = content; 18577 }, 18578 18579 // [append] 18580 // 18581 // On stack, before: value, ... 18582 // On stack, after: ... 18583 // 18584 // Coerces `value` to a String and appends it to the current buffer. 18585 // 18586 // If `value` is truthy, or 0, it is coerced into a string and appended 18587 // Otherwise, the empty string is appended 18588 append: function() { 18589 // Force anything that is inlined onto the stack so we don't have duplication 18590 // when we examine local 18591 this.flushInline(); 18592 var local = this.popStack(); 18593 this.pushSource('if (' + local + ' != null) { ' + this.appendToBuffer(local) + ' }'); 18594 if (this.environment.isSimple) { 18595 this.pushSource("else { " + this.appendToBuffer("''") + " }"); 18596 } 18597 }, 18598 18599 // [appendEscaped] 18600 // 18601 // On stack, before: value, ... 18602 // On stack, after: ... 18603 // 18604 // Escape `value` and append it to the buffer 18605 appendEscaped: function() { 18606 this.aliases.escapeExpression = 'this.escapeExpression'; 18607 18608 this.pushSource(this.appendToBuffer("escapeExpression(" + this.popStack() + ")")); 18609 }, 18610 18611 // [getContext] 18612 // 18613 // On stack, before: ... 18614 // On stack, after: ... 18615 // Compiler value, after: lastContext=depth 18616 // 18617 // Set the value of the `lastContext` compiler value to the depth 18618 getContext: function(depth) { 18619 this.lastContext = depth; 18620 }, 18621 18622 // [pushContext] 18623 // 18624 // On stack, before: ... 18625 // On stack, after: currentContext, ... 18626 // 18627 // Pushes the value of the current context onto the stack. 18628 pushContext: function() { 18629 this.pushStackLiteral(this.contextName(this.lastContext)); 18630 }, 18631 18632 // [lookupOnContext] 18633 // 18634 // On stack, before: ... 18635 // On stack, after: currentContext[name], ... 18636 // 18637 // Looks up the value of `name` on the current context and pushes 18638 // it onto the stack. 18639 lookupOnContext: function(parts, falsy, scoped) { 18640 /*jshint -W083 */ 18641 var i = 0, 18642 len = parts.length; 18643 18644 if (!scoped && this.options.compat && !this.lastContext) { 18645 // The depthed query is expected to handle the undefined logic for the root level that 18646 // is implemented below, so we evaluate that directly in compat mode 18647 this.push(this.depthedLookup(parts[i++])); 18648 } else { 18649 this.pushContext(); 18650 } 18651 18652 for (; i < len; i++) { 18653 this.replaceStack(function(current) { 18654 var lookup = this.nameLookup(current, parts[i], 'context'); 18655 // We want to ensure that zero and false are handled properly if the context (falsy flag) 18656 // needs to have the special handling for these values. 18657 if (!falsy) { 18658 return ' != null ? ' + lookup + ' : ' + current; 18659 } else {
18660 // Otherwise we can use generic falsy handling 18661 return ' && ' + lookup; 18662 } 18663 }); 18664 } 18665 }, 18666 18667 // [lookupData] 18668 // 18669 // On stack, before: ... 18670 // On stack, after: data, ... 18671 // 18672 // Push the data lookup operator 18673 lookupData: function(depth, parts) { 18674 /*jshint -W083 */ 18675 if (!depth) { 18676 this.pushStackLiteral('data'); 18677 } else { 18678 this.pushStackLiteral('this.data(data, ' + depth + ')'); 18679 } 18680 18681 var len = parts.length; 18682 for (var i = 0; i < len; i++) { 18683 this.replaceStack(function(current) { 18684 return ' && ' + this.nameLookup(current, parts[i], 'data'); 18685 }); 18686 } 18687 }, 18688 18689 // [resolvePossibleLambda] 18690 // 18691 // On stack, before: value, ... 18692 // On stack, after: resolved value, ... 18693 // 18694 // If the `value` is a lambda, replace it on the stack by 18695 // the return value of the lambda 18696 resolvePossibleLambda: function() { 18697 this.aliases.lambda = 'this.lambda'; 18698 18699 this.push('lambda(' + this.popStack() + ', ' + this.contextName(0) + ')'); 18700 }, 18701 18702 // [pushStringParam] 18703 // 18704 // On stack, before: ... 18705 // On stack, after: string, currentContext, ... 18706 // 18707 // This opcode is designed for use in string mode, which 18708 // provides the string value of a parameter along with its 18709 // depth rather than resolving it immediately. 18710 pushStringParam: function(string, type) { 18711 this.pushContext(); 18712 this.pushString(type); 18713 18714 // If it's a subexpression, the string result 18715 // will be pushed after this opcode. 18716 if (type !== 'sexpr') { 18717 if (typeof string === 'string') { 18718 this.pushString(string); 18719 } else { 18720 this.pushStackLiteral(string); 18721 } 18722 } 18723 }, 18724 18725 emptyHash: function() { 18726 this.pushStackLiteral('{}'); 18727 18728 if (this.trackIds) { 18729 this.push('{}'); // hashIds 18730 } 18731 if (this.stringParams) { 18732 this.push('{}'); // hashContexts 18733 this.push('{}'); // hashTypes 18734 } 18735 }, 18736 pushHash: function() { 18737 if (this.hash) { 18738 this.hashes.push(this.hash); 18739 } 18740 this.hash = {values: [], types: [], contexts: [], ids: []}; 18741 }, 18742 popHash: function() { 18743 var hash = this.hash; 18744 this.hash = this.hashes.pop(); 18745 18746 if (this.trackIds) { 18747 this.push('{' + hash.ids.join(',') + '}'); 18748 } 18749 if (this.stringParams) { 18750 this.push('{' + hash.contexts.join(',') + '}'); 18751 this.push('{' + hash.types.join(',') + '}'); 18752 } 18753 18754 this.push('{\n ' + hash.values.join(',\n ') + '\n }'); 18755 }, 18756 18757 // [pushString] 18758 // 18759 // On stack, before: ... 18760 // On stack, after: quotedString(string), ... 18761 // 18762 // Push a quoted version of `string` onto the stack 18763 pushString: function(string) { 18764 this.pushStackLiteral(this.quotedString(string)); 18765 }, 18766 18767 // [push] 18768 // 18769 // On stack, before: ... 18770 // On stack, after: expr, ... 18771 // 18772 // Push an expression onto the stack 18773 push: function(expr) { 18774 this.inlineStack.push(expr); 18775 return expr; 18776 }, 18777 18778 // [pushLiteral] 18779 // 18780 // On stack, before: ... 18781 // On stack, after: value, ... 18782 // 18783 // Pushes a value onto the stack. This operation prevents 18784 // the compiler from creating a temporary variable to hold 18785 // it. 18786 pushLiteral: function(value) { 18787 this.pushStackLiteral(value); 18788 }, 18789 18790 // [pushProgram] 18791 // 18792 // On stack, before: ... 18793 // On stack, after: program(guid), ... 18794 // 18795 // Push a program expression onto the stack. This takes 18796 // a compile-time guid and converts it into a runtime-accessible 18797 // expression. 18798 pushProgram: function(guid) { 18799 if (guid != null) { 18800 this.pushStackLiteral(this.programExpression(guid)); 18801 } else { 18802 this.pushStackLiteral(null); 18803 } 18804 }, 18805 18806 // [invokeHelper] 18807 // 18808 // On stack, before: hash, inverse, program, params..., ... 18809 // On stack, after: result of helper invocation 18810 // 18811 // Pops off the helper's parameters, invokes the helper, 18812 // and pushes the helper's return value onto the stack. 18813 // 18814 // If the helper is not found, `helperMissing` is called. 18815 invokeHelper: function(paramSize, name, isSimple) { 18816 this.aliases.helperMissing = 'helpers.helperMissing'; 18817 18818 var nonHelper = this.popStack(); 18819 var helper = this.setupHelper(paramSize, name); 18820 18821 var lookup = (isSimple ? helper.name + ' || ' : '') + nonHelper + ' || helperMissing'; 18822 this.push('((' + lookup + ').call(' + helper.callParams + '))'); 18823 }, 18824 18825 // [invokeKnownHelper] 18826 // 18827 // On stack, before: hash, inverse, program, params..., ... 18828 // On stack, after: result of helper invocation 18829 // 18830 // This operation is used when the helper is known to exist, 18831 // so a `helperMissing` fallback is not required. 18832 invokeKnownHelper: function(paramSize, name) { 18833 var helper = this.setupHelper(paramSize, name); 18834 this.push(helper.name + ".call(" + helper.callParams + ")"); 18835 }, 18836 18837 // [invokeAmbiguous] 18838 // 18839 // On stack, before: hash, inverse, program, params..., ... 18840 // On stack, after: result of disambiguation 18841 // 18842 // This operation is used when an expression like `{{foo}}` 18843 // is provided, but we don't know at compile-time whether it 18844 // is a helper or a path. 18845 // 18846 // This operation emits more code than the other options, 18847 // and can be avoided by passing the `knownHelpers` and 18848 // `knownHelpersOnly` flags at compile-time. 18849 invokeAmbiguous: function(name, helperCall) { 18850 this.aliases.functionType = '"function"'; 18851 this.aliases.helperMissing = 'helpers.helperMissing'; 18852 this.useRegister('helper'); 18853 18854 var nonHelper = this.popStack(); 18855 18856 this.emptyHash(); 18857 var helper = this.setupHelper(0, name, helperCall); 18858 18859 var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper'); 18860 18861 this.push( 18862 '((helper = (helper = ' + helperName + ' || ' + nonHelper + ') != null ? helper : helperMissing' 18863 + (helper.paramsInit ? '),(' + helper.paramsInit : '') + '),' 18864 + '(typeof helper === functionType ? helper.call(' + helper.callParams + ')
18864: helper))'); 18865 }, 18866 18867 // [invokePartial] 18868 // 18869 // On stack, before: context, ... 18870 // On stack after: result of partial invocation 18871 // 18872 // This operation pops off a context, invokes a partial with that context, 18873 // and pushes the result of the invocation back. 18874 invokePartial: function(name, indent) { 18875 var params = [this.nameLookup('partials', name, 'partial'), "'" + indent + "'", "'" + name + "'", this.popStack(), this.popStack(), "helpers", "partials"]; 18876 18877 if (this.options.data) { 18878 params.push("data"); 18879 } else if (this.options.compat) { 18880 params.push('undefined'); 18881 } 18882 if (this.options.compat) { 18883 params.push('depths'); 18884 } 18885 18886 this.push("this.invokePartial(" + params.join(", ") + ")"); 18887 }, 18888 18889 // [assignToHash] 18890 // 18891 // On stack, before: value, ..., hash, ... 18892 // On stack, after: ..., hash, ... 18893 // 18894 // Pops a value off the stack and assigns it to the current hash 18895 assignToHash: function(key) { 18896 var value = this.popStack(), 18897 context, 18898 type, 18899 id; 18900 18901 if (this.trackIds) { 18902 id = this.popStack(); 18903 } 18904 if (this.stringParams) { 18905 type = this.popStack(); 18906 context = this.popStack(); 18907 } 18908 18909 var hash = this.hash; 18910 if (context) { 18911 hash.contexts.push("'" + key + "': " + context); 18912 } 18913 if (type) { 18914 hash.types.push("'" + key + "': " + type); 18915 } 18916 if (id) { 18917 hash.ids.push("'" + key + "': " + id); 18918 } 18919 hash.values.push("'" + key + "': (" + value + ")"); 18920 }, 18921 18922 pushId: function(type, name) { 18923 if (type === 'ID' || type === 'DATA') { 18924 this.pushString(name); 18925 } else if (type === 'sexpr') { 18926 this.pushStackLiteral('true'); 18927 } else { 18928 this.pushStackLiteral('null'); 18929 } 18930 }, 18931 18932 // HELPERS 18933 18934 compiler: JavaScriptCompiler, 18935 18936 compileChildren: function(environment, options) { 18937 var children = environment.children, child, compiler; 18938 18939 for(var i=0, l=children.length; i<l; i++) { 18940 child = children[i]; 18941 compiler = new this.compiler(); 18942 18943 var index = this.matchExistingProgram(child); 18944 18945 if (index == null) { 18946 this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children 18947 index = this.context.programs.length; 18948 child.index = index; 18949 child.name = 'program' + index; 18950 this.context.programs[index] = compiler.compile(child, options, this.context, !this.precompile); 18951 this.context.environments[index] = child; 18952 18953 this.useDepths = this.useDepths || compiler.useDepths; 18954 } else { 18955 child.index = index; 18956 child.name = 'program' + index; 18957 } 18958 } 18959 }, 18960 matchExistingProgram: function(child) { 18961 for (var i = 0, len = this.context.environments.length; i < len; i++) { 18962 var environment = this.context.environments[i]; 18963 if (environment && environment.equals(child)) { 18964 return i; 18965 } 18966 } 18967 }, 18968 18969 programExpression: function(guid) { 18970 var child = this.environment.children[guid], 18971 depths = child.depths.list, 18972 useDepths = this.useDepths, 18973 depth; 18974 18975 var programParams = [child.index, 'data']; 18976 18977 if (useDepths) { 18978 programParams.push('depths'); 18979 } 18980 18981 return 'this.program(' + programParams.join(', ') + ')'; 18982 }, 18983 18984 useRegister: function(name) { 18985 if(!this.registers[name]) { 18986 this.registers[name] = true; 18987 this.registers.list.push(name); 18988 } 18989 }, 18990 18991 pushStackLiteral: function(item) { 18992 return this.push(new Literal(item)); 18993 }, 18994 18995 pushSource: function(source) { 18996 if (this.pendingContent) { 18997 this.source.push(this.appendToBuffer(this.quotedString(this.pendingContent))); 18998 this.pendingContent = undefined; 18999 } 19000 19001 if (source) { 19002 this.source.push(source); 19003 } 19004 }, 19005 19006 pushStack: function(item) { 19007 this.flushInline(); 19008 19009 var stack = this.incrStack(); 19010 this.pushSource(stack + " = " + item + ";"); 19011 this.compileStack.push(stack); 19012 return stack; 19013 }, 19014 19015 replaceStack: function(callback) { 19016 var prefix = '', 19017 inline = this.isInline(), 19018 stack, 19019 createdStack, 19020 usedLiteral; 19021 19022 /* istanbul ignore next */ 19023 if (!this.isInline()) { 19024 throw new Exception('replaceStack on non-inline'); 19025 } 19026 19027 // We want to merge the inline statement into the replacement statement via ',' 19028 var top = this.popStack(true); 19029 19030 if (top instanceof Literal) { 19031 // Literals do not need to be inlined 19032 prefix = stack = top.value; 19033 usedLiteral = true; 19034 } else { 19035 // Get or create the current stack name for use by the inline 19036 createdStack = !this.stackSlot; 19037 var name = !createdStack ? this.topStackName() : this.incrStack(); 19038 19039 prefix = '(' + this.push(name) + ' = ' + top + ')'; 19040 stack = this.topStack(); 19041 } 19042 19043 var item = callback.call(this, stack); 19044 19045 if (!usedLiteral) { 19046 this.popStack(); 19047 } 19048 if (createdStack) { 19049 this.stackSlot--; 19050 } 19051 this.push('(' + prefix + item + ')'); 19052 }, 19053 19054 incrStack: function() { 19055 this.stackSlot++; 19056 if(this.stackSlot > this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); } 19057 return this.topStackName(); 19058 }, 19059 topStackName: function() { 19060 return "stack" + this.stackSlot; 19061 }, 19062 flushInline: function() { 19063 var inlineStack = this.inlineStack; 19064 if (inlineStack.length) { 19065 this.inlineStack = []; 19066 for (var i = 0, len = inlineStack.length; i < len; i++) { 19067 var entry = inlineStack[i]; 19068 if (entry instanceof Literal) { 19069 this.compileStack.push(entry); 19070 } else { 19071 this.pushStack(entry); 19072 } 19073 } 19074 } 19075 }, 19076 isInline: function() { 19077 return this.inlineStack.length; 19078 }, 19079 19080 popStack: function(wrapped) { 19081 var inline = this.isInline(), 19082 item = (inline ? this.inlineStack : this.compileStack).pop(); 19083 19084 if (!wrapped && (item instanceof Literal)) { 19085 return item.value; 19086 } else { 19087 if (!inline) { 19088 /* istanbul ignore next */ 19089 if (!this.stackSlot) { 19090 throw new Exception('Invalid stack pop'); 19091 } 19092 this.stackSlot--; 19093 } 19094 return item; 19095 } 19096 }, 19097 19098 topStack: function() { 19099 var stack = (this.isInline() ? this.inlineStack : this.compileStack), 19100 item = stack[stack.length - 1]; 19101 19102 if (item instanceof Literal) { 19103 return item.value; 19104 } else { 19105 return item; 19106 } 19107 }, 19108 19109 contextName: function(context) { 19110 if (this.useDepths && context) { 19111 return 'depths[' + context + ']'; 19112 } else { 19113 return 'depth' + context; 19114 } 19115 }, 19116 19117 quotedString: function(str) { 19118 return '"' + str 19119 .replace(/\\/g, '\\\\') 19120 .replace(/"/g, '\\"') 19121 .replace(/\n/g, '\\n') 19122 .replace(/\r/g, '\\r') 19123 .replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4 19124 .replace(/\u2029/g, '\\u2029') + '"'; 19125 }, 19126
19127 objectLiteral: function(obj) { 19128 var pairs = []; 19129 19130 for (var key in obj) { 19131 if (obj.hasOwnProperty(key)) { 19132 pairs.push(this.quotedString(key) + ':' + obj[key]); 19133 } 19134 } 19135 19136 return '{' + pairs.join(',') + '}'; 19137 }, 19138 19139 setupHelper: function(paramSize, name, blockHelper) { 19140 var params = [], 19141 paramsInit = this.setupParams(name, paramSize, params, blockHelper); 19142 var foundHelper = this.nameLookup('helpers', name, 'helper'); 19143 19144 return { 19145 params: params, 19146 paramsInit: paramsInit, 19147 name: foundHelper, 19148 callParams: [this.contextName(0)].concat(params).join(", ") 19149 }; 19150 }, 19151 19152 setupOptions: function(helper, paramSize, params) { 19153 var options = {}, contexts = [], types = [], ids = [], param, inverse, program; 19154 19155 options.name = this.quotedString(helper); 19156 options.hash = this.popStack(); 19157 19158 if (this.trackIds) { 19159 options.hashIds = this.popStack(); 19160 } 19161 if (this.stringParams) { 19162 options.hashTypes = this.popStack(); 19163 options.hashContexts = this.popStack(); 19164 } 19165 19166 inverse = this.popStack(); 19167 program = this.popStack(); 19168 19169 // Avoid setting fn and inverse if neither are set. This allows 19170 // helpers to do a check for `if (options.fn)` 19171 if (program || inverse) { 19172 if (!program) { 19173 program = 'this.noop'; 19174 } 19175 19176 if (!inverse) { 19177 inverse = 'this.noop'; 19178 } 19179 19180 options.fn = program; 19181 options.inverse = inverse; 19182 } 19183 19184 // The parameters go on to the stack in order (making sure that they are evaluated in order) 19185 // so we need to pop them off the stack in reverse order 19186 var i = paramSize; 19187 while (i--) { 19188 param = this.popStack(); 19189 params[i] = param; 19190 19191 if (this.trackIds) { 19192 ids[i] = this.popStack(); 19193 } 19194 if (this.stringParams) { 19195 types[i] = this.popStack(); 19196 contexts[i] = this.popStack(); 19197 } 19198 } 19199 19200 if (this.trackIds) { 19201 options.ids = "[" + ids.join(",") + "]"; 19202 } 19203 if (this.stringParams) { 19204 options.types = "[" + types.join(",") + "]"; 19205 options.contexts = "[" + contexts.join(",") + "]"; 19206 } 19207 19208 if (this.options.data) { 19209 options.data = "data"; 19210 } 19211 19212 return options; 19213 }, 19214 19215 // the params and contexts arguments are passed in arrays 19216 // to fill in 19217 setupParams: function(helperName, paramSize, params, useRegister) { 19218 var options = this.objectLiteral(this.setupOptions(helperName, paramSize, params)); 19219 19220 if (useRegister) { 19221 this.useRegister('options'); 19222 params.push('options'); 19223 return 'options=' + options; 19224 } else { 19225 params.push(options); 19226 return ''; 19227 } 19228 } 19229 }; 19230 19231 var reservedWords = ( 19232 "break else new var" + 19233 " case finally return void" + 19234 " catch for switch while" + 19235 " continue function this with" + 19236 " default if throw" + 19237 " delete in try" + 19238 " do instanceof typeof" + 19239 " abstract enum int short" + 19240 " boolean export interface static" + 19241 " byte extends long super" + 19242 " char final native synchronized" + 19243 " class float package throws" + 19244 " const goto private transient" + 19245 " debugger implements protected volatile" + 19246 " double import public let yield" 19247 ).split(" "); 19248 19249 var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {}; 19250 19251 for(var i=0, l=reservedWords.length; i<l; i++) { 19252 compilerWords[reservedWords[i]] = true; 19253 } 19254 19255 JavaScriptCompiler.isValidJavaScriptVariableName = function(name) { 19256 return !JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name); 19257 }; 19258 19259 __exports__ = JavaScriptCompiler; 19260 return __exports__; 19261})(__module2__, __module5__); 19262 19263// handlebars.js 19264var __module0__ = (function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__) { 19265 "use strict"; 19266 var __exports__; 19267 /*globals Handlebars: true */ 19268 var Handlebars = __dependency1__; 19269 19270 // Compiler imports 19271 var AST = __dependency2__; 19272 var Parser = __dependency3__.parser; 19273 var parse = __dependency3__.parse; 19274 var Compiler = __dependency4__.Compiler; 19275 var compile = __dependency4__.compile; 19276 var precompile = __dependency4__.precompile; 19277 var JavaScriptCompiler = __dependency5__; 19278 19279 var _create = Handlebars.create; 19280 var create = function() { 19281 var hb = _create(); 19282 19283 hb.compile = function(input, options) { 19284 return compile(input, options, hb); 19285 }; 19286 hb.precompile = function (input, options) { 19287 return precompile(input, options, hb); 19288 }; 19289 19290 hb.AST = AST; 19291 hb.Compiler = Compiler; 19292 hb.JavaScriptCompiler = JavaScriptCompiler; 19293 hb.Parser = Parser; 19294 hb.parse = parse; 19295 19296 return hb; 19297 }; 19298 19299 Handlebars = create(); 19300 Handlebars.create = create; 19301 19302 Handlebars['default'] = Handlebars; 19303 19304 __exports__ = Handlebars; 19305 return __exports__; 19306})(__module1__, __module7__, __module8__, __module11__, __module12__); 19307 19308 return __module0__; 19309})); 19310 19311/*! 19312 * typeahead.js 0.10.5 19313 * https://github.com/twitter/typeahead.js 19314 * Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT 19315 */ 19316 19317(function($) { 19318 var _ = function() { 19319 "use strict"; 19320 return { 19321 isMsie: function() { 19322 return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false;
vendor: 1,592 bytes, lines 19323-19367
19323 }, 19324 isBlankString: function(str) { 19325 return !str || /^\s*$/.test(str); 19326 }, 19327 escapeRegExChars: function(str) { 19328 return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); 19329 }, 19330 isString: function(obj) { 19331 return typeof obj === "string"; 19332 }, 19333 isNumber: function(obj) { 19334 return typeof obj === "number"; 19335 }, 19336 isArray: $.isArray, 19337 isFunction: $.isFunction, 19338 isObject: $.isPlainObject, 19339 isUndefined: function(obj) { 19340 return typeof obj === "undefined"; 19341 }, 19342 toStr: function toStr(s) { 19343 return _.isUndefined(s) || s === null ? "" : s + ""; 19344 }, 19345 bind: $.proxy, 19346 each: function(collection, cb) { 19347 $.each(collection, reverseArgs); 19348 function reverseArgs(index, value) { 19349 return cb(value, index); 19350 } 19351 }, 19352 map: $.map, 19353 filter: $.grep, 19354 every: function(obj, test) { 19355 var result = true; 19356 if (!obj) { 19357 return result; 19358 } 19359 $.each(obj, function(key, val) { 19360 if (!(result = test.call(null, val, key, obj))) { 19361 return false; 19362 } 19363 }); 19364 return !!result; 19365 }, 19366 some: function(obj, test) { 19367 var result = false;
19368 if (!obj) { 19369 return result; 19370 } 19371 $.each(obj, function(key, val) { 19372 if (result = test.call(null, val, key, obj)) { 19373 return false; 19374 } 19375 }); 19376 return !!result; 19377 }, 19378 mixin: $.extend, 19379 getUniqueId: function() { 19380 var counter = 0; 19381 return function() { 19382 return counter++; 19383 }; 19384 }(), 19385 templatify: function templatify(obj) { 19386 return $.isFunction(obj) ? obj : template; 19387 function template() { 19388 return String(obj); 19389 } 19390 }, 19391 defer: function(fn) { 19392 setTimeout(fn, 0); 19393 }, 19394 debounce: function(func, wait, immediate) { 19395 var timeout, result; 19396 return function() { 19397 var context = this, args = arguments, later, callNow; 19398 later = function() { 19399 timeout = null; 19400 if (!immediate) { 19401 result = func.apply(context, args); 19402 } 19403 }; 19404 callNow = immediate && !timeout; 19405 clearTimeout(timeout); 19406 timeout = setTimeout(later, wait); 19407 if (callNow) { 19408 result = func.apply(context, args); 19409 } 19410 return result; 19411 }; 19412 }, 19413 throttle: function(func, wait) { 19414 var context, args, timeout, result, previous, later; 19415 previous = 0; 19416 later = function() { 19417 previous = new Date(); 19418 timeout = null; 19419 result = func.apply(context, args); 19420 }; 19421 return function() { 19422 var now = new Date(), remaining = wait - (now - previous); 19423 context = this; 19424 args = arguments; 19425 if (remaining <= 0) { 19426 clearTimeout(timeout); 19427 timeout = null; 19428 previous = now; 19429 result = func.apply(context, args); 19430 } else if (!timeout) { 19431 timeout = setTimeout(later, remaining); 19432 } 19433 return result; 19434 }; 19435 }, 19436 noop: function() {} 19437 }; 19438 }(); 19439 var html = function() { 19440 return { 19441 wrapper: '<span class="twitter-typeahead"></span>', 19442 dropdown: '<span class="tt-dropdown-menu"></span>', 19443 dataset: '<div class="tt-dataset-%CLASS%"></div>', 19444 suggestions: '<span class="tt-suggestions"></span>', 19445 suggestion: '<div class="tt-suggestion"></div>' 19446 }; 19447 }(); 19448 var css = function() { 19449 "use strict"; 19450 var css = { 19451 wrapper: { 19452 position: "relative", 19453 display: "inline-block" 19454 }, 19455 hint: { 19456 position: "absolute", 19457 top: "0", 19458 left: "0", 19459 borderColor: "transparent", 19460 boxShadow: "none", 19461 opacity: "1" 19462 }, 19463 input: { 19464 position: "relative", 19465 verticalAlign: "top", 19466 backgroundColor: "transparent" 19467 }, 19468 inputWithNoHint: { 19469 position: "relative", 19470 verticalAlign: "top" 19471 }, 19472 dropdown: { 19473 position: "absolute", 19474 top: "100%", 19475 left: "0", 19476 zIndex: "100", 19477 display: "none" 19478 }, 19479 suggestions: { 19480 display: "block" 19481 }, 19482 suggestion: { 19483 whiteSpace: "nowrap", 19484 cursor: "pointer" 19485 }, 19486 suggestionChild: { 19487 whiteSpace: "normal" 19488 }, 19489 ltr: { 19490 left: "0", 19491 right: "auto" 19492 }, 19493 rtl: { 19494 left: "auto", 19495 right: " 0" 19496 } 19497 }; 19498 if (_.isMsie()) { 19499 _.mixin(css.input, { 19500 backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)" 19501 }); 19502 } 19503 if (_.isMsie() && _.isMsie() <= 7) { 19504 _.mixin(css.input, { 19505 marginTop: "-1px" 19506 }); 19507 } 19508 return css; 19509 }(); 19510 var EventBus = function() { 19511 "use strict"; 19512 var namespace = "typeahead:"; 19513 function EventBus(o) { 19514 if (!o || !o.el) { 19515 $.error("EventBus initialized without el"); 19516 } 19517 this.$el = $(o.el); 19518 } 19519 _.mixin(EventBus.prototype, { 19520 trigger: function(type) { 19521 var args = [].slice.call(arguments, 1); 19522 this.$el.trigger(namespace + type, args); 19523 } 19524 }); 19525 return EventBus; 19526 }(); 19527 var EventEmitter = function() { 19528 "use strict"; 19529 var splitter = /\s+/, nextTick = getNextTick(); 19530 return { 19531 onSync: onSync, 19532 onAsync: onAsync,
vendor: 6,364 bytes, lines 19533-19698
19533 off: off, 19534 trigger: trigger 19535 }; 19536 function on(method, types, cb, context) { 19537 var type; 19538 if (!cb) { 19539 return this; 19540 } 19541 types = types.split(splitter); 19542 cb = context ? bindContext(cb, context) : cb; 19543 this._callbacks = this._callbacks || {}; 19544 while (type = types.shift()) { 19545 this._callbacks[type] = this._callbacks[type] || { 19546 sync: [], 19547 async: [] 19548 }; 19549 this._callbacks[type][method].push(cb); 19550 } 19551 return this; 19552 } 19553 function onAsync(types, cb, context) { 19554 return on.call(this, "async", types, cb, context); 19555 } 19556 function onSync(types, cb, context) { 19557 return on.call(this, "sync", types, cb, context); 19558 } 19559 function off(types) { 19560 var type; 19561 if (!this._callbacks) { 19562 return this; 19563 } 19564 types = types.split(splitter); 19565 while (type = types.shift()) { 19566 delete this._callbacks[type]; 19567 } 19568 return this; 19569 } 19570 function trigger(types) { 19571 var type, callbacks, args, syncFlush, asyncFlush; 19572 if (!this._callbacks) { 19573 return this; 19574 } 19575 types = types.split(splitter); 19576 args = [].slice.call(arguments, 1); 19577 while ((type = types.shift()) && (callbacks = this._callbacks[type])) { 19578 syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args)); 19579 asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args)); 19580 syncFlush() && nextTick(asyncFlush); 19581 } 19582 return this; 19583 } 19584 function getFlush(callbacks, context, args) { 19585 return flush; 19586 function flush() { 19587 var cancelled; 19588 for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) { 19589 cancelled = callbacks[i].apply(context, args) === false; 19590 } 19591 return !cancelled; 19592 } 19593 } 19594 function getNextTick() { 19595 var nextTickFn; 19596 if (window.setImmediate) { 19597 nextTickFn = function nextTickSetImmediate(fn) { 19598 setImmediate(function() { 19599 fn(); 19600 }); 19601 }; 19602 } else { 19603 nextTickFn = function nextTickSetTimeout(fn) { 19604 setTimeout(function() { 19605 fn(); 19606 }, 0); 19607 }; 19608 } 19609 return nextTickFn; 19610 } 19611 function bindContext(fn, context) { 19612 return fn.bind ? fn.bind(context) : function() { 19613 fn.apply(context, [].slice.call(arguments, 0)); 19614 }; 19615 } 19616 }(); 19617 var highlight = function(doc) { 19618 "use strict"; 19619 var defaults = { 19620 node: null, 19621 pattern: null, 19622 tagName: "strong", 19623 className: null, 19624 wordsOnly: false, 19625 caseSensitive: false 19626 }; 19627 return function hightlight(o) { 19628 var regex; 19629 o = _.mixin({}, defaults, o); 19630 if (!o.node || !o.pattern) { 19631 return; 19632 } 19633 o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ]; 19634 regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly); 19635 traverse(o.node, hightlightTextNode); 19636 function hightlightTextNode(textNode) { 19637 var match, patternNode, wrapperNode; 19638 if (match = regex.exec(textNode.data)) { 19639 wrapperNode = doc.createElement(o.tagName); 19640 o.className && (wrapperNode.className = o.className); 19641 patternNode = textNode.splitText(match.index); 19642 patternNode.splitText(match[0].length); 19643 wrapperNode.appendChild(patternNode.cloneNode(true)); 19644 textNode.parentNode.replaceChild(wrapperNode, patternNode); 19645 } 19646 return !!match; 19647 } 19648 function traverse(el, hightlightTextNode) { 19649 var childNode, TEXT_NODE_TYPE = 3; 19650 for (var i = 0; i < el.childNodes.length; i++) { 19651 childNode = el.childNodes[i]; 19652 if (childNode.nodeType === TEXT_NODE_TYPE) { 19653 i += hightlightTextNode(childNode) ? 1 : 0; 19654 } else { 19655 traverse(childNode, hightlightTextNode); 19656 } 19657 } 19658 } 19659 }; 19660 function getRegex(patterns, caseSensitive, wordsOnly) { 19661 var escapedPatterns = [], regexStr; 19662 for (var i = 0, len = patterns.length; i < len; i++) { 19663 escapedPatterns.push(_.escapeRegExChars(patterns[i])); 19664 } 19665 regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")"; 19666 return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, "i"); 19667 } 19668 }(window.document); 19669 var Input = function() { 19670 "use strict"; 19671 var specialKeyCodeMap; 19672 specialKeyCodeMap = { 19673 9: "tab", 19674 27: "esc", 19675 37: "left", 19676 39: "right", 19677 13: "enter", 19678 38: "up", 19679 40: "down" 19680 }; 19681 function Input(o) { 19682 var that = this, onBlur, onFocus, onKeydown, onInput; 19683 o = o || {}; 19684 if (!o.input) { 19685 $.error("input is missing"); 19686 } 19687 onBlur = _.bind(this._onBlur, this); 19688 onFocus = _.bind(this._onFocus, this); 19689 onKeydown = _.bind(this._onKeydown, this); 19690 onInput = _.bind(this._onInput, this); 19691 this.$hint = $(o.hint); 19692 this.$input = $(o.input).on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown); 19693 if (this.$hint.length === 0) { 19694 this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop; 19695 } 19696 if (!_.isMsie()) { 19697 this.$input.on("input.tt", onInput); 19698 } else {
vendor: 1,932 bytes, lines 19699-19745
19699 this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) { 19700 if (specialKeyCodeMap[$e.which || $e.keyCode]) { 19701 return; 19702 } 19703 _.defer(_.bind(that._onInput, that, $e)); 19704 }); 19705 } 19706 this.query = this.$input.val(); 19707 this.$overflowHelper = buildOverflowHelper(this.$input); 19708 } 19709 Input.normalizeQuery = function(str) { 19710 return (str || "").replace(/^\s*/g, "").replace(/\s{2,}/g, " "); 19711 }; 19712 _.mixin(Input.prototype, EventEmitter, { 19713 _onBlur: function onBlur() { 19714 this.resetInputValue(); 19715 this.trigger("blurred"); 19716 }, 19717 _onFocus: function onFocus() { 19718 this.trigger("focused"); 19719 }, 19720 _onKeydown: function onKeydown($e) { 19721 var keyName = specialKeyCodeMap[$e.which || $e.keyCode]; 19722 this._managePreventDefault(keyName, $e); 19723 if (keyName && this._shouldTrigger(keyName, $e)) { 19724 this.trigger(keyName + "Keyed", $e); 19725 } 19726 }, 19727 _onInput: function onInput() { 19728 this._checkInputValue(); 19729 }, 19730 _managePreventDefault: function managePreventDefault(keyName, $e) { 19731 var preventDefault, hintValue, inputValue; 19732 switch (keyName) { 19733 case "tab": 19734 hintValue = this.getHint(); 19735 inputValue = this.getInputValue(); 19736 preventDefault = hintValue && hintValue !== inputValue && !withModifier($e); 19737 break; 19738 19739 case "up": 19740 case "down": 19741 preventDefault = !withModifier($e); 19742 break; 19743 19744 default: 19745 preventDefault = false;
19746 } 19747 preventDefault && $e.preventDefault(); 19748 }, 19749 _shouldTrigger: function shouldTrigger(keyName, $e) { 19750 var trigger; 19751 switch (keyName) { 19752 case "tab": 19753 trigger = !withModifier($e); 19754 break; 19755 19756 default: 19757 trigger = true; 19758 } 19759 return trigger; 19760 }, 19761 _checkInputValue: function checkInputValue() { 19762 var inputValue, areEquivalent, hasDifferentWhitespace; 19763 inputValue = this.getInputValue(); 19764 areEquivalent = areQueriesEquivalent(inputValue, this.query); 19765 hasDifferentWhitespace = areEquivalent ? this.query.length !== inputValue.length : false; 19766 this.query = inputValue; 19767 if (!areEquivalent) { 19768 this.trigger("queryChanged", this.query); 19769 } else if (hasDifferentWhitespace) { 19770 this.trigger("whitespaceChanged", this.query); 19771 } 19772 }, 19773 focus: function focus() { 19774 this.$input.focus(); 19775 }, 19776 blur: function blur() { 19777 this.$input.blur(); 19778 }, 19779 getQuery: function getQuery() { 19780 return this.query; 19781 }, 19782 setQuery: function setQuery(query) { 19783 this.query = query; 19784 }, 19785 getInputValue: function getInputValue() { 19786 return this.$input.val(); 19787 }, 19788 setInputValue: function setInputValue(value, silent) { 19789 this.$input.val(value); 19790 silent ? this.clearHint() : this._checkInputValue(); 19791 }, 19792 resetInputValue: function resetInputValue() { 19793 this.setInputValue(this.query, true); 19794 }, 19795 getHint: function getHint() { 19796 return this.$hint.val(); 19797 }, 19798 setHint: function setHint(value) { 19799 this.$hint.val(value); 19800 }, 19801 clearHint: function clearHint() { 19802 this.setHint(""); 19803 }, 19804 clearHintIfInvalid: function clearHintIfInvalid() { 19805 var val, hint, valIsPrefixOfHint, isValid; 19806 val = this.getInputValue(); 19807 hint = this.getHint(); 19808 valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0; 19809 isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow(); 19810 !isValid && this.clearHint(); 19811 }, 19812 getLanguageDirection: function getLanguageDirection() { 19813 return (this.$input.css("direction") || "ltr").toLowerCase(); 19814 }, 19815 hasOverflow: function hasOverflow() { 19816 var constraint = this.$input.width() - 2; 19817 this.$overflowHelper.text(this.getInputValue()); 19818 return this.$overflowHelper.width() >= constraint; 19819 }, 19820 isCursorAtEnd: function() { 19821 var valueLength, selectionStart, range; 19822 valueLength = this.$input.val().length; 19823 selectionStart = this.$input[0].selectionStart; 19824 if (_.isNumber(selectionStart)) { 19825 return selectionStart === valueLength; 19826 } else if (document.selection) { 19827 range = document.selection.createRange(); 19828 range.moveStart("character", -valueLength); 19829 return valueLength === range.text.length; 19830 } 19831 return true; 19832 }, 19833 destroy: function destroy() { 19834 this.$hint.off(".tt"); 19835 this.$input.off(".tt"); 19836 this.$hint = this.$input = this.$overflowHelper = null; 19837 } 19838 }); 19839 return Input; 19840 function buildOverflowHelper($input) { 19841 return $('<pre aria-hidden="true"></pre>').css({ 19842 position: "absolute", 19843 visibility: "hidden", 19844 whiteSpace: "pre", 19845 fontFamily: $input.css("font-family"), 19846 fontSize: $input.css("font-size"), 19847 fontStyle: $input.css("font-style"), 19848 fontVariant: $input.css("font-variant"), 19849 fontWeight: $input.css("font-weight"), 19850 wordSpacing: $input.css("word-spacing"), 19851 letterSpacing: $input.css("letter-spacing"), 19852 textIndent: $input.css("text-indent"), 19853 textRendering: $input.css("text-rendering"), 19854 textTransform: $input.css("text-transform") 19855 }).insertAfter($input); 19856 } 19857 function areQueriesEquivalent(a, b) { 19858 return Input.normalizeQuery(a) === Input.normalizeQuery(b); 19859 } 19860 function withModifier($e) { 19861 return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey; 19862 } 19863 }(); 19864 var Dataset = function() { 19865 "use strict"; 19866 var datasetKey = "ttDataset", valueKey = "ttValue", datumKey = "ttDatum"; 19867 function Dataset(o) { 19868 o = o || {}; 19869 o.templates = o.templates || {}; 19870 if (!o.source) { 19871 $.error("missing source"); 19872 } 19873 if (o.name && !isValidName(o.name)) { 19874 $.error("invalid dataset name: " + o.name); 19875 } 19876 this.query = null; 19877 this.highlight = !!o.highlight; 19878 this.name = o.name || _.getUniqueId(); 19879 this.source = o.source; 19880 this.displayFn = getDisplayFn(o.display || o.displayKey); 19881 this.templates = getTemplates(o.templates, this.displayFn); 19882 this.$el = $(html.dataset.replace("%CLASS%", this.name)); 19883 } 19884 Dataset.extractDatasetName = function extractDatasetName(el) { 19885 return $(el).data(datasetKey); 19886 }; 19887 Dataset.extractValue = function extractDatum(el) { 19888 return $(el).data(valueKey); 19889 }; 19890 Dataset.extractDatum = function extractDatum(el) { 19891 return $(el).data(datumKey); 19892 }; 19893 _.mixin(Dataset.prototype, EventEmitter, { 19894 _render: function render(query, suggestions) { 19895 if (!this.$el) { 19896 return; 19897 } 19898 var that = this, hasSuggestions; 19899 this.$el.empty(); 19900 hasSuggestions = suggestions && suggestions.length; 19901 if (!hasSuggestions && this.templates.empty) { 19902 this.$el.html(getEmptyHtml()).prepend(that.templates.header ? getHeaderHtml() : null).append(that.templates.footer ? getFooterHtml() : null); 19903 } else if (hasSuggestions) { 19904 this.$el.html(getSuggestionsHtml()).prepend(that.templates.header ? getHeaderHtml() : null).append(that.templates.footer ? getFooterHtml() : null); 19905 } 19906 this.trigger("rendered"); 19907 function getEmptyHtml() { 19908 return that.templates.empty({ 19909 query: query, 19910 isEmpty: true 19911 }); 19912 } 19913 function getSuggestionsHtml() { 19914 var $suggestions, nodes; 19915 $suggestions = $(html.suggestions).css(css.suggestions); 19916 nodes = _.map(suggestions, getSuggestionNode); 19917 $suggestions.append.apply($suggestions, nodes); 19918 that.highlight && highlight({ 19919 className: "tt-highlight", 19920 node: $suggestions[0], 19921 pattern: query 19922 }); 19923 return $suggestions; 19924 function getSuggestionNode(suggestion) { 19925 var $el; 19926 $el = $(html.suggestion).append(that.templates.suggestion(suggestion)).data(datasetKey, that.name).data(valueKey, that.displayFn(suggestion)).data(datumKey, suggestion); 19927 $el.children().each(function() { 19928 $(this).css(css.suggestionChild); 19929 }); 19930 return $el; 19931 } 19932 } 19933 function getHeaderHtml() { 19934 return that.templates.header({ 19935 query: query, 19936 isEmpty: !hasSuggestions 19937 }); 19938 } 19939 function getFooterHtml() { 19940 return that.templates.footer({ 19941 query: query, 19942 isEmpty: !hasSuggestions 19943 }); 19944 } 19945 }, 19946 getRoot: function getRoot() { 19947 return this.$el; 19948 }, 19949 update: function update(query) { 19950 var that = this; 19951 this.query = query; 19952 this.canceled = false;
19953 this.source(query, render); 19954 function render(suggestions) { 19955 if (!that.canceled && query === that.query) { 19956 that._render(query, suggestions); 19957 } 19958 } 19959 }, 19960 cancel: function cancel() { 19961 this.canceled = true; 19962 }, 19963 clear: function clear() { 19964 this.cancel(); 19965 this.$el.empty(); 19966 this.trigger("rendered"); 19967 }, 19968 isEmpty: function isEmpty() { 19969 return this.$el.is(":empty"); 19970 }, 19971 destroy: function destroy() { 19972 this.$el = null; 19973 } 19974 }); 19975 return Dataset; 19976 function getDisplayFn(display) { 19977 display = display || "value"; 19978 return _.isFunction(display) ? display : displayFn; 19979 function displayFn(obj) { 19980 return obj[display]; 19981 } 19982 } 19983 function getTemplates(templates, displayFn) { 19984 return { 19985 empty: templates.empty && _.templatify(templates.empty), 19986 header: templates.header && _.templatify(templates.header), 19987 footer: templates.footer && _.templatify(templates.footer), 19988 suggestion: templates.suggestion || suggestionTemplate 19989 }; 19990 function suggestionTemplate(context) { 19991 return "<p>" + displayFn(context) + "</p>"; 19992 } 19993 } 19994 function isValidName(str) { 19995 return /^[_a-zA-Z0-9-]+$/.test(str); 19996 } 19997 }(); 19998 var Dropdown = function() { 19999 "use strict"; 20000 function Dropdown(o) { 20001 var that = this, onSuggestionClick, onSuggestionMouseEnter, onSuggestionMouseLeave; 20002 o = o || {}; 20003 if (!o.menu) { 20004 $.error("menu is required"); 20005 } 20006 this.isOpen = false; 20007 this.isEmpty = true; 20008 this.datasets = _.map(o.datasets, initializeDataset); 20009 onSuggestionClick = _.bind(this._onSuggestionClick, this); 20010 onSuggestionMouseEnter = _.bind(this._onSuggestionMouseEnter, this); 20011 onSuggestionMouseLeave = _.bind(this._onSuggestionMouseLeave, this); 20012 this.$menu = $(o.menu).on("click.tt", ".tt-suggestion", onSuggestionClick).on("mouseenter.tt", ".tt-suggestion", onSuggestionMouseEnter).on("mouseleave.tt", ".tt-suggestion", onSuggestionMouseLeave); 20013 _.each(this.datasets, function(dataset) { 20014 that.$menu.append(dataset.getRoot()); 20015 dataset.onSync("rendered", that._onRendered, that); 20016 }); 20017 } 20018 _.mixin(Dropdown.prototype, EventEmitter, { 20019 _onSuggestionClick: function onSuggestionClick($e) { 20020 this.trigger("suggestionClicked", $($e.currentTarget)); 20021 }, 20022 _onSuggestionMouseEnter: function onSuggestionMouseEnter($e) { 20023 this._removeCursor(); 20024 this._setCursor($($e.currentTarget), true); 20025 }, 20026 _onSuggestionMouseLeave: function onSuggestionMouseLeave() { 20027 this._removeCursor(); 20028 }, 20029 _onRendered: function onRendered() { 20030 this.isEmpty = _.every(this.datasets, isDatasetEmpty); 20031 this.isEmpty ? this._hide() : this.isOpen && this._show(); 20032 this.trigger("datasetRendered"); 20033 function isDatasetEmpty(dataset) { 20034 return dataset.isEmpty(); 20035 } 20036 }, 20037 _hide: function() { 20038 this.$menu.hide(); 20039 }, 20040 _show: function() { 20041 this.$menu.css("display", "block"); 20042 }, 20043 _getSuggestions: function getSuggestions() { 20044 return this.$menu.find(".tt-suggestion"); 20045 }, 20046 _getCursor: function getCursor() { 20047 return this.$menu.find(".tt-cursor").first(); 20048 }, 20049 _setCursor: function setCursor($el, silent) { 20050 $el.first().addClass("tt-cursor"); 20051 !silent && this.trigger("cursorMoved"); 20052 },
20053 _removeCursor: function removeCursor() { 20054 this._getCursor().removeClass("tt-cursor"); 20055 }, 20056 _moveCursor: function moveCursor(increment) { 20057 var $suggestions, $oldCursor, newCursorIndex, $newCursor; 20058 if (!this.isOpen) { 20059 return; 20060 } 20061 $oldCursor = this._getCursor(); 20062 $suggestions = this._getSuggestions(); 20063 this._removeCursor(); 20064 newCursorIndex = $suggestions.index($oldCursor) + increment; 20065 newCursorIndex = (newCursorIndex + 1) % ($suggestions.length + 1) - 1; 20066 if (newCursorIndex === -1) { 20067 this.trigger("cursorRemoved"); 20068 return; 20069 } else if (newCursorIndex < -1) { 20070 newCursorIndex = $suggestions.length - 1; 20071 } 20072 this._setCursor($newCursor = $suggestions.eq(newCursorIndex)); 20073 this._ensureVisible($newCursor); 20074 }, 20075 _ensureVisible: function ensureVisible($el) { 20076 var elTop, elBottom, menuScrollTop, menuHeight; 20077 elTop = $el.position().top; 20078 elBottom = elTop + $el.outerHeight(true); 20079 menuScrollTop = this.$menu.scrollTop(); 20080 menuHeight = this.$menu.height() + parseInt(this.$menu.css("paddingTop"), 10) + parseInt(this.$menu.css("paddingBottom"), 10); 20081 if (elTop < 0) { 20082 this.$menu.scrollTop(menuScrollTop + elTop); 20083 } else if (menuHeight < elBottom) { 20084 this.$menu.scrollTop(menuScrollTop + (elBottom - menuHeight)); 20085 } 20086 }, 20087 close: function close() { 20088 if (this.isOpen) { 20089 this.isOpen = false; 20090 this._removeCursor(); 20091 this._hide(); 20092 this.trigger("closed"); 20093 } 20094 }, 20095 open: function open() { 20096 if (!this.isOpen) { 20097 this.isOpen = true; 20098 !this.isEmpty && this._show(); 20099 this.trigger("opened"); 20100 } 20101 }, 20102 setLanguageDirection: function setLanguageDirection(dir) { 20103 this.$menu.css(dir === "ltr" ? css.ltr : css.rtl); 20104 }, 20105 moveCursorUp: function moveCursorUp() { 20106 this._moveCursor(-1); 20107 }, 20108 moveCursorDown: function moveCursorDown() { 20109 this._moveCursor(+1); 20110 }, 20111 getDatumForSuggestion: function getDatumForSuggestion($el) { 20112 var datum = null; 20113 if ($el.length) { 20114 datum = { 20115 raw: Dataset.extractDatum($el), 20116 value: Dataset.extractValue($el), 20117 datasetName: Dataset.extractDatasetName($el) 20118 }; 20119 } 20120 return datum; 20121 }, 20122 getDatumForCursor: function getDatumForCursor() { 20123 return this.getDatumForSuggestion(this._getCursor().first()); 20124 }, 20125 getDatumForTopSuggestion: function getDatumForTopSuggestion() { 20126 return this.getDatumForSuggestion(this._getSuggestions().first()); 20127 }, 20128 update: function update(query) { 20129 _.each(this.datasets, updateDataset); 20130 function updateDataset(dataset) { 20131 dataset.update(query); 20132 } 20133 }, 20134 empty: function empty() { 20135 _.each(this.datasets, clearDataset); 20136 this.isEmpty = true; 20137 function clearDataset(dataset) { 20138 dataset.clear(); 20139 } 20140 }, 20141 isVisible: function isVisible() { 20142 return this.isOpen && !this.isEmpty; 20143 }, 20144 destroy: function destroy() { 20145 this.$menu.off(".tt"); 20146 this.$menu = null; 20147 _.each(this.datasets, destroyDataset); 20148 function destroyDataset(dataset) { 20149 dataset.destroy(); 20150 } 20151 } 20152 }); 20153 return Dropdown; 20154 function initializeDataset(oDataset) { 20155 return new Dataset(oDataset); 20156 } 20157 }(); 20158 var Typeahead = function() { 20159 "use strict"; 20160 var attrsKey = "ttAttrs"; 20161 function Typeahead(o) { 20162 var $menu, $input, $hint; 20163 o = o || {}; 20164 if (!o.input) { 20165 $.error("missing input"); 20166 } 20167 this.isActivated = false;
20168 this.autoselect = !!o.autoselect; 20169 this.minLength = _.isNumber(o.minLength) ? o.minLength : 1; 20170 this.$node = buildDom(o.input, o.withHint); 20171 $menu = this.$node.find(".tt-dropdown-menu"); 20172 $input = this.$node.find(".tt-input"); 20173 $hint = this.$node.find(".tt-hint"); 20174 $input.on("blur.tt", function($e) { 20175 var active, isActive, hasActive; 20176 active = document.activeElement; 20177 isActive = $menu.is(active); 20178 hasActive = $menu.has(active).length > 0; 20179 if (_.isMsie() && (isActive || hasActive)) { 20180 $e.preventDefault(); 20181 $e.stopImmediatePropagation(); 20182 _.defer(function() { 20183 $input.focus(); 20184 }); 20185 } 20186 }); 20187 $menu.on("mousedown.tt", function($e) { 20188 $e.preventDefault(); 20189 }); 20190 this.eventBus = o.eventBus || new EventBus({ 20191 el: $input 20192 }); 20193 this.dropdown = new Dropdown({ 20194 menu: $menu, 20195 datasets: o.datasets 20196 }).onSync("suggestionClicked", this._onSuggestionClicked, this).onSync("cursorMoved", this._onCursorMoved, this).onSync("cursorRemoved", this._onCursorRemoved, this).onSync("opened", this._onOpened, this).onSync("closed", this._onClosed, this).onAsync("datasetRendered", this._onDatasetRendered, this); 20197 this.input = new Input({ 20198 input: $input, 20199 hint: $hint 20200 }).onSync("focused", this._onFocused, this).onSync("blurred", this._onBlurred, this).onSync("enterKeyed", this._onEnterKeyed, this).onSync("tabKeyed", this._onTabKeyed, this).onSync("escKeyed", this._onEscKeyed, this).onSync("upKeyed", this._onUpKeyed, this).onSync("downKeyed", this._onDownKeyed, this).onSync("leftKeyed", this._onLeftKeyed, this).onSync("rightKeyed", this._onRightKeyed, this).onSync("queryChanged", this._onQueryChanged, this).onSync("whitespaceChanged", this._onWhitespaceChanged, this); 20201 this._setLanguageDirection(); 20202 } 20203 _.mixin(Typeahead.prototype, { 20204 _onSuggestionClicked: function onSuggestionClicked(type, $el) { 20205 var datum; 20206 if (datum = this.dropdown.getDatumForSuggestion($el)) { 20207 this._select(datum); 20208 } 20209 }, 20210 _onCursorMoved: function onCursorMoved() { 20211 var datum = this.dropdown.getDatumForCursor(); 20212 this.input.setInputValue(datum.value, true); 20213 this.eventBus.trigger("cursorchanged", datum.raw, datum.datasetName); 20214 }, 20215 _onCursorRemoved: function onCursorRemoved() { 20216 this.input.resetInputValue(); 20217 this._updateHint(); 20218 }, 20219 _onDatasetRendered: function onDatasetRendered() { 20220 this._updateHint(); 20221 }, 20222 _onOpened: function onOpened() { 20223 this._updateHint(); 20224 this.eventBus.trigger("opened"); 20225 }, 20226 _onClosed: function onClosed() { 20227 this.input.clearHint(); 20228 this.eventBus.trigger("closed"); 20229 }, 20230 _onFocused: function onFocused() { 20231 this.isActivated = true; 20232 this.dropdown.open(); 20233 }, 20234 _onBlurred: function onBlurred() { 20235 this.isActivated = false; 20236 this.dropdown.empty(); 20237 this.dropdown.close(); 20238 }, 20239 _onEnterKeyed: function onEnterKeyed(type, $e) { 20240 var cursorDatum, topSuggestionDatum; 20241 cursorDatum = this.dropdown.getDatumForCursor(); 20242 topSuggestionDatum = this.dropdown.getDatumForTopSuggestion(); 20243 if (cursorDatum) { 20244 this._select(cursorDatum); 20245 $e.preventDefault(); 20246 } else if (this.autoselect && topSuggestionDatum) { 20247 this._select(topSuggestionDatum); 20248 $e.preventDefault(); 20249 } 20250 }, 20251 _onTabKeyed: function onTabKeyed(type, $e) { 20252 var datum;
20253 if (datum = this.dropdown.getDatumForCursor()) { 20254 this._select(datum); 20255 $e.preventDefault(); 20256 } else { 20257 this._autocomplete(true); 20258 } 20259 }, 20260 _onEscKeyed: function onEscKeyed() { 20261 this.dropdown.close(); 20262 this.input.resetInputValue(); 20263 }, 20264 _onUpKeyed: function onUpKeyed() { 20265 var query = this.input.getQuery(); 20266 this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorUp(); 20267 this.dropdown.open(); 20268 }, 20269 _onDownKeyed: function onDownKeyed() { 20270 var query = this.input.getQuery(); 20271 this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorDown(); 20272 this.dropdown.open(); 20273 }, 20274 _onLeftKeyed: function onLeftKeyed() { 20275 this.dir === "rtl" && this._autocomplete(); 20276 }, 20277 _onRightKeyed: function onRightKeyed() { 20278 this.dir === "ltr" && this._autocomplete(); 20279 }, 20280 _onQueryChanged: function onQueryChanged(e, query) { 20281 this.input.clearHintIfInvalid(); 20282 query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.empty(); 20283 this.dropdown.open(); 20284 this._setLanguageDirection(); 20285 }, 20286 _onWhitespaceChanged: function onWhitespaceChanged() { 20287 this._updateHint(); 20288 this.dropdown.open(); 20289 }, 20290 _setLanguageDirection: function setLanguageDirection() { 20291 var dir; 20292 if (this.dir !== (dir = this.input.getLanguageDirection())) { 20293 this.dir = dir; 20294 this.$node.css("direction", dir); 20295 this.dropdown.setLanguageDirection(dir); 20296 } 20297 }, 20298 _updateHint: function updateHint() { 20299 var datum, val, query, escapedQuery, frontMatchRegEx, match; 20300 datum = this.dropdown.getDatumForTopSuggestion(); 20301 if (datum && this.dropdown.isVisible() && !this.input.hasOverflow()) { 20302 val = this.input.getInputValue(); 20303 query = Input.normalizeQuery(val); 20304 escapedQuery = _.escapeRegExChars(query); 20305 frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i"); 20306 match = frontMatchRegEx.exec(datum.value); 20307 match ? this.input.setHint(val + match[1]) : this.input.clearHint(); 20308 } else { 20309 this.input.clearHint(); 20310 } 20311 }, 20312 _autocomplete: function autocomplete(laxCursor) { 20313 var hint, query, isCursorAtEnd, datum; 20314 hint = this.input.getHint(); 20315 query = this.input.getQuery(); 20316 isCursorAtEnd = laxCursor || this.input.isCursorAtEnd(); 20317 if (hint && query !== hint && isCursorAtEnd) { 20318 datum = this.dropdown.getDatumForTopSuggestion(); 20319 datum && this.input.setInputValue(datum.value); 20320 this.eventBus.trigger("autocompleted", datum.raw, datum.datasetName); 20321 } 20322 }, 20323 _select: function select(datum) { 20324 this.input.setQuery(datum.value); 20325 this.input.setInputValue(datum.value, true); 20326 this._setLanguageDirection(); 20327 this.eventBus.trigger("selected", datum.raw, datum.datasetName); 20328 this.dropdown.close(); 20329 _.defer(_.bind(this.dropdown.empty, this.dropdown)); 20330 }, 20331 open: function open() { 20332 this.dropdown.open(); 20333 }, 20334 close: function close() { 20335 this.dropdown.close(); 20336 }, 20337 setVal: function setVal(val) { 20338 val = _.toStr(val); 20339 if (this.isActivated) { 20340 this.input.setInputValue(val); 20341 } else { 20342 this.input.setQuery(val); 20343 this.input.setInputValue(val, true); 20344 } 20345 this._setLanguageDirection(); 20346 }, 20347 getVal: function getVal() { 20348 return this.input.getQuery(); 20349 }, 20350 destroy: function destroy() { 20351 this.input.destroy(); 20352 this.dropdown.destroy(); 20353 destroyDomStructure(this.$node); 20354 this.$node = null; 20355 } 20356 }); 20357 return Typeahead; 20358 function buildDom(input, withHint) { 20359 var $input, $wrapper, $dropdown, $hint; 20360 $input = $(input); 20361 $wrapper = $(html.wrapper).css(css.wrapper); 20362 $dropdown = $(html.dropdown).css(css.dropdown); 20363 $hint = $input.clone().css(css.hint).css(getBackgroun
20363dStyles($input)); 20364 $hint.val("").removeData().addClass("tt-hint").removeAttr("id name placeholder required").prop("readonly", true).attr({ 20365 autocomplete: "off", 20366 spellcheck: "false", 20367 tabindex: -1 20368 }); 20369 $input.data(attrsKey, { 20370 dir: $input.attr("dir"), 20371 autocomplete: $input.attr("autocomplete"), 20372 spellcheck: $input.attr("spellcheck"), 20373 style: $input.attr("style") 20374 }); 20375 $input.addClass("tt-input").attr({ 20376 autocomplete: "off", 20377 spellcheck: false 20378 }).css(withHint ? css.input : css.inputWithNoHint); 20379 try { 20380 !$input.attr("dir") && $input.attr("dir", "auto"); 20381 } catch (e) {} 20382 return $input.wrap($wrapper).parent().prepend(withHint ? $hint : null).append($dropdown); 20383 } 20384 function getBackgroundStyles($el) { 20385 return { 20386 backgroundAttachment: $el.css("background-attachment"), 20387 backgroundClip: $el.css("background-clip"), 20388 backgroundColor: $el.css("background-color"), 20389 backgroundImage: $el.css("background-image"), 20390 backgroundOrigin: $el.css("background-origin"), 20391 backgroundPosition: $el.css("background-position"), 20392 backgroundRepeat: $el.css("background-repeat"), 20393 backgroundSize: $el.css("background-size") 20394 }; 20395 } 20396 function destroyDomStructure($node) { 20397 var $input = $node.find(".tt-input"); 20398 _.each($input.data(attrsKey), function(val, key) { 20399 _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val); 20400 }); 20401 $input.detach().removeData(attrsKey).removeClass("tt-input").insertAfter($node); 20402 $node.remove(); 20403 } 20404 }(); 20405 (function() { 20406 "use strict"; 20407 var old, typeaheadKey, methods; 20408 old = $.fn.typeahead; 20409 typeaheadKey = "ttTypeahead"; 20410 methods = { 20411 initialize: function initialize(o, datasets) { 20412 datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1); 20413 o = o || {}; 20414 return this.each(attach); 20415 function attach() { 20416 var $input = $(this), eventBus, typeahead; 20417 _.each(datasets, function(d) { 20418 d.highlight = !!o.highlight; 20419 }); 20420 typeahead = new Typeahead({ 20421 input: $input, 20422 eventBus: eventBus = new EventBus({ 20423 el: $input 20424 }), 20425 withHint: _.isUndefined(o.hint) ? true : !!o.hint, 20426 minLength: o.minLength, 20427 autoselect: o.autoselect, 20428 datasets: datasets 20429 }); 20430 $input.data(typeaheadKey, typeahead); 20431 } 20432 }, 20433 open: function open() { 20434 return this.each(openTypeahead); 20435 function openTypeahead() { 20436 var $input = $(this), typeahead; 20437 if (typeahead = $input.data(typeaheadKey)) { 20438 typeahead.open(); 20439 } 20440 } 20441 }, 20442 close: function close() { 20443 return this.each(closeTypeahead); 20444 function closeTypeahead() { 20445 var $input = $(this), typeahead; 20446 if (typeahead = $input.data(typeaheadKey)) { 20447 typeahead.close(); 20448 } 20449 } 20450 }, 20451 val: function val(newVal) { 20452 return !arguments.length ? getVal(this.first()) : this.each(setVal); 20453 function setVal() { 20454 var $input = $(this), typeahead; 20455 if (typeahead = $input.data(typeaheadKey)) {
20456 typeahead.setVal(newVal); 20457 } 20458 } 20459 function getVal($input) { 20460 var typeahead, query; 20461 if (typeahead = $input.data(typeaheadKey)) { 20462 query = typeahead.getVal(); 20463 } 20464 return query; 20465 } 20466 }, 20467 destroy: function destroy() { 20468 return this.each(unattach); 20469 function unattach() { 20470 var $input = $(this), typeahead; 20471 if (typeahead = $input.data(typeaheadKey)) { 20472 typeahead.destroy(); 20473 $input.removeData(typeaheadKey); 20474 } 20475 } 20476 } 20477 }; 20478 $.fn.typeahead = function(method) { 20479 var tts; 20480 if (methods[method] && method !== "initialize") { 20481 tts = this.filter(function() { 20482 return !!$(this).data(typeaheadKey); 20483 }); 20484 return methods[method].apply(tts, [].slice.call(arguments, 1)); 20485 } else { 20486 return methods.initialize.apply(this, arguments); 20487 } 20488 }; 20489 $.fn.typeahead.noConflict = function noConflict() { 20490 $.fn.typeahead = old; 20491 return this; 20492 }; 20493 })(); 20494})(window.jQuery); 20495/*! 20496 * headroom.js v0.7.0 - Give your page some headroom. Hide your header until you need it 20497 * Copyright (c) 2014 Nick Williams - http://wicky.nillia.ms/headroom.js 20498 * License: MIT 20499 */ 20500 20501(function(window, document) { 20502 20503 'use strict'; 20504 20505 /* exported features */ 20506 20507 var features = { 20508 bind : !!(function(){}.bind), 20509 classList : 'classList' in document.documentElement, 20510 rAF : !!(window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame) 20511 }; 20512 window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame; 20513 20514 /** 20515 * Handles debouncing of events via requestAnimationFrame 20516 * @see http://www.html5rocks.com/en/tutorials/speed/animations/ 20517 * @param {Function} callback The callback to handle whichever event 20518 */ 20519 function Debouncer (callback) { 20520 this.callback = callback; 20521 this.ticking = false; 20522 } 20523 Debouncer.prototype = { 20524 constructor : Debouncer, 20525 20526 /** 20527 * dispatches the event to the supplied callback 20528 * @private 20529 */ 20530 update : function() { 20531 this.callback && this.callback(); 20532 this.ticking = false; 20533 }, 20534 20535 /** 20536 * ensures events don't get stacked 20537 * @private 20538 */ 20539 requestTick : function() { 20540 if(!this.ticking) { 20541 requestAnimationFrame(this.rafCallback || (this.rafCallback = this.update.bind(this))); 20542 this.ticking = true; 20543 } 20544 }, 20545 20546 /** 20547 * Attach this as the event listeners 20548 */ 20549 handleEvent : function() { 20550 this.requestTick(); 20551 } 20552 }; 20553 /** 20554 * Check if object is part of the DOM 20555 * @constructor 20556 * @param {Object} obj element to check 20557 */ 20558 function isDOMElement(obj) { 20559 return obj && typeof window !== 'undefined' && (obj === window || obj.nodeType); 20560 } 20561 20562 /** 20563 * Helper function for extending objects 20564 */ 20565 function extend (object /*, objectN ... */) { 20566 if(arguments.length <= 0) { 20567 throw new Error('Missing arguments in extend function'); 20568 } 20569 20570 var result = object || {}, 20571 key, 20572 i; 20573 20574 for (i = 1; i < arguments.length; i++) { 20575 var replacement = arguments[i] || {}; 20576 20577 for (key in replacement) { 20578 // Recurse into object except if the object is a DOM element 20579 if(typeof result[key] === 'object' && ! isDOMElement(result[key])) { 20580 result[key] = extend(result[key], replacement[key]); 20581 } 20582 else { 20583 result[key] = result[key] || replacement[key]; 20584 } 20585 } 20586 } 20587 20588 return result; 20589 } 20590 20591 /** 20592 * Helper function for normalizing tolerance option to object format 20593 */ 20594 function normalizeTolerance (t) { 20595 return t === Object(t) ? t : { down : t, up : t }; 20596 } 20597 20598 /** 20599 * UI enhancement for fixed headers. 20600 * Hides header when scrolling down 20601 * Shows header when scrolling up 20602 * @constructor 20603 * @param {DOMElement} elem the header element 20604 * @param {Object} options options for the widget 20605 */ 20606 function Headroom (elem, options) { 20607 options = extend(options, Headroom.options); 20608 20609 this.lastKnownScrollY = 0; 20610 this.elem = elem; 20611 this.debouncer = new Debouncer(this.update.bind(this)); 20612 this.tolerance = normalizeTolerance(options.tolerance); 20613 this.classes = options.classes; 20614 this.offset = options.offset; 20615 this.scroller = options.scroller; 20616 this.initialised = false;
20617 this.onPin = options.onPin; 20618 this.onUnpin = options.onUnpin; 20619 this.onTop = options.onTop; 20620 this.onNotTop = options.onNotTop; 20621 } 20622 Headroom.prototype = { 20623 constructor : Headroom, 20624 20625 /** 20626 * Initialises the widget 20627 */ 20628 init : function() { 20629 if(!Headroom.cutsTheMustard) { 20630 return; 20631 } 20632 20633 this.elem.classList.add(this.classes.initial); 20634 20635 // defer event registration to handle browser 20636 // potentially restoring previous scroll position 20637 setTimeout(this.attachEvent.bind(this), 100); 20638 20639 return this; 20640 }, 20641 20642 /** 20643 * Unattaches events and removes any classes that were added 20644 */ 20645 destroy : function() { 20646 var classes = this.classes; 20647 20648 this.initialised = false; 20649 this.elem.classList.remove(classes.unpinned, classes.pinned, classes.top, classes.initial); 20650 this.scroller.removeEventListener('scroll', this.debouncer, false); 20651 }, 20652 20653 /** 20654 * Attaches the scroll event 20655 * @private 20656 */ 20657 attachEvent : function() { 20658 if(!this.initialised){ 20659 this.lastKnownScrollY = this.getScrollY(); 20660 this.initialised = true; 20661 this.scroller.addEventListener('scroll', this.debouncer, false); 20662 20663 this.debouncer.handleEvent(); 20664 } 20665 }, 20666 20667 /** 20668 * Unpins the header if it's currently pinned 20669 */ 20670 unpin : function() { 20671 var classList = this.elem.classList, 20672 classes = this.classes; 20673 20674 if(classList.contains(classes.pinned) || !classList.contains(classes.unpinned)) { 20675 classList.add(classes.unpinned); 20676 classList.remove(classes.pinned); 20677 this.onUnpin && this.onUnpin.call(this); 20678 } 20679 }, 20680 20681 /** 20682 * Pins the header if it's currently unpinned 20683 */ 20684 pin : function() { 20685 var classList = this.elem.classList, 20686 classes = this.classes; 20687 20688 if(classList.contains(classes.unpinned)) { 20689 classList.remove(classes.unpinned); 20690 classList.add(classes.pinned); 20691 this.onPin && this.onPin.call(this); 20692 } 20693 }, 20694 20695 /** 20696 * Handles the top states 20697 */ 20698 top : function() { 20699 var classList = this.elem.classList, 20700 classes = this.classes; 20701 20702 if(!classList.contains(classes.top)) { 20703 classList.add(classes.top); 20704 classList.remove(classes.notTop); 20705 this.onTop && this.onTop.call(this); 20706 } 20707 }, 20708 20709 /** 20710 * Handles the not top state 20711 */ 20712 notTop : function() { 20713 var classList = this.elem.classList, 20714 classes = this.classes; 20715 20716 if(!classList.contains(classes.notTop)) { 20717 classList.add(classes.notTop); 20718 classList.remove(classes.top); 20719 this.onNotTop && this.onNotTop.call(this); 20720 } 20721 }, 20722 20723 /** 20724 * Gets the Y scroll position 20725 * @see https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollY 20726 * @return {Number} pixels the page has scrolled along the Y-axis 20727 */ 20728 getScrollY : function() { 20729 return (this.scroller.pageYOffset !== undefined) 20730 ? this.scroller.pageYOffset 20731 : (this.scroller.scrollTop !== undefined) 20732 ? this.scroller.scrollTop 20733 : (document.documentElement || document.body.parentNode || document.body).scrollTop; 20734 }, 20735 20736 /** 20737 * Gets the height of the viewport 20738 * @see http://andylangton.co.uk/blog/development/get-viewport-size-width-and-height-javascript 20739 * @return {int} the height of the viewport in pixels 20740 */ 20741 getViewportHeight : function () { 20742 return window.innerHeight 20743 || document.documentElement.clientHeight 20744 || document.body.clientHeight; 20745 }, 20746 20747 /** 20748 * Gets the height of the document 20749 * @see http://james.padolsey.com/javascript/get-document-height-cross-browser/ 20750 * @return {int} the height of the document in pixels 20751 */ 20752 getDocumentHeight : function () { 20753 var body = document.body, 20754 documentElement = document.documentElement; 20755 20756 return Math.max( 20757 body.scrollHeight, documentElement.scrollHeight, 20758 body.offsetHeight, documentElement.offsetHeight, 20759 body.clientHeight, documentElement.clientHeight 20760 ); 20761 }, 20762 20763 /** 20764 * Gets the height of the DOM element 20765 * @param {Object} elm the element to calculate the height of which 20766 * @return {int} the height of the element in pixels 20767 */ 20768 getElementHeight : function (elm) { 20769 return Math.max( 20770 elm.scrollHeight, 20771 elm.offsetHeight, 20772 elm.clientHeight 20773 ); 20774 }, 20775 20776 /** 20777 * Gets the height of the scroller element 20778 * @return {int} the height of the scroller element in pixels 20779 */ 20780 getScrollerHeight : function () { 20781 return (this.scroller === window || this.scroller === document.body) 20782 ? this.getDocumentHeight() 20783 : this.getElementHeight(this.scroller); 20784 }, 20785 20786 /** 20787 * determines if the scroll position is outside of document boundaries 20788 * @param {int} currentScrollY the current y scroll position 20789 * @return {bool} true if out of bounds, false otherwise 20790 */ 20791 isOutOfBounds : function (currentScrollY) { 20792 var pastTop = currentScrollY < 0,
20793 pastBottom = currentScrollY + this.getViewportHeight() > this.getScrollerHeight(); 20794 20795 return pastTop || pastBottom; 20796 }, 20797 20798 /** 20799 * determines if the tolerance has been exceeded 20800 * @param {int} currentScrollY the current scroll y position 20801 * @return {bool} true if tolerance exceeded, false otherwise 20802 */ 20803 toleranceExceeded : function (currentScrollY, direction) { 20804 return Math.abs(currentScrollY-this.lastKnownScrollY) >= this.tolerance[direction]; 20805 }, 20806 20807 /** 20808 * determine if it is appropriate to unpin 20809 * @param {int} currentScrollY the current y scroll position 20810 * @param {bool} toleranceExceeded has the tolerance been exceeded? 20811 * @return {bool} true if should unpin, false otherwise 20812 */ 20813 shouldUnpin : function (currentScrollY, toleranceExceeded) { 20814 var scrollingDown = currentScrollY > this.lastKnownScrollY, 20815 pastOffset = currentScrollY >= this.offset; 20816 20817 return scrollingDown && pastOffset && toleranceExceeded; 20818 }, 20819 20820 /** 20821 * determine if it is appropriate to pin 20822 * @param {int} currentScrollY the current y scroll position 20823 * @param {bool} toleranceExceeded has the tolerance been exceeded? 20824 * @return {bool} true if should pin, false otherwise 20825 */ 20826 shouldPin : function (currentScrollY, toleranceExceeded) { 20827 var scrollingUp = currentScrollY < this.lastKnownScrollY, 20828 pastOffset = currentScrollY <= this.offset; 20829 20830 return (scrollingUp && toleranceExceeded) || pastOffset; 20831 }, 20832 20833 /** 20834 * Handles updating the state of the widget 20835 */ 20836 update : function() { 20837 var currentScrollY = this.getScrollY(), 20838 scrollDirection = currentScrollY > this.lastKnownScrollY ? 'down' : 'up', 20839 toleranceExceeded = this.toleranceExceeded(currentScrollY, scrollDirection); 20840 20841 if(this.isOutOfBounds(currentScrollY)) { // Ignore bouncy scrolling in OSX 20842 return; 20843 } 20844 20845 if (currentScrollY <= this.offset ) { 20846 this.top(); 20847 } else { 20848 this.notTop(); 20849 } 20850 20851 if(this.shouldUnpin(currentScrollY, toleranceExceeded)) { 20852 this.unpin(); 20853 } 20854 else if(this.shouldPin(currentScrollY, toleranceExceeded)) { 20855 this.pin(); 20856 } 20857 20858 this.lastKnownScrollY = currentScrollY; 20859 } 20860 }; 20861 /** 20862 * Default options 20863 * @type {Object} 20864 */ 20865 Headroom.options = { 20866 tolerance : { 20867 up : 0, 20868 down : 0 20869 }, 20870 offset : 0, 20871 scroller: window, 20872 classes : { 20873 pinned : 'headroom--pinned', 20874 unpinned : 'headroom--unpinned', 20875 top : 'headroom--top', 20876 notTop : 'headroom--not-top', 20877 initial : 'headroom' 20878 } 20879 }; 20880 Headroom.cutsTheMustard = typeof features !== 'undefined' && features.rAF && features.bind && features.classList; 20881 20882 window.Headroom = Headroom; 20883 20884}(window, document)); 20885 20886/*! 20887 * headroom.js v0.7.0 - Give your page some headroom. Hide your header until you need it 20888 * Copyright (c) 2014 Nick Williams - http://wicky.nillia.ms/headroom.js 20889 * License: MIT 20890 */ 20891 20892(function($) { 20893 20894 if(!$) { 20895 return; 20896 } 20897 20898 //////////// 20899 // Plugin // 20900 //////////// 20901 20902 $.fn.headroom = function(option) { 20903 return this.each(function() { 20904 var $this = $(this), 20905 data = $this.data('headroom'), 20906 options = typeof option === 'object' && option; 20907 20908 options = $.extend(true, {}, Headroom.options, options); 20909 20910 if (!data) { 20911 data = new Headroom(this, options); 20912 data.init(); 20913 $this.data('headroom', data); 20914 } 20915 if (typeof option === 'string') { 20916 data[option](); 20917 } 20918 }); 20919 }; 20920 20921 ////////////// 20922 // Data API // 20923 ////////////// 20924 20925 $('[data-headroom]').each(function() { 20926 var $this = $(this); 20927 $this.headroom($this.data()); 20928 }); 20929 20930}(window.Zepto || window.jQuery)); 20931/*! 20932 * jQuery Cookie Plugin v1.4.1 20933 * https://github.com/carhartl/jquery-cookie 20934 * 20935 * Copyright 2013 Klaus Hartl 20936 * Released under the MIT license 20937 */ 20938(function (factory) { 20939 if (typeof define === 'function' && define.amd) { 20940 // AMD 20941 define(['jquery'], factory); 20942 } else if (typeof exports === 'object') { 20943 // CommonJS 20944 factory(require('jquery')); 20945 } else { 20946 // Browser globals 20947 factory(jQuery); 20948 } 20949}(function ($) { 20950 20951 var pluses = /\+/g; 20952 20953 function encode(s) { 20954 return config.raw ? s : encodeURIComponent(s); 20955 } 20956 20957 function decode(s) { 20958 return config.raw ? s : decodeURIComponent(s); 20959 } 20960 20961 function stringifyCookieValue(value) { 20962 return encode(config.json ? JSON.stringify(value) : String(value)); 20963 } 20964 20965 function parseCookieValue(s) { 20966 if (s.indexOf('"') === 0) { 20967 // This is a quoted cookie as according to RFC2068, unescape... 20968 s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\'); 20969 } 20970 20971 try { 20972 // Replace server-side written pluses with spaces. 20973 // If we can't decode the cookie, ignore it, it's unusable. 20974 // If we can't parse the cookie, ignore it, it's unusable. 20975 s = decodeURIComponent(s.replace(pluses, ' ')); 20976 return config.json ? JSON.parse(s) : s; 20977 } catch(e) {} 20978 } 20979 20980 function read(s, converter) { 20981 var value = config.raw ? s : parseCookieValue(s); 20982 return $.isFunction(converter) ? converter(value) : value; 20983 } 20984 20985 var config = $.cookie = function (key, value, options) { 20986 20987 // Write 20988 20989 if (value !== undefined && !$.isFunction(value)) { 20990 options = $.extend({}, config.defaults, options); 20991 20992 if (typeof options.expires === 'number') { 20993 var days = options.expires, t = options.expires = new Date(); 20994 t.setTime(+t + days * 864e+5); 20995 } 20996 20997 return (document.cookie = [ 20998 encode(key), '=', stringifyCookieValue(value), 20999 options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE 21000 options.path ? '; path=' + options.path : '', 21001 options.domain ? '; domain=' + options.domain : '', 21002 options.secure ? '; secure' : '' 21003 ].join('')); 21004 } 21005 21006 // Read 21007 21008 var result = key ? undefined : {}; 21009 21010 // To prevent the for loop in the first place assign an empty array 21011 // in case there are no cookies at all. Also prevents odd result when 21012 // calling $.cookie(). 21013 var cookies = document.cookie ? document.cookie.split('; ') : []; 21014 21015 for (var i = 0, l = cookies.length; i < l; i++) { 21016 var parts = cookies[i].split('='); 21017 var name = decode(parts.shift()); 21018 var cookie = parts.join('='); 21019 21020 if (key && key === name) { 21021 // If second argument (value) is a function it's a converter... 21022 result = read(cookie, value); 21023 break; 21024 } 21025 21026 // Prevent storing a cookie that we couldn't decode. 21027 if (!key && (cookie = read(cookie)) !== undefined) { 21028 result[name] = cookie; 21029 } 21030 } 21031 21032 return result; 21033 }; 21034 21035 config.defaults = {}; 21036 21037 $.removeCookie = function (key, options) { 21038 if ($.cookie(key) === undefined) { 21039 return false;
21040 } 21041 21042 // Must not alter options, thus extending a fresh object... 21043 $.cookie(key, '', $.extend({}, options, { expires: -1 })); 21044 return !$.cookie(key); 21045 }; 21046 21047})); 21048 21049function getContentLanguage() { 21050 return ( $("html[lang]").length > 0 ) ? $('html').attr('lang') : 'de'; 21051}; 21052 21053// replace header and navigation 21054$(document).ready(function(){ 21055 21056 $.ajaxPrefilter(function( options, originalOptions, jqXHR ) { 21057 if ( options.dataType == 'script' || originalOptions.dataType == 'script' ) { 21058 options.cache = true; 21059 } 21060 }); 21061 21062 window.syncObjects = { 21063 'de': [{ 21064 'remoteSnippetURL': "//www.bme.de/remote/footer/?no_cache=1&type=456", 21065 'targetSelector': '.footer-wrapper', 21066 'expirationDelta': 600000, // 86396875 21067 'localStorageItem': 'footer_html_de', 21068 'localStorageExpirationItem': 'footer_cache_date_de', 21069 'callback': swapped_navigation 21070 }, 21071 { 21072 'remoteSnippetURL': "//www.bme.de/remote/navigation/?no_cache=1&type=456", 21073 'targetSelector': '#replaceable-navigation', 21074 'expirationDelta': 600000, 21075 'localStorageItem': 'navigation_html_de', 21076 'localStorageExpirationItem': 'navigation_cache_date_de', 21077 'callback': swapped_navigation 21078 }, 21079 { 21080 'remoteSnippetURL': "//shop.bme.de/de/shopping_cart?locale=de", 21081 'targetSelector': '#shopping-cart-nav-item', 21082 'expirationDelta': -1, 21083 'localStorageItem': 'navigation_cart_de', 21084 'localStorageExpirationItem': 'navigation_cart_cache_delta_de', 21085 'callback': swapped_navigation 21086 } 21087 ], 21088 'en': [{ 21089 'remoteSnippetURL': "//www.bme.de/remote/footer-en/?no_cache=1&type=456", 21090 'targetSelector': '.footer-wrapper', 21091 'expirationDelta': 600000, 21092 'localStorageItem': 'footer_html_en', 21093 'localStorageExpirationItem': 'footer_cache_date_en', 21094 'callback': swapped_navigation 21095 }, 21096 { 21097 'remoteSnippetURL': "//www.bme.de/remote/navigation-en/?no_cache=1&type=456", 21098 'targetSelector': '#replaceable-navigation', 21099 'expirationDelta': 600000, 21100 'localStorageItem': 'navigation_html_en', 21101 'localStorageExpirationItem': 'navigation_cache_date_en', 21102 'callback': swapped_navigation 21103 }, 21104 { 21105 'remoteSnippetURL': "//shop.bme.de/de/shopping_cart?locale=en", 21106 'targetSelector': '#shopping-cart-nav-item', 21107 'expirationDelta': -1, 21108 'localStorageItem': 'navigation_cart_en', 21109 'localStorageExpirationItem': 'navigation_cart_cache_delta_en', 21110 'callback': swapped_navigation 21111 } 21112 ] 21113 }; 21114 21115 window.syncFactory = (new SyncHTMLPartials); 21116 window.syncFactory.sync(window.syncObjects); 21117}); 21118 21119var SyncHTMLPartials = function(){ 21120 SyncHTMLPartials.prototype.sync = function(syncObjects) { 21121 for (var i = syncObjects[getContentLanguage().toLowerCase()].length - 1; i >= 0; i--) { 21122 var snippet, syncobject = syncObjects[getContentLanguage().toLowerCase()][i]; 21123 21124 if ($(syncobject.targetSelector).length === 0 || $(syncobject.targetSelector).attr('data-no-remote-sync')) { 21125 continue; 21126 } 21127 21128 if (snippet = this.loadFromCache(syncobject)) { 21129 // If the navigation is cached, swap it. 21130 this.swapHTML(snippet, syncobject.targetSelector, syncobject.callback); 21131 } else { 21132 // If not, perform an ajax request. 21133 this.retrieveHTML(this, syncobject); 21134 } 21135 } 21136 }; 21137 SyncHTMLPartials.prototype.retrieveHTML = function(klass, syncobject) { 21138 var syncobjectid = window.syncObjects[getContentLanguage().toLowerCase()].indexOf(syncobject); 21139 var script_url = syncobject.remoteSnippetURL; 21140 21141 var script = document.createElement('script'); 21142 script.type = 'text/javascript'; 21143 script.id = 'syncobject_' + syncobjectid; 21144 script.src = script_url + '&callback=window.syncFactory.processHTML&syncobjectid=' + syncobjectid; 21145 21146 if ($('head').find(script.id).length > 0) { 21147 $('head').find(script.id).replaceWith(script); 21148 } else { 21149 $('head').append(script); 21150 } 21151 }; 21152 SyncHTMLPartials.prototype.processHTML = function(syncobjectID, data) { 21153 syncobject = window.syncObjects[getContentLanguage().toLowerCase()][syncobjectID]; 21154 21155 // The expiration date is based on the current time (in ticks) + the specified delta 21156 localStorage.setItem(syncobject.localStorageExpirationItem, (new Date).valueOf() + syncobject.expirationDelta ); 21157 localStorage.setItem(syncobject.localStorageItem, data); 21158 (new SyncHTMLPartials).swapHTML(data, syncobject.targetSelector, syncobject.callback); 21159 };
21160 SyncHTMLPartials.prototype.swapHTML = function(htmlPartial, targetSelector, callback) { 21161 $( targetSelector ).html( htmlPartial ); 21162 21163 $('a', $(targetSelector)).attr("target", ""); // BME only! 21164 21165 if (callback !== undefined && typeof callback == 'function') callback(); 21166 }; 21167 SyncHTMLPartials.prototype.loadFromCache = function(syncobject) { 21168 var result = localStorage.getItem( syncobject.localStorageItem ); 21169 var not_expired = ( localStorage.getItem(syncobject.localStorageExpirationItem) > (new Date).valueOf() ); 21170 return (not_expired && result != "undefined" && !!result && result != "" && result !== undefined) ? result : false; 21171 }; 21172}; 21173 21174function environment_switch(production, development) { 21175 $body = $("body"); 21176 $html = $("html"); 21177 env = production; 21178 21179 if ($body.data("environment") === "development" || $html.data("environment") === "development") { 21180 env = development; 21181 } 21182 21183 return env; 21184} 21185 21186(function($) { 21187 $.yuniqueSSO = function(element, options) { 21188 var defaults = { 21189 idp_template: 'me', 21190 idp_host: 'https://regionen.bme.de', 21191 idp_path: '', 21192 sp_user_id: '', 21193 sp_hash: '', 21194 sp_name: '', 21195 poll_interval: 30000, 21196 uuid: '' + Math.floor(Math.random()*20), 21197 locale: getContentLanguage() || 'de' 21198 }; 21199 21200 var plugin = this; 21201 plugin.settings = {}; 21202 21203 var $element = $(element), 21204 element = element; 21205 21206 plugin.init = function() { 21207 plugin.settings = $.extend({}, defaults, options); 21208 21209 window['yuniqueSSO_' + plugin.settings.uuid] = {}; 21210 window['yuniqueSSO_' + plugin.settings.uuid].current_state = 0; 21211 window['yuniqueSSO_' + plugin.settings.uuid].ssoCallback = function (state, data, redirect) { 21212 if (window['yuniqueSSO_' + plugin.settings.uuid].current_state !== state) { 21213 if (state == 200 || state == 401) { 21214 $element.html(data); 21215 } else { 21216 document.location.href = redirect.replace('&', '&'); 21217 } 21218 window['yuniqueSSO_' + plugin.settings.uuid].current_state = state; 21219 } 21220 }; 21221 21222 window['yuniqueSSO_' + plugin.settings.uuid].jsonpInclude = function() { 21223 var script = document.createElement('script'); 21224 script.type = 'text/javascript'; 21225 script.id = 'yuniqueSSO_' + plugin.settings.uuid; 21226 script.src = plugin.settings.idp_host + 21227 '/account/' + plugin.settings.idp_template + '.js' + 21228 '?sp_user_id=' + plugin.settings.sp_user_id + 21229 '&sp_callback=window.yuniqueSSO_' + plugin.settings.uuid + 21230 '.ssoCallback&sp_name=' + plugin.settings.sp_name + 21231 '&sp_hash=' + plugin.settings.sp_hash + 21232 '&locale=' + plugin.settings.locale + 21233 '&sp_return_uri=' + encodeURIComponent($(location).attr('pathname') + $(location).attr('search')) + 21234 '&sp_thash=' + new Date().getTime(); 21235 21236 if ($('head').find('#yuniqueSSO_' + plugin.settings.uuid).length > 0) { 21237 $('head').find('#yuniqueSSO_' + plugin.settings.uuid).replaceWith(script); 21238 } else { 21239 $('head').append(script); 21240 } 21241 }; 21242 21243 window['yuniqueSSO_' + plugin.settings.uuid].jsonpInclude(); 21244 if (plugin.settings.poll_interval >= 0) { 21245 window.setInterval( 21246 window['yuniqueSSO_' + plugin.settings.uuid].jsonpInclude, 21247 plugin.settings.poll_interval 21248 ); 21249 } 21250 }; 21251 21252 plugin.init(); 21253 }; 21254 21255 $.fn.yuniqueSSO = function(options) { 21256 return this.each(function() { 21257 if (undefined === $(this).data('yuniqueSSO')) { 21258 var plugin = new $.yuniqueSSO(this, options); 21259 $(this).data('yuniqueSSO', plugin); 21260 } 21261 }); 21262 }; 21263})(jQuery); 21264 21265if (window.infopool_url === undefined) { 21266 if (document.location.host.indexOf("bme.de") != -1) { window.infopool_url = '//suche.bme.de'; } 21267 else { window.infopool_url = '//bme-search.staging.yum.de'; } 21268} 21269 21270function bindSearch() { 21271 $('#header-search-tablet-form').attr('action', window.infopool_url); 21272 $('#header-search-tablet-form input').attr('name', 'q'); 21273 $('#header-search-tablet-form').append('<input type="hidden" name="lang" value="' + getContentLanguage() + '">'); 21274 21275 var globalSearch = new Bloodhound({ 21276 datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'), 21277 queryTokenizer: Bloodhound.tokenizers.whitespace, 21278 limit: 100, 21279 remote: { 21280 url: window.infopool_url + '/search.jsonp?q=%QUERY&lang=' + getContentLanguage() + '&callback=?', 21281 dataType: 'jsonp', 21282 filter: function(list) { 21283 return $.map(list.results, function(result) { 21284 result.title = result.title.replace(/("|&quot;)/g, "\""); 21285 result.pub_date = (result.pub_date != undefined) ? result.pub_date : null; 21286 if (result.is_group !== true) { 21287 result.categories = result.category.split(",").join(" / ").replace(/("|&quot;)/g, "\"").replace(/&/g, "&"); 21288 } 21289 return result; 21290 }); 21291 } 21292 } 21293 }); 21294 21295 globalSearch.initialize(); 21296 21297 $('#header-search-tablet-form input[name="q"]').typeahead({ 21298 highlight: true, 21299 minLength: 3 21300 }, { 21301 name: 'best-pictures', 21302 displayKey: 'query', 21303 source: globalSearch.ttAdapter(), 21304 templates: { 21305 empty: [ 21306 '<div class="tt-suggestions"><div class="tt-suggestion text-center tt-suggestion-no-results">', 21307 (getContentLanguage() == 'en' ? 'No results found.' : 'Keine Suchergebnisse gefunden.'), 21308 '</div></div>' 21309 ].join('\n'), 21310 suggestion: Handlebars.compile('{{#if is_group}}<a href="{{link}}" class="search-results-group-title"> <h3>{{title}} <i class="icon-dfb icon-sm"></i></h3></a>{{else}}<a href="{{link}}" class="search-result-link"> <h6>{{#if pub_date}}{{pub_date}}{{/if}}{{#if categories}} / {{categories}}{{/if}}</h6><h4 class="list-group-item-heading">{{title}}</h4></a>{{/if}}') 21311 } 21312 }).on('typeahead:selected', function(event, selection) { 21313 window.location.href = selection.link; 21314 $('#header-search-tablet-form input').typeahead('close'); 21315 }).off('blur'); 21316 21317 $(document).click(function(event) { 21318 if ($(event.target).attr('class') !== 'tt-input') $('#header-search-tablet-form input').typeahead('close'); 21319 }); 21320} 21321 21322$(document).ready(function() { 21323 bindSearch(); 21324}); 21325 21326/* 21327Copyright 2012 Igor Vaynberg 21328 21329Version: 3.4.8 Timestamp: Thu May 1 09:50:32 EDT 2014 21330 21331This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU 21332General Public License version 2 (the "GPL License"). You may choose either license to govern your 21333use of this software only upon the condition that you accept all of the terms of either the Apache 21334License or the GPL License. 21335 21336You may obtain a copy of the Apache License and the GPL License at: 21337 21338 http://www.apache.org/licenses/LICENSE-2.0 21339 http://www.gnu.org/licenses/gpl-2.0.html 21340 21341Unless required by applicable law or agreed to in writing, softw
21341are distributed under the 21342Apache License or the GPL License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 21343CONDITIONS OF ANY KIND, either express or implied. See the Apache License and the GPL License for 21344the specific language governing permissions and limitations under the Apache License and the GPL License. 21345*/ 21346 21347(function ($) { 21348 if(typeof $.fn.each2 == "undefined") { 21349 $.extend($.fn, { 21350 /* 21351 * 4-10 times faster .each replacement 21352 * use it carefully, as it overrides jQuery context of element on each iteration 21353 */ 21354 each2 : function (c) { 21355 var j = $([0]), i = -1, l = this.length; 21356 while ( 21357 ++i < l 21358 && (j.context = j[0] = this[i]) 21359 && c.call(j[0], i, j) !== false //"this"=DOM, i=index, j=jQuery object 21360 ); 21361 return this; 21362 } 21363 }); 21364 } 21365})(jQuery); 21366 21367(function ($, undefined) { 21368 "use strict"; 21369 /*global document, window, jQuery, console */ 21370 21371 if (window.Select2 !== undefined) { 21372 return; 21373 } 21374 21375 var KEY, AbstractSelect2, SingleSelect2, MultiSelect2, nextUid, sizer, 21376 lastMousePosition={x:0,y:0}, $document, scrollBarDimensions, 21377 21378 KEY = { 21379 TAB: 9, 21380 ENTER: 13, 21381 ESC: 27, 21382 SPACE: 32, 21383 LEFT: 37, 21384 UP: 38, 21385 RIGHT: 39, 21386 DOWN: 40, 21387 SHIFT: 16, 21388 CTRL: 17, 21389 ALT: 18, 21390 PAGE_UP: 33, 21391 PAGE_DOWN: 34, 21392 HOME: 36, 21393 END: 35, 21394 BACKSPACE: 8, 21395 DELETE: 46, 21396 isArrow: function (k) { 21397 k = k.which ? k.which : k; 21398 switch (k) { 21399 case KEY.LEFT: 21400 case KEY.RIGHT: 21401 case KEY.UP: 21402 case KEY.DOWN: 21403 return true; 21404 } 21405 return false; 21406 }, 21407 isControl: function (e) { 21408 var k = e.which; 21409 switch (k) { 21410 case KEY.SHIFT: 21411 case KEY.CTRL: 21412 case KEY.ALT: 21413 return true; 21414 } 21415 21416 if (e.metaKey) return true; 21417 21418 return false; 21419 }, 21420 isFunctionKey: function (k) { 21421 k = k.which ? k.which : k; 21422 return k >= 112 && k <= 123; 21423 } 21424 }, 21425 MEASURE_SCROLLBAR_TEMPLATE = "<div class='select2-measure-scrollbar'></div>", 21426 21427 DIACRITICS = {"\u24B6":"A","\uFF21":"A","\u00C0":"A","\u00C1":"A","\u00C2":"A","\u1EA6":"A","\u1EA4":"A","\u1EAA":"A","\u1EA8":"A","\u00C3":"A","\u0100":"A","\u0102":"A","\u1EB0":"A","\u1EAE":"A","\u1EB4":"A","\u1EB2":"A","\u0226":"A","\u01E0":"A","\u00C4":"A","\u01DE":"A","\u1EA2":"A","\u00C5":"A","\u01FA":"A","\u01CD":"A","\u0200":"A","\u0202":"A","\u1EA0":"A","\u1EAC":"A","\u1EB6":"A","\u1E00":"A","\u0104":"A","\u023A":"A","\u2C6F":"A","\uA732":"AA","\u00C6":"AE","\u01FC":"AE","\u01E2":"AE","\uA734":"AO","\uA736":"AU","\uA738":"AV","\uA73A":"AV","\uA73C":"AY","\u24B7":"B","\uFF22":"B","\u1E02":"B","\u1E04":"B","\u1E06":"B","\u0243":"B","\u0182":"B","\u0181":"B","\u24B8":"C","\uFF23":"C","\u0106":"C","\u0108":"C","\u010A":"C","\u010C":"C","\u00C7":"C","\u1E08":"C","\u0187":"C","\u023B":"C","\uA73E":"C","\u24B9":"D","\uFF24":"D","\u1E0A":"D","\u010E":"D","\u1E0C":"D","\u1E10":"D","\u1E12":"D","\u1E0E":"D","\u0110":"D","\u018B":"D","\u018A":"D","\u0189":"D","\uA779":"D","\u01F1":"DZ","\u01C4":"DZ","\u01F2":"Dz","\u01C5":"Dz","\u24BA":"E","\uFF25":"E","\u00C8":"E","\u00C9":"E","\u00CA":"E","\u1EC0":"E","\u1EBE":"E","\u1EC4":"E","\u1EC2":"E","\u1EBC":"E","\u0112":"E","\u1E14":"E","\u1E16":"E","\u0114":"E","\u0116":"E","\u00CB":"E","\u1EBA":"E","\u011A":"E","\u0204":"E","\u0206":"E","\u1EB8":"E","\u1EC6":"E","\u0228":"E","\u1E1C":"E","\u0118":"E","\u1E18"
21427:"E","\u1E1A":"E","\u0190":"E","\u018E":"E","\u24BB":"F","\uFF26":"F","\u1E1E":"F","\u0191":"F","\uA77B":"F","\u24BC":"G","\uFF27":"G","\u01F4":"G","\u011C":"G","\u1E20":"G","\u011E":"G","\u0120":"G","\u01E6":"G","\u0122":"G","\u01E4":"G","\u0193":"G","\uA7A0":"G","\uA77D":"G","\uA77E":"G","\u24BD":"H","\uFF28":"H","\u0124":"H","\u1E22":"H","\u1E26":"H","\u021E":"H","\u1E24":"H","\u1E28":"H","\u1E2A":"H","\u0126":"H","\u2C67":"H","\u2C75":"H","\uA78D":"H","\u24BE":"I","\uFF29":"I","\u00CC":"I","\u00CD":"I","\u00CE":"I","\u0128":"I","\u012A":"I","\u012C":"I","\u0130":"I","\u00CF":"I","\u1E2E":"I","\u1EC8":"I","\u01CF":"I","\u0208":"I","\u020A":"I","\u1ECA":"I","\u012E":"I","\u1E2C":"I","\u0197":"I","\u24BF":"J","\uFF2A":"J","\u0134":"J","\u0248":"J","\u24C0":"K","\uFF2B":"K","\u1E30":"K","\u01E8":"K","\u1E32":"K","\u0136":"K","\u1E34":"K","\u0198":"K","\u2C69":"K","\uA740":"K","\uA742":"K","\uA744":"K","\uA7A2":"K","\u24C1":"L","\uFF2C":"L","\u013F":"L","\u0139":"L","\u013D":"L","\u1E36":"L","\u1E38":"L","\u013B":"L","\u1E3C":"L","\u1E3A":"L","\u0141":"L","\u023D":"L","\u2C62":"L","\u2C60":"L","\uA748":"L","\uA746":"L","\uA780":"L","\u01C7":"LJ","\u01C8":"Lj","\u24C2":"M","\uFF2D":"M","\u1E3E":"M","\u1E40":"M","\u1E42":"M","\u2C6E":"M","\u019C":"M","\u24C3":"N","\uFF2E":"N","\u01F8":"N","\u0143":"N","\u00D1":"N","\u1E44":"N","\u0147":"N","\u1E46":"N","\u0145":"N","\u1E4A":"N","\u1E48":"N","\u0220":"N","\u019D":"N","\uA790":"N","\uA7A4":"N","\u01CA":"NJ","\u01CB":"Nj","\u24C4":"O","\uFF2F":"O","\u00D2":"O","\u00D3":"O","\u00D4":"O","\u1ED2":"O","\u1ED0":"O","\u1ED6":"O","\u1ED4":"O","\u00D5":"O","\u1E4C":"O","\u022C":"O","\u1E4E":"O","\u014C":"O","\u1E50":"O","\u1E52":"O","\u014E":"O","\u022E":"O","\u0230":"O","\u00D6":"O","\u022A":"O","\u1ECE":"O","\u0150":"O","\u01D1":"O","\u020C":"O","\u020E":"O","\u01A0":"O","\u1EDC":"O","\u1EDA":"O","\u1EE0":"O","\u1EDE":"O","\u1EE2":"O","\u1ECC":"O","\u1ED8":"O","\u01EA":"O","\u01EC":"O","\u00D8":"O","\u01FE":"O","\u0186":"O","\u019F":"O","\uA74A":"O","\uA74C":"O","\u01A2":"OI","\uA74E":"OO","\u0222":"OU","\u24C5":"P","\uFF30":"P","\u1E54":"P","\u1E56":"P","\u01A4":"P","\u2C63":"P","\uA750":"P","\uA752":"P","\uA754":"P","\u24C6":"Q","\uFF31":"Q","\uA756":"Q","\uA758":"Q","\u024A":"Q","\u24C7":"R","\uFF32":"R","\u0154":"R","\u1E58":"R","\u0158":"R","\u0210":"R","\u0212":"R","\u1E5A":"R","\u1E5C":"R","\u0156":"R","\u1E5E":"R","\u024C":"R","\u2C64":"R","\uA75A":"R","\uA7A6":"R","\uA782":"R","\u24C8":"S","\uFF33":"S","\u1E9E":"S","\u015A":"S","\u1E64":"S","\u015C":"S","\u1E60":"S","\u0160":"S","\u1E66":"S","\u1E62":"S","\u1E68":"S","\u0218":"S","\u015E":"S","\u2C7E":"S","\uA7A8":"S","\uA784":"S","\u24C9":"T","\uFF34":"T","\u1E6A":"T","\u0164":"T","\u1E6C":"T","\u021A":"T","\u0162":"T","\u1E70":"T","\u1E6E":"T","\u0166":"T","\u01AC":"T","\u01AE":"T","\u023E":"T","\uA786":"T","\uA728":"TZ","\u24CA":"U","\uFF35":"U","\u00D9":"U","\u00DA":"U","\u00DB":"U","\u0168":"U","\u1E78":"U","\u016A":"U","\u1E7A":"U","\u016C":"U","\u00DC":"U","\u01DB":"U","\u01D7":"U","\u01D5":"U","\u01D9":"U","\u1EE6":"U","\u016E":"U","\u0170":"U","\u01D3":"U","\u0214":"U","\u0216":"U","\u01AF":"U","\u1EEA":"U","\u1EE8":"U","\u1EEE":"U","\u1EEC":"U","\u1EF0":"U","\u1EE4":"U","\u1E72":"U","\u0172":"U","\u1E76":"U","\u1E74":"U","\u0244":"U","\u24CB":"V","\uFF36":"V","\u1E7C":"V","\u1E7E":"V","\u01B2":"V","\uA75E":"V","\u0245":"V","\uA760":"VY","\u24CC":"W","\uFF37":"W","\u1E80":"W","\u1E82":"W","\u0174":"W","\u1E86":"W","\u1E84":"W","\u1E88":"W","\u2C72":"W","\u24CD":"X","\uFF38":"X","\u1E8A":"X","\u1E8C":"X","\u24CE":"Y","\uFF39":"Y","\u1EF2":"Y","\u00DD":"Y","\u0176":"Y","\u1EF8":"Y","\u0232":"Y","\u1E8E":"Y","\u0178":"Y","\u1EF6":"Y","\u1EF4":"Y","\u01B3":"Y","\u024E":"Y","\u1EFE":"Y","\u24CF":"Z","\uFF3A":"Z","\u0179":"Z","\u1E90":"Z","\u017B":"Z","\u017D":"Z","\u1E92":"Z","\u1E94":"Z","\u01B5":"Z","\u0224":"Z","\u2C7F":"Z","\u2C6B":"Z","\uA762":"Z","\u24D0":"a","\uFF41":"a","\u1E9A":"a","\u00E0":"a","\u00E1":"a","\u00E2":"a","\u1EA7":"a","\u1EA5":"a","\u1EAB":"a","\u1EA9":"a","\u00E3":"a","\u0101":"a","\u0103":"a","\u1EB1":"a","\u1EAF":"a","\u1EB5":"a","\u1EB3":"a","\u0227":"a","\u01E1":"a","\u00E4":"a","\u01DF":"a","\u1EA3":"a","\u00E5":"a","\u01FB":"a","\u01CE":"a","\u0201":"a","\u0203":"a","\u1EA1":"a","\u1EAD":"a","\u1EB7":"a","\u1E01":"a","\u0105":"a","\u2C65":"a","\u0250":"a","\uA733":"aa","\u00E6":"ae","\u01FD":"ae","\u01E3":"ae","\uA735":"ao","\uA737":"au","\uA739":"av","\uA73B":"av","\uA73D":"ay","\u24D1":"b","\uFF42":"b","\u1E03":"b","\u1E05":"b","\u1E07":"b","\u0180":"b","\u0183":"b","\u0253":"b","\u24D2":"c","\uFF43":"c","\u0107":"c","\u0109":"c","\u010B":"c","\u010D":"c","\u00E7":"c","\u1E09":"c","\u0188":"c","\u023C":"c","\uA73F":"c","\u2184":"c","\u24D3":"d","\uFF44":"d","\u1E0B":"d","\u010F":"d","\u1E0D":"d","\u1E11":"d","\u1E13":"d","\u1E0F":"d","\u0111":"d","\u018C":"d","\u0256":"d","\u0257":"d","\uA77A":"d","\u01F3":"dz","\u01C6":"dz","\u24D4":"e","\uFF45":"e","\u00E8":"e","\u00E9":"e","\u00EA":"e","\u1EC1":"e","\u1EBF":"e","\u1EC
214275":"e","\u1EC3":"e","\u1EBD":"e","\u0113":"e","\u1E15":"e","\u1E17":"e","\u0115":"e","\u0117":"e","\u00EB":"e","\u1EBB":"e","\u011B":"e","\u0205":"e","\u0207":"e","\u1EB9":"e","\u1EC7":"e","\u0229":"e","\u1E1D":"e","\u0119":"e","\u1E19":"e","\u1E1B":"e","\u0247":"e","\u025B":"e","\u01DD":"e","\u24D5":"f","\uFF46":"f","\u1E1F":"f","\u0192":"f","\uA77C":"f","\u24D6":"g","\uFF47":"g","\u01F5":"g","\u011D":"g","\u1E21":"g","\u011F":"g","\u0121":"g","\u01E7":"g","\u0123":"g","\u01E5":"g","\u0260":"g","\uA7A1":"g","\u1D79":"g","\uA77F":"g","\u24D7":"h","\uFF48":"h","\u0125":"h","\u1E23":"h","\u1E27":"h","\u021F":"h","\u1E25":"h","\u1E29":"h","\u1E2B":"h","\u1E96":"h","\u0127":"h","\u2C68":"h","\u2C76":"h","\u0265":"h","\u0195":"hv","\u24D8":"i","\uFF49":"i","\u00EC":"i","\u00ED":"i","\u00EE":"i","\u0129":"i","\u012B":"i","\u012D":"i","\u00EF":"i","\u1E2F":"i","\u1EC9":"i","\u01D0":"i","\u0209":"i","\u020B":"i","\u1ECB":"i","\u012F":"i","\u1E2D":"i","\u0268":"i","\u0131":"i","\u24D9":"j","\uFF4A":"j","\u0135":"j","\u01F0":"j","\u0249":"j","\u24DA":"k","\uFF4B":"k","\u1E31":"k","\u01E9":"k","\u1E33":"k","\u0137":"k","\u1E35":"k","\u0199":"k","\u2C6A":"k","\uA741":"k","\uA743":"k","\uA745":"k","\uA7A3":"k","\u24DB":"l","\uFF4C":"l","\u0140":"l","\u013A":"l","\u013E":"l","\u1E37":"l","\u1E39":"l","\u013C":"l","\u1E3D":"l","\u1E3B":"l","\u017F":"l","\u0142":"l","\u019A":"l","\u026B":"l","\u2C61":"l","\uA749":"l","\uA781":"l","\uA747":"l","\u01C9":"lj","\u24DC":"m","\uFF4D":"m","\u1E3F":"m","\u1E41":"m","\u1E43":"m","\u0271":"m","\u026F":"m","\u24DD":"n","\uFF4E":"n","\u01F9":"n","\u0144":"n","\u00F1":"n","\u1E45":"n","\u0148":"n","\u1E47":"n","\u0146":"n","\u1E4B":"n","\u1E49":"n","\u019E":"n","\u0272":"n","\u0149":"n","\uA791":"n","\uA7A5":"n","\u01CC":"nj","\u24DE":"o","\uFF4F":"o","\u00F2":"o","\u00F3":"o","\u00F4":"o","\u1ED3":"o","\u1ED1":"o","\u1ED7":"o","\u1ED5":"o","\u00F5":"o","\u1E4D":"o","\u022D":"o","\u1E4F":"o","\u014D":"o","\u1E51":"o","\u1E53":"o","\u014F":"o","\u022F":"o","\u0231":"o","\u00F6":"o","\u022B":"o","\u1ECF":"o","\u0151":"o","\u01D2":"o","\u020D":"o","\u020F":"o","\u01A1":"o","\u1EDD":"o","\u1EDB":"o","\u1EE1":"o","\u1EDF":"o","\u1EE3":"o","\u1ECD":"o","\u1ED9":"o","\u01EB":"o","\u01ED":"o","\u00F8":"o","\u01FF":"o","\u0254":"o","\uA74B":"o","\uA74D":"o","\u0275":"o","\u01A3":"oi","\u0223":"ou","\uA74F":"oo","\u24DF":"p","\uFF50":"p","\u1E55":"p","\u1E57":"p","\u01A5":"p","\u1D7D":"p","\uA751":"p","\uA753":"p","\uA755":"p","\u24E0":"q","\uFF51":"q","\u024B":"q","\uA757":"q","\uA759":"q","\u24E1":"r","\uFF52":"r","\u0155":"r","\u1E59":"r","\u0159":"r","\u0211":"r","\u0213":"r","\u1E5B":"r","\u1E5D":"r","\u0157":"r","\u1E5F":"r","\u024D":"r","\u027D":"r","\uA75B":"r","\uA7A7":"r","\uA783":"r","\u24E2":"s","\uFF53":"s","\u00DF":"s","\u015B":"s","\u1E65":"s","\u015D":"s","\u1E61":"s","\u0161":"s","\u1E67":"s","\u1E63":"s","\u1E69":"s","\u0219":"s","\u015F":"s","\u023F":"s","\uA7A9":"s","\uA785":"s","\u1E9B":"s","\u24E3":"t","\uFF54":"t","\u1E6B":"t","\u1E97":"t","\u0165":"t","\u1E6D":"t","\u021B":"t","\u0163":"t","\u1E71":"t","\u1E6F":"t","\u0167":"t","\u01AD":"t","\u0288":"t","\u2C66":"t","\uA787":"t","\uA729":"tz","\u24E4":"u","\uFF55":"u","\u00F9":"u","\u00FA":"u","\u00FB":"u","\u0169":"u","\u1E79":"u","\u016B":"u","\u1E7B":"u","\u016D":"u","\u00FC":"u","\u01DC":"u","\u01D8":"u","\u01D6":"u","\u01DA":"u","\u1EE7":"u","\u016F":"u","\u0171":"u","\u01D4":"u","\u0215":"u","\u0217":"u","\u01B0":"u","\u1EEB":"u","\u1EE9":"u","\u1EEF":"u","\u1EED":"u","\u1EF1":"u","\u1EE5":"u","\u1E73":"u","\u0173":"u","\u1E77":"u","\u1E75":"u","\u0289":"u","\u24E5":"v","\uFF56":"v","\u1E7D":"v","\u1E7F":"v","\u028B":"v","\uA75F":"v","\u028C":"v","\uA761":"vy","\u24E6":"w","\uFF57":"w","\u1E81":"w","\u1E83":"w","\u0175":"w","\u1E87":"w","\u1E85":"w","\u1E98":"w","\u1E89":"w","\u2C73":"w","\u24E7":"x","\uFF58":"x","\u1E8B":"x","\u1E8D":"x","\u24E8":"y","\uFF59":"y","\u1EF3":"y","\u00FD":"y","\u0177":"y","\u1EF9":"y","\u0233":"y","\u1E8F":"y","\u00FF":"y","\u1EF7":"y","\u1E99":"y","\u1EF5":"y","\u01B4":"y","\u024F":"y","\u1EFF":"y","\u24E9":"z","\uFF5A":"z","\u017A":"z","\u1E91":"z","\u017C":"z","\u017E":"z","\u1E93":"z","\u1E95":"z","\u01B6":"z","\u0225":"z","\u0240":"z","\u2C6C":"z","\uA763":"z"}; 21428 21429 $document = $(document); 21430 21431 nextUid=(function() { var counter=1; return function() { return counter++; }; }()); 21432 21433 21434 function reinsertElement(element) { 21435 var placeholder = $(document.createTextNode('')); 21436 21437 element.before(placeholder); 21438 placeholder.before(element); 21439 placeholder.remove(); 21440 } 21441 21442 function stripDiacritics(str) { 21443 // Used 'uni range + named function' from http://jsperf.com/diacritics/18 21444 function match(a) { 21445 return DIACRITICS[a] || a; 21446 } 21447
21448 return str.replace(/[^\u0000-\u007E]/g, match); 21449 } 21450 21451 function indexOf(value, array) { 21452 var i = 0, l = array.length; 21453 for (; i < l; i = i + 1) { 21454 if (equal(value, array[i])) return i; 21455 } 21456 return -1; 21457 } 21458 21459 function measureScrollbar () { 21460 var $template = $( MEASURE_SCROLLBAR_TEMPLATE ); 21461 $template.appendTo('body'); 21462 21463 var dim = { 21464 width: $template.width() - $template[0].clientWidth, 21465 height: $template.height() - $template[0].clientHeight 21466 }; 21467 $template.remove(); 21468 21469 return dim; 21470 } 21471 21472 /** 21473 * Compares equality of a and b 21474 * @param a 21475 * @param b 21476 */ 21477 function equal(a, b) { 21478 if (a === b) return true; 21479 if (a === undefined || b === undefined) return false; 21480 if (a === null || b === null) return false; 21481 // Check whether 'a' or 'b' is a string (primitive or object). 21482 // The concatenation of an empty string (+'') converts its argument to a string's primitive. 21483 if (a.constructor === String) return a+'' === b+''; // a+'' - in case 'a' is a String object 21484 if (b.constructor === String) return b+'' === a+''; // b+'' - in case 'b' is a String object 21485 return false; 21486 } 21487 21488 /** 21489 * Splits the string into an array of values, trimming each value. An empty array is returned for nulls or empty 21490 * strings 21491 * @param string 21492 * @param separator 21493 */ 21494 function splitVal(string, separator) { 21495 var val, i, l; 21496 if (string === null || string.length < 1) return []; 21497 val = string.split(separator); 21498 for (i = 0, l = val.length; i < l; i = i + 1) val[i] = $.trim(val[i]); 21499 return val; 21500 } 21501 21502 function getSideBorderPadding(element) { 21503 return element.outerWidth(false) - element.width(); 21504 } 21505 21506 function installKeyUpChangeEvent(element) { 21507 var key="keyup-change-value"; 21508 element.on("keydown", function () { 21509 if ($.data(element, key) === undefined) { 21510 $.data(element, key, element.val()); 21511 } 21512 }); 21513 element.on("keyup", function () { 21514 var val= $.data(element, key); 21515 if (val !== undefined && element.val() !== val) { 21516 $.removeData(element, key); 21517 element.trigger("keyup-change"); 21518 } 21519 }); 21520 } 21521 21522 $document.on("mousemove", function (e) { 21523 lastMousePosition.x = e.pageX; 21524 lastMousePosition.y = e.pageY; 21525 }); 21526 21527 /** 21528 * filters mouse events so an event is fired only if the mouse moved. 21529 * 21530 * filters out mouse events that occur when mouse is stationary but 21531 * the elements under the pointer are scrolled. 21532 */ 21533 function installFilteredMouseMove(element) { 21534 element.on("mousemove", function (e) { 21535 var lastpos = lastMousePosition; 21536 if (lastpos === undefined || lastpos.x !== e.pageX || lastpos.y !== e.pageY) { 21537 $(e.target).trigger("mousemove-filtered", e); 21538 } 21539 }); 21540 } 21541 21542 /** 21543 * Debounces a function. Returns a function that calls the original fn function only if no invocations have been made 21544 * within the last quietMillis milliseconds. 21545 * 21546 * @param quietMillis number of milliseconds to wait before invoking fn 21547 * @param fn function to be debounced 21548 * @param ctx object to be used as this reference within fn 21549 * @return debounced version of fn 21550 */ 21551 function debounce(quietMillis, fn, ctx) { 21552 ctx = ctx || undefined; 21553 var timeout; 21554 return function () { 21555 var args = arguments; 21556 window.clearTimeout(timeout); 21557 timeout = window.setTimeout(function() { 21558 fn.apply(ctx, args); 21559 }, quietMillis); 21560 }; 21561 } 21562 21563 function installDebouncedScroll(threshold, element) { 21564 var notify = debounce(threshold, function (e) { element.trigger("scroll-debounced", e);}); 21565 element.on("scroll", function (e) { 21566 if (indexOf(e.target, element.get()) >= 0) notify(e); 21567 }); 21568 } 21569 21570 function focus($el) { 21571 if ($el[0] === document.activeElement) return; 21572 21573 /* set the focus in a 0 timeout - that way the focus is set after the processing 21574 of the current event has finished - which seems like the only reliable way 21575 to set focus */ 21576 window.setTimeout(function() { 21577 var el=$el[0], pos=$el.val().length, range; 21578 21579 $el.focus(); 21580 21581 /* make sure el received focus so we do not error out when trying to manipulate the caret. 21582 sometimes modals or others listeners may steal it after its set */ 21583 var isVisible = (el.offsetWidth > 0 || el.offsetHeight > 0); 21584 if (isVisible && el === document.activeElement) { 21585 21586 /* after the focus is set move the caret to the end, necessary when we val() 21587 just before setting focus */ 21588 if(el.setSelectionRange) 21589 { 21590 el.setSelectionRange(pos, pos); 21591 } 21592 else if (el.createTextRange) { 21593 range = el.createTextRange(); 21594 range.collapse(false); 21595 range.select(); 21596 } 21597 } 21598 }, 0); 21599 } 21600 21601 function getCursorInfo(el) { 21602 el = $(el)[0]; 21603 var offset = 0; 21604 var length = 0; 21605 if ('selectionStart' in el) { 21606 offset = el.selectionStart; 21607 length = el.selectionEnd - offset; 21608 } else if ('selection' in document) { 21609 el.focus(); 21610 var sel = document.selection.createRange(); 21611 length = document.selection.createRange().text.length; 21612 sel.moveStart('character', -el.value.length); 21613 offset = sel.text.length - length; 21614 } 21615 return { offset: offset, length: length }; 21616 } 21617 21618 function killEvent(event) { 21619 event.preventDefault(); 21620 event.stopPropagation(); 21621 } 21622 function killEventImmediately(event) { 21623 event.preventDefault(); 21624 event.stopImmediatePropagation(); 21625 } 21626 21627 function measureTextWidth(e) { 21628 if (!sizer){ 21629 var style = e[0].currentStyle || window.getComputedStyle(e[0], null); 21630 sizer = $(document.createElement("div")).css({ 21631 position: "absolute", 21632 left: "-10000px", 21633 top: "-10000px", 21634 display: "none", 21635 fontSize: style.fontSize, 21636 fontFamily: style.fontFamily, 21637 fontStyle: style.fontStyle, 21638 fontWeight: style.fontWeight, 21639 letterSpacing: style.letterSpacing, 21640 textTransform: style.textTransform, 21641 whiteSpace: "nowrap" 21642 }); 21643 sizer.attr("class","select2-sizer"); 21644 $("body").append(sizer); 21645 } 21646 sizer.text(e.val()); 21647 return sizer.width(); 21648 } 21649
21650 function syncCssClasses(dest, src, adapter) { 21651 var classes, replacements = [], adapted; 21652 21653 classes = dest.attr("class"); 21654 if (classes) { 21655 classes = '' + classes; // for IE which returns object 21656 $(classes.split(" ")).each2(function() { 21657 if (this.indexOf("select2-") === 0) { 21658 replacements.push(this); 21659 } 21660 }); 21661 } 21662 classes = src.attr("class"); 21663 if (classes) { 21664 classes = '' + classes; // for IE which returns object 21665 $(classes.split(" ")).each2(function() { 21666 if (this.indexOf("select2-") !== 0) { 21667 adapted = adapter(this); 21668 if (adapted) { 21669 replacements.push(adapted); 21670 } 21671 } 21672 }); 21673 } 21674 dest.attr("class", replacements.join(" ")); 21675 } 21676 21677 21678 function markMatch(text, term, markup, escapeMarkup) { 21679 var match=stripDiacritics(text.toUpperCase()).indexOf(stripDiacritics(term.toUpperCase())), 21680 tl=term.length; 21681 21682 if (match<0) { 21683 markup.push(escapeMarkup(text)); 21684 return; 21685 } 21686 21687 markup.push(escapeMarkup(text.substring(0, match))); 21688 markup.push("<span class='select2-match'>"); 21689 markup.push(escapeMarkup(text.substring(match, match + tl))); 21690 markup.push("</span>"); 21691 markup.push(escapeMarkup(text.substring(match + tl, text.length))); 21692 } 21693 21694 function defaultEscapeMarkup(markup) { 21695 var replace_map = { 21696 '\\': '\', 21697 '&': '&', 21698 '<': '<', 21699 '>': '>', 21700 '"': '"', 21701 "'": ''', 21702 "/": '/' 21703 }; 21704 21705 return String(markup).replace(/[&<>"'\/\\]/g, function (match) { 21706 return replace_map[match]; 21707 }); 21708 } 21709 21710 /** 21711 * Produces an ajax-based query function 21712 * 21713 * @param options object containing configuration parameters 21714 * @param options.params parameter map for the transport ajax call, can contain such options as cache, jsonpCallback, etc. see $.ajax 21715 * @param options.transport function that will be used to execute the ajax request. must be compatible with parameters supported by $.ajax 21716 * @param options.url url for the data 21717 * @param options.data a function(searchTerm, pageNumber, context) that should return an object c
21717ontaining query string parameters for the above url. 21718 * @param options.dataType request data type: ajax, jsonp, other datatypes supported by jQuery's $.ajax function or the transport function if specified 21719 * @param options.quietMillis (optional) milliseconds to wait before making the ajaxRequest, helps debounce the ajax function if invoked too often 21720 * @param options.results a function(remoteData, pageNumber) that converts data returned form the remote request to the format expected by Select2. 21721 * The expected format is an object containing the following keys: 21722 * results array of objects that will be used as choices 21723 * more (optional) boolean indicating whether there are more results available 21724 * Example: {results:[{id:1, text:'Red'},{id:2, text:'Blue'}], more:true} 21725 */ 21726 function ajax(options) { 21727 var timeout, // current scheduled but not yet executed request 21728 handler = null, 21729 quietMillis = options.quietMillis || 100, 21730 ajaxUrl = options.url, 21731 self = this; 21732 21733 return function (query) { 21734 window.clearTimeout(timeout); 21735 timeout = window.setTimeout(function () { 21736 var data = options.data, // ajax data function 21737 url = ajaxUrl, // ajax url string or function 21738 transport = options.transport || $.fn.select2.ajaxDefaults.transport, 21739 // deprecated - to be removed in 4.0 - use params instead 21740 deprecated = { 21741 type: options.type || 'GET', // set type of request (GET or POST) 21742 cache: options.cache || false, 21743 jsonpCallback: options.jsonpCallback||undefined, 21744 dataType: options.dataType||"json" 21745 }, 21746 params = $.extend({}, $.fn.select2.ajaxDefaults.params, deprecated); 21747 21748 data = data ? data.call(self, query.term, query.page, query.context) : null; 21749 url = (typeof url === 'function') ? url.call(self, query.term, query.page, query.context) : url; 21750 21751 if (handler && typeof handler.abort === "function") { handler.abort(); } 21752 21753 if (options.params) { 21754 if ($.isFunction(options.params)) { 21755 $.extend(params, options.params.call(self)); 21756 } else { 21757 $.extend(params, options.params); 21758 } 21759 } 21760 21761 $.extend(params, { 21762 url: url, 21763 dataType: options.dataType, 21764 data: data, 21765 success: function (data) { 21766 // TODO - replace query.page with query so users have access to term, page, etc. 21767 var results = options.results(data, query.page); 21768 query.callback(results); 21769 } 21770 }); 21771 handler = transport.call(self, params); 21772 }, quietMillis); 21773 }; 21774 } 21775 21776 /** 21777 * Produces a query function that works with a local array 21778 * 21779 * @param options object containing configuration parameters. The options parameter can either be an array or an 21780 * object. 21781 * 21782 * If the array form is used it is assumed that it contains objects with 'id' and 'text' keys. 21783 * 21784 * If the object form is used it is assumed that it contains 'data' and 'text' keys. The 'data' key should contain 21785 * an array of objects that will be used as choices. These objects must contain at least an 'id' key. The 'text' 21786 * key can either be a String in which case it is expected that each element in the 'data' array has a key with the 21787 * value of 'text' which will be used to match choices. Alternatively, text can be a function(item) that can extract 21788 * the text. 21789 */ 21790 function local(options) { 21791 var data = options, // data elements 21792 dataText, 21793 tmp, 21794 text = function (item) { return ""+item.text; }; // function used to retrieve the text portion of a data item that is matched against the search 21795 21796 if ($.isArray(data)) { 21797 tmp = data; 21798 data = { results: tmp }; 21799 } 21800 21801 if ($.isFunction(data) === false) { 21802 tmp = data; 21803 data = function() { return tmp; }; 21804 } 21805 21806 var dataItem = data(); 21807 if (dataItem.text) { 21808 text = dataItem.text; 21809 // if text is not a function we assume it to be a key name 21810 if (!$.isFunction(text)) { 21811 dataText = dataItem.text; // we need to store this in a separate variable because in the next step data gets reset and data.text is no longer available 21812 text = function (item) { return item[dataText]; }; 21813 } 21814 } 21815 21816 return function (query) { 21817 var t = query.term, filtered = { results: [] }, process; 21818 if (t === "") { 21819 query.callback(data()); 21820 return; 21821 } 21822 21823 process = function(datum, collection) { 21824 var group, attr; 21825 datum = datum[0]; 21826 if (datum.children) { 21827 group = {}; 21828 for (attr in datum) { 21829 if (datum.hasOwnProperty(attr)) group[attr]=datum[attr]; 21830 } 21831 group.children=[]; 21832 $(datum.children).each2(function(i, childDatum) { process(childDatum, group.children); }); 21833 if (group.children.length || query.matcher(t, text(group), datum)) { 21834 collection.push(group); 21835 } 21836 } else { 21837 if (query.matcher(t, text(datum), datum)) { 21838 collection.push(datum); 21839 } 21840 } 21841 }; 21842 21843 $(data().results).each2(function(i, datum) { process(datum, filtered.results); }); 21844 query.callback(filtered); 21845 }; 21846 } 21847 21848 // TODO javadoc 21849 function tags(data) { 21850 var isFunc = $.isFunction(data); 21851 return function (query) { 21852 var t = query.term, filtered = {results: []}; 21853 var result = isFunc ? data(query) : data; 21854 if ($.isArray(result)) { 21855 $(result).each(function () { 21856 var isObject = this.text !== undefined, 21857 text = isObject ? this.text : this; 21858 if (t === "" || query.matcher(t, text)) { 21859 filtered.results.push(isObject ? this : {id: this, text: this}); 21860 } 21861 }); 21862 query.callback(filtered); 21863 } 21864 }; 21865 } 21866 21867 /** 21868 * Checks if the formatter function should be used. 21869 * 21870 * Throws an error if it is not a function. Returns true if it should be used, 21871 * false if no formatting should be performed. 21872 * 21873 * @param formatter 21874 */ 21875 function checkFormatter(formatter, formatterName) { 21876 if ($.isFunction(formatter)) return true; 21877 if (!formatter) return false;
21878 if (typeof(formatter) === 'string') return true; 21879 throw new Error(formatterName +" must be a string, function, or falsy value"); 21880 } 21881 21882 function evaluate(val) { 21883 if ($.isFunction(val)) { 21884 var args = Array.prototype.slice.call(arguments, 1); 21885 return val.apply(null, args); 21886 } 21887 return val; 21888 } 21889 21890 function countResults(results) { 21891 var count = 0; 21892 $.each(results, function(i, item) { 21893 if (item.children) { 21894 count += countResults(item.children); 21895 } else { 21896 count++; 21897 } 21898 }); 21899 return count; 21900 } 21901 21902 /** 21903 * Default tokenizer. This function uses breaks the input on substring match of any string from the 21904 * opts.tokenSeparators array and uses opts.createSearchChoice to create the choice object. Both of those 21905 * two options have to be defined in order for the tokenizer to work. 21906 * 21907 * @param input text user has typed so far or pasted into the search field 21908 * @param selection currently selected choices 21909 * @param selectCallback function(choice) callback tho add the choice to selection 21910 * @param opts select2's opts 21911 * @return undefined/null to leave the current input unchanged, or a string to change the input to the returned value 21912 */ 21913 function defaultTokenizer(input, selection, selectCallback, opts) { 21914 var original = input, // store the original so we can compare and know if we need to tell the search to update its text 21915 dupe = false, // check for whether a token we extracted represents a duplicate selected choice 21916 token, // token 21917 index, // position at which the separator was found 21918 i, l, // looping variables 21919 separator; // the matched separator 21920 21921 if (!opts.createSearchChoice || !opts.tokenSeparators || opts.tokenSeparators.length < 1) return undefined; 21922 21923 while (true) { 21924 index = -1; 21925 21926 for (i = 0, l = opts.tokenSeparators.length; i < l; i++) { 21927 separator = opts.tokenSeparators[i]; 21928 index = input.indexOf(separator); 21929 if (index >= 0) break; 21930 } 21931 21932 if (index < 0) break; // did not find any token separator in the input string, bail 21933 21934 token = input.substring(0, index); 21935 input = input.substring(index + separator.length); 21936 21937 if (token.length > 0) { 21938 token = opts.createSearchChoice.call(this, token, selection); 21939 if (token !== undefined && token !== null && opts.id(token) !== undefined && opts.id(token) !== null) { 21940 dupe = false; 21941 for (i = 0, l = selection.length; i < l; i++) { 21942 if (equal(opts.id(token), opts.id(selection[i]))) { 21943 dupe = true; break; 21944 } 21945 } 21946 21947 if (!dupe) selectCallback(token); 21948 } 21949 } 21950 } 21951
21952 if (original!==input) return input; 21953 } 21954 21955 function cleanupJQueryElements() { 21956 var self = this; 21957 21958 Array.prototype.forEach.call(arguments, function (element) { 21959 self[element].remove(); 21960 self[element] = null; 21961 }); 21962 } 21963 21964 /** 21965 * Creates a new class 21966 * 21967 * @param superClass 21968 * @param methods 21969 */ 21970 function clazz(SuperClass, methods) { 21971 var constructor = function () {}; 21972 constructor.prototype = new SuperClass; 21973 constructor.prototype.constructor = constructor; 21974 constructor.prototype.parent = SuperClass.prototype; 21975 constructor.prototype = $.extend(constructor.prototype, methods); 21976 return constructor; 21977 } 21978 21979 AbstractSelect2 = clazz(Object, { 21980 21981 // abstract 21982 bind: function (func) { 21983 var self = this; 21984 return function () { 21985 func.apply(self, arguments); 21986 }; 21987 }, 21988 21989 // abstract 21990 init: function (opts) { 21991 var results, search, resultsSelector = ".select2-results"; 21992 21993 // prepare options 21994 this.opts = opts = this.prepareOpts(opts); 21995 21996 this.id=opts.id; 21997 21998 // destroy if called on an existing component 21999 if (opts.element.data("select2") !== undefined && 22000 opts.element.data("select2") !== null) { 22001 opts.element.data("select2").destroy(); 22002 } 22003 22004 this.container = this.createContainer(); 22005 22006 this.liveRegion = $("<span>", { 22007 role: "status", 22008 "aria-live": "polite" 22009 }) 22010 .addClass("select2-hidden-accessible") 22011 .appendTo(document.body); 22012 22013 this.containerId="s2id_"+(opts.element.attr("id") || "autogen"+nextUid()); 22014 this.containerEventName= this.containerId 22015 .replace(/([.])/g, '_') 22016 .replace(/([;&,\-\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1'); 22017 this.container.attr("id", this.containerId); 22018 22019 this.container.attr("title", opts.element.attr("title")); 22020 22021 this.body = $("body"); 22022 22023 syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass); 22024 22025 this.container.attr("style", opts.element.attr("style")); 22026 this.container.css(evaluate(opts.containerCss)); 22027 this.container.addClass(evaluate(opts.containerCssClass)); 22028 22029 this.elementTabIndex = this.opts.element.attr("tabindex"); 22030 22031 // swap container for the element 22032 this.opts.element 22033 .data("select2", this) 22034 .attr("tabindex", "-1") 22035 .before(this.container) 22036 .on("click.select2", killEvent); // do not leak click events 22037 22038 this.container.data("select2", this); 22039 22040 this.dropdown = this.container.find(".select2-drop"); 22041 22042 syncCssClasses(this.dropdown, this.opts.element, this.opts.adaptDropdownCssClass); 22043 22044 this.dropdown.addClass(evaluate(opts.dropdownCssClass)); 22045 this.dropdown.data("select2", this); 22046 this.dropdown.on("click", killEvent); 22047 22048 this.results = results = this.container.find(resultsSelector); 22049 this.search = search = this.container.find("input.select2-input"); 22050 22051 this.queryCount = 0; 22052 this.resultsPage = 0; 22053 this.context = null; 22054 22055 // initialize the container 22056 this.initContainer(); 22057 22058 this.container.on("click", killEvent); 22059 22060 installFilteredMouseMove(this.results); 22061 22062 this.dropdown.on("mousemove-filtered", resultsSelector, this.bind(this.highlightUnderEvent)); 22063 this.dropdown.on("touchstart touchmove touchend", resultsSelector, this.bind(function (event) { 22064 this._touchEvent = true; 22065 this.highlightUnderEvent(event); 22066 })); 22067 this.dropdown.on("touchmove", resultsSelector, this.bind(this.touchMoved)); 22068 this.dropdown.on("touchstart touchend", resultsSelector, this.bind(this.clearTouchMoved)); 22069 22070 // Waiting for a click event on touch devices to select option and hide dropdown 22071 // otherwise click will be triggered on an underlying element 22072 this.dropdown.on('click', this.bind(function (event) { 22073 if (this._touchEvent) { 22074 this._touchEvent = false;
22075 this.selectHighlighted(); 22076 } 22077 })); 22078 22079 installDebouncedScroll(80, this.results); 22080 this.dropdown.on("scroll-debounced", resultsSelector, this.bind(this.loadMoreIfNeeded)); 22081 22082 // do not propagate change event from the search field out of the component 22083 $(this.container).on("change", ".select2-input", function(e) {e.stopPropagation();}); 22084 $(this.dropdown).on("change", ".select2-input", function(e) {e.stopPropagation();}); 22085 22086 // if jquery.mousewheel plugin is installed we can prevent out-of-bounds scrolling of results via mousewheel 22087 if ($.fn.mousewheel) { 22088 results.mousewheel(function (e, delta, deltaX, deltaY) { 22089 var top = results.scrollTop(); 22090 if (deltaY > 0 && top - deltaY <= 0) { 22091 results.scrollTop(0); 22092 killEvent(e); 22093 } else if (deltaY < 0 && results.get(0).scrollHeight - results.scrollTop() + deltaY <= results.height()) { 22094 results.scrollTop(results.get(0).scrollHeight - results.height()); 22095 killEvent(e); 22096 } 22097 }); 22098 } 22099 22100 installKeyUpChangeEvent(search); 22101 search.on("keyup-change input paste", this.bind(this.updateResults)); 22102 search.on("focus", function () { search.addClass("select2-focused"); }); 22103 search.on("blur", function () { search.removeClass("select2-focused");}); 22104 22105 this.dropdown.on("mouseup", resultsSelector, this.bind(function (e) { 22106 if ($(e.target).closest(".select2-result-selectable").length > 0) { 22107 this.highlightUnderEvent(e); 22108 this.selectHighlighted(e); 22109 } 22110 })); 22111 22112 // trap all mouse events from leaving the dropdown. sometimes there may be a modal that is listening 22113 // for mouse events outside of itself so it can close itself. since the dropdown is now outside the select2's 22114 // dom it will trigger the popup close, which is not what we want 22115 // focusin can cause focus wars between modals and select2 since the dropdown is outside the modal. 22116 this.dropdown.on("click mouseup mousedown touchstart touchend focusin", function (e) { e.stopPropagation(); }); 22117 22118 this.nextSearchTerm = undefined; 22119 22120 if ($.isFunction(this.opts.initSelection)) { 22121 // initialize selection based on the current value of the source element 22122 this.initSelection(); 22123 22124 // if the user has provided a function that can set selection based on the value of the source element 22125 // we monitor the change event on the element and trigger it, allowing for two way synchronization 22126 this.monitorSource(); 22127 } 22128 22129 if (opts.maximumInputLength !== null) { 22130 this.search.attr("maxlength", opts.maximumInputLength); 22131 } 22132 22133 var disabled = opts.element.prop("disabled"); 22134 if (disabled === undefined) disabled = false; 22135 this.enable(!disabled); 22136 22137 var readonly = opts.element.prop("readonly"); 22138 if (readonly === undefined) readonly = false; 22139 this.readonly(readonly); 22140 22141 // Calculate size of scrollbar 22142 scrollBarDimensions = scrollBarDimensions || measureScrollbar(); 22143 22144 this.autofocus = opts.element.prop("autofocus"); 22145 opts.element.prop("autofocus", false); 22146 if (this.autofocus) this.focus(); 22147 22148 this.search.attr("placeholder", opts.searchInputPlaceholder); 22149 }, 22150 22151 // abstract 22152 destroy: function () { 22153 var element=this.opts.element, select2 = element.data("select2"); 22154 22155 this.close(); 22156 22157 if (this.propertyObserver) { 22158 this.propertyObserver.disconnect(); 22159 this.propertyObserver = null; 22160 } 22161 22162 if (select2 !== undefined) { 22163 select2.container.remove(); 22164 select2.liveRegion.remove(); 22165 select2.dropdown.remove(); 22166 element 22167 .removeClass("select2-offscreen") 22168 .removeData("select2") 22169 .off(".select2") 22170 .prop("autofocus", this.autofocus || false); 22171 if (this.elementTabIndex) { 22172 element.attr({tabindex: this.elementTabIndex}); 22173 } else { 22174 element.removeAttr("tabindex"); 22175 } 22176 element.show(); 22177 } 22178 22179 cleanupJQueryElements.call(this, 22180 "container", 22181 "liveRegion", 22182 "dropdown", 22183 "results", 22184 "search" 22185 ); 22186 }, 22187 22188 // abstract 22189 optionToData: function(element) { 22190 if (element.is("option")) { 22191 return { 22192 id:element.prop("value"), 22193 text:element.text(), 22194 element: element.get(), 22195 css: element.attr("class"), 22196 disabled: element.prop("disabled"), 22197 locked: equal(element.attr("locked"), "locked") || equal(element.data("locked"), true) 22198 }; 22199 } else if (element.is("optgroup")) { 22200 return { 22201 text:element.attr("label"), 22202 children:[], 22203 element: element.get(), 22204 css: element.attr("class") 22205 }; 22206 } 22207 }, 22208 22209 // abstract 22210 prepareOpts: function (opts) { 22211 var element, select, idKey, ajaxUrl, self = this; 22212 22213 element = opts.element; 22214 22215 if (element.get(0).tagName.toLowerCase() === "select") { 22216 this.select = select = opts.element; 22217 } 22218 22219 if (select) { 22220 // these options are not allowed when attached to a select because they are picked up off the element itself 22221 $.each(["id", "multiple", "ajax", "query", "createSearchChoice", "initSelection", "data", "tags"], function () { 22222 if (this in opts) { 22223 throw new Error("Option '" + this + "' is not allowed for Select2 when attached to a <select> element."); 22224 } 22225 }); 22226 } 22227 22228 opts = $.extend({}, { 22229 populateResults: function(container, results, query
22229) { 22230 var populate, id=this.opts.id, liveRegion=this.liveRegion; 22231 22232 populate=function(results, container, depth) { 22233 22234 var i, l, result, selectable, disabled, compound, node, label, innerContainer, formatted; 22235 22236 results = opts.sortResults(results, container, query); 22237 22238 for (i = 0, l = results.length; i < l; i = i + 1) { 22239 22240 result=results[i]; 22241 22242 disabled = (result.disabled === true); 22243 selectable = (!disabled) && (id(result) !== undefined); 22244 22245 compound=result.children && result.children.length > 0; 22246 22247 node=$("<li></li>"); 22248 node.addClass("select2-results-dept-"+depth); 22249 node.addClass("select2-result"); 22250 node.addClass(selectable ? "select2-result-selectable" : "select2-result-unselectable"); 22251 if (disabled) { node.addClass("select2-disabled"); } 22252 if (compound) { node.addClass("select2-result-with-children"); } 22253 node.addClass(self.opts.formatResultCssClass(result)); 22254 node.attr("role", "presentation"); 22255 22256 label=$(document.createElement("div")); 22257 label.addClass("select2-result-label"); 22258 label.attr("id", "select2-result-label-" + nextUid()); 22259 label.attr("role", "option"); 22260 22261 formatted=opts.formatResult(result, label, query, self.opts.escapeMarkup); 22262 if (formatted!==undefined) { 22263 label.html(formatted); 22264 node.append(label); 22265 } 22266 22267 22268 if (compound) { 22269 22270 innerContainer=$("<ul></ul>"); 22271 innerContainer.addClass("select2-result-sub"); 22272 populate(result.children, innerContainer, depth+1); 22273 node.append(innerContainer); 22274 } 22275 22276 node.data("select2-data", result); 22277 container.append(node); 22278 } 22279 22280 liveRegion.text(opts.formatMatches(results.length)); 22281 }; 22282 22283 populate(results, container, 0); 22284 } 22285 }, $.fn.select2.defaults, opts); 22286 22287 if (typeof(opts.id) !== "function") { 22288 idKey = opts.id; 22289 opts.id = function (e) { return e[idKey]; }; 22290 } 22291 22292 if ($.isArray(opts.element.data("select2Tags"))) { 22293 if ("tags" in opts) { 22294 throw "tags specified as both an attribute 'data-select2-tags' and in options of Select2 " + opts.element.attr("id"); 22295 } 22296 opts.tags=opts.element.data("select2Tags"); 22297 } 22298 22299 if (select) { 22300 opts.query = this.bind(function (query) { 22301 var data = { results: [], more: false }, 22302 term = query.term, 22303 children, placeholderOption, process; 22304 22305 process=function(element, collection) { 22306 var group; 22307 if (element.is("option")) { 22308 if (query.matcher(term, element.text(), element)) { 22309 collection.push(self.optionToData(element)); 22310 } 22311 } else if (element.is("optgroup")) { 22312 group=self.optionToData(element); 22313 element.children().each2(function(i, elm) { process(elm, group.children); }); 22314 if (group.children.length>0) { 22315 collection.push(group); 22316 } 22317 } 22318 }; 22319 22320 children=element.children(); 22321 22322 // ignore the placeholder option if there is one 22323 if (this.getPlaceholder() !== undefined && children.length > 0) { 22324 placeholderOption = this.getPlaceholderOption(); 22325 if (placeholderOption) { 22326 children=children.not(placeholderOption); 22327 } 22328 } 22329 22330 children.each2(function(i, elm) { process(elm, data.results); }); 22331 22332 query.callback(data); 22333 }); 22334 // this is needed because inside val() we construct choices from options and there id is hardcoded 22335 opts.id=function(e) { return e.id; }; 22336 } else {
22337 if (!("query" in opts)) { 22338 22339 if ("ajax" in opts) { 22340 ajaxUrl = opts.element.data("ajax-url"); 22341 if (ajaxUrl && ajaxUrl.length > 0) { 22342 opts.ajax.url = ajaxUrl; 22343 } 22344 opts.query = ajax.call(opts.element, opts.ajax); 22345 } else if ("data" in opts) { 22346 opts.query = local(opts.data); 22347 } else if ("tags" in opts) { 22348 opts.query = tags(opts.tags); 22349 if (opts.createSearchChoice === undefined) { 22350 opts.createSearchChoice = function (term) { return {id: $.trim(term), text: $.trim(term)}; }; 22351 } 22352 if (opts.initSelection === undefined) { 22353 opts.initSelection = function (element, callback) { 22354 var data = []; 22355 $(splitVal(element.val(), opts.separator)).each(function () { 22356 var obj = { id: this, text: this }, 22357 tags = opts.tags; 22358 if ($.isFunction(tags)) tags=tags(); 22359 $(tags).each(function() { if (equal(this.id, obj.id)) { obj = this; return false; } }); 22360 data.push(obj); 22361 }); 22362 22363 callback(data); 22364 }; 22365 } 22366 } 22367 } 22368 } 22369 if (typeof(opts.query) !== "function") { 22370 throw "query function not defined for Select2 " + opts.element.attr("id"); 22371 } 22372 22373 if (opts.createSearchChoicePosition === 'top') { 22374 opts.createSearchChoicePosition = function(list, item) { list.unshift(item); }; 22375 } 22376 else if (opts.createSearchChoicePosition === 'bottom') { 22377 opts.createSearchChoicePosition = function(list, item) { list.push(item); }; 22378 } 22379 else if (typeof(opts.createSearchChoicePosition) !== "function") { 22380 throw "invalid createSearchChoicePosition option must be 'top', 'bottom' or a custom function"; 22381 } 22382 22383 return opts; 22384 }, 22385 22386 /** 22387 * Monitor the original element for changes and update select2 accordingly 22388 */ 22389 // abstract 22390 monitorSource: function () { 22391 var el = this.opts.element, sync, observer; 22392 22393 el.on("change.select2", this.bind(function (e) { 22394 if (this.opts.element.data("select2-change-triggered") !== true) { 22395 this.initSelection(); 22396 } 22397 })); 22398 22399 sync = this.bind(function () { 22400 22401 // sync enabled state 22402 var disabled = el.prop("disabled"); 22403 if (disabled === undefined) disabled = false; 22404 this.enable(!disabled); 22405 22406 var readonly = el.prop("readonly"); 22407 if (readonly === undefined) readonly = false; 22408 this.readonly(readonly); 22409 22410 syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass); 22411 this.container.addClass(evaluate(this.opts.containerCssClass)); 22412 22413 syncCssClasses(this.dropdown, this.opts.element, this.opts.adaptDropdownCssClass); 22414 this.dropdown.addClass(evaluate(this.opts.dropdownCssClass)); 22415 22416 }); 22417 22418 // IE8-10 (IE9/10 won't fire propertyChange via attachEventListener) 22419 if (el.length && el[0].attachEvent) { 22420 el.each(function() { 22421 this.attachEvent("onpropertychange", sync); 22422 }); 22423 } 22424 22425 // safari, chrome, firefox, IE11 22426 observer = window.MutationObserver || window.WebKitMutationObserver|| window.MozMutationObserver; 22427 if (observer !== undefined) { 22428 if (this.propertyObserver) { delete this.propertyObserver; this.propertyObserver = null; } 22429 this.propertyObserver = new observer(function (mutations) { 22430 mutations.forEach(sync); 22431 }); 22432 this.propertyObserver.observe(el.get(0), { attributes:true, subtree:false }); 22433 } 22434 }, 22435 22436 // abstract 22437 triggerSelect: function(data) { 22438 var evt = $.Event("select2-selecting", { val: this.id(data), object: data }); 22439 this.opts.element.trigger(evt); 22440 return !evt.isDefaultPrevented(); 22441 }, 22442 22443 /** 22444 * Triggers the change event on the source element 22445 */ 22446 // abstract 22447 triggerChange: function (details) { 22448 22449 details = details || {}; 22450 details= $.extend({}, details, { type: "change", val: this.val() }); 22451 // prevents recursive triggering 22452 this.opts.element.data("select2-change-triggered", true); 22453 this.opts.element.trigger(details); 22454 this.opts.element.data("select2-change-triggered", false); 22455 22456 // some validation frameworks ignore the change event and listen instead to keyup, click for selects 22457 // so here we trigger the click event manually 22458 this.opts.element.click(); 22459 22460 // ValidationEngine ignores the change event and listens instead to blur 22461 // so here we trigger the blur event manually if so desired 22462 if (this.opts.blurOnChange) 22463 this.opts.element.blur(); 22464 }, 22465 22466 //abstract 22467 isInterfaceEnabled: function() 22468 { 22469 return this.enabledInterface === true; 22470 }, 22471 22472 // abstract 22473 enableInterface: function() { 22474 var enabled = this._enabled && !this._readonly, 22475 disabled = !enabled; 22476 22477 if (enabled === this.enabledInterface) return false;
22478 22479 this.container.toggleClass("select2-container-disabled", disabled); 22480 this.close(); 22481 this.enabledInterface = enabled; 22482 22483 return true; 22484 }, 22485 22486 // abstract 22487 enable: function(enabled) { 22488 if (enabled === undefined) enabled = true; 22489 if (this._enabled === enabled) return; 22490 this._enabled = enabled; 22491 22492 this.opts.element.prop("disabled", !enabled); 22493 this.enableInterface(); 22494 }, 22495 22496 // abstract 22497 disable: function() { 22498 this.enable(false); 22499 }, 22500 22501 // abstract 22502 readonly: function(enabled) { 22503 if (enabled === undefined) enabled = false; 22504 if (this._readonly === enabled) return; 22505 this._readonly = enabled; 22506 22507 this.opts.element.prop("readonly", enabled); 22508 this.enableInterface(); 22509 }, 22510 22511 // abstract 22512 opened: function () { 22513 return this.container.hasClass("select2-dropdown-open"); 22514 }, 22515 22516 // abstract 22517 positionDropdown: function() { 22518 var $dropdown = this.dropdown, 22519 offset = this.container.offset(), 22520 height = this.container.outerHeight(false), 22521 width = this.container.outerWidth(false), 22522 dropHeight = $dropdown.outerHeight(false), 22523 $window = $(window), 22524 windowWidth = $window.width(), 22525 windowHeight = $window.height(), 22526 viewPortRight = $window.scrollLeft() + windowWidth, 22527 viewportBottom = $window.scrollTop() + windowHeight, 22528 dropTop = offset.top + height, 22529 dropLeft = offset.left, 22530 enoughRoomBelow = dropTop + dropHeight <= viewportBottom, 22531 enoughRoomAbove = (offset.top - dropHeight) >= $window.scrollTop(), 22532 dropWidth = $dropdown.outerWidth(false), 22533 enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight, 22534 aboveNow = $dropdown.hasClass("select2-drop-above"), 22535 bodyOffset, 22536 above, 22537 changeDirection, 22538 css, 22539 resultsListNode; 22540 22541 // always prefer the current above/below alignment, unless there is not enough room 22542 if (aboveNow) { 22543 above = true; 22544 if (!enoughRoomAbove && enoughRoomBelow) { 22545 changeDirection = true; 22546 above = false; 22547 } 22548 } else { 22549 above = false; 22550 if (!enoughRoomBelow && enoughRoomAbove) { 22551 changeDirection = true; 22552 above = true; 22553 } 22554 } 22555 22556 //if we are changing direction we need to get positions when dropdown is hidden; 22557 if (changeDirection) { 22558 $dropdown.hide(); 22559 offset = this.container.offset(); 22560 height = this.container.outerHeight(false); 22561 width = this.container.outerWidth(false); 22562 dropHeight = $dropdown.outerHeight(false); 22563 viewPortRight = $window.scrollLeft() + windowWidth; 22564 viewportBottom = $window.scrollTop() + windowHeight; 22565 dropTop = offset.top + height; 22566 dropLeft = offset.left; 22567 dropWidth = $dropdown.outerWidth(false); 22568 enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight; 22569 $dropdown.show(); 22570 22571 // fix so the cursor does not move to the left within the search-textbox in IE 22572 this.focusSearch(); 22573 } 22574 22575 if (this.opts.dropdownAutoWidth) { 22576 resultsListNode = $('.select2-results', $dropdown)[0]; 22577 $dropdown.addClass('select2-drop-auto-width'); 22578 $dropdown.css('width', ''); 22579 // Add scrollbar width to dropdown if vertical scrollbar is present 22580 dropWidth = $dropdown.outerWidth(false) + (resultsListNode.scrollHeight === resultsListNode.clientHeight ? 0 : scrollBarDimensions.width); 22581 dropWidth > width ? width = dropWidth : dropWidth = width; 22582 dropHeight = $dropdown.outerHeight(false); 22583 enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight; 22584 } 22585 else { 22586 this.container.removeClass('select2-drop-auto-width'); 22587 } 22588 22589 //console.log("below/ droptop:", dropTop, "dropHeight", dropHeight, "sum", (dropTop+dropHeight)+" viewport bottom", viewportBottom, "enough?", enoughRoomBelow); 22590 //console.log("above/ offset.top", offset.top, "dropHeight", dropHeight, "top", (offset.top-dropHeight), "scrollTop", this.body.scrollTop(), "enough?", enoughRoomAbove); 22591 22592 // fix positioning when body has an offset and is not position: static 22593 if (this.body.css('position') !== 'static') { 22594 bodyOffset = this.body.offset(); 22595 dropTop -= bodyOffset.top; 22596 dropLeft -= bodyOffset.left; 22597 } 22598 22599 if (!enoughRoomOnRight) { 22600 dropLeft = offset.left + this.container.outerWidth(false) - dropWidth; 22601 } 22602 22603 css = { 22604 left: dropLeft, 22605 width: width 22606 }; 22607 22608 if (above) { 22609 css.top = offset.top - dropHeight; 22610 css.bottom = 'auto'; 22611 this.container.addClass("select2-drop-above"); 22612 $dropdown.addClass("select2-drop-above"); 22613 } 22614 else { 22615 css.top = dropTop; 22616 css.bottom = 'auto'; 22617 this.container.removeClass("select2-drop-above"); 22618 $dropdown.removeClass("select2-drop-above"); 22619 } 22620 css = $.extend(css, evaluate(this.opts.dropdownCss)); 22621 22622 $dropdown.css(css); 22623 }, 22624 22625 // abstract 22626 shouldOpen: function() { 22627 var event; 22628 22629 if (this.opened()) return false;
22630 22631 if (this._enabled === false || this._readonly === true) return false; 22632 22633 event = $.Event("select2-opening"); 22634 this.opts.element.trigger(event); 22635 return !event.isDefaultPrevented(); 22636 }, 22637 22638 // abstract 22639 clearDropdownAlignmentPreference: function() { 22640 // clear the classes used to figure out the preference of where the dropdown should be opened 22641 this.container.removeClass("select2-drop-above"); 22642 this.dropdown.removeClass("select2-drop-above"); 22643 }, 22644 22645 /** 22646 * Opens the dropdown 22647 * 22648 * @return {Boolean} whether or not dropdown was opened. This method will return false if, for example, 22649 * the dropdown is already open, or if the 'open' event listener on the element called preventDefault(). 22650 */ 22651 // abstract 22652 open: function () { 22653 22654 if (!this.shouldOpen()) return false; 22655 22656 this.opening(); 22657 22658 return true; 22659 }, 22660 22661 /** 22662 * Performs the opening of the dropdown 22663 */ 22664 // abstract 22665 opening: function() { 22666 var cid = this.containerEventName, 22667 scroll = "scroll." + cid, 22668 resize = "resize."+cid, 22669 orient = "orientationchange."+cid, 22670 mask; 22671 22672 this.container.addClass("select2-dropdown-open").addClass("select2-container-active"); 22673 22674 this.clearDropdownAlignmentPreference(); 22675 22676 if(this.dropdown[0] !== this.body.children().last()[0]) { 22677 this.dropdown.detach().appendTo(this.body); 22678 } 22679 22680 // create the dropdown mask if doesn't already exist 22681 mask = $("#select2-drop-mask"); 22682 if (mask.length == 0) { 22683 mask = $(document.createElement("div")); 22684 mask.attr("id","select2-drop-mask").attr("class","select2-drop-mask"); 22685 mask.hide(); 22686 mask.appendTo(this.body); 22687 mask.on("mousedown touchstart click", function (e) { 22688 // Prevent IE from generating a click event on the body 22689 reinsertElement(mask); 22690 22691 var dropdown = $("#select2-drop"), self; 22692 if (dropdown.length > 0) { 22693 self=dropdown.data("select2"); 22694 if (self.opts.selectOnBlur) { 22695 self.selectHighlighted({noFocus: true}); 22696 } 22697 self.close(); 22698 e.preventDefault(); 22699 e.stopPropagation(); 22700 } 22701 }); 22702 } 22703 22704 // ensure the mask is always right before the dropdown 22705 if (this.dropdown.prev()[0] !== mask[0]) { 22706 this.dropdown.before(mask); 22707 } 22708 22709 // move the global id to the correct dropdown 22710 $("#select2-drop").removeAttr("id"); 22711 this.dropdown.attr("id", "select2-drop"); 22712 22713 // show the elements 22714 mask.show(); 22715 22716 this.positionDropdown(); 22717 this.dropdown.show(); 22718 this.positionDropdown(); 22719 22720 this.dropdown.addClass("select2-drop-active"); 22721 22722 // attach listeners to events that can change the position of the container and thus require 22723 // the position of the dropdown to be updated as well so it does not come unglued from the container 22724 var that = this; 22725 this.container.parents().add(window).each(function () { 22726 $(this).on(resize+" "+scroll+" "+orient, function (e) { 22727 if (that.opened()) that.positionDropdown(); 22728 }); 22729 }); 22730 22731 22732 }, 22733 22734 // abstract 22735 close: function () { 22736 if (!this.opened()) return; 22737 22738 var cid = this.containerEventName, 22739 scroll = "scroll." + cid, 22740 resize = "resize."+cid, 22741 orient = "orientationchange."+cid; 22742 22743 // unbind event listeners 22744 this.container.parents().add(window).each(function () { $(this).off(scroll).off(resize).off(orient); }); 22745 22746 this.clearDropdownAlignmentPreference(); 22747 22748 $("#select2-drop-mask").hide(); 22749 this.dropdown.removeAttr("id"); // only the active dropdown has the select2-drop id 22750 this.dropdown.hide(); 22751 this.container.removeClass("select2-dropdown-open").removeClass("select2-container-active"); 22752 this.results.empty(); 22753 22754 22755 this.clearSearch(); 22756 this.search.removeClass("select2-active"); 22757 this.opts.element.trigger($.Event("select2-close")); 22758 }, 22759 22760 /** 22761 * Opens control, sets input value, and updates results. 22762 */ 22763 // abstract 22764 externalSearch: function (term) { 22765 this.open(); 22766 this.search.val(term); 22767 this.updateResults(false); 22768 }, 22769 22770 // abstract 22771 clearSearch: function () { 22772 22773 }, 22774 22775 //abstract 22776 getMaximumSelectionSize: function() { 22777 return evaluate(this.opts.maximumSelectionSize); 22778 }, 22779 22780 // abstract 22781 ensureHighlightVisible: function () { 22782 var results = this.results, children, index, child, hb, rb, y, more; 22783 22784 index = this.highlight(); 22785 22786 if (index < 0) return; 22787 22788 if (index == 0) { 22789 22790 // if the first element is highlighted scroll all the way to the top, 22791 // that way any unselectable headers above it will also be scrolled 22792 // into view 22793 22794 results.scrollTop(0); 22795 return; 22796 } 22797 22798 children = this.findHighlightableChoices().find('.select2-result-label'); 22799 22800 child = $(children[index]); 22801 22802 hb = child.offset().top + child.outerHeight(true); 22803 22804 // if this is the last child lets also make sure select2-more-results is visible 22805 if (index === children.length - 1) { 22806 more = results.find("li.select2-more-results"); 22807 if (more.length > 0) { 22808 hb = more.offset().top + more.outerHeight(true); 22809 } 22810 } 22811 22812 rb = results.offset().top + results.outerHeight(true); 22813 if (hb > rb) { 22814 results.scrollTop(results.scrollTop() + (hb - rb)); 22815 } 22816 y = child.offset().top - results.offset().top; 22817 22818 // make sure the top of the element is visible 22819 if (y < 0 && child.css('display') != 'none' ) { 22820 results.scrollTop(results.scrollTop() + y); // y is negative 22821 } 22822 }, 22823 22824 // abstract 22825 findHighlightableChoices: function() { 22826 return this.results.find(".select2-result-selectable:not(.select2-disabled):not(.select2-selected)"); 22827 }, 22828 22829 // abstract 22830 moveHighlight: function (delta) { 22831 var choices = this.findHighlightableChoices(), 22832 index = this.highlight(); 22833 22834 while (index > -1 && index < choices.length) { 22835 index += delta; 22836 var choice = $(choices[index]); 22837 if (choice.hasClass("select2-result-selectable") && !c
22837hoice.hasClass("select2-disabled") && !choice.hasClass("select2-selected")) { 22838 this.highlight(index); 22839 break; 22840 } 22841 } 22842 }, 22843 22844 // abstract 22845 highlight: function (index) { 22846 var choices = this.findHighlightableChoices(), 22847 choice, 22848 data; 22849 22850 if (arguments.length === 0) { 22851 return indexOf(choices.filter(".select2-highlighted")[0], choices.get()); 22852 } 22853 22854 if (index >= choices.length) index = choices.length - 1; 22855 if (index < 0) index = 0; 22856 22857 this.removeHighlight(); 22858 22859 choice = $(choices[index]); 22860 choice.addClass("select2-highlighted"); 22861 22862 // ensure assistive technology can determine the active choice 22863 this.search.attr("aria-activedescendant", choice.find(".select2-result-label").attr("id")); 22864 22865 this.ensureHighlightVisible(); 22866 22867 this.liveRegion.text(choice.text()); 22868 22869 data = choice.data("select2-data"); 22870 if (data) { 22871 this.opts.element.trigger({ type: "select2-highlight", val: this.id(data), choice: data }); 22872 } 22873 }, 22874 22875 removeHighlight: function() { 22876 this.results.find(".select2-highlighted").removeClass("select2-highlighted"); 22877 }, 22878 22879 touchMoved: function() { 22880 this._touchMoved = true; 22881 }, 22882 22883 clearTouchMoved: function() { 22884 this._touchMoved = false; 22885 }, 22886 22887 // abstract 22888 countSelectableResults: function() { 22889 return this.findHighlightableChoices().length; 22890 }, 22891 22892 // abstract 22893 highlightUnderEvent: function (event) { 22894 var el = $(event.target).closest(".select2-result-selectable"); 22895 if (el.length > 0 && !el.is(".select2-highlighted")) { 22896 var choices = this.findHighlightableChoices(); 22897 this.highlight(choices.index(el)); 22898 } else if (el.length == 0) { 22899 // if we are over an unselectable item remove all highlights 22900 this.removeHighlight(); 22901 } 22902 }, 22903 22904 // abstract 22905 loadMoreIfNeeded: function () { 22906 var results = this.results, 22907 more = results.find("li.select2-more-results"), 22908 below, // pixels the element is below the scroll fold, below==0 is when the element is starting to be visible 22909 page = this.resultsPage + 1, 22910 self=this, 22911 term=this.search.val(), 22912 context=this.context; 22913 22914 if (more.length === 0) return; 22915 below = more.offset().top - results.offset().top - results.height(); 22916 22917 if (below <= this.opts.loadMorePadding) { 22918 more.addClass("select2-active"); 22919 this.opts.query({ 22920 element: this.opts.element, 22921 term: term, 22922 page: page, 22923 context: context, 22924 matcher: this.opts.matcher, 22925 callback: this.bind(function (data) { 22926 22927 // ignore a response if the select2 has been closed before it was received 22928 if (!self.opened()) return; 22929 22930 22931 self.opts.populateResults.call(this, results, data.results, {term: term, page: page, context:context}); 22932 self.postprocessResults(data, false, false); 22933 22934 if (data.more===true) { 22935 more.detach().appendTo(results).text(evaluate(self.opts.formatLoadMore, page+1)); 22936 window.setTimeout(function() { self.loadMoreIfNeeded(); }, 10); 22937 } else { 22938 more.remove(); 22939 } 22940 self.positionDropdown(); 22941 self.resultsPage = page; 22942 self.context = data.context; 22943 this.opts.element.trigger({ type: "select2-loaded", items: data }); 22944 })}); 22945 } 22946 }, 22947 22948 /** 22949 * Default tokenizer function which does nothing 22950 */ 22951 tokenize: function() { 22952 22953 }, 22954 22955 /** 22956 * @param initial whether or not this is the call to this method right after the dropdown has been opened 22957 */ 22958 // abstract 22959 updateResults: function (initial) { 22960 var search = this.search, 22961 results = this.results, 22962 opts = this.opts, 22963 data, 22964 self = this, 22965 input, 22966 term = search.val(), 22967 lastTerm = $.data(this.container, "select2-last-term"), 22968 // sequence number used to drop out-of-order responses 22969 queryNumber; 22970 22971 // prevent duplicate queries against the same term 22972 if (initial !== true && lastTerm && equal(term, lastTerm)) return; 22973 22974 $.data(this.container, "select2-last-term", term); 22975 22976 // if the search is currently hidden we do not alter the results 22977 if (initial !== true && (this.showSearchInput === false || !this.opened())) { 22978 return; 22979 } 22980 22981 function postRender() { 22982 search.removeClass("select2-active"); 22983 self.positionDropdown(); 22984 if (results.find('.select2-no-results,.select2-selection-limit,.select2-searching').length) { 22985 self.liveRegion.text(results.text()); 22986 } 22987 else { 22988 self.liveRegion.text(self.opts.formatMatches(results.find('.select2-result-selectable').length)); 22989 } 22990 } 22991 22992 function render(html) { 22993 results.html(html); 22994 postRender(); 22995 } 22996 22997 queryNumber = ++this.queryCount; 22998 22999 var maxSelSize = this.getMaximumSelectionSize(); 23000 if (maxSelSize >=1) { 23001 data = this.data(); 23002 if ($.isArray(data) && data.length >= maxSelSize && checkFormatter(opts.formatSelectionTooBig, "formatSelectionTooBig")) {
23003 render("<li class='select2-selection-limit'>" + evaluate(opts.formatSelectionTooBig, maxSelSize) + "</li>"); 23004 return; 23005 } 23006 } 23007 23008 if (search.val().length < opts.minimumInputLength) { 23009 if (checkFormatter(opts.formatInputTooShort, "formatInputTooShort")) { 23010 render("<li class='select2-no-results'>" + evaluate(opts.formatInputTooShort, search.val(), opts.minimumInputLength) + "</li>"); 23011 } else { 23012 render(""); 23013 } 23014 if (initial && this.showSearch) this.showSearch(true); 23015 return; 23016 } 23017 23018 if (opts.maximumInputLength && search.val().length > opts.maximumInputLength) { 23019 if (checkFormatter(opts.formatInputTooLong, "formatInputTooLong")) { 23020 render("<li class='select2-no-results'>" + evaluate(opts.formatInputTooLong, search.val(), opts.maximumInputLength) + "</li>"); 23021 } else { 23022 render(""); 23023 } 23024 return; 23025 } 23026 23027 if (opts.formatSearching && this.findHighlightableChoices().length === 0) { 23028 render("<li class='select2-searching'>" + evaluate(opts.formatSearching) + "</li>"); 23029 } 23030 23031 search.addClass("select2-active"); 23032 23033 this.removeHighlight(); 23034 23035 // give the tokenizer a chance to pre-process the input 23036 input = this.tokenize(); 23037 if (input != undefined && input != null) { 23038 search.val(input); 23039 } 23040 23041 this.resultsPage = 1; 23042 23043 opts.query({ 23044 element: opts.element, 23045 term: search.val(), 23046 page: this.resultsPage, 23047 context: null, 23048 matcher: opts.matcher, 23049 callback: this.bind(function (data) { 23050 var def; // default choice 23051 23052 // ignore old responses 23053 if (queryNumber != this.queryCount) { 23054 return; 23055 } 23056 23057 // ignore a response if the select2 has been closed before it was received 23058 if (!this.opened()) { 23059 this.search.removeClass("select2-active"); 23060 return; 23061 } 23062 23063 // save context, if any 23064 this.context = (data.context===undefined) ? null : data.context; 23065 // create a default choice and prepend it to the list 23066 if (this.opts.createSearchChoice && search.val() !== "") { 23067 def = this.opts.createSearchChoice.call(self, search.val(), data.results); 23068 if (def !== undefined && def !== null && self.id(def) !== undefined && self.id(def) !== null) { 23069 if ($(data.results).filter( 23070 function () { 23071 return equal(self.id(this), self.id(def)); 23072 }).length === 0) { 23073 this.opts.createSearchChoicePosition(data.results, def); 23074 } 23075 } 23076 } 23077 23078 if (data.results.length === 0 && checkFormatter(opts.formatNoMatches, "formatNoMatches")) { 23079 render("<li class='select2-no-results'>" + evaluate(opts.formatNoMatches, search.val()) + "</li>"); 23080 return; 23081 } 23082 23083 results.empty(); 23084 self.opts.populateResults.call(this, results, data.results, {term: search.val(), page: this.resultsPage, context:null}); 23085 23086 if (data.more === true && checkFormatter(opts.formatLoadMore, "formatLoadMore")) { 23087 results.append("<li class='select2-more-results'>" + self.opts.escapeMarkup(evaluate(opts.formatLoadMore, this.resultsPage)) + "</li>"); 23088 window.setTimeout(function() { self.loadMoreIfNeeded(); }, 10); 23089 } 23090 23091 this.postprocessResults(data, initial); 23092 23093 postRender(); 23094 23095 this.opts.element.trigger({ type: "select2-loaded", items: data }); 23096 })}); 23097 }, 23098 23099 // abstract 23100 cancel: function () { 23101 this.close(); 23102 }, 23103 23104 // abstract 23105 blur: function () { 23106 // if selectOnBlur == true, select the currently highlighted option 23107 if (this.opts.selectOnBlur) 23108 this.selectHighlighted({noFocus: true}); 23109 23110 this.close(); 23111 this.container.removeClass("select2-container-active"); 23112 // synonymous to .is(':focus'), which is available in jquery >= 1.6 23113 if (this.search[0] === document.activeElement) { this.search.blur(); } 23114 this.clearSearch(); 23115 this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus"); 23116 }, 23117 23118 // abstract 23119 focusSearch: function () { 23120 focus(this.search); 23121 }, 23122 23123 // abstract 23124 selectHighlighted: function (options) { 23125 if (this._touchMoved) { 23126 this.clearTouchMoved(); 23127 return; 23128 } 23129 var index=this.highlight(), 23130 highlighted=this.results.find(".select2-highlighted"), 23131 data = highlighted.closest('.select2-result').data("select2-data"); 23132 23133 if (data) { 23134 this.highlight(index); 23135 this.onSelect(data, options); 23136 } else if (options && options.noFocus) { 23137 this.close(); 23138 } 23139 }, 23140 23141 // abstract 23142 getPlaceholder: function () { 23143 var placeholderOption; 23144 return this.opts.element.attr("placeholder") || 23145 this.opts.element.attr("data-placeholder") || // jquery 1.4 compat 23146 this.opts.element.data("placeholder") || 23147 this.opts.placeholder || 23148 ((placeholderOption = this.getPlaceholderOption()) !== undefined ? placeholderOption.text() : undefined); 23149 }, 23150 23151 // abstract 23152 getPlaceholderOption: function() { 23153 if (this.select) { 23154 var firstOption = this.select.children('option').first(); 23155 if (this.opts.placeholderOption !== undefined ) { 23156 //Determine the placeholder option based on the specified placeholderOption setting 23157 return (this.opts.placeholderOption === "first" && firstOption) || 23158 (typeof this.opts.placeholderOption === "function" && this.opts.placeholderOption(this.select)); 23159 } else if ($.trim(firstOption.text()) === "" && firstOption.val() === "") { 23160 //No explicit placeholder option specified, use the first if it's blank 23161 return firstOption; 23162 } 23163 } 23164 }, 23165 23166 /** 23167 * Get the desired width for the container element. This is 23168 * derived first from option `width` passed to select2, then 23169 * the inline 'style' on the original element, and finally 23170 * falls back to the jQuery calculated element width. 23171 */ 23172 // abstract 23173 initContainerWidth: function () {
23174 function resolveContainerWidth() { 23175 var style, attrs, matches, i, l, attr; 23176 23177 if (this.opts.width === "off") { 23178 return null; 23179 } else if (this.opts.width === "element"){ 23180 return this.opts.element.outerWidth(false) === 0 ? 'auto' : this.opts.element.outerWidth(false) + 'px'; 23181 } else if (this.opts.width === "copy" || this.opts.width === "resolve") { 23182 // check if there is inline style on the element that contains width 23183 style = this.opts.element.attr('style'); 23184 if (style !== undefined) { 23185 attrs = style.split(';'); 23186 for (i = 0, l = attrs.length; i < l; i = i + 1) { 23187 attr = attrs[i].replace(/\s/g, ''); 23188 matches = attr.match(/^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i); 23189 if (matches !== null && matches.length >= 1) 23190 return matches[1]; 23191 } 23192 } 23193 23194 if (this.opts.width === "resolve") { 23195 // next check if css('width') can resolve a width that is percent based, this is sometimes possible 23196 // when attached to input type=hidden or elements hidden via css 23197 style = this.opts.element.css('width'); 23198 if (style.indexOf("%") > 0) return style; 23199 23200 // finally, fallback on the calculated width of the element 23201 return (this.opts.element.outerWidth(false) === 0 ? 'auto' : this.opts.element.outerWidth(false) + 'px'); 23202 } 23203 23204 return null; 23205 } else if ($.isFunction(this.opts.width)) { 23206 return this.opts.width(); 23207 } else { 23208 return this.opts.width; 23209 } 23210 }; 23211 23212 var width = resolveContainerWidth.call(this); 23213 if (width !== null) { 23214 this.container.css("width", width); 23215 } 23216 } 23217 }); 23218 23219 SingleSelect2 = clazz(AbstractSelect2, { 23220 23221 // single 23222 23223 createContainer: function () { 23224 var container = $(document.createElement("div")).attr({ 23225 "class": "select2-container" 23226 }).html([ 23227 "<a href='javascript:void(0)' class='select2-choice' tabindex='-1'>", 23228 " <span class='select2-chosen'> </span><abbr class='select2-search-choice-close'></abbr>", 23229 " <span class='select2-arrow' role='presentation'><b role='presentation'></b></span>", 23230 "</a>", 23231 "<label for='' class='select2-offscreen'></label>", 23232 "<input class='select2-focusser select2-offscreen' type='text' aria-haspopup='true' role='button' />", 23233 "<div class='select2-drop select2-display-none'>", 23234 " <div class='select2-search'>", 23235 " <label for='' class='select2-offscreen'></label>", 23236 " <input type='text' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' class='select2-input' role='combobox' aria-expanded='true'", 23237 " aria-autocomplete='list' />", 23238 " </div>", 23239 " <ul class='select2-results' role='listbox'>", 23240 " </ul>", 23241 "</div>"].join("")); 23242 return container; 23243 }, 23244 23245 // single 23246 enableInterface: function() { 23247 if (this.parent.enableInterface.apply(this, arguments)) { 23248 this.focusser.prop("disabled", !this.isInterfaceEnabled()); 23249 } 23250 }, 23251 23252 // single 23253 opening: function () { 23254 var el, range, len; 23255 23256 if (this.opts.minimumResultsForSearch >= 0) { 23257 this.showSearch(true); 23258 } 23259 23260 this.parent.opening.apply(this, arguments); 23261 23262 if (this.showSearchInput !== false) { 23263 // IE appends focusser.val() at the end of field :/ so we manually insert it at the beginning using a range 23264 // all other browsers handle this just fine 23265 23266 this.search.val(this.focusser.val()); 23267 } 23268 if (this.opts.shouldFocusInput(this)) { 23269 this.search.focus(); 23270 // move the cursor to the end after focussing, otherwise it will be at the beginning and 23271 // new text will appear *before* focusser.val() 23272 el = this.search.get(0); 23273 if (el.createTextRange) { 23274 range = el.createTextRange(); 23275 range.collapse(false); 23276 range.select(); 23277 } else if (el.setSelectionRange) { 23278 len = this.search.val().length; 23279 el.setSelectionRange(len, len); 23280 } 23281 } 23282 23283 // initializes search's value with nextSearchTerm (if defined by user) 23284 // ignore nextSearchTerm if the dropdown is opened by the user pressing a letter 23285 if(this.search.val() === "") { 23286 if(this.nextSearchTerm != undefined){ 23287 this.search.val(this.nextSearchTerm); 23288 this.search.select(); 23289 } 23290 } 23291 23292 this.focusser.prop("disabled", true).val(""); 23293 this.updateResults(true); 23294 this.opts.element.trigger($.Event("select2-open")); 23295 }, 23296 23297 // single 23298 close: function () { 23299 if (!this.opened()) return; 23300 this.parent.close.apply(this, arguments); 23301 23302 this.focusser.prop("disabled", false); 23303 23304 if (this.opts.shouldFocusInput(this)) { 23305 this.focusser.focus(); 23306 } 23307 }, 23308 23309 // single 23310 focus: function () { 23311 if (this.opened()) { 23312 this.close(); 23313 } else { 23314 this.focusser.prop("disabled", false); 23315 if (this.opts.shouldFocusInput(this)) { 23316 this.focusser.focus(); 23317 } 23318 } 23319 }, 23320 23321 // single 23322 isFocused: function () { 23323 return this.container.hasClass("select2-container-active"); 23324 }, 23325 23326 // single 23327 cancel: function () { 23328 this.parent.cancel.apply(this, arguments); 23329 this.focusser.prop("disabled", false); 23330 23331 if (this.opts.shouldFocusInput(this)) { 23332 this.focusser.focus(); 23333 } 23334 }, 23335 23336 // single 23337 destroy: function() { 23338 $("label[for='" + this.focusser.attr('id') + "']") 23339 .attr('for', this.opts.element.attr("id")); 23340 this.parent.destroy.apply(this, arguments); 23341 23342 cleanupJQueryElements.call(this, 23343 "selection", 23344 "focusser" 23345 ); 23346 }, 23347 23348 // single 23349 initContainer: function () { 23350 23351 var selection, 23352 container = this.container, 23353 dropdown = this.dropdown, 23354 idSuffix = nextUid(), 23355 elementLabel; 23356 23357 if (this.opts.minimumResultsForSearch < 0) { 23358 this.showSearch(false); 23359 } else { 23360 this.showSearch(true); 23361 } 23362 23363 this.selection = selection = container.find(".select2-choice"); 23364 23365 this.focusser = container.find(".select2-focusser"); 23366 23367 // add aria associations 23368 selection.find(".select2-chosen").attr("id", "select2-chosen-"+idSuffix); 23369 this.focusser.attr("aria-labelledby", "select2-chosen-"+idSuffix); 23370 this.results.attr("id", "select2-results-"+idSuffix); 23371 this.search.attr("aria-owns", "select2-results-"+idSuffix); 23372 23373 // rewrite labels from original element to focusser 23374 this.focusser.attr("id", "s2id_autogen"+idSuffix); 23375 23376 elementLabel = $("label[for='" + this.opts.element.attr("id") + "']"); 23377 23378 this.focusser.prev() 23379 .text(elementLabel.text()) 23380 .attr('for', this.focusser.attr('id')); 23381 23382 // Ensure the original element retains an accessible name 23383 var originalTitle = this.opts.element.attr("title"); 23384 this.opts.element.attr("title", (originalTitle || elementLabel.text())); 23385 23386 this.focusser.attr("tabindex", this.elementTabIndex); 23387
23388 // write label for search field using the label from the focusser element 23389 this.search.attr("id", this.focusser.attr('id') + '_search'); 23390 23391 this.search.prev() 23392 .text($("label[for='" + this.focusser.attr('id') + "']").text()) 23393 .attr('for', this.search.attr('id')); 23394 23395 this.search.on("keydown", this.bind(function (e) { 23396 if (!this.isInterfaceEnabled()) return; 23397 23398 if (e.which === KEY.PAGE_UP || e.which === KEY.PAGE_DOWN) { 23399 // prevent the page from scrolling 23400 killEvent(e); 23401 return; 23402 } 23403 23404 switch (e.which) { 23405 case KEY.UP: 23406 case KEY.DOWN: 23407 this.moveHighlight((e.which === KEY.UP) ? -1 : 1); 23408 killEvent(e); 23409 return; 23410 case KEY.ENTER: 23411 this.selectHighlighted(); 23412 killEvent(e); 23413 return; 23414 case KEY.TAB: 23415 this.selectHighlighted({noFocus: true}); 23416 return; 23417 case KEY.ESC: 23418 this.cancel(e); 23419 killEvent(e); 23420 return; 23421 } 23422 })); 23423 23424 this.search.on("blur", this.bind(function(e) { 23425 // a workaround for chrome to keep the search field focussed when the scroll bar is used to scroll the dropdown. 23426 // without this the search field loses focus which is annoying 23427 if (document.activeElement === this.body.get(0)) { 23428 window.setTimeout(this.bind(function() { 23429 if (this.opened()) { 23430 this.search.focus(); 23431 } 23432 }), 0); 23433 } 23434 })); 23435 23436 this.focusser.on("keydown", this.bind(function (e) { 23437 if (!this.isInterfaceEnabled()) return; 23438 23439 if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC) { 23440 return; 23441 } 23442 23443 if (this.opts.openOnEnter === false && e.which === KEY.ENTER) { 23444 killEvent(e); 23445 return; 23446 } 23447 23448 if (e.which == KEY.DOWN || e.which == KEY.UP 23449 || (e.which == KEY.ENTER && this.opts.openOnEnter)) { 23450 23451 if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) return; 23452 23453 this.open(); 23454 killEvent(e); 23455 return; 23456 } 23457 23458 if (e.which == KEY.DELETE || e.which == KEY.BACKSPACE) { 23459 if (this.opts.allowClear) { 23460 this.clear(); 23461 } 23462 killEvent(e); 23463 return; 23464 } 23465 })); 23466 23467 23468 installKeyUpChangeEvent(this.focusser); 23469 this.focusser.on("keyup-change input", this.bind(function(e) { 23470 if (this.opts.minimumResultsForSearch >= 0) { 23471 e.stopPropagation(); 23472 if (this.opened()) return; 23473 this.open(); 23474 } 23475 })); 23476 23477 selection.on("mousedown touchstart", "abbr", this.bind(function (e) { 23478 if (!this.isInterfaceEnabled()) return; 23479 this.clear(); 23480 killEventImmediately(e); 23481 this.close(); 23482 this.selection.focus(); 23483 })); 23484 23485 selection.on("mousedown touchstart", this.bind(function (e) { 23486 // Prevent IE from generating a click event on the body 23487 reinsertElement(selection); 23488 23489 if (!this.container.hasClass("select2-container-active")) { 23490 this.opts.element.trigger($.Event("select2-focus")); 23491 } 23492 23493 if (this.opened()) { 23494 this.close(); 23495 } else if (this.isInterfaceEnabled()) { 23496 this.open(); 23497 } 23498 23499 killEvent(e); 23500 })); 23501 23502 dropdown.on("mousedown touchstart", this.bind(function() { 23503 if (this.opts.shouldFocusInput(this)) { 23504 this.search.focus(); 23505 } 23506 })); 23507 23508 selection.on("focus", this.bind(function(e) { 23509 killEvent(e); 23510 })); 23511 23512 this.focusser.on("focus", this.bind(function(){ 23513 if (!this.container.hasClass("select2-container-active")) { 23514 this.opts.element.trigger($.Event("select2-focus")); 23515 } 23516 this.container.addClass("select2-container-active"); 23517 })).on("blur", this.bind(function() { 23518 if (!this.opened()) { 23519 this.container.removeClass("select2-container-active"); 23520 this.opts.element.trigger($.Event("select2-blur")); 23521 } 23522 })); 23523 this.search.on("focus", this.bind(function(){ 23524 if (!this.container.hasClass("select2-container-active")) { 23525 this.opts.element.trigger($.Event("select2-focus")); 23526 } 23527 this.container.addClass("select2-container-active"); 23528 })); 23529 23530 this.initContainerWidth(); 23531 this.opts.element.addClass("select2-offscreen"); 23532 this.setPlaceholder(); 23533 23534 }, 23535 23536 // single 23537 clear: function(triggerChange) { 23538 var data=this.selection.data("select2-data"); 23539 if (data) { // guard against queued quick consecutive clicks 23540 var evt = $.Event("select2-clearing"); 23541 this.opts.element.trigger(evt); 23542 if (evt.isDefaultPrevented()) { 23543 return; 23544 } 23545 var placeholderOption = this.getPlaceholderOption(); 23546 this.opts.element.val(placeholderOption ? placeholderOption.val() : ""); 23547 this.selection.find(".select2-chosen").empty(); 23548 this.selection.removeData("select2-data"); 23549 this.setPlaceholder(); 23550 23551 if (triggerChange !== false){ 23552 this.opts.element.trigger({ type: "select2-removed", val: this.id(data), choice: data }); 23553 this.triggerChange({removed:data}); 23554 } 23555 } 23556 }, 23557 23558 /** 23559 * Sets selection based on source element's value 23560 */ 23561 // single 23562 initSelection: function () { 23563 var selected; 23564 if (this.isPlaceholderOptionSelected()) { 23565 this.updateSelection(null); 23566 this.close(); 23567 this.setPlaceholder(); 23568 } else { 23569 var self = this; 23570 this.opts.initSelection.call(null, this.opts.element, function(selected){ 23571 if (selected !== undefined && selected !== null) { 23572 self.updateSelection(selected); 23573 self.close(); 23574 self.setPlaceholder(); 23575 self.nextSearchTerm = self.opts.nextSearchTerm(selected, self.search.val()); 23576 } 23577 }); 23578 } 23579 }, 23580 23581 isPlaceholderOptionSelected: function() { 23582 var placeholderOption; 23583 if (this.getPlaceholder() === undefined) return false; // no placeholder specified so no option should be considered 23584 return ((placeholderOption = this.getPlaceholderOption()) !== undefined && placeholderOption.prop("selected")) 23585 || (this.opts.element.val() === "") 23586 || (this.opts.element.val() === undefined) 23587 || (this.opts.element.val() === null); 23588 }, 23589 23590 // single 23591 prepareOpts: function () { 23592 var opts = this.parent.prepareOpts.apply(this, arguments), 23593 self=this; 23594 23595 if (opts.element.get(0).tagName.toLowerCase() === "select") { 23596 // install the selection initializer 23597 opts.initSelection = function (element, callback) { 23598 var selected = element.find("option").filter(function() { return this.selected && !this.disabled }); 23599 // a single select box always has a value, no need to null check 'selected' 23600 callback(self.optionToData(selected)); 23601 }; 23602 } else if ("data" in opts) { 23603 // install default initSelection when applied to hidden input and data is local 23604 opts.initSelection = opts.initSelection || function (element, callback) { 23605 var id = element.val(); 23606 //search in data by id, storing the actual matching item 23607 var match = null; 23608 opts.query({ 23609 matcher: function(term, text, el){ 23610 var is_match = equal(id, opts.id(el)); 23611 if (is_match) { 23612 match = el; 23613 } 23614 return is_match; 23615 },
23616 callback: !$.isFunction(callback) ? $.noop : function() { 23617 callback(match); 23618 } 23619 }); 23620 }; 23621 } 23622 23623 return opts; 23624 }, 23625 23626 // single 23627 getPlaceholder: function() { 23628 // if a placeholder is specified on a single select without a valid placeholder option ignore it 23629 if (this.select) { 23630 if (this.getPlaceholderOption() === undefined) { 23631 return undefined; 23632 } 23633 } 23634 23635 return this.parent.getPlaceholder.apply(this, arguments); 23636 }, 23637 23638 // single 23639 setPlaceholder: function () { 23640 var placeholder = this.getPlaceholder(); 23641 23642 if (this.isPlaceholderOptionSelected() && placeholder !== undefined) { 23643 23644 // check for a placeholder option if attached to a select 23645 if (this.select && this.getPlaceholderOption() === undefined) return; 23646 23647 this.selection.find(".select2-chosen").html(this.opts.escapeMarkup(placeholder)); 23648 23649 this.selection.addClass("select2-default"); 23650 23651 this.container.removeClass("select2-allowclear"); 23652 } 23653 }, 23654 23655 // single 23656 postprocessResults: function (data, initial, noHighlightUpdate) { 23657 var selected = 0, self = this, showSearchInput = true; 23658 23659 // find the selected element in the result list 23660 23661 this.findHighlightableChoices().each2(function (i, elm) { 23662 if (equal(self.id(elm.data("select2-data")), self.opts.element.val())) { 23663 selected = i; 23664 return false; 23665 } 23666 }); 23667 23668 // and highlight it 23669 if (noHighlightUpdate !== false) { 23670 if (initial === true && selected >= 0) { 23671 this.highlight(selected); 23672 } else { 23673 this.highlight(0); 23674 } 23675 } 23676 23677 // hide the search box if this is the first we got the results and there are enough of them for search 23678 23679 if (initial === true) { 23680 var min = this.opts.minimumResultsForSearch; 23681 if (min >= 0) { 23682 this.showSearch(countResults(data.results) >= min); 23683 } 23684 } 23685 }, 23686 23687 // single 23688 showSearch: function(showSearchInput) { 23689 if (this.showSearchInput === showSearchInput) return; 23690 23691 this.showSearchInput = showSearchInput; 23692 23693 this.dropdown.find(".select2-search").toggleClass("select2-search-hidden", !showSearchInput); 23694 this.dropdown.find(".select2-search").toggleClass("select2-offscreen", !showSearchInput); 23695 //add "select2-with-searchbox" to the container if search box is shown 23696 $(this.dropdown, this.container).toggleClass("select2-with-searchbox", showSearchInput); 23697 }, 23698 23699 // single 23700 onSelect: function (data, options) { 23701 23702 if (!this.triggerSelect(data)) { return; } 23703 23704 var old = this.opts.element.val(), 23705 oldData = this.data(); 23706 23707 this.opts.element.val(this.id(data)); 23708 this.updateSelection(data); 23709 23710 this.opts.element.trigger({ type: "select2-selected", val: this.id(data), choice: data }); 23711 23712 this.nextSearchTerm = this.opts.nextSearchTerm(data, this.search.val()); 23713 this.close(); 23714 23715 if ((!options || !options.noFocus) && this.opts.shouldFocusInput(this)) { 23716 this.focusser.focus(); 23717 } 23718 23719 if (!equal(old, this.id(data))) { 23720 this.triggerChange({ added: data, removed: oldData }); 23721 } 23722 }, 23723 23724 // single 23725 updateSelection: function (data) { 23726 23727 var container=this.selection.find(".select2-chosen"), formatted, cssClass; 23728 23729 this.selection.data("select2-data", data); 23730 23731 container.empty(); 23732 if (data !== null) { 23733 formatted=this.opts.formatSelection(data, container, this.opts.escapeMarkup); 23734 } 23735 if (formatted !== undefined) { 23736 container.append(formatted); 23737 } 23738 cssClass=this.opts.formatSelectionCssClass(data, container); 23739 if (cssClass !== undefined) { 23740 container.addClass(cssClass); 23741 } 23742 23743 this.selection.removeClass("select2-default"); 23744 23745 if (this.opts.allowClear && this.getPlaceholder() !== undefined) { 23746 this.container.addClass("select2-allowclear"); 23747 } 23748 }, 23749 23750 // single 23751 val: function () { 23752 var val, 23753 triggerChange = false, 23754 data = null, 23755 self = this, 23756 oldData = this.data(); 23757 23758 if (arguments.length === 0) { 23759 return this.opts.element.val(); 23760 } 23761 23762 val = arguments[0]; 23763 23764 if (arguments.length > 1) { 23765 triggerChange = arguments[1]; 23766 } 23767 23768 if (this.select) { 23769 this.select 23770 .val(val) 23771 .find("option").filter(function() { return this.selected }).each2(function (i, elm) { 23772 data = self.optionToData(elm); 23773 return false;
23774 }); 23775 this.updateSelection(data); 23776 this.setPlaceholder(); 23777 if (triggerChange) { 23778 this.triggerChange({added: data, removed:oldData}); 23779 } 23780 } else { 23781 // val is an id. !val is true for [undefined,null,'',0] - 0 is legal 23782 if (!val && val !== 0) { 23783 this.clear(triggerChange); 23784 return; 23785 } 23786 if (this.opts.initSelection === undefined) { 23787 throw new Error("cannot call val() if initSelection() is not defined"); 23788 } 23789 this.opts.element.val(val); 23790 this.opts.initSelection(this.opts.element, function(data){ 23791 self.opts.element.val(!data ? "" : self.id(data)); 23792 self.updateSelection(data); 23793 self.setPlaceholder(); 23794 if (triggerChange) { 23795 self.triggerChange({added: data, removed:oldData}); 23796 } 23797 }); 23798 } 23799 }, 23800 23801 // single 23802 clearSearch: function () { 23803 this.search.val(""); 23804 this.focusser.val(""); 23805 }, 23806 23807 // single 23808 data: function(value) { 23809 var data, 23810 triggerChange = false; 23811 23812 if (arguments.length === 0) { 23813 data = this.selection.data("select2-data"); 23814 if (data == undefined) data = null; 23815 return data; 23816 } else { 23817 if (arguments.length > 1) { 23818 triggerChange = arguments[1]; 23819 } 23820 if (!value) { 23821 this.clear(triggerChange); 23822 } else { 23823 data = this.data(); 23824 this.opts.element.val(!value ? "" : this.id(value)); 23825 this.updateSelection(value); 23826 if (triggerChange) { 23827 this.triggerChange({added: value, removed:data}); 23828 } 23829 } 23830 } 23831 } 23832 }); 23833 23834 MultiSelect2 = clazz(AbstractSelect2, { 23835 23836 // multi 23837 createContainer: function () { 23838 var container = $(document.createElement("div")).attr({ 23839 "class": "select2-container select2-container-multi" 23840 }).html([ 23841 "<ul class='select2-choices'>", 23842 " <li class='select2-search-field'>", 23843 " <label for='' class='select2-offscreen'></label>", 23844 " <input type='text' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' class='select2-input'>", 23845 " </li>", 23846 "</ul>", 23847 "<div class='select2-drop select2-drop-multi select2-display-none'>", 23848 " <ul class='select2-results'>", 23849 " </ul>", 23850 "</div>"].join("")); 23851 return container; 23852 }, 23853 23854 // multi 23855 prepareOpts: function () { 23856 var opts = this.parent.prepareOpts.apply(this, arguments), 23857 self=this; 23858 23859 // TODO validate placeholder is a string if specified 23860 23861 if (opts.element.get(0).tagName.toLowerCase() === "select") { 23862 // install the selection initializer 23863 opts.initSelection = function (element, callback) { 23864 23865 var data = []; 23866 23867 element.find("option").filter(function() { return this.selected && !this.disabled }).each2(function (i, elm) { 23868 data.push(self.optionToData(elm)); 23869 }); 23870 callback(data); 23871 }; 23872 } else if ("data" in opts) { 23873 // install default initSelection when applied to hidden input and data is local 23874 opts.initSelection = opts.initSelection || function (element, callback) { 23875 var ids = splitVal(element.val(), opts.separator); 23876 //search in data by array of ids, storing matching items in a list 23877 var matches = []; 23878 opts.query({ 23879 matcher: function(term, text, el){ 23880 var is_match = $.grep(ids, function(id) { 23881 return equal(id, opts.id(el)); 23882 }).length; 23883 if (is_match) { 23884 matches.push(el); 23885 } 23886 return is_match; 23887 },
23888 callback: !$.isFunction(callback) ? $.noop : function() { 23889 // reorder matches based on the order they appear in the ids array because right now 23890 // they are in the order in which they appear in data array 23891 var ordered = []; 23892 for (var i = 0; i < ids.length; i++) { 23893 var id = ids[i]; 23894 for (var j = 0; j < matches.length; j++) { 23895 var match = matches[j]; 23896 if (equal(id, opts.id(match))) { 23897 ordered.push(match); 23898 matches.splice(j, 1); 23899 break; 23900 } 23901 } 23902 } 23903 callback(ordered); 23904 } 23905 }); 23906 }; 23907 } 23908 23909 return opts; 23910 }, 23911 23912 // multi 23913 selectChoice: function (choice) { 23914 23915 var selected = this.container.find(".select2-search-choice-focus"); 23916 if (selected.length && choice && choice[0] == selected[0]) { 23917 23918 } else { 23919 if (selected.length) { 23920 this.opts.element.trigger("choice-deselected", selected); 23921 } 23922 selected.removeClass("select2-search-choice-focus"); 23923 if (choice && choice.length) { 23924 this.close(); 23925 choice.addClass("select2-search-choice-focus"); 23926 this.opts.element.trigger("choice-selected", choice); 23927 } 23928 } 23929 }, 23930 23931 // multi 23932 destroy: function() { 23933 $("label[for='" + this.search.attr('id') + "']") 23934 .attr('for', this.opts.element.attr("id")); 23935 this.parent.destroy.apply(this, arguments); 23936 23937 cleanupJQueryElements.call(this, 23938 "searchContainer", 23939 "selection" 23940 ); 23941 }, 23942 23943 // multi 23944 initContainer: function () { 23945 23946 var selector = ".select2-choices", selection; 23947 23948 this.searchContainer = this.container.find(".select2-search-field"); 23949 this.selection = selection = this.container.find(selector); 23950 23951 var _this = this; 23952 this.selection.on("click", ".select2-search-choice:not(.select2-locked)", function (e) { 23953 //killEvent(e); 23954 _this.search[0].focus(); 23955 _this.selectChoice($(this)); 23956 }); 23957 23958 // rewrite labels from original element to focusser 23959 this.search.attr("id", "s2id_autogen"+nextUid()); 23960 23961 this.search.prev() 23962 .text($("label[for='" + this.opts.element.attr("id") + "']").text()) 23963 .attr('for', this.search.attr('id')); 23964 23965 this.search.on("input paste", this.bind(function() { 23966 if (!this.isInterfaceEnabled()) return; 23967 if (!this.opened()) { 23968 this.open(); 23969 } 23970 })); 23971 23972 this.search.attr("tabindex", this.elementTabIndex); 23973 23974 this.keydowns = 0; 23975 this.search.on("keydown", this.bind(function (e) { 23976 if (!this.isInterfaceEnabled()) return; 23977 23978 ++this.keydowns; 23979 var selected = selection.find(".select2-search-choice-focus"); 23980 var prev = selected.prev(".select2-search-choice:not(.select2-locked)"); 23981 var next = selected.next(".select2-search-choice:not(.select2-locked)"); 23982 var pos = getCursorInfo(this.search); 23983 23984 if (selected.length && 23985 (e.which == KEY.LEFT || e.which == KEY.RIGHT || e.which == KEY.BACKSPACE || e.which == KEY.DELETE || e.which == KEY.ENTER)) { 23986 var selectedChoice = selected; 23987 if (e.which == KEY.LEFT && prev.length) { 23988 selectedChoice = prev; 23989 } 23990 else if (e.which == KEY.RIGHT) { 23991 selectedChoice = next.length ? next : null; 23992 } 23993 else if (e.which === KEY.BACKSPACE) { 23994 if (this.unselect(selected.first())) { 23995 this.search.width(10); 23996 selectedChoice = prev.length ? prev : next; 23997 } 23998 } else if (e.which == KEY.DELETE) { 23999 if (this.unselect(selected.first())) { 24000 this.search.width(10); 24001 selectedChoice = next.length ? next : null; 24002 } 24003 } else if (e.which == KEY.ENTER) { 24004 selectedChoice = null; 24005 } 24006 24007 this.selectChoice(selectedChoice); 24008 killEvent(e); 24009 if (!selectedChoice || !selectedChoice.length) { 24010 this.open(); 24011 } 24012 return; 24013 } else if (((e.which === KEY.BACKSPACE && this.keydowns == 1) 24014 || e.which == KEY.LEFT) && (pos.offset == 0 && !pos.length)) { 24015 24016 this.selectChoice(selection.find(".select2-search-choice:not(.select2-locked)").last()); 24017 killEvent(e); 24018 return; 24019 } else { 24020 this.selectChoice(null); 24021 } 24022 24023 if (this.opened()) { 24024 switch (e.which) { 24025 case KEY.UP: 24026 case KEY.DOWN: 24027 this.moveHighlight((e.which === KEY.UP) ? -1 : 1); 24028 killEvent(e); 24029 return; 24030 case KEY.ENTER: 24031 this.selectHighlighted(); 24032 killEvent(e); 24033 return; 24034 case KEY.TAB: 24035 this.selectHighlighted({noFocus:true}); 24036 this.close(); 24037 return; 24038 case KEY.ESC: 24039 this.cancel(e); 24040 killEvent(e); 24041 return; 24042 } 24043 } 24044 24045 if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) 24046 || e.which === KEY.BACKSPACE || e.which === KEY.ESC) { 24047 return; 24048 } 24049 24050 if (e.which === KEY.ENTER) { 24051 if (this.opts.openOnEnter === false) { 24052 return; 24053 } else if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) { 24054 return; 24055 } 24056 } 24057 24058 this.open(); 24059 24060 if (e.which === KEY.PAGE_UP || e.which === KEY.PAGE_DOWN) { 24061 // prevent the page from scrolling 24062 killEvent(e); 24063 } 24064 24065 if (e.which === KEY.ENTER) { 24066 // prevent form from being submitted 24067 killEvent(e); 24068 } 24069 24070 })); 24071 24072 this.search.on("keyup", this.bind(function (e) { 24073 this.keydowns = 0; 24074 this.resizeSearch(); 24075 }) 24076 ); 24077 24078 this.search.on("blur", this.bind(function(e) { 24079 this.container.removeClass("select2-container-active"); 24080 this.search.removeClass("select2-focused"); 24081 this.selectChoice(null); 24082 if (!this.opened()) this.clearSearch(); 24083 e.stopImmediatePropagation(); 24084 this.opts.element.trigger($.Event("select2-blur")); 24085 })); 24086 24087 this.container.on("click", selector, this.bind(function (e) { 24088 if (!this.isInterfaceEnabled()) return; 24089 if ($(e.target).closest(".select2-search-choice").length > 0) { 24090 // clicked inside a select2 search choice, do not open 24091 return; 24092 } 24093 this.selectChoice(null); 24094 this.clearPlaceholder(); 24095 if (!this.container.hasClass("select2-container-active")) { 24096 this.opts.element.trigger($.Event("select2-focus")); 24097 } 24098 this.open(); 24099 this.focusSearch(); 24100 e.preventDefault(); 24101 })); 24102 24103 this.container.on("focus", selector, this.bind(function () { 24104 if (!this.isInterfaceEnabled()) return; 24105 if (!this.container.hasClass("select2-container-active")) { 24106 this.opts.element.trigger($.Event("select2-focus")); 24107 } 24108 this.container.addClass("select2-container-active"); 24109 this.dropdown.addClass("select2-drop-active"); 24110 this.clearPlaceholder(); 24111 })); 24112 24113 this.initContainerWidth(); 24114 this.opts.element.addClass("select2-offscreen"); 24115 24116 // set the placeholder if necessary 24117 this.clearSearch(); 24118 }, 24119 24120 // multi 24121 enableInterface: function() { 24122 if (this.parent.enableInterface.apply(this, arguments)) { 24123 this.search.prop("disabled", !this.isInterfaceEnabled()); 24124 } 24125 }, 24126 24127 // multi 24128 initSelection: function () { 24129 var data; 24130 if (this.opts.element.val() === "" && this.opts.element.text() === "") { 24131 this.updateSelection([]); 24132 this.close(); 24133 // set the placeholder if necessary 24134 this.clearSearch(); 24135 } 24136 if (this.select || this.opts.element.val() !== "") { 24137 var self = this; 24138 this.opts.initSelection.call(null, this.opts.element, function(data){ 24139 if (data !== undefined && data !== null) { 24140 self.updateSelection(data); 24141 self.close(); 24142 // set the placeholder if necessary 24143 self.clearSearch(); 24144 } 24145 }); 24146 } 24147 }, 24148 24149 // multi 24150 clearSearch: function () { 24151 var placeholder = this.getPlaceholder(), 24152 maxWidth = this.getMaxSearchWidth(); 24153 24154 if (placeholder !== undefined && this.getVal().length === 0 && this.search.hasClass("select2-focused") === false) { 24155 this.search.val(placeholder).addClass("select2-default"); 24156 // stretch the search box to full width of the container so as much of the placeholder is visible as possible 24157 // we could call this.resizeSearch(), but we do not because that requires a sizer and we do not want to create one so early because of a firefox bug, see #944 24158 this.search.width(maxWidth > 0 ? maxWidth : this.container.css("width")); 24159 } else { 24160 this.search.val("").width(10); 24161 } 24162 }, 24163 24164 // multi 24165 clearPlaceholder: function () { 24166 if (this.search.hasClass("select2-default")) { 24167 this.search.val("").removeClass("select2-default"); 24168 } 24169 }, 24170 24171 // multi 24172 opening: function () { 24173 this.clearPlaceholder(); // should be done before super so placeholder is not used to search 24174 this.resizeSearch(); 24175 24176 this.parent.opening.apply(this, arguments); 24177 24178 this.focusSearch(); 24179 24180 // initializes search's value with nextSearchTerm (if defined by user) 24181 // ignore nextSearchTerm if the dropdown is opened by the user pressing a letter 24182 if(this.search.val() === "") { 24183 if(this.nextSearchTerm != undefined){ 24184 this.search.val(this.nextSearchTerm); 24185 this.search.select(); 24186 } 24187 } 24188 24189 this.updateResults(true); 24190 if (this.opts.shouldFocusInput(this)) { 24191 this.search.focus(); 24192 } 24193 this.opts.element.trigger($.Event("select2-open")); 24194 }, 24195 24196 // multi 24197 close: function () { 24198 if (!this.opened()) return; 24199 this.parent.close.apply(this, arguments); 24200 }, 24201 24202 // multi 24203 focus: function () { 24204 this.close(); 24205 this.search.focus(); 24206 }, 24207 24208 // multi 24209 isFocused: function () { 24210 return this.search.hasClass("select2-focused"); 24211 }, 24212 24213 // multi 24214 updateSelection: function (data) { 24215 var ids = [], filtered = [], self = this; 24216 24217 // filter out duplicates 24218 $(data).each(function () { 24219 if (indexOf(self.id(this), ids) < 0) { 24220 ids.push(self.id(this)); 24221 filtered.push(this); 24222 } 24223 }); 24224 data = filtered; 24225 24226 this.selection.find(".select2-search-choice").remove(); 24227 $(data).each(function () { 24228 self.addSelectedChoice(this); 24229 }); 24230 self.postprocessResults(); 24231 }, 24232 24233 // multi 24234 tokenize: function() { 24235 var input = this.search.val(); 24236 input = this.opts.tokenizer.call(this, input, this.data(), this.bind(this.onSelect), this.opts); 24237 if (input != null && input != undefined) { 24238 this.search.val(input); 24239 if (input.length > 0) { 24240 this.open(); 24241 } 24242 } 24243 24244 }, 24245 24246 // multi 24247 onSelect: function (data, options) { 24248 24249 if (!this.triggerSelect(data)) { return; } 24250 24251 this.addSelectedChoice(data); 24252 24253 this.opts.element.trigger({ type: "selected", val: this.id(data), choice: data }); 24254 24255 // keep track of the search's value before it gets cleared
24256 this.nextSearchTerm = this.opts.nextSearchTerm(data, this.search.val()); 24257 24258 this.clearSearch(); 24259 this.updateResults(); 24260 24261 if (this.select || !this.opts.closeOnSelect) this.postprocessResults(data, false, this.opts.closeOnSelect===true); 24262 24263 if (this.opts.closeOnSelect) { 24264 this.close(); 24265 this.search.width(10); 24266 } else { 24267 if (this.countSelectableResults()>0) { 24268 this.search.width(10); 24269 this.resizeSearch(); 24270 if (this.getMaximumSelectionSize() > 0 && this.val().length >= this.getMaximumSelectionSize()) { 24271 // if we reached max selection size repaint the results so choices 24272 // are replaced with the max selection reached message 24273 this.updateResults(true); 24274 } else { 24275 // initializes search's value with nextSearchTerm and update search result 24276 if(this.nextSearchTerm != undefined){ 24277 this.search.val(this.nextSearchTerm); 24278 this.updateResults(); 24279 this.search.select(); 24280 } 24281 } 24282 this.positionDropdown(); 24283 } else { 24284 // if nothing left to select close 24285 this.close(); 24286 this.search.width(10); 24287 } 24288 } 24289 24290 // since its not possible to select an element that has already been 24291 // added we do not need to check if this is a new element before firing change 24292 this.triggerChange({ added: data }); 24293 24294 if (!options || !options.noFocus) 24295 this.focusSearch(); 24296 }, 24297 24298 // multi 24299 cancel: function () { 24300 this.close(); 24301 this.focusSearch(); 24302 }, 24303 24304 addSelectedChoice: function (data) { 24305 var enableChoice = !data.locked, 24306 enabledItem = $( 24307 "<li class='select2-search-choice'>" + 24308 " <div></div>" + 24309 " <a href='#' class='select2-search-choice-close' tabindex='-1'></a>" + 24310 "</li>"), 24311 disabledItem = $( 24312 "<li class='select2-search-choice select2-locked'>" + 24313 "<div></div>" + 24314 "</li>"); 24315 var choice = enableChoice ? enabledItem : disabledItem, 24316 id = this.id(data), 24317 val = this.getVal(), 24318 formatted, 24319 cssClass; 24320 24321 formatted=this.opts.formatSelection(data, choice.find("div"), this.opts.escapeMarkup); 24322 if (formatted != undefined) { 24323 choice.find("div").replaceWith("<div>"+formatted+"</div>"); 24324 } 24325 cssClass=this.opts.formatSelectionCssClass(data, choice.find("div")); 24326 if (cssClass != undefined) { 24327 choice.addClass(cssClass); 24328 } 24329 24330 if(enableChoice){ 24331 choice.find(".select2-search-choice-close") 24332 .on("mousedown", killEvent) 24333 .on("click dblclick", this.bind(function (e) { 24334 if (!this.isInterfaceEnabled()) return; 24335 24336 this.unselect($(e.target)); 24337 this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus"); 24338 killEvent(e); 24339 this.close(); 24340 this.focusSearch(); 24341 })).on("focus", this.bind(function () { 24342 if (!this.isInterfaceEnabled()) return; 24343 this.container.addClass("select2-container-active"); 24344 this.dropdown.addClass("select2-drop-active"); 24345 })); 24346 } 24347 24348 choice.data("select2-data", data); 24349 choice.insertBefore(this.searchContainer); 24350 24351 val.push(id); 24352 this.setVal(val); 24353 }, 24354 24355 // multi 24356 unselect: function (selected) { 24357 var val = this.getVal(), 24358 data, 24359 index; 24360 selected = selected.closest(".select2-search-choice"); 24361 24362 if (selected.length === 0) { 24363 throw "Invalid argument: " + selected + ". Must be .select2-search-choice"; 24364 } 24365 24366 data = selected.data("select2-data"); 24367 24368 if (!data) { 24369 // prevent a race condition when the 'x' is clicked really fast repeatedly the event can be queued 24370 // and invoked on an element already removed 24371 return; 24372 } 24373 24374 var evt = $.Event("select2-removing"); 24375 evt.val = this.id(data); 24376 evt.choice = data; 24377 this.opts.element.trigger(evt); 24378 24379 if (evt.isDefaultPrevented()) { 24380 return false;
24381 } 24382 24383 while((index = indexOf(this.id(data), val)) >= 0) { 24384 val.splice(index, 1); 24385 this.setVal(val); 24386 if (this.select) this.postprocessResults(); 24387 } 24388 24389 selected.remove(); 24390 24391 this.opts.element.trigger({ type: "select2-removed", val: this.id(data), choice: data }); 24392 this.triggerChange({ removed: data }); 24393 24394 return true; 24395 }, 24396 24397 // multi 24398 postprocessResults: function (data, initial, noHighlightUpdate) { 24399 var val = this.getVal(), 24400 choices = this.results.find(".select2-result"), 24401 compound = this.results.find(".select2-result-with-children"), 24402 self = this; 24403 24404 choices.each2(function (i, choice) { 24405 var id = self.id(choice.data("select2-data")); 24406 if (indexOf(id, val) >= 0) { 24407 choice.addClass("select2-selected"); 24408 // mark all children of the selected parent as selected 24409 choice.find(".select2-result-selectable").addClass("select2-selected"); 24410 } 24411 }); 24412 24413 compound.each2(function(i, choice) { 24414 // hide an optgroup if it doesn't have any selectable children 24415 if (!choice.is('.select2-result-selectable') 24416 && choice.find(".select2-result-selectable:not(.select2-selected)").length === 0) { 24417 choice.addClass("select2-selected"); 24418 } 24419 }); 24420 24421 if (this.highlight() == -1 && noHighlightUpdate !== false){ 24422 self.highlight(0); 24423 } 24424 24425 //If all results are chosen render formatNoMatches 24426 if(!this.opts.createSearchChoice && !choices.filter('.select2-result:not(.select2-selected)').length > 0){ 24427 if(!data || data && !data.more && this.results.find(".select2-no-results").length === 0) { 24428 if (checkFormatter(self.opts.formatNoMatches, "formatNoMatches")) { 24429 this.results.append("<li class='select2-no-results'>" + evaluate(self.opts.formatNoMatches, self.search.val()) + "</li>"); 24430 } 24431 } 24432 } 24433 24434 }, 24435 24436 // multi 24437 getMaxSearchWidth: function() { 24438 return this.selection.width() - getSideBorderPadding(this.search); 24439 }, 24440 24441 // multi 24442 resizeSearch: function () { 24443 var minimumWidth, left, maxWidth, containerLeft, searchWidth, 24444 sideBorderPadding = getSideBorderPadding(this.search); 24445 24446 minimumWidth = measureTextWidth(this.search) + 10; 24447 24448 left = this.search.offset().left; 24449 24450 maxWidth = this.selection.width(); 24451 containerLeft = this.selection.offset().left; 24452 24453 searchWidth = maxWidth - (left - containerLeft) - sideBorderPadding; 24454 24455 if (searchWidth < minimumWidth) { 24456 searchWidth = maxWidth - sideBorderPadding; 24457 } 24458 24459 if (searchWidth < 40) { 24460 searchWidth = maxWidth - sideBorderPadding; 24461 } 24462 24463 if (searchWidth <= 0) { 24464 searchWidth = minimumWidth; 24465 } 24466 24467 this.search.width(Math.floor(searchWidth)); 24468 }, 24469 24470 // multi 24471 getVal: function () { 24472 var val; 24473 if (this.select) { 24474 val = this.select.val(); 24475 return val === null ? [] : val; 24476 } else { 24477 val = this.opts.element.val(); 24478 return splitVal(val, this.opts.separator); 24479 } 24480 }, 24481 24482 // multi 24483 setVal: function (val) { 24484 var unique; 24485 if (this.select) { 24486 this.select.val(val); 24487 } else { 24488 unique = []; 24489 // filter out duplicates 24490 $(val).each(function () { 24491 if (indexOf(this, unique) < 0) unique.push(this); 24492 }); 24493 this.opts.element.val(unique.length === 0 ? "" : unique.join(this.opts.separator)); 24494 } 24495 }, 24496 24497 // multi 24498 buildChangeDetails: function (old, current) { 24499 var current = current.slice(0), 24500 old = old.slice(0); 24501 24502 // remove intersection from each array 24503 for (var i = 0; i < current.length; i++) { 24504 for (var j = 0; j < old.length; j++) { 24505 if (equal(this.opts.id(current[i]), this.opts.id(old[j]))) { 24506 current.splice(i, 1); 24507 if(i>0){ 24508 i--; 24509 } 24510 old.splice(j, 1); 24511 j--; 24512 } 24513 } 24514 } 24515 24516 return {added: current, removed: old}; 24517 }, 24518 24519 24520 // multi 24521 val: function (val, triggerChange) { 24522 var oldData, self=this; 24523 24524 if (arguments.length === 0) { 24525 return this.getVal(); 24526 } 24527 24528 oldData=this.data(); 24529 if (!oldData.length) oldData=[]; 24530 24531 // val is an id. !val is true for [undefined,null,'',0] - 0 is legal 24532 if (!val && val !== 0) { 24533 this.opts.element.val(""); 24534 this.updateSelection([]); 24535 this.clearSearch(); 24536 if (triggerChange) { 24537 this.triggerChange({added: this.data(), removed: oldData}); 24538 } 24539 return; 24540 } 24541 24542 // val is a list of ids 24543 this.setVal(val); 24544 24545 if (this.select) { 24546 this.opts.initSelection(this.select, this.bind(this.updateSelection)); 24547 if (triggerChange) { 24548 this.triggerChange(this.buildChangeDetails(oldData, this.data())); 24549 } 24550 } else { 24551 if (this.opts.initSelection === undefined) { 24552 throw new Error("val() cannot be called if initSelection() is not defined"); 24553 } 24554 24555 this.opts.initSelection(this.opts.element, function(data){ 24556 var ids=$.map(data, self.id); 24557 self.setVal(ids); 24558 self.updateSelection(data); 24559 self.clearSearch(); 24560 if (triggerChange) { 24561 self.triggerChange(self.buildChangeDetails(oldData, self.data())); 24562 } 24563 }); 24564 } 24565 this.clearSearch(); 24566 }, 24567 24568 // multi 24569 onSortStart: function() { 24570 if (this.select) { 24571 throw new Error("Sorting of elements is not supported when attached to <select>. Attach to <input type='hidden'/> instead."); 24572 } 24573
24574 // collapse search field into 0 width so its container can be collapsed as well 24575 this.search.width(0); 24576 // hide the container 24577 this.searchContainer.hide(); 24578 }, 24579 24580 // multi 24581 onSortEnd:function() { 24582 24583 var val=[], self=this; 24584 24585 // show search and move it to the end of the list 24586 this.searchContainer.show(); 24587 // make sure the search container is the last item in the list 24588 this.searchContainer.appendTo(this.searchContainer.parent()); 24589 // since we collapsed the width in dragStarted, we resize it here 24590 this.resizeSearch(); 24591 24592 // update selection 24593 this.selection.find(".select2-search-choice").each(function() { 24594 val.push(self.opts.id($(this).data("select2-data"))); 24595 }); 24596 this.setVal(val); 24597 this.triggerChange(); 24598 }, 24599 24600 // multi 24601 data: function(values, triggerChange) { 24602 var self=this, ids, old; 24603 if (arguments.length === 0) { 24604 return this.selection 24605 .children(".select2-search-choice") 24606 .map(function() { return $(this).data("select2-data"); }) 24607 .get(); 24608 } else { 24609 old = this.data(); 24610 if (!values) { values = []; } 24611 ids = $.map(values, function(e) { return self.opts.id(e); }); 24612 this.setVal(ids); 24613 this.updateSelection(values); 24614 this.clearSearch(); 24615 if (triggerChange) { 24616 this.triggerChange(this.buildChangeDetails(old, this.data())); 24617 } 24618 } 24619 } 24620 }); 24621 24622 $.fn.select2 = function () { 24623 24624 var args = Array.prototype.slice.call(arguments, 0), 24625 opts, 24626 select2, 24627 method, value, multiple, 24628 allowedMethods = ["val", "destroy", "opened", "open", "close", "focu
24628s", "isFocused", "container", "dropdown", "onSortStart", "onSortEnd", "enable", "disable", "readonly", "positionDropdown", "data", "search"], 24629 valueMethods = ["opened", "isFocused", "container", "dropdown"], 24630 propertyMethods = ["val", "data"], 24631 methodsMap = { search: "externalSearch" }; 24632 24633 this.each(function () { 24634 if (args.length === 0 || typeof(args[0]) === "object") { 24635 opts = args.length === 0 ? {} : $.extend({}, args[0]); 24636 opts.element = $(this); 24637 24638 if (opts.element.get(0).tagName.toLowerCase() === "select") { 24639 multiple = opts.element.prop("multiple"); 24640 } else { 24641 multiple = opts.multiple || false; 24642 if ("tags" in opts) {opts.multiple = multiple = true;} 24643 } 24644 24645 select2 = multiple ? new window.Select2["class"].multi() : new window.Select2["class"].single(); 24646 select2.init(opts); 24647 } else if (typeof(args[0]) === "string") { 24648 24649 if (indexOf(args[0], allowedMethods) < 0) { 24650 throw "Unknown method: " + args[0]; 24651 } 24652 24653 value = undefined; 24654 select2 = $(this).data("select2"); 24655 if (select2 === undefined) return; 24656 24657 method=args[0]; 24658 24659 if (method === "container") { 24660 value = select2.container; 24661 } else if (method === "dropdown") { 24662 value = select2.dropdown; 24663 } else { 24664 if (methodsMap[method]) method = methodsMap[method]; 24665 24666 value = select2[method].apply(select2, args.slice(1)); 24667 } 24668 if (indexOf(args[0], valueMethods) >= 0 24669 || (indexOf(args[0], propertyMethods) >= 0 && args.length == 1)) { 24670 return false; // abort the iteration, ready to return first matched value 24671 } 24672 } else { 24673 throw "Invalid arguments to select2 plugin: " + args; 24674 } 24675 }); 24676 return (value === undefined) ? this : value; 24677 }; 24678 24679 // plugin defaults, accessible to users 24680 $.fn.select2.defaults = { 24681 width: "copy", 24682 loadMorePadding: 0, 24683 closeOnSelect: true, 24684 openOnEnter: true, 24685 containerCss: {}, 24686 dropdownCss: {}, 24687 containerCssClass: "", 24688 dropdownCssClass: "", 24689 formatResult: function(result, container, query, escapeMarkup) { 24690 var markup=[]; 24691 markMatch(result.text, query.term, markup, escapeMarkup); 24692 return markup.join(""); 24693 }, 24694 formatSelection: function (data, container, escapeMarkup) { 24695 return data ? escapeMarkup(data.text) : undefined; 24696 }, 24697 sortResults: function (results, container, query) { 24698 return results; 24699 }, 24700 formatResultCssClass: function(data) {return data.css;}, 24701 formatSelectionCssClass: function(data, container) {return undefined;}, 24702 formatMatches: function (matches) { return matches + " results are available, use up and down arrow keys to navigate."; }, 24703 formatNoMatches: function () { return "No matches found"; }, 24704 formatInputTooShort: function (input, min) { var n = min - input.length; return "Please enter " + n + " or more character" + (n == 1? "" : "s"); }, 24705 formatInputTooLong: function (input, max) { var n = input.length - max; return "Please delete " + n + " character" + (n == 1? "" : "s"); }, 24706 formatSelectionTooBig: function (limit) { return "You can only select " + limit + " item" + (limit == 1 ? "" : "s"); }, 24707 formatLoadMore: function (pageNumber) { return "Loading more resultsâ¦"; }, 24708 formatSearching: function () { return "Searchingâ¦"; }, 24709 minimumResultsForSearch: 0, 24710 minimumInputLength: 0, 24711 maximumInputLength: null, 24712 maximumSelectionSize: 0, 24713 id: function (e) { return e == undefined ? null : e.id; }, 24714 matcher: function(term, text) { 24715 return stripDiacritics(''+text).toUpperCase().indexOf(stripDiacritics(''+term).toUpperCase()) >= 0; 24716 }, 24717 separator: ",", 24718 tokenSeparators: [], 24719 tokenizer: defaultTokenizer, 24720 escapeMarkup: defaultEscapeMarkup,
24721 blurOnChange: false, 24722 selectOnBlur: false, 24723 adaptContainerCssClass: function(c) { return c; }, 24724 adaptDropdownCssClass: function(c) { return null; }, 24725 nextSearchTerm: function(selectedObject, currentSearchTerm) { return undefined; }, 24726 searchInputPlaceholder: '', 24727 createSearchChoicePosition: 'top', 24728 shouldFocusInput: function (instance) { 24729 // Attempt to detect touch devices 24730 var supportsTouchEvents = (('ontouchstart' in window) || 24731 (navigator.msMaxTouchPoints > 0)); 24732 24733 // Only devices which support touch events should be special cased 24734 if (!supportsTouchEvents) { 24735 return true; 24736 } 24737 24738 // Never focus the input if search is disabled 24739 if (instance.opts.minimumResultsForSearch < 0) { 24740 return false; 24741 } 24742 24743 return true; 24744 } 24745 }; 24746 24747 $.fn.select2.ajaxDefaults = { 24748 transport: $.ajax, 24749 params: { 24750 type: "GET", 24751 cache: false, 24752 dataType: "json" 24753 } 24754 }; 24755 24756 // exports 24757 window.Select2 = { 24758 query: { 24759 ajax: ajax, 24760 local: local, 24761 tags: tags 24762 }, util: { 24763 debounce: debounce, 24764 markMatch: markMatch, 24765 escapeMarkup: defaultEscapeMarkup, 24766 stripDiacritics: stripDiacritics 24767 }, "class": { 24768 "abstract": AbstractSelect2, 24769 "single": SingleSelect2, 24770 "multi": MultiSelect2 24771 } 24772 }; 24773 24774}(jQuery)); 24775 24776 24777/** 24778 * Select2 translations 24779 */ 24780(function ($) { 24781 "use strict"; 24782 if (getContentLanguage() === 'de') { 24783 $.extend($.fn.select2.defaults, { 24784 formatNoMatches: function () { return "Keine Ãbereinstimmungen gefunden"; }, 24785 formatInputTooShort: function (input, min) { var n = min - input.length; return "Bitte " + n + " Zeichen mehr eingeben"; }, 24786 formatInputTooLong: function (input, max) { var n = input.length - max; return "Bitte " + n + " Zeichen weniger eingeben"; }, 24787 formatSelectionTooBig: function (limit) { return "Sie können nur " + limit + " Eintr" + (limit === 1 ? "ag" : "äge") + " auswählen"; }, 24788 formatLoadMore: function (pageNumber) { return "Lade mehr Ergebnisseâ¦"; }, 24789 formatSearching: function () { return "Sucheâ¦"; } 24790 }); 24791 } 24792})(jQuery); 24793 24794/** 24795 * Select2 bindings 24796 */ 24797$(function(){ 24798 window.format_select2_image = function(state) { 24799 var originalOption = state.element; 24800 if ($(originalOption).data('thumb-url')) { 24801 return "<img style='width: 30px; margin-right: 10px;' src='" + $(originalOption).data('thumb-url') + "' />" + state.text; 24802 } else { 24803 return state.text; 24804 } 24805 }; 24806 24807 $('.select2-connectable').select2({ 24808 formatResult: window.format_select2_image, 24809 formatSelection: window.format_select2_image, 24810 escapeMarkup: function(m) { return m; } 24811 }); 24812 24813 24814 $('.select2-image-connectable').select2({ 24815 placeholder: '[Auswählen]', 24816 allowClear: true, 24817 formatResult: window.format_select2_image, 24818 formatSelection: window.format_select2_image, 24819 escapeMarkup: function(m) { return m; } 24820 }); 24821}); 24822 24823 24824(function() { 24825 window.SocialShareButton = { 24826 openUrl: function(url) { 24827 window.open(url); 24828 return false; 24829 }, 24830 share: function(el) { 24831 var get_tumblr_extra, img, site, title, tumblr_params, url; 24832 site = $(el).data('site'); 24833 title = encodeURIComponent($(el).parent().data('title') || ''); 24834 img = encodeURIComponent($(el).parent().data("img") || ''); 24835 url = encodeURIComponent($(el).parent().data("url") || ''); 24836 if (url.length === 0) { 24837 url = encodeURIComponent(location.href); 24838 } 24839 switch (site) { 24840 case "email": 24841 location.href = "mailto:?to=&subject=" + title + "&body=" + url; 24842 break; 24843 case "weibo": 24844 SocialShareButton.openUrl("http://service.weibo.com/share/share.php?url=" + url + "&type=3&pic=" + img + "&title=" + title); 24845 break; 24846 case "twitter": 24847 SocialShareButton.openUrl("https://twitter.com/home?status=" + title + ": " + url); 24848 break; 24849 case "douban": 24850 SocialShareButton.openUrl("http://shuo.douban.com/!service/share?href=" + url + "&name=" + title + "&image=" + img); 24851 break; 24852 case "facebook": 24853 SocialShareButton.openUrl("http://www.facebook.com/sharer.php?u=" + url); 24854 break; 24855 case "qq": 24856 SocialShareButton.openUrl("http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=" + url + "&title=" + title + "&pics=" + img); 24857 break; 24858 case "tqq": 24859 SocialShareButton.openUrl("http://share.v.t.qq.com/index.php?c=share&a=index&url=" + url + "&title=" + title + "&pic=" + img); 24860 break; 24861 case "baidu":
24862 SocialShareButton.openUrl("http://hi.baidu.com/pub/show/share?url=" + url + "&title=" + title + "&content="); 24863 break; 24864 case "kaixin001": 24865 SocialShareButton.openUrl("http://www.kaixin001.com/rest/records.php?url=" + url + "&content=" + title + "&style=11&pic=" + img); 24866 break; 24867 case "renren": 24868 SocialShareButton.openUrl("http://widget.renren.com/dialog/share?resourceUrl=" + url + "&srcUrl=" + url + "&title=" + title + "&pic=" + img + "&description="); 24869 break; 24870 case "google_plus": 24871 SocialShareButton.openUrl("https://plus.google.com/share?url=" + url); 24872 break; 24873 case "google_bookmark": 24874 SocialShareButton.openUrl("https://www.google.com/bookmarks/mark?op=edit&output=popup&bkmk=" + url + "&title=" + title); 24875 break; 24876 case "delicious": 24877 SocialShareButton.openUrl("http://www.delicious.com/save?url=" + url + "&title=" + title + "&jump=yes&pic=" + img); 24878 break; 24879 case "plurk": 24880 SocialShareButton.openUrl("http://www.plurk.com/?status=" + title + ": " + url + "&qualifier=shares"); 24881 break; 24882 case "pinterest": 24883 SocialShareButton.openUrl("http://www.pinterest.com/pin/create/button/?url=" + url + "&media=" + img + "&description=" + title); 24884 break; 24885 case "tumblr": 24886 get_tumblr_extra = function(param) { 24887 var cutom_data; 24888 cutom_data = $(el).attr("data-" + param); 24889 if (cutom_data) { 24890 return encodeURIComponent(cutom_data); 24891 } 24892 }; 24893 tumblr_params = function() { 24894 var params, path, quote, source; 24895 path = get_tumblr_extra('type') || 'link'; 24896 params = (function() { 24897 switch (path) { 24898 case 'text': 24899 title = get_tumblr_extra('title') || title; 24900 return "title=" + title; 24901 case 'photo': 24902 title = get_tumblr_extra('caption') || title; 24903 source = get_tumblr_extra('source') || img; 24904 return "caption=" + title + "&source=" + source; 24905 case 'quote': 24906 quote = get_tumblr_extra('quote') || title; 24907 source = get_tumblr_extra('source') || ''; 24908 return "quote=" + quote + "&source=" + source; 24909 default: 24910 title = get_tumblr_extra('title') || title; 24911 url = get_tumblr_extra('url') || url; 24912 return "name=" + title + "&url=" + url; 24913 } 24914 })(); 24915 return "/" + path + "?" + params; 24916 }; 24917 SocialShareButton.openUrl("http://www.tumblr.com/share" + (tumblr_params())); 24918 } 24919 return false; 24920 } 24921 }; 24922 24923}).call(this); 24924(function($, window, undefined) { 24925 "use strict"; 24926 24927 //regex 24928 var rtextshadow = /(-?\d+px|(?:hsl|rgb)a?\(.+?\)|#(?:[a-fA-F0-9]{3}){1,2}|0)/g, 24929 rtextshadowsplit = /(,)(?=(?:[^\)]|\([^\)]*\))*$)/, 24930 rcolortest = /^((?:rgb|hsl)a?|#)/, 24931 rcolor = /(rgb|hsl)a?\(\s*(\d+)\s*,\s*(\d+)%?\s*,\s*(\d+)%?(?:\s*,\s*([\.\d]+))?/, 24932 rshadowsplit = /(,)(?=(?:[^\)]|\([^\)]*\))*$)/g, 24933 filter = "progid:DXImageTransform.Microsoft.", 24934 marker = '\u2063', 24935 rmarker = /\u2063/g, 24936 rbreakleft = /([\(\[\{])/g, 24937 rbreakright = /([\)\]\}%°\!\?\u2014])/g, 24938 rbreakboth = /([\-\u2013])/g, 24939 rsplit = /[\s\u2063]/, 24940 rspace = /(\s*)/g, 24941 rspaceonly = /^\s*$/, 24942 rprespace = /^(\s*)/, 24943 prefix = "ui-text-shadow"; 24944 24945 // create a plugin 24946 $.fn.textshadow = function(value, options) { 24947 if (typeof value === 'object' && !options) { 24948 options = value; 24949 value = null; 24950 } 24951 var opts = options || {}, 24952 useStyle = opts.useStyle === false ? false : true, 24953 numShadows = opts.numShadows || 1, 24954 doDestroy = opts.destroy || false; 24955 24956 // handle clearing all of the shadows 24957 if (doDestroy) { 24958 return this.each(function() { 24959 destroy(this); 24960 }); 24961 } 24962 24963 // loop the found items 24964 return this.each(function() { 24965 var $elem = $(this), 24966 copySelector = '.' + prefix + '-copy', 24967 $copy; 24968 24969 // find the copy elements 24970 $copy = $elem.find(copySelector); 24971 24972 // create them if none exist 24973 if (!$copy.length) { 24974 // create all of the elements 24975 allWords(this); 24976 $copy = $elem.find(copySelector); 24977 } 24978 if (useStyle) { 24979 applyStyles($copy, value); 24980 } else if (numShadows > 1) { 24981 $copy.filter(copySelector + '-1').each(function() { 24982 var i = 1, 24983 $parent = $(this.parentNode), 24984 shadowSelector, $elem; 24985 while (i < numShadows) { 24986 shadowSelector = copySelector + '-' + (i + 1); 24987 if (!$parent.find(shadowSelector).length) { 24988 $elem = $(this.cloneNode(true)) 24989 .addClass(shadowSelector.substring(1)) 24990 .removeClass(prefix + '-copy-1');
24991 $parent.prepend($elem); 24992 } 24993 i++; 24994 } 24995 }); 24996 } 24997 }); 24998 }; 24999 25000 25001 //--------------------- 25002 // For splitting words 25003 //--------------------- 25004 // function for returning all words in an element as text nodes 25005 function allWords(elem) { 25006 $(elem).contents().each(function() { 25007 if (this.nodeType === 3 && this.data) { 25008 makeWords(this); 25009 return true; 25010 } 25011 25012 var $elem = $(this); 25013 if (this.nodeType === 1 && (!$elem.hasClass(prefix) || !$elem.hasClass(prefix + '-original') || !$elem.hasClass(prefix + '-copy'))) { 25014 allWords(this); 25015 return true; 25016 } 25017 }); 25018 } 25019 25020 // splits text nodes 25021 function makeWords(textNode) { 25022 // Split the text in the node by space characters 25023 var split, length, spaces, node, 25024 text = textNode.nodeValue, 25025 lastIndex = 0; 25026 25027 // Skip empty nodes or nodes that are only whitespace 25028 if (!text || /^\s*$/.test(text)) { 25029 return; 25030 } 25031 25032 //correct for IE break characters 25033 //leave a strange unicode character as a marker 25034 text = text.replace(rbreakleft, marker + '$1') 25035 .replace(rbreakright, '$1' + marker) 25036 .replace(rbreakboth, marker + '$1' + marker); 25037 25038 // split the string by break characters 25039 split = text.split(rsplit); 25040 25041 // remove our markers 25042 text = text.replace(rmarker, ''); 25043 25044 // Add the original string (it gets split) 25045 var fragment = document.createDocumentFragment(); 25046 25047 // set the "last index" based on leading whitespace 25048 lastIndex = rprespace.exec(text)[1].length; 25049 25050 // loop by the splits 25051 $.each(split, function() { 25052 length = this.length; 25053 25054 // IE9 will return empty splits (consecutive spaces) 25055 if (!length) { 25056 return true; 25057 } 25058 25059 //include the trailing space characters 25060 rspace.lastIndex = lastIndex + length; 25061 spaces = rspace.exec(text); 25062 25063 // slice out our text 25064 // create a new node with it 25065 node = wrapWord(text.substr(lastIndex, length + spaces[1].length)); 25066 if (node !== null) { 25067 fragment.appendChild(node); 25068 } 25069 lastIndex = lastIndex + length + spaces[1].length; 25070 }); 25071 textNode.parentNode.replaceChild(fragment.cloneNode(true), textNode); 25072 } 25073 25074 var shadowNode = $('<span class="' + prefix + '" />')[0], 25075 origNode = $('<span class="' + prefix + '-original" />')[0], 25076 copyNode = $('<span class="' + prefix + '-copy ' + prefix + '-copy-1" />')[0]; 25077 25078 // Removes the generated elements 25079 function destroy(elem) { 25080 var $elem = $(elem); 25081 25082 $elem.find('.' + prefix + '-copy').remove(); 25083 $elem.find('.' + prefix + '-original').unwrap().each(function() { 25084 $(this).replaceWith(this.childNodes); 25085 }); 25086 } 25087 25088 // Wrap words in generated elements 25089 function wrapWord(text) { 25090 if (!text.length) { // IE 9 25091 return null; 25092 } 25093 var shadow = shadowNode.cloneNode(false), 25094 orig = origNode.cloneNode(false), 25095 copy = copyNode.cloneNode(false); 25096 25097 shadow.appendChild(copy); 25098 shadow.appendChild(orig); 25099 25100 orig.appendChild(document.createTextNode(text)); 25101 copy.appendChild(document.createTextNode(text)); 25102 25103 return shadow; 25104 } 25105 25106 //--------------------- 25107 // For Applying Styles 25108 //--------------------- 25109 function applyStyles($copy, value) { 25110 // skip this if there's no currentStyle property 25111 if ($copy.length && !$copy[0].currentStyle) { return; } 25112 25113 // this will work in IE 25114 $copy.each(function() { 25115 var copy = this, 25116 style = value || copy.currentStyle['text-shadow'], 25117 $copy = $(copy), 25118 parent = copy.parentNode, 25119 shadows, i = 0; 25120 25121 // ensure we have the correct style using inheritence 25122 while ((!style || style === 'none') && parent.nodeName !== 'HTML') { 25123 style = parent.currentStyle['text-shadow']; 25124 parent = parent.parentNode; 25125 } 25126 25127 // don't apply style if we can't find one 25128 if (!style || style === 'none') { 25129 return true; 25130 } 25131 25132 // split the style, in case of multiple shadows 25133 shadows = style.split(rtextshadowsplit); 25134 25135 // loop by the splits 25136 $.each(shadows, function() { 25137 var shadow = this; 25138 25139 if (shadow == ',') { // IE 9 25140 return true; 25141 } 25142 25143 // parse the style 25144 var values = shadow.match(rtextshadow), 25145 color = 'inherit', 25146 opacity = 1, 25147 x, y, blur, $elem; 25148 25149 // capture the values 25150 25151 // pull out the color from either the first or last position 25152 // actually remove it from the array 25153 if (rcolortest.test(values[0])) { 25154 opacity = getAlpha(values[0]); 25155 color = toHex(values.shift()); 25156 } else if (rcolortest.test(values[values.length - 1])) { 25157 opacity = getAlpha(values[values.length - 1]); 25158 color = toHex(values.pop()); 25159 } 25160 25161 x = parseFloat(values[0]); // TODO: handle units 25162 y = parseFloat(values[1]); // TODO: handle units 25163 blur = values[2] !== undefined ? parseFloat(values[2]) : 0; // TODO: handle units 25164 25165 // create new shadows when multiple shadows exist 25166 if (i == 0) { 25167 $elem = $copy; 25168 } else { 25169 $elem = $copy.clone().prependTo($copy.parent()) 25170 .addClass(prefix + '-copy-' + (i + 1)) 25171 .removeClass(prefix + '-copy-1'); 25172 } 25173 25174 // style the element 25175 $elem.css({ 25176 color: color, 25177 left: (x - blur) + 'px', 25178 top: (y - blur) + 'px' 25179 }); 25180 25181 // add in the filters 25182 if (opacity < 1 || blur > 0) { 25183 $elem[0].style.filter = [ 25184 opacity < 1 ? filter + "Alpha(opacity=" + parseInt(opacity * 100, 10) + ") " : '', 25185 blur > 0 ? filter + "Blur(pixelRadius=" + blur + ")" : '' 25186 ].join(''); 25187 } 25188 i++; 25189 }); 25190 }); 25191 } 25192 25193 //--------------------- 25194 // For Colors 25195 //--------------------- 25196 // http://haacked.com/archive/2009/12/29/convert-rgb-to-hex.aspx 25197 function toHex(color) { 25198 // handle rgb 25199 var matches = rcolor.exec(color), rgb; 25200 25201 // handle hsl 25202 if (matches && matches[1] === 'hsl') { 25203 rgb = hsl2rgb(matches[2], matches[3], matches[4]); 25204 matches[2] = rgb[0]; 25205 matches[3] = rgb[1]; 25206 matches[4] = rgb[2]; 25207 } 25208 25209 // convert to hex 25210 return matches ? '#' + (1 << 24 | matches[2] << 16 | matches[3] << 8 | matches[4]).toString(16).substr(1) : color; 25211 } 25212 25213 function getAlpha(color) { 25214 var matches = rcolor.exec(color); 25215 if (matches) { 25216 return matches[5] !== undefined ? matches[5] : 1; 25217 } 25218 return 1; 25219 } 25220 25221 // http://www.codingforums.com/showthread.php?t=11156 25222 function hsl2rgb(h, s, l) { 25223 var m1, m2, hue, r, g, b; 25224 s /=100; 25225 l /= 100; 25226 if (s === 0) { 25227 r = g = b = (l * 255); 25228 } else { 25229 if (l <= 0.5) { 25230 m2 = l * (s + 1); 25231 } else { 25232 m2 = l + s - l * s; 25233 } 25234 m1 = l * 2 - m2; 25235 hue = h / 360; 25236 r = hue2rgb(m1, m2, hue + 1/3); 25237 g = hue2rgb(m1, m2, hue); 25238 b = hue2rgb(m1, m2, hue - 1/3); 25239 } 25240 return [r, g, b]; 25241 } 25242 25243 function hue2rgb(m1, m2, hue) { 25244 var v; 25245 if (hue < 0) { 25246 hue += 1; 25247 } else if (hue > 1) { 25248 hue -= 1; 25249 } 25250 25251 if (6 * hue < 1) { 25252 v = m1 + (m2 - m1) * hue * 6; 25253 } else if (2 * hue < 1) { 25254 v = m2; 25255 } else if (3 * hue < 2) { 25256 v = m1 + (m2 - m1) * (2/3 - hue) * 6; 25257 } else { 25258 v = m1; 25259 } 25260 25261 return 255 * v; 25262 } 25263})(jQuery, this); 25264window.searchbaractivity = false;
25265window.windowWidth = $(window).width(); 25266window.screen_sm = 768; 25267 25268 25269// --------------- 25270 25271 25272// header utilities ux 25273 25274// let the header dropdowns open on over and do nothing on click if no-touch 25275$(document).ready(function() { 25276 // check back if this is not a touch device 25277 if($("html").hasClass("no-touch")) { 25278 apply_navbar_mouseevents(false); 25279 } 25280 fix_dropdown_form(); 25281}); 25282 25283 25284 25285// --------------- 25286 25287 25288// open navbar dropdowns on hover 25289function apply_navbar_mouseevents(custom_selector) { 25290 25291 if (custom_selector === false) { 25292 $selector = $("#header-container li.dropdown"); 25293 } else { 25294 $selector = custom_selector; 25295 } 25296 25297 // enable dropdown hover 25298 $selector.find("a.dropdown-toggle").mouseenter(function(){ 25299 $this = $(this); 25300 $dropdown = $this.parent(); 25301 25302 if($dropdown.hasClass("open") === false) { 25303 $this.dropdown('toggle'); 25304 25305 // focus search input 25306 if ($dropdown.hasClass("dropdown-search")) { 25307 $dropdown.find("input").focus(); 25308 } 25309 } 25310 }); 25311 $selector.mouseleave(function(){ 25312 $this = $(this); 25313 if ($this.hasClass('dropdown-flags')) { 25314 if($this.hasClass("open") === true) { 25315 $this.find("a.dropdown-toggle").dropdown('toggle'); 25316 } 25317 $this.find("a.dropdown-toggle").blur(); 25318 } 25319 }); 25320}; 25321function close_nav_dropdowns() { 25322 $('.nav .dropdown.open').dropdown('toggle'); 25323} 25324 25325function fix_dropdown_form() { 25326 $('.dropdown .dropdown-menu form, .dropdown .dropdown-menu input, .dropdown .dropdown-menu a, .dropdown .dropdown-menu .checkbox, .dropdown .dropdown-menu button').bind('click', function (e) { e.stopPropagation() }); 25327}; 25328function reconnect_navbar_dropdowns() { 25329 $("#header-container li.dropdown a.dropdown-toggle").dropdown(); 25330 fix_dropdown_form(); 25331 25332 // check back if this is not a touch device 25333 if($("html").hasClass("no-touch")) { 25334 apply_navbar_mouseevents($("#meta-nav")); 25335 } 25336}; 25337 25338 25339// --------------- 25340 25341 25342function add_browser_classes(classes) {
25343 $("body").addClass(classes); 25344 25345 $.event.trigger({ 25346 type: "browserClassesAdded", 25347 message: "Hello World!", 25348 time: new Date() 25349 }); 25350} 25351 25352 25353// enable navigation hovering 25354function swapped_navigation() { 25355 // hover-navigation 25356 if($("html").hasClass("no-touch")) { 25357 enable_no_touch_navigation_hover(); 25358 } 25359 if($("html").hasClass("touch")) { 25360 enable_touch_navigation_hover(); 25361 } 25362} 25363 25364function enable_no_touch_navigation_hover() { 25365 $('#mainnavigation .navbar-nav > li').hover(function() { 25366 var $this = $(this); 25367 var nav_hover = $this.find(".navigation-hover"); 25368 25369 if (nav_hover.length > 0) { 25370 if ($this.parent().hasClass('open')) { 25371 // $this.find('.navigation-hover').show(); 25372 clearTimeout(window.mainNavHover); 25373 return true; 25374 } 25375 clearTimeout(window.mainNavHover); 25376 window.mainNavHover = setTimeout(function() { 25377 $this.addClass('open'); 25378 25379 close_nav_dropdowns(); 25380 25381 // $this.find('.navigation-hover').show(); 25382 }, 400); 25383 } 25384 }, function() { 25385 var $this = $(this); 25386 clearTimeout(window.mainNavHover); 25387 // $this.find('.navigation-hover').hide(); 25388 }); 25389 25390 $('.navigation-hover').mouseleave(function() { 25391 $(this).closest("li").removeClass('open'); 25392 }); 25393 $('.navigation-hover').parent().mouseleave(function() { 25394 $(this).removeClass('open'); 25395 }); 25396} 25397function enable_touch_navigation_hover() { 25398 $hover_navs = $(".navigation-hover"); 25399 25400 $("#mainnavigation .navbar-left > li > a").click(function(){ 25401 $trigger = $(this); 25402 $nav_li = $trigger.parent(); 25403 $hover_nav = $nav_li.find(".navigation-hover"); 25404 hover_state = ($nav_li.hasClass("open") ? "open" : "closed"); 25405 has_hover_nav = ($hover_nav.length > 0 ? true : false); 25406 25407 // close all hover navs 25408 hide_hover_navs($hover_navs); 25409 25410 // open desired hover nav 25411 if (hover_state == "closed" && has_hover_nav) { 25412 open_hover_nav(this); 25413 return false; 25414 } else { 25415 return true; 25416 } 25417 }); 25418 25419 $(document).click(function(){ 25420 // close all hover navs 25421 hide_hover_navs($hover_navs); 25422 }); 25423} 25424 25425function open_hover_nav(trigger) { 25426 // add direct hover class to parent 25427 $(trigger).parent().addClass("open"); 25428 25429 close_nav_dropdowns(); 25430 25431 // show nav 25432 $(trigger).parent().find(".navigation-hover").show(); 25433} 25434function hide_hover_navs(hover_navs) { 25435 hover_navs.each(function(){ 25436 $this = $(this); 25437 $this.parent().removeClass("open"); 25438 // $this.hide(); 25439 }); 25440} 25441 25442 25443 25444 25445 25446 25447// affix header 25448// $(document).ready(function() { 25449// $skysraper = $(".bme-ad-wallpaper-wrapper .bme-ad-skyscraper"); // bme-ad-skyscraper:not(.bme-ad-wallpaper) 25450// window.header_height = 200; //$("#header-container").first().outerHeight(true); 25451// 25452// $('#header-container').affix({ 25453// offset: window.header_height + 100 25454// }); 25455// 25456// 25457// $('#header-container').on('affixed.bs.affix', function () { 25458// window.header_height = 200; 25459// $(".page").css("margin-top", window.header_height); 25460// $('#header-container').addClass('animated fadeInDown'); 25461// }); 25462// 25463// $('#header-container').on('affixed-top.bs.affix', function () { 25464// $(".page").css("margin-top", 0); 25465// $('#header-container').removeClass('animated fadeInDown'); 25466// }); 25467// }); 25468 25469 25470// tooltips 25471$(document).ready(function(){ 25472 $('[data-toggle="tooltip"]').tooltip(); 25473}); 25474 25475 25476 25477// --------------- 25478 25479 25480 25481$(document).ready(function(){ 25482 if($("body").data("env") == "development") { 25483 $(".nav.nav-pills.nav-stacked a, .sidebar-navigation a").each(function(){ 25484 $this = $(this); 25485 href = $this.attr("href"); 25486 target_url = window.location.protocol + "//" + window.location.host + href; 25487 current_url = document.URL; 25488 25489 if (current_url == target_url) { 25490 $this.toggleClass("active"); 25491 $this.parent().toggleClass("active"); 25492 } 25493 }); 25494 } 25495}); 25496 25497 25498 25499// --------------- 25500 25501 25502// start the image gallery 25503$(document).ready(function(){ 25504 $(".play-image-gallery").click(function(){ 25505 id = $(this).attr("data-target"); 25506 if(id !== undefined) { 25507 $(id).find("a:first").click(); 25508 } else { 25509 $(this).next(".teaser-listing-gallery").find("a:first").click(); 25510 } 25511 }); 25512}); 25513 25514 25515 25516// -------------- 25517 25518 25519// since bootstrap doesnt support -> just for the meta box 25520$(document).ready(function(){ 25521 $('[data-parent]').click(function(){ 25522 $this = $(this); 25523 parent = $this.data("parent"); 25524 $parent = $(parent); 25525 target = $this.data("target"); 25526 $target = $(target);
25527 $collapse_target = $this.data("collapse-target") + ".in"; 25528 25529 // close all available header meta boxes 25530 $parent.find($collapse_target).each(function(){ 25531 $box = $(this); 25532 $box.collapse('hide'); 25533 }); 25534 25535 // open the target 25536 $target.collapse('show'); 25537 }); 25538}); 25539 25540 25541// -------------- 25542 25543// ie8 textshadow 25544 25545$(document).ready(function(){ 25546 if (!Modernizr.textshadow) { 25547 $('.header-branding h2').textshadow("0 1px 30px white, 0 1px 10px white, 0 1px 40px white, 0 1px 20px white"); 25548 } 25549}); 25550 25551 25552 25553// wrap tables within the responsive div 25554$(document).ready(function() { 25555 $(".page-content table").wrap('<div class="table-responsive"></div>'); 25556}); 25557 25558 25559// -------------- 25560 25561 25562// headroom 25563$(document).ready(function() { 25564 window.header_height = 200; 25565 25566 $('#header-container').headroom({ 25567 offset: $(".page").offset().top + 30, 25568 tolerance : { 25569 up : 0, 25570 down : 10 25571 }, 25572 classes: { 25573 initial: 'headroom--initial', 25574 pinned: "headroom--pinned" 25575 }, 25576 onPin: function() { 25577 $('#header-container').addClass('animated fadeInDown'); 25578 25579 $('#header-container').one('animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd', function(){ 25580 $('#header-container').removeClass('animated fadeInDown'); 25581 }); 25582 }, 25583 onUnpin: function() { 25584 $('#header-container').addClass('animated fadeOutUp'); 25585 25586 $('#header-container').one('animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd', function(){ 25587 $('#header-container').removeClass('animated fadeOutUp'); 25588 }); 25589 }, 25590 onTop: function() { 25591 $("#headroom-placeholder").remove(); 25592 $('#header-container').removeClass('animated fadeInDown fadeOutUp'); 25593 }, 25594 onNotTop: function() { 25595 // add a placeholder to keep the scrollpoint 25596 var $div = '<div id="headroom-placeholder" style="height: ' + window.header_height + 'px;"></div>'; 25597 25598 $('#header-container').before($($div)); 25599 25600 // prevent animation for a small timeframe 25601 $('#header-container').addClass("disable-animations"); 25602 setTimeout(function(){ 25603 $('#header-container').removeClass("disable-animations"); 25604 }, 700); 25605 25606 // don't pin asap 25607 $('#header-container').removeClass("headroom--pinned"); 25608 setTimeout(function(){ 25609 $('#header-container').removeClass("headroom--pinned"); 25610 }, 50); 25611 setTimeout(function(){ 25612 $('#header-container').removeClass("headroom--pinned"); 25613 }, 100); 25614 setTimeout(function(){ 25615 $('#header-container').removeClass("headroom--pinned"); 25616 }, 150); 25617 } 25618 }); 25619}); 25620 25621 25622 25623 25624// feedback button 25625$(document).ready(function() { 25626 $btn = $('<a class="btn btn-feedback" href="https://app.smartsheet.com/b/form?EQBCT=7a395d139d2b4df39df8d00c86d0627c" target="_blank">Feedback</a>'); 25627 path = window.location.pathname.split('/')[1]; // should be veranstaltungen 25628 subdomain = window.location.host.split('.')[0]; // should be shop 25629 breadcrumb = false 25630 if ($(".breadcrumb").length > 0) { 25631 breadcrumb = $(".breadcrumb").html().indexOf("GroÃveranstaltungen") !== -1; 25632 } 25633 25634 if (path == 'veranstaltungen' || subdomain == 'shop' || breadcrumb === true) { 25635 $('body').append($btn); 25636 } 25637}); 25638 25639 25640// close nav dropdowns when hovering hover language icons on desktop 25641$(document).ready(function(){ 25642 var $dropdown = $('.dropdown-flags'); 25643 var $dropdown_menu = $dropdown.find('.dropdown-menu'); 25644 25645 // close on hover if menu is relative 25646 if ($dropdown_menu.css('position') == 'relative') { 25647 $dropdown_menu.find('a').hover(function(){ 25648 close_nav_dropdowns(); 25649 }); 25650 } 25651}); 25652 25653 25654 25655// change wallpaper background color 25656$(document).ready(function(){ 25657 adjust_wallpaper_styles(); 25658}); 25659$(window).load(function(){ 25660 adjust_wallpaper_styles(); 25661 setTimeout(adjust_wallpaper_styles, 1000); 25662 setTimeout(adjust_wallpaper_styles, 2000); 25663}); 25664 25665function adjust_wallpaper_styles() { 25666 if (typeof p != 'undefined') { 25667 var wallpaperColor = p.backgroundColor; 25668 var sasTagId = window.sasTagId; 25669 var $wallpaperContainer = $('#' + sasTagId).first().find('.megabanner_background').first(); 25670 var $banner = $("#" + window.sasTagId); 25671 25672 // apply color 25673 $wallpaperContainer.css('backgroundColor', "#" + wallpaperColor); 25674 25675 // remove style tag inserted by smartadserver 25676 var target_style_content = "background-color: #" + wallpaperColor + " !important;"; 25677 25678 // add class to banner 25679 $banner.addClass('ad-wallpaper'); 25680 25681 $('body').addClass('ad-has-wallpaper'); 25682 25683 $('style').each(function(){ 25684 var style = $(this); 25685 var style_html = style.html(); 25686 25687 if (style_html.indexOf(target_style_content) >= 0) { 25688 style.remove(); 25689 } 25690 }) 25691 } 25692} 25693 25694 25695$(document).on("browserClassesAdded", function(){ 25696 25697 $body = $("body"); 25698 25699 if (!$body.hasClass("mobile") && !$body.hasClass("msie8") && !$body.hasClass("msie8")) { 25700 // get all hires images 25701 $hires = $("[data-hires]"); 25702 25703 // loop through the images 25704 $hires.each(function(){ 25705 $this = $(this); 25706 var hires_src = $this.data("hires"); 25707 var src = $this.attr("src"); 25708 var img = $this; 25709 25710 var img_call = $.ajax(hires_src) 25711 .success(function() { 25712 25713 // swap image if the hires alternative is available 25714 swap_hires_image(img, hires_src, src); 25715 }); 25716 }); 25717 } 25718}); 25719 25720function swap_hires_image(element, hires_src, src) { 25721 $(element).attr("src", null); 25722 $(element).attr("src", hires_src); 25723 $(element).attr("data-original-src", src); 25724} 25725
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.