1/*! 2 * jQuery JavaScript Library v2.2.2 3 * http://jquery.com/ 4 * 5 * Includes Sizzle.js 6 * http://sizzlejs.com/ 7 * 8 * Copyright jQuery Foundation and other contributors 9 * Released under the MIT license 10 * http://jquery.org/license 11 * 12 * Date: 2016-03-17T17:51Z 13 */ 14 15(function( global, factory ) { 16 17 if ( typeof module === "object" && typeof module.exports === "object" ) { 18 // For CommonJS and CommonJS-like environments where a proper `window` 19 // is present, execute the factory and get jQuery. 20 // For environments that do not have a `window` with a `document` 21 // (such as Node.js), expose a factory as module.exports. 22 // This accentuates the need for the creation of a real `window`. 23 // e.g. var jQuery = require("jquery")(window); 24 // See ticket #14549 for more info. 25 module.exports = global.document ? 26 factory( global, true ) : 27 function( w ) { 28 if ( !w.document ) { 29 throw new Error( "jQuery requires a window with a document" ); 30 } 31 return factory( w ); 32 }; 33 } else { 34 factory( global ); 35 } 36 37// Pass this if window is not defined yet 38}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { 39 40// Support: Firefox 18+ 41// Can't be in strict mode, several libs including ASP.NET trace 42// the stack via arguments.caller.callee and Firefox dies if 43// you try to trace through "use strict" call chains. (#13335) 44//"use strict"; 45var arr = []; 46 47var document = window.document; 48 49var slice = arr.slice; 50 51var concat = arr.concat; 52 53var push = arr.push; 54 55var indexOf = arr.indexOf; 56 57var class2type = {}; 58 59var toString = class2type.toString; 60 61var hasOwn = class2type.hasOwnProperty; 62 63var support = {}; 64 65 66 67var 68 version = "2.2.2
vendor: 132,342 bytes, lines 68-5008
68", 69 70 // Define a local copy of jQuery 71 jQuery = function( selector, context ) { 72 73 // The jQuery object is actually just the init constructor 'enhanced' 74 // Need init if jQuery is called (just allow error to be thrown if not included) 75 return new jQuery.fn.init( selector, context ); 76 }, 77 78 // Support: Android<4.1 79 // Make sure we trim BOM and NBSP 80 rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, 81 82 // Matches dashed string for camelizing 83 rmsPrefix = /^-ms-/, 84 rdashAlpha = /-([\da-z])/gi, 85 86 // Used by jQuery.camelCase as callback to replace() 87 fcamelCase = function( all, letter ) { 88 return letter.toUpperCase(); 89 }; 90 91jQuery.fn = jQuery.prototype = { 92 93 // The current version of jQuery being used 94 jquery: version, 95 96 constructor: jQuery, 97 98 // Start with an empty selector 99 selector: "", 100 101 // The default length of a jQuery object is 0 102 length: 0, 103 104 toArray: function() { 105 return slice.call( this ); 106 }, 107 108 // Get the Nth element in the matched element set OR 109 // Get the whole matched element set as a clean array 110 get: function( num ) { 111 return num != null ? 112 113 // Return just the one element from the set 114 ( num < 0 ? this[ num + this.length ] : this[ num ] ) : 115 116 // Return all the elements in a clean array 117 slice.call( this ); 118 }, 119 120 // Take an array of elements and push it onto the stack 121 // (returning the new matched element set) 122 pushStack: function( elems ) { 123 124 // Build a new jQuery matched element set 125 var ret = jQuery.merge( this.constructor(), elems ); 126 127 // Add the old object onto the stack (as a reference) 128 ret.prevObject = this; 129 ret.context = this.context; 130 131 // Return the newly-formed element set 132 return ret; 133 }, 134 135 // Execute a callback for every element in the matched set. 136 each: function( callback ) { 137 return jQuery.each( this, callback ); 138 }, 139 140 map: function( callback ) { 141 return this.pushStack( jQuery.map( this, function( elem, i ) { 142 return callback.call( elem, i, elem ); 143 } ) ); 144 }, 145 146 slice: function() { 147 return this.pushStack( slice.apply( this, arguments ) ); 148 }, 149 150 first: function() { 151 return this.eq( 0 ); 152 }, 153 154 last: function() { 155 return this.eq( -1 ); 156 }, 157 158 eq: function( i ) { 159 var len = this.length, 160 j = +i + ( i < 0 ? len : 0 ); 161 return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); 162 }, 163 164 end: function() { 165 return this.prevObject || this.constructor(); 166 }, 167 168 // For internal use only. 169 // Behaves like an Array's method, not like a jQuery method. 170 push: push, 171 sort: arr.sort, 172 splice: arr.splice 173}; 174 175jQuery.extend = jQuery.fn.extend = function() { 176 var options, name, src, copy, copyIsArray, clone, 177 target = arguments[ 0 ] || {}, 178 i = 1, 179 length = arguments.length, 180 deep = false; 181 182 // Handle a deep copy situation 183 if ( typeof target === "boolean" ) { 184 deep = target; 185 186 // Skip the boolean and the target 187 target = arguments[ i ] || {}; 188 i++; 189 } 190 191 // Handle case when target is a string or something (possible in deep copy) 192 if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { 193 target = {}; 194 } 195 196 // Extend jQuery itself if only one argument is passed 197 if ( i === length ) { 198 target = this; 199 i--; 200 } 201 202 for ( ; i < length; i++ ) { 203 204 // Only deal with non-null/undefined values 205 if ( ( options = arguments[ i ] ) != null ) { 206 207 // Extend the base object 208 for ( name in options ) { 209 src = target[ name ]; 210 copy = options[ name ]; 211 212 // Prevent never-ending loop 213 if ( target === copy ) { 214 continue; 215 } 216 217 // Recurse if we're merging plain objects or arrays 218 if ( deep && copy && ( jQuery.isPlainObject( copy ) || 219 ( copyIsArray = jQuery.isArray( copy ) ) ) ) { 220 221 if ( copyIsArray ) { 222 copyIsArray = false; 223 clone = src && jQuery.isArray( src ) ? src : []; 224 225 } else { 226 clone = src && jQuery.isPlainObject( src ) ? src : {}; 227 } 228 229 // Never move original objects, clone them 230 target[ name ] = jQuery.extend( deep, clone, copy ); 231 232 // Don't bring in undefined values 233 } else if ( copy !== undefined ) { 234 target[ name ] = copy; 235 } 236 } 237 } 238 } 239 240 // Return the modified object 241 return target; 242}; 243 244jQuery.extend( { 245 246 // Unique for each copy of jQuery on the page 247 expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), 248 249 // Assume jQuery is ready without the ready module 250 isReady: true, 251 252 error: function( msg ) { 253 throw new Error( msg ); 254 }, 255 256 noop: function() {}, 257 258 isFunction: function( obj ) { 259 return jQuery.type( obj ) === "function"; 260 }, 261 262 isArray: Array.isArray, 263 264 isWindow: function( obj ) { 265 return obj != null && obj === obj.window; 266 }, 267 268 isNumeric: function( obj ) { 269 270 // parseFloat NaNs numeric-cast false positives (null|true|false|"") 271 // ...but misinterprets leading-number strings, particularly hex literals ("0x...") 272 // subtraction forces infinities to NaN 273 // adding 1 corrects loss of precision from parseFloat (#15100) 274 var realStringObj = obj && obj.toString(); 275 return !jQuery.isArray( obj ) && ( realStringObj - parseFloat( realStringObj ) + 1 ) >= 0; 276 }, 277 278 isPlainObject: function( obj ) { 279 var key; 280 281 // Not plain objects: 282 // - Any object or value whose internal [[Class]] property is not "[object Object]" 283 // - DOM nodes 284 // - window 285 if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { 286 return false; 287 } 288 289 // Not own constructor property must be Object 290 if ( obj.constructor && 291 !hasOwn.call( obj, "constructor" ) && 292 !hasOwn.call( obj.constructor.prototype || {}, "isPrototypeOf" ) ) { 293 return false; 294 } 295 296 // Own properties are enumerated firstly, so to speed up, 297 // if last one is own, then all properties are own 298 for ( key in obj ) {} 299 300 return key === undefined || hasOwn.call( obj, key ); 301 }, 302 303 isEmptyObject: function( obj ) { 304 var name; 305 for ( name in obj ) { 306 return false; 307 } 308 return true; 309 }, 310 311 type: function( obj ) { 312 if ( obj == null ) { 313 return obj + ""; 314 } 315 316 // Support: Android<4.0, iOS<6 (functionish RegExp) 317 return typeof obj === "object" || typeof obj === "function" ? 318 class2type[ toString.call( obj ) ] || "object" : 319 typeof obj; 320 }, 321 322 // Evaluates a script in a global context 323 globalEval: function( code ) { 324 var script, 325 indirect = eval; 326 327 code = jQuery.trim( code ); 328 329 if ( code ) { 330 331 // If the code includes a valid, prologue position 332 // strict mode pragma, execute code by injecting a 333 // script tag into the document. 334 if ( code.indexOf( "use strict" ) === 1 ) { 335 script = document.createElement( "script" ); 336 script.text = code; 337 document.head.appendChild( script ).parentNode.removeChild( script ); 338 } else { 339 340 // Otherwise, avoid the DOM node creation, insertion 341 // and removal by using an indirect global eval 342 343 indirect( code ); 344 } 345 } 346 }, 347 348 // Convert dashed to camelCase; used by the css and data modules 349 // Support: IE9-11+ 350 // Microsoft forgot to hump their vendor prefix (#9572) 351 camelCase: function( string ) { 352 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); 353 }, 354 355 nodeName: function( elem, name ) { 356 return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); 357 }, 358 359 each: function( obj, callback ) { 360 var length, i = 0; 361 362 if ( isArrayLike( obj ) ) { 363 length = obj.length; 364 for ( ; i < length; i++ ) { 365 if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { 366 break; 367 } 368 } 369 } else { 370 for ( i in obj ) { 371 if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { 372 break; 373 } 374 } 375 } 376 377 return obj; 378 }, 379 380 // Support: Android<4.1 381 trim: function( text ) { 382 return text == null ? 383 "" : 384 ( text + "" ).replace( rtrim, "" ); 385 }, 386 387 // results is for internal usage only 388 makeArray: function( arr, results ) { 389 var ret = results || []; 390 391 if ( arr != null ) { 392 if ( isArrayLike( Object( arr ) ) ) { 393 jQuery.merge( ret, 394 typeof arr === "string" ? 395 [ arr ] : arr 396 ); 397 } else { 398 push.call( ret, arr ); 399 } 400 } 401 402 return ret; 403 }, 404 405 inArray: function( elem, arr, i ) { 406 return arr == null ? -1 : indexOf.call( arr, elem, i ); 407 }, 408 409 merge: function( first, second ) { 410 var len = +second.length, 411 j = 0, 412 i = first.length; 413 414 for ( ; j < len; j++ ) { 415 first[ i++ ] = second[ j ]; 416 } 417 418 first.length = i; 419 420 return first; 421 }, 422 423 grep: function( elems, callback, invert ) { 424 var callbackInverse, 425 matches = [], 426 i = 0, 427 length = elems.length, 428 callbackExpect = !invert; 429 430 // Go through the array, only saving the items 431 // that pass the validator function 432 for ( ; i < length; i++ ) { 433 callbackInverse = !callback( elems[ i ], i ); 434 if ( callbackInverse !== callbackExpect ) { 435 matches.push( elems[ i ] ); 436 } 437 } 438 439 return matches; 440 }, 441 442 // arg is for internal usage only 443 map: function( elems, callback, arg ) { 444 var length, value, 445 i = 0, 446 ret = []; 447 448 // Go through the array, translating each of the items to their new values 449 if ( isArrayLike( elems ) ) { 450 length = elems.length; 451 for ( ; i < length; i++ ) { 452 value = callback( elems[ i ], i, arg ); 453 454 if ( value != null ) { 455 ret.push( value ); 456 } 457 } 458 459 // Go through every key on the object, 460 } else { 461 for ( i in elems ) { 462 value = callback( elems[ i ], i, arg ); 463 464 if ( value != null ) { 465 ret.push( value ); 466 } 467 } 468 } 469 470 // Flatten any nested arrays 471 return concat.apply( [], ret ); 472 }, 473 474 // A global GUID counter for objects 475 guid: 1, 476 477 // Bind a function to a context, optionally partially applying any 478 // arguments. 479 proxy: function( fn, context ) { 480 var tmp, args, proxy; 481 482 if ( typeof context === "string" ) { 483 tmp = fn[ context ]; 484 context = fn; 485 fn = tmp; 486 } 487 488 // Quick check to determine if target is callable, in the spec 489 // this throws a TypeError, but we will just return undefined. 490 if ( !jQuery.isFunction( fn ) ) { 491 return undefined; 492 } 493 494 // Simulated bind 495 args = slice.call( arguments, 2 ); 496 proxy = function() { 497 return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); 498 }; 499 500 // Set the guid of unique handler to the same of original handler, so it can be removed 501 proxy.guid = fn.guid = fn.guid || jQuery.guid++; 502 503 return proxy; 504 }, 505 506 now: Date.now, 507 508 // jQuery.support is not used in Core but other projects attach their 509 // properties to it so it needs to exist. 510 support: support 511} ); 512 513// JSHint would error on this code due to the Symbol not being defined in ES5. 514// Defining this global in .jshintrc would create a danger of using the global 515// unguarded in another place, it seems safer to just disable JSHint for these 516// three lines. 517/* jshint ignore: start */ 518if ( typeof Symbol === "function" ) { 519 jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; 520} 521/* jshint ignore: end */ 522 523// Populate the class2type map 524jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), 525function( i, name ) { 526 class2type[ "[object " + name + "]" ] = name.toLowerCase(); 527} ); 528 529function isArrayLike( obj ) { 530 531 // Support: iOS 8.2 (not reproducible in simulator) 532 // `in` check used to prevent JIT error (gh-2145) 533 // hasOwn isn't used here due to false negatives 534 // regarding Nodelist length in IE 535 var length = !!obj && "length" in obj && obj.length, 536 type = jQuery.type( obj ); 537 538 if ( type === "function" || jQuery.isWindow( obj ) ) { 539 return false; 540 } 541 542 return type === "array" || length === 0 || 543 typeof length === "number" && length > 0 && ( length - 1 ) in obj; 544} 545var Sizzle = 546/*! 547 * Sizzle CSS Selector Engine v2.2.1 548 * http://sizzlejs.com/ 549 * 550 * Copyright jQuery Foundation and other contributors 551 * Released under the MIT license 552 * http://jquery.org/license 553 * 554 * Date: 2015-10-17 555 */ 556(function( window ) { 557 558var i, 559 support, 560 Expr, 561 getText, 562 isXML, 563 tokenize, 564 compile, 565 select, 566 outermostContext, 567 sortInput, 568 hasDuplicate, 569 570 // Local document vars 571 setDocument, 572 document, 573 docElem, 574 documentIsHTML, 575 rbuggyQSA, 576 rbuggyMatches, 577 matches, 578 contains, 579 580 // Instance-specific data 581 expando = "sizzle" + 1 * new Date(), 582 preferredDoc = window.document, 583 dirruns = 0, 584 done = 0, 585 classCache = createCache(), 586 tokenCache = createCache(), 587 compilerCache = createCache(), 588 sortOrder = function( a, b ) { 589 if ( a === b ) { 590 hasDuplicate = true; 591 } 592 return 0; 593 }, 594 595 // General-purpose constants 596 MAX_NEGATIVE = 1 << 31, 597 598 // Instance methods 599 hasOwn = ({}).hasOwnProperty, 600 arr = [], 601 pop = arr.pop, 602 push_native = arr.push, 603 push = arr.push, 604 slice = arr.slice, 605 // Use a stripped-down indexOf as it's faster than native 606 // http://jsperf.com/thor-indexof-vs-for/5 607 indexOf = function( list, elem ) { 608 var i = 0, 609 len = list.length; 610 for ( ; i < len; i++ ) { 611 if ( list[i] === elem ) { 612 return i; 613 } 614 } 615 return -1; 616 }, 617 618 booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", 619 620 // Regular expressions 621 622 // http://www.w3.org/TR/css3-selectors/#whitespace 623 whitespace = "[\\x20\\t\\r\\n\\f]", 624 625 // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier 626 identifier = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", 627 628 // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors 629 attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + 630 // Operator (capture 2) 631 "*([*^$|!~]?=)" + whitespace + 632 // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" 633 "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + 634 "*\\]", 635 636 pseudos = ":(" + identifier + ")(?:\\((" + 637 // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: 638 // 1. quoted (capture 3; capture 4 or capture 5) 639 "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + 640 // 2. simple (capture 6) 641 "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + 642 // 3. anything else (capture 2) 643 ".*" + 644 ")\\)|)", 645 646 // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter 647 rwhitespace = new RegExp( whitespace + "+", "g" ), 648 rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), 649 650 rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), 651 rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), 652 653 rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), 654 655 rpseudo = new RegExp( pseudos ), 656 ridentifier = new RegExp( "^" + identifier + "$" ), 657 658 matchExpr = { 659 "ID": new RegExp( "^#(" + identifier + ")" ), 660 "CLASS": new RegExp( "^\\.(" + identifier + ")" ), 661 "TAG": new RegExp( "^(" + identifier + "|[*])" ), 662 "ATTR": new RegExp( "^" + attributes ), 663 "PSEUDO": new RegExp( "^" + pseudos ), 664 "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + 665 "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + 666 "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), 667 "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), 668 // For use in libraries implementing .is() 669 // We use this for POS matching in `select` 670 "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + 671 whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) 672 }, 673 674 rinputs = /^(?:input|select|textarea|button)$/i, 675 rheader = /^h\d$/i, 676 677 rnative = /^[^{]+\{\s*\[native \w/, 678 679 // Easily-parseable/retrievable ID or TAG or CLASS selectors 680 rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, 681 682 rsibling = /[+~]/, 683 rescape = /'|\\/g, 684 685 // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters 686 runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), 687 funescape = function( _, escaped, escapedWhitespace ) { 688 var high = "0x" + escaped - 0x10000; 689 // NaN means non-codepoint 690 // Support: Firefox<24 691 // Workaround erroneous numeric interpretation of +"0x" 692 return high !== high || escapedWhitespace ? 693 escaped : 694 high < 0 ? 695 // BMP codepoint 696 String.fromCharCode( high + 0x10000 ) : 697 // Supplemental Plane codepoint (surrogate pair) 698 String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); 699 }, 700 701 // Used for iframes 702 // See setDocument() 703 // Removing the function wrapper causes a "Permission Denied" 704 // error in IE 705 unloadHandler = function() { 706 setDocument(); 707 }; 708 709// Optimize for push.apply( _, NodeList ) 710try { 711 push.apply( 712 (arr = slice.call( preferredDoc.childNodes )), 713 preferredDoc.childNodes 714 ); 715 // Support: Android<4.0 716 // Detect silently failing push.apply 717 arr[ preferredDoc.childNodes.length ].nodeType; 718} catch ( e ) { 719 push = { apply: arr.length ? 720 721 // Leverage slice if possible 722 function( target, els ) { 723 push_native.apply( target, slice.call(els) ); 724 } : 725 726 // Support: IE<9 727 // Otherwise append directly 728 function( target, els ) { 729 var j = target.length, 730 i = 0; 731 // Can't trust NodeList.length 732 while ( (target[j++] = els[i++]) ) {} 733 target.length = j - 1; 734 } 735 }; 736} 737 738function Sizzle( selector, context, results, seed ) { 739 var m, i, elem, nid, nidselect, match, groups, newSelector, 740 newContext = context && context.ownerDocument, 741 742 // nodeType defaults to 9, since context defaults to document 743 nodeType = context ? context.nodeType : 9; 744 745 results = results || []; 746 747 // Return early from calls with invalid selector or context 748 if ( typeof selector !== "string" || !selector || 749 nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { 750 751 return results; 752 } 753 754 // Try to shortcut find operations (as opposed to filters) in HTML documents 755 if ( !seed ) { 756 757 if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { 758 setDocument( context ); 759 } 760 context = context || document; 761 762 if ( documentIsHTML ) { 763 764 // If the selector is sufficiently simple, try using a "get*By*" DOM method 765 // (excepting DocumentFragment context, where the methods don't exist) 766 if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { 767 768 // ID selector 769 if ( (m = match[1]) ) { 770 771 // Document context 772 if ( nodeType === 9 ) { 773 if ( (elem = context.getElementById( m )) ) { 774 775 // Support: IE, Opera, Webkit 776 // TODO: identify versions 777 // getElementById can match elements by name instead of ID 778 if ( elem.id === m ) { 779 results.push( elem ); 780 return results; 781 } 782 } else { 783 return results; 784 } 785 786 // Element context 787 } else { 788 789 // Support: IE, Opera, Webkit 790 // TODO: identify versions 791 // getElementById can match elements by name instead of ID 792 if ( newContext && (elem = newContext.getElementById( m )) && 793 contains( context, elem ) && 794 elem.id === m ) { 795 796 results.push( elem ); 797 return results; 798 } 799 } 800 801 // Type selector 802 } else if ( match[2] ) { 803 push.apply( results, context.getElementsByTagName( selector ) ); 804 return results; 805 806 // Class selector 807 } else if ( (m = match[3]) && support.getElementsByClassName && 808 context.getElementsByClassName ) { 809 810 push.apply( results, context.getElementsByClassName( m ) ); 811 return results; 812 } 813 } 814 815 // Take advantage of querySelectorAll 816 if ( support.qsa && 817 !compilerCache[ selector + " " ] && 818 (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { 819 820 if ( nodeType !== 1 ) { 821 newContext = context; 822 newSelector = selector; 823 824 // qSA looks outside Element context, which is not what we want 825 // Thanks to Andrew Dupont for this workaround technique 826 // Support: IE <=8 827 // Exclude object elements 828 } else if ( context.nodeName.toLowerCase() !== "object" ) { 829 830 // Capture the context ID, setting it first if necessary 831 if ( (nid = context.getAttribute( "id" )) ) { 832 nid = nid.replace( rescape, "\\$&" ); 833 } else { 834 context.setAttribute( "id", (nid = expando) ); 835 } 836 837 // Prefix every selector in the list 838 groups = tokenize( selector ); 839 i = groups.length; 840 nidselect = ridentifier.test( nid ) ? "#" + nid : "[id='" + nid + "']"; 841 while ( i-- ) { 842 groups[i] = nidselect + " " + toSelector( groups[i] ); 843 } 844 newSelector = groups.join( "," ); 845 846 // Expand context for sibling selectors 847 newContext = rsibling.test( selector ) && testContext( context.parentNode ) || 848 context; 849 } 850 851 if ( newSelector ) { 852 try { 853 push.apply( results, 854 newContext.querySelectorAll( newSelector ) 855 ); 856 return results; 857 } catch ( qsaError ) { 858 } finally { 859 if ( nid === expando ) { 860 context.removeAttribute( "id" ); 861 } 862 } 863 } 864 } 865 } 866 } 867 868 // All others 869 return select( selector.replace( rtrim, "$1" ), context, results, seed ); 870} 871 872/** 873 * Create key-value caches of limited size 874 * @returns {function(string, object)} Returns the Object data after storing it on itself with 875 * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) 876 * deleting the oldest entry 877 */ 878function createCache() { 879 var keys = []; 880 881 function cache( key, value ) { 882 // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) 883 if ( keys.push( key + " " ) > Expr.cacheLength ) { 884 // Only keep the most recent entries 885 delete cache[ keys.shift() ]; 886 } 887 return (cache[ key + " " ] = value); 888 } 889 return cache; 890} 891 892/** 893 * Mark a function for special use by Sizzle 894 * @param {Function} fn The function to mark 895 */ 896function markFunction( fn ) { 897 fn[ expando ] = true; 898 return fn; 899} 900 901/** 902 * Support testing using an element 903 * @param {Function} fn Passed the created div and expects a boolean result 904 */ 905function assert( fn ) { 906 var div = document.createElement("div"); 907 908 try { 909 return !!fn( div ); 910 } catch (e) { 911 return false; 912 } finally { 913 // Remove from its parent by default 914 if ( div.parentNode ) { 915 div.parentNode.removeChild( div ); 916 } 917 // release memory in IE 918 div = null; 919 } 920} 921 922/** 923 * Adds the same handler for all of the specified attrs 924 * @param {String} attrs Pipe-separated list of attributes 925 * @param {Function} handler The method that will be applied 926 */ 927function addHandle( attrs, handler ) { 928 var arr = attrs.split("|"), 929 i = arr.length; 930 931 while ( i-- ) { 932 Expr.attrHandle[ arr[i] ] = handler; 933 } 934} 935 936/** 937 * Checks document order of two siblings 938 * @param {Element} a 939 * @param {Element} b 940 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b 941 */ 942function siblingCheck( a, b ) { 943 var cur = b && a, 944 diff = cur && a.nodeType === 1 && b.nodeType === 1 && 945 ( ~b.sourceIndex || MAX_NEGATIVE ) - 946 ( ~a.sourceIndex || MAX_NEGATIVE ); 947 948 // Use IE sourceIndex if available on both nodes 949 if ( diff ) { 950 return diff; 951 } 952 953 // Check if b follows a 954 if ( cur ) { 955 while ( (cur = cur.nextSibling) ) { 956 if ( cur === b ) { 957 return -1; 958 } 959 } 960 } 961 962 return a ? 1 : -1; 963} 964 965/** 966 * Returns a function to use in pseudos for input types 967 * @param {String} type 968 */ 969function createInputPseudo( type ) { 970 return function( elem ) { 971 var name = elem.nodeName.toLowerCase(); 972 return name === "input" && elem.type === type; 973 }; 974} 975 976/** 977 * Returns a function to use in pseudos for buttons 978 * @param {String} type 979 */ 980function createButtonPseudo( type ) { 981 return function( elem ) { 982 var name = elem.nodeName.toLowerCase(); 983 return (name === "input" || name === "button") && elem.type === type; 984 }; 985} 986 987/** 988 * Returns a function to use in pseudos for positionals 989 * @param {Function} fn 990 */ 991function createPositionalPseudo( fn ) { 992 return markFunction(function( argument ) { 993 argument = +argument; 994 return markFunction(function( seed, matches ) { 995 var j, 996 matchIndexes = fn( [], seed.length, argument ), 997 i = matchIndexes.length; 998 999 // Match elements found at the specified indexes 1000 while ( i-- ) { 1001 if ( seed[ (j = matchIndexes[i]) ] ) { 1002 seed[j] = !(matches[j] = seed[j]); 1003 } 1004 } 1005 }); 1006 }); 1007} 1008 1009/** 1010 * Checks a node for validity as a Sizzle context 1011 * @param {Element|Object=} context 1012 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value 1013 */ 1014function testContext( context ) { 1015 return context && typeof context.getElementsByTagName !== "undefined" && context; 1016} 1017 1018// Expose support vars for convenience 1019support = Sizzle.support = {}; 1020 1021/** 1022 * Detects XML nodes 1023 * @param {Element|Object} elem An element or a document 1024 * @returns {Boolean} True iff elem is a non-HTML XML node 1025 */ 1026isXML = Sizzle.isXML = function( elem ) { 1027 // documentElement is verified for cases where it doesn't yet exist 1028 // (such as loading iframes in IE - #4833) 1029 var documentElement = elem && (elem.ownerDocument || elem).documentElement; 1030 return documentElement ? documentElement.nodeName !== "HTML" : false; 1031}; 1032 1033/** 1034 * Sets document-related variables once based on the current document 1035 * @param {Element|Object} [doc] An element or document object to use to set the document 1036 * @returns {Object} Returns the current document 1037 */ 1038setDocument = Sizzle.setDocument = function( node ) { 1039 var hasCompare, parent, 1040 doc = node ? node.ownerDocument || node : preferredDoc; 1041 1042 // Return early if doc is invalid or already selected 1043 if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { 1044 return document; 1045 } 1046 1047 // Update global variables 1048 document = doc; 1049 docElem = document.documentElement; 1050 documentIsHTML = !isXML( document ); 1051 1052 // Support: IE 9-11, Edge 1053 // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) 1054 if ( (parent = document.defaultView) && parent.top !== parent ) { 1055 // Support: IE 11 1056 if ( parent.addEventListener ) { 1057 parent.addEventListener( "unload", unloadHandler, false ); 1058 1059 // Support: IE 9 - 10 only 1060 } else if ( parent.attachEvent ) { 1061 parent.attachEvent( "onunload", unloadHandler ); 1062 } 1063 } 1064 1065 /* Attributes 1066 ---------------------------------------------------------------------- */ 1067 1068 // Support: IE<8 1069 // Verify that getAttribute really returns attributes and not properties 1070 // (excepting IE8 booleans) 1071 support.attributes = assert(function( div ) { 1072 div.className = "i"; 1073 return !div.getAttribute("className"); 1074 }); 1075 1076 /* getElement(s)By* 1077 ---------------------------------------------------------------------- */ 1078 1079 // Check if getElementsByTagName("*") returns only elements 1080 support.getElementsByTagName = assert(function( div ) { 1081 div.appendChild( document.createComment("") ); 1082 return !div.getElementsByTagName("*").length; 1083 }); 1084 1085 // Support: IE<9 1086 support.getElementsByClassName = rnative.test( document.getElementsByClassName ); 1087 1088 // Support: IE<10 1089 // Check if getElementById returns elements by name 1090 // The broken getElementById methods don't pick up programatically-set names, 1091 // so use a roundabout getElementsByName test 1092 support.getById = assert(function( div ) { 1093 docElem.appendChild( div ).id = expando; 1094 return !document.getElementsByName || !document.getElementsByName( expando ).length; 1095 }); 1096 1097 // ID find and filter 1098 if ( support.getById ) { 1099 Expr.find["ID"] = function( id, context ) { 1100 if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { 1101 var m = context.getElementById( id ); 1102 return m ? [ m ] : []; 1103 } 1104 }; 1105 Expr.filter["ID"] = function( id ) { 1106 var attrId = id.replace( runescape, funescape ); 1107 return function( elem ) { 1108 return elem.getAttribute("id") === attrId; 1109 }; 1110 }; 1111 } else { 1112 // Support: IE6/7 1113 // getElementById is not reliable as a find shortcut 1114 delete Expr.find["ID"]; 1115 1116 Expr.filter["ID"] = function( id ) { 1117 var attrId = id.replace( runescape, funescape ); 1118 return function( elem ) { 1119 var node = typeof elem.getAttributeNode !== "undefined" && 1120 elem.getAttributeNode("id"); 1121 return node && node.value === attrId; 1122 }; 1123 }; 1124 } 1125 1126 // Tag 1127 Expr.find["TAG"] = support.getElementsByTagName ? 1128 function( tag, context ) { 1129 if ( typeof context.getElementsByTagName !== "undefined" ) { 1130 return context.getElementsByTagName( tag ); 1131 1132 // DocumentFragment nodes don't have gEBTN 1133 } else if ( support.qsa ) { 1134 return context.querySelectorAll( tag ); 1135 } 1136 } : 1137 1138 function( tag, context ) { 1139 var elem, 1140 tmp = [], 1141 i = 0, 1142 // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too 1143 results = context.getElementsByTagName( tag ); 1144 1145 // Filter out possible comments 1146 if ( tag === "*" ) { 1147 while ( (elem = results[i++]) ) { 1148 if ( elem.nodeType === 1 ) { 1149 tmp.push( elem ); 1150 } 1151 } 1152 1153 return tmp; 1154 } 1155 return results; 1156 }; 1157 1158 // Class 1159 Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { 1160 if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { 1161 return context.getElementsByClassName( className ); 1162 } 1163 }; 1164 1165 /* QSA/matchesSelector 1166 ---------------------------------------------------------------------- */ 1167 1168 // QSA and matchesSelector support 1169 1170 // matchesSelector(:active) reports false when true (IE9/Opera 11.5) 1171 rbuggyMatches = []; 1172 1173 // qSa(:focus) reports false when true (Chrome 21) 1174 // We allow this because of a bug in IE8/9 that throws an error 1175 // whenever `document.activeElement` is accessed on an iframe 1176 // So, we allow :focus to pass through QSA all the time to avoid the IE error 1177 // See http://bugs.jquery.com/ticket/13378 1178 rbuggyQSA = []; 1179 1180 if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { 1181 // Build QSA regex 1182 // Regex strategy adopted from Diego Perini 1183 assert(function( div ) { 1184 // Select is set to empty string on purpose 1185 // This is to test IE's treatment of not explicitly 1186 // setting a boolean content attribute, 1187 // since its presence should be enough 1188 // http://bugs.jquery.com/ticket/12359 1189 docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" + 1190 "<select id='" + expando + "-\r\\' msallowcapture=''>" + 1191 "<option selected=''></option></select>"; 1192 1193 // Support: IE8, Opera 11-12.16 1194 // Nothing should be selected when empty strings follow ^= or $= or *= 1195 // The test attribute must be unknown in Opera but "safe" for WinRT 1196 // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section 1197 if ( div.querySelectorAll("[msallowcapture^='']").length ) { 1198 rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); 1199 } 1200 1201 // Support: IE8 1202 // Boolean attributes and "value" are not treated correctly 1203 if ( !div.querySelectorAll("[selected]").length ) { 1204 rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); 1205 } 1206 1207 // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ 1208 if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) { 1209 rbuggyQSA.push("~="); 1210 } 1211 1212 // Webkit/Opera - :checked should return selected option elements 1213 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked 1214 // IE8 throws error here and will not see later tests 1215 if ( !div.querySelectorAll(":checked").length ) { 1216 rbuggyQSA.push(":checked"); 1217 } 1218 1219 // Support: Safari 8+, iOS 8+ 1220 // https://bugs.webkit.org/show_bug.cgi?id=136851 1221 // In-page `selector#id sibing-combinator selector` fails 1222 if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) { 1223 rbuggyQSA.push(".#.+[+~]"); 1224 } 1225 }); 1226 1227 assert(function( div ) { 1228 // Support: Windows 8 Native Apps 1229 // The type and name attributes are restricted during .innerHTML assignment 1230 var input = document.createElement("input"); 1231 input.setAttribute( "type", "hidden" ); 1232 div.appendChild( input ).setAttribute( "name", "D" ); 1233 1234 // Support: IE8 1235 // Enforce case-sensitivity of name attribute 1236 if ( div.querySelectorAll("[name=d]").length ) { 1237 rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); 1238 } 1239 1240 // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) 1241 // IE8 throws error here and will not see later tests 1242 if ( !div.querySelectorAll(":enabled").length ) { 1243 rbuggyQSA.push( ":enabled", ":disabled" ); 1244 } 1245 1246 // Opera 10-11 does not throw on post-comma invalid pseudos 1247 div.querySelectorAll("*,:x"); 1248 rbuggyQSA.push(",.*:"); 1249 }); 1250 } 1251 1252 if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || 1253 docElem.webkitMatchesSelector || 1254 docElem.mozMatchesSelector || 1255 docElem.oMatchesSelector || 1256 docElem.msMatchesSelector) )) ) { 1257 1258 assert(function( div ) { 1259 // Check to see if it's possible to do matchesSelector 1260 // on a disconnected node (IE 9) 1261 support.disconnectedMatch = matches.call( div, "div" ); 1262 1263 // This should fail with an exception 1264 // Gecko does not error, returns false instead 1265 matches.call( div, "[s!='']:x" ); 1266 rbuggyMatches.push( "!=", pseudos ); 1267 }); 1268 } 1269 1270 rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); 1271 rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); 1272 1273 /* Contains 1274 ---------------------------------------------------------------------- */ 1275 hasCompare = rnative.test( docElem.compareDocumentPosition ); 1276 1277 // Element contains another 1278 // Purposefully self-exclusive 1279 // As in, an element does not contain itself 1280 contains = hasCompare || rnative.test( docElem.contains ) ? 1281 function( a, b ) { 1282 var adown = a.nodeType === 9 ? a.documentElement : a, 1283 bup = b && b.parentNode; 1284 return a === bup || !!( bup && bup.nodeType === 1 && ( 1285 adown.contains ? 1286 adown.contains( bup ) : 1287 a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 1288 )); 1289 } : 1290 function( a, b ) { 1291 if ( b ) { 1292 while ( (b = b.parentNode) ) { 1293 if ( b === a ) { 1294 return true; 1295 } 1296 } 1297 } 1298 return false; 1299 }; 1300 1301 /* Sorting 1302 ---------------------------------------------------------------------- */ 1303 1304 // Document order sorting 1305 sortOrder = hasCompare ? 1306 function( a, b ) { 1307 1308 // Flag for duplicate removal 1309 if ( a === b ) { 1310 hasDuplicate = true; 1311 return 0; 1312 } 1313 1314 // Sort on method existence if only one input has compareDocumentPosition 1315 var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; 1316 if ( compare ) { 1317 return compare; 1318 } 1319 1320 // Calculate position if both inputs belong to the same document 1321 compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? 1322 a.compareDocumentPosition( b ) : 1323 1324 // Otherwise we know they are disconnected 1325 1; 1326 1327 // Disconnected nodes 1328 if ( compare & 1 || 1329 (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { 1330 1331 // Choose the first element that is related to our preferred document 1332 if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { 1333 return -1; 1334 } 1335 if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { 1336 return 1; 1337 } 1338 1339 // Maintain original order 1340 return sortInput ? 1341 ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : 1342 0; 1343 } 1344 1345 return compare & 4 ? -1 : 1; 1346 } : 1347 function( a, b ) { 1348 // Exit early if the nodes are identical 1349 if ( a === b ) { 1350 hasDuplicate = true; 1351 return 0; 1352 } 1353 1354 var cur, 1355 i = 0, 1356 aup = a.parentNode, 1357 bup = b.parentNode, 1358 ap = [ a ], 1359 bp = [ b ]; 1360 1361 // Parentless nodes are either documents or disconnected 1362 if ( !aup || !bup ) { 1363 return a === document ? -1 : 1364 b === document ? 1 : 1365 aup ? -1 : 1366 bup ? 1 : 1367 sortInput ? 1368 ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : 1369 0; 1370 1371 // If the nodes are siblings, we can do a quick check 1372 } else if ( aup === bup ) { 1373 return siblingCheck( a, b ); 1374 } 1375 1376 // Otherwise we need full lists of their ancestors for comparison 1377 cur = a; 1378 while ( (cur = cur.parentNode) ) { 1379 ap.unshift( cur ); 1380 } 1381 cur = b; 1382 while ( (cur = cur.parentNode) ) { 1383 bp.unshift( cur ); 1384 } 1385 1386 // Walk down the tree looking for a discrepancy 1387 while ( ap[i] === bp[i] ) { 1388 i++; 1389 } 1390 1391 return i ? 1392 // Do a sibling check if the nodes have a common ancestor 1393 siblingCheck( ap[i], bp[i] ) : 1394 1395 // Otherwise nodes in our document sort first 1396 ap[i] === preferredDoc ? -1 : 1397 bp[i] === preferredDoc ? 1 : 1398 0; 1399 }; 1400 1401 return document; 1402}; 1403 1404Sizzle.matches = function( expr, elements ) { 1405 return Sizzle( expr, null, null, elements ); 1406}; 1407 1408Sizzle.matchesSelector = function( elem, expr ) { 1409 // Set document vars if needed 1410 if ( ( elem.ownerDocument || elem ) !== document ) { 1411 setDocument( elem ); 1412 } 1413 1414 // Make sure that attribute selectors are quoted 1415 expr = expr.replace( rattributeQuotes, "='$1']" ); 1416 1417 if ( support.matchesSelector && documentIsHTML && 1418 !compilerCache[ expr + " " ] && 1419 ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && 1420 ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { 1421 1422 try { 1423 var ret = matches.call( elem, expr ); 1424 1425 // IE 9's matchesSelector returns false on disconnected nodes 1426 if ( ret || support.disconnectedMatch || 1427 // As well, disconnected nodes are said to be in a document 1428 // fragment in IE 9 1429 elem.document && elem.document.nodeType !== 11 ) { 1430 return ret; 1431 } 1432 } catch (e) {} 1433 } 1434 1435 return Sizzle( expr, document, null, [ elem ] ).length > 0; 1436}; 1437 1438Sizzle.contains = function( context, elem ) { 1439 // Set document vars if needed 1440 if ( ( context.ownerDocument || context ) !== document ) { 1441 setDocument( context ); 1442 } 1443 return contains( context, elem ); 1444}; 1445 1446Sizzle.attr = function( elem, name ) { 1447 // Set document vars if needed 1448 if ( ( elem.ownerDocument || elem ) !== document ) { 1449 setDocument( elem ); 1450 } 1451 1452 var fn = Expr.attrHandle[ name.toLowerCase() ], 1453 // Don't get fooled by Object.prototype properties (jQuery #13807) 1454 val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? 1455 fn( elem, name, !documentIsHTML ) : 1456 undefined; 1457 1458 return val !== undefined ? 1459 val : 1460 support.attributes || !documentIsHTML ? 1461 elem.getAttribute( name ) : 1462 (val = elem.getAttributeNode(name)) && val.specified ? 1463 val.value : 1464 null; 1465}; 1466 1467Sizzle.error = function( msg ) { 1468 throw new Error( "Syntax error, unrecognized expression: " + msg ); 1469}; 1470 1471/** 1472 * Document sorting and removing duplicates 1473 * @param {ArrayLike} results 1474 */ 1475Sizzle.uniqueSort = function( results ) { 1476 var elem, 1477 duplicates = [], 1478 j = 0, 1479 i = 0; 1480 1481 // Unless we *know* we can detect duplicates, assume their presence 1482 hasDuplicate = !support.detectDuplicates; 1483 sortInput = !support.sortStable && results.slice( 0 ); 1484 results.sort( sortOrder ); 1485 1486 if ( hasDuplicate ) { 1487 while ( (elem = results[i++]) ) { 1488 if ( elem === results[ i ] ) { 1489 j = duplicates.push( i ); 1490 } 1491 } 1492 while ( j-- ) { 1493 results.splice( duplicates[ j ], 1 ); 1494 } 1495 } 1496 1497 // Clear input after sorting to release objects 1498 // See https://github.com/jquery/sizzle/pull/225 1499 sortInput = null; 1500 1501 return results; 1502}; 1503 1504/** 1505 * Utility function for retrieving the text value of an array of DOM nodes 1506 * @param {Array|Element} elem 1507 */ 1508getText = Sizzle.getText = function( elem ) { 1509 var node, 1510 ret = "", 1511 i = 0, 1512 nodeType = elem.nodeType; 1513 1514 if ( !nodeType ) { 1515 // If no nodeType, this is expected to be an array 1516 while ( (node = elem[i++]) ) { 1517 // Do not traverse comment nodes 1518 ret += getText( node ); 1519 } 1520 } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { 1521 // Use textContent for elements 1522 // innerText usage removed for consistency of new lines (jQuery #11153) 1523 if ( typeof elem.textContent === "string" ) { 1524 return elem.textContent; 1525 } else { 1526 // Traverse its children 1527 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { 1528 ret += getText( elem ); 1529 } 1530 } 1531 } else if ( nodeType === 3 || nodeType === 4 ) { 1532 return elem.nodeValue; 1533 } 1534 // Do not include comment or processing instruction nodes 1535 1536 return ret; 1537}; 1538 1539Expr = Sizzle.selectors = { 1540 1541 // Can be adjusted by the user 1542 cacheLength: 50, 1543 1544 createPseudo: markFunction, 1545 1546 match: matchExpr, 1547 1548 attrHandle: {}, 1549 1550 find: {}, 1551 1552 relative: { 1553 ">": { dir: "parentNode", first: true }, 1554 " ": { dir: "parentNode" }, 1555 "+": { dir: "previousSibling", first: true }, 1556 "~": { dir: "previousSibling" } 1557 }, 1558 1559 preFilter: { 1560 "ATTR": function( match ) { 1561 match[1] = match[1].replace( runescape, funescape ); 1562 1563 // Move the given value to match[3] whether quoted or unquoted 1564 match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); 1565 1566 if ( match[2] === "~=" ) { 1567 match[3] = " " + match[3] + " "; 1568 } 1569 1570 return match.slice( 0, 4 ); 1571 }, 1572 1573 "CHILD": function( match ) { 1574 /* matches from matchExpr["CHILD"] 1575 1 type (only|nth|...) 1576 2 what (child|of-type) 1577 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) 1578 4 xn-component of xn+y argument ([+-]?\d*n|) 1579 5 sign of xn-component 1580 6 x of xn-component 1581 7 sign of y-component 1582 8 y of y-component 1583 */ 1584 match[1] = match[1].toLowerCase(); 1585 1586 if ( match[1].slice( 0, 3 ) === "nth" ) { 1587 // nth-* requires argument 1588 if ( !match[3] ) { 1589 Sizzle.error( match[0] ); 1590 } 1591 1592 // numeric x and y parameters for Expr.filter.CHILD 1593 // remember that false/true cast respectively to 0/1 1594 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); 1595 match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); 1596 1597 // other types prohibit arguments 1598 } else if ( match[3] ) { 1599 Sizzle.error( match[0] ); 1600 } 1601 1602 return match; 1603 }, 1604 1605 "PSEUDO": function( match ) { 1606 var excess, 1607 unquoted = !match[6] && match[2]; 1608 1609 if ( matchExpr["CHILD"].test( match[0] ) ) { 1610 return null; 1611 } 1612 1613 // Accept quoted arguments as-is 1614 if ( match[3] ) { 1615 match[2] = match[4] || match[5] || ""; 1616 1617 // Strip excess characters from unquoted arguments 1618 } else if ( unquoted && rpseudo.test( unquoted ) && 1619 // Get excess from tokenize (recursively) 1620 (excess = tokenize( unquoted, true )) && 1621 // advance to the next closing parenthesis 1622 (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { 1623 1624 // excess is a negative index 1625 match[0] = match[0].slice( 0, excess ); 1626 match[2] = unquoted.slice( 0, excess ); 1627 } 1628 1629 // Return only captures needed by the pseudo filter method (type and argument) 1630 return match.slice( 0, 3 ); 1631 } 1632 }, 1633 1634 filter: { 1635 1636 "TAG": function( nodeNameSelector ) { 1637 var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); 1638 return nodeNameSelector === "*" ? 1639 function() { return true; } : 1640 function( elem ) { 1641 return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; 1642 }; 1643 }, 1644 1645 "CLASS": function( className ) { 1646 var pattern = classCache[ className + " " ]; 1647 1648 return pattern || 1649 (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && 1650 classCache( className, function( elem ) { 1651 return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); 1652 }); 1653 }, 1654 1655 "ATTR": function( name, operator, check ) { 1656 return function( elem ) { 1657 var result = Sizzle.attr( elem, name ); 1658 1659 if ( result == null ) { 1660 return operator === "!="; 1661 } 1662 if ( !operator ) { 1663 return true; 1664 } 1665 1666 result += ""; 1667 1668 return operator === "=" ? result === check : 1669 operator === "!=" ? result !== check : 1670 operator === "^=" ? check && result.indexOf( check ) === 0 : 1671 operator === "*=" ? check && result.indexOf( check ) > -1 : 1672 operator === "$=" ? check && result.slice( -check.length ) === check : 1673 operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : 1674 operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : 1675 false; 1676 }; 1677 }, 1678 1679 "CHILD": function( type, what, argument, first, last ) { 1680 var simple = type.slice( 0, 3 ) !== "nth", 1681 forward = type.slice( -4 ) !== "last", 1682 ofType = what === "of-type"; 1683 1684 return first === 1 && last === 0 ? 1685 1686 // Shortcut for :nth-*(n) 1687 function( elem ) { 1688 return !!elem.parentNode; 1689 } : 1690 1691 function( elem, context, xml ) { 1692 var cache, uniqueCache, outerCache, node, nodeIndex, start, 1693 dir = simple !== forward ? "nextSibling" : "previousSibling", 1694 parent = elem.parentNode, 1695 name = ofType && elem.nodeName.toLowerCase(), 1696 useCache = !xml && !ofType, 1697 diff = false; 1698 1699 if ( parent ) { 1700 1701 // :(first|last|only)-(child|of-type) 1702 if ( simple ) { 1703 while ( dir ) { 1704 node = elem; 1705 while ( (node = node[ dir ]) ) { 1706 if ( ofType ? 1707 node.nodeName.toLowerCase() === name : 1708 node.nodeType === 1 ) { 1709 1710 return false; 1711 } 1712 } 1713 // Reverse direction for :only-* (if we haven't yet done so) 1714 start = dir = type === "only" && !start && "nextSibling"; 1715 } 1716 return true; 1717 } 1718 1719 start = [ forward ? parent.firstChild : parent.lastChild ]; 1720 1721 // non-xml :nth-child(...) stores cache data on `parent` 1722 if ( forward && useCache ) { 1723 1724 // Seek `elem` from a previously-cached index 1725 1726 // ...in a gzip-friendly way 1727 node = parent; 1728 outerCache = node[ expando ] || (node[ expando ] = {}); 1729 1730 // Support: IE <9 only 1731 // Defend against cloned attroperties (jQuery gh-1709) 1732 uniqueCache = outerCache[ node.uniqueID ] || 1733 (outerCache[ node.uniqueID ] = {}); 1734 1735 cache = uniqueCache[ type ] || []; 1736 nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; 1737 diff = nodeIndex && cache[ 2 ]; 1738 node = nodeIndex && parent.childNodes[ nodeIndex ]; 1739 1740 while ( (node = ++nodeIndex && node && node[ dir ] || 1741 1742 // Fallback to seeking `elem` from the start 1743 (diff = nodeIndex = 0) || start.pop()) ) { 1744 1745 // When found, cache indexes on `parent` and break 1746 if ( node.nodeType === 1 && ++diff && node === elem ) { 1747 uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; 1748 break; 1749 } 1750 } 1751 1752 } else { 1753 // Use previously-cached element index if available 1754 if ( useCache ) { 1755 // ...in a gzip-friendly way 1756 node = elem; 1757 outerCache = node[ expando ] || (node[ expando ] = {}); 1758 1759 // Support: IE <9 only 1760 // Defend against cloned attroperties (jQuery gh-1709) 1761 uniqueCache = outerCache[ node.uniqueID ] || 1762 (outerCache[ node.uniqueID ] = {}); 1763 1764 cache = uniqueCache[ type ] || []; 1765 nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; 1766 diff = nodeIndex; 1767 } 1768 1769 // xml :nth-child(...) 1770 // or :nth-last-child(...) or :nth(-last)?-of-type(...) 1771 if ( diff === false ) { 1772 // Use the same loop as above to seek `elem` from the start 1773 while ( (node = ++nodeIndex && node && node[ dir ] || 1774 (diff = nodeIndex = 0) || start.pop()) ) { 1775 1776 if ( ( ofType ? 1777 node.nodeName.toLowerCase() === name : 1778 node.nodeType === 1 ) && 1779 ++diff ) { 1780 1781 // Cache the index of each encountered element 1782 if ( useCache ) { 1783 outerCache = node[ expando ] || (node[ expando ] = {}); 1784 1785 // Support: IE <9 only 1786 // Defend against cloned attroperties (jQuery gh-1709) 1787 uniqueCache = outerCache[ node.uniqueID ] || 1788 (outerCache[ node.uniqueID ] = {}); 1789 1790 uniqueCache[ type ] = [ dirruns, diff ]; 1791 } 1792 1793 if ( node === elem ) { 1794 break; 1795 } 1796 } 1797 } 1798 } 1799 } 1800 1801 // Incorporate the offset, then check against cycle size 1802 diff -= last; 1803 return diff === first || ( diff % first === 0 && diff / first >= 0 ); 1804 } 1805 }; 1806 }, 1807 1808 "PSEUDO": function( pseudo, argument ) { 1809 // pseudo-class names are case-insensitive 1810 // http://www.w3.org/TR/selectors/#pseudo-classes 1811 // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters 1812 // Remember that setFilters inherits from pseudos 1813 var args, 1814 fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || 1815 Sizzle.error( "unsupported pseudo: " + pseudo ); 1816 1817 // The user may use createPseudo to indicate that 1818 // arguments are needed to create the filter function 1819 // just as Sizzle does 1820 if ( fn[ expando ] ) { 1821 return fn( argument ); 1822 } 1823 1824 // But maintain support for old signatures 1825 if ( fn.length > 1 ) { 1826 args = [ pseudo, pseudo, "", argument ]; 1827 return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? 1828 markFunction(function( seed, matches ) { 1829 var idx, 1830 matched = fn( seed, argument ), 1831 i = matched.length; 1832 while ( i-- ) { 1833 idx = indexOf( seed, matched[i] ); 1834 seed[ idx ] = !( matches[ idx ] = matched[i] ); 1835 } 1836 }) : 1837 function( elem ) { 1838 return fn( elem, 0, args ); 1839 }; 1840 } 1841 1842 return fn; 1843 } 1844 }, 1845 1846 pseudos: { 1847 // Potentially complex pseudos 1848 "not": markFunction(function( selector ) { 1849 // Trim the selector passed to compile 1850 // to avoid treating leading and trailing 1851 // spaces as combinators 1852 var input = [], 1853 results = [], 1854 matcher = compile( selector.replace( rtrim, "$1" ) ); 1855 1856 return matcher[ expando ] ? 1857 markFunction(function( seed, matches, context, xml ) { 1858 var elem, 1859 unmatched = matcher( seed, null, xml, [] ), 1860 i = seed.length; 1861 1862 // Match elements unmatched by `matcher` 1863 while ( i-- ) { 1864 if ( (elem = unmatched[i]) ) { 1865 seed[i] = !(matches[i] = elem); 1866 } 1867 } 1868 }) : 1869 function( elem, context, xml ) { 1870 input[0] = elem; 1871 matcher( input, null, xml, results ); 1872 // Don't keep the element (issue #299) 1873 input[0] = null; 1874 return !results.pop(); 1875 }; 1876 }), 1877 1878 "has": markFunction(function( selector ) { 1879 return function( elem ) { 1880 return Sizzle( selector, elem ).length > 0; 1881 }; 1882 }), 1883 1884 "contains": markFunction(function( text ) { 1885 text = text.replace( runescape, funescape ); 1886 return function( elem ) { 1887 return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; 1888 }; 1889 }), 1890 1891 // "Whether an element is represented by a :lang() selector 1892 // is based solely on the element's language value 1893 // being equal to the identifier C, 1894 // or beginning with the identifier C immediately followed by "-". 1895 // The matching of C against the element's language value is performed case-insensitively. 1896 // The identifier C does not have to be a valid language name." 1897 // http://www.w3.org/TR/selectors/#lang-pseudo 1898 "lang": markFunction( function( lang ) { 1899 // lang value must be a valid identifier 1900 if ( !ridentifier.test(lang || "") ) { 1901 Sizzle.error( "unsupported lang: " + lang ); 1902 } 1903 lang = lang.replace( runescape, funescape ).toLowerCase(); 1904 return function( elem ) { 1905 var elemLang; 1906 do { 1907 if ( (elemLang = documentIsHTML ? 1908 elem.lang : 1909 elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { 1910 1911 elemLang = elemLang.toLowerCase(); 1912 return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; 1913 } 1914 } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); 1915 return false; 1916 }; 1917 }), 1918 1919 // Miscellaneous 1920 "target": function( elem ) { 1921 var hash = window.location && window.location.hash; 1922 return hash && hash.slice( 1 ) === elem.id; 1923 }, 1924 1925 "root": function( elem ) { 1926 return elem === docElem; 1927 }, 1928 1929 "focus": function( elem ) { 1930 return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); 1931 }, 1932 1933 // Boolean properties 1934 "enabled": function( elem ) { 1935 return elem.disabled === false; 1936 }, 1937 1938 "disabled": function( elem ) { 1939 return elem.disabled === true; 1940 }, 1941 1942 "checked": function( elem ) { 1943 // In CSS3, :checked should return both checked and selected elements 1944 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked 1945 var nodeName = elem.nodeName.toLowerCase(); 1946 return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); 1947 }, 1948 1949 "selected": function( elem ) { 1950 // Accessing this property makes selected-by-default 1951 // options in Safari work properly 1952 if ( elem.parentNode ) { 1953 elem.parentNode.selectedIndex; 1954 } 1955 1956 return elem.selected === true; 1957 }, 1958 1959 // Contents 1960 "empty": function( elem ) { 1961 // http://www.w3.org/TR/selectors/#empty-pseudo 1962 // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), 1963 // but not by others (comment: 8; processing instruction: 7; etc.) 1964 // nodeType < 6 works because attributes (2) do not appear as children 1965 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { 1966 if ( elem.nodeType < 6 ) { 1967 return false; 1968 } 1969 } 1970 return true; 1971 }, 1972 1973 "parent": function( elem ) { 1974 return !Expr.pseudos["empty"]( elem ); 1975 }, 1976 1977 // Element/input types 1978 "header": function( elem ) { 1979 return rheader.test( elem.nodeName ); 1980 }, 1981 1982 "input": function( elem ) { 1983 return rinputs.test( elem.nodeName ); 1984 }, 1985 1986 "button": function( elem ) { 1987 var name = elem.nodeName.toLowerCase(); 1988 return name === "input" && elem.type === "button" || name === "button"; 1989 }, 1990 1991 "text": function( elem ) { 1992 var attr; 1993 return elem.nodeName.toLowerCase() === "input" && 1994 elem.type === "text" && 1995 1996 // Support: IE<8 1997 // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" 1998 ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); 1999 }, 2000 2001 // Position-in-collection 2002 "first": createPositionalPseudo(function() { 2003 return [ 0 ]; 2004 }), 2005 2006 "last": createPositionalPseudo(function( matchIndexes, length ) { 2007 return [ length - 1 ]; 2008 }), 2009 2010 "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { 2011 return [ argument < 0 ? argument + length : argument ]; 2012 }), 2013 2014 "even": createPositionalPseudo(function( matchIndexes, length ) { 2015 var i = 0; 2016 for ( ; i < length; i += 2 ) { 2017 matchIndexes.push( i ); 2018 } 2019 return matchIndexes; 2020 }), 2021 2022 "odd": createPositionalPseudo(function( matchIndexes, length ) { 2023 var i = 1; 2024 for ( ; i < length; i += 2 ) { 2025 matchIndexes.push( i ); 2026 } 2027 return matchIndexes; 2028 }), 2029 2030 "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { 2031 var i = argument < 0 ? argument + length : argument; 2032 for ( ; --i >= 0; ) { 2033 matchIndexes.push( i ); 2034 } 2035 return matchIndexes; 2036 }), 2037 2038 "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { 2039 var i = argument < 0 ? argument + length : argument; 2040 for ( ; ++i < length; ) { 2041 matchIndexes.push( i ); 2042 } 2043 return matchIndexes; 2044 }) 2045 } 2046}; 2047 2048Expr.pseudos["nth"] = Expr.pseudos["eq"]; 2049 2050// Add button/input type pseudos 2051for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { 2052 Expr.pseudos[ i ] = createInputPseudo( i ); 2053} 2054for ( i in { submit: true, reset: true } ) { 2055 Expr.pseudos[ i ] = createButtonPseudo( i ); 2056} 2057 2058// Easy API for creating new setFilters 2059function setFilters() {} 2060setFilters.prototype = Expr.filters = Expr.pseudos; 2061Expr.setFilters = new setFilters(); 2062 2063tokenize = Sizzle.tokenize = function( selector, parseOnly ) { 2064 var matched, match, tokens, type, 2065 soFar, groups, preFilters, 2066 cached = tokenCache[ selector + " " ]; 2067 2068 if ( cached ) { 2069 return parseOnly ? 0 : cached.slice( 0 ); 2070 } 2071 2072 soFar = selector; 2073 groups = []; 2074 preFilters = Expr.preFilter; 2075 2076 while ( soFar ) { 2077 2078 // Comma and first run 2079 if ( !matched || (match = rcomma.exec( soFar )) ) { 2080 if ( match ) { 2081 // Don't consume trailing commas as valid 2082 soFar = soFar.slice( match[0].length ) || soFar; 2083 } 2084 groups.push( (tokens = []) ); 2085 } 2086 2087 matched = false; 2088 2089 // Combinators 2090 if ( (match = rcombinators.exec( soFar )) ) { 2091 matched = match.shift(); 2092 tokens.push({ 2093 value: matched, 2094 // Cast descendant combinators to space 2095 type: match[0].replace( rtrim, " " ) 2096 }); 2097 soFar = soFar.slice( matched.length ); 2098 } 2099 2100 // Filters 2101 for ( type in Expr.filter ) { 2102 if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || 2103 (match = preFilters[ type ]( match ))) ) { 2104 matched = match.shift(); 2105 tokens.push({ 2106 value: matched, 2107 type: type, 2108 matches: match 2109 }); 2110 soFar = soFar.slice( matched.length ); 2111 } 2112 } 2113 2114 if ( !matched ) { 2115 break; 2116 } 2117 } 2118 2119 // Return the length of the invalid excess 2120 // if we're just parsing 2121 // Otherwise, throw an error or return tokens 2122 return parseOnly ? 2123 soFar.length : 2124 soFar ? 2125 Sizzle.error( selector ) : 2126 // Cache the tokens 2127 tokenCache( selector, groups ).slice( 0 ); 2128}; 2129 2130function toSelector( tokens ) { 2131 var i = 0, 2132 len = tokens.length, 2133 selector = ""; 2134 for ( ; i < len; i++ ) { 2135 selector += tokens[i].value; 2136 } 2137 return selector; 2138} 2139 2140function addCombinator( matcher, combinator, base ) { 2141 var dir = combinator.dir, 2142 checkNonElements = base && dir === "parentNode", 2143 doneName = done++; 2144 2145 return combinator.first ? 2146 // Check against closest ancestor/preceding element 2147 function( elem, context, xml ) { 2148 while ( (elem = elem[ dir ]) ) { 2149 if ( elem.nodeType === 1 || checkNonElements ) { 2150 return matcher( elem, context, xml ); 2151 } 2152 } 2153 } : 2154 2155 // Check against all ancestor/preceding elements 2156 function( elem, context, xml ) { 2157 var oldCache, uniqueCache, outerCache, 2158 newCache = [ dirruns, doneName ]; 2159 2160 // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching 2161 if ( xml ) { 2162 while ( (elem = elem[ dir ]) ) { 2163 if ( elem.nodeType === 1 || checkNonElements ) { 2164 if ( matcher( elem, context, xml ) ) { 2165 return true; 2166 } 2167 } 2168 } 2169 } else { 2170 while ( (elem = elem[ dir ]) ) { 2171 if ( elem.nodeType === 1 || checkNonElements ) { 2172 outerCache = elem[ expando ] || (elem[ expando ] = {}); 2173 2174 // Support: IE <9 only 2175 // Defend against cloned attroperties (jQuery gh-1709) 2176 uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); 2177 2178 if ( (oldCache = uniqueCache[ dir ]) && 2179 oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { 2180 2181 // Assign to newCache so results back-propagate to previous elements 2182 return (newCache[ 2 ] = oldCache[ 2 ]); 2183 } else { 2184 // Reuse newcache so results back-propagate to previous elements 2185 uniqueCache[ dir ] = newCache; 2186 2187 // A match means we're done; a fail means we have to keep checking 2188 if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { 2189 return true; 2190 } 2191 } 2192 } 2193 } 2194 } 2195 }; 2196} 2197 2198function elementMatcher( matchers ) { 2199 return matchers.length > 1 ? 2200 function( elem, context, xml ) { 2201 var i = matchers.length; 2202 while ( i-- ) { 2203 if ( !matchers[i]( elem, context, xml ) ) { 2204 return false; 2205 } 2206 } 2207 return true; 2208 } : 2209 matchers[0]; 2210} 2211 2212function multipleContexts( selector, contexts, results ) { 2213 var i = 0, 2214 len = contexts.length; 2215 for ( ; i < len; i++ ) { 2216 Sizzle( selector, contexts[i], results ); 2217 } 2218 return results; 2219} 2220 2221function condense( unmatched, map, filter, context, xml ) { 2222 var elem, 2223 newUnmatched = [], 2224 i = 0, 2225 len = unmatched.length, 2226 mapped = map != null; 2227 2228 for ( ; i < len; i++ ) { 2229 if ( (elem = unmatched[i]) ) { 2230 if ( !filter || filter( elem, context, xml ) ) { 2231 newUnmatched.push( elem ); 2232 if ( mapped ) { 2233 map.push( i ); 2234 } 2235 } 2236 } 2237 } 2238 2239 return newUnmatched; 2240} 2241 2242function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { 2243 if ( postFilter && !postFilter[ expando ] ) { 2244 postFilter = setMatcher( postFilter ); 2245 } 2246 if ( postFinder && !postFinder[ expando ] ) { 2247 postFinder = setMatcher( postFinder, postSelector ); 2248 } 2249 return markFunction(function( seed, results, context, xml ) { 2250 var temp, i, elem, 2251 preMap = [], 2252 postMap = [], 2253 preexisting = results.length, 2254 2255 // Get initial elements from seed or context 2256 elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), 2257 2258 // Prefilter to get matcher input, preserving a map for seed-results synchronization 2259 matcherIn = preFilter && ( seed || !selector ) ? 2260 condense( elems, preMap, preFilter, context, xml ) : 2261 elems, 2262 2263 matcherOut = matcher ? 2264 // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, 2265 postFinder || ( seed ? preFilter : preexisting || postFilter ) ? 2266 2267 // ...intermediate processing is necessary 2268 [] : 2269 2270 // ...otherwise use results directly 2271 results : 2272 matcherIn; 2273 2274 // Find primary matches 2275 if ( matcher ) { 2276 matcher( matcherIn, matcherOut, context, xml ); 2277 } 2278 2279 // Apply postFilter 2280 if ( postFilter ) { 2281 temp = condense( matcherOut, postMap ); 2282 postFilter( temp, [], context, xml ); 2283 2284 // Un-match failing elements by moving them back to matcherIn 2285 i = temp.length; 2286 while ( i-- ) { 2287 if ( (elem = temp[i]) ) { 2288 matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); 2289 } 2290 } 2291 } 2292 2293 if ( seed ) { 2294 if ( postFinder || preFilter ) { 2295 if ( postFinder ) { 2296 // Get the final matcherOut by condensing this intermediate into postFinder contexts 2297 temp = []; 2298 i = matcherOut.length; 2299 while ( i-- ) { 2300 if ( (elem = matcherOut[i]) ) { 2301 // Restore matcherIn since elem is not yet a final match 2302 temp.push( (matcherIn[i] = elem) ); 2303 } 2304 } 2305 postFinder( null, (matcherOut = []), temp, xml ); 2306 } 2307 2308 // Move matched elements from seed to results to keep them synchronized 2309 i = matcherOut.length; 2310 while ( i-- ) { 2311 if ( (elem = matcherOut[i]) && 2312 (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { 2313 2314 seed[temp] = !(results[temp] = elem); 2315 } 2316 } 2317 } 2318 2319 // Add elements to results, through postFinder if defined 2320 } else { 2321 matcherOut = condense( 2322 matcherOut === results ? 2323 matcherOut.splice( preexisting, matcherOut.length ) : 2324 matcherOut 2325 ); 2326 if ( postFinder ) { 2327 postFinder( null, results, matcherOut, xml ); 2328 } else { 2329 push.apply( results, matcherOut ); 2330 } 2331 } 2332 }); 2333} 2334 2335function matcherFromTokens( tokens ) { 2336 var checkContext, matcher, j, 2337 len = tokens.length, 2338 leadingRelative = Expr.relative[ tokens[0].type ], 2339 implicitRelative = leadingRelative || Expr.relative[" "], 2340 i = leadingRelative ? 1 : 0, 2341 2342 // The foundational matcher ensures that elements are reachable from top-level context(s) 2343 matchContext = addCombinator( function( elem ) { 2344 return elem === checkContext; 2345 }, implicitRelative, true ), 2346 matchAnyContext = addCombinator( function( elem ) { 2347 return indexOf( checkContext, elem ) > -1; 2348 }, implicitRelative, true ), 2349 matchers = [ function( elem, context, xml ) { 2350 var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( 2351 (checkContext = context).nodeType ? 2352 matchContext( elem, context, xml ) : 2353 matchAnyContext( elem, context, xml ) ); 2354 // Avoid hanging onto element (issue #299) 2355 checkContext = null; 2356 return ret; 2357 } ]; 2358 2359 for ( ; i < len; i++ ) { 2360 if ( (matcher = Expr.relative[ tokens[i].type ]) ) { 2361 matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; 2362 } else { 2363 matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); 2364 2365 // Return special upon seeing a positional matcher 2366 if ( matcher[ expando ] ) { 2367 // Find the next relative operator (if any) for proper handling 2368 j = ++i; 2369 for ( ; j < len; j++ ) { 2370 if ( Expr.relative[ tokens[j].type ] ) { 2371 break; 2372 } 2373 } 2374 return setMatcher( 2375 i > 1 && elementMatcher( matchers ), 2376 i > 1 && toSelector( 2377 // If the preceding token was a descendant combinator, insert an implicit any-element `*` 2378 tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) 2379 ).replace( rtrim, "$1" ), 2380 matcher, 2381 i < j && matcherFromTokens( tokens.slice( i, j ) ), 2382 j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), 2383 j < len && toSelector( tokens ) 2384 ); 2385 } 2386 matchers.push( matcher ); 2387 } 2388 } 2389 2390 return elementMatcher( matchers ); 2391} 2392 2393function matcherFromGroupMatchers( elementMatchers, setMatchers ) { 2394 var bySet = setMatchers.length > 0, 2395 byElement = elementMatchers.length > 0, 2396 superMatcher = function( seed, context, xml, results, outermost ) { 2397 var elem, j, matcher, 2398 matchedCount = 0, 2399 i = "0", 2400 unmatched = seed && [], 2401 setMatched = [], 2402 contextBackup = outermostContext, 2403 // We must always have either seed elements or outermost context 2404 elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), 2405 // Use integer dirruns iff this is the outermost matcher 2406 dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), 2407 len = elems.length; 2408 2409 if ( outermost ) { 2410 outermostContext = context === document || context || outermost; 2411 } 2412 2413 // Add elements passing elementMatchers directly to results 2414 // Support: IE<9, Safari 2415 // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id 2416 for ( ; i !== len && (elem = elems[i]) != null; i++ ) { 2417 if ( byElement && elem ) { 2418 j = 0; 2419 if ( !context && elem.ownerDocument !== document ) { 2420 setDocument( elem ); 2421 xml = !documentIsHTML; 2422 } 2423 while ( (matcher = elementMatchers[j++]) ) { 2424 if ( matcher( elem, context || document, xml) ) { 2425 results.push( elem ); 2426 break; 2427 } 2428 } 2429 if ( outermost ) { 2430 dirruns = dirrunsUnique; 2431 } 2432 } 2433 2434 // Track unmatched elements for set filters 2435 if ( bySet ) { 2436 // They will have gone through all possible matchers 2437 if ( (elem = !matcher && elem) ) { 2438 matchedCount--; 2439 } 2440 2441 // Lengthen the array for every element, matched or not 2442 if ( seed ) { 2443 unmatched.push( elem ); 2444 } 2445 } 2446 } 2447 2448 // `i` is now the count of elements visited above, and adding it to `matchedCount` 2449 // makes the latter nonnegative. 2450 matchedCount += i; 2451 2452 // Apply set filters to unmatched elements 2453 // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` 2454 // equals `i`), unless we didn't visit _any_ elements in the above loop because we have 2455 // no element matchers and no seed. 2456 // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that 2457 // case, which will result in a "00" `matchedCount` that differs from `i` but is also 2458 // numerically zero. 2459 if ( bySet && i !== matchedCount ) { 2460 j = 0; 2461 while ( (matcher = setMatchers[j++]) ) { 2462 matcher( unmatched, setMatched, context, xml ); 2463 } 2464 2465 if ( seed ) { 2466 // Reintegrate element matches to eliminate the need for sorting 2467 if ( matchedCount > 0 ) { 2468 while ( i-- ) { 2469 if ( !(unmatched[i] || setMatched[i]) ) { 2470 setMatched[i] = pop.call( results ); 2471 } 2472 } 2473 } 2474 2475 // Discard index placeholder values to get only actual matches 2476 setMatched = condense( setMatched ); 2477 } 2478 2479 // Add matches to results 2480 push.apply( results, setMatched ); 2481 2482 // Seedless set matches succeeding multiple successful matchers stipulate sorting 2483 if ( outermost && !seed && setMatched.length > 0 && 2484 ( matchedCount + setMatchers.length ) > 1 ) { 2485 2486 Sizzle.uniqueSort( results ); 2487 } 2488 } 2489 2490 // Override manipulation of globals by nested matchers 2491 if ( outermost ) { 2492 dirruns = dirrunsUnique; 2493 outermostContext = contextBackup; 2494 } 2495 2496 return unmatched; 2497 }; 2498 2499 return bySet ? 2500 markFunction( superMatcher ) : 2501 superMatcher; 2502} 2503 2504compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { 2505 var i, 2506 setMatchers = [], 2507 elementMatchers = [], 2508 cached = compilerCache[ selector + " " ]; 2509 2510 if ( !cached ) { 2511 // Generate a function of recursive functions that can be used to check each element 2512 if ( !match ) { 2513 match = tokenize( selector ); 2514 } 2515 i = match.length; 2516 while ( i-- ) { 2517 cached = matcherFromTokens( match[i] ); 2518 if ( cached[ expando ] ) { 2519 setMatchers.push( cached ); 2520 } else { 2521 elementMatchers.push( cached ); 2522 } 2523 } 2524 2525 // Cache the compiled function 2526 cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); 2527 2528 // Save selector and tokenization 2529 cached.selector = selector; 2530 } 2531 return cached; 2532}; 2533 2534/** 2535 * A low-level selection function that works with Sizzle's compiled 2536 * selector functions 2537 * @param {String|Function} selector A selector or a pre-compiled 2538 * selector function built with Sizzle.compile 2539 * @param {Element} context 2540 * @param {Array} [results] 2541 * @param {Array} [seed] A set of elements to match against 2542 */ 2543select = Sizzle.select = function( selector, context, results, seed ) { 2544 var i, tokens, token, type, find, 2545 compiled = typeof selector === "function" && selector, 2546 match = !seed && tokenize( (selector = compiled.selector || selector) ); 2547 2548 results = results || []; 2549 2550 // Try to minimize operations if there is only one selector in the list and no seed 2551 // (the latter of which guarantees us context) 2552 if ( match.length === 1 ) { 2553 2554 // Reduce context if the leading compound selector is an ID 2555 tokens = match[0] = match[0].slice( 0 ); 2556 if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && 2557 support.getById && context.nodeType === 9 && documentIsHTML && 2558 Expr.relative[ tokens[1].type ] ) { 2559 2560 context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; 2561 if ( !context ) { 2562 return results; 2563 2564 // Precompiled matchers will still verify ancestry, so step up a level 2565 } else if ( compiled ) { 2566 context = context.parentNode; 2567 } 2568 2569 selector = selector.slice( tokens.shift().value.length ); 2570 } 2571 2572 // Fetch a seed set for right-to-left matching 2573 i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; 2574 while ( i-- ) { 2575 token = tokens[i]; 2576 2577 // Abort if we hit a combinator 2578 if ( Expr.relative[ (type = token.type) ] ) { 2579 break; 2580 } 2581 if ( (find = Expr.find[ type ]) ) { 2582 // Search, expanding context for leading sibling combinators 2583 if ( (seed = find( 2584 token.matches[0].replace( runescape, funescape ), 2585 rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context 2586 )) ) { 2587 2588 // If seed is empty or no tokens remain, we can return early 2589 tokens.splice( i, 1 ); 2590 selector = seed.length && toSelector( tokens ); 2591 if ( !selector ) { 2592 push.apply( results, seed ); 2593 return results; 2594 } 2595 2596 break; 2597 } 2598 } 2599 } 2600 } 2601 2602 // Compile and execute a filtering function if one is not provided 2603 // Provide `match` to avoid retokenization if we modified the selector above 2604 ( compiled || compile( selector, match ) )( 2605 seed, 2606 context, 2607 !documentIsHTML, 2608 results, 2609 !context || rsibling.test( selector ) && testContext( context.parentNode ) || context 2610 ); 2611 return results; 2612}; 2613 2614// One-time assignments 2615 2616// Sort stability 2617support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; 2618 2619// Support: Chrome 14-35+ 2620// Always assume duplicates if they aren't passed to the comparison function 2621support.detectDuplicates = !!hasDuplicate; 2622 2623// Initialize against the default document 2624setDocument(); 2625 2626// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) 2627// Detached nodes confoundingly follow *each other* 2628support.sortDetached = assert(function( div1 ) { 2629 // Should return 1, but returns 4 (following) 2630 return div1.compareDocumentPosition( document.createElement("div") ) & 1; 2631}); 2632 2633// Support: IE<8 2634// Prevent attribute/property "interpolation" 2635// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx 2636if ( !assert(function( div ) { 2637 div.innerHTML = "<a href='#'></a>"; 2638 return div.firstChild.getAttribute("href") === "#" ; 2639}) ) { 2640 addHandle( "type|href|height|width", function( elem, name, isXML ) { 2641 if ( !isXML ) { 2642 return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); 2643 } 2644 }); 2645} 2646 2647// Support: IE<9 2648// Use defaultValue in place of getAttribute("value") 2649if ( !support.attributes || !assert(function( div ) { 2650 div.innerHTML = "<input/>"; 2651 div.firstChild.setAttribute( "value", "" ); 2652 return div.firstChild.getAttribute( "value" ) === ""; 2653}) ) { 2654 addHandle( "value", function( elem, name, isXML ) { 2655 if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { 2656 return elem.defaultValue; 2657 } 2658 }); 2659} 2660 2661// Support: IE<9 2662// Use getAttributeNode to fetch booleans when getAttribute lies 2663if ( !assert(function( div ) { 2664 return div.getAttribute("disabled") == null; 2665}) ) { 2666 addHandle( booleans, function( elem, name, isXML ) { 2667 var val; 2668 if ( !isXML ) { 2669 return elem[ name ] === true ? name.toLowerCase() : 2670 (val = elem.getAttributeNode( name )) && val.specified ? 2671 val.value : 2672 null; 2673 } 2674 }); 2675} 2676 2677return Sizzle; 2678 2679})( window ); 2680 2681 2682 2683jQuery.find = Sizzle; 2684jQuery.expr = Sizzle.selectors; 2685jQuery.expr[ ":" ] = jQuery.expr.pseudos; 2686jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; 2687jQuery.text = Sizzle.getText; 2688jQuery.isXMLDoc = Sizzle.isXML; 2689jQuery.contains = Sizzle.contains; 2690 2691 2692 2693var dir = function( elem, dir, until ) { 2694 var matched = [], 2695 truncate = until !== undefined; 2696 2697 while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { 2698 if ( elem.nodeType === 1 ) { 2699 if ( truncate && jQuery( elem ).is( until ) ) { 2700 break; 2701 } 2702 matched.push( elem ); 2703 } 2704 } 2705 return matched; 2706}; 2707 2708 2709var siblings = function( n, elem ) { 2710 var matched = []; 2711 2712 for ( ; n; n = n.nextSibling ) { 2713 if ( n.nodeType === 1 && n !== elem ) { 2714 matched.push( n ); 2715 } 2716 } 2717 2718 return matched; 2719}; 2720 2721 2722var rneedsContext = jQuery.expr.match.needsContext; 2723 2724var rsingleTag = ( /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/ ); 2725 2726 2727 2728var risSimple = /^.[^:#\[\.,]*$/; 2729 2730// Implement the identical functionality for filter and not 2731function winnow( elements, qualifier, not ) { 2732 if ( jQuery.isFunction( qualifier ) ) { 2733 return jQuery.grep( elements, function( elem, i ) { 2734 /* jshint -W018 */ 2735 return !!qualifier.call( elem, i, elem ) !== not; 2736 } ); 2737 2738 } 2739 2740 if ( qualifier.nodeType ) { 2741 return jQuery.grep( elements, function( elem ) { 2742 return ( elem === qualifier ) !== not; 2743 } ); 2744 2745 } 2746 2747 if ( typeof qualifier === "string" ) { 2748 if ( risSimple.test( qualifier ) ) { 2749 return jQuery.filter( qualifier, elements, not ); 2750 } 2751 2752 qualifier = jQuery.filter( qualifier, elements ); 2753 } 2754 2755 return jQuery.grep( elements, function( elem ) { 2756 return ( indexOf.call( qualifier, elem ) > -1 ) !== not; 2757 } ); 2758} 2759 2760jQuery.filter = function( expr, elems, not ) { 2761 var elem = elems[ 0 ]; 2762 2763 if ( not ) { 2764 expr = ":not(" + expr + ")"; 2765 } 2766 2767 return elems.length === 1 && elem.nodeType === 1 ? 2768 jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : 2769 jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { 2770 return elem.nodeType === 1; 2771 } ) ); 2772}; 2773 2774jQuery.fn.extend( { 2775 find: function( selector ) { 2776 var i, 2777 len = this.length, 2778 ret = [], 2779 self = this; 2780 2781 if ( typeof selector !== "string" ) { 2782 return this.pushStack( jQuery( selector ).filter( function() { 2783 for ( i = 0; i < len; i++ ) { 2784 if ( jQuery.contains( self[ i ], this ) ) { 2785 return true; 2786 } 2787 } 2788 } ) ); 2789 } 2790 2791 for ( i = 0; i < len; i++ ) { 2792 jQuery.find( selector, self[ i ], ret ); 2793 } 2794 2795 // Needed because $( selector, context ) becomes $( context ).find( selector ) 2796 ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); 2797 ret.selector = this.selector ? this.selector + " " + selector : selector; 2798 return ret; 2799 }, 2800 filter: function( selector ) { 2801 return this.pushStack( winnow( this, selector || [], false ) ); 2802 }, 2803 not: function( selector ) { 2804 return this.pushStack( winnow( this, selector || [], true ) ); 2805 }, 2806 is: function( selector ) { 2807 return !!winnow( 2808 this, 2809 2810 // If this is a positional/relative selector, check membership in the returned set 2811 // so $("p:first").is("p:last") won't return true for a doc with two "p". 2812 typeof selector === "string" && rneedsContext.test( selector ) ? 2813 jQuery( selector ) : 2814 selector || [], 2815 false 2816 ).length; 2817 } 2818} ); 2819 2820 2821// Initialize a jQuery object 2822 2823 2824// A central reference to the root jQuery(document) 2825var rootjQuery, 2826 2827 // A simple way to check for HTML strings 2828 // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) 2829 // Strict HTML recognition (#11290: must start with <) 2830 rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, 2831 2832 init = jQuery.fn.init = function( selector, context, root ) { 2833 var match, elem; 2834 2835 // HANDLE: $(""), $(null), $(undefined), $(false) 2836 if ( !selector ) { 2837 return this; 2838 } 2839 2840 // Method init() accepts an alternate rootjQuery 2841 // so migrate can support jQuery.sub (gh-2101) 2842 root = root || rootjQuery; 2843 2844 // Handle HTML strings 2845 if ( typeof selector === "string" ) { 2846 if ( selector[ 0 ] === "<" && 2847 selector[ selector.length - 1 ] === ">" && 2848 selector.length >= 3 ) { 2849 2850 // Assume that strings that start and end with <> are HTML and skip the regex check 2851 match = [ null, selector, null ]; 2852 2853 } else { 2854 match = rquickExpr.exec( selector ); 2855 } 2856 2857 // Match html or make sure no context is specified for #id 2858 if ( match && ( match[ 1 ] || !context ) ) { 2859 2860 // HANDLE: $(html) -> $(array) 2861 if ( match[ 1 ] ) { 2862 context = context instanceof jQuery ? context[ 0 ] : context; 2863 2864 // Option to run scripts is true for back-compat 2865 // Intentionally let the error be thrown if parseHTML is not present 2866 jQuery.merge( this, jQuery.parseHTML( 2867 match[ 1 ], 2868 context && context.nodeType ? context.ownerDocument || context : document, 2869 true 2870 ) ); 2871 2872 // HANDLE: $(html, props) 2873 if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { 2874 for ( match in context ) { 2875 2876 // Properties of context are called as methods if possible 2877 if ( jQuery.isFunction( this[ match ] ) ) { 2878 this[ match ]( context[ match ] ); 2879 2880 // ...and otherwise set as attributes 2881 } else { 2882 this.attr( match, context[ match ] ); 2883 } 2884 } 2885 } 2886 2887 return this; 2888 2889 // HANDLE: $(#id) 2890 } else { 2891 elem = document.getElementById( match[ 2 ] ); 2892 2893 // Support: Blackberry 4.6 2894 // gEBID returns nodes no longer in the document (#6963) 2895 if ( elem && elem.parentNode ) { 2896 2897 // Inject the element directly into the jQuery object 2898 this.length = 1; 2899 this[ 0 ] = elem; 2900 } 2901 2902 this.context = document; 2903 this.selector = selector; 2904 return this; 2905 } 2906 2907 // HANDLE: $(expr, $(...)) 2908 } else if ( !context || context.jquery ) { 2909 return ( context || root ).find( selector ); 2910 2911 // HANDLE: $(expr, context) 2912 // (which is just equivalent to: $(context).find(expr) 2913 } else { 2914 return this.constructor( context ).find( selector ); 2915 } 2916 2917 // HANDLE: $(DOMElement) 2918 } else if ( selector.nodeType ) { 2919 this.context = this[ 0 ] = selector; 2920 this.length = 1; 2921 return this; 2922 2923 // HANDLE: $(function) 2924 // Shortcut for document ready 2925 } else if ( jQuery.isFunction( selector ) ) { 2926 return root.ready !== undefined ? 2927 root.ready( selector ) : 2928 2929 // Execute immediately if ready is not present 2930 selector( jQuery ); 2931 } 2932 2933 if ( selector.selector !== undefined ) { 2934 this.selector = selector.selector; 2935 this.context = selector.context; 2936 } 2937 2938 return jQuery.makeArray( selector, this ); 2939 }; 2940 2941// Give the init function the jQuery prototype for later instantiation 2942init.prototype = jQuery.fn; 2943 2944// Initialize central reference 2945rootjQuery = jQuery( document ); 2946 2947 2948var rparentsprev = /^(?:parents|prev(?:Until|All))/, 2949 2950 // Methods guaranteed to produce a unique set when starting from a unique set 2951 guaranteedUnique = { 2952 children: true, 2953 contents: true, 2954 next: true, 2955 prev: true 2956 }; 2957 2958jQuery.fn.extend( { 2959 has: function( target ) { 2960 var targets = jQuery( target, this ), 2961 l = targets.length; 2962 2963 return this.filter( function() { 2964 var i = 0; 2965 for ( ; i < l; i++ ) { 2966 if ( jQuery.contains( this, targets[ i ] ) ) { 2967 return true; 2968 } 2969 } 2970 } ); 2971 }, 2972 2973 closest: function( selectors, context ) { 2974 var cur, 2975 i = 0, 2976 l = this.length, 2977 matched = [], 2978 pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? 2979 jQuery( selectors, context || this.context ) : 2980 0; 2981 2982 for ( ; i < l; i++ ) { 2983 for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { 2984 2985 // Always skip document fragments 2986 if ( cur.nodeType < 11 && ( pos ? 2987 pos.index( cur ) > -1 : 2988 2989 // Don't pass non-elements to Sizzle 2990 cur.nodeType === 1 && 2991 jQuery.find.matchesSelector( cur, selectors ) ) ) { 2992 2993 matched.push( cur ); 2994 break; 2995 } 2996 } 2997 } 2998 2999 return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); 3000 }, 3001 3002 // Determine the position of an element within the set 3003 index: function( elem ) { 3004 3005 // No argument, return index in parent 3006 if ( !elem ) { 3007 return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; 3008 } 3009 3010 // Index in selector 3011 if ( typeof elem === "string" ) { 3012 return indexOf.call( jQuery( elem ), this[ 0 ] ); 3013 } 3014 3015 // Locate the position of the desired element 3016 return indexOf.call( this, 3017 3018 // If it receives a jQuery object, the first element is used 3019 elem.jquery ? elem[ 0 ] : elem 3020 ); 3021 }, 3022 3023 add: function( selector, context ) { 3024 return this.pushStack( 3025 jQuery.uniqueSort( 3026 jQuery.merge( this.get(), jQuery( selector, context ) ) 3027 ) 3028 ); 3029 }, 3030 3031 addBack: function( selector ) { 3032 return this.add( selector == null ? 3033 this.prevObject : this.prevObject.filter( selector ) 3034 ); 3035 } 3036} ); 3037 3038function sibling( cur, dir ) { 3039 while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} 3040 return cur; 3041} 3042 3043jQuery.each( { 3044 parent: function( elem ) { 3045 var parent = elem.parentNode; 3046 return parent && parent.nodeType !== 11 ? parent : null; 3047 }, 3048 parents: function( elem ) { 3049 return dir( elem, "parentNode" ); 3050 }, 3051 parentsUntil: function( elem, i, until ) { 3052 return dir( elem, "parentNode", until ); 3053 }, 3054 next: function( elem ) { 3055 return sibling( elem, "nextSibling" ); 3056 }, 3057 prev: function( elem ) { 3058 return sibling( elem, "previousSibling" ); 3059 }, 3060 nextAll: function( elem ) { 3061 return dir( elem, "nextSibling" ); 3062 }, 3063 prevAll: function( elem ) { 3064 return dir( elem, "previousSibling" ); 3065 }, 3066 nextUntil: function( elem, i, until ) { 3067 return dir( elem, "nextSibling", until ); 3068 }, 3069 prevUntil: function( elem, i, until ) { 3070 return dir( elem, "previousSibling", until ); 3071 }, 3072 siblings: function( elem ) { 3073 return siblings( ( elem.parentNode || {} ).firstChild, elem ); 3074 }, 3075 children: function( elem ) { 3076 return siblings( elem.firstChild ); 3077 }, 3078 contents: function( elem ) { 3079 return elem.contentDocument || jQuery.merge( [], elem.childNodes ); 3080 } 3081}, function( name, fn ) { 3082 jQuery.fn[ name ] = function( until, selector ) { 3083 var matched = jQuery.map( this, fn, until ); 3084 3085 if ( name.slice( -5 ) !== "Until" ) { 3086 selector = until; 3087 } 3088 3089 if ( selector && typeof selector === "string" ) { 3090 matched = jQuery.filter( selector, matched ); 3091 } 3092 3093 if ( this.length > 1 ) { 3094 3095 // Remove duplicates 3096 if ( !guaranteedUnique[ name ] ) { 3097 jQuery.uniqueSort( matched ); 3098 } 3099 3100 // Reverse order for parents* and prev-derivatives 3101 if ( rparentsprev.test( name ) ) { 3102 matched.reverse(); 3103 } 3104 } 3105 3106 return this.pushStack( matched ); 3107 }; 3108} ); 3109var rnotwhite = ( /\S+/g ); 3110 3111 3112 3113// Convert String-formatted options into Object-formatted ones 3114function createOptions( options ) { 3115 var object = {}; 3116 jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { 3117 object[ flag ] = true; 3118 } ); 3119 return object; 3120} 3121 3122/* 3123 * Create a callback list using the following parameters: 3124 * 3125 * options: an optional list of space-separated options that will change how 3126 * the callback list behaves or a more traditional option object 3127 * 3128 * By default a callback list will act like an event callback list and can be 3129 * "fired" multiple times. 3130 * 3131 * Possible options: 3132 * 3133 * once: will ensure the callback list can only be fired once (like a Deferred) 3134 * 3135 * memory: will keep track of previous values and will call any callback added 3136 * after the list has been fired right away with the latest "memorized" 3137 * values (like a Deferred) 3138 * 3139 * unique: will ensure a callback can only be added once (no duplicate in the list) 3140 * 3141 * stopOnFalse: interrupt callings when a callback returns false 3142 * 3143 */ 3144jQuery.Callbacks = function( options ) { 3145 3146 // Convert options from String-formatted to Object-formatted if needed 3147 // (we check in cache first) 3148 options = typeof options === "string" ? 3149 createOptions( options ) : 3150 jQuery.extend( {}, options ); 3151 3152 var // Flag to know if list is currently firing 3153 firing, 3154 3155 // Last fire value for non-forgettable lists 3156 memory, 3157 3158 // Flag to know if list was already fired 3159 fired, 3160 3161 // Flag to prevent firing 3162 locked, 3163 3164 // Actual callback list 3165 list = [], 3166 3167 // Queue of execution data for repeatable lists 3168 queue = [], 3169 3170 // Index of currently firing callback (modified by add/remove as needed) 3171 firingIndex = -1, 3172 3173 // Fire callbacks 3174 fire = function() { 3175 3176 // Enforce single-firing 3177 locked = options.once; 3178 3179 // Execute callbacks for all pending executions, 3180 // respecting firingIndex overrides and runtime changes 3181 fired = firing = true; 3182 for ( ; queue.length; firingIndex = -1 ) { 3183 memory = queue.shift(); 3184 while ( ++firingIndex < list.length ) { 3185 3186 // Run callback and check for early termination 3187 if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && 3188 options.stopOnFalse ) { 3189 3190 // Jump to end and forget the data so .add doesn't re-fire 3191 firingIndex = list.length; 3192 memory = false; 3193 } 3194 } 3195 } 3196 3197 // Forget the data if we're done with it 3198 if ( !options.memory ) { 3199 memory = false; 3200 } 3201 3202 firing = false; 3203 3204 // Clean up if we're done firing for good 3205 if ( locked ) { 3206 3207 // Keep an empty list if we have data for future add calls 3208 if ( memory ) { 3209 list = []; 3210 3211 // Otherwise, this object is spent 3212 } else { 3213 list = ""; 3214 } 3215 } 3216 }, 3217 3218 // Actual Callbacks object 3219 self = { 3220 3221 // Add a callback or a collection of callbacks to the list 3222 add: function() { 3223 if ( list ) { 3224 3225 // If we have memory from a past run, we should fire after adding 3226 if ( memory && !firing ) { 3227 firingIndex = list.length - 1; 3228 queue.push( memory ); 3229 } 3230 3231 ( function add( args ) { 3232 jQuery.each( args, function( _, arg ) { 3233 if ( jQuery.isFunction( arg ) ) { 3234 if ( !options.unique || !self.has( arg ) ) { 3235 list.push( arg ); 3236 } 3237 } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) { 3238 3239 // Inspect recursively 3240 add( arg ); 3241 } 3242 } ); 3243 } )( arguments ); 3244 3245 if ( memory && !firing ) { 3246 fire(); 3247 } 3248 } 3249 return this; 3250 }, 3251 3252 // Remove a callback from the list 3253 remove: function() { 3254 jQuery.each( arguments, function( _, arg ) { 3255 var index; 3256 while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { 3257 list.splice( index, 1 ); 3258 3259 // Handle firing indexes 3260 if ( index <= firingIndex ) { 3261 firingIndex--; 3262 } 3263 } 3264 } ); 3265 return this; 3266 }, 3267 3268 // Check if a given callback is in the list. 3269 // If no argument is given, return whether or not list has callbacks attached. 3270 has: function( fn ) { 3271 return fn ? 3272 jQuery.inArray( fn, list ) > -1 : 3273 list.length > 0; 3274 }, 3275 3276 // Remove all callbacks from the list 3277 empty: function() { 3278 if ( list ) { 3279 list = []; 3280 } 3281 return this; 3282 }, 3283 3284 // Disable .fire and .add 3285 // Abort any current/pending executions 3286 // Clear all callbacks and values 3287 disable: function() { 3288 locked = queue = []; 3289 list = memory = ""; 3290 return this; 3291 }, 3292 disabled: function() { 3293 return !list; 3294 }, 3295 3296 // Disable .fire 3297 // Also disable .add unless we have memory (since it would have no effect) 3298 // Abort any pending executions 3299 lock: function() { 3300 locked = queue = []; 3301 if ( !memory ) { 3302 list = memory = ""; 3303 } 3304 return this; 3305 }, 3306 locked: function() { 3307 return !!locked; 3308 }, 3309 3310 // Call all callbacks with the given context and arguments 3311 fireWith: function( context, args ) { 3312 if ( !locked ) { 3313 args = args || []; 3314 args = [ context, args.slice ? args.slice() : args ]; 3315 queue.push( args ); 3316 if ( !firing ) { 3317 fire(); 3318 } 3319 } 3320 return this; 3321 }, 3322 3323 // Call all the callbacks with the given arguments 3324 fire: function() { 3325 self.fireWith( this, arguments ); 3326 return this; 3327 }, 3328 3329 // To know if the callbacks have already been called at least once 3330 fired: function() { 3331 return !!fired; 3332 } 3333 }; 3334 3335 return self; 3336}; 3337 3338 3339jQuery.extend( { 3340 3341 Deferred: function( func ) { 3342 var tuples = [ 3343 3344 // action, add listener, listener list, final state 3345 [ "resolve", "done", jQuery.Callbacks( "once memory" ), "resolved" ], 3346 [ "reject", "fail", jQuery.Callbacks( "once memory" ), "rejected" ], 3347 [ "notify", "progress", jQuery.Callbacks( "memory" ) ] 3348 ], 3349 state = "pending", 3350 promise = { 3351 state: function() { 3352 return state; 3353 }, 3354 always: function() { 3355 deferred.done( arguments ).fail( arguments ); 3356 return this; 3357 }, 3358 then: function( /* fnDone, fnFail, fnProgress */ ) { 3359 var fns = arguments; 3360 return jQuery.Deferred( function( newDefer ) { 3361 jQuery.each( tuples, function( i, tuple ) { 3362 var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; 3363 3364 // deferred[ done | fail | progress ] for forwarding actions to newDefer 3365 deferred[ tuple[ 1 ] ]( function() { 3366 var returned = fn && fn.apply( this, arguments ); 3367 if ( returned && jQuery.isFunction( returned.promise ) ) { 3368 returned.promise() 3369 .progress( newDefer.notify ) 3370 .done( newDefer.resolve ) 3371 .fail( newDefer.reject ); 3372 } else { 3373 newDefer[ tuple[ 0 ] + "With" ]( 3374 this === promise ? newDefer.promise() : this, 3375 fn ? [ returned ] : arguments 3376 ); 3377 } 3378 } ); 3379 } ); 3380 fns = null; 3381 } ).promise(); 3382 }, 3383 3384 // Get a promise for this deferred 3385 // If obj is provided, the promise aspect is added to the object 3386 promise: function( obj ) { 3387 return obj != null ? jQuery.extend( obj, promise ) : promise; 3388 } 3389 }, 3390 deferred = {}; 3391 3392 // Keep pipe for back-compat 3393 promise.pipe = promise.then; 3394 3395 // Add list-specific methods 3396 jQuery.each( tuples, function( i, tuple ) { 3397 var list = tuple[ 2 ], 3398 stateString = tuple[ 3 ]; 3399 3400 // promise[ done | fail | progress ] = list.add 3401 promise[ tuple[ 1 ] ] = list.add; 3402 3403 // Handle state 3404 if ( stateString ) { 3405 list.add( function() { 3406 3407 // state = [ resolved | rejected ] 3408 state = stateString; 3409 3410 // [ reject_list | resolve_list ].disable; progress_list.lock 3411 }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); 3412 } 3413 3414 // deferred[ resolve | reject | notify ] 3415 deferred[ tuple[ 0 ] ] = function() { 3416 deferred[ tuple[ 0 ] + "With" ]( this === deferred ? promise : this, arguments ); 3417 return this; 3418 }; 3419 deferred[ tuple[ 0 ] + "With" ] = list.fireWith; 3420 } ); 3421 3422 // Make the deferred a promise 3423 promise.promise( deferred ); 3424 3425 // Call given func if any 3426 if ( func ) { 3427 func.call( deferred, deferred ); 3428 } 3429 3430 // All done! 3431 return deferred; 3432 }, 3433 3434 // Deferred helper 3435 when: function( subordinate /* , ..., subordinateN */ ) { 3436 var i = 0, 3437 resolveValues = slice.call( arguments ), 3438 length = resolveValues.length, 3439 3440 // the count of uncompleted subordinates 3441 remaining = length !== 1 || 3442 ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, 3443 3444 // the master Deferred. 3445 // If resolveValues consist of only a single Deferred, just use that. 3446 deferred = remaining === 1 ? subordinate : jQuery.Deferred(), 3447 3448 // Update function for both resolve and progress values 3449 updateFunc = function( i, contexts, values ) { 3450 return function( value ) { 3451 contexts[ i ] = this; 3452 values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; 3453 if ( values === progressValues ) { 3454 deferred.notifyWith( contexts, values ); 3455 } else if ( !( --remaining ) ) { 3456 deferred.resolveWith( contexts, values ); 3457 } 3458 }; 3459 }, 3460 3461 progressValues, progressContexts, resolveContexts; 3462 3463 // Add listeners to Deferred subordinates; treat others as resolved 3464 if ( length > 1 ) { 3465 progressValues = new Array( length ); 3466 progressContexts = new Array( length ); 3467 resolveContexts = new Array( length ); 3468 for ( ; i < length; i++ ) { 3469 if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { 3470 resolveValues[ i ].promise() 3471 .progress( updateFunc( i, progressContexts, progressValues ) ) 3472 .done( updateFunc( i, resolveContexts, resolveValues ) ) 3473 .fail( deferred.reject ); 3474 } else { 3475 --remaining; 3476 } 3477 } 3478 } 3479 3480 // If we're not waiting on anything, resolve the master 3481 if ( !remaining ) { 3482 deferred.resolveWith( resolveContexts, resolveValues ); 3483 } 3484 3485 return deferred.promise(); 3486 } 3487} ); 3488 3489 3490// The deferred used on DOM ready 3491var readyList; 3492 3493jQuery.fn.ready = function( fn ) { 3494 3495 // Add the callback 3496 jQuery.ready.promise().done( fn ); 3497 3498 return this; 3499}; 3500 3501jQuery.extend( { 3502 3503 // Is the DOM ready to be used? Set to true once it occurs. 3504 isReady: false, 3505 3506 // A counter to track how many items to wait for before 3507 // the ready event fires. See #6781 3508 readyWait: 1, 3509 3510 // Hold (or release) the ready event 3511 holdReady: function( hold ) { 3512 if ( hold ) { 3513 jQuery.readyWait++; 3514 } else { 3515 jQuery.ready( true ); 3516 } 3517 }, 3518 3519 // Handle when the DOM is ready 3520 ready: function( wait ) { 3521 3522 // Abort if there are pending holds or we're already ready 3523 if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { 3524 return; 3525 } 3526 3527 // Remember that the DOM is ready 3528 jQuery.isReady = true; 3529 3530 // If a normal DOM Ready event fired, decrement, and wait if need be 3531 if ( wait !== true && --jQuery.readyWait > 0 ) { 3532 return; 3533 } 3534 3535 // If there are functions bound, to execute 3536 readyList.resolveWith( document, [ jQuery ] ); 3537 3538 // Trigger any bound ready events 3539 if ( jQuery.fn.triggerHandler ) { 3540 jQuery( document ).triggerHandler( "ready" ); 3541 jQuery( document ).off( "ready" ); 3542 } 3543 } 3544} ); 3545 3546/** 3547 * The ready event handler and self cleanup method 3548 */ 3549function completed() { 3550 document.removeEventListener( "DOMContentLoaded", completed ); 3551 window.removeEventListener( "load", completed ); 3552 jQuery.ready(); 3553} 3554 3555jQuery.ready.promise = function( obj ) { 3556 if ( !readyList ) { 3557 3558 readyList = jQuery.Deferred(); 3559 3560 // Catch cases where $(document).ready() is called 3561 // after the browser event has already occurred. 3562 // Support: IE9-10 only 3563 // Older IE sometimes signals "interactive" too soon 3564 if ( document.readyState === "complete" || 3565 ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { 3566 3567 // Handle it asynchronously to allow scripts the opportunity to delay ready 3568 window.setTimeout( jQuery.ready ); 3569 3570 } else { 3571 3572 // Use the handy event callback 3573 document.addEventListener( "DOMContentLoaded", completed ); 3574 3575 // A fallback to window.onload, that will always work 3576 window.addEventListener( "load", completed ); 3577 } 3578 } 3579 return readyList.promise( obj ); 3580}; 3581 3582// Kick off the DOM ready check even if the user does not 3583jQuery.ready.promise(); 3584 3585 3586 3587 3588// Multifunctional method to get and set values of a collection 3589// The value/s can optionally be executed if it's a function 3590var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { 3591 var i = 0, 3592 len = elems.length, 3593 bulk = key == null; 3594 3595 // Sets many values 3596 if ( jQuery.type( key ) === "object" ) { 3597 chainable = true; 3598 for ( i in key ) { 3599 access( elems, fn, i, key[ i ], true, emptyGet, raw ); 3600 } 3601 3602 // Sets one value 3603 } else if ( value !== undefined ) { 3604 chainable = true; 3605 3606 if ( !jQuery.isFunction( value ) ) { 3607 raw = true; 3608 } 3609 3610 if ( bulk ) { 3611 3612 // Bulk operations run against the entire set 3613 if ( raw ) { 3614 fn.call( elems, value ); 3615 fn = null; 3616 3617 // ...except when executing function values 3618 } else { 3619 bulk = fn; 3620 fn = function( elem, key, value ) { 3621 return bulk.call( jQuery( elem ), value ); 3622 }; 3623 } 3624 } 3625 3626 if ( fn ) { 3627 for ( ; i < len; i++ ) { 3628 fn( 3629 elems[ i ], key, raw ? 3630 value : 3631 value.call( elems[ i ], i, fn( elems[ i ], key ) ) 3632 ); 3633 } 3634 } 3635 } 3636 3637 return chainable ? 3638 elems : 3639 3640 // Gets 3641 bulk ? 3642 fn.call( elems ) : 3643 len ? fn( elems[ 0 ], key ) : emptyGet; 3644}; 3645var acceptData = function( owner ) { 3646 3647 // Accepts only: 3648 // - Node 3649 // - Node.ELEMENT_NODE 3650 // - Node.DOCUMENT_NODE 3651 // - Object 3652 // - Any 3653 /* jshint -W018 */ 3654 return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); 3655}; 3656 3657 3658 3659 3660function Data() { 3661 this.expando = jQuery.expando + Data.uid++; 3662} 3663 3664Data.uid = 1; 3665 3666Data.prototype = { 3667 3668 register: function( owner, initial ) { 3669 var value = initial || {}; 3670 3671 // If it is a node unlikely to be stringify-ed or looped over 3672 // use plain assignment 3673 if ( owner.nodeType ) { 3674 owner[ this.expando ] = value; 3675 3676 // Otherwise secure it in a non-enumerable, non-writable property 3677 // configurability must be true to allow the property to be 3678 // deleted with the delete operator 3679 } else { 3680 Object.defineProperty( owner, this.expando, { 3681 value: value, 3682 writable: true, 3683 configurable: true 3684 } ); 3685 } 3686 return owner[ this.expando ]; 3687 }, 3688 cache: function( owner ) { 3689 3690 // We can accept data for non-element nodes in modern browsers, 3691 // but we should not, see #8335. 3692 // Always return an empty object. 3693 if ( !acceptData( owner ) ) { 3694 return {}; 3695 } 3696 3697 // Check if the owner object already has a cache 3698 var value = owner[ this.expando ]; 3699 3700 // If not, create one 3701 if ( !value ) { 3702 value = {}; 3703 3704 // We can accept data for non-element nodes in modern browsers, 3705 // but we should not, see #8335. 3706 // Always return an empty object. 3707 if ( acceptData( owner ) ) { 3708 3709 // If it is a node unlikely to be stringify-ed or looped over 3710 // use plain assignment 3711 if ( owner.nodeType ) { 3712 owner[ this.expando ] = value; 3713 3714 // Otherwise secure it in a non-enumerable property 3715 // configurable must be true to allow the property to be 3716 // deleted when data is removed 3717 } else { 3718 Object.defineProperty( owner, this.expando, { 3719 value: value, 3720 configurable: true 3721 } ); 3722 } 3723 } 3724 } 3725 3726 return value; 3727 }, 3728 set: function( owner, data, value ) { 3729 var prop, 3730 cache = this.cache( owner ); 3731 3732 // Handle: [ owner, key, value ] args 3733 if ( typeof data === "string" ) { 3734 cache[ data ] = value; 3735 3736 // Handle: [ owner, { properties } ] args 3737 } else { 3738 3739 // Copy the properties one-by-one to the cache object 3740 for ( prop in data ) { 3741 cache[ prop ] = data[ prop ]; 3742 } 3743 } 3744 return cache; 3745 }, 3746 get: function( owner, key ) { 3747 return key === undefined ? 3748 this.cache( owner ) : 3749 owner[ this.expando ] && owner[ this.expando ][ key ]; 3750 }, 3751 access: function( owner, key, value ) { 3752 var stored; 3753 3754 // In cases where either: 3755 // 3756 // 1. No key was specified 3757 // 2. A string key was specified, but no value provided 3758 // 3759 // Take the "read" path and allow the get method to determine 3760 // which value to return, respectively either: 3761 // 3762 // 1. The entire cache object 3763 // 2. The data stored at the key 3764 // 3765 if ( key === undefined || 3766 ( ( key && typeof key === "string" ) && value === undefined ) ) { 3767 3768 stored = this.get( owner, key ); 3769 3770 return stored !== undefined ? 3771 stored : this.get( owner, jQuery.camelCase( key ) ); 3772 } 3773 3774 // When the key is not a string, or both a key and value 3775 // are specified, set or extend (existing objects) with either: 3776 // 3777 // 1. An object of properties 3778 // 2. A key and value 3779 // 3780 this.set( owner, key, value ); 3781 3782 // Since the "set" path can have two possible entry points 3783 // return the expected data based on which path was taken[*] 3784 return value !== undefined ? value : key; 3785 }, 3786 remove: function( owner, key ) { 3787 var i, name, camel, 3788 cache = owner[ this.expando ]; 3789 3790 if ( cache === undefined ) { 3791 return; 3792 } 3793 3794 if ( key === undefined ) { 3795 this.register( owner ); 3796 3797 } else { 3798 3799 // Support array or space separated string of keys 3800 if ( jQuery.isArray( key ) ) { 3801 3802 // If "name" is an array of keys... 3803 // When data is initially created, via ("key", "val") signature, 3804 // keys will be converted to camelCase. 3805 // Since there is no way to tell _how_ a key was added, remove 3806 // both plain key and camelCase key. #12786 3807 // This will only penalize the array argument path. 3808 name = key.concat( key.map( jQuery.camelCase ) ); 3809 } else { 3810 camel = jQuery.camelCase( key ); 3811 3812 // Try the string as a key before any manipulation 3813 if ( key in cache ) { 3814 name = [ key, camel ]; 3815 } else { 3816 3817 // If a key with the spaces exists, use it. 3818 // Otherwise, create an array by matching non-whitespace 3819 name = camel; 3820 name = name in cache ? 3821 [ name ] : ( name.match( rnotwhite ) || [] ); 3822 } 3823 } 3824 3825 i = name.length; 3826 3827 while ( i-- ) { 3828 delete cache[ name[ i ] ]; 3829 } 3830 } 3831 3832 // Remove the expando if there's no more data 3833 if ( key === undefined || jQuery.isEmptyObject( cache ) ) { 3834 3835 // Support: Chrome <= 35-45+ 3836 // Webkit & Blink performance suffers when deleting properties 3837 // from DOM nodes, so set to undefined instead 3838 // https://code.google.com/p/chromium/issues/detail?id=378607 3839 if ( owner.nodeType ) { 3840 owner[ this.expando ] = undefined; 3841 } else { 3842 delete owner[ this.expando ]; 3843 } 3844 } 3845 }, 3846 hasData: function( owner ) { 3847 var cache = owner[ this.expando ]; 3848 return cache !== undefined && !jQuery.isEmptyObject( cache ); 3849 } 3850}; 3851var dataPriv = new Data(); 3852 3853var dataUser = new Data(); 3854 3855 3856 3857// Implementation Summary 3858// 3859// 1. Enforce API surface and semantic compatibility with 1.9.x branch 3860// 2. Improve the module's maintainability by reducing the storage 3861// paths to a single mechanism. 3862// 3. Use the same single mechanism to support "private" and "user" data. 3863// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) 3864// 5. Avoid exposing implementation details on user objects (eg. expando properties) 3865// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 3866 3867var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, 3868 rmultiDash = /[A-Z]/g; 3869 3870function dataAttr( elem, key, data ) { 3871 var name; 3872 3873 // If nothing was found internally, try to fetch any 3874 // data from the HTML5 data-* attribute 3875 if ( data === undefined && elem.nodeType === 1 ) { 3876 name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); 3877 data = elem.getAttribute( name ); 3878 3879 if ( typeof data === "string" ) { 3880 try { 3881 data = data === "true" ? true : 3882 data === "false" ? false : 3883 data === "null" ? null : 3884 3885 // Only convert to a number if it doesn't change the string 3886 +data + "" === data ? +data : 3887 rbrace.test( data ) ? jQuery.parseJSON( data ) : 3888 data; 3889 } catch ( e ) {} 3890 3891 // Make sure we set the data so it isn't changed later 3892 dataUser.set( elem, key, data ); 3893 } else { 3894 data = undefined; 3895 } 3896 } 3897 return data; 3898} 3899 3900jQuery.extend( { 3901 hasData: function( elem ) { 3902 return dataUser.hasData( elem ) || dataPriv.hasData( elem ); 3903 }, 3904 3905 data: function( elem, name, data ) { 3906 return dataUser.access( elem, name, data ); 3907 }, 3908 3909 removeData: function( elem, name ) { 3910 dataUser.remove( elem, name ); 3911 }, 3912 3913 // TODO: Now that all calls to _data and _removeData have been replaced 3914 // with direct calls to dataPriv methods, these can be deprecated. 3915 _data: function( elem, name, data ) { 3916 return dataPriv.access( elem, name, data ); 3917 }, 3918 3919 _removeData: function( elem, name ) { 3920 dataPriv.remove( elem, name ); 3921 } 3922} ); 3923 3924jQuery.fn.extend( { 3925 data: function( key, value ) { 3926 var i, name, data, 3927 elem = this[ 0 ], 3928 attrs = elem && elem.attributes; 3929 3930 // Gets all values 3931 if ( key === undefined ) { 3932 if ( this.length ) { 3933 data = dataUser.get( elem ); 3934 3935 if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { 3936 i = attrs.length; 3937 while ( i-- ) { 3938 3939 // Support: IE11+ 3940 // The attrs elements can be null (#14894) 3941 if ( attrs[ i ] ) { 3942 name = attrs[ i ].name; 3943 if ( name.indexOf( "data-" ) === 0 ) { 3944 name = jQuery.camelCase( name.slice( 5 ) ); 3945 dataAttr( elem, name, data[ name ] ); 3946 } 3947 } 3948 } 3949 dataPriv.set( elem, "hasDataAttrs", true ); 3950 } 3951 } 3952 3953 return data; 3954 } 3955 3956 // Sets multiple values 3957 if ( typeof key === "object" ) { 3958 return this.each( function() { 3959 dataUser.set( this, key ); 3960 } ); 3961 } 3962 3963 return access( this, function( value ) { 3964 var data, camelKey; 3965 3966 // The calling jQuery object (element matches) is not empty 3967 // (and therefore has an element appears at this[ 0 ]) and the 3968 // `value` parameter was not undefined. An empty jQuery object 3969 // will result in `undefined` for elem = this[ 0 ] which will 3970 // throw an exception if an attempt to read a data cache is made. 3971 if ( elem && value === undefined ) { 3972 3973 // Attempt to get data from the cache 3974 // with the key as-is 3975 data = dataUser.get( elem, key ) || 3976 3977 // Try to find dashed key if it exists (gh-2779) 3978 // This is for 2.2.x only 3979 dataUser.get( elem, key.replace( rmultiDash, "-$&" ).toLowerCase() ); 3980 3981 if ( data !== undefined ) { 3982 return data; 3983 } 3984 3985 camelKey = jQuery.camelCase( key ); 3986 3987 // Attempt to get data from the cache 3988 // with the key camelized 3989 data = dataUser.get( elem, camelKey ); 3990 if ( data !== undefined ) { 3991 return data; 3992 } 3993 3994 // Attempt to "discover" the data in 3995 // HTML5 custom data-* attrs 3996 data = dataAttr( elem, camelKey, undefined ); 3997 if ( data !== undefined ) { 3998 return data; 3999 } 4000 4001 // We tried really hard, but the data doesn't exist. 4002 return; 4003 } 4004 4005 // Set the data... 4006 camelKey = jQuery.camelCase( key ); 4007 this.each( function() { 4008 4009 // First, attempt to store a copy or reference of any 4010 // data that might've been store with a camelCased key. 4011 var data = dataUser.get( this, camelKey ); 4012 4013 // For HTML5 data-* attribute interop, we have to 4014 // store property names with dashes in a camelCase form. 4015 // This might not apply to all properties...* 4016 dataUser.set( this, camelKey, value ); 4017 4018 // *... In the case of properties that might _actually_ 4019 // have dashes, we need to also store a copy of that 4020 // unchanged property. 4021 if ( key.indexOf( "-" ) > -1 && data !== undefined ) { 4022 dataUser.set( this, key, value ); 4023 } 4024 } ); 4025 }, null, value, arguments.length > 1, null, true ); 4026 }, 4027 4028 removeData: function( key ) { 4029 return this.each( function() { 4030 dataUser.remove( this, key ); 4031 } ); 4032 } 4033} ); 4034 4035 4036jQuery.extend( { 4037 queue: function( elem, type, data ) { 4038 var queue; 4039 4040 if ( elem ) { 4041 type = ( type || "fx" ) + "queue"; 4042 queue = dataPriv.get( elem, type ); 4043 4044 // Speed up dequeue by getting out quickly if this is just a lookup 4045 if ( data ) { 4046 if ( !queue || jQuery.isArray( data ) ) { 4047 queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); 4048 } else { 4049 queue.push( data ); 4050 } 4051 } 4052 return queue || []; 4053 } 4054 }, 4055 4056 dequeue: function( elem, type ) { 4057 type = type || "fx"; 4058 4059 var queue = jQuery.queue( elem, type ), 4060 startLength = queue.length, 4061 fn = queue.shift(), 4062 hooks = jQuery._queueHooks( elem, type ), 4063 next = function() { 4064 jQuery.dequeue( elem, type ); 4065 }; 4066 4067 // If the fx queue is dequeued, always remove the progress sentinel 4068 if ( fn === "inprogress" ) { 4069 fn = queue.shift(); 4070 startLength--; 4071 } 4072 4073 if ( fn ) { 4074 4075 // Add a progress sentinel to prevent the fx queue from being 4076 // automatically dequeued 4077 if ( type === "fx" ) { 4078 queue.unshift( "inprogress" ); 4079 } 4080 4081 // Clear up the last queue stop function 4082 delete hooks.stop; 4083 fn.call( elem, next, hooks ); 4084 } 4085 4086 if ( !startLength && hooks ) { 4087 hooks.empty.fire(); 4088 } 4089 }, 4090 4091 // Not public - generate a queueHooks object, or return the current one 4092 _queueHooks: function( elem, type ) { 4093 var key = type + "queueHooks"; 4094 return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { 4095 empty: jQuery.Callbacks( "once memory" ).add( function() { 4096 dataPriv.remove( elem, [ type + "queue", key ] ); 4097 } ) 4098 } ); 4099 } 4100} ); 4101 4102jQuery.fn.extend( { 4103 queue: function( type, data ) { 4104 var setter = 2; 4105 4106 if ( typeof type !== "string" ) { 4107 data = type; 4108 type = "fx"; 4109 setter--; 4110 } 4111 4112 if ( arguments.length < setter ) { 4113 return jQuery.queue( this[ 0 ], type ); 4114 } 4115 4116 return data === undefined ? 4117 this : 4118 this.each( function() { 4119 var queue = jQuery.queue( this, type, data ); 4120 4121 // Ensure a hooks for this queue 4122 jQuery._queueHooks( this, type ); 4123 4124 if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { 4125 jQuery.dequeue( this, type ); 4126 } 4127 } ); 4128 }, 4129 dequeue: function( type ) { 4130 return this.each( function() { 4131 jQuery.dequeue( this, type ); 4132 } ); 4133 }, 4134 clearQueue: function( type ) { 4135 return this.queue( type || "fx", [] ); 4136 }, 4137 4138 // Get a promise resolved when queues of a certain type 4139 // are emptied (fx is the type by default) 4140 promise: function( type, obj ) { 4141 var tmp, 4142 count = 1, 4143 defer = jQuery.Deferred(), 4144 elements = this, 4145 i = this.length, 4146 resolve = function() { 4147 if ( !( --count ) ) { 4148 defer.resolveWith( elements, [ elements ] ); 4149 } 4150 }; 4151 4152 if ( typeof type !== "string" ) { 4153 obj = type; 4154 type = undefined; 4155 } 4156 type = type || "fx"; 4157 4158 while ( i-- ) { 4159 tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); 4160 if ( tmp && tmp.empty ) { 4161 count++; 4162 tmp.empty.add( resolve ); 4163 } 4164 } 4165 resolve(); 4166 return defer.promise( obj ); 4167 } 4168} ); 4169var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; 4170 4171var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); 4172 4173 4174var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; 4175 4176var isHidden = function( elem, el ) { 4177 4178 // isHidden might be called from jQuery#filter function; 4179 // in that case, element will be second argument 4180 elem = el || elem; 4181 return jQuery.css( elem, "display" ) === "none" || 4182 !jQuery.contains( elem.ownerDocument, elem ); 4183 }; 4184 4185 4186 4187function adjustCSS( elem, prop, valueParts, tween ) { 4188 var adjusted, 4189 scale = 1, 4190 maxIterations = 20, 4191 currentValue = tween ? 4192 function() { return tween.cur(); } : 4193 function() { return jQuery.css( elem, prop, "" ); }, 4194 initial = currentValue(), 4195 unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), 4196 4197 // Starting value computation is required for potential unit mismatches 4198 initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && 4199 rcssNum.exec( jQuery.css( elem, prop ) ); 4200 4201 if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { 4202 4203 // Trust units reported by jQuery.css 4204 unit = unit || initialInUnit[ 3 ]; 4205 4206 // Make sure we update the tween properties later on 4207 valueParts = valueParts || []; 4208 4209 // Iteratively approximate from a nonzero starting point 4210 initialInUnit = +initial || 1; 4211 4212 do { 4213 4214 // If previous iteration zeroed out, double until we get *something*. 4215 // Use string for doubling so we don't accidentally see scale as unchanged below 4216 scale = scale || ".5"; 4217 4218 // Adjust and apply 4219 initialInUnit = initialInUnit / scale; 4220 jQuery.style( elem, prop, initialInUnit + unit ); 4221 4222 // Update scale, tolerating zero or NaN from tween.cur() 4223 // Break the loop if scale is unchanged or perfect, or if we've just had enough. 4224 } while ( 4225 scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations 4226 ); 4227 } 4228 4229 if ( valueParts ) { 4230 initialInUnit = +initialInUnit || +initial || 0; 4231 4232 // Apply relative offset (+=/-=) if specified 4233 adjusted = valueParts[ 1 ] ? 4234 initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : 4235 +valueParts[ 2 ]; 4236 if ( tween ) { 4237 tween.unit = unit; 4238 tween.start = initialInUnit; 4239 tween.end = adjusted; 4240 } 4241 } 4242 return adjusted; 4243} 4244var rcheckableType = ( /^(?:checkbox|radio)$/i ); 4245 4246var rtagName = ( /<([\w:-]+)/ ); 4247 4248var rscriptType = ( /^$|\/(?:java|ecma)script/i ); 4249 4250 4251 4252// We have to close these tags to support XHTML (#13200) 4253var wrapMap = { 4254 4255 // Support: IE9 4256 option: [ 1, "<select multiple='multiple'>", "</select>" ], 4257 4258 // XHTML parsers do not magically insert elements in the 4259 // same way that tag soup parsers do. So we cannot shorten 4260 // this by omitting <tbody> or other required elements. 4261 thead: [ 1, "<table>", "</table>" ], 4262 col: [ 2, "<table><colgroup>", "</colgroup></table>" ], 4263 tr: [ 2, "<table><tbody>", "</tbody></table>" ], 4264 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], 4265 4266 _default: [ 0, "", "" ] 4267}; 4268 4269// Support: IE9 4270wrapMap.optgroup = wrapMap.option; 4271 4272wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; 4273wrapMap.th = wrapMap.td; 4274 4275 4276function getAll( context, tag ) { 4277 4278 // Support: IE9-11+ 4279 // Use typeof to avoid zero-argument method invocation on host objects (#15151) 4280 var ret = typeof context.getElementsByTagName !== "undefined" ? 4281 context.getElementsByTagName( tag || "*" ) : 4282 typeof context.querySelectorAll !== "undefined" ? 4283 context.querySelectorAll( tag || "*" ) : 4284 []; 4285 4286 return tag === undefined || tag && jQuery.nodeName( context, tag ) ? 4287 jQuery.merge( [ context ], ret ) : 4288 ret; 4289} 4290 4291 4292// Mark scripts as having already been evaluated 4293function setGlobalEval( elems, refElements ) { 4294 var i = 0, 4295 l = elems.length; 4296 4297 for ( ; i < l; i++ ) { 4298 dataPriv.set( 4299 elems[ i ], 4300 "globalEval", 4301 !refElements || dataPriv.get( refElements[ i ], "globalEval" ) 4302 ); 4303 } 4304} 4305 4306 4307var rhtml = /<|&#?\w+;/; 4308 4309function buildFragment( elems, context, scripts, selection, ignored ) { 4310 var elem, tmp, tag, wrap, contains, j, 4311 fragment = context.createDocumentFragment(), 4312 nodes = [], 4313 i = 0, 4314 l = elems.length; 4315 4316 for ( ; i < l; i++ ) { 4317 elem = elems[ i ]; 4318 4319 if ( elem || elem === 0 ) { 4320 4321 // Add nodes directly 4322 if ( jQuery.type( elem ) === "object" ) { 4323 4324 // Support: Android<4.1, PhantomJS<2 4325 // push.apply(_, arraylike) throws on ancient WebKit 4326 jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); 4327 4328 // Convert non-html into a text node 4329 } else if ( !rhtml.test( elem ) ) { 4330 nodes.push( context.createTextNode( elem ) ); 4331 4332 // Convert html into DOM nodes 4333 } else { 4334 tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); 4335 4336 // Deserialize a standard representation 4337 tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); 4338 wrap = wrapMap[ tag ] || wrapMap._default; 4339 tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; 4340 4341 // Descend through wrappers to the right content 4342 j = wrap[ 0 ]; 4343 while ( j-- ) { 4344 tmp = tmp.lastChild; 4345 } 4346 4347 // Support: Android<4.1, PhantomJS<2 4348 // push.apply(_, arraylike) throws on ancient WebKit 4349 jQuery.merge( nodes, tmp.childNodes ); 4350 4351 // Remember the top-level container 4352 tmp = fragment.firstChild; 4353 4354 // Ensure the created nodes are orphaned (#12392) 4355 tmp.textContent = ""; 4356 } 4357 } 4358 } 4359 4360 // Remove wrapper from fragment 4361 fragment.textContent = ""; 4362 4363 i = 0; 4364 while ( ( elem = nodes[ i++ ] ) ) { 4365 4366 // Skip elements already in the context collection (trac-4087) 4367 if ( selection && jQuery.inArray( elem, selection ) > -1 ) { 4368 if ( ignored ) { 4369 ignored.push( elem ); 4370 } 4371 continue; 4372 } 4373 4374 contains = jQuery.contains( elem.ownerDocument, elem ); 4375 4376 // Append to fragment 4377 tmp = getAll( fragment.appendChild( elem ), "script" ); 4378 4379 // Preserve script evaluation history 4380 if ( contains ) { 4381 setGlobalEval( tmp ); 4382 } 4383 4384 // Capture executables 4385 if ( scripts ) { 4386 j = 0; 4387 while ( ( elem = tmp[ j++ ] ) ) { 4388 if ( rscriptType.test( elem.type || "" ) ) { 4389 scripts.push( elem ); 4390 } 4391 } 4392 } 4393 } 4394 4395 return fragment; 4396} 4397 4398 4399( function() { 4400 var fragment = document.createDocumentFragment(), 4401 div = fragment.appendChild( document.createElement( "div" ) ), 4402 input = document.createElement( "input" ); 4403 4404 // Support: Android 4.0-4.3, Safari<=5.1 4405 // Check state lost if the name is set (#11217) 4406 // Support: Windows Web Apps (WWA) 4407 // `name` and `type` must use .setAttribute for WWA (#14901) 4408 input.setAttribute( "type", "radio" ); 4409 input.setAttribute( "checked", "checked" ); 4410 input.setAttribute( "name", "t" ); 4411 4412 div.appendChild( input ); 4413 4414 // Support: Safari<=5.1, Android<4.2 4415 // Older WebKit doesn't clone checked state correctly in fragments 4416 support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; 4417 4418 // Support: IE<=11+ 4419 // Make sure textarea (and checkbox) defaultValue is properly cloned 4420 div.innerHTML = "<textarea>x</textarea>"; 4421 support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; 4422} )(); 4423 4424 4425var 4426 rkeyEvent = /^key/, 4427 rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, 4428 rtypenamespace = /^([^.]*)(?:\.(.+)|)/; 4429 4430function returnTrue() { 4431 return true; 4432} 4433 4434function returnFalse() { 4435 return false; 4436} 4437 4438// Support: IE9 4439// See #13393 for more info 4440function safeActiveElement() { 4441 try { 4442 return document.activeElement; 4443 } catch ( err ) { } 4444} 4445 4446function on( elem, types, selector, data, fn, one ) { 4447 var origFn, type; 4448 4449 // Types can be a map of types/handlers 4450 if ( typeof types === "object" ) { 4451 4452 // ( types-Object, selector, data ) 4453 if ( typeof selector !== "string" ) { 4454 4455 // ( types-Object, data ) 4456 data = data || selector; 4457 selector = undefined; 4458 } 4459 for ( type in types ) { 4460 on( elem, type, selector, data, types[ type ], one ); 4461 } 4462 return elem; 4463 } 4464 4465 if ( data == null && fn == null ) { 4466 4467 // ( types, fn ) 4468 fn = selector; 4469 data = selector = undefined; 4470 } else if ( fn == null ) { 4471 if ( typeof selector === "string" ) { 4472 4473 // ( types, selector, fn ) 4474 fn = data; 4475 data = undefined; 4476 } else { 4477 4478 // ( types, data, fn ) 4479 fn = data; 4480 data = selector; 4481 selector = undefined; 4482 } 4483 } 4484 if ( fn === false ) { 4485 fn = returnFalse; 4486 } else if ( !fn ) { 4487 return elem; 4488 } 4489 4490 if ( one === 1 ) { 4491 origFn = fn; 4492 fn = function( event ) { 4493 4494 // Can use an empty set, since event contains the info 4495 jQuery().off( event ); 4496 return origFn.apply( this, arguments ); 4497 }; 4498 4499 // Use same guid so caller can remove using origFn 4500 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); 4501 } 4502 return elem.each( function() { 4503 jQuery.event.add( this, types, fn, data, selector ); 4504 } ); 4505} 4506 4507/* 4508 * Helper functions for managing events -- not part of the public interface. 4509 * Props to Dean Edwards' addEvent library for many of the ideas. 4510 */ 4511jQuery.event = { 4512 4513 global: {}, 4514 4515 add: function( elem, types, handler, data, selector ) { 4516 4517 var handleObjIn, eventHandle, tmp, 4518 events, t, handleObj, 4519 special, handlers, type, namespaces, origType, 4520 elemData = dataPriv.get( elem ); 4521 4522 // Don't attach events to noData or text/comment nodes (but allow plain objects) 4523 if ( !elemData ) { 4524 return; 4525 } 4526 4527 // Caller can pass in an object of custom data in lieu of the handler 4528 if ( handler.handler ) { 4529 handleObjIn = handler; 4530 handler = handleObjIn.handler; 4531 selector = handleObjIn.selector; 4532 } 4533 4534 // Make sure that the handler has a unique ID, used to find/remove it later 4535 if ( !handler.guid ) { 4536 handler.guid = jQuery.guid++; 4537 } 4538 4539 // Init the element's event structure and main handler, if this is the first 4540 if ( !( events = elemData.events ) ) { 4541 events = elemData.events = {}; 4542 } 4543 if ( !( eventHandle = elemData.handle ) ) { 4544 eventHandle = elemData.handle = function( e ) { 4545 4546 // Discard the second event of a jQuery.event.trigger() and 4547 // when an event is called after a page has unloaded 4548 return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? 4549 jQuery.event.dispatch.apply( elem, arguments ) : undefined; 4550 }; 4551 } 4552 4553 // Handle multiple events separated by a space 4554 types = ( types || "" ).match( rnotwhite ) || [ "" ]; 4555 t = types.length; 4556 while ( t-- ) { 4557 tmp = rtypenamespace.exec( types[ t ] ) || []; 4558 type = origType = tmp[ 1 ]; 4559 namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); 4560 4561 // There *must* be a type, no attaching namespace-only handlers 4562 if ( !type ) { 4563 continue; 4564 } 4565 4566 // If event changes its type, use the special event handlers for the changed type 4567 special = jQuery.event.special[ type ] || {}; 4568 4569 // If selector defined, determine special event api type, otherwise given type 4570 type = ( selector ? special.delegateType : special.bindType ) || type; 4571 4572 // Update special based on newly reset type 4573 special = jQuery.event.special[ type ] || {}; 4574 4575 // handleObj is passed to all event handlers 4576 handleObj = jQuery.extend( { 4577 type: type, 4578 origType: origType, 4579 data: data, 4580 handler: handler, 4581 guid: handler.guid, 4582 selector: selector, 4583 needsContext: selector && jQuery.expr.match.needsContext.test( selector ), 4584 namespace: namespaces.join( "." ) 4585 }, handleObjIn ); 4586 4587 // Init the event handler queue if we're the first 4588 if ( !( handlers = events[ type ] ) ) { 4589 handlers = events[ type ] = []; 4590 handlers.delegateCount = 0; 4591 4592 // Only use addEventListener if the special events handler returns false 4593 if ( !special.setup || 4594 special.setup.call( elem, data, namespaces, eventHandle ) === false ) { 4595 4596 if ( elem.addEventListener ) { 4597 elem.addEventListener( type, eventHandle ); 4598 } 4599 } 4600 } 4601 4602 if ( special.add ) { 4603 special.add.call( elem, handleObj ); 4604 4605 if ( !handleObj.handler.guid ) { 4606 handleObj.handler.guid = handler.guid; 4607 } 4608 } 4609 4610 // Add to the element's handler list, delegates in front 4611 if ( selector ) { 4612 handlers.splice( handlers.delegateCount++, 0, handleObj ); 4613 } else { 4614 handlers.push( handleObj ); 4615 } 4616 4617 // Keep track of which events have ever been used, for event optimization 4618 jQuery.event.global[ type ] = true; 4619 } 4620 4621 }, 4622 4623 // Detach an event or set of events from an element 4624 remove: function( elem, types, handler, selector, mappedTypes ) { 4625 4626 var j, origCount, tmp, 4627 events, t, handleObj, 4628 special, handlers, type, namespaces, origType, 4629 elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); 4630 4631 if ( !elemData || !( events = elemData.events ) ) { 4632 return; 4633 } 4634 4635 // Once for each type.namespace in types; type may be omitted 4636 types = ( types || "" ).match( rnotwhite ) || [ "" ]; 4637 t = types.length; 4638 while ( t-- ) { 4639 tmp = rtypenamespace.exec( types[ t ] ) || []; 4640 type = origType = tmp[ 1 ]; 4641 namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); 4642 4643 // Unbind all events (on this namespace, if provided) for the element 4644 if ( !type ) { 4645 for ( type in events ) { 4646 jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); 4647 } 4648 continue; 4649 } 4650 4651 special = jQuery.event.special[ type ] || {}; 4652 type = ( selector ? special.delegateType : special.bindType ) || type; 4653 handlers = events[ type ] || []; 4654 tmp = tmp[ 2 ] && 4655 new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); 4656 4657 // Remove matching events 4658 origCount = j = handlers.length; 4659 while ( j-- ) { 4660 handleObj = handlers[ j ]; 4661 4662 if ( ( mappedTypes || origType === handleObj.origType ) && 4663 ( !handler || handler.guid === handleObj.guid ) && 4664 ( !tmp || tmp.test( handleObj.namespace ) ) && 4665 ( !selector || selector === handleObj.selector || 4666 selector === "**" && handleObj.selector ) ) { 4667 handlers.splice( j, 1 ); 4668 4669 if ( handleObj.selector ) { 4670 handlers.delegateCount--; 4671 } 4672 if ( special.remove ) { 4673 special.remove.call( elem, handleObj ); 4674 } 4675 } 4676 } 4677 4678 // Remove generic event handler if we removed something and no more handlers exist 4679 // (avoids potential for endless recursion during removal of special event handlers) 4680 if ( origCount && !handlers.length ) { 4681 if ( !special.teardown || 4682 special.teardown.call( elem, namespaces, elemData.handle ) === false ) { 4683 4684 jQuery.removeEvent( elem, type, elemData.handle ); 4685 } 4686 4687 delete events[ type ]; 4688 } 4689 } 4690 4691 // Remove data and the expando if it's no longer used 4692 if ( jQuery.isEmptyObject( events ) ) { 4693 dataPriv.remove( elem, "handle events" ); 4694 } 4695 }, 4696 4697 dispatch: function( event ) { 4698 4699 // Make a writable jQuery.Event from the native event object 4700 event = jQuery.event.fix( event ); 4701 4702 var i, j, ret, matched, handleObj, 4703 handlerQueue = [], 4704 args = slice.call( arguments ), 4705 handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], 4706 special = jQuery.event.special[ event.type ] || {}; 4707 4708 // Use the fix-ed jQuery.Event rather than the (read-only) native event 4709 args[ 0 ] = event; 4710 event.delegateTarget = this; 4711 4712 // Call the preDispatch hook for the mapped type, and let it bail if desired 4713 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { 4714 return; 4715 } 4716 4717 // Determine handlers 4718 handlerQueue = jQuery.event.handlers.call( this, event, handlers ); 4719 4720 // Run delegates first; they may want to stop propagation beneath us 4721 i = 0; 4722 while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { 4723 event.currentTarget = matched.elem; 4724 4725 j = 0; 4726 while ( ( handleObj = matched.handlers[ j++ ] ) && 4727 !event.isImmediatePropagationStopped() ) { 4728 4729 // Triggered event must either 1) have no namespace, or 2) have namespace(s) 4730 // a subset or equal to those in the bound event (both can have no namespace). 4731 if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { 4732 4733 event.handleObj = handleObj; 4734 event.data = handleObj.data; 4735 4736 ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || 4737 handleObj.handler ).apply( matched.elem, args ); 4738 4739 if ( ret !== undefined ) { 4740 if ( ( event.result = ret ) === false ) { 4741 event.preventDefault(); 4742 event.stopPropagation(); 4743 } 4744 } 4745 } 4746 } 4747 } 4748 4749 // Call the postDispatch hook for the mapped type 4750 if ( special.postDispatch ) { 4751 special.postDispatch.call( this, event ); 4752 } 4753 4754 return event.result; 4755 }, 4756 4757 handlers: function( event, handlers ) { 4758 var i, matches, sel, handleObj, 4759 handlerQueue = [], 4760 delegateCount = handlers.delegateCount, 4761 cur = event.target; 4762 4763 // Support (at least): Chrome, IE9 4764 // Find delegate handlers 4765 // Black-hole SVG <use> instance trees (#13180) 4766 // 4767 // Support: Firefox<=42+ 4768 // Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343) 4769 if ( delegateCount && cur.nodeType && 4770 ( event.type !== "click" || isNaN( event.button ) || event.button < 1 ) ) { 4771 4772 for ( ; cur !== this; cur = cur.parentNode || this ) { 4773 4774 // Don't check non-elements (#13208) 4775 // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) 4776 if ( cur.nodeType === 1 && ( cur.disabled !== true || event.type !== "click" ) ) { 4777 matches = []; 4778 for ( i = 0; i < delegateCount; i++ ) { 4779 handleObj = handlers[ i ]; 4780 4781 // Don't conflict with Object.prototype properties (#13203) 4782 sel = handleObj.selector + " "; 4783 4784 if ( matches[ sel ] === undefined ) { 4785 matches[ sel ] = handleObj.needsContext ? 4786 jQuery( sel, this ).index( cur ) > -1 : 4787 jQuery.find( sel, this, null, [ cur ] ).length; 4788 } 4789 if ( matches[ sel ] ) { 4790 matches.push( handleObj ); 4791 } 4792 } 4793 if ( matches.length ) { 4794 handlerQueue.push( { elem: cur, handlers: matches } ); 4795 } 4796 } 4797 } 4798 } 4799 4800 // Add the remaining (directly-bound) handlers 4801 if ( delegateCount < handlers.length ) { 4802 handlerQueue.push( { elem: this, handlers: handlers.slice( delegateCount ) } ); 4803 } 4804 4805 return handlerQueue; 4806 }, 4807 4808 // Includes some event props shared by KeyEvent and MouseEvent 4809 props: ( "altKey bubbles cancelable ctrlKey currentTarget detail eventPhase " + 4810 "metaKey relatedTarget shiftKey target timeStamp view which" ).split( " " ), 4811 4812 fixHooks: {}, 4813 4814 keyHooks: { 4815 props: "char charCode key keyCode".split( " " ), 4816 filter: function( event, original ) { 4817 4818 // Add which for key events 4819 if ( event.which == null ) { 4820 event.which = original.charCode != null ? original.charCode : original.keyCode; 4821 } 4822 4823 return event; 4824 } 4825 }, 4826 4827 mouseHooks: { 4828 props: ( "button buttons clientX clientY offsetX offsetY pageX pageY " + 4829 "screenX screenY toElement" ).split( " " ), 4830 filter: function( event, original ) { 4831 var eventDoc, doc, body, 4832 button = original.button; 4833 4834 // Calculate pageX/Y if missing and clientX/Y available 4835 if ( event.pageX == null && original.clientX != null ) { 4836 eventDoc = event.target.ownerDocument || document; 4837 doc = eventDoc.documentElement; 4838 body = eventDoc.body; 4839 4840 event.pageX = original.clientX + 4841 ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - 4842 ( doc && doc.clientLeft || body && body.clientLeft || 0 ); 4843 event.pageY = original.clientY + 4844 ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - 4845 ( doc && doc.clientTop || body && body.clientTop || 0 ); 4846 } 4847 4848 // Add which for click: 1 === left; 2 === middle; 3 === right 4849 // Note: button is not normalized, so don't use it 4850 if ( !event.which && button !== undefined ) { 4851 event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); 4852 } 4853 4854 return event; 4855 } 4856 }, 4857 4858 fix: function( event ) { 4859 if ( event[ jQuery.expando ] ) { 4860 return event; 4861 } 4862 4863 // Create a writable copy of the event object and normalize some properties 4864 var i, prop, copy, 4865 type = event.type, 4866 originalEvent = event, 4867 fixHook = this.fixHooks[ type ]; 4868 4869 if ( !fixHook ) { 4870 this.fixHooks[ type ] = fixHook = 4871 rmouseEvent.test( type ) ? this.mouseHooks : 4872 rkeyEvent.test( type ) ? this.keyHooks : 4873 {}; 4874 } 4875 copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; 4876 4877 event = new jQuery.Event( originalEvent ); 4878 4879 i = copy.length; 4880 while ( i-- ) { 4881 prop = copy[ i ]; 4882 event[ prop ] = originalEvent[ prop ]; 4883 } 4884 4885 // Support: Cordova 2.5 (WebKit) (#13255) 4886 // All events should have a target; Cordova deviceready doesn't 4887 if ( !event.target ) { 4888 event.target = document; 4889 } 4890 4891 // Support: Safari 6.0+, Chrome<28 4892 // Target should not be a text node (#504, #13143) 4893 if ( event.target.nodeType === 3 ) { 4894 event.target = event.target.parentNode; 4895 } 4896 4897 return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; 4898 }, 4899 4900 special: { 4901 load: { 4902 4903 // Prevent triggered image.load events from bubbling to window.load 4904 noBubble: true 4905 }, 4906 focus: { 4907 4908 // Fire native event if possible so blur/focus sequence is correct 4909 trigger: function() { 4910 if ( this !== safeActiveElement() && this.focus ) { 4911 this.focus(); 4912 return false; 4913 } 4914 }, 4915 delegateType: "focusin" 4916 }, 4917 blur: { 4918 trigger: function() { 4919 if ( this === safeActiveElement() && this.blur ) { 4920 this.blur(); 4921 return false; 4922 } 4923 }, 4924 delegateType: "focusout" 4925 }, 4926 click: { 4927 4928 // For checkbox, fire native event so checked state will be right 4929 trigger: function() { 4930 if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) { 4931 this.click(); 4932 return false; 4933 } 4934 }, 4935 4936 // For cross-browser consistency, don't fire native .click() on links 4937 _default: function( event ) { 4938 return jQuery.nodeName( event.target, "a" ); 4939 } 4940 }, 4941 4942 beforeunload: { 4943 postDispatch: function( event ) { 4944 4945 // Support: Firefox 20+ 4946 // Firefox doesn't alert if the returnValue field is not set. 4947 if ( event.result !== undefined && event.originalEvent ) { 4948 event.originalEvent.returnValue = event.result; 4949 } 4950 } 4951 } 4952 } 4953}; 4954 4955jQuery.removeEvent = function( elem, type, handle ) { 4956 4957 // This "if" is needed for plain objects 4958 if ( elem.removeEventListener ) { 4959 elem.removeEventListener( type, handle ); 4960 } 4961}; 4962 4963jQuery.Event = function( src, props ) { 4964 4965 // Allow instantiation without the 'new' keyword 4966 if ( !( this instanceof jQuery.Event ) ) { 4967 return new jQuery.Event( src, props ); 4968 } 4969 4970 // Event object 4971 if ( src && src.type ) { 4972 this.originalEvent = src; 4973 this.type = src.type; 4974 4975 // Events bubbling up the document may have been marked as prevented 4976 // by a handler lower down the tree; reflect the correct value. 4977 this.isDefaultPrevented = src.defaultPrevented || 4978 src.defaultPrevented === undefined && 4979 4980 // Support: Android<4.0 4981 src.returnValue === false ? 4982 returnTrue : 4983 returnFalse; 4984 4985 // Event type 4986 } else { 4987 this.type = src; 4988 } 4989 4990 // Put explicitly provided properties onto the event object 4991 if ( props ) { 4992 jQuery.extend( this, props ); 4993 } 4994 4995 // Create a timestamp if incoming event doesn't have one 4996 this.timeStamp = src && src.timeStamp || jQuery.now(); 4997 4998 // Mark it as fixed 4999 this[ jQuery.expando ] = true; 5000}; 5001 5002// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding 5003// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html 5004jQuery.Event.prototype = { 5005 constructor: jQuery.Event, 5006 isDefaultPrevented: returnFalse, 5007 isPropagationStopped: returnFalse, 5008 isImmediatePropagationStopped: returnFalse,
5009 5010 preventDefault: function() { 5011 var e = this.originalEvent; 5012 5013 this.isDefaultPrevented = returnTrue; 5014 5015 if ( e ) { 5016 e.preventDefault(); 5017 } 5018 }, 5019 stopPropagation: function() { 5020 var e = this.originalEvent; 5021 5022 this.isPropagationStopped = returnTrue; 5023 5024 if ( e ) { 5025 e.stopPropagation(); 5026 } 5027 }, 5028 stopImmediatePropagation: function() { 5029 var e = this.originalEvent; 5030 5031 this.isImmediatePropagationStopped = returnTrue; 5032 5033 if ( e
vendor: 24,946 bytes, lines 5033-5964
5033 ) { 5034 e.stopImmediatePropagation(); 5035 } 5036 5037 this.stopPropagation(); 5038 } 5039}; 5040 5041// Create mouseenter/leave events using mouseover/out and event-time checks 5042// so that event delegation works in jQuery. 5043// Do the same for pointerenter/pointerleave and pointerover/pointerout 5044// 5045// Support: Safari 7 only 5046// Safari sends mouseenter too often; see: 5047// https://code.google.com/p/chromium/issues/detail?id=470258 5048// for the description of the bug (it existed in older Chrome versions as well). 5049jQuery.each( { 5050 mouseenter: "mouseover", 5051 mouseleave: "mouseout", 5052 pointerenter: "pointerover", 5053 pointerleave: "pointerout" 5054}, function( orig, fix ) { 5055 jQuery.event.special[ orig ] = { 5056 delegateType: fix, 5057 bindType: fix, 5058 5059 handle: function( event ) { 5060 var ret, 5061 target = this, 5062 related = event.relatedTarget, 5063 handleObj = event.handleObj; 5064 5065 // For mouseenter/leave call the handler if related is outside the target. 5066 // NB: No relatedTarget if the mouse left/entered the browser window 5067 if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { 5068 event.type = handleObj.origType; 5069 ret = handleObj.handler.apply( this, arguments ); 5070 event.type = fix; 5071 } 5072 return ret; 5073 } 5074 }; 5075} ); 5076 5077jQuery.fn.extend( { 5078 on: function( types, selector, data, fn ) { 5079 return on( this, types, selector, data, fn ); 5080 }, 5081 one: function( types, selector, data, fn ) { 5082 return on( this, types, selector, data, fn, 1 ); 5083 }, 5084 off: function( types, selector, fn ) { 5085 var handleObj, type; 5086 if ( types && types.preventDefault && types.handleObj ) { 5087 5088 // ( event ) dispatched jQuery.Event 5089 handleObj = types.handleObj; 5090 jQuery( types.delegateTarget ).off( 5091 handleObj.namespace ? 5092 handleObj.origType + "." + handleObj.namespace : 5093 handleObj.origType, 5094 handleObj.selector, 5095 handleObj.handler 5096 ); 5097 return this; 5098 } 5099 if ( typeof types === "object" ) { 5100 5101 // ( types-object [, selector] ) 5102 for ( type in types ) { 5103 this.off( type, selector, types[ type ] ); 5104 } 5105 return this; 5106 } 5107 if ( selector === false || typeof selector === "function" ) { 5108 5109 // ( types [, fn] ) 5110 fn = selector; 5111 selector = undefined; 5112 } 5113 if ( fn === false ) { 5114 fn = returnFalse; 5115 } 5116 return this.each( function() { 5117 jQuery.event.remove( this, types, fn, selector ); 5118 } ); 5119 } 5120} ); 5121 5122 5123var 5124 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi, 5125 5126 // Support: IE 10-11, Edge 10240+ 5127 // In IE/Edge using regex groups here causes severe slowdowns. 5128 // See https://connect.microsoft.com/IE/feedback/details/1736512/ 5129 rnoInnerhtml = /<script|<style|<link/i, 5130 5131 // checked="checked" or checked 5132 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, 5133 rscriptTypeMasked = /^true\/(.*)/, 5134 rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g; 5135 5136// Manipulating tables requires a tbody 5137function manipulationTarget( elem, content ) { 5138 return jQuery.nodeName( elem, "table" ) && 5139 jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ? 5140 5141 elem.getElementsByTagName( "tbody" )[ 0 ] || 5142 elem.appendChild( elem.ownerDocument.createElement( "tbody" ) ) : 5143 elem; 5144} 5145 5146// Replace/restore the type attribute of script elements for safe DOM manipulation 5147function disableScript( elem ) { 5148 elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; 5149 return elem; 5150} 5151function restoreScript( elem ) { 5152 var match = rscriptTypeMasked.exec( elem.type ); 5153 5154 if ( match ) { 5155 elem.type = match[ 1 ]; 5156 } else { 5157 elem.removeAttribute( "type" ); 5158 } 5159 5160 return elem; 5161} 5162 5163function cloneCopyEvent( src, dest ) { 5164 var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; 5165 5166 if ( dest.nodeType !== 1 ) { 5167 return; 5168 } 5169 5170 // 1. Copy private data: events, handlers, etc. 5171 if ( dataPriv.hasData( src ) ) { 5172 pdataOld = dataPriv.access( src ); 5173 pdataCur = dataPriv.set( dest, pdataOld ); 5174 events = pdataOld.events; 5175 5176 if ( events ) { 5177 delete pdataCur.handle; 5178 pdataCur.events = {}; 5179 5180 for ( type in events ) { 5181 for ( i = 0, l = events[ type ].length; i < l; i++ ) { 5182 jQuery.event.add( dest, type, events[ type ][ i ] ); 5183 } 5184 } 5185 } 5186 } 5187 5188 // 2. Copy user data 5189 if ( dataUser.hasData( src ) ) { 5190 udataOld = dataUser.access( src ); 5191 udataCur = jQuery.extend( {}, udataOld ); 5192 5193 dataUser.set( dest, udataCur ); 5194 } 5195} 5196 5197// Fix IE bugs, see support tests 5198function fixInput( src, dest ) { 5199 var nodeName = dest.nodeName.toLowerCase(); 5200 5201 // Fails to persist the checked state of a cloned checkbox or radio button. 5202 if ( nodeName === "input" && rcheckableType.test( src.type ) ) { 5203 dest.checked = src.checked; 5204 5205 // Fails to return the selected option to the default selected state when cloning options 5206 } else if ( nodeName === "input" || nodeName === "textarea" ) { 5207 dest.defaultValue = src.defaultValue; 5208 } 5209} 5210 5211function domManip( collection, args, callback, ignored ) { 5212 5213 // Flatten any nested arrays 5214 args = concat.apply( [], args ); 5215 5216 var fragment, first, scripts, hasScripts, node, doc, 5217 i = 0, 5218 l = collection.length, 5219 iNoClone = l - 1, 5220 value = args[ 0 ], 5221 isFunction = jQuery.isFunction( value ); 5222 5223 // We can't cloneNode fragments that contain checked, in WebKit 5224 if ( isFunction || 5225 ( l > 1 && typeof value === "string" && 5226 !support.checkClone && rchecked.test( value ) ) ) { 5227 return collection.each( function( index ) { 5228 var self = collection.eq( index ); 5229 if ( isFunction ) { 5230 args[ 0 ] = value.call( this, index, self.html() ); 5231 } 5232 domManip( self, args, callback, ignored ); 5233 } ); 5234 } 5235 5236 if ( l ) { 5237 fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); 5238 first = fragment.firstChild; 5239 5240 if ( fragment.childNodes.length === 1 ) { 5241 fragment = first; 5242 } 5243 5244 // Require either new content or an interest in ignored elements to invoke the callback 5245 if ( first || ignored ) { 5246 scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); 5247 hasScripts = scripts.length; 5248 5249 // Use the original fragment for the last item 5250 // instead of the first because it can end up 5251 // being emptied incorrectly in certain situations (#8070). 5252 for ( ; i < l; i++ ) { 5253 node = fragment; 5254 5255 if ( i !== iNoClone ) { 5256 node = jQuery.clone( node, true, true ); 5257 5258 // Keep references to cloned scripts for later restoration 5259 if ( hasScripts ) { 5260 5261 // Support: Android<4.1, PhantomJS<2 5262 // push.apply(_, arraylike) throws on ancient WebKit 5263 jQuery.merge( scripts, getAll( node, "script" ) ); 5264 } 5265 } 5266 5267 callback.call( collection[ i ], node, i ); 5268 } 5269 5270 if ( hasScripts ) { 5271 doc = scripts[ scripts.length - 1 ].ownerDocument; 5272 5273 // Reenable scripts 5274 jQuery.map( scripts, restoreScript ); 5275 5276 // Evaluate executable scripts on first document insertion 5277 for ( i = 0; i < hasScripts; i++ ) { 5278 node = scripts[ i ]; 5279 if ( rscriptType.test( node.type || "" ) && 5280 !dataPriv.access( node, "globalEval" ) && 5281 jQuery.contains( doc, node ) ) { 5282 5283 if ( node.src ) { 5284 5285 // Optional AJAX dependency, but won't run scripts if not present 5286 if ( jQuery._evalUrl ) { 5287 jQuery._evalUrl( node.src ); 5288 } 5289 } else { 5290 jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) ); 5291 } 5292 } 5293 } 5294 } 5295 } 5296 } 5297 5298 return collection; 5299} 5300 5301function remove( elem, selector, keepData ) { 5302 var node, 5303 nodes = selector ? jQuery.filter( selector, elem ) : elem, 5304 i = 0; 5305 5306 for ( ; ( node = nodes[ i ] ) != null; i++ ) { 5307 if ( !keepData && node.nodeType === 1 ) { 5308 jQuery.cleanData( getAll( node ) ); 5309 } 5310 5311 if ( node.parentNode ) { 5312 if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { 5313 setGlobalEval( getAll( node, "script" ) ); 5314 } 5315 node.parentNode.removeChild( node ); 5316 } 5317 } 5318 5319 return elem; 5320} 5321 5322jQuery.extend( { 5323 htmlPrefilter: function( html ) { 5324 return html.replace( rxhtmlTag, "<$1></$2>" ); 5325 }, 5326 5327 clone: function( elem, dataAndEvents, deepDataAndEvents ) { 5328 var i, l, srcElements, destElements, 5329 clone = elem.cloneNode( true ), 5330 inPage = jQuery.contains( elem.ownerDocument, elem ); 5331 5332 // Fix IE cloning issues 5333 if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && 5334 !jQuery.isXMLDoc( elem ) ) { 5335 5336 // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 5337 destElements = getAll( clone ); 5338 srcElements = getAll( elem ); 5339 5340 for ( i = 0, l = srcElements.length; i < l; i++ ) { 5341 fixInput( srcElements[ i ], destElements[ i ] ); 5342 } 5343 } 5344 5345 // Copy the events from the original to the clone 5346 if ( dataAndEvents ) { 5347 if ( deepDataAndEvents ) { 5348 srcElements = srcElements || getAll( elem ); 5349 destElements = destElements || getAll( clone ); 5350 5351 for ( i = 0, l = srcElements.length; i < l; i++ ) { 5352 cloneCopyEvent( srcElements[ i ], destElements[ i ] ); 5353 } 5354 } else { 5355 cloneCopyEvent( elem, clone ); 5356 } 5357 } 5358 5359 // Preserve script evaluation history 5360 destElements = getAll( clone, "script" ); 5361 if ( destElements.length > 0 ) { 5362 setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); 5363 } 5364 5365 // Return the cloned set 5366 return clone; 5367 }, 5368 5369 cleanData: function( elems ) { 5370 var data, elem, type, 5371 special = jQuery.event.special, 5372 i = 0; 5373 5374 for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { 5375 if ( acceptData( elem ) ) { 5376 if ( ( data = elem[ dataPriv.expando ] ) ) { 5377 if ( data.events ) { 5378 for ( type in data.events ) { 5379 if ( special[ type ] ) { 5380 jQuery.event.remove( elem, type ); 5381 5382 // This is a shortcut to avoid jQuery.event.remove's overhead 5383 } else { 5384 jQuery.removeEvent( elem, type, data.handle ); 5385 } 5386 } 5387 } 5388 5389 // Support: Chrome <= 35-45+ 5390 // Assign undefined instead of using delete, see Data#remove 5391 elem[ dataPriv.expando ] = undefined; 5392 } 5393 if ( elem[ dataUser.expando ] ) { 5394 5395 // Support: Chrome <= 35-45+ 5396 // Assign undefined instead of using delete, see Data#remove 5397 elem[ dataUser.expando ] = undefined; 5398 } 5399 } 5400 } 5401 } 5402} ); 5403 5404jQuery.fn.extend( { 5405 5406 // Keep domManip exposed until 3.0 (gh-2225) 5407 domManip: domManip, 5408 5409 detach: function( selector ) { 5410 return remove( this, selector, true ); 5411 }, 5412 5413 remove: function( selector ) { 5414 return remove( this, selector ); 5415 }, 5416 5417 text: function( value ) { 5418 return access( this, function( value ) { 5419 return value === undefined ? 5420 jQuery.text( this ) : 5421 this.empty().each( function() { 5422 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { 5423 this.textContent = value; 5424 } 5425 } ); 5426 }, null, value, arguments.length ); 5427 }, 5428 5429 append: function() { 5430 return domManip( this, arguments, function( elem ) { 5431 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { 5432 var target = manipulationTarget( this, elem ); 5433 target.appendChild( elem ); 5434 } 5435 } ); 5436 }, 5437 5438 prepend: function() { 5439 return domManip( this, arguments, function( elem ) { 5440 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { 5441 var target = manipulationTarget( this, elem ); 5442 target.insertBefore( elem, target.firstChild ); 5443 } 5444 } ); 5445 }, 5446 5447 before: function() { 5448 return domManip( this, arguments, function( elem ) { 5449 if ( this.parentNode ) { 5450 this.parentNode.insertBefore( elem, this ); 5451 } 5452 } ); 5453 }, 5454 5455 after: function() { 5456 return domManip( this, arguments, function( elem ) { 5457 if ( this.parentNode ) { 5458 this.parentNode.insertBefore( elem, this.nextSibling ); 5459 } 5460 } ); 5461 }, 5462 5463 empty: function() { 5464 var elem, 5465 i = 0; 5466 5467 for ( ; ( elem = this[ i ] ) != null; i++ ) { 5468 if ( elem.nodeType === 1 ) { 5469 5470 // Prevent memory leaks 5471 jQuery.cleanData( getAll( elem, false ) ); 5472 5473 // Remove any remaining nodes 5474 elem.textContent = ""; 5475 } 5476 } 5477 5478 return this; 5479 }, 5480 5481 clone: function( dataAndEvents, deepDataAndEvents ) { 5482 dataAndEvents = dataAndEvents == null ? false : dataAndEvents; 5483 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; 5484 5485 return this.map( function() { 5486 return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); 5487 } ); 5488 }, 5489 5490 html: function( value ) { 5491 return access( this, function( value ) { 5492 var elem = this[ 0 ] || {}, 5493 i = 0, 5494 l = this.length; 5495 5496 if ( value === undefined && elem.nodeType === 1 ) { 5497 return elem.innerHTML; 5498 } 5499 5500 // See if we can take a shortcut and just use innerHTML 5501 if ( typeof value === "string" && !rnoInnerhtml.test( value ) && 5502 !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { 5503 5504 value = jQuery.htmlPrefilter( value ); 5505 5506 try { 5507 for ( ; i < l; i++ ) { 5508 elem = this[ i ] || {}; 5509 5510 // Remove element nodes and prevent memory leaks 5511 if ( elem.nodeType === 1 ) { 5512 jQuery.cleanData( getAll( elem, false ) ); 5513 elem.innerHTML = value; 5514 } 5515 } 5516 5517 elem = 0; 5518 5519 // If using innerHTML throws an exception, use the fallback method 5520 } catch ( e ) {} 5521 } 5522 5523 if ( elem ) { 5524 this.empty().append( value ); 5525 } 5526 }, null, value, arguments.length ); 5527 }, 5528 5529 replaceWith: function() { 5530 var ignored = []; 5531 5532 // Make the changes, replacing each non-ignored context element with the new content 5533 return domManip( this, arguments, function( elem ) { 5534 var parent = this.parentNode; 5535 5536 if ( jQuery.inArray( this, ignored ) < 0 ) { 5537 jQuery.cleanData( getAll( this ) ); 5538 if ( parent ) { 5539 parent.replaceChild( elem, this ); 5540 } 5541 } 5542 5543 // Force callback invocation 5544 }, ignored ); 5545 } 5546} ); 5547 5548jQuery.each( { 5549 appendTo: "append", 5550 prependTo: "prepend", 5551 insertBefore: "before", 5552 insertAfter: "after", 5553 replaceAll: "replaceWith" 5554}, function( name, original ) { 5555 jQuery.fn[ name ] = function( selector ) { 5556 var elems, 5557 ret = [], 5558 insert = jQuery( selector ), 5559 last = insert.length - 1, 5560 i = 0; 5561 5562 for ( ; i <= last; i++ ) { 5563 elems = i === last ? this : this.clone( true ); 5564 jQuery( insert[ i ] )[ original ]( elems ); 5565 5566 // Support: QtWebKit 5567 // .get() because push.apply(_, arraylike) throws 5568 push.apply( ret, elems.get() ); 5569 } 5570 5571 return this.pushStack( ret ); 5572 }; 5573} ); 5574 5575 5576var iframe, 5577 elemdisplay = { 5578 5579 // Support: Firefox 5580 // We have to pre-define these values for FF (#10227) 5581 HTML: "block", 5582 BODY: "block" 5583 }; 5584 5585/** 5586 * Retrieve the actual display of a element 5587 * @param {String} name nodeName of the element 5588 * @param {Object} doc Document object 5589 */ 5590 5591// Called only from within defaultDisplay 5592function actualDisplay( name, doc ) { 5593 var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), 5594 5595 display = jQuery.css( elem[ 0 ], "display" ); 5596 5597 // We don't have any data stored on the element, 5598 // so use "detach" method as fast way to get rid of the element 5599 elem.detach(); 5600 5601 return display; 5602} 5603 5604/** 5605 * Try to determine the default display value of an element 5606 * @param {String} nodeName 5607 */ 5608function defaultDisplay( nodeName ) { 5609 var doc = document, 5610 display = elemdisplay[ nodeName ]; 5611 5612 if ( !display ) { 5613 display = actualDisplay( nodeName, doc ); 5614 5615 // If the simple way fails, read from inside an iframe 5616 if ( display === "none" || !display ) { 5617 5618 // Use the already-created iframe if possible 5619 iframe = ( iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" ) ) 5620 .appendTo( doc.documentElement ); 5621 5622 // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse 5623 doc = iframe[ 0 ].contentDocument; 5624 5625 // Support: IE 5626 doc.write(); 5627 doc.close(); 5628 5629 display = actualDisplay( nodeName, doc ); 5630 iframe.detach(); 5631 } 5632 5633 // Store the correct default display 5634 elemdisplay[ nodeName ] = display; 5635 } 5636 5637 return display; 5638} 5639var rmargin = ( /^margin/ ); 5640 5641var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); 5642 5643var getStyles = function( elem ) { 5644 5645 // Support: IE<=11+, Firefox<=30+ (#15098, #14150) 5646 // IE throws on elements created in popups 5647 // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" 5648 var view = elem.ownerDocument.defaultView; 5649 5650 if ( !view || !view.opener ) { 5651 view = window; 5652 } 5653 5654 return view.getComputedStyle( elem ); 5655 }; 5656 5657var swap = function( elem, options, callback, args ) { 5658 var ret, name, 5659 old = {}; 5660 5661 // Remember the old values, and insert the new ones 5662 for ( name in options ) { 5663 old[ name ] = elem.style[ name ]; 5664 elem.style[ name ] = options[ name ]; 5665 } 5666 5667 ret = callback.apply( elem, args || [] ); 5668 5669 // Revert the old values 5670 for ( name in options ) { 5671 elem.style[ name ] = old[ name ]; 5672 } 5673 5674 return ret; 5675}; 5676 5677 5678var documentElement = document.documentElement; 5679 5680 5681 5682( function() { 5683 var pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal, 5684 container = document.createElement( "div" ), 5685 div = document.createElement( "div" ); 5686 5687 // Finish early in limited (non-browser) environments 5688 if ( !div.style ) { 5689 return; 5690 } 5691 5692 // Support: IE9-11+ 5693 // Style of cloned element affects source element cloned (#8908) 5694 div.style.backgroundClip = "content-box"; 5695 div.cloneNode( true ).style.backgroundClip = ""; 5696 support.clearCloneStyle = div.style.backgroundClip === "content-box"; 5697 5698 container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" + 5699 "padding:0;margin-top:1px;position:absolute"; 5700 container.appendChild( div ); 5701 5702 // Executing both pixelPosition & boxSizingReliable tests require only one layout 5703 // so they're executed at the same time to save the second computation. 5704 function computeStyleTests() { 5705 div.style.cssText = 5706 5707 // Support: Firefox<29, Android 2.3 5708 // Vendor-prefix box-sizing 5709 "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;" + 5710 "position:relative;display:block;" + 5711 "margin:auto;border:1px;padding:1px;" + 5712 "top:1%;width:50%"; 5713 div.innerHTML = ""; 5714 documentElement.appendChild( container ); 5715 5716 var divStyle = window.getComputedStyle( div ); 5717 pixelPositionVal = divStyle.top !== "1%"; 5718 reliableMarginLeftVal = divStyle.marginLeft === "2px"; 5719 boxSizingReliableVal = divStyle.width === "4px"; 5720 5721 // Support: Android 4.0 - 4.3 only 5722 // Some styles come back with percentage values, even though they shouldn't 5723 div.style.marginRight = "50%"; 5724 pixelMarginRightVal = divStyle.marginRight === "4px"; 5725 5726 documentElement.removeChild( container ); 5727 } 5728 5729 jQuery.extend( support, { 5730 pixelPosition: function() { 5731 5732 // This test is executed only once but we still do memoizing 5733 // since we can use the boxSizingReliable pre-computing. 5734 // No need to check if the test was already performed, though. 5735 computeStyleTests(); 5736 return pixelPositionVal; 5737 }, 5738 boxSizingReliable: function() { 5739 if ( boxSizingReliableVal == null ) { 5740 computeStyleTests(); 5741 } 5742 return boxSizingReliableVal; 5743 }, 5744 pixelMarginRight: function() { 5745 5746 // Support: Android 4.0-4.3 5747 // We're checking for boxSizingReliableVal here instead of pixelMarginRightVal 5748 // since that compresses better and they're computed together anyway. 5749 if ( boxSizingReliableVal == null ) { 5750 computeStyleTests(); 5751 } 5752 return pixelMarginRightVal; 5753 }, 5754 reliableMarginLeft: function() { 5755 5756 // Support: IE <=8 only, Android 4.0 - 4.3 only, Firefox <=3 - 37 5757 if ( boxSizingReliableVal == null ) { 5758 computeStyleTests(); 5759 } 5760 return reliableMarginLeftVal; 5761 }, 5762 reliableMarginRight: function() { 5763 5764 // Support: Android 2.3 5765 // Check if div with explicit width and no margin-right incorrectly 5766 // gets computed margin-right based on width of container. (#3333) 5767 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right 5768 // This support function is only executed once so no memoizing is needed. 5769 var ret, 5770 marginDiv = div.appendChild( document.createElement( "div" ) ); 5771 5772 // Reset CSS: box-sizing; display; margin; border; padding 5773 marginDiv.style.cssText = div.style.cssText = 5774 5775 // Support: Android 2.3 5776 // Vendor-prefix box-sizing 5777 "-webkit-box-sizing:content-box;box-sizing:content-box;" + 5778 "display:block;margin:0;border:0;padding:0"; 5779 marginDiv.style.marginRight = marginDiv.style.width = "0"; 5780 div.style.width = "1px"; 5781 documentElement.appendChild( container ); 5782 5783 ret = !parseFloat( window.getComputedStyle( marginDiv ).marginRight ); 5784 5785 documentElement.removeChild( container ); 5786 div.removeChild( marginDiv ); 5787 5788 return ret; 5789 } 5790 } ); 5791} )(); 5792 5793 5794function curCSS( elem, name, computed ) { 5795 var width, minWidth, maxWidth, ret, 5796 style = elem.style; 5797 5798 computed = computed || getStyles( elem ); 5799 ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined; 5800 5801 // Support: Opera 12.1x only 5802 // Fall back to style even without computed 5803 // computed is undefined for elems on document fragments 5804 if ( ( ret === "" || ret === undefined ) && !jQuery.contains( elem.ownerDocument, elem ) ) { 5805 ret = jQuery.style( elem, name ); 5806 } 5807 5808 // Support: IE9 5809 // getPropertyValue is only needed for .css('filter') (#12537) 5810 if ( computed ) { 5811 5812 // A tribute to the "awesome hack by Dean Edwards" 5813 // Android Browser returns percentage for some values, 5814 // but width seems to be reliably pixels. 5815 // This is against the CSSOM draft spec: 5816 // http://dev.w3.org/csswg/cssom/#resolved-values 5817 if ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) { 5818 5819 // Remember the original values 5820 width = style.width; 5821 minWidth = style.minWidth; 5822 maxWidth = style.maxWidth; 5823 5824 // Put in the new values to get a computed value out 5825 style.minWidth = style.maxWidth = style.width = ret; 5826 ret = computed.width; 5827 5828 // Revert the changed values 5829 style.width = width; 5830 style.minWidth = minWidth; 5831 style.maxWidth = maxWidth; 5832 } 5833 } 5834 5835 return ret !== undefined ? 5836 5837 // Support: IE9-11+ 5838 // IE returns zIndex value as an integer. 5839 ret + "" : 5840 ret; 5841} 5842 5843 5844function addGetHookIf( conditionFn, hookFn ) { 5845 5846 // Define the hook, we'll check on the first run if it's really needed. 5847 return { 5848 get: function() { 5849 if ( conditionFn() ) { 5850 5851 // Hook not needed (or it's not possible to use it due 5852 // to missing dependency), remove it. 5853 delete this.get; 5854 return; 5855 } 5856 5857 // Hook needed; redefine it so that the support test is not executed again. 5858 return ( this.get = hookFn ).apply( this, arguments ); 5859 } 5860 }; 5861} 5862 5863 5864var 5865 5866 // Swappable if display is none or starts with table 5867 // except "table", "table-cell", or "table-caption" 5868 // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display 5869 rdisplayswap = /^(none|table(?!-c[ea]).+)/, 5870 5871 cssShow = { position: "absolute", visibility: "hidden", display: "block" }, 5872 cssNormalTransform = { 5873 letterSpacing: "0", 5874 fontWeight: "400" 5875 }, 5876 5877 cssPrefixes = [ "Webkit", "O", "Moz", "ms" ], 5878 emptyStyle = document.createElement( "div" ).style; 5879 5880// Return a css property mapped to a potentially vendor prefixed property 5881function vendorPropName( name ) { 5882 5883 // Shortcut for names that are not vendor prefixed 5884 if ( name in emptyStyle ) { 5885 return name; 5886 } 5887 5888 // Check for vendor prefixed names 5889 var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), 5890 i = cssPrefixes.length; 5891 5892 while ( i-- ) { 5893 name = cssPrefixes[ i ] + capName; 5894 if ( name in emptyStyle ) { 5895 return name; 5896 } 5897 } 5898} 5899 5900function setPositiveNumber( elem, value, subtract ) { 5901 5902 // Any relative (+/-) values have already been 5903 // normalized at this point 5904 var matches = rcssNum.exec( value ); 5905 return matches ? 5906 5907 // Guard against undefined "subtract", e.g., when used as in cssHooks 5908 Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : 5909 value; 5910} 5911 5912function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { 5913 var i = extra === ( isBorderBox ? "border" : "content" ) ? 5914 5915 // If we already have the right measurement, avoid augmentation 5916 4 : 5917 5918 // Otherwise initialize for horizontal or vertical properties 5919 name === "width" ? 1 : 0, 5920 5921 val = 0; 5922 5923 for ( ; i < 4; i += 2 ) { 5924 5925 // Both box models exclude margin, so add it if we want it 5926 if ( extra === "margin" ) { 5927 val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); 5928 } 5929 5930 if ( isBorderBox ) { 5931 5932 // border-box includes padding, so remove it if we want content 5933 if ( extra === "content" ) { 5934 val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); 5935 } 5936 5937 // At this point, extra isn't border nor margin, so remove border 5938 if ( extra !== "margin" ) { 5939 val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); 5940 } 5941 } else { 5942 5943 // At this point, extra isn't content, so add padding 5944 val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); 5945 5946 // At this point, extra isn't content nor padding, so add border 5947 if ( extra !== "padding" ) { 5948 val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); 5949 } 5950 } 5951 } 5952 5953 return val; 5954} 5955 5956function getWidthOrHeight( elem, name, extra ) { 5957 5958 // Start with offset property, which is equivalent to the border-box value 5959 var valueIsBorderBox = true, 5960 val = name === "width" ? elem.offsetWidth : elem.offsetHeight, 5961 styles = getStyles( elem ), 5962 isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; 5963 5964 // S
5964upport: IE11 only 5965 // In IE 11 fullscreen elements inside of an iframe have 5966 // 100x too small dimensions (gh-1764). 5967 if ( document.msFullscreenElement && window.top !== window ) { 5968 5969 // Support: IE11 only 5970 // Running getBoundingClientRect on a disconnected node 5971 // in IE throws an error. 5972 if ( elem.getClientRects().length ) { 5973 val = Math.round( elem.getBoundingClientRect()[ name ] * 100 ); 5974 } 5975 }
vendor: 47,683 bytes, lines 5975-7867
5975 5976 5977 // Some non-html elements return undefined for offsetWidth, so check for null/undefined 5978 // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 5979 // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 5980 if ( val <= 0 || val == null ) { 5981 5982 // Fall back to computed then uncomputed css if necessary 5983 val = curCSS( elem, name, styles ); 5984 if ( val < 0 || val == null ) { 5985 val = elem.style[ name ]; 5986 } 5987 5988 // Computed unit is not pixels. Stop here and return. 5989 if ( rnumnonpx.test( val ) ) { 5990 return val; 5991 } 5992 5993 // Check for style in case a browser which returns unreliable values 5994 // for getComputedStyle silently falls back to the reliable elem.style 5995 valueIsBorderBox = isBorderBox && 5996 ( support.boxSizingReliable() || val === elem.style[ name ] ); 5997 5998 // Normalize "", auto, and prepare for extra 5999 val = parseFloat( val ) || 0; 6000 } 6001 6002 // Use the active box-sizing model to add/subtract irrelevant styles 6003 return ( val + 6004 augmentWidthOrHeight( 6005 elem, 6006 name, 6007 extra || ( isBorderBox ? "border" : "content" ), 6008 valueIsBorderBox, 6009 styles 6010 ) 6011 ) + "px"; 6012} 6013 6014function showHide( elements, show ) { 6015 var display, elem, hidden, 6016 values = [], 6017 index = 0, 6018 length = elements.length; 6019 6020 for ( ; index < length; index++ ) { 6021 elem = elements[ index ]; 6022 if ( !elem.style ) { 6023 continue; 6024 } 6025 6026 values[ index ] = dataPriv.get( elem, "olddisplay" ); 6027 display = elem.style.display; 6028 if ( show ) { 6029 6030 // Reset the inline display of this element to learn if it is 6031 // being hidden by cascaded rules or not 6032 if ( !values[ index ] && display === "none" ) { 6033 elem.style.display = ""; 6034 } 6035 6036 // Set elements which have been overridden with display: none 6037 // in a stylesheet to whatever the default browser style is 6038 // for such an element 6039 if ( elem.style.display === "" && isHidden( elem ) ) { 6040 values[ index ] = dataPriv.access( 6041 elem, 6042 "olddisplay", 6043 defaultDisplay( elem.nodeName ) 6044 ); 6045 } 6046 } else { 6047 hidden = isHidden( elem ); 6048 6049 if ( display !== "none" || !hidden ) { 6050 dataPriv.set( 6051 elem, 6052 "olddisplay", 6053 hidden ? display : jQuery.css( elem, "display" ) 6054 ); 6055 } 6056 } 6057 } 6058 6059 // Set the display of most of the elements in a second loop 6060 // to avoid the constant reflow 6061 for ( index = 0; index < length; index++ ) { 6062 elem = elements[ index ]; 6063 if ( !elem.style ) { 6064 continue; 6065 } 6066 if ( !show || elem.style.display === "none" || elem.style.display === "" ) { 6067 elem.style.display = show ? values[ index ] || "" : "none"; 6068 } 6069 } 6070 6071 return elements; 6072} 6073 6074jQuery.extend( { 6075 6076 // Add in style property hooks for overriding the default 6077 // behavior of getting and setting a style property 6078 cssHooks: { 6079 opacity: { 6080 get: function( elem, computed ) { 6081 if ( computed ) { 6082 6083 // We should always get a number back from opacity 6084 var ret = curCSS( elem, "opacity" ); 6085 return ret === "" ? "1" : ret; 6086 } 6087 } 6088 } 6089 }, 6090 6091 // Don't automatically add "px" to these possibly-unitless properties 6092 cssNumber: { 6093 "animationIterationCount": true, 6094 "columnCount": true, 6095 "fillOpacity": true, 6096 "flexGrow": true, 6097 "flexShrink": true, 6098 "fontWeight": true, 6099 "lineHeight": true, 6100 "opacity": true, 6101 "order": true, 6102 "orphans": true, 6103 "widows": true, 6104 "zIndex": true, 6105 "zoom": true 6106 }, 6107 6108 // Add in properties whose names you wish to fix before 6109 // setting or getting the value 6110 cssProps: { 6111 "float": "cssFloat" 6112 }, 6113 6114 // Get and set the style property on a DOM Node 6115 style: function( elem, name, value, extra ) { 6116 6117 // Don't set styles on text and comment nodes 6118 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { 6119 return; 6120 } 6121 6122 // Make sure that we're working with the right name 6123 var ret, type, hooks, 6124 origName = jQuery.camelCase( name ), 6125 style = elem.style; 6126 6127 name = jQuery.cssProps[ origName ] || 6128 ( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName ); 6129 6130 // Gets hook for the prefixed version, then unprefixed version 6131 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; 6132 6133 // Check if we're setting a value 6134 if ( value !== undefined ) { 6135 type = typeof value; 6136 6137 // Convert "+=" or "-=" to relative numbers (#7345) 6138 if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { 6139 value = adjustCSS( elem, name, ret ); 6140 6141 // Fixes bug #9237 6142 type = "number"; 6143 } 6144 6145 // Make sure that null and NaN values aren't set (#7116) 6146 if ( value == null || value !== value ) { 6147 return; 6148 } 6149 6150 // If a number was passed in, add the unit (except for certain CSS properties) 6151 if ( type === "number" ) { 6152 value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); 6153 } 6154 6155 // Support: IE9-11+ 6156 // background-* props affect original clone's values 6157 if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { 6158 style[ name ] = "inherit"; 6159 } 6160 6161 // If a hook was provided, use that value, otherwise just set the specified value 6162 if ( !hooks || !( "set" in hooks ) || 6163 ( value = hooks.set( elem, value, extra ) ) !== undefined ) { 6164 6165 style[ name ] = value; 6166 } 6167 6168 } else { 6169 6170 // If a hook was provided get the non-computed value from there 6171 if ( hooks && "get" in hooks && 6172 ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { 6173 6174 return ret; 6175 } 6176 6177 // Otherwise just get the value from the style object 6178 return style[ name ]; 6179 } 6180 }, 6181 6182 css: function( elem, name, extra, styles ) { 6183 var val, num, hooks, 6184 origName = jQuery.camelCase( name ); 6185 6186 // Make sure that we're working with the right name 6187 name = jQuery.cssProps[ origName ] || 6188 ( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName ); 6189 6190 // Try prefixed name followed by the unprefixed name 6191 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; 6192 6193 // If a hook was provided get the computed value from there 6194 if ( hooks && "get" in hooks ) { 6195 val = hooks.get( elem, true, extra ); 6196 } 6197 6198 // Otherwise, if a way to get the computed value exists, use that 6199 if ( val === undefined ) { 6200 val = curCSS( elem, name, styles ); 6201 } 6202 6203 // Convert "normal" to computed value 6204 if ( val === "normal" && name in cssNormalTransform ) { 6205 val = cssNormalTransform[ name ]; 6206 } 6207 6208 // Make numeric if forced or a qualifier was provided and val looks numeric 6209 if ( extra === "" || extra ) { 6210 num = parseFloat( val ); 6211 return extra === true || isFinite( num ) ? num || 0 : val; 6212 } 6213 return val; 6214 } 6215} ); 6216 6217jQuery.each( [ "height", "width" ], function( i, name ) { 6218 jQuery.cssHooks[ name ] = { 6219 get: function( elem, computed, extra ) { 6220 if ( computed ) { 6221 6222 // Certain elements can have dimension info if we invisibly show them 6223 // but it must have a current display style that would benefit 6224 return rdisplayswap.test( jQuery.css( elem, "display" ) ) && 6225 elem.offsetWidth === 0 ? 6226 swap( elem, cssShow, function() { 6227 return getWidthOrHeight( elem, name, extra ); 6228 } ) : 6229 getWidthOrHeight( elem, name, extra ); 6230 } 6231 }, 6232 6233 set: function( elem, value, extra ) { 6234 var matches, 6235 styles = extra && getStyles( elem ), 6236 subtract = extra && augmentWidthOrHeight( 6237 elem, 6238 name, 6239 extra, 6240 jQuery.css( elem, "boxSizing", false, styles ) === "border-box", 6241 styles 6242 ); 6243 6244 // Convert to pixels if value adjustment is needed 6245 if ( subtract && ( matches = rcssNum.exec( value ) ) && 6246 ( matches[ 3 ] || "px" ) !== "px" ) { 6247 6248 elem.style[ name ] = value; 6249 value = jQuery.css( elem, name ); 6250 } 6251 6252 return setPositiveNumber( elem, value, subtract ); 6253 } 6254 }; 6255} ); 6256 6257jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, 6258 function( elem, computed ) { 6259 if ( computed ) { 6260 return ( parseFloat( curCSS( elem, "marginLeft" ) ) || 6261 elem.getBoundingClientRect().left - 6262 swap( elem, { marginLeft: 0 }, function() { 6263 return elem.getBoundingClientRect().left; 6264 } ) 6265 ) + "px"; 6266 } 6267 } 6268); 6269 6270// Support: Android 2.3 6271jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight, 6272 function( elem, computed ) { 6273 if ( computed ) { 6274 return swap( elem, { "display": "inline-block" }, 6275 curCSS, [ elem, "marginRight" ] ); 6276 } 6277 } 6278); 6279 6280// These hooks are used by animate to expand properties 6281jQuery.each( { 6282 margin: "", 6283 padding: "", 6284 border: "Width" 6285}, function( prefix, suffix ) { 6286 jQuery.cssHooks[ prefix + suffix ] = { 6287 expand: function( value ) { 6288 var i = 0, 6289 expanded = {}, 6290 6291 // Assumes a single number if not a string 6292 parts = typeof value === "string" ? value.split( " " ) : [ value ]; 6293 6294 for ( ; i < 4; i++ ) { 6295 expanded[ prefix + cssExpand[ i ] + suffix ] = 6296 parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; 6297 } 6298 6299 return expanded; 6300 } 6301 }; 6302 6303 if ( !rmargin.test( prefix ) ) { 6304 jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; 6305 } 6306} ); 6307 6308jQuery.fn.extend( { 6309 css: function( name, value ) { 6310 return access( this, function( elem, name, value ) { 6311 var styles, len, 6312 map = {}, 6313 i = 0; 6314 6315 if ( jQuery.isArray( name ) ) { 6316 styles = getStyles( elem ); 6317 len = name.length; 6318 6319 for ( ; i < len; i++ ) { 6320 map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); 6321 } 6322 6323 return map; 6324 } 6325 6326 return value !== undefined ? 6327 jQuery.style( elem, name, value ) : 6328 jQuery.css( elem, name ); 6329 }, name, value, arguments.length > 1 ); 6330 }, 6331 show: function() { 6332 return showHide( this, true ); 6333 }, 6334 hide: function() { 6335 return showHide( this ); 6336 }, 6337 toggle: function( state ) { 6338 if ( typeof state === "boolean" ) { 6339 return state ? this.show() : this.hide(); 6340 } 6341 6342 return this.each( function() { 6343 if ( isHidden( this ) ) { 6344 jQuery( this ).show(); 6345 } else { 6346 jQuery( this ).hide(); 6347 } 6348 } ); 6349 } 6350} ); 6351 6352 6353function Tween( elem, options, prop, end, easing ) { 6354 return new Tween.prototype.init( elem, options, prop, end, easing ); 6355} 6356jQuery.Tween = Tween; 6357 6358Tween.prototype = { 6359 constructor: Tween, 6360 init: function( elem, options, prop, end, easing, unit ) { 6361 this.elem = elem; 6362 this.prop = prop; 6363 this.easing = easing || jQuery.easing._default; 6364 this.options = options; 6365 this.start = this.now = this.cur(); 6366 this.end = end; 6367 this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); 6368 }, 6369 cur: function() { 6370 var hooks = Tween.propHooks[ this.prop ]; 6371 6372 return hooks && hooks.get ? 6373 hooks.get( this ) : 6374 Tween.propHooks._default.get( this ); 6375 }, 6376 run: function( percent ) { 6377 var eased, 6378 hooks = Tween.propHooks[ this.prop ]; 6379 6380 if ( this.options.duration ) { 6381 this.pos = eased = jQuery.easing[ this.easing ]( 6382 percent, this.options.duration * percent, 0, 1, this.options.duration 6383 ); 6384 } else { 6385 this.pos = eased = percent; 6386 } 6387 this.now = ( this.end - this.start ) * eased + this.start; 6388 6389 if ( this.options.step ) { 6390 this.options.step.call( this.elem, this.now, this ); 6391 } 6392 6393 if ( hooks && hooks.set ) { 6394 hooks.set( this ); 6395 } else { 6396 Tween.propHooks._default.set( this ); 6397 } 6398 return this; 6399 } 6400}; 6401 6402Tween.prototype.init.prototype = Tween.prototype; 6403 6404Tween.propHooks = { 6405 _default: { 6406 get: function( tween ) { 6407 var result; 6408 6409 // Use a property on the element directly when it is not a DOM element, 6410 // or when there is no matching style property that exists. 6411 if ( tween.elem.nodeType !== 1 || 6412 tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { 6413 return tween.elem[ tween.prop ]; 6414 } 6415 6416 // Passing an empty string as a 3rd parameter to .css will automatically 6417 // attempt a parseFloat and fallback to a string if the parse fails. 6418 // Simple values such as "10px" are parsed to Float; 6419 // complex values such as "rotate(1rad)" are returned as-is. 6420 result = jQuery.css( tween.elem, tween.prop, "" ); 6421 6422 // Empty strings, null, undefined and "auto" are converted to 0. 6423 return !result || result === "auto" ? 0 : result; 6424 }, 6425 set: function( tween ) { 6426 6427 // Use step hook for back compat. 6428 // Use cssHook if its there. 6429 // Use .style if available and use plain properties where available. 6430 if ( jQuery.fx.step[ tween.prop ] ) { 6431 jQuery.fx.step[ tween.prop ]( tween ); 6432 } else if ( tween.elem.nodeType === 1 && 6433 ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || 6434 jQuery.cssHooks[ tween.prop ] ) ) { 6435 jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); 6436 } else { 6437 tween.elem[ tween.prop ] = tween.now; 6438 } 6439 } 6440 } 6441}; 6442 6443// Support: IE9 6444// Panic based approach to setting things on disconnected nodes 6445Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { 6446 set: function( tween ) { 6447 if ( tween.elem.nodeType && tween.elem.parentNode ) { 6448 tween.elem[ tween.prop ] = tween.now; 6449 } 6450 } 6451}; 6452 6453jQuery.easing = { 6454 linear: function( p ) { 6455 return p; 6456 }, 6457 swing: function( p ) { 6458 return 0.5 - Math.cos( p * Math.PI ) / 2; 6459 }, 6460 _default: "swing" 6461}; 6462 6463jQuery.fx = Tween.prototype.init; 6464 6465// Back Compat <1.8 extension point 6466jQuery.fx.step = {}; 6467 6468 6469 6470 6471var 6472 fxNow, timerId, 6473 rfxtypes = /^(?:toggle|show|hide)$/, 6474 rrun = /queueHooks$/; 6475 6476// Animations created synchronously will run synchronously 6477function createFxNow() { 6478 window.setTimeout( function() { 6479 fxNow = undefined; 6480 } ); 6481 return ( fxNow = jQuery.now() ); 6482} 6483 6484// Generate parameters to create a standard animation 6485function genFx( type, includeWidth ) { 6486 var which, 6487 i = 0, 6488 attrs = { height: type }; 6489 6490 // If we include width, step value is 1 to do all cssExpand values, 6491 // otherwise step value is 2 to skip over Left and Right 6492 includeWidth = includeWidth ? 1 : 0; 6493 for ( ; i < 4 ; i += 2 - includeWidth ) { 6494 which = cssExpand[ i ]; 6495 attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; 6496 } 6497 6498 if ( includeWidth ) { 6499 attrs.opacity = attrs.width = type; 6500 } 6501 6502 return attrs; 6503} 6504 6505function createTween( value, prop, animation ) { 6506 var tween, 6507 collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), 6508 index = 0, 6509 length = collection.length; 6510 for ( ; index < length; index++ ) { 6511 if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { 6512 6513 // We're done with this property 6514 return tween; 6515 } 6516 } 6517} 6518 6519function defaultPrefilter( elem, props, opts ) { 6520 /* jshint validthis: true */ 6521 var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay, 6522 anim = this, 6523 orig = {}, 6524 style = elem.style, 6525 hidden = elem.nodeType && isHidden( elem ), 6526 dataShow = dataPriv.get( elem, "fxshow" ); 6527 6528 // Handle queue: false promises 6529 if ( !opts.queue ) { 6530 hooks = jQuery._queueHooks( elem, "fx" ); 6531 if ( hooks.unqueued == null ) { 6532 hooks.unqueued = 0; 6533 oldfire = hooks.empty.fire; 6534 hooks.empty.fire = function() { 6535 if ( !hooks.unqueued ) { 6536 oldfire(); 6537 } 6538 }; 6539 } 6540 hooks.unqueued++; 6541 6542 anim.always( function() { 6543 6544 // Ensure the complete handler is called before this completes 6545 anim.always( function() { 6546 hooks.unqueued--; 6547 if ( !jQuery.queue( elem, "fx" ).length ) { 6548 hooks.empty.fire(); 6549 } 6550 } ); 6551 } ); 6552 } 6553 6554 // Height/width overflow pass 6555 if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) { 6556 6557 // Make sure that nothing sneaks out 6558 // Record all 3 overflow attributes because IE9-10 do not 6559 // change the overflow attribute when overflowX and 6560 // overflowY are set to the same value 6561 opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; 6562 6563 // Set display property to inline-block for height/width 6564 // animations on inline elements that are having width/height animated 6565 display = jQuery.css( elem, "display" ); 6566 6567 // Test default display if display is currently "none" 6568 checkDisplay = display === "none" ? 6569 dataPriv.get( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display; 6570 6571 if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) { 6572 style.display = "inline-block"; 6573 } 6574 } 6575 6576 if ( opts.overflow ) { 6577 style.overflow = "hidden"; 6578 anim.always( function() { 6579 style.overflow = opts.overflow[ 0 ]; 6580 style.overflowX = opts.overflow[ 1 ]; 6581 style.overflowY = opts.overflow[ 2 ]; 6582 } ); 6583 } 6584 6585 // show/hide pass 6586 for ( prop in props ) { 6587 value = props[ prop ]; 6588 if ( rfxtypes.exec( value ) ) { 6589 delete props[ prop ]; 6590 toggle = toggle || value === "toggle"; 6591 if ( value === ( hidden ? "hide" : "show" ) ) { 6592 6593 // If there is dataShow left over from a stopped hide or show 6594 // and we are going to proceed with show, we should pretend to be hidden 6595 if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { 6596 hidden = true; 6597 } else { 6598 continue; 6599 } 6600 } 6601 orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); 6602 6603 // Any non-fx value stops us from restoring the original display value 6604 } else { 6605 display = undefined; 6606 } 6607 } 6608 6609 if ( !jQuery.isEmptyObject( orig ) ) { 6610 if ( dataShow ) { 6611 if ( "hidden" in dataShow ) { 6612 hidden = dataShow.hidden; 6613 } 6614 } else { 6615 dataShow = dataPriv.access( elem, "fxshow", {} ); 6616 } 6617 6618 // Store state if its toggle - enables .stop().toggle() to "reverse" 6619 if ( toggle ) { 6620 dataShow.hidden = !hidden; 6621 } 6622 if ( hidden ) { 6623 jQuery( elem ).show(); 6624 } else { 6625 anim.done( function() { 6626 jQuery( elem ).hide(); 6627 } ); 6628 } 6629 anim.done( function() { 6630 var prop; 6631 6632 dataPriv.remove( elem, "fxshow" ); 6633 for ( prop in orig ) { 6634 jQuery.style( elem, prop, orig[ prop ] ); 6635 } 6636 } ); 6637 for ( prop in orig ) { 6638 tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); 6639 6640 if ( !( prop in dataShow ) ) { 6641 dataShow[ prop ] = tween.start; 6642 if ( hidden ) { 6643 tween.end = tween.start; 6644 tween.start = prop === "width" || prop === "height" ? 1 : 0; 6645 } 6646 } 6647 } 6648 6649 // If this is a noop like .hide().hide(), restore an overwritten display value 6650 } else if ( ( display === "none" ? defaultDisplay( elem.nodeName ) : display ) === "inline" ) { 6651 style.display = display; 6652 } 6653} 6654 6655function propFilter( props, specialEasing ) { 6656 var index, name, easing, value, hooks; 6657 6658 // camelCase, specialEasing and expand cssHook pass 6659 for ( index in props ) { 6660 name = jQuery.camelCase( index ); 6661 easing = specialEasing[ name ]; 6662 value = props[ index ]; 6663 if ( jQuery.isArray( value ) ) { 6664 easing = value[ 1 ]; 6665 value = props[ index ] = value[ 0 ]; 6666 } 6667 6668 if ( index !== name ) { 6669 props[ name ] = value; 6670 delete props[ index ]; 6671 } 6672 6673 hooks = jQuery.cssHooks[ name ]; 6674 if ( hooks && "expand" in hooks ) { 6675 value = hooks.expand( value ); 6676 delete props[ name ]; 6677 6678 // Not quite $.extend, this won't overwrite existing keys. 6679 // Reusing 'index' because we have the correct "name" 6680 for ( index in value ) { 6681 if ( !( index in props ) ) { 6682 props[ index ] = value[ index ]; 6683 specialEasing[ index ] = easing; 6684 } 6685 } 6686 } else { 6687 specialEasing[ name ] = easing; 6688 } 6689 } 6690} 6691 6692function Animation( elem, properties, options ) { 6693 var result, 6694 stopped, 6695 index = 0, 6696 length = Animation.prefilters.length, 6697 deferred = jQuery.Deferred().always( function() { 6698 6699 // Don't match elem in the :animated selector 6700 delete tick.elem; 6701 } ), 6702 tick = function() { 6703 if ( stopped ) { 6704 return false; 6705 } 6706 var currentTime = fxNow || createFxNow(), 6707 remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), 6708 6709 // Support: Android 2.3 6710 // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) 6711 temp = remaining / animation.duration || 0, 6712 percent = 1 - temp, 6713 index = 0, 6714 length = animation.tweens.length; 6715 6716 for ( ; index < length ; index++ ) { 6717 animation.tweens[ index ].run( percent ); 6718 } 6719 6720 deferred.notifyWith( elem, [ animation, percent, remaining ] ); 6721 6722 if ( percent < 1 && length ) { 6723 return remaining; 6724 } else { 6725 deferred.resolveWith( elem, [ animation ] ); 6726 return false; 6727 } 6728 }, 6729 animation = deferred.promise( { 6730 elem: elem, 6731 props: jQuery.extend( {}, properties ), 6732 opts: jQuery.extend( true, { 6733 specialEasing: {}, 6734 easing: jQuery.easing._default 6735 }, options ), 6736 originalProperties: properties, 6737 originalOptions: options, 6738 startTime: fxNow || createFxNow(), 6739 duration: options.duration, 6740 tweens: [], 6741 createTween: function( prop, end ) { 6742 var tween = jQuery.Tween( elem, animation.opts, prop, end, 6743 animation.opts.specialEasing[ prop ] || animation.opts.easing ); 6744 animation.tweens.push( tween ); 6745 return tween; 6746 }, 6747 stop: function( gotoEnd ) { 6748 var index = 0, 6749 6750 // If we are going to the end, we want to run all the tweens 6751 // otherwise we skip this part 6752 length = gotoEnd ? animation.tweens.length : 0; 6753 if ( stopped ) { 6754 return this; 6755 } 6756 stopped = true; 6757 for ( ; index < length ; index++ ) { 6758 animation.tweens[ index ].run( 1 ); 6759 } 6760 6761 // Resolve when we played the last frame; otherwise, reject 6762 if ( gotoEnd ) { 6763 deferred.notifyWith( elem, [ animation, 1, 0 ] ); 6764 deferred.resolveWith( elem, [ animation, gotoEnd ] ); 6765 } else { 6766 deferred.rejectWith( elem, [ animation, gotoEnd ] ); 6767 } 6768 return this; 6769 } 6770 } ), 6771 props = animation.props; 6772 6773 propFilter( props, animation.opts.specialEasing ); 6774 6775 for ( ; index < length ; index++ ) { 6776 result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); 6777 if ( result ) { 6778 if ( jQuery.isFunction( result.stop ) ) { 6779 jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = 6780 jQuery.proxy( result.stop, result ); 6781 } 6782 return result; 6783 } 6784 } 6785 6786 jQuery.map( props, createTween, animation ); 6787 6788 if ( jQuery.isFunction( animation.opts.start ) ) { 6789 animation.opts.start.call( elem, animation ); 6790 } 6791 6792 jQuery.fx.timer( 6793 jQuery.extend( tick, { 6794 elem: elem, 6795 anim: animation, 6796 queue: animation.opts.queue 6797 } ) 6798 ); 6799 6800 // attach callbacks from options 6801 return animation.progress( animation.opts.progress ) 6802 .done( animation.opts.done, animation.opts.complete ) 6803 .fail( animation.opts.fail ) 6804 .always( animation.opts.always ); 6805} 6806 6807jQuery.Animation = jQuery.extend( Animation, { 6808 tweeners: { 6809 "*": [ function( prop, value ) { 6810 var tween = this.createTween( prop, value ); 6811 adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); 6812 return tween; 6813 } ] 6814 }, 6815 6816 tweener: function( props, callback ) { 6817 if ( jQuery.isFunction( props ) ) { 6818 callback = props; 6819 props = [ "*" ]; 6820 } else { 6821 props = props.match( rnotwhite ); 6822 } 6823 6824 var prop, 6825 index = 0, 6826 length = props.length; 6827 6828 for ( ; index < length ; index++ ) { 6829 prop = props[ index ]; 6830 Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; 6831 Animation.tweeners[ prop ].unshift( callback ); 6832 } 6833 }, 6834 6835 prefilters: [ defaultPrefilter ], 6836 6837 prefilter: function( callback, prepend ) { 6838 if ( prepend ) { 6839 Animation.prefilters.unshift( callback ); 6840 } else { 6841 Animation.prefilters.push( callback ); 6842 } 6843 } 6844} ); 6845 6846jQuery.speed = function( speed, easing, fn ) { 6847 var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { 6848 complete: fn || !fn && easing || 6849 jQuery.isFunction( speed ) && speed, 6850 duration: speed, 6851 easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing 6852 }; 6853 6854 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? 6855 opt.duration : opt.duration in jQuery.fx.speeds ? 6856 jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default; 6857 6858 // Normalize opt.queue - true/undefined/null -> "fx" 6859 if ( opt.queue == null || opt.queue === true ) { 6860 opt.queue = "fx"; 6861 } 6862 6863 // Queueing 6864 opt.old = opt.complete; 6865 6866 opt.complete = function() { 6867 if ( jQuery.isFunction( opt.old ) ) { 6868 opt.old.call( this ); 6869 } 6870 6871 if ( opt.queue ) { 6872 jQuery.dequeue( this, opt.queue ); 6873 } 6874 }; 6875 6876 return opt; 6877}; 6878 6879jQuery.fn.extend( { 6880 fadeTo: function( speed, to, easing, callback ) { 6881 6882 // Show any hidden elements after setting opacity to 0 6883 return this.filter( isHidden ).css( "opacity", 0 ).show() 6884 6885 // Animate to the value specified 6886 .end().animate( { opacity: to }, speed, easing, callback ); 6887 }, 6888 animate: function( prop, speed, easing, callback ) { 6889 var empty = jQuery.isEmptyObject( prop ), 6890 optall = jQuery.speed( speed, easing, callback ), 6891 doAnimation = function() { 6892 6893 // Operate on a copy of prop so per-property easing won't be lost 6894 var anim = Animation( this, jQuery.extend( {}, prop ), optall ); 6895 6896 // Empty animations, or finishing resolves immediately 6897 if ( empty || dataPriv.get( this, "finish" ) ) { 6898 anim.stop( true ); 6899 } 6900 }; 6901 doAnimation.finish = doAnimation; 6902 6903 return empty || optall.queue === false ? 6904 this.each( doAnimation ) : 6905 this.queue( optall.queue, doAnimation ); 6906 }, 6907 stop: function( type, clearQueue, gotoEnd ) { 6908 var stopQueue = function( hooks ) { 6909 var stop = hooks.stop; 6910 delete hooks.stop; 6911 stop( gotoEnd ); 6912 }; 6913 6914 if ( typeof type !== "string" ) { 6915 gotoEnd = clearQueue; 6916 clearQueue = type; 6917 type = undefined; 6918 } 6919 if ( clearQueue && type !== false ) { 6920 this.queue( type || "fx", [] ); 6921 } 6922 6923 return this.each( function() { 6924 var dequeue = true, 6925 index = type != null && type + "queueHooks", 6926 timers = jQuery.timers, 6927 data = dataPriv.get( this ); 6928 6929 if ( index ) { 6930 if ( data[ index ] && data[ index ].stop ) { 6931 stopQueue( data[ index ] ); 6932 } 6933 } else { 6934 for ( index in data ) { 6935 if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { 6936 stopQueue( data[ index ] ); 6937 } 6938 } 6939 } 6940 6941 for ( index = timers.length; index--; ) { 6942 if ( timers[ index ].elem === this && 6943 ( type == null || timers[ index ].queue === type ) ) { 6944 6945 timers[ index ].anim.stop( gotoEnd ); 6946 dequeue = false; 6947 timers.splice( index, 1 ); 6948 } 6949 } 6950 6951 // Start the next in the queue if the last step wasn't forced. 6952 // Timers currently will call their complete callbacks, which 6953 // will dequeue but only if they were gotoEnd. 6954 if ( dequeue || !gotoEnd ) { 6955 jQuery.dequeue( this, type ); 6956 } 6957 } ); 6958 }, 6959 finish: function( type ) { 6960 if ( type !== false ) { 6961 type = type || "fx"; 6962 } 6963 return this.each( function() { 6964 var index, 6965 data = dataPriv.get( this ), 6966 queue = data[ type + "queue" ], 6967 hooks = data[ type + "queueHooks" ], 6968 timers = jQuery.timers, 6969 length = queue ? queue.length : 0; 6970 6971 // Enable finishing flag on private data 6972 data.finish = true; 6973 6974 // Empty the queue first 6975 jQuery.queue( this, type, [] ); 6976 6977 if ( hooks && hooks.stop ) { 6978 hooks.stop.call( this, true ); 6979 } 6980 6981 // Look for any active animations, and finish them 6982 for ( index = timers.length; index--; ) { 6983 if ( timers[ index ].elem === this && timers[ index ].queue === type ) { 6984 timers[ index ].anim.stop( true ); 6985 timers.splice( index, 1 ); 6986 } 6987 } 6988 6989 // Look for any animations in the old queue and finish them 6990 for ( index = 0; index < length; index++ ) { 6991 if ( queue[ index ] && queue[ index ].finish ) { 6992 queue[ index ].finish.call( this ); 6993 } 6994 } 6995 6996 // Turn off finishing flag 6997 delete data.finish; 6998 } ); 6999 } 7000} ); 7001 7002jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) { 7003 var cssFn = jQuery.fn[ name ]; 7004 jQuery.fn[ name ] = function( speed, easing, callback ) { 7005 return speed == null || typeof speed === "boolean" ? 7006 cssFn.apply( this, arguments ) : 7007 this.animate( genFx( name, true ), speed, easing, callback ); 7008 }; 7009} ); 7010 7011// Generate shortcuts for custom animations 7012jQuery.each( { 7013 slideDown: genFx( "show" ), 7014 slideUp: genFx( "hide" ), 7015 slideToggle: genFx( "toggle" ), 7016 fadeIn: { opacity: "show" }, 7017 fadeOut: { opacity: "hide" }, 7018 fadeToggle: { opacity: "toggle" } 7019}, function( name, props ) { 7020 jQuery.fn[ name ] = function( speed, easing, callback ) { 7021 return this.animate( props, speed, easing, callback ); 7022 }; 7023} ); 7024 7025jQuery.timers = []; 7026jQuery.fx.tick = function() { 7027 var timer, 7028 i = 0, 7029 timers = jQuery.timers; 7030 7031 fxNow = jQuery.now(); 7032 7033 for ( ; i < timers.length; i++ ) { 7034 timer = timers[ i ]; 7035 7036 // Checks the timer has not already been removed 7037 if ( !timer() && timers[ i ] === timer ) { 7038 timers.splice( i--, 1 ); 7039 } 7040 } 7041 7042 if ( !timers.length ) { 7043 jQuery.fx.stop(); 7044 } 7045 fxNow = undefined; 7046}; 7047 7048jQuery.fx.timer = function( timer ) { 7049 jQuery.timers.push( timer ); 7050 if ( timer() ) { 7051 jQuery.fx.start(); 7052 } else { 7053 jQuery.timers.pop(); 7054 } 7055}; 7056 7057jQuery.fx.interval = 13; 7058jQuery.fx.start = function() { 7059 if ( !timerId ) { 7060 timerId = window.setInterval( jQuery.fx.tick, jQuery.fx.interval ); 7061 } 7062}; 7063 7064jQuery.fx.stop = function() { 7065 window.clearInterval( timerId ); 7066 7067 timerId = null; 7068}; 7069 7070jQuery.fx.speeds = { 7071 slow: 600, 7072 fast: 200, 7073 7074 // Default speed 7075 _default: 400 7076}; 7077 7078 7079// Based off of the plugin by Clint Helfers, with permission. 7080// http://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ 7081jQuery.fn.delay = function( time, type ) { 7082 time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; 7083 type = type || "fx"; 7084 7085 return this.queue( type, function( next, hooks ) { 7086 var timeout = window.setTimeout( next, time ); 7087 hooks.stop = function() { 7088 window.clearTimeout( timeout ); 7089 }; 7090 } ); 7091}; 7092 7093 7094( function() { 7095 var input = document.createElement( "input" ), 7096 select = document.createElement( "select" ), 7097 opt = select.appendChild( document.createElement( "option" ) ); 7098 7099 input.type = "checkbox"; 7100 7101 // Support: iOS<=5.1, Android<=4.2+ 7102 // Default value for a checkbox should be "on" 7103 support.checkOn = input.value !== ""; 7104 7105 // Support: IE<=11+ 7106 // Must access selectedIndex to make default options select 7107 support.optSelected = opt.selected; 7108 7109 // Support: Android<=2.3 7110 // Options inside disabled selects are incorrectly marked as disabled 7111 select.disabled = true; 7112 support.optDisabled = !opt.disabled; 7113 7114 // Support: IE<=11+ 7115 // An input loses its value after becoming a radio 7116 input = document.createElement( "input" ); 7117 input.value = "t"; 7118 input.type = "radio"; 7119 support.radioValue = input.value === "t"; 7120} )(); 7121 7122 7123var boolHook, 7124 attrHandle = jQuery.expr.attrHandle; 7125 7126jQuery.fn.extend( { 7127 attr: function( name, value ) { 7128 return access( this, jQuery.attr, name, value, arguments.length > 1 ); 7129 }, 7130 7131 removeAttr: function( name ) { 7132 return this.each( function() { 7133 jQuery.removeAttr( this, name ); 7134 } ); 7135 } 7136} ); 7137 7138jQuery.extend( { 7139 attr: function( elem, name, value ) { 7140 var ret, hooks, 7141 nType = elem.nodeType; 7142 7143 // Don't get/set attributes on text, comment and attribute nodes 7144 if ( nType === 3 || nType === 8 || nType === 2 ) { 7145 return; 7146 } 7147 7148 // Fallback to prop when attributes are not supported 7149 if ( typeof elem.getAttribute === "undefined" ) { 7150 return jQuery.prop( elem, name, value ); 7151 } 7152 7153 // All attributes are lowercase 7154 // Grab necessary hook if one is defined 7155 if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { 7156 name = name.toLowerCase(); 7157 hooks = jQuery.attrHooks[ name ] || 7158 ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); 7159 } 7160 7161 if ( value !== undefined ) { 7162 if ( value === null ) { 7163 jQuery.removeAttr( elem, name ); 7164 return; 7165 } 7166 7167 if ( hooks && "set" in hooks && 7168 ( ret = hooks.set( elem, value, name ) ) !== undefined ) { 7169 return ret; 7170 } 7171 7172 elem.setAttribute( name, value + "" ); 7173 return value; 7174 } 7175 7176 if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { 7177 return ret; 7178 } 7179 7180 ret = jQuery.find.attr( elem, name ); 7181 7182 // Non-existent attributes return null, we normalize to undefined 7183 return ret == null ? undefined : ret; 7184 }, 7185 7186 attrHooks: { 7187 type: { 7188 set: function( elem, value ) { 7189 if ( !support.radioValue && value === "radio" && 7190 jQuery.nodeName( elem, "input" ) ) { 7191 var val = elem.value; 7192 elem.setAttribute( "type", value ); 7193 if ( val ) { 7194 elem.value = val; 7195 } 7196 return value; 7197 } 7198 } 7199 } 7200 }, 7201 7202 removeAttr: function( elem, value ) { 7203 var name, propName, 7204 i = 0, 7205 attrNames = value && value.match( rnotwhite ); 7206 7207 if ( attrNames && elem.nodeType === 1 ) { 7208 while ( ( name = attrNames[ i++ ] ) ) { 7209 propName = jQuery.propFix[ name ] || name; 7210 7211 // Boolean attributes get special treatment (#10870) 7212 if ( jQuery.expr.match.bool.test( name ) ) { 7213 7214 // Set corresponding property to false 7215 elem[ propName ] = false; 7216 } 7217 7218 elem.removeAttribute( name ); 7219 } 7220 } 7221 } 7222} ); 7223 7224// Hooks for boolean attributes 7225boolHook = { 7226 set: function( elem, value, name ) { 7227 if ( value === false ) { 7228 7229 // Remove boolean attributes when set to false 7230 jQuery.removeAttr( elem, name ); 7231 } else { 7232 elem.setAttribute( name, name ); 7233 } 7234 return name; 7235 } 7236}; 7237jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { 7238 var getter = attrHandle[ name ] || jQuery.find.attr; 7239 7240 attrHandle[ name ] = function( elem, name, isXML ) { 7241 var ret, handle; 7242 if ( !isXML ) { 7243 7244 // Avoid an infinite loop by temporarily removing this function from the getter 7245 handle = attrHandle[ name ]; 7246 attrHandle[ name ] = ret; 7247 ret = getter( elem, name, isXML ) != null ? 7248 name.toLowerCase() : 7249 null; 7250 attrHandle[ name ] = handle; 7251 } 7252 return ret; 7253 }; 7254} ); 7255 7256 7257 7258 7259var rfocusable = /^(?:input|select|textarea|button)$/i, 7260 rclickable = /^(?:a|area)$/i; 7261 7262jQuery.fn.extend( { 7263 prop: function( name, value ) { 7264 return access( this, jQuery.prop, name, value, arguments.length > 1 ); 7265 }, 7266 7267 removeProp: function( name ) { 7268 return this.each( function() { 7269 delete this[ jQuery.propFix[ name ] || name ]; 7270 } ); 7271 } 7272} ); 7273 7274jQuery.extend( { 7275 prop: function( elem, name, value ) { 7276 var ret, hooks, 7277 nType = elem.nodeType; 7278 7279 // Don't get/set properties on text, comment and attribute nodes 7280 if ( nType === 3 || nType === 8 || nType === 2 ) { 7281 return; 7282 } 7283 7284 if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { 7285 7286 // Fix name and attach hooks 7287 name = jQuery.propFix[ name ] || name; 7288 hooks = jQuery.propHooks[ name ]; 7289 } 7290 7291 if ( value !== undefined ) { 7292 if ( hooks && "set" in hooks && 7293 ( ret = hooks.set( elem, value, name ) ) !== undefined ) { 7294 return ret; 7295 } 7296 7297 return ( elem[ name ] = value ); 7298 } 7299 7300 if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { 7301 return ret; 7302 } 7303 7304 return elem[ name ]; 7305 }, 7306 7307 propHooks: { 7308 tabIndex: { 7309 get: function( elem ) { 7310 7311 // elem.tabIndex doesn't always return the 7312 // correct value when it hasn't been explicitly set 7313 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ 7314 // Use proper attribute retrieval(#12072) 7315 var tabindex = jQuery.find.attr( elem, "tabindex" ); 7316 7317 return tabindex ? 7318 parseInt( tabindex, 10 ) : 7319 rfocusable.test( elem.nodeName ) || 7320 rclickable.test( elem.nodeName ) && elem.href ? 7321 0 : 7322 -1; 7323 } 7324 } 7325 }, 7326 7327 propFix: { 7328 "for": "htmlFor", 7329 "class": "className" 7330 } 7331} ); 7332 7333// Support: IE <=11 only 7334// Accessing the selectedIndex property 7335// forces the browser to respect setting selected 7336// on the option 7337// The getter ensures a default option is selected 7338// when in an optgroup 7339if ( !support.optSelected ) { 7340 jQuery.propHooks.selected = { 7341 get: function( elem ) { 7342 var parent = elem.parentNode; 7343 if ( parent && parent.parentNode ) { 7344 parent.parentNode.selectedIndex; 7345 } 7346 return null; 7347 }, 7348 set: function( elem ) { 7349 var parent = elem.parentNode; 7350 if ( parent ) { 7351 parent.selectedIndex; 7352 7353 if ( parent.parentNode ) { 7354 parent.parentNode.selectedIndex; 7355 } 7356 } 7357 } 7358 }; 7359} 7360 7361jQuery.each( [ 7362 "tabIndex", 7363 "readOnly", 7364 "maxLength", 7365 "cellSpacing", 7366 "cellPadding", 7367 "rowSpan", 7368 "colSpan", 7369 "useMap", 7370 "frameBorder", 7371 "contentEditable" 7372], function() { 7373 jQuery.propFix[ this.toLowerCase() ] = this; 7374} ); 7375 7376 7377 7378 7379var rclass = /[\t\r\n\f]/g; 7380 7381function getClass( elem ) { 7382 return elem.getAttribute && elem.getAttribute( "class" ) || ""; 7383} 7384 7385jQuery.fn.extend( { 7386 addClass: function( value ) { 7387 var classes, elem, cur, curValue, clazz, j, finalValue, 7388 i = 0; 7389 7390 if ( jQuery.isFunction( value ) ) { 7391 return this.each( function( j ) { 7392 jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); 7393 } ); 7394 } 7395 7396 if ( typeof value === "string" && value ) { 7397 classes = value.match( rnotwhite ) || []; 7398 7399 while ( ( elem = this[ i++ ] ) ) { 7400 curValue = getClass( elem ); 7401 cur = elem.nodeType === 1 && 7402 ( " " + curValue + " " ).replace( rclass, " " ); 7403 7404 if ( cur ) { 7405 j = 0; 7406 while ( ( clazz = classes[ j++ ] ) ) { 7407 if ( cur.indexOf( " " + clazz + " " ) < 0 ) { 7408 cur += clazz + " "; 7409 } 7410 } 7411 7412 // Only assign if different to avoid unneeded rendering. 7413 finalValue = jQuery.trim( cur ); 7414 if ( curValue !== finalValue ) { 7415 elem.setAttribute( "class", finalValue ); 7416 } 7417 } 7418 } 7419 } 7420 7421 return this; 7422 }, 7423 7424 removeClass: function( value ) { 7425 var classes, elem, cur, curValue, clazz, j, finalValue, 7426 i = 0; 7427 7428 if ( jQuery.isFunction( value ) ) { 7429 return this.each( function( j ) { 7430 jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); 7431 } ); 7432 } 7433 7434 if ( !arguments.length ) { 7435 return this.attr( "class", "" ); 7436 } 7437 7438 if ( typeof value === "string" && value ) { 7439 classes = value.match( rnotwhite ) || []; 7440 7441 while ( ( elem = this[ i++ ] ) ) { 7442 curValue = getClass( elem ); 7443 7444 // This expression is here for better compressibility (see addClass) 7445 cur = elem.nodeType === 1 && 7446 ( " " + curValue + " " ).replace( rclass, " " ); 7447 7448 if ( cur ) { 7449 j = 0; 7450 while ( ( clazz = classes[ j++ ] ) ) { 7451 7452 // Remove *all* instances 7453 while ( cur.indexOf( " " + clazz + " " ) > -1 ) { 7454 cur = cur.replace( " " + clazz + " ", " " ); 7455 } 7456 } 7457 7458 // Only assign if different to avoid unneeded rendering. 7459 finalValue = jQuery.trim( cur ); 7460 if ( curValue !== finalValue ) { 7461 elem.setAttribute( "class", finalValue ); 7462 } 7463 } 7464 } 7465 } 7466 7467 return this; 7468 }, 7469 7470 toggleClass: function( value, stateVal ) { 7471 var type = typeof value; 7472 7473 if ( typeof stateVal === "boolean" && type === "string" ) { 7474 return stateVal ? this.addClass( value ) : this.removeClass( value ); 7475 } 7476 7477 if ( jQuery.isFunction( value ) ) { 7478 return this.each( function( i ) { 7479 jQuery( this ).toggleClass( 7480 value.call( this, i, getClass( this ), stateVal ), 7481 stateVal 7482 ); 7483 } ); 7484 } 7485 7486 return this.each( function() { 7487 var className, i, self, classNames; 7488 7489 if ( type === "string" ) { 7490 7491 // Toggle individual class names 7492 i = 0; 7493 self = jQuery( this ); 7494 classNames = value.match( rnotwhite ) || []; 7495 7496 while ( ( className = classNames[ i++ ] ) ) { 7497 7498 // Check each className given, space separated list 7499 if ( self.hasClass( className ) ) { 7500 self.removeClass( className ); 7501 } else { 7502 self.addClass( className ); 7503 } 7504 } 7505 7506 // Toggle whole class name 7507 } else if ( value === undefined || type === "boolean" ) { 7508 className = getClass( this ); 7509 if ( className ) { 7510 7511 // Store className if set 7512 dataPriv.set( this, "__className__", className ); 7513 } 7514 7515 // If the element has a class name or if we're passed `false`, 7516 // then remove the whole classname (if there was one, the above saved it). 7517 // Otherwise bring back whatever was previously saved (if anything), 7518 // falling back to the empty string if nothing was stored. 7519 if ( this.setAttribute ) { 7520 this.setAttribute( "class", 7521 className || value === false ? 7522 "" : 7523 dataPriv.get( this, "__className__" ) || "" 7524 ); 7525 } 7526 } 7527 } ); 7528 }, 7529 7530 hasClass: function( selector ) { 7531 var className, elem, 7532 i = 0; 7533 7534 className = " " + selector + " "; 7535 while ( ( elem = this[ i++ ] ) ) { 7536 if ( elem.nodeType === 1 && 7537 ( " " + getClass( elem ) + " " ).replace( rclass, " " ) 7538 .indexOf( className ) > -1 7539 ) { 7540 return true; 7541 } 7542 } 7543 7544 return false; 7545 } 7546} ); 7547 7548 7549 7550 7551var rreturn = /\r/g, 7552 rspaces = /[\x20\t\r\n\f]+/g; 7553 7554jQuery.fn.extend( { 7555 val: function( value ) { 7556 var hooks, ret, isFunction, 7557 elem = this[ 0 ]; 7558 7559 if ( !arguments.length ) { 7560 if ( elem ) { 7561 hooks = jQuery.valHooks[ elem.type ] || 7562 jQuery.valHooks[ elem.nodeName.toLowerCase() ]; 7563 7564 if ( hooks && 7565 "get" in hooks && 7566 ( ret = hooks.get( elem, "value" ) ) !== undefined 7567 ) { 7568 return ret; 7569 } 7570 7571 ret = elem.value; 7572 7573 return typeof ret === "string" ? 7574 7575 // Handle most common string cases 7576 ret.replace( rreturn, "" ) : 7577 7578 // Handle cases where value is null/undef or number 7579 ret == null ? "" : ret; 7580 } 7581 7582 return; 7583 } 7584 7585 isFunction = jQuery.isFunction( value ); 7586 7587 return this.each( function( i ) { 7588 var val; 7589 7590 if ( this.nodeType !== 1 ) { 7591 return; 7592 } 7593 7594 if ( isFunction ) { 7595 val = value.call( this, i, jQuery( this ).val() ); 7596 } else { 7597 val = value; 7598 } 7599 7600 // Treat null/undefined as ""; convert numbers to string 7601 if ( val == null ) { 7602 val = ""; 7603 7604 } else if ( typeof val === "number" ) { 7605 val += ""; 7606 7607 } else if ( jQuery.isArray( val ) ) { 7608 val = jQuery.map( val, function( value ) { 7609 return value == null ? "" : value + ""; 7610 } ); 7611 } 7612 7613 hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; 7614 7615 // If set returns undefined, fall back to normal setting 7616 if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { 7617 this.value = val; 7618 } 7619 } ); 7620 } 7621} ); 7622 7623jQuery.extend( { 7624 valHooks: { 7625 option: { 7626 get: function( elem ) { 7627 7628 var val = jQuery.find.attr( elem, "value" ); 7629 return val != null ? 7630 val : 7631 7632 // Support: IE10-11+ 7633 // option.text throws exceptions (#14686, #14858) 7634 // Strip and collapse whitespace 7635 // https://html.spec.whatwg.org/#strip-and-collapse-whitespace 7636 jQuery.trim( jQuery.text( elem ) ).replace( rspaces, " " ); 7637 } 7638 }, 7639 select: { 7640 get: function( elem ) { 7641 var value, option, 7642 options = elem.options, 7643 index = elem.selectedIndex, 7644 one = elem.type === "select-one" || index < 0, 7645 values = one ? null : [], 7646 max = one ? index + 1 : options.length, 7647 i = index < 0 ? 7648 max : 7649 one ? index : 0; 7650 7651 // Loop through all the selected options 7652 for ( ; i < max; i++ ) { 7653 option = options[ i ]; 7654 7655 // IE8-9 doesn't update selected after form reset (#2551) 7656 if ( ( option.selected || i === index ) && 7657 7658 // Don't return options that are disabled or in a disabled optgroup 7659 ( support.optDisabled ? 7660 !option.disabled : option.getAttribute( "disabled" ) === null ) && 7661 ( !option.parentNode.disabled || 7662 !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { 7663 7664 // Get the specific value for the option 7665 value = jQuery( option ).val(); 7666 7667 // We don't need an array for one selects 7668 if ( one ) { 7669 return value; 7670 } 7671 7672 // Multi-Selects return an array 7673 values.push( value ); 7674 } 7675 } 7676 7677 return values; 7678 }, 7679 7680 set: function( elem, value ) { 7681 var optionSet, option, 7682 options = elem.options, 7683 values = jQuery.makeArray( value ), 7684 i = options.length; 7685 7686 while ( i-- ) { 7687 option = options[ i ]; 7688 if ( option.selected = 7689 jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 7690 ) { 7691 optionSet = true; 7692 } 7693 } 7694 7695 // Force browsers to behave consistently when non-matching value is set 7696 if ( !optionSet ) { 7697 elem.selectedIndex = -1; 7698 } 7699 return values; 7700 } 7701 } 7702 } 7703} ); 7704 7705// Radios and checkboxes getter/setter 7706jQuery.each( [ "radio", "checkbox" ], function() { 7707 jQuery.valHooks[ this ] = { 7708 set: function( elem, value ) { 7709 if ( jQuery.isArray( value ) ) { 7710 return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); 7711 } 7712 } 7713 }; 7714 if ( !support.checkOn ) { 7715 jQuery.valHooks[ this ].get = function( elem ) { 7716 return elem.getAttribute( "value" ) === null ? "on" : elem.value; 7717 }; 7718 } 7719} ); 7720 7721 7722 7723 7724// Return jQuery for attributes-only inclusion 7725 7726 7727var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/; 7728 7729jQuery.extend( jQuery.event, { 7730 7731 trigger: function( event, data, elem, onlyHandlers ) { 7732 7733 var i, cur, tmp, bubbleType, ontype, handle, special, 7734 eventPath = [ elem || document ], 7735 type = hasOwn.call( event, "type" ) ? event.type : event, 7736 namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; 7737 7738 cur = tmp = elem = elem || document; 7739 7740 // Don't do events on text and comment nodes 7741 if ( elem.nodeType === 3 || elem.nodeType === 8 ) { 7742 return; 7743 } 7744 7745 // focus/blur morphs to focusin/out; ensure we're not firing them right now 7746 if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { 7747 return; 7748 } 7749 7750 if ( type.indexOf( "." ) > -1 ) { 7751 7752 // Namespaced trigger; create a regexp to match event type in handle() 7753 namespaces = type.split( "." ); 7754 type = namespaces.shift(); 7755 namespaces.sort(); 7756 } 7757 ontype = type.indexOf( ":" ) < 0 && "on" + type; 7758 7759 // Caller can pass in a jQuery.Event object, Object, or just an event type string 7760 event = event[ jQuery.expando ] ? 7761 event : 7762 new jQuery.Event( type, typeof event === "object" && event ); 7763 7764 // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) 7765 event.isTrigger = onlyHandlers ? 2 : 3; 7766 event.namespace = namespaces.join( "." ); 7767 event.rnamespace = event.namespace ? 7768 new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : 7769 null; 7770 7771 // Clean up the event in case it is being reused 7772 event.result = undefined; 7773 if ( !event.target ) { 7774 event.target = elem; 7775 } 7776 7777 // Clone any incoming data and prepend the event, creating the handler arg list 7778 data = data == null ? 7779 [ event ] : 7780 jQuery.makeArray( data, [ event ] ); 7781 7782 // Allow special events to draw outside the lines 7783 special = jQuery.event.special[ type ] || {}; 7784 if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { 7785 return; 7786 } 7787 7788 // Determine event propagation path in advance, per W3C events spec (#9951) 7789 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) 7790 if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { 7791 7792 bubbleType = special.delegateType || type; 7793 if ( !rfocusMorph.test( bubbleType + type ) ) { 7794 cur = cur.parentNode; 7795 } 7796 for ( ; cur; cur = cur.parentNode ) { 7797 eventPath.push( cur ); 7798 tmp = cur; 7799 } 7800 7801 // Only add window if we got to document (e.g., not plain obj or detached DOM) 7802 if ( tmp === ( elem.ownerDocument || document ) ) { 7803 eventPath.push( tmp.defaultView || tmp.parentWindow || window ); 7804 } 7805 } 7806 7807 // Fire handlers on the event path 7808 i = 0; 7809 while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { 7810 7811 event.type = i > 1 ? 7812 bubbleType : 7813 special.bindType || type; 7814 7815 // jQuery handler 7816 handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] && 7817 dataPriv.get( cur, "handle" ); 7818 if ( handle ) { 7819 handle.apply( cur, data ); 7820 } 7821 7822 // Native handler 7823 handle = ontype && cur[ ontype ]; 7824 if ( handle && handle.apply && acceptData( cur ) ) { 7825 event.result = handle.apply( cur, data ); 7826 if ( event.result === false ) { 7827 event.preventDefault(); 7828 } 7829 } 7830 } 7831 event.type = type; 7832 7833 // If nobody prevented the default action, do it now 7834 if ( !onlyHandlers && !event.isDefaultPrevented() ) { 7835 7836 if ( ( !special._default || 7837 special._default.apply( eventPath.pop(), data ) === false ) && 7838 acceptData( elem ) ) { 7839 7840 // Call a native DOM method on the target with the same name name as the event. 7841 // Don't do default actions on window, that's where global variables be (#6170) 7842 if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) { 7843 7844 // Don't re-trigger an onFOO event when we call its FOO() method 7845 tmp = elem[ ontype ]; 7846 7847 if ( tmp ) { 7848 elem[ ontype ] = null; 7849 } 7850 7851 // Prevent re-triggering of the same event, since we already bubbled it above 7852 jQuery.event.triggered = type; 7853 elem[ type ](); 7854 jQuery.event.triggered = undefined; 7855 7856 if ( tmp ) { 7857 elem[ ontype ] = tmp; 7858 } 7859 } 7860 } 7861 } 7862 7863 return event.result; 7864 }, 7865 7866 // Piggyback on a donor event to simulate a different one 7867
7867simulate: function( type, elem, event ) { 7868 var e = jQuery.extend( 7869 new jQuery.Event(), 7870 event, 7871 { 7872 type: type, 7873 isSimulated: true 7874 7875 // Previously, `originalEvent: {}` was set here, so stopPropagation call 7876 // would not be triggered on donor event, since in our own 7877 // jQuery.event.stopPropagation function we had a check for existence of 7878 // originalEvent.stopPropagation method, so, consequently it would be a noop. 7879 // 7880 // But now, this "simulate" function is used only for events 7881 // for which stopPropagation() is noop, so there is no need for that anymore. 7882 // 7883 // For the 1.x branch though, guard for "click" and "submit" 7884 // events is still used, but was moved to jQuery.event.stopPropagation function 7885 // because `originalEvent` should point to the original event for the constancy 7886 // with other events and for more focused logic 7887 } 7888 ); 7889 7890 jQuery.event.trigger( e, null, elem ); 7891 7892 if ( e.isDefaultPrevented() ) { 7893 event.preventDefault(); 7894 }
vendor: 40,185 bytes, lines 7894-9478
7894 7895 } 7896 7897} ); 7898 7899jQuery.fn.extend( { 7900 7901 trigger: function( type, data ) { 7902 return this.each( function() { 7903 jQuery.event.trigger( type, data, this ); 7904 } ); 7905 }, 7906 triggerHandler: function( type, data ) { 7907 var elem = this[ 0 ]; 7908 if ( elem ) { 7909 return jQuery.event.trigger( type, data, elem, true ); 7910 } 7911 } 7912} ); 7913 7914 7915jQuery.each( ( "blur focus focusin focusout load resize scroll unload click dblclick " + 7916 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + 7917 "change select submit keydown keypress keyup error contextmenu" ).split( " " ), 7918 function( i, name ) { 7919 7920 // Handle event binding 7921 jQuery.fn[ name ] = function( data, fn ) { 7922 return arguments.length > 0 ? 7923 this.on( name, null, data, fn ) : 7924 this.trigger( name ); 7925 }; 7926} ); 7927 7928jQuery.fn.extend( { 7929 hover: function( fnOver, fnOut ) { 7930 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); 7931 } 7932} ); 7933 7934 7935 7936 7937support.focusin = "onfocusin" in window; 7938 7939 7940// Support: Firefox 7941// Firefox doesn't have focus(in | out) events 7942// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 7943// 7944// Support: Chrome, Safari 7945// focus(in | out) events fire after focus & blur events, 7946// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order 7947// Related ticket - https://code.google.com/p/chromium/issues/detail?id=449857 7948if ( !support.focusin ) { 7949 jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { 7950 7951 // Attach a single capturing handler on the document while someone wants focusin/focusout 7952 var handler = function( event ) { 7953 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); 7954 }; 7955 7956 jQuery.event.special[ fix ] = { 7957 setup: function() { 7958 var doc = this.ownerDocument || this, 7959 attaches = dataPriv.access( doc, fix ); 7960 7961 if ( !attaches ) { 7962 doc.addEventListener( orig, handler, true ); 7963 } 7964 dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); 7965 }, 7966 teardown: function() { 7967 var doc = this.ownerDocument || this, 7968 attaches = dataPriv.access( doc, fix ) - 1; 7969 7970 if ( !attaches ) { 7971 doc.removeEventListener( orig, handler, true ); 7972 dataPriv.remove( doc, fix ); 7973 7974 } else { 7975 dataPriv.access( doc, fix, attaches ); 7976 } 7977 } 7978 }; 7979 } ); 7980} 7981var location = window.location; 7982 7983var nonce = jQuery.now(); 7984 7985var rquery = ( /\?/ ); 7986 7987 7988 7989// Support: Android 2.3 7990// Workaround failure to string-cast null input 7991jQuery.parseJSON = function( data ) { 7992 return JSON.parse( data + "" ); 7993}; 7994 7995 7996// Cross-browser xml parsing 7997jQuery.parseXML = function( data ) { 7998 var xml; 7999 if ( !data || typeof data !== "string" ) { 8000 return null; 8001 } 8002 8003 // Support: IE9 8004 try { 8005 xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); 8006 } catch ( e ) { 8007 xml = undefined; 8008 } 8009 8010 if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { 8011 jQuery.error( "Invalid XML: " + data ); 8012 } 8013 return xml; 8014}; 8015 8016 8017var 8018 rhash = /#.*$/, 8019 rts = /([?&])_=[^&]*/, 8020 rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, 8021 8022 // #7653, #8125, #8152: local protocol detection 8023 rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, 8024 rnoContent = /^(?:GET|HEAD)$/, 8025 rprotocol = /^\/\//, 8026 8027 /* Prefilters 8028 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) 8029 * 2) These are called: 8030 * - BEFORE asking for a transport 8031 * - AFTER param serialization (s.data is a string if s.processData is true) 8032 * 3) key is the dataType 8033 * 4) the catchall symbol "*" can be used 8034 * 5) execution will start with transport dataType and THEN continue down to "*" if needed 8035 */ 8036 prefilters = {}, 8037 8038 /* Transports bindings 8039 * 1) key is the dataType 8040 * 2) the catchall symbol "*" can be used 8041 * 3) selection will start with transport dataType and THEN go to "*" if needed 8042 */ 8043 transports = {}, 8044 8045 // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression 8046 allTypes = "*/".concat( "*" ), 8047 8048 // Anchor tag for parsing the document origin 8049 originAnchor = document.createElement( "a" ); 8050 originAnchor.href = location.href; 8051 8052// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport 8053function addToPrefiltersOrTransports( structure ) { 8054 8055 // dataTypeExpression is optional and defaults to "*" 8056 return function( dataTypeExpression, func ) { 8057 8058 if ( typeof dataTypeExpression !== "string" ) { 8059 func = dataTypeExpression; 8060 dataTypeExpression = "*"; 8061 } 8062 8063 var dataType, 8064 i = 0, 8065 dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || []; 8066 8067 if ( jQuery.isFunction( func ) ) { 8068 8069 // For each dataType in the dataTypeExpression 8070 while ( ( dataType = dataTypes[ i++ ] ) ) { 8071 8072 // Prepend if requested 8073 if ( dataType[ 0 ] === "+" ) { 8074 dataType = dataType.slice( 1 ) || "*"; 8075 ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); 8076 8077 // Otherwise append 8078 } else { 8079 ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); 8080 } 8081 } 8082 } 8083 }; 8084} 8085 8086// Base inspection function for prefilters and transports 8087function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { 8088 8089 var inspected = {}, 8090 seekingTransport = ( structure === transports ); 8091 8092 function inspect( dataType ) { 8093 var selected; 8094 inspected[ dataType ] = true; 8095 jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { 8096 var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); 8097 if ( typeof dataTypeOrTransport === "string" && 8098 !seekingTransport && !inspected[ dataTypeOrTransport ] ) { 8099 8100 options.dataTypes.unshift( dataTypeOrTransport ); 8101 inspect( dataTypeOrTransport ); 8102 return false; 8103 } else if ( seekingTransport ) { 8104 return !( selected = dataTypeOrTransport ); 8105 } 8106 } ); 8107 return selected; 8108 } 8109 8110 return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); 8111} 8112 8113// A special extend for ajax options 8114// that takes "flat" options (not to be deep extended) 8115// Fixes #9887 8116function ajaxExtend( target, src ) { 8117 var key, deep, 8118 flatOptions = jQuery.ajaxSettings.flatOptions || {}; 8119 8120 for ( key in src ) { 8121 if ( src[ key ] !== undefined ) { 8122 ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; 8123 } 8124 } 8125 if ( deep ) { 8126 jQuery.extend( true, target, deep ); 8127 } 8128 8129 return target; 8130} 8131 8132/* Handles responses to an ajax request: 8133 * - finds the right dataType (mediates between content-type and expected dataType) 8134 * - returns the corresponding response 8135 */ 8136function ajaxHandleResponses( s, jqXHR, responses ) { 8137 8138 var ct, type, finalDataType, firstDataType, 8139 contents = s.contents, 8140 dataTypes = s.dataTypes; 8141 8142 // Remove auto dataType and get content-type in the process 8143 while ( dataTypes[ 0 ] === "*" ) { 8144 dataTypes.shift(); 8145 if ( ct === undefined ) { 8146 ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); 8147 } 8148 } 8149 8150 // Check if we're dealing with a known content-type 8151 if ( ct ) { 8152 for ( type in contents ) { 8153 if ( contents[ type ] && contents[ type ].test( ct ) ) { 8154 dataTypes.unshift( type ); 8155 break; 8156 } 8157 } 8158 } 8159 8160 // Check to see if we have a response for the expected dataType 8161 if ( dataTypes[ 0 ] in responses ) { 8162 finalDataType = dataTypes[ 0 ]; 8163 } else { 8164 8165 // Try convertible dataTypes 8166 for ( type in responses ) { 8167 if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { 8168 finalDataType = type; 8169 break; 8170 } 8171 if ( !firstDataType ) { 8172 firstDataType = type; 8173 } 8174 } 8175 8176 // Or just use first one 8177 finalDataType = finalDataType || firstDataType; 8178 } 8179 8180 // If we found a dataType 8181 // We add the dataType to the list if needed 8182 // and return the corresponding response 8183 if ( finalDataType ) { 8184 if ( finalDataType !== dataTypes[ 0 ] ) { 8185 dataTypes.unshift( finalDataType ); 8186 } 8187 return responses[ finalDataType ]; 8188 } 8189} 8190 8191/* Chain conversions given the request and the original response 8192 * Also sets the responseXXX fields on the jqXHR instance 8193 */ 8194function ajaxConvert( s, response, jqXHR, isSuccess ) { 8195 var conv2, current, conv, tmp, prev, 8196 converters = {}, 8197 8198 // Work with a copy of dataTypes in case we need to modify it for conversion 8199 dataTypes = s.dataTypes.slice(); 8200 8201 // Create converters map with lowercased keys 8202 if ( dataTypes[ 1 ] ) { 8203 for ( conv in s.converters ) { 8204 converters[ conv.toLowerCase() ] = s.converters[ conv ]; 8205 } 8206 } 8207 8208 current = dataTypes.shift(); 8209 8210 // Convert to each sequential dataType 8211 while ( current ) { 8212 8213 if ( s.responseFields[ current ] ) { 8214 jqXHR[ s.responseFields[ current ] ] = response; 8215 } 8216 8217 // Apply the dataFilter if provided 8218 if ( !prev && isSuccess && s.dataFilter ) { 8219 response = s.dataFilter( response, s.dataType ); 8220 } 8221 8222 prev = current; 8223 current = dataTypes.shift(); 8224 8225 if ( current ) { 8226 8227 // There's only work to do if current dataType is non-auto 8228 if ( current === "*" ) { 8229 8230 current = prev; 8231 8232 // Convert response if prev dataType is non-auto and differs from current 8233 } else if ( prev !== "*" && prev !== current ) { 8234 8235 // Seek a direct converter 8236 conv = converters[ prev + " " + current ] || converters[ "* " + current ]; 8237 8238 // If none found, seek a pair 8239 if ( !conv ) { 8240 for ( conv2 in converters ) { 8241 8242 // If conv2 outputs current 8243 tmp = conv2.split( " " ); 8244 if ( tmp[ 1 ] === current ) { 8245 8246 // If prev can be converted to accepted input 8247 conv = converters[ prev + " " + tmp[ 0 ] ] || 8248 converters[ "* " + tmp[ 0 ] ]; 8249 if ( conv ) { 8250 8251 // Condense equivalence converters 8252 if ( conv === true ) { 8253 conv = converters[ conv2 ]; 8254 8255 // Otherwise, insert the intermediate dataType 8256 } else if ( converters[ conv2 ] !== true ) { 8257 current = tmp[ 0 ]; 8258 dataTypes.unshift( tmp[ 1 ] ); 8259 } 8260 break; 8261 } 8262 } 8263 } 8264 } 8265 8266 // Apply converter (if not an equivalence) 8267 if ( conv !== true ) { 8268 8269 // Unless errors are allowed to bubble, catch and return them 8270 if ( conv && s.throws ) { 8271 response = conv( response ); 8272 } else { 8273 try { 8274 response = conv( response ); 8275 } catch ( e ) { 8276 return { 8277 state: "parsererror", 8278 error: conv ? e : "No conversion from " + prev + " to " + current 8279 }; 8280 } 8281 } 8282 } 8283 } 8284 } 8285 } 8286 8287 return { state: "success", data: response }; 8288} 8289 8290jQuery.extend( { 8291 8292 // Counter for holding the number of active queries 8293 active: 0, 8294 8295 // Last-Modified header cache for next request 8296 lastModified: {}, 8297 etag: {}, 8298 8299 ajaxSettings: { 8300 url: location.href, 8301 type: "GET", 8302 isLocal: rlocalProtocol.test( location.protocol ), 8303 global: true, 8304 processData: true, 8305 async: true, 8306 contentType: "application/x-www-form-urlencoded; charset=UTF-8", 8307 /* 8308 timeout: 0, 8309 data: null, 8310 dataType: null, 8311 username: null, 8312 password: null, 8313 cache: null, 8314 throws: false, 8315 traditional: false, 8316 headers: {}, 8317 */ 8318 8319 accepts: { 8320 "*": allTypes, 8321 text: "text/plain", 8322 html: "text/html", 8323 xml: "application/xml, text/xml", 8324 json: "application/json, text/javascript" 8325 }, 8326 8327 contents: { 8328 xml: /\bxml\b/, 8329 html: /\bhtml/, 8330 json: /\bjson\b/ 8331 }, 8332 8333 responseFields: { 8334 xml: "responseXML", 8335 text: "responseText", 8336 json: "responseJSON" 8337 }, 8338 8339 // Data converters 8340 // Keys separate source (or catchall "*") and destination types with a single space 8341 converters: { 8342 8343 // Convert anything to text 8344 "* text": String, 8345 8346 // Text to html (true = no transformation) 8347 "text html": true, 8348 8349 // Evaluate text as a json expression 8350 "text json": jQuery.parseJSON, 8351 8352 // Parse text as xml 8353 "text xml": jQuery.parseXML 8354 }, 8355 8356 // For options that shouldn't be deep extended: 8357 // you can add your own custom options here if 8358 // and when you create one that shouldn't be 8359 // deep extended (see ajaxExtend) 8360 flatOptions: { 8361 url: true, 8362 context: true 8363 } 8364 }, 8365 8366 // Creates a full fledged settings object into target 8367 // with both ajaxSettings and settings fields. 8368 // If target is omitted, writes into ajaxSettings. 8369 ajaxSetup: function( target, settings ) { 8370 return settings ? 8371 8372 // Building a settings object 8373 ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : 8374 8375 // Extending ajaxSettings 8376 ajaxExtend( jQuery.ajaxSettings, target ); 8377 }, 8378 8379 ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), 8380 ajaxTransport: addToPrefiltersOrTransports( transports ), 8381 8382 // Main method 8383 ajax: function( url, options ) { 8384 8385 // If url is an object, simulate pre-1.5 signature 8386 if ( typeof url === "object" ) { 8387 options = url; 8388 url = undefined; 8389 } 8390 8391 // Force options to be an object 8392 options = options || {}; 8393 8394 var transport, 8395 8396 // URL without anti-cache param 8397 cacheURL, 8398 8399 // Response headers 8400 responseHeadersString, 8401 responseHeaders, 8402 8403 // timeout handle 8404 timeoutTimer, 8405 8406 // Url cleanup var 8407 urlAnchor, 8408 8409 // To know if global events are to be dispatched 8410 fireGlobals, 8411 8412 // Loop variable 8413 i, 8414 8415 // Create the final options object 8416 s = jQuery.ajaxSetup( {}, options ), 8417 8418 // Callbacks context 8419 callbackContext = s.context || s, 8420 8421 // Context for global events is callbackContext if it is a DOM node or jQuery collection 8422 globalEventContext = s.context && 8423 ( callbackContext.nodeType || callbackContext.jquery ) ? 8424 jQuery( callbackContext ) : 8425 jQuery.event, 8426 8427 // Deferreds 8428 deferred = jQuery.Deferred(), 8429 completeDeferred = jQuery.Callbacks( "once memory" ), 8430 8431 // Status-dependent callbacks 8432 statusCode = s.statusCode || {}, 8433 8434 // Headers (they are sent all at once) 8435 requestHeaders = {}, 8436 requestHeadersNames = {}, 8437 8438 // The jqXHR state 8439 state = 0, 8440 8441 // Default abort message 8442 strAbort = "canceled", 8443 8444 // Fake xhr 8445 jqXHR = { 8446 readyState: 0, 8447 8448 // Builds headers hashtable if needed 8449 getResponseHeader: function( key ) { 8450 var match; 8451 if ( state === 2 ) { 8452 if ( !responseHeaders ) { 8453 responseHeaders = {}; 8454 while ( ( match = rheaders.exec( responseHeadersString ) ) ) { 8455 responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; 8456 } 8457 } 8458 match = responseHeaders[ key.toLowerCase() ]; 8459 } 8460 return match == null ? null : match; 8461 }, 8462 8463 // Raw string 8464 getAllResponseHeaders: function() { 8465 return state === 2 ? responseHeadersString : null; 8466 }, 8467 8468 // Caches the header 8469 setRequestHeader: function( name, value ) { 8470 var lname = name.toLowerCase(); 8471 if ( !state ) { 8472 name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; 8473 requestHeaders[ name ] = value; 8474 } 8475 return this; 8476 }, 8477 8478 // Overrides response content-type header 8479 overrideMimeType: function( type ) { 8480 if ( !state ) { 8481 s.mimeType = type; 8482 } 8483 return this; 8484 }, 8485 8486 // Status-dependent callbacks 8487 statusCode: function( map ) { 8488 var code; 8489 if ( map ) { 8490 if ( state < 2 ) { 8491 for ( code in map ) { 8492 8493 // Lazy-add the new callback in a way that preserves old ones 8494 statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; 8495 } 8496 } else { 8497 8498 // Execute the appropriate callbacks 8499 jqXHR.always( map[ jqXHR.status ] ); 8500 } 8501 } 8502 return this; 8503 }, 8504 8505 // Cancel the request 8506 abort: function( statusText ) { 8507 var finalText = statusText || strAbort; 8508 if ( transport ) { 8509 transport.abort( finalText ); 8510 } 8511 done( 0, finalText ); 8512 return this; 8513 } 8514 }; 8515 8516 // Attach deferreds 8517 deferred.promise( jqXHR ).complete = completeDeferred.add; 8518 jqXHR.success = jqXHR.done; 8519 jqXHR.error = jqXHR.fail; 8520 8521 // Remove hash character (#7531: and string promotion) 8522 // Add protocol if not provided (prefilters might expect it) 8523 // Handle falsy url in the settings object (#10093: consistency with old signature) 8524 // We also use the url parameter if available 8525 s.url = ( ( url || s.url || location.href ) + "" ).replace( rhash, "" ) 8526 .replace( rprotocol, location.protocol + "//" ); 8527 8528 // Alias method option to type as per ticket #12004 8529 s.type = options.method || options.type || s.method || s.type; 8530 8531 // Extract dataTypes list 8532 s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ]; 8533 8534 // A cross-domain request is in order when the origin doesn't match the current origin. 8535 if ( s.crossDomain == null ) { 8536 urlAnchor = document.createElement( "a" ); 8537 8538 // Support: IE8-11+ 8539 // IE throws exception if url is malformed, e.g. http://example.com:80x/ 8540 try { 8541 urlAnchor.href = s.url; 8542 8543 // Support: IE8-11+ 8544 // Anchor's host property isn't correctly set when s.url is relative 8545 urlAnchor.href = urlAnchor.href; 8546 s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== 8547 urlAnchor.protocol + "//" + urlAnchor.host; 8548 } catch ( e ) { 8549 8550 // If there is an error parsing the URL, assume it is crossDomain, 8551 // it can be rejected by the transport if it is invalid 8552 s.crossDomain = true; 8553 } 8554 } 8555 8556 // Convert data if not already a string 8557 if ( s.data && s.processData && typeof s.data !== "string" ) { 8558 s.data = jQuery.param( s.data, s.traditional ); 8559 } 8560 8561 // Apply prefilters 8562 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); 8563 8564 // If request was aborted inside a prefilter, stop there 8565 if ( state === 2 ) { 8566 return jqXHR; 8567 } 8568 8569 // We can fire global events as of now if asked to 8570 // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) 8571 fireGlobals = jQuery.event && s.global; 8572 8573 // Watch for a new set of requests 8574 if ( fireGlobals && jQuery.active++ === 0 ) { 8575 jQuery.event.trigger( "ajaxStart" ); 8576 } 8577 8578 // Uppercase the type 8579 s.type = s.type.toUpperCase(); 8580 8581 // Determine if request has content 8582 s.hasContent = !rnoContent.test( s.type ); 8583 8584 // Save the URL in case we're toying with the If-Modified-Since 8585 // and/or If-None-Match header later on 8586 cacheURL = s.url; 8587 8588 // More options handling for requests with no content 8589 if ( !s.hasContent ) { 8590 8591 // If data is available, append data to url 8592 if ( s.data ) { 8593 cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data ); 8594 8595 // #9682: remove data so that it's not used in an eventual retry 8596 delete s.data; 8597 } 8598 8599 // Add anti-cache in url if needed 8600 if ( s.cache === false ) { 8601 s.url = rts.test( cacheURL ) ? 8602 8603 // If there is already a '_' parameter, set its value 8604 cacheURL.replace( rts, "$1_=" + nonce++ ) : 8605 8606 // Otherwise add one to the end 8607 cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++; 8608 } 8609 } 8610 8611 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. 8612 if ( s.ifModified ) { 8613 if ( jQuery.lastModified[ cacheURL ] ) { 8614 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); 8615 } 8616 if ( jQuery.etag[ cacheURL ] ) { 8617 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); 8618 } 8619 } 8620 8621 // Set the correct header, if data is being sent 8622 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { 8623 jqXHR.setRequestHeader( "Content-Type", s.contentType ); 8624 } 8625 8626 // Set the Accepts header for the server, depending on the dataType 8627 jqXHR.setRequestHeader( 8628 "Accept", 8629 s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? 8630 s.accepts[ s.dataTypes[ 0 ] ] + 8631 ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : 8632 s.accepts[ "*" ] 8633 ); 8634 8635 // Check for headers option 8636 for ( i in s.headers ) { 8637 jqXHR.setRequestHeader( i, s.headers[ i ] ); 8638 } 8639 8640 // Allow custom headers/mimetypes and early abort 8641 if ( s.beforeSend && 8642 ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { 8643 8644 // Abort if not done already and return 8645 return jqXHR.abort(); 8646 } 8647 8648 // Aborting is no longer a cancellation 8649 strAbort = "abort"; 8650 8651 // Install callbacks on deferreds 8652 for ( i in { success: 1, error: 1, complete: 1 } ) { 8653 jqXHR[ i ]( s[ i ] ); 8654 } 8655 8656 // Get transport 8657 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); 8658 8659 // If no transport, we auto-abort 8660 if ( !transport ) { 8661 done( -1, "No Transport" ); 8662 } else { 8663 jqXHR.readyState = 1; 8664 8665 // Send global event 8666 if ( fireGlobals ) { 8667 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); 8668 } 8669 8670 // If request was aborted inside ajaxSend, stop there 8671 if ( state === 2 ) { 8672 return jqXHR; 8673 } 8674 8675 // Timeout 8676 if ( s.async && s.timeout > 0 ) { 8677 timeoutTimer = window.setTimeout( function() { 8678 jqXHR.abort( "timeout" ); 8679 }, s.timeout ); 8680 } 8681 8682 try { 8683 state = 1; 8684 transport.send( requestHeaders, done ); 8685 } catch ( e ) { 8686 8687 // Propagate exception as error if not done 8688 if ( state < 2 ) { 8689 done( -1, e ); 8690 8691 // Simply rethrow otherwise 8692 } else { 8693 throw e; 8694 } 8695 } 8696 } 8697 8698 // Callback for when everything is done 8699 function done( status, nativeStatusText, responses, headers ) { 8700 var isSuccess, success, error, response, modified, 8701 statusText = nativeStatusText; 8702 8703 // Called once 8704 if ( state === 2 ) { 8705 return; 8706 } 8707 8708 // State is "done" now 8709 state = 2; 8710 8711 // Clear timeout if it exists 8712 if ( timeoutTimer ) { 8713 window.clearTimeout( timeoutTimer ); 8714 } 8715 8716 // Dereference transport for early garbage collection 8717 // (no matter how long the jqXHR object will be used) 8718 transport = undefined; 8719 8720 // Cache response headers 8721 responseHeadersString = headers || ""; 8722 8723 // Set readyState 8724 jqXHR.readyState = status > 0 ? 4 : 0; 8725 8726 // Determine if successful 8727 isSuccess = status >= 200 && status < 300 || status === 304; 8728 8729 // Get response data 8730 if ( responses ) { 8731 response = ajaxHandleResponses( s, jqXHR, responses ); 8732 } 8733 8734 // Convert no matter what (that way responseXXX fields are always set) 8735 response = ajaxConvert( s, response, jqXHR, isSuccess ); 8736 8737 // If successful, handle type chaining 8738 if ( isSuccess ) { 8739 8740 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. 8741 if ( s.ifModified ) { 8742 modified = jqXHR.getResponseHeader( "Last-Modified" ); 8743 if ( modified ) { 8744 jQuery.lastModified[ cacheURL ] = modified; 8745 } 8746 modified = jqXHR.getResponseHeader( "etag" ); 8747 if ( modified ) { 8748 jQuery.etag[ cacheURL ] = modified; 8749 } 8750 } 8751 8752 // if no content 8753 if ( status === 204 || s.type === "HEAD" ) { 8754 statusText = "nocontent"; 8755 8756 // if not modified 8757 } else if ( status === 304 ) { 8758 statusText = "notmodified"; 8759 8760 // If we have data, let's convert it 8761 } else { 8762 statusText = response.state; 8763 success = response.data; 8764 error = response.error; 8765 isSuccess = !error; 8766 } 8767 } else { 8768 8769 // Extract error from statusText and normalize for non-aborts 8770 error = statusText; 8771 if ( status || !statusText ) { 8772 statusText = "error"; 8773 if ( status < 0 ) { 8774 status = 0; 8775 } 8776 } 8777 } 8778 8779 // Set data for the fake xhr object 8780 jqXHR.status = status; 8781 jqXHR.statusText = ( nativeStatusText || statusText ) + ""; 8782 8783 // Success/Error 8784 if ( isSuccess ) { 8785 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); 8786 } else { 8787 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); 8788 } 8789 8790 // Status-dependent callbacks 8791 jqXHR.statusCode( statusCode ); 8792 statusCode = undefined; 8793 8794 if ( fireGlobals ) { 8795 globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", 8796 [ jqXHR, s, isSuccess ? success : error ] ); 8797 } 8798 8799 // Complete 8800 completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); 8801 8802 if ( fireGlobals ) { 8803 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); 8804 8805 // Handle the global AJAX counter 8806 if ( !( --jQuery.active ) ) { 8807 jQuery.event.trigger( "ajaxStop" ); 8808 } 8809 } 8810 } 8811 8812 return jqXHR; 8813 }, 8814 8815 getJSON: function( url, data, callback ) { 8816 return jQuery.get( url, data, callback, "json" ); 8817 }, 8818 8819 getScript: function( url, callback ) { 8820 return jQuery.get( url, undefined, callback, "script" ); 8821 } 8822} ); 8823 8824jQuery.each( [ "get", "post" ], function( i, method ) { 8825 jQuery[ method ] = function( url, data, callback, type ) { 8826 8827 // Shift arguments if data argument was omitted 8828 if ( jQuery.isFunction( data ) ) { 8829 type = type || callback; 8830 callback = data; 8831 data = undefined; 8832 } 8833 8834 // The url can be an options object (which then must have .url) 8835 return jQuery.ajax( jQuery.extend( { 8836 url: url, 8837 type: method, 8838 dataType: type, 8839 data: data, 8840 success: callback 8841 }, jQuery.isPlainObject( url ) && url ) ); 8842 }; 8843} ); 8844 8845 8846jQuery._evalUrl = function( url ) { 8847 return jQuery.ajax( { 8848 url: url, 8849 8850 // Make this explicit, since user can override this through ajaxSetup (#11264) 8851 type: "GET", 8852 dataType: "script", 8853 async: false, 8854 global: false, 8855 "throws": true 8856 } ); 8857}; 8858 8859 8860jQuery.fn.extend( { 8861 wrapAll: function( html ) { 8862 var wrap; 8863 8864 if ( jQuery.isFunction( html ) ) { 8865 return this.each( function( i ) { 8866 jQuery( this ).wrapAll( html.call( this, i ) ); 8867 } ); 8868 } 8869 8870 if ( this[ 0 ] ) { 8871 8872 // The elements to wrap the target around 8873 wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); 8874 8875 if ( this[ 0 ].parentNode ) { 8876 wrap.insertBefore( this[ 0 ] ); 8877 } 8878 8879 wrap.map( function() { 8880 var elem = this; 8881 8882 while ( elem.firstElementChild ) { 8883 elem = elem.firstElementChild; 8884 } 8885 8886 return elem; 8887 } ).append( this ); 8888 } 8889 8890 return this; 8891 }, 8892 8893 wrapInner: function( html ) { 8894 if ( jQuery.isFunction( html ) ) { 8895 return this.each( function( i ) { 8896 jQuery( this ).wrapInner( html.call( this, i ) ); 8897 } ); 8898 } 8899 8900 return this.each( function() { 8901 var self = jQuery( this ), 8902 contents = self.contents(); 8903 8904 if ( contents.length ) { 8905 contents.wrapAll( html ); 8906 8907 } else { 8908 self.append( html ); 8909 } 8910 } ); 8911 }, 8912 8913 wrap: function( html ) { 8914 var isFunction = jQuery.isFunction( html ); 8915 8916 return this.each( function( i ) { 8917 jQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html ); 8918 } ); 8919 }, 8920 8921 unwrap: function() { 8922 return this.parent().each( function() { 8923 if ( !jQuery.nodeName( this, "body" ) ) { 8924 jQuery( this ).replaceWith( this.childNodes ); 8925 } 8926 } ).end(); 8927 } 8928} ); 8929 8930 8931jQuery.expr.filters.hidden = function( elem ) { 8932 return !jQuery.expr.filters.visible( elem ); 8933}; 8934jQuery.expr.filters.visible = function( elem ) { 8935 8936 // Support: Opera <= 12.12 8937 // Opera reports offsetWidths and offsetHeights less than zero on some elements 8938 // Use OR instead of AND as the element is not visible if either is true 8939 // See tickets #10406 and #13132 8940 return elem.offsetWidth > 0 || elem.offsetHeight > 0 || elem.getClientRects().length > 0; 8941}; 8942 8943 8944 8945 8946var r20 = /%20/g, 8947 rbracket = /\[\]$/, 8948 rCRLF = /\r?\n/g, 8949 rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, 8950 rsubmittable = /^(?:input|select|textarea|keygen)/i; 8951 8952function buildParams( prefix, obj, traditional, add ) { 8953 var name; 8954 8955 if ( jQuery.isArray( obj ) ) { 8956 8957 // Serialize array item. 8958 jQuery.each( obj, function( i, v ) { 8959 if ( traditional || rbracket.test( prefix ) ) { 8960 8961 // Treat each array item as a scalar. 8962 add( prefix, v ); 8963 8964 } else { 8965 8966 // Item is non-scalar (array or object), encode its numeric index. 8967 buildParams( 8968 prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", 8969 v, 8970 traditional, 8971 add 8972 ); 8973 } 8974 } ); 8975 8976 } else if ( !traditional && jQuery.type( obj ) === "object" ) { 8977 8978 // Serialize object item. 8979 for ( name in obj ) { 8980 buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); 8981 } 8982 8983 } else { 8984 8985 // Serialize scalar item. 8986 add( prefix, obj ); 8987 } 8988} 8989 8990// Serialize an array of form elements or a set of 8991// key/values into a query string 8992jQuery.param = function( a, traditional ) { 8993 var prefix, 8994 s = [], 8995 add = function( key, value ) { 8996 8997 // If value is a function, invoke it and return its value 8998 value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value ); 8999 s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value ); 9000 }; 9001 9002 // Set traditional to true for jQuery <= 1.3.2 behavior. 9003 if ( traditional === undefined ) { 9004 traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional; 9005 } 9006 9007 // If an array was passed in, assume that it is an array of form elements. 9008 if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { 9009 9010 // Serialize the form elements 9011 jQuery.each( a, function() { 9012 add( this.name, this.value ); 9013 } ); 9014 9015 } else { 9016 9017 // If traditional, encode the "old" way (the way 1.3.2 or older 9018 // did it), otherwise encode params recursively. 9019 for ( prefix in a ) { 9020 buildParams( prefix, a[ prefix ], traditional, add ); 9021 } 9022 } 9023 9024 // Return the resulting serialization 9025 return s.join( "&" ).replace( r20, "+" ); 9026}; 9027 9028jQuery.fn.extend( { 9029 serialize: function() { 9030 return jQuery.param( this.serializeArray() ); 9031 }, 9032 serializeArray: function() { 9033 return this.map( function() { 9034 9035 // Can add propHook for "elements" to filter or add form elements 9036 var elements = jQuery.prop( this, "elements" ); 9037 return elements ? jQuery.makeArray( elements ) : this; 9038 } ) 9039 .filter( function() { 9040 var type = this.type; 9041 9042 // Use .is( ":disabled" ) so that fieldset[disabled] works 9043 return this.name && !jQuery( this ).is( ":disabled" ) && 9044 rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && 9045 ( this.checked || !rcheckableType.test( type ) ); 9046 } ) 9047 .map( function( i, elem ) { 9048 var val = jQuery( this ).val(); 9049 9050 return val == null ? 9051 null : 9052 jQuery.isArray( val ) ? 9053 jQuery.map( val, function( val ) { 9054 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; 9055 } ) : 9056 { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; 9057 } ).get(); 9058 } 9059} ); 9060 9061 9062jQuery.ajaxSettings.xhr = function() { 9063 try { 9064 return new window.XMLHttpRequest(); 9065 } catch ( e ) {} 9066}; 9067 9068var xhrSuccessStatus = { 9069 9070 // File protocol always yields status code 0, assume 200 9071 0: 200, 9072 9073 // Support: IE9 9074 // #1450: sometimes IE returns 1223 when it should be 204 9075 1223: 204 9076 }, 9077 xhrSupported = jQuery.ajaxSettings.xhr(); 9078 9079support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); 9080support.ajax = xhrSupported = !!xhrSupported; 9081 9082jQuery.ajaxTransport( function( options ) { 9083 var callback, errorCallback; 9084 9085 // Cross domain only allowed if supported through XMLHttpRequest 9086 if ( support.cors || xhrSupported && !options.crossDomain ) { 9087 return { 9088 send: function( headers, complete ) { 9089 var i, 9090 xhr = options.xhr(); 9091 9092 xhr.open( 9093 options.type, 9094 options.url, 9095 options.async, 9096 options.username, 9097 options.password 9098 ); 9099 9100 // Apply custom fields if provided 9101 if ( options.xhrFields ) { 9102 for ( i in options.xhrFields ) { 9103 xhr[ i ] = options.xhrFields[ i ]; 9104 } 9105 } 9106 9107 // Override mime type if needed 9108 if ( options.mimeType && xhr.overrideMimeType ) { 9109 xhr.overrideMimeType( options.mimeType ); 9110 } 9111 9112 // X-Requested-With header 9113 // For cross-domain requests, seeing as conditions for a preflight are 9114 // akin to a jigsaw puzzle, we simply never set it to be sure. 9115 // (it can always be set on a per-request basis or even using ajaxSetup) 9116 // For same-domain requests, won't change header if already provided. 9117 if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { 9118 headers[ "X-Requested-With" ] = "XMLHttpRequest"; 9119 } 9120 9121 // Set headers 9122 for ( i in headers ) { 9123 xhr.setRequestHeader( i, headers[ i ] ); 9124 } 9125 9126 // Callback 9127 callback = function( type ) { 9128 return function() { 9129 if ( callback ) { 9130 callback = errorCallback = xhr.onload = 9131 xhr.onerror = xhr.onabort = xhr.onreadystatechange = null; 9132 9133 if ( type === "abort" ) { 9134 xhr.abort(); 9135 } else if ( type === "error" ) { 9136 9137 // Support: IE9 9138 // On a manual native abort, IE9 throws 9139 // errors on any property access that is not readyState 9140 if ( typeof xhr.status !== "number" ) { 9141 complete( 0, "error" ); 9142 } else { 9143 complete( 9144 9145 // File: protocol always yields status 0; see #8605, #14207 9146 xhr.status, 9147 xhr.statusText 9148 ); 9149 } 9150 } else { 9151 complete( 9152 xhrSuccessStatus[ xhr.status ] || xhr.status, 9153 xhr.statusText, 9154 9155 // Support: IE9 only 9156 // IE9 has no XHR2 but throws on binary (trac-11426) 9157 // For XHR2 non-text, let the caller handle it (gh-2498) 9158 ( xhr.responseType || "text" ) !== "text" || 9159 typeof xhr.responseText !== "string" ? 9160 { binary: xhr.response } : 9161 { text: xhr.responseText }, 9162 xhr.getAllResponseHeaders() 9163 ); 9164 } 9165 } 9166 }; 9167 }; 9168 9169 // Listen to events 9170 xhr.onload = callback(); 9171 errorCallback = xhr.onerror = callback( "error" ); 9172 9173 // Support: IE9 9174 // Use onreadystatechange to replace onabort 9175 // to handle uncaught aborts 9176 if ( xhr.onabort !== undefined ) { 9177 xhr.onabort = errorCallback; 9178 } else { 9179 xhr.onreadystatechange = function() { 9180 9181 // Check readyState before timeout as it changes 9182 if ( xhr.readyState === 4 ) { 9183 9184 // Allow onerror to be called first, 9185 // but that will not handle a native abort 9186 // Also, save errorCallback to a variable 9187 // as xhr.onerror cannot be accessed 9188 window.setTimeout( function() { 9189 if ( callback ) { 9190 errorCallback(); 9191 } 9192 } ); 9193 } 9194 }; 9195 } 9196 9197 // Create the abort callback 9198 callback = callback( "abort" ); 9199 9200 try { 9201 9202 // Do send the request (this may raise an exception) 9203 xhr.send( options.hasContent && options.data || null ); 9204 } catch ( e ) { 9205 9206 // #14683: Only rethrow if this hasn't been notified as an error yet 9207 if ( callback ) { 9208 throw e; 9209 } 9210 } 9211 }, 9212 9213 abort: function() { 9214 if ( callback ) { 9215 callback(); 9216 } 9217 } 9218 }; 9219 } 9220} ); 9221 9222 9223 9224 9225// Install script dataType 9226jQuery.ajaxSetup( { 9227 accepts: { 9228 script: "text/javascript, application/javascript, " + 9229 "application/ecmascript, application/x-ecmascript" 9230 }, 9231 contents: { 9232 script: /\b(?:java|ecma)script\b/ 9233 }, 9234 converters: { 9235 "text script": function( text ) { 9236 jQuery.globalEval( text ); 9237 return text; 9238 } 9239 } 9240} ); 9241 9242// Handle cache's special case and crossDomain 9243jQuery.ajaxPrefilter( "script", function( s ) { 9244 if ( s.cache === undefined ) { 9245 s.cache = false; 9246 } 9247 if ( s.crossDomain ) { 9248 s.type = "GET"; 9249 } 9250} ); 9251 9252// Bind script tag hack transport 9253jQuery.ajaxTransport( "script", function( s ) { 9254 9255 // This transport only deals with cross domain requests 9256 if ( s.crossDomain ) { 9257 var script, callback; 9258 return { 9259 send: function( _, complete ) { 9260 script = jQuery( "<script>" ).prop( { 9261 charset: s.scriptCharset, 9262 src: s.url 9263 } ).on( 9264 "load error", 9265 callback = function( evt ) { 9266 script.remove(); 9267 callback = null; 9268 if ( evt ) { 9269 complete( evt.type === "error" ? 404 : 200, evt.type ); 9270 } 9271 } 9272 ); 9273 9274 // Use native DOM manipulation to avoid our domManip AJAX trickery 9275 document.head.appendChild( script[ 0 ] ); 9276 }, 9277 abort: function() { 9278 if ( callback ) { 9279 callback(); 9280 } 9281 } 9282 }; 9283 } 9284} ); 9285 9286 9287 9288 9289var oldCallbacks = [], 9290 rjsonp = /(=)\?(?=&|$)|\?\?/; 9291 9292// Default jsonp settings 9293jQuery.ajaxSetup( { 9294 jsonp: "callback", 9295 jsonpCallback: function() { 9296 var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) ); 9297 this[ callback ] = true; 9298 return callback; 9299 } 9300} ); 9301 9302// Detect, normalize options and install callbacks for jsonp requests 9303jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { 9304 9305 var callbackName, overwritten, responseContainer, 9306 jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ? 9307 "url" : 9308 typeof s.data === "string" && 9309 ( s.contentType || "" ) 9310 .indexOf( "application/x-www-form-urlencoded" ) === 0 && 9311 rjsonp.test( s.data ) && "data" 9312 ); 9313 9314 // Handle iff the expected data type is "jsonp" or we have a parameter to set 9315 if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) { 9316 9317 // Get callback name, remembering preexisting value associated with it 9318 callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ? 9319 s.jsonpCallback() : 9320 s.jsonpCallback; 9321 9322 // Insert callback into url or form data 9323 if ( jsonProp ) { 9324 s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName ); 9325 } else if ( s.jsonp !== false ) { 9326 s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; 9327 } 9328 9329 // Use data converter to retrieve json after script execution 9330 s.converters[ "script json" ] = function() { 9331 if ( !responseContainer ) { 9332 jQuery.error( callbackName + " was not called" ); 9333 } 9334 return responseContainer[ 0 ]; 9335 }; 9336 9337 // Force json dataType 9338 s.dataTypes[ 0 ] = "json"; 9339 9340 // Install callback 9341 overwritten = window[ callbackName ]; 9342 window[ callbackName ] = function() { 9343 responseContainer = arguments; 9344 }; 9345 9346 // Clean-up function (fires after converters) 9347 jqXHR.always( function() { 9348 9349 // If previous value didn't exist - remove it 9350 if ( overwritten === undefined ) { 9351 jQuery( window ).removeProp( callbackName ); 9352 9353 // Otherwise restore preexisting value 9354 } else { 9355 window[ callbackName ] = overwritten; 9356 } 9357 9358 // Save back as free 9359 if ( s[ callbackName ] ) { 9360 9361 // Make sure that re-using the options doesn't screw things around 9362 s.jsonpCallback = originalSettings.jsonpCallback; 9363 9364 // Save the callback name for future use 9365 oldCallbacks.push( callbackName ); 9366 } 9367 9368 // Call if it was a function and we have a response 9369 if ( responseContainer && jQuery.isFunction( overwritten ) ) { 9370 overwritten( responseContainer[ 0 ] ); 9371 } 9372 9373 responseContainer = overwritten = undefined; 9374 } ); 9375 9376 // Delegate to script 9377 return "script"; 9378 } 9379} ); 9380 9381 9382 9383 9384// Argument "data" should be string of html 9385// context (optional): If specified, the fragment will be created in this context, 9386// defaults to document 9387// keepScripts (optional): If true, will include scripts passed in the html string 9388jQuery.parseHTML = function( data, context, keepScripts ) { 9389 if ( !data || typeof data !== "string" ) { 9390 return null; 9391 } 9392 if ( typeof context === "boolean" ) { 9393 keepScripts = context; 9394 context = false; 9395 } 9396 context = context || document; 9397 9398 var parsed = rsingleTag.exec( data ), 9399 scripts = !keepScripts && []; 9400 9401 // Single tag 9402 if ( parsed ) { 9403 return [ context.createElement( parsed[ 1 ] ) ]; 9404 } 9405 9406 parsed = buildFragment( [ data ], context, scripts ); 9407 9408 if ( scripts && scripts.length ) { 9409 jQuery( scripts ).remove(); 9410 } 9411 9412 return jQuery.merge( [], parsed.childNodes ); 9413}; 9414 9415 9416// Keep a copy of the old load method 9417var _load = jQuery.fn.load; 9418 9419/** 9420 * Load a url into a page 9421 */ 9422jQuery.fn.load = function( url, params, callback ) { 9423 if ( typeof url !== "string" && _load ) { 9424 return _load.apply( this, arguments ); 9425 } 9426 9427 var selector, type, response, 9428 self = this, 9429 off = url.indexOf( " " ); 9430 9431 if ( off > -1 ) { 9432 selector = jQuery.trim( url.slice( off ) ); 9433 url = url.slice( 0, off ); 9434 } 9435 9436 // If it's a function 9437 if ( jQuery.isFunction( params ) ) { 9438 9439 // We assume that it's the callback 9440 callback = params; 9441 params = undefined; 9442 9443 // Otherwise, build a param string 9444 } else if ( params && typeof params === "object" ) { 9445 type = "POST"; 9446 } 9447 9448 // If we have elements to modify, make the request 9449 if ( self.length > 0 ) { 9450 jQuery.ajax( { 9451 url: url, 9452 9453 // If "type" variable is undefined, then "GET" method will be used. 9454 // Make value of this field explicit since 9455 // user can override it through ajaxSetup method 9456 type: type || "GET", 9457 dataType: "html", 9458 data: params 9459 } ).done( function( responseText ) { 9460 9461 // Save response for use in complete callback 9462 response = arguments; 9463 9464 self.html( selector ? 9465 9466 // If a selector was specified, locate the right elements in a dummy div 9467 // Exclude scripts to avoid IE 'Permission Denied' errors 9468 jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) : 9469 9470 // Otherwise use the full result 9471 responseText ); 9472 9473 // If the request succeeds, this function gets "data", "status", "jqXHR" 9474 // but they are ignored because response was set above. 9475 // If it fails, this function gets "jqXHR", "status", "error" 9476 } ).always( callback && function( jqXHR, status ) { 9477 self.each( function() { 9478 callback.apply(
9478self
vendor: 9,975 bytes, lines 9478-9843
9478, response || [ jqXHR.responseText, status, jqXHR ] ); 9479 } ); 9480 } ); 9481 } 9482 9483 return this; 9484}; 9485 9486 9487 9488 9489// Attach a bunch of functions for handling common AJAX events 9490jQuery.each( [ 9491 "ajaxStart", 9492 "ajaxStop", 9493 "ajaxComplete", 9494 "ajaxError", 9495 "ajaxSuccess", 9496 "ajaxSend" 9497], function( i, type ) { 9498 jQuery.fn[ type ] = function( fn ) { 9499 return this.on( type, fn ); 9500 }; 9501} ); 9502 9503 9504 9505 9506jQuery.expr.filters.animated = function( elem ) { 9507 return jQuery.grep( jQuery.timers, function( fn ) { 9508 return elem === fn.elem; 9509 } ).length; 9510}; 9511 9512 9513 9514 9515/** 9516 * Gets a window from an element 9517 */ 9518function getWindow( elem ) { 9519 return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView; 9520} 9521 9522jQuery.offset = { 9523 setOffset: function( elem, options, i ) { 9524 var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition, 9525 position = jQuery.css( elem, "position" ), 9526 curElem = jQuery( elem ), 9527 props = {}; 9528 9529 // Set position first, in-case top/left are set even on static elem 9530 if ( position === "static" ) { 9531 elem.style.position = "relative"; 9532 } 9533 9534 curOffset = curElem.offset(); 9535 curCSSTop = jQuery.css( elem, "top" ); 9536 curCSSLeft = jQuery.css( elem, "left" ); 9537 calculatePosition = ( position === "absolute" || position === "fixed" ) && 9538 ( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1; 9539 9540 // Need to be able to calculate position if either 9541 // top or left is auto and position is either absolute or fixed 9542 if ( calculatePosition ) { 9543 curPosition = curElem.position(); 9544 curTop = curPosition.top; 9545 curLeft = curPosition.left; 9546 9547 } else { 9548 curTop = parseFloat( curCSSTop ) || 0; 9549 curLeft = parseFloat( curCSSLeft ) || 0; 9550 } 9551 9552 if ( jQuery.isFunction( options ) ) { 9553 9554 // Use jQuery.extend here to allow modification of coordinates argument (gh-1848) 9555 options = options.call( elem, i, jQuery.extend( {}, curOffset ) ); 9556 } 9557 9558 if ( options.top != null ) { 9559 props.top = ( options.top - curOffset.top ) + curTop; 9560 } 9561 if ( options.left != null ) { 9562 props.left = ( options.left - curOffset.left ) + curLeft; 9563 } 9564 9565 if ( "using" in options ) { 9566 options.using.call( elem, props ); 9567 9568 } else { 9569 curElem.css( props ); 9570 } 9571 } 9572}; 9573 9574jQuery.fn.extend( { 9575 offset: function( options ) { 9576 if ( arguments.length ) { 9577 return options === undefined ? 9578 this : 9579 this.each( function( i ) { 9580 jQuery.offset.setOffset( this, options, i ); 9581 } ); 9582 } 9583 9584 var docElem, win, 9585 elem = this[ 0 ], 9586 box = { top: 0, left: 0 }, 9587 doc = elem && elem.ownerDocument; 9588 9589 if ( !doc ) { 9590 return; 9591 } 9592 9593 docElem = doc.documentElement; 9594 9595 // Make sure it's not a disconnected DOM node 9596 if ( !jQuery.contains( docElem, elem ) ) { 9597 return box; 9598 } 9599 9600 box = elem.getBoundingClientRect(); 9601 win = getWindow( doc ); 9602 return { 9603 top: box.top + win.pageYOffset - docElem.clientTop, 9604 left: box.left + win.pageXOffset - docElem.clientLeft 9605 }; 9606 }, 9607 9608 position: function() { 9609 if ( !this[ 0 ] ) { 9610 return; 9611 } 9612 9613 var offsetParent, offset, 9614 elem = this[ 0 ], 9615 parentOffset = { top: 0, left: 0 }; 9616 9617 // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, 9618 // because it is its only offset parent 9619 if ( jQuery.css( elem, "position" ) === "fixed" ) { 9620 9621 // Assume getBoundingClientRect is there when computed position is fixed 9622 offset = elem.getBoundingClientRect(); 9623 9624 } else { 9625 9626 // Get *real* offsetParent 9627 offsetParent = this.offsetParent(); 9628 9629 // Get correct offsets 9630 offset = this.offset(); 9631 if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) { 9632 parentOffset = offsetParent.offset(); 9633 } 9634 9635 // Add offsetParent borders 9636 parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ); 9637 parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true ); 9638 } 9639 9640 // Subtract parent offsets and element margins 9641 return { 9642 top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ), 9643 left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true ) 9644 }; 9645 }, 9646 9647 // This method will return documentElement in the following cases: 9648 // 1) For the element inside the iframe without offsetParent, this method will return 9649 // documentElement of the parent window 9650 // 2) For the hidden or detached element 9651 // 3) For body or html element, i.e. in case of the html node - it will return itself 9652 // 9653 // but those exceptions were never presented as a real life use-cases 9654 // and might be considered as more preferable results. 9655 // 9656 // This logic, however, is not guaranteed and can change at any point in the future 9657 offsetParent: function() { 9658 return this.map( function() { 9659 var offsetParent = this.offsetParent; 9660 9661 while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) { 9662 offsetParent = offsetParent.offsetParent; 9663 } 9664 9665 return offsetParent || documentElement; 9666 } ); 9667 } 9668} ); 9669 9670// Create scrollLeft and scrollTop methods 9671jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) { 9672 var top = "pageYOffset" === prop; 9673 9674 jQuery.fn[ method ] = function( val ) { 9675 return access( this, function( elem, method, val ) { 9676 var win = getWindow( elem ); 9677 9678 if ( val === undefined ) { 9679 return win ? win[ prop ] : elem[ method ]; 9680 } 9681 9682 if ( win ) { 9683 win.scrollTo( 9684 !top ? val : win.pageXOffset, 9685 top ? val : win.pageYOffset 9686 ); 9687 9688 } else { 9689 elem[ method ] = val; 9690 } 9691 }, method, val, arguments.length ); 9692 }; 9693} ); 9694 9695// Support: Safari<7-8+, Chrome<37-44+ 9696// Add the top/left cssHooks using jQuery.fn.position 9697// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084 9698// Blink bug: https://code.google.com/p/chromium/issues/detail?id=229280 9699// getComputedStyle returns percent when specified for top/left/bottom/right; 9700// rather than make the css module depend on the offset module, just check for it here 9701jQuery.each( [ "top", "left" ], function( i, prop ) { 9702 jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition, 9703 function( elem, computed ) { 9704 if ( computed ) { 9705 computed = curCSS( elem, prop ); 9706 9707 // If curCSS returns percentage, fallback to offset 9708 return rnumnonpx.test( computed ) ? 9709 jQuery( elem ).position()[ prop ] + "px" : 9710 computed; 9711 } 9712 } 9713 ); 9714} ); 9715 9716 9717// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods 9718jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { 9719 jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, 9720 function( defaultExtra, funcName ) { 9721 9722 // Margin is only for outerHeight, outerWidth 9723 jQuery.fn[ funcName ] = function( margin, value ) { 9724 var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ), 9725 extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" ); 9726 9727 return access( this, function( elem, type, value ) { 9728 var doc; 9729 9730 if ( jQuery.isWindow( elem ) ) { 9731 9732 // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there 9733 // isn't a whole lot we can do. See pull request at this URL for discussion: 9734 // https://github.com/jquery/jquery/pull/764 9735 return elem.document.documentElement[ "client" + name ]; 9736 } 9737 9738 // Get document width or height 9739 if ( elem.nodeType === 9 ) { 9740 doc = elem.documentElement; 9741 9742 // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], 9743 // whichever is greatest 9744 return Math.max( 9745 elem.body[ "scroll" + name ], doc[ "scroll" + name ], 9746 elem.body[ "offset" + name ], doc[ "offset" + name ], 9747 doc[ "client" + name ] 9748 ); 9749 } 9750 9751 return value === undefined ? 9752 9753 // Get width or height on the element, requesting but not forcing parseFloat 9754 jQuery.css( elem, type, extra ) : 9755 9756 // Set width or height on the element 9757 jQuery.style( elem, type, value, extra ); 9758 }, type, chainable ? margin : undefined, chainable, null ); 9759 }; 9760 } ); 9761} ); 9762 9763 9764jQuery.fn.extend( { 9765 9766 bind: function( types, data, fn ) { 9767 return this.on( types, null, data, fn ); 9768 }, 9769 unbind: function( types, fn ) { 9770 return this.off( types, null, fn ); 9771 }, 9772 9773 delegate: function( selector, types, data, fn ) { 9774 return this.on( types, selector, data, fn ); 9775 }, 9776 undelegate: function( selector, types, fn ) { 9777 9778 // ( namespace ) or ( selector, types [, fn] ) 9779 return arguments.length === 1 ? 9780 this.off( selector, "**" ) : 9781 this.off( types, selector || "**", fn ); 9782 }, 9783 size: function() { 9784 return this.length; 9785 } 9786} ); 9787 9788jQuery.fn.andSelf = jQuery.fn.addBack; 9789 9790 9791 9792 9793// Register as a named AMD module, since jQuery can be concatenated with other 9794// files that may use define, but not via a proper concatenation script that 9795// understands anonymous AMD modules. A named AMD is safest and most robust 9796// way to register. Lowercase jquery is used because AMD module names are 9797// derived from file names, and jQuery is normally delivered in a lowercase 9798// file name. Do this after creating the global so that if an AMD module wants 9799// to call noConflict to hide this version of jQuery, it will work. 9800 9801// Note that for maximum portability, libraries that are not jQuery should 9802// declare themselves as anonymous modules, and avoid setting a global if an 9803// AMD loader is present. jQuery is a special case. For more information, see 9804// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon 9805 9806if ( typeof define === "function" && define.amd ) { 9807 define( "jquery", [], function() { 9808 return jQuery; 9809 } ); 9810} 9811 9812 9813 9814var 9815 9816 // Map over jQuery in case of overwrite 9817 _jQuery = window.jQuery, 9818 9819 // Map over the $ in case of overwrite 9820 _$ = window.$; 9821 9822jQuery.noConflict = function( deep ) { 9823 if ( window.$ === jQuery ) { 9824 window.$ = _$; 9825 } 9826 9827 if ( deep && window.jQuery === jQuery ) { 9828 window.jQuery = _jQuery; 9829 } 9830 9831 return jQuery; 9832}; 9833 9834// Expose jQuery and $ identifiers, even in AMD 9835// (#7102#comment:10, https://github.com/jquery/jquery/pull/557) 9836// and CommonJS for browser emulators (#13566) 9837if ( !noGlobal ) { 9838 window.jQuery = window.$ = jQuery; 9839} 9840 9841return jQuery; 9842})); 9843
vendor: 4,163 bytes, lines 9844-9989
9844/*! 9845 * Bootstrap v3.3.6 (http://getbootstrap.com) 9846 * Copyright 2011-2015 Twitter, Inc. 9847 * Licensed under the MIT license 9848 */ 9849 9850if (typeof jQuery === 'undefined') { 9851 throw new Error('Bootstrap\'s JavaScript requires jQuery') 9852} 9853 9854+function ($) { 9855 'use strict'; 9856 var version = $.fn.jquery.split(' ')[0].split('.') 9857 if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 2)) { 9858 throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 3') 9859 } 9860}(jQuery); 9861 9862/* ======================================================================== 9863 * Bootstrap: transition.js v3.3.6 9864 * http://getbootstrap.com/javascript/#transitions 9865 * ======================================================================== 9866 * Copyright 2011-2015 Twitter, Inc. 9867 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 9868 * ======================================================================== */ 9869 9870 9871+function ($) { 9872 'use strict'; 9873 9874 // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) 9875 // ============================================================ 9876 9877 function transitionEnd() { 9878 var el = document.createElement('bootstrap') 9879 9880 var transEndEventNames = { 9881 WebkitTransition : 'webkitTransitionEnd', 9882 MozTransition : 'transitionend', 9883 OTransition : 'oTransitionEnd otransitionend', 9884 transition : 'transitionend' 9885 } 9886 9887 for (var name in transEndEventNames) { 9888 if (el.style[name] !== undefined) { 9889 return { end: transEndEventNames[name] } 9890 } 9891 } 9892 9893 return false // explicit for ie8 ( ._.) 9894 } 9895 9896 // http://blog.alexmaccaw.com/css-transitions 9897 $.fn.emulateTransitionEnd = function (duration) { 9898 var called = false 9899 var $el = this 9900 $(this).one('bsTransitionEnd', function () { called = true }) 9901 var callback = function () { if (!called) $($el).trigger($.support.transition.end) } 9902 setTimeout(callback, duration) 9903 return this 9904 } 9905 9906 $(function () { 9907 $.support.transition = transitionEnd() 9908 9909 if (!$.support.transition) return 9910 9911 $.event.special.bsTransitionEnd = { 9912 bindType: $.support.transition.end, 9913 delegateType: $.support.transition.end, 9914 handle: function (e) { 9915 if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments) 9916 } 9917 } 9918 }) 9919 9920}(jQuery); 9921 9922/* ======================================================================== 9923 * Bootstrap: alert.js v3.3.6 9924 * http://getbootstrap.com/javascript/#alerts 9925 * ======================================================================== 9926 * Copyright 2011-2015 Twitter, Inc. 9927 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 9928 * ======================================================================== */ 9929 9930 9931+function ($) { 9932 'use strict'; 9933 9934 // ALERT CLASS DEFINITION 9935 // ====================== 9936 9937 var dismiss = '[data-dismiss="alert"]' 9938 var Alert = function (el) { 9939 $(el).on('click', dismiss, this.close) 9940 } 9941 9942 Alert.VERSION = '3.3.6' 9943 9944 Alert.TRANSITION_DURATION = 150 9945 9946 Alert.prototype.close = function (e) { 9947 var $this = $(this) 9948 var selector = $this.attr('data-target') 9949 9950 if (!selector) { 9951 selector = $this.attr('href') 9952 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 9953 } 9954 9955 var $parent = $(selector) 9956 9957 if (e) e.preventDefault() 9958 9959 if (!$parent.length) { 9960 $parent = $this.closest('.alert') 9961 } 9962 9963 $parent.trigger(e = $.Event('close.bs.alert')) 9964 9965 if (e.isDefaultPrevented()) return 9966 9967 $parent.removeClass('in') 9968 9969 function removeElement() { 9970 // detach from parent, fire event then clean up data 9971 $parent.detach().trigger('closed.bs.alert').remove() 9972 } 9973 9974 $.support.transition && $parent.hasClass('fade') ? 9975 $parent 9976 .one('bsTransitionEnd', removeElement) 9977 .emulateTransitionEnd(Alert.TRANSITION_DURATION) : 9978 removeElement() 9979 } 9980 9981 9982 // ALERT PLUGIN DEFINITION 9983 // ======================= 9984 9985 function Plugin(option) { 9986 return this.each(function () { 9987 var $this = $(this) 9988 var data = $this.data('bs.alert') 9989
vendor: 4,197 bytes, lines 9990-10140
9990 if (!data) $this.data('bs.alert', (data = new Alert(this))) 9991 if (typeof option == 'string') data[option].call($this) 9992 }) 9993 } 9994 9995 var old = $.fn.alert 9996 9997 $.fn.alert = Plugin 9998 $.fn.alert.Constructor = Alert 9999 10000 10001 // ALERT NO CONFLICT 10002 // ================= 10003 10004 $.fn.alert.noConflict = function () { 10005 $.fn.alert = old 10006 return this 10007 } 10008 10009 10010 // ALERT DATA-API 10011 // ============== 10012 10013 $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) 10014 10015}(jQuery); 10016 10017/* ======================================================================== 10018 * Bootstrap: button.js v3.3.6 10019 * http://getbootstrap.com/javascript/#buttons 10020 * ======================================================================== 10021 * Copyright 2011-2015 Twitter, Inc. 10022 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 10023 * ======================================================================== */ 10024 10025 10026+function ($) { 10027 'use strict'; 10028 10029 // BUTTON PUBLIC CLASS DEFINITION 10030 // ============================== 10031 10032 var Button = function (element, options) { 10033 this.$element = $(element) 10034 this.options = $.extend({}, Button.DEFAULTS, options) 10035 this.isLoading = false 10036 } 10037 10038 Button.VERSION = '3.3.6' 10039 10040 Button.DEFAULTS = { 10041 loadingText: 'loading...' 10042 } 10043 10044 Button.prototype.setState = function (state) { 10045 var d = 'disabled' 10046 var $el = this.$element 10047 var val = $el.is('input') ? 'val' : 'html' 10048 var data = $el.data() 10049 10050 state += 'Text' 10051 10052 if (data.resetText == null) $el.data('resetText', $el[val]()) 10053 10054 // push to event loop to allow forms to submit 10055 setTimeout($.proxy(function () { 10056 $el[val](data[state] == null ? this.options[state] : data[state]) 10057 10058 if (state == 'loadingText') { 10059 this.isLoading = true 10060 $el.addClass(d).attr(d, d) 10061 } else if (this.isLoading) { 10062 this.isLoading = false 10063 $el.removeClass(d).removeAttr(d) 10064 } 10065 }, this), 0) 10066 } 10067 10068 Button.prototype.toggle = function () { 10069 var changed = true 10070 var $parent = this.$element.closest('[data-toggle="buttons"]') 10071 10072 if ($parent.length) { 10073 var $input = this.$element.find('input') 10074 if ($input.prop('type') == 'radio') { 10075 if ($input.prop('checked')) changed = false 10076 $parent.find('.active').removeClass('active') 10077 this.$element.addClass('active') 10078 } else if ($input.prop('type') == 'checkbox') { 10079 if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false 10080 this.$element.toggleClass('active') 10081 } 10082 $input.prop('checked', this.$element.hasClass('active')) 10083 if (changed) $input.trigger('change') 10084 } else { 10085 this.$element.attr('aria-pressed', !this.$element.hasClass('active')) 10086 this.$element.toggleClass('active') 10087 } 10088 } 10089 10090 10091 // BUTTON PLUGIN DEFINITION 10092 // ======================== 10093 10094 function Plugin(option) { 10095 return this.each(function () { 10096 var $this = $(this) 10097 var data = $this.data('bs.button') 10098 var options = typeof option == 'object' && option 10099 10100 if (!data) $this.data('bs.button', (data = new Button(this, options))) 10101 10102 if (option == 'toggle') data.toggle() 10103 else if (option) data.setState(option) 10104 }) 10105 } 10106 10107 var old = $.fn.button 10108 10109 $.fn.button = Plugin 10110 $.fn.button.Constructor = Button 10111 10112 10113 // BUTTON NO CONFLICT 10114 // ================== 10115 10116 $.fn.button.noConflict = function () { 10117 $.fn.button = old 10118 return this 10119 } 10120 10121 10122 // BUTTON DATA-API 10123 // =============== 10124 10125 $(document) 10126 .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { 10127 var $btn = $(e.target) 10128 if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') 10129 Plugin.call($btn, 'toggle') 10130 if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault() 10131 }) 10132 .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) { 10133 $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type)) 10134 }) 10135 10136}(jQuery); 10137 10138/* ======================================================================== 10139 * Bootstrap: carousel.js v3.3.6 10140 * http://getbootstrap.com/javascript/#carousel
vendor: 4,375 bytes, lines 10141-10281
10141 * ======================================================================== 10142 * Copyright 2011-2015 Twitter, Inc. 10143 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 10144 * ======================================================================== */ 10145 10146 10147+function ($) { 10148 'use strict'; 10149 10150 // CAROUSEL CLASS DEFINITION 10151 // ========================= 10152 10153 var Carousel = function (element, options) { 10154 this.$element = $(element) 10155 this.$indicators = this.$element.find('.carousel-indicators') 10156 this.options = options 10157 this.paused = null 10158 this.sliding = null 10159 this.interval = null 10160 this.$active = null 10161 this.$items = null 10162 10163 this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) 10164 10165 this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element 10166 .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) 10167 .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) 10168 } 10169 10170 Carousel.VERSION = '3.3.6' 10171 10172 Carousel.TRANSITION_DURATION = 600 10173 10174 Carousel.DEFAULTS = { 10175 interval: 5000, 10176 pause: 'hover', 10177 wrap: true, 10178 keyboard: true 10179 } 10180 10181 Carousel.prototype.keydown = function (e) { 10182 if (/input|textarea/i.test(e.target.tagName)) return 10183 switch (e.which) { 10184 case 37: this.prev(); break 10185 case 39: this.next(); break 10186 default: return 10187 } 10188 10189 e.preventDefault() 10190 } 10191 10192 Carousel.prototype.cycle = function (e) { 10193 e || (this.paused = false) 10194 10195 this.interval && clearInterval(this.interval) 10196 10197 this.options.interval 10198 && !this.paused 10199 && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) 10200 10201 return this 10202 } 10203 10204 Carousel.prototype.getItemIndex = function (item) { 10205 this.$items = item.parent().children('.item') 10206 return this.$items.index(item || this.$active) 10207 } 10208 10209 Carousel.prototype.getItemForDirection = function (direction, active) { 10210 var activeIndex = this.getItemIndex(active) 10211 var willWrap = (direction == 'prev' && activeIndex === 0) 10212 || (direction == 'next' && activeIndex == (this.$items.length - 1)) 10213 if (willWrap && !this.options.wrap) return active 10214 var delta = direction == 'prev' ? -1 : 1 10215 var itemIndex = (activeIndex + delta) % this.$items.length 10216 return this.$items.eq(itemIndex) 10217 } 10218 10219 Carousel.prototype.to = function (pos) { 10220 var that = this 10221 var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) 10222 10223 if (pos > (this.$items.length - 1) || pos < 0) return 10224 10225 if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" 10226 if (activeIndex == pos) return this.pause().cycle() 10227 10228 return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) 10229 } 10230 10231 Carousel.prototype.pause = function (e) { 10232 e || (this.paused = true) 10233 10234 if (this.$element.find('.next, .prev').length && $.support.transition) { 10235 this.$element.trigger($.support.transition.end) 10236 this.cycle(true) 10237 } 10238 10239 this.interval = clearInterval(this.interval) 10240 10241 return this 10242 } 10243 10244 Carousel.prototype.next = function () { 10245 if (this.sliding) return 10246 return this.slide('next') 10247 } 10248 10249 Carousel.prototype.prev = function () { 10250 if (this.sliding) return 10251 return this.slide('prev') 10252 } 10253 10254 Carousel.prototype.slide = function (type, next) { 10255 var $active = this.$element.find('.item.active') 10256 var $next = next || this.getItemForDirection(type, $active) 10257 var isCycling = this.interval 10258 var direction = type == 'next' ? 'left' : 'right' 10259 var that = this 10260 10261 if ($next.hasClass('active')) return (this.sliding = false) 10262 10263 var relatedTarget = $next[0] 10264 var slideEvent = $.Event('slide.bs.carousel', { 10265 relatedTarget: relatedTarget, 10266 direction: direction 10267 }) 10268 this.$element.trigger(slideEvent) 10269 if (slideEvent.isDefaultPrevented()) return 10270 10271 this.sliding = true 10272 10273 isCycling && this.pause() 10274 10275 if (this.$indicators.length) { 10276 this.$indicators.find('.active').removeClass('active') 10277 var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]) 10278 $nextIndicator && $nextIndicator.addClass('active') 10279 } 10280 10281 var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
vendor: 14,005 bytes, lines 10282-10772
10282 if ($.support.transition && this.$element.hasClass('slide')) { 10283 $next.addClass(type) 10284 $next[0].offsetWidth // force reflow 10285 $active.addClass(direction) 10286 $next.addClass(direction) 10287 $active 10288 .one('bsTransitionEnd', function () { 10289 $next.removeClass([type, direction].join(' ')).addClass('active') 10290 $active.removeClass(['active', direction].join(' ')) 10291 that.sliding = false 10292 setTimeout(function () { 10293 that.$element.trigger(slidEvent) 10294 }, 0) 10295 }) 10296 .emulateTransitionEnd(Carousel.TRANSITION_DURATION) 10297 } else { 10298 $active.removeClass('active') 10299 $next.addClass('active') 10300 this.sliding = false 10301 this.$element.trigger(slidEvent) 10302 } 10303 10304 isCycling && this.cycle() 10305 10306 return this 10307 } 10308 10309 10310 // CAROUSEL PLUGIN DEFINITION 10311 // ========================== 10312 10313 function Plugin(option) { 10314 return this.each(function () { 10315 var $this = $(this) 10316 var data = $this.data('bs.carousel') 10317 var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) 10318 var action = typeof option == 'string' ? option : options.slide 10319 10320 if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) 10321 if (typeof option == 'number') data.to(option) 10322 else if (action) data[action]() 10323 else if (options.interval) data.pause().cycle() 10324 }) 10325 } 10326 10327 var old = $.fn.carousel 10328 10329 $.fn.carousel = Plugin 10330 $.fn.carousel.Constructor = Carousel 10331 10332 10333 // CAROUSEL NO CONFLICT 10334 // ==================== 10335 10336 $.fn.carousel.noConflict = function () { 10337 $.fn.carousel = old 10338 return this 10339 } 10340 10341 10342 // CAROUSEL DATA-API 10343 // ================= 10344 10345 var clickHandler = function (e) { 10346 var href 10347 var $this = $(this) 10348 var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 10349 if (!$target.hasClass('carousel')) return 10350 var options = $.extend({}, $target.data(), $this.data()) 10351 var slideIndex = $this.attr('data-slide-to') 10352 if (slideIndex) options.interval = false 10353 10354 Plugin.call($target, options) 10355 10356 if (slideIndex) { 10357 $target.data('bs.carousel').to(slideIndex) 10358 } 10359 10360 e.preventDefault() 10361 } 10362 10363 $(document) 10364 .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) 10365 .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler) 10366 10367 $(window).on('load', function () { 10368 $('[data-ride="carousel"]').each(function () { 10369 var $carousel = $(this) 10370 Plugin.call($carousel, $carousel.data()) 10371 }) 10372 }) 10373 10374}(jQuery); 10375 10376/* ======================================================================== 10377 * Bootstrap: collapse.js v3.3.6 10378 * http://getbootstrap.com/javascript/#collapse 10379 * ======================================================================== 10380 * Copyright 2011-2015 Twitter, Inc. 10381 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 10382 * ======================================================================== */ 10383 10384 10385+function ($) { 10386 'use strict'; 10387 10388 // COLLAPSE PUBLIC CLASS DEFINITION 10389 // ================================ 10390 10391 var Collapse = function (element, options) { 10392 this.$element = $(element) 10393 this.options = $.extend({}, Collapse.DEFAULTS, options) 10394 this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' + 10395 '[data-toggle="collapse"][data-target="#' + element.id + '"]') 10396 this.transitioning = null 10397 10398 if (this.options.parent) { 10399 this.$parent = this.getParent() 10400 } else { 10401 this.addAriaAndCollapsedClass(this.$element, this.$trigger) 10402 } 10403 10404 if (this.options.toggle) this.toggle() 10405 } 10406 10407 Collapse.VERSION = '3.3.6' 10408 10409 Collapse.TRANSITION_DURATION = 350 10410 10411 Collapse.DEFAULTS = { 10412 toggle: true 10413 } 10414 10415 Collapse.prototype.dimension = function () { 10416 var hasWidth = this.$element.hasClass('width') 10417 return hasWidth ? 'width' : 'height' 10418 } 10419 10420 Collapse.prototype.show = function () { 10421 if (this.transitioning || this.$element.hasClass('in')) return 10422 10423 var activesData 10424 var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing') 10425 10426 if (actives && actives.length) { 10427 activesData = actives.data('bs.collapse') 10428 if (activesData && activesData.transitioning) return 10429 } 10430 10431 var startEvent = $.Event('show.bs.collapse') 10432 this.$element.trigger(startEvent) 10433 if (startEvent.isDefaultPrevented()) return 10434 10435 if (actives && actives.length) { 10436 Plugin.call(actives, 'hide') 10437 activesData || actives.data('bs.collapse', null) 10438 } 10439 10440 var dimension = this.dimension() 10441 10442 this.$element 10443 .removeClass('collapse') 10444 .addClass('collapsing')[dimension](0) 10445 .attr('aria-expanded', true) 10446 10447 this.$trigger 10448 .removeClass('collapsed') 10449 .attr('aria-expanded', true) 10450 10451 this.transitioning = 1 10452 10453 var complete = function () { 10454 this.$element 10455 .removeClass('collapsing') 10456 .addClass('collapse in')[dimension]('') 10457 this.transitioning = 0 10458 this.$element 10459 .trigger('shown.bs.collapse') 10460 } 10461 10462 if (!$.support.transition) return complete.call(this) 10463 10464 var scrollSize = $.camelCase(['scroll', dimension].join('-')) 10465 10466 this.$element 10467 .one('bsTransitionEnd', $.proxy(complete, this)) 10468 .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) 10469 } 10470 10471 Collapse.prototype.hide = function () { 10472 if (this.transitioning || !this.$element.hasClass('in')) return 10473 10474 var startEvent = $.Event('hide.bs.collapse') 10475 this.$element.trigger(startEvent) 10476 if (startEvent.isDefaultPrevented()) return 10477 10478 var dimension = this.dimension() 10479 10480 this.$element[dimension](this.$element[dimension]())[0].offsetHeight 10481 10482 this.$element 10483 .addClass('collapsing') 10484 .removeClass('collapse in') 10485 .attr('aria-expanded', false) 10486 10487 this.$trigger 10488 .addClass('collapsed') 10489 .attr('aria-expanded', false) 10490 10491 this.transitioning = 1 10492 10493 var complete = function () { 10494 this.transitioning = 0 10495 this.$element 10496 .removeClass('collapsing') 10497 .addClass('collapse') 10498 .trigger('hidden.bs.collapse') 10499 } 10500 10501 if (!$.support.transition) return complete.call(this) 10502 10503 this.$element 10504 [dimension](0) 10505 .one('bsTransitionEnd', $.proxy(complete, this)) 10506 .emulateTransitionEnd(Collapse.TRANSITION_DURATION) 10507 } 10508 10509 Collapse.prototype.toggle = function () { 10510 this[this.$element.hasClass('in') ? 'hide' : 'show']() 10511 } 10512 10513 Collapse.prototype.getParent = function () { 10514 return $(this.options.parent) 10515 .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') 10516 .each($.proxy(function (i, element) { 10517 var $element = $(element) 10518 this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element) 10519 }, this)) 10520 .end() 10521 } 10522 10523 Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { 10524 var isOpen = $element.hasClass('in') 10525 10526 $element.attr('aria-expanded', isOpen) 10527 $trigger 10528 .toggleClass('collapsed', !isOpen) 10529 .attr('aria-expanded', isOpen) 10530 } 10531 10532 function getTargetFromTrigger($trigger) { 10533 var href 10534 var target = $trigger.attr('data-target') 10535 || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 10536 10537 return $(target) 10538 } 10539 10540 10541 // COLLAPSE PLUGIN DEFINITION 10542 // ========================== 10543 10544 function Plugin(option) { 10545 return this.each(function () { 10546 var $this = $(this) 10547 var data = $this.data('bs.collapse') 10548 var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) 10549 10550 if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false 10551 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) 10552 if (typeof option == 'string') data[option]() 10553 }) 10554 } 10555 10556 var old = $.fn.collapse 10557 10558 $.fn.collapse = Plugin 10559 $.fn.collapse.Constructor = Collapse 10560 10561 10562 // COLLAPSE NO CONFLICT 10563 // ==================== 10564 10565 $.fn.collapse.noConflict = function () { 10566 $.fn.collapse = old 10567 return this 10568 } 10569 10570 10571 // COLLAPSE DATA-API 10572 // ================= 10573 10574 $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { 10575 var $this = $(this) 10576 10577 if (!$this.attr('data-target')) e.preventDefault() 10578 10579 var $target = getTargetFromTrigger($this) 10580 var data = $target.data('bs.collapse') 10581 var option = data ? 'toggle' : $this.data() 10582 10583 Plugin.call($target, option) 10584 }) 10585 10586}(jQuery); 10587 10588/* ======================================================================== 10589 * Bootstrap: dropdown.js v3.3.6 10590 * http://getbootstrap.com/javascript/#dropdowns 10591 * ======================================================================== 10592 * Copyright 2011-2015 Twitter, Inc. 10593 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 10594 * ======================================================================== */ 10595 10596 10597+function ($) { 10598 'use strict'; 10599 10600 // DROPDOWN CLASS DEFINITION 10601 // ========================= 10602 10603 var backdrop = '.dropdown-backdrop' 10604 var toggle = '[data-toggle="dropdown"]' 10605 var Dropdown = function (element) { 10606 $(element).on('click.bs.dropdown', this.toggle) 10607 } 10608 10609 Dropdown.VERSION = '3.3.6' 10610 10611 function getParent($this) { 10612 var selector = $this.attr('data-target') 10613 10614 if (!selector) { 10615 selector = $this.attr('href') 10616 selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 10617 } 10618 10619 var $parent = selector && $(selector) 10620 10621 return $parent && $parent.length ? $parent : $this.parent() 10622 } 10623 10624 function clearMenus(e) { 10625 if (e && e.which === 3) return 10626 $(backdrop).remove() 10627 $(toggle).each(function () { 10628 var $this = $(this) 10629 var $parent = getParent($this) 10630 var relatedTarget = { relatedTarget: this } 10631 10632 if (!$parent.hasClass('open')) return 10633 10634 if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return 10635 10636 $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) 10637 10638 if (e.isDefaultPrevented()) return 10639 10640 $this.attr('aria-expanded', 'false') 10641 $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget)) 10642 }) 10643 } 10644 10645 Dropdown.prototype.toggle = function (e) { 10646 var $this = $(this) 10647 10648 if ($this.is('.disabled, :disabled')) return 10649 10650 var $parent = getParent($this) 10651 var isActive = $parent.hasClass('open') 10652 10653 clearMenus() 10654 10655 if (!isActive) { 10656 if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { 10657 // if mobile we use a backdrop because click events don't delegate 10658 $(document.createElement('div')) 10659 .addClass('dropdown-backdrop') 10660 .insertAfter($(this)) 10661 .on('click', clearMenus) 10662 } 10663 10664 var relatedTarget = { relatedTarget: this } 10665 $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) 10666 10667 if (e.isDefaultPrevented()) return 10668 10669 $this 10670 .trigger('focus') 10671 .attr('aria-expanded', 'true') 10672 10673 $parent 10674 .toggleClass('open') 10675 .trigger($.Event('shown.bs.dropdown', relatedTarget)) 10676 } 10677 10678 return false 10679 } 10680 10681 Dropdown.prototype.keydown = function (e) { 10682 if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return 10683 10684 var $this = $(this) 10685 10686 e.preventDefault() 10687 e.stopPropagation() 10688 10689 if ($this.is('.disabled, :disabled')) return 10690 10691 var $parent = getParent($this) 10692 var isActive = $parent.hasClass('open') 10693 10694 if (!isActive && e.which != 27 || isActive && e.which == 27) { 10695 if (e.which == 27) $parent.find(toggle).trigger('focus') 10696 return $this.trigger('click') 10697 } 10698 10699 var desc = ' li:not(.disabled):visible a' 10700 var $items = $parent.find('.dropdown-menu' + desc) 10701 10702 if (!$items.length) return 10703 10704 var index = $items.index(e.target) 10705 10706 if (e.which == 38 && index > 0) index-- // up 10707 if (e.which == 40 && index < $items.length - 1) index++ // down 10708 if (!~index) index = 0 10709 10710 $items.eq(index).trigger('focus') 10711 } 10712 10713 10714 // DROPDOWN PLUGIN DEFINITION 10715 // ========================== 10716 10717 function Plugin(option) { 10718 return this.each(function () { 10719 var $this = $(this) 10720 var data = $this.data('bs.dropdown') 10721 10722 if (!data) $this.data('bs.dropdown', (data = new Dropdown(this))) 10723 if (typeof option == 'string') data[option].call($this) 10724 }) 10725 } 10726 10727 var old = $.fn.dropdown 10728 10729 $.fn.dropdown = Plugin 10730 $.fn.dropdown.Constructor = Dropdown 10731 10732 10733 // DROPDOWN NO CONFLICT 10734 // ==================== 10735 10736 $.fn.dropdown.noConflict = function () { 10737 $.fn.dropdown = old 10738 return this 10739 } 10740 10741 10742 // APPLY TO STANDARD DROPDOWN ELEMENTS 10743 // =================================== 10744 10745 $(document) 10746 .on('click.bs.dropdown.data-api', clearMenus) 10747 .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) 10748 .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) 10749 .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) 10750 .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown) 10751 10752}(jQuery); 10753 10754/* ======================================================================== 10755 * Bootstrap: modal.js v3.3.6 10756 * http://getbootstrap.com/javascript/#modals 10757 * ======================================================================== 10758 * Copyright 2011-2015 Twitter, Inc. 10759 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 10760 * ======================================================================== */ 10761 10762 10763+function ($) { 10764 'use strict'; 10765 10766 // MODAL CLASS DEFINITION 10767 // ====================== 10768 10769 var Modal = function (element, options) { 10770 this.options = options 10771 this.$body = $(document.body) 10772 this.$element = $(element)
vendor: 10,154 bytes, lines 10773-11120
10773 this.$dialog = this.$element.find('.modal-dialog') 10774 this.$backdrop = null 10775 this.isShown = null 10776 this.originalBodyPad = null 10777 this.scrollbarWidth = 0 10778 this.ignoreBackdropClick = false 10779 10780 if (this.options.remote) { 10781 this.$element 10782 .find('.modal-content') 10783 .load(this.options.remote, $.proxy(function () { 10784 this.$element.trigger('loaded.bs.modal') 10785 }, this)) 10786 } 10787 } 10788 10789 Modal.VERSION = '3.3.6' 10790 10791 Modal.TRANSITION_DURATION = 300 10792 Modal.BACKDROP_TRANSITION_DURATION = 150 10793 10794 Modal.DEFAULTS = { 10795 backdrop: true, 10796 keyboard: true, 10797 show: true 10798 } 10799 10800 Modal.prototype.toggle = function (_relatedTarget) { 10801 return this.isShown ? this.hide() : this.show(_relatedTarget) 10802 } 10803 10804 Modal.prototype.show = function (_relatedTarget) { 10805 var that = this 10806 var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget }) 10807 10808 this.$element.trigger(e) 10809 10810 if (this.isShown || e.isDefaultPrevented()) return 10811 10812 this.isShown = true 10813 10814 this.checkScrollbar() 10815 this.setScrollbar() 10816 this.$body.addClass('modal-open') 10817 10818 this.escape() 10819 this.resize() 10820 10821 this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) 10822 10823 this.$dialog.on('mousedown.dismiss.bs.modal', function () { 10824 that.$element.one('mouseup.dismiss.bs.modal', function (e) { 10825 if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true 10826 }) 10827 }) 10828 10829 this.backdrop(function () { 10830 var transition = $.support.transition && that.$element.hasClass('fade') 10831 10832 if (!that.$element.parent().length) { 10833 that.$element.appendTo(that.$body) // don't move modals dom position 10834 } 10835 10836 that.$element 10837 .show() 10838 .scrollTop(0) 10839 10840 that.adjustDialog() 10841 10842 if (transition) { 10843 that.$element[0].offsetWidth // force reflow 10844 } 10845 10846 that.$element.addClass('in') 10847 10848 that.enforceFocus() 10849 10850 var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) 10851 10852 transition ? 10853 that.$dialog // wait for modal to slide in 10854 .one('bsTransitionEnd', function () { 10855 that.$element.trigger('focus').trigger(e) 10856 }) 10857 .emulateTransitionEnd(Modal.TRANSITION_DURATION) : 10858 that.$element.trigger('focus').trigger(e) 10859 }) 10860 } 10861 10862 Modal.prototype.hide = function (e) { 10863 if (e) e.preventDefault() 10864 10865 e = $.Event('hide.bs.modal') 10866 10867 this.$element.trigger(e) 10868 10869 if (!this.isShown || e.isDefaultPrevented()) return 10870 10871 this.isShown = false 10872 10873 this.escape() 10874 this.resize() 10875 10876 $(document).off('focusin.bs.modal') 10877 10878 this.$element 10879 .removeClass('in') 10880 .off('click.dismiss.bs.modal') 10881 .off('mouseup.dismiss.bs.modal') 10882 10883 this.$dialog.off('mousedown.dismiss.bs.modal') 10884 10885 $.support.transition && this.$element.hasClass('fade') ? 10886 this.$element 10887 .one('bsTransitionEnd', $.proxy(this.hideModal, this)) 10888 .emulateTransitionEnd(Modal.TRANSITION_DURATION) : 10889 this.hideModal() 10890 } 10891 10892 Modal.prototype.enforceFocus = function () { 10893 $(document) 10894 .off('focusin.bs.modal') // guard against infinite focus loop 10895 .on('focusin.bs.modal', $.proxy(function (e) { 10896 if (this.$element[0] !== e.target && !this.$element.has(e.target).length) { 10897 this.$element.trigger('focus') 10898 } 10899 }, this)) 10900 } 10901 10902 Modal.prototype.escape = function () { 10903 if (this.isShown && this.options.keyboard) { 10904 this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) { 10905 e.which == 27 && this.hide() 10906 }, this)) 10907 } else if (!this.isShown) { 10908 this.$element.off('keydown.dismiss.bs.modal') 10909 } 10910 } 10911 10912 Modal.prototype.resize = function () { 10913 if (this.isShown) { 10914 $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this)) 10915 } else { 10916 $(window).off('resize.bs.modal') 10917 } 10918 } 10919 10920 Modal.prototype.hideModal = function () { 10921 var that = this 10922 this.$element.hide() 10923 this.backdrop(function () { 10924 that.$body.removeClass('modal-open') 10925 that.resetAdjustments() 10926 that.resetScrollbar() 10927 that.$element.trigger('hidden.bs.modal') 10928 }) 10929 } 10930 10931 Modal.prototype.removeBackdrop = function () { 10932 this.$backdrop && this.$backdrop.remove() 10933 this.$backdrop = null 10934 } 10935 10936 Modal.prototype.backdrop = function (callback) { 10937 var that = this 10938 var animate = this.$element.hasClass('fade') ? 'fade' : '' 10939 10940 if (this.isShown && this.options.backdrop) { 10941 var doAnimate = $.support.transition && animate 10942 10943 this.$backdrop = $(document.createElement('div')) 10944 .addClass('modal-backdrop ' + animate) 10945 .appendTo(this.$body) 10946 10947 this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { 10948 if (this.ignoreBackdropClick) { 10949 this.ignoreBackdropClick = false 10950 return 10951 } 10952 if (e.target !== e.currentTarget) return 10953 this.options.backdrop == 'static' 10954 ? this.$element[0].focus() 10955 : this.hide() 10956 }, this)) 10957 10958 if (doAnimate) this.$backdrop[0].offsetWidth // force reflow 10959 10960 this.$backdrop.addClass('in') 10961 10962 if (!callback) return 10963 10964 doAnimate ? 10965 this.$backdrop 10966 .one('bsTransitionEnd', callback) 10967 .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : 10968 callback() 10969 10970 } else if (!this.isShown && this.$backdrop) { 10971 this.$backdrop.removeClass('in') 10972 10973 var callbackRemove = function () { 10974 that.removeBackdrop() 10975 callback && callback() 10976 } 10977 $.support.transition && this.$element.hasClass('fade') ? 10978 this.$backdrop 10979 .one('bsTransitionEnd', callbackRemove) 10980 .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : 10981 callbackRemove() 10982 10983 } else if (callback) { 10984 callback() 10985 } 10986 } 10987 10988 // these following methods are used to handle overflowing modals 10989 10990 Modal.prototype.handleUpdate = function () { 10991 this.adjustDialog() 10992 } 10993 10994 Modal.prototype.adjustDialog = function () { 10995 var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight 10996 10997 this.$element.css({ 10998 paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '', 10999 paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : '' 11000 }) 11001 } 11002 11003 Modal.prototype.resetAdjustments = function () { 11004 this.$element.css({ 11005 paddingLeft: '', 11006 paddingRight: '' 11007 }) 11008 } 11009 11010 Modal.prototype.checkScrollbar = function () { 11011 var fullWindowWidth = window.innerWidth 11012 if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8 11013 var documentElementRect = document.documentElement.getBoundingClientRect() 11014 fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left) 11015 } 11016 this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth 11017 this.scrollbarWidth = this.measureScrollbar() 11018 } 11019 11020 Modal.prototype.setScrollbar = function () { 11021 var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) 11022 this.originalBodyPad = document.body.style.paddingRight || '' 11023 if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth) 11024 } 11025 11026 Modal.prototype.resetScrollbar = function () { 11027 this.$body.css('padding-right', this.originalBodyPad) 11028 } 11029 11030 Modal.prototype.measureScrollbar = function () { // thx walsh 11031 var scrollDiv = document.createElement('div') 11032 scrollDiv.className = 'modal-scrollbar-measure' 11033 this.$body.append(scrollDiv) 11034 var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth 11035 this.$body[0].removeChild(scrollDiv) 11036 return scrollbarWidth 11037 } 11038 11039 11040 // MODAL PLUGIN DEFINITION 11041 // ======================= 11042 11043 function Plugin(option, _relatedTarget) { 11044 return this.each(function () { 11045 var $this = $(this) 11046 var data = $this.data('bs.modal') 11047 var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) 11048 11049 if (!data) $this.data('bs.modal', (data = new Modal(this, options))) 11050 if (typeof option == 'string') data[option](_relatedTarget) 11051 else if (options.show) data.show(_relatedTarget) 11052 }) 11053 } 11054 11055 var old = $.fn.modal 11056 11057 $.fn.modal = Plugin 11058 $.fn.modal.Constructor = Modal 11059 11060 11061 // MODAL NO CONFLICT 11062 // ================= 11063 11064 $.fn.modal.noConflict = function () { 11065 $.fn.modal = old 11066 return this 11067 } 11068 11069 11070 // MODAL DATA-API 11071 // ============== 11072 11073 $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { 11074 var $this = $(this) 11075 var href = $this.attr('href') 11076 var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7 11077 var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) 11078 11079 if ($this.is('a')) e.preventDefault() 11080 11081 $target.one('show.bs.modal', function (showEvent) { 11082 if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown 11083 $target.one('hidden.bs.modal', function () { 11084 $this.is(':visible') && $this.trigger('focus') 11085 }) 11086 }) 11087 Plugin.call($target, option, this) 11088 }) 11089 11090}(jQuery); 11091 11092/* ======================================================================== 11093 * Bootstrap: tooltip.js v3.3.6 11094 * http://getbootstrap.com/javascript/#tooltip 11095 * Inspired by the original jQuery.tipsy by Jason Frame 11096 * ======================================================================== 11097 * Copyright 2011-2015 Twitter, Inc. 11098 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 11099 * ======================================================================== */ 11100 11101 11102+function ($) { 11103 'use strict'; 11104 11105 // TOOLTIP PUBLIC CLASS DEFINITION 11106 // =============================== 11107 11108 var Tooltip = function (element, options) { 11109 this.type = null 11110 this.options = null 11111 this.enabled = null 11112 this.timeout = null 11113 this.hoverState = null 11114 this.$element = null 11115 this.inState = null 11116 11117 this.init('tooltip', element, options) 11118 } 11119 11120 Tooltip.VERSION = '3.3.6
vendor: 15,550 bytes, lines 11120-11608
11120' 11121 11122 Tooltip.TRANSITION_DURATION = 150 11123 11124 Tooltip.DEFAULTS = { 11125 animation: true, 11126 placement: 'top', 11127 selector: false, 11128 template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', 11129 trigger: 'hover focus', 11130 title: '', 11131 delay: 0, 11132 html: false, 11133 container: false, 11134 viewport: { 11135 selector: 'body', 11136 padding: 0 11137 } 11138 } 11139 11140 Tooltip.prototype.init = function (type, element, options) { 11141 this.enabled = true 11142 this.type = type 11143 this.$element = $(element) 11144 this.options = this.getOptions(options) 11145 this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport)) 11146 this.inState = { click: false, hover: false, focus: false } 11147 11148 if (this.$element[0] instanceof document.constructor && !this.options.selector) { 11149 throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!') 11150 } 11151 11152 var triggers = this.options.trigger.split(' ') 11153 11154 for (var i = triggers.length; i--;) { 11155 var trigger = triggers[i] 11156 11157 if (trigger == 'click') { 11158 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) 11159 } else if (trigger != 'manual') { 11160 var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' 11161 var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' 11162 11163 this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) 11164 this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) 11165 } 11166 } 11167 11168 this.options.selector ? 11169 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : 11170 this.fixTitle() 11171 } 11172 11173 Tooltip.prototype.getDefaults = function () { 11174 return Tooltip.DEFAULTS 11175 } 11176 11177 Tooltip.prototype.getOptions = function (options) { 11178 options = $.extend({}, this.getDefaults(), this.$element.data(), options) 11179 11180 if (options.delay && typeof options.delay == 'number') { 11181 options.delay = { 11182 show: options.delay, 11183 hide: options.delay 11184 } 11185 } 11186 11187 return options 11188 } 11189 11190 Tooltip.prototype.getDelegateOptions = function () { 11191 var options = {} 11192 var defaults = this.getDefaults() 11193 11194 this._options && $.each(this._options, function (key, value) { 11195 if (defaults[key] != value) options[key] = value 11196 }) 11197 11198 return options 11199 } 11200 11201 Tooltip.prototype.enter = function (obj) { 11202 var self = obj instanceof this.constructor ? 11203 obj : $(obj.currentTarget).data('bs.' + this.type) 11204 11205 if (!self) { 11206 self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) 11207 $(obj.currentTarget).data('bs.' + this.type, self) 11208 } 11209 11210 if (obj instanceof $.Event) { 11211 self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true 11212 } 11213 11214 if (self.tip().hasClass('in') || self.hoverState == 'in') { 11215 self.hoverState = 'in' 11216 return 11217 } 11218 11219 clearTimeout(self.timeout) 11220 11221 self.hoverState = 'in' 11222 11223 if (!self.options.delay || !self.options.delay.show) return self.show() 11224 11225 self.timeout = setTimeout(function () { 11226 if (self.hoverState == 'in') self.show() 11227 }, self.options.delay.show) 11228 } 11229 11230 Tooltip.prototype.isInStateTrue = function () { 11231 for (var key in this.inState) { 11232 if (this.inState[key]) return true 11233 } 11234 11235 return false 11236 } 11237 11238 Tooltip.prototype.leave = function (obj) { 11239 var self = obj instanceof this.constructor ? 11240 obj : $(obj.currentTarget).data('bs.' + this.type) 11241 11242 if (!self) { 11243 self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) 11244 $(obj.currentTarget).data('bs.' + this.type, self) 11245 } 11246 11247 if (obj instanceof $.Event) { 11248 self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false 11249 } 11250 11251 if (self.isInStateTrue()) return 11252 11253 clearTimeout(self.timeout) 11254 11255 self.hoverState = 'out' 11256 11257 if (!self.options.delay || !self.options.delay.hide) return self.hide() 11258 11259 self.timeout = setTimeout(function () { 11260 if (self.hoverState == 'out') self.hide() 11261 }, self.options.delay.hide) 11262 } 11263 11264 Tooltip.prototype.show = function () { 11265 var e = $.Event('show.bs.' + this.type) 11266 11267 if (this.hasContent() && this.enabled) { 11268 this.$element.trigger(e) 11269 11270 var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]) 11271 if (e.isDefaultPrevented() || !inDom) return 11272 var that = this 11273 11274 var $tip = this.tip() 11275 11276 var tipId = this.getUID(this.type) 11277 11278 this.setContent() 11279 $tip.attr('id', tipId) 11280 this.$element.attr('aria-describedby', tipId) 11281 11282 if (this.options.animation) $tip.addClass('fade') 11283 11284 var placement = typeof this.options.placement == 'function' ? 11285 this.options.placement.call(this, $tip[0], this.$element[0]) : 11286 this.options.placement 11287 11288 var autoToken = /\s?auto?\s?/i 11289 var autoPlace = autoToken.test(placement) 11290 if (autoPlace) placement = placement.replace(autoToken, '') || 'top' 11291 11292 $tip 11293 .detach() 11294 .css({ top: 0, left: 0, display: 'block' }) 11295 .addClass(placement) 11296 .data('bs.' + this.type, this) 11297 11298 this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) 11299 this.$element.trigger('inserted.bs.' + this.type) 11300 11301 var pos = this.getPosition() 11302 var actualWidth = $tip[0].offsetWidth 11303 var actualHeight = $tip[0].offsetHeight 11304 11305 if (autoPlace) { 11306 var orgPlacement = placement 11307 var viewportDim = this.getPosition(this.$viewport) 11308 11309 placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' : 11310 placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' : 11311 placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' : 11312 placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' : 11313 placement 11314 11315 $tip 11316 .removeClass(orgPlacement) 11317 .addClass(placement) 11318 } 11319 11320 var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) 11321 11322 this.applyPlacement(calculatedOffset, placement) 11323 11324 var complete = function () { 11325 var prevHoverState = that.hoverState 11326 that.$element.trigger('shown.bs.' + that.type) 11327 that.hoverState = null 11328 11329 if (prevHoverState == 'out') that.leave(that) 11330 } 11331 11332 $.support.transition && this.$tip.hasClass('fade') ? 11333 $tip 11334 .one('bsTransitionEnd', complete) 11335 .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : 11336 complete() 11337 } 11338 } 11339 11340 Tooltip.prototype.applyPlacement = function (offset, placement) { 11341 var $tip = this.tip() 11342 var width = $tip[0].offsetWidth 11343 var height = $tip[0].offsetHeight 11344 11345 // manually read margins because getBoundingClientRect includes difference 11346 var marginTop = parseInt($tip.css('margin-top'), 10) 11347 var marginLeft = parseInt($tip.css('margin-left'), 10) 11348 11349 // we must check for NaN for ie 8/9 11350 if (isNaN(marginTop)) marginTop = 0 11351 if (isNaN(marginLeft)) marginLeft = 0 11352 11353 offset.top += marginTop 11354 offset.left += marginLeft 11355 11356 // $.fn.offset doesn't round pixel values 11357 // so we use setOffset directly with our own function B-0 11358 $.offset.setOffset($tip[0], $.extend({ 11359 using: function (props) { 11360 $tip.css({ 11361 top: Math.round(props.top), 11362 left: Math.round(props.left) 11363 }) 11364 } 11365 }, offset), 0) 11366 11367 $tip.addClass('in') 11368 11369 // check to see if placing tip in new offset caused the tip to resize itself 11370 var actualWidth = $tip[0].offsetWidth 11371 var actualHeight = $tip[0].offsetHeight 11372 11373 if (placement == 'top' && actualHeight != height) { 11374 offset.top = offset.top + height - actualHeight 11375 } 11376 11377 var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) 11378 11379 if (delta.left) offset.left += delta.left 11380 else offset.top += delta.top 11381 11382 var isVertical = /top|bottom/.test(placement) 11383 var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight 11384 var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight' 11385 11386 $tip.offset(offset) 11387 this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical) 11388 } 11389 11390 Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) { 11391 this.arrow() 11392 .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%') 11393 .css(isVertical ? 'top' : 'left', '') 11394 } 11395 11396 Tooltip.prototype.setContent = function () { 11397 var $tip = this.tip() 11398 var title = this.getTitle() 11399 11400 $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) 11401 $tip.removeClass('fade in top bottom left right') 11402 } 11403 11404 Tooltip.prototype.hide = function (callback) { 11405 var that = this 11406 var $tip = $(this.$tip) 11407 var e = $.Event('hide.bs.' + this.type) 11408 11409 function complete() { 11410 if (that.hoverState != 'in') $tip.detach() 11411 that.$element 11412 .removeAttr('aria-describedby') 11413 .trigger('hidden.bs.' + that.type) 11414 callback && callback() 11415 } 11416 11417 this.$element.trigger(e) 11418 11419 if (e.isDefaultPrevented()) return 11420 11421 $tip.removeClass('in') 11422 11423 $.support.transition && $tip.hasClass('fade') ? 11424 $tip 11425 .one('bsTransitionEnd', complete) 11426 .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : 11427 complete() 11428 11429 this.hoverState = null 11430 11431 return this 11432 } 11433 11434 Tooltip.prototype.fixTitle = function () { 11435 var $e = this.$element 11436 if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') { 11437 $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') 11438 } 11439 } 11440 11441 Tooltip.prototype.hasContent = function () { 11442 return this.getTitle() 11443 } 11444 11445 Tooltip.prototype.getPosition = function ($element) { 11446 $element = $element || this.$element 11447 11448 var el = $element[0] 11449 var isBody = el.tagName == 'BODY' 11450 11451 var elRect = el.getBoundingClientRect() 11452 if (elRect.width == null) { 11453 // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093 11454 elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top }) 11455 } 11456 var elOffset = isBody ? { top: 0, left: 0 } : $element.offset() 11457 var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() } 11458 var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null 11459 11460 return $.extend({}, elRect, scroll, outerDims, elOffset) 11461 } 11462 11463 Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { 11464 return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : 11465 placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : 11466 placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : 11467 /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } 11468 11469 } 11470 11471 Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { 11472 var delta = { top: 0, left: 0 } 11473 if (!this.$viewport) return delta 11474 11475 var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 11476 var viewportDimensions = this.getPosition(this.$viewport) 11477 11478 if (/right|left/.test(placement)) { 11479 var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll 11480 var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight 11481 if (topEdgeOffset < viewportDimensions.top) { // top overflow 11482 delta.top = viewportDimensions.top - topEdgeOffset 11483 } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow 11484 delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset 11485 } 11486 } else { 11487 var leftEdgeOffset = pos.left - viewportPadding 11488 var rightEdgeOffset = pos.left + viewportPadding + actualWidth 11489 if (leftEdgeOffset < viewportDimensions.left) { // left overflow 11490 delta.left = viewportDimensions.left - leftEdgeOffset 11491 } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow 11492 delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset 11493 } 11494 } 11495 11496 return delta 11497 } 11498 11499 Tooltip.prototype.getTitle = function () { 11500 var title 11501 var $e = this.$element 11502 var o = this.options 11503 11504 title = $e.attr('data-original-title') 11505 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) 11506 11507 return title 11508 } 11509 11510 Tooltip.prototype.getUID = function (prefix) { 11511 do prefix += ~~(Math.random() * 1000000) 11512 while (document.getElementById(prefix)) 11513 return prefix 11514 } 11515 11516 Tooltip.prototype.tip = function () { 11517 if (!this.$tip) { 11518 this.$tip = $(this.options.template) 11519 if (this.$tip.length != 1) { 11520 throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!') 11521 } 11522 } 11523 return this.$tip 11524 } 11525 11526 Tooltip.prototype.arrow = function () { 11527 return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')) 11528 } 11529 11530 Tooltip.prototype.enable = function () { 11531 this.enabled = true 11532 } 11533 11534 Tooltip.prototype.disable = function () { 11535 this.enabled = false 11536 } 11537 11538 Tooltip.prototype.toggleEnabled = function () { 11539 this.enabled = !this.enabled 11540 } 11541 11542 Tooltip.prototype.toggle = function (e) { 11543 var self = this 11544 if (e) { 11545 self = $(e.currentTarget).data('bs.' + this.type) 11546 if (!self) { 11547 self = new this.constructor(e.currentTarget, this.getDelegateOptions()) 11548 $(e.currentTarget).data('bs.' + this.type, self) 11549 } 11550 } 11551 11552 if (e) { 11553 self.inState.click = !self.inState.click 11554 if (self.isInStateTrue()) self.enter(self) 11555 else self.leave(self) 11556 } else { 11557 self.tip().hasClass('in') ? self.leave(self) : self.enter(self) 11558 } 11559 } 11560 11561 Tooltip.prototype.destroy = function () { 11562 var that = this 11563 clearTimeout(this.timeout) 11564 this.hide(function () { 11565 that.$element.off('.' + that.type).removeData('bs.' + that.type) 11566 if (that.$tip) { 11567 that.$tip.detach() 11568 } 11569 that.$tip = null 11570 that.$arrow = null 11571 that.$viewport = null 11572 }) 11573 } 11574 11575 11576 // TOOLTIP PLUGIN DEFINITION 11577 // ========================= 11578 11579 function Plugin(option) { 11580 return this.each(function () { 11581 var $this = $(this) 11582 var data = $this.data('bs.tooltip') 11583 var options = typeof option == 'object' && option 11584 11585 if (!data && /destroy|hide/.test(option)) return 11586 if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) 11587 if (typeof option == 'string') data[option]() 11588 }) 11589 } 11590 11591 var old = $.fn.tooltip 11592 11593 $.fn.tooltip = Plugin 11594 $.fn.tooltip.Constructor = Tooltip 11595 11596 11597 // TOOLTIP NO CONFLICT 11598 // =================== 11599 11600 $.fn.tooltip.noConflict = function () { 11601 $.fn.tooltip = old 11602 return this 11603 } 11604 11605}(jQuery); 11606 11607/* ======================================================================== 11608 * Bootstrap: popover.js v3.3.
vendor: 14,729 bytes, lines 11608-12130
116086 11609 * http://getbootstrap.com/javascript/#popovers 11610 * ======================================================================== 11611 * Copyright 2011-2015 Twitter, Inc. 11612 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 11613 * ======================================================================== */ 11614 11615 11616+function ($) { 11617 'use strict'; 11618 11619 // POPOVER PUBLIC CLASS DEFINITION 11620 // =============================== 11621 11622 var Popover = function (element, options) { 11623 this.init('popover', element, options) 11624 } 11625 11626 if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') 11627 11628 Popover.VERSION = '3.3.6' 11629 11630 Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { 11631 placement: 'right', 11632 trigger: 'click', 11633 content: '', 11634 template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>' 11635 }) 11636 11637 11638 // NOTE: POPOVER EXTENDS tooltip.js 11639 // ================================ 11640 11641 Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype) 11642 11643 Popover.prototype.constructor = Popover 11644 11645 Popover.prototype.getDefaults = function () { 11646 return Popover.DEFAULTS 11647 } 11648 11649 Popover.prototype.setContent = function () { 11650 var $tip = this.tip() 11651 var title = this.getTitle() 11652 var content = this.getContent() 11653 11654 $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title) 11655 $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events 11656 this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text' 11657 ](content) 11658 11659 $tip.removeClass('fade top bottom left right in') 11660 11661 // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do 11662 // this manually by checking the contents. 11663 if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide() 11664 } 11665 11666 Popover.prototype.hasContent = function () { 11667 return this.getTitle() || this.getContent() 11668 } 11669 11670 Popover.prototype.getContent = function () { 11671 var $e = this.$element 11672 var o = this.options 11673 11674 return $e.attr('data-content') 11675 || (typeof o.content == 'function' ? 11676 o.content.call($e[0]) : 11677 o.content) 11678 } 11679 11680 Popover.prototype.arrow = function () { 11681 return (this.$arrow = this.$arrow || this.tip().find('.arrow')) 11682 } 11683 11684 11685 // POPOVER PLUGIN DEFINITION 11686 // ========================= 11687 11688 function Plugin(option) { 11689 return this.each(function () { 11690 var $this = $(this) 11691 var data = $this.data('bs.popover') 11692 var options = typeof option == 'object' && option 11693 11694 if (!data && /destroy|hide/.test(option)) return 11695 if (!data) $this.data('bs.popover', (data = new Popover(this, options))) 11696 if (typeof option == 'string') data[option]() 11697 }) 11698 } 11699 11700 var old = $.fn.popover 11701 11702 $.fn.popover = Plugin 11703 $.fn.popover.Constructor = Popover 11704 11705 11706 // POPOVER NO CONFLICT 11707 // =================== 11708 11709 $.fn.popover.noConflict = function () { 11710 $.fn.popover = old 11711 return this 11712 } 11713 11714}(jQuery); 11715 11716/* ======================================================================== 11717 * Bootstrap: scrollspy.js v3.3.6 11718 * http://getbootstrap.com/javascript/#scrollspy 11719 * ======================================================================== 11720 * Copyright 2011-2015 Twitter, Inc. 11721 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 11722 * ======================================================================== */ 11723 11724 11725+function ($) { 11726 'use strict'; 11727 11728 // SCROLLSPY CLASS DEFINITION 11729 // ========================== 11730 11731 function ScrollSpy(element, options) { 11732 this.$body = $(document.body) 11733 this.$scrollElement = $(element).is(document.body) ? $(window) : $(element) 11734 this.options = $.extend({}, ScrollSpy.DEFAULTS, options) 11735 this.selector = (this.options.target || '') + ' .nav li > a' 11736 this.offsets = [] 11737 this.targets = [] 11738 this.activeTarget = null 11739 this.scrollHeight = 0 11740 11741 this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this)) 11742 this.refresh() 11743 this.process() 11744 } 11745 11746 ScrollSpy.VERSION = '3.3.6' 11747 11748 ScrollSpy.DEFAULTS = { 11749 offset: 10 11750 } 11751 11752 ScrollSpy.prototype.getScrollHeight = function () { 11753 return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight) 11754 } 11755 11756 ScrollSpy.prototype.refresh = function () { 11757 var that = this 11758 var offsetMethod = 'offset' 11759 var offsetBase = 0 11760 11761 this.offsets = [] 11762 this.targets = [] 11763 this.scrollHeight = this.getScrollHeight() 11764 11765 if (!$.isWindow(this.$scrollElement[0])) { 11766 offsetMethod = 'position' 11767 offsetBase = this.$scrollElement.scrollTop() 11768 } 11769 11770 this.$body 11771 .find(this.selector) 11772 .map(function () { 11773 var $el = $(this) 11774 var href = $el.data('target') || $el.attr('href') 11775 var $href = /^#./.test(href) && $(href) 11776 11777 return ($href 11778 && $href.length 11779 && $href.is(':visible') 11780 && [[$href[offsetMethod]().top + offsetBase, href]]) || null 11781 }) 11782 .sort(function (a, b) { return a[0] - b[0] }) 11783 .each(function () { 11784 that.offsets.push(this[0]) 11785 that.targets.push(this[1]) 11786 }) 11787 } 11788 11789 ScrollSpy.prototype.process = function () { 11790 var scrollTop = this.$scrollElement.scrollTop() + this.options.offset 11791 var scrollHeight = this.getScrollHeight() 11792 var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height() 11793 var offsets = this.offsets 11794 var targets = this.targets 11795 var activeTarget = this.activeTarget 11796 var i 11797 11798 if (this.scrollHeight != scrollHeight) { 11799 this.refresh() 11800 } 11801 11802 if (scrollTop >= maxScroll) { 11803 return activeTarget != (i = targets[targets.length - 1]) && this.activate(i) 11804 } 11805 11806 if (activeTarget && scrollTop < offsets[0]) { 11807 this.activeTarget = null 11808 return this.clear() 11809 } 11810 11811 for (i = offsets.length; i--;) { 11812 activeTarget != targets[i] 11813 && scrollTop >= offsets[i] 11814 && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1]) 11815 && this.activate(targets[i]) 11816 } 11817 } 11818 11819 ScrollSpy.prototype.activate = function (target) { 11820 this.activeTarget = target 11821 11822 this.clear() 11823 11824 var selector = this.selector + 11825 '[data-target="' + target + '"],' + 11826 this.selector + '[href="' + target + '"]' 11827 11828 var active = $(selector) 11829 .parents('li') 11830 .addClass('active') 11831 11832 if (active.parent('.dropdown-menu').length) { 11833 active = active 11834 .closest('li.dropdown') 11835 .addClass('active') 11836 } 11837 11838 active.trigger('activate.bs.scrollspy') 11839 } 11840 11841 ScrollSpy.prototype.clear = function () { 11842 $(this.selector) 11843 .parentsUntil(this.options.target, '.active') 11844 .removeClass('active') 11845 } 11846 11847 11848 // SCROLLSPY PLUGIN DEFINITION 11849 // =========================== 11850 11851 function Plugin(option) { 11852 return this.each(function () { 11853 var $this = $(this) 11854 var data = $this.data('bs.scrollspy') 11855 var options = typeof option == 'object' && option 11856 11857 if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))) 11858 if (typeof option == 'string') data[option]() 11859 }) 11860 } 11861 11862 var old = $.fn.scrollspy 11863 11864 $.fn.scrollspy = Plugin 11865 $.fn.scrollspy.Constructor = ScrollSpy 11866 11867 11868 // SCROLLSPY NO CONFLICT 11869 // ===================== 11870 11871 $.fn.scrollspy.noConflict = function () { 11872 $.fn.scrollspy = old 11873 return this 11874 } 11875 11876 11877 // SCROLLSPY DATA-API 11878 // ================== 11879 11880 $(window).on('load.bs.scrollspy.data-api', function () { 11881 $('[data-spy="scroll"]').each(function () { 11882 var $spy = $(this) 11883 Plugin.call($spy, $spy.data()) 11884 }) 11885 }) 11886 11887}(jQuery); 11888 11889/* ======================================================================== 11890 * Bootstrap: tab.js v3.3.6 11891 * http://getbootstrap.com/javascript/#tabs 11892 * ======================================================================== 11893 * Copyright 2011-2015 Twitter, Inc. 11894 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 11895 * ======================================================================== */ 11896 11897 11898+function ($) { 11899 'use strict'; 11900 11901 // TAB CLASS DEFINITION 11902 // ==================== 11903 11904 var Tab = function (element) { 11905 // jscs:disable requireDollarBeforejQueryAssignment 11906 this.element = $(element) 11907 // jscs:enable requireDollarBeforejQueryAssignment 11908 } 11909 11910 Tab.VERSION = '3.3.6' 11911 11912 Tab.TRANSITION_DURATION = 150 11913 11914 Tab.prototype.show = function () { 11915 var $this = this.element 11916 var $ul = $this.closest('ul:not(.dropdown-menu)') 11917 var selector = $this.data('target') 11918 11919 if (!selector) { 11920 selector = $this.attr('href') 11921 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 11922 } 11923 11924 if ($this.parent('li').hasClass('active')) return 11925 11926 var $previous = $ul.find('.active:last a') 11927 var hideEvent = $.Event('hide.bs.tab', { 11928 relatedTarget: $this[0] 11929 }) 11930 var showEvent = $.Event('show.bs.tab', { 11931 relatedTarget: $previous[0] 11932 }) 11933 11934 $previous.trigger(hideEvent) 11935 $this.trigger(showEvent) 11936 11937 if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return 11938 11939 var $target = $(selector) 11940 11941 this.activate($this.closest('li'), $ul) 11942 this.activate($target, $target.parent(), function () { 11943 $previous.trigger({ 11944 type: 'hidden.bs.tab', 11945 relatedTarget: $this[0] 11946 }) 11947 $this.trigger({ 11948 type: 'shown.bs.tab', 11949 relatedTarget: $previous[0] 11950 }) 11951 }) 11952 } 11953 11954 Tab.prototype.activate = function (element, container, callback) { 11955 var $active = container.find('> .active') 11956 var transition = callback 11957 && $.support.transition 11958 && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length) 11959 11960 function next() { 11961 $active 11962 .removeClass('active') 11963 .find('> .dropdown-menu > .active') 11964 .removeClass('active') 11965 .end() 11966 .find('[data-toggle="tab"]') 11967 .attr('aria-expanded', false) 11968 11969 element 11970 .addClass('active') 11971 .find('[data-toggle="tab"]') 11972 .attr('aria-expanded', true) 11973 11974 if (transition) { 11975 element[0].offsetWidth // reflow for transition 11976 element.addClass('in') 11977 } else { 11978 element.removeClass('fade') 11979 } 11980 11981 if (element.parent('.dropdown-menu').length) { 11982 element 11983 .closest('li.dropdown') 11984 .addClass('active') 11985 .end() 11986 .find('[data-toggle="tab"]') 11987 .attr('aria-expanded', true) 11988 } 11989 11990 callback && callback() 11991 } 11992 11993 $active.length && transition ? 11994 $active 11995 .one('bsTransitionEnd', next) 11996 .emulateTransitionEnd(Tab.TRANSITION_DURATION) : 11997 next() 11998 11999 $active.removeClass('in') 12000 } 12001 12002 12003 // TAB PLUGIN DEFINITION 12004 // ===================== 12005 12006 function Plugin(option) { 12007 return this.each(function () { 12008 var $this = $(this) 12009 var data = $this.data('bs.tab') 12010 12011 if (!data) $this.data('bs.tab', (data = new Tab(this))) 12012 if (typeof option == 'string') data[option]() 12013 }) 12014 } 12015 12016 var old = $.fn.tab 12017 12018 $.fn.tab = Plugin 12019 $.fn.tab.Constructor = Tab 12020 12021 12022 // TAB NO CONFLICT 12023 // =============== 12024 12025 $.fn.tab.noConflict = function () { 12026 $.fn.tab = old 12027 return this 12028 } 12029 12030 12031 // TAB DATA-API 12032 // ============ 12033 12034 var clickHandler = function (e) { 12035 e.preventDefault() 12036 Plugin.call($(this), 'show') 12037 } 12038 12039 $(document) 12040 .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler) 12041 .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler) 12042 12043}(jQuery); 12044 12045/* ======================================================================== 12046 * Bootstrap: affix.js v3.3.6 12047 * http://getbootstrap.com/javascript/#affix 12048 * ======================================================================== 12049 * Copyright 2011-2015 Twitter, Inc. 12050 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 12051 * ======================================================================== */ 12052 12053 12054+function ($) { 12055 'use strict'; 12056 12057 // AFFIX CLASS DEFINITION 12058 // ====================== 12059 12060 var Affix = function (element, options) { 12061 this.options = $.extend({}, Affix.DEFAULTS, options) 12062 12063 this.$target = $(this.options.target) 12064 .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this)) 12065 .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this)) 12066 12067 this.$element = $(element) 12068 this.affixed = null 12069 this.unpin = null 12070 this.pinnedOffset = null 12071 12072 this.checkPosition() 12073 } 12074 12075 Affix.VERSION = '3.3.6' 12076 12077 Affix.RESET = 'affix affix-top affix-bottom' 12078 12079 Affix.DEFAULTS = { 12080 offset: 0, 12081 target: window 12082 } 12083 12084 Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) { 12085 var scrollTop = this.$target.scrollTop() 12086 var position = this.$element.offset() 12087 var targetHeight = this.$target.height() 12088 12089 if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false 12090 12091 if (this.affixed == 'bottom') { 12092 if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom' 12093 return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom' 12094 } 12095 12096 var initializing = this.affixed == null 12097 var colliderTop = initializing ? scrollTop : position.top 12098 var colliderHeight = initializing ? targetHeight : height 12099 12100 if (offsetTop != null && scrollTop <= offsetTop) return 'top' 12101 if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom' 12102 12103 return false 12104 } 12105 12106 Affix.prototype.getPinnedOffset = function () { 12107 if (this.pinnedOffset) return this.pinnedOffset 12108 this.$element.removeClass(Affix.RESET).addClass('affix') 12109 var scrollTop = this.$target.scrollTop() 12110 var position = this.$element.offset() 12111 return (this.pinnedOffset = position.top - scrollTop) 12112 } 12113 12114 Affix.prototype.checkPositionWithEventLoop = function () { 12115 setTimeout($.proxy(this.checkPosition, this), 1) 12116 } 12117 12118 Affix.prototype.checkPosition = function () { 12119 if (!this.$element.is(':visible')) return 12120 12121 var height = this.$element.height() 12122 var offset = this.options.offset 12123 var offsetTop = offset.top 12124 var offsetBottom = offset.bottom 12125 var scrollHeight = Math.max($(document).height(), $(document.body).height()) 12126 12127 if (typeof offset != 'object') offsetBottom = offsetTop = offset 12128 if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element) 12129 if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element) 12130
12131 var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom) 12132 12133 if (this.affixed != affix) { 12134 if (this.unpin != null) this.$element.css('top', '') 12135 12136 var affixType = 'affix' + (affix ? '-' + affix : '') 12137 var e = $.Event(affixType + '.bs.affix') 12138 12139 this.$element.trigger(e) 12140 12141 if (e.isDefaultPrevented()) return 12142 12143 this.affixed = affix 12144 this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null 12145 12146 this.$element 12147 .removeClass(Affix.RESET) 12148 .addClass(affixType) 12149 .trigger(affixType.replace('affix', 'affixed') + '.bs.affix') 12150 } 12151 12152 if (affix == 'bottom') { 12153 this.$element.offset({ 12154 top: scrollHeight - height - offsetBottom 12155 }) 12156 } 12157 } 12158 12159 12160 // AFFIX PLUGIN DEFINITION 12161 // ======================= 12162 12163 function Plugin(option) { 12164 return this.each(function () { 12165 var $this = $(this) 12166 var data = $this.data('bs.affix') 12167 var options = typeof option == 'object' && option 12168 12169 if (!data) $this.data('bs.affix', (data = new Affix(this, options))) 12170 if (typeof option == 'string') data[option]() 12171 }) 12172 } 12173 12174 var old = $.fn.affix 12175 12176 $.fn.affix = Plugin 12177 $.fn.affix.Constructor = Affix 12178 12179 12180 // AFFIX NO CONFLICT 12181 // ================= 12182 12183 $.fn.affix.noConflict = function () { 12184 $.fn.affix = old 12185 return this 12186 } 12187 12188 12189 // AFFIX DATA-API 12190 // ============== 12191 12192 $(window).on('load', function () { 12193 $('[data-spy="affix"]').each(function () { 12194 var $spy = $(this) 12195 var data = $spy.data() 12196 12197 data.offset = data.offset || {} 12198 12199 if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom 12200 if (data.offsetTop != null) data.offset.top = data.offsetTop 12201 12202 Plugin.call($spy, data) 12203 }) 12204 }) 12205 12206}(jQuery); 12207 12208// Generated by CoffeeScript 1.8.0 12209 12210/* 12211jQuery Credit Card Validator 1.0 12212 12213Copyright 2012-2015 Pawel Decowski 12214 12215Permission is hereby granted, free of charge, to any person obtaining a copy 12216of this software and associated documentation files (the "Software"), to deal 12217in the Software without restriction, including without limitation the rights 12218to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12219copies of the Software, and to permit persons to whom the Software 12220is furnished to do so, subject to the following conditions: 12221 12222The above copyright notice and this permission notice shall be included 12223in all copies or substantial portions of the Software. 12224 12225THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 12226OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12227FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 12228THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 12229LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 12230OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 12231IN THE SOFTWARE. 12232 */ 12233 12234(function() { 12235 var $, 12236 __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; 12237 12238 $ = jQuery; 12239 12240 $.fn.validateCreditCard = function(callback, options) { 12241 var bind, card, card_type, card_types, get_card_type, is_valid_length, is_valid_luhn, normalize, validate, validate_number, _i, _len, _ref; 12242 card_types = [ 12243 { 12244 name: 'amex', 12245 pattern: /^3[47]/, 12246 valid_length: [15] 12247 }, { 12248 name: 'diners_club_carte_blanche', 12249 pattern: /^30[0-5]/, 12250 valid_length: [14] 12251 }, { 12252 name: 'diners_club_international', 12253 pattern: /^36/, 12254 valid_length: [14] 12255 }, { 12256 name: 'jcb', 12257 pattern: /^35(2[89]|[3-8][0-9])/, 12258 valid_length: [16] 12259 }, { 12260 name: 'laser', 12261 pattern: /^(6304|670[69]|6771)/, 12262 valid_length: [16, 17, 18, 19] 12263 }, { 12264 name: 'visa_electron', 12265 pattern: /^(4026|417500|4508|4844|491(3|7))/, 12266 valid_length: [16] 12267 }, { 12268 name: 'visa', 12269 pattern: /^4/, 12270 valid_length: [16] 12271 }, { 12272 name: 'mastercard', 12273 pattern: /^5[1-5]/, 12274 valid_length: [16] 12275 }, { 12276 name: 'maestro', 12277 pattern: /^(5018|5020|5038|6304|6759|676[1-3])/, 12278 valid_length: [12, 13, 14, 15, 16, 17, 18, 19] 12279 }, { 12280 name: 'discover', 12281 pattern: /^(6011|622(12[6-9]|1[3-9][0-9]|[2-8][0-9]{2}|9[0-1][0-9]|92[0-5]|64[4-9])|65)/, 12282 valid_length: [16] 12283 } 12284 ]; 12285 bind = false;
12286 if (callback) { 12287 if (typeof callback === 'object') { 12288 options = callback; 12289 bind = false; 12290 callback = null; 12291 } else if (typeof callback === 'function') { 12292 bind = true; 12293 } 12294 } 12295 if (options == null) { 12296 options = {}; 12297 } 12298 if (options.accept == null) { 12299 options.accept = (function() { 12300 var _i, _len, _results; 12301 _results = []; 12302 for (_i = 0, _len = card_types.length; _i < _len; _i++) { 12303 card = card_types[_i]; 12304 _results.push(card.name); 12305 } 12306 return _results; 12307 })(); 12308 } 12309 _ref = options.accept; 12310 for (_i = 0, _len = _ref.length; _i < _len; _i++) { 12311 card_type = _ref[_i]; 12312 if (__indexOf.call((function() { 12313 var _j, _len1, _results; 12314 _results = []; 12315 for (_j = 0, _len1 = card_types.length; _j < _len1; _j++) { 12316 card = card_types[_j]; 12317 _results.push(card.name); 12318 } 12319 return _results; 12320 })(), card_type) < 0) { 12321 throw "Credit card type '" + card_type + "' is not supported"; 12322 } 12323 } 12324 get_card_type = function(number) { 12325 var _j, _len1, _ref1; 12326 _ref1 = (function() { 12327 var _k, _len1, _ref1, _results; 12328 _results = []; 12329 for (_k = 0, _len1 = card_types.length; _k < _len1; _k++) { 12330 card = card_types[_k]; 12331 if (_ref1 = card.name, __indexOf.call(options.accept, _ref1) >= 0) { 12332 _results.push(card); 12333 } 12334 } 12335 return _results; 12336 })(); 12337 for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { 12338 card_type = _ref1[_j]; 12339 if (number.match(card_type.pattern)) { 12340 return card_type; 12341 } 12342 } 12343 return null; 12344 }; 12345 is_valid_luhn = function(number) { 12346 var digit, n, sum, _j, _len1, _ref1; 12347 sum = 0; 12348 _ref1 = number.split('').reverse(); 12349 for (n = _j = 0, _len1 = _ref1.length; _j < _len1; n = ++_j) { 12350 digit = _ref1[n]; 12351 digit = +digit; 12352 if (n % 2) { 12353 digit *= 2; 12354 if (digit < 10) { 12355 sum += digit; 12356 } else { 12357 sum += digit - 9; 12358 } 12359 } else { 12360 sum += digit; 12361 } 12362 } 12363 return sum % 10 === 0; 12364 }; 12365 is_valid_length = function(number, card_type) { 12366 var _ref1; 12367 return _ref1 = number.length, __indexOf.call(card_type.valid_length, _ref1) >= 0; 12368 }; 12369 validate_number = (function(_this) { 12370 return function(number) { 12371 var length_valid, luhn_valid; 12372 card_type = get_card_type(number); 12373 luhn_valid = false; 12374 length_valid = false; 12375 if (card_type != null) { 12376 luhn_valid = is_valid_luhn(number); 12377 length_valid = is_valid_length(number, card_type); 12378 } 12379 return { 12380 card_type: card_type, 12381 valid: luhn_valid && length_valid, 12382 luhn_valid: luhn_valid, 12383 length_valid: length_valid 12384 }; 12385 }; 12386 })(this); 12387 validate = (function(_this) { 12388 return function() { 12389 var number; 12390 number = normalize($(_this).val()); 12391 return validate_number(number); 12392 }; 12393 })(this); 12394 normalize = function(number) { 12395 return number.replace(/[ -]/g, ''); 12396 }; 12397 if (!bind) { 12398 return validate(); 12399 } 12400 this.on('input.jccv', (function(_this) { 12401 return function() { 12402 $(_this).off('keyup.jccv'); 12403 return callback.call(_this, validate()); 12404 }; 12405 })(this)); 12406 this.on('keyup.jccv', (function(_this) { 12407 return function() { 12408 return callback.call(_this, validate()); 12409 }; 12410 })(this)); 12411 callback.call(this, validate()); 12412 return this; 12413 }; 12414 12415}).call(this); 12416 12417/** 12418 * EvEmitter v1.0.2 12419 * Lil' event emitter 12420 * MIT License 12421 */ 12422 12423/* jshint unused: true, undef: true, strict: true */ 12424 12425( function( global, factory ) { 12426 // universal module definition 12427 /* jshint strict: false */ /* globals define, module */ 12428 if ( typeof define == 'function' && define.amd ) { 12429 // AMD - RequireJS 12430 define( factory ); 12431 } else if ( typeof module == 'object' && module.exports ) { 12432 // CommonJS - Browserify, Webpack 12433 module.exports = factory(); 12434 } else { 12435 // Browser globals 12436 global.EvEmitter = factory(); 12437 } 12438 12439}( this, function() { 12440 12441"use strict"; 12442 12443function EvEmitter() {} 12444 12445var proto = EvEmitter.prototype; 12446 12447proto.on = function( eventName, listener ) { 12448 if ( !eventName || !listener ) { 12449 return; 12450 } 12451 // set events hash 12452 var events = this._events = this._events || {}; 12453 // set listeners array 12454 var listeners = events[ eventName ] = events[ eventName ] || []; 12455 // only add once 12456 if ( listeners.indexOf( listener ) == -1 ) { 12457 listeners.push( listener ); 12458 } 12459 12460 return this; 12461}; 12462 12463proto.once = function( eventName, listener ) { 12464 if ( !eventName || !listener ) { 12465 return; 12466 } 12467 // add event 12468 this.on( eventName, listener ); 12469 // set once flag 12470 // set onceEvents hash 12471 var onceEvents = this._onceEvents = this._onceEvents || {}; 12472 // set onceListeners object 12473 var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {}; 12474 // set flag 12475 onceListeners[ listener ] = true; 12476 12477 return this; 12478}; 12479 12480proto.off = function( eventName, listener ) { 12481 var listeners = this._events && this._events[ eventName ]; 12482 if ( !listeners || !listeners.length ) { 12483 return; 12484 } 12485 var index = listeners.indexOf( listener ); 12486 if ( index != -1 ) { 12487 listeners.splice( index, 1 ); 12488 } 12489 12490 return this; 12491}; 12492 12493proto.emitEvent = function( eventName, args ) { 12494 var listeners = this._events && this._events[ eventName ]; 12495 if ( !listeners || !listeners.length ) { 12496 return; 12497 } 12498 var i = 0; 12499 var listener = listeners[i]; 12500 args = args || []; 12501 // once stuff 12502 var onceListeners = this._onceEvents && this._onceEvents[ eventName ]; 12503 12504 while ( listener ) { 12505 var isOnce = onceListeners && onceListeners[ listener ]; 12506 if ( isOnce ) { 12507 // remove listener 12508 // remove before trigger to prevent recursion 12509 this.off( eventName, listener ); 12510 // unset once flag 12511 delete onceListeners[ listener ]; 12512 } 12513 // trigger listener 12514 listener.apply( this, args ); 12515 // get next listener 12516 i += isOnce ? 0 : 1; 12517 listener = listeners[i]; 12518 } 12519 12520 return this; 12521}; 12522 12523return EvEmitter; 12524 12525})); 12526 12527/*! 12528 * Select2 4.0.1 12529 * https://select2.github.io 12530 * 12531 * Released under the MIT license 12532 * https://github.com/select2/select2/blob/master/LICENSE.md 12533 */ 12534(function (factory) { 12535 if (typeof define === 'function' && define.amd) { 12536 // AMD. Register as an anonymous module. 12537 define(['jquery'], factory); 12538 } else if (typeof exports === 'object') { 12539 // Node/CommonJS 12540 factory(require('jquery')); 12541 } else { 12542 // Browser globals 12543 factory(jQuery); 12544 } 12545}(function (jQuery) { 12546 // This is needed so we can catch the AMD loader configuration and use it 12547 // The inner file should be wrapped (by `banner.start.js`) in a function that 12548 // returns the AMD loader references. 12549 var S2 = 12550(function () { 12551 // Restore the Select2 AMD loader so it can be used 12552 // Needed mostly in the language files, where the loader is not inserted 12553 if (jQuery && jQuery.fn && jQuery.fn.select2 && jQuery.fn.select2.amd) { 12554 var S2 = jQuery.fn.select2.amd; 12555 } 12556var S2;(function () { if (!S2 || !S2.requirejs) { 12557if (!S2) { S2 = {}; } else { require = S2; } 12558/** 12559 * @license almond 0.3.1 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved. 12560 * Available via the MIT or new BSD license. 12561 * see: http://github.com/jrburke/almond for details 12562 */ 12563//Going sloppy to avoid 'use strict' string cost, but strict practices should 12564//be followed. 12565/*jslint sloppy: true */ 12566/*global setTimeout: false */ 12567 12568var requirejs, require, define; 12569(function (undef) { 12570 var main, req, makeMap, handlers, 12571 defined = {}, 12572 waiting = {}, 12573 config = {}, 12574 defining = {}, 12575 hasOwn = Object.prototype.hasOwnProperty, 12576 aps = [].slice, 12577 jsSuffixRegExp = /\.js$/; 12578 12579 function hasProp(obj, prop) { 12580 return hasOwn.call(obj, prop); 12581 } 12582 12583 /** 12584 * Given a relative module name, like ./something, normalize it to 12585 * a real name that can be mapped to a path. 12586 * @param {String} name the relative name 12587 * @param {String} baseName a real name that the name arg is relative 12588 * to. 12589 * @returns {String} normalized name 12590 */ 12591 function normalize(name, baseName) { 12592 var nameParts, nameSegment, mapValue, foundMap, lastIndex, 12593 foundI, foundStarMap, starI, i, j, part, 12594 baseParts = baseName && baseName.split("/"), 12595 map = config.map, 12596 starMap = (map && map['*']) || {}; 12597 12598 //Adjust any relative paths. 12599 if (name && name.charAt(0) === ".") { 12600 //If have a base name, try to normalize against it, 12601 //otherwise, assume it is a top-level require that will 12602 //be relative to baseUrl in the end. 12603 if (baseName) { 12604 name = name.split('/'); 12605 lastIndex = name.length - 1; 12606 12607 // Node .js allowance: 12608 if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) { 12609 name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); 12610 } 12611 12612 //Lop off the last part of baseParts, so that . matches the 12613 //"directory" and not name of the baseName's module. For instance, 12614 //baseName of "one/two/three", maps to "one/two/three.js", but we 12615 //want the directory, "one/two" for this normalization. 12616 name = baseParts.slice(0, baseParts.length - 1).concat(name); 12617 12618 //start trimDots 12619 for (i = 0; i < name.length; i += 1) { 12620 part = name[i]; 12621 if (part === ".") { 12622 name.splice(i, 1); 12623 i -= 1; 12624 } else if (part === "..") { 12625 if (i === 1 && (name[2] === '..' || name[0] === '..')) { 12626 //End of the line. Keep at least one non-dot 12627 //path segment at the front so it can be mapped 12628 //correctly to disk. Otherwise, there is likely 12629 //no path mapping for a path starting with '..'. 12630 //This can still fail, but catches the most reasonable 12631 //uses of .. 12632 break; 12633 } else if (i > 0) { 12634 name.splice(i - 1, 2); 12635 i -= 2; 12636 } 12637 } 12638 } 12639 //end trimDots 12640 12641 name = name.join("/"); 12642 } else if (name.indexOf('./') === 0) { 12643 // No baseName, so this is ID is resolved relative 12644 // to baseUrl, pull off the leading dot. 12645 name = name.substring(2); 12646 } 12647 } 12648 12649 //Apply map config if available. 12650 if ((baseParts || starMap) && map) {
vendor: 8,882 bytes, lines 12651-12904
12651 nameParts = name.split('/'); 12652 12653 for (i = nameParts.length; i > 0; i -= 1) { 12654 nameSegment = nameParts.slice(0, i).join("/"); 12655 12656 if (baseParts) { 12657 //Find the longest baseName segment match in the config. 12658 //So, do joins on the biggest to smallest lengths of baseParts. 12659 for (j = baseParts.length; j > 0; j -= 1) { 12660 mapValue = map[baseParts.slice(0, j).join('/')]; 12661 12662 //baseName segment has config, find if it has one for 12663 //this name. 12664 if (mapValue) { 12665 mapValue = mapValue[nameSegment]; 12666 if (mapValue) { 12667 //Match, update name to the new value. 12668 foundMap = mapValue; 12669 foundI = i; 12670 break; 12671 } 12672 } 12673 } 12674 } 12675 12676 if (foundMap) { 12677 break; 12678 } 12679 12680 //Check for a star map match, but just hold on to it, 12681 //if there is a shorter segment match later in a matching 12682 //config, then favor over this star map. 12683 if (!foundStarMap && starMap && starMap[nameSegment]) { 12684 foundStarMap = starMap[nameSegment]; 12685 starI = i; 12686 } 12687 } 12688 12689 if (!foundMap && foundStarMap) { 12690 foundMap = foundStarMap; 12691 foundI = starI; 12692 } 12693 12694 if (foundMap) { 12695 nameParts.splice(0, foundI, foundMap); 12696 name = nameParts.join('/'); 12697 } 12698 } 12699 12700 return name; 12701 } 12702 12703 function makeRequire(relName, forceSync) { 12704 return function () { 12705 //A version of a require function that passes a moduleName 12706 //value for items that may need to 12707 //look up paths relative to the moduleName 12708 var args = aps.call(arguments, 0); 12709 12710 //If first arg is not require('string'), and there is only 12711 //one arg, it is the array form without a callback. Insert 12712 //a null so that the following concat is correct. 12713 if (typeof args[0] !== 'string' && args.length === 1) { 12714 args.push(null); 12715 } 12716 return req.apply(undef, args.concat([relName, forceSync])); 12717 }; 12718 } 12719 12720 function makeNormalize(relName) { 12721 return function (name) { 12722 return normalize(name, relName); 12723 }; 12724 } 12725 12726 function makeLoad(depName) { 12727 return function (value) { 12728 defined[depName] = value; 12729 }; 12730 } 12731 12732 function callDep(name) { 12733 if (hasProp(waiting, name)) { 12734 var args = waiting[name]; 12735 delete waiting[name]; 12736 defining[name] = true; 12737 main.apply(undef, args); 12738 } 12739 12740 if (!hasProp(defined, name) && !hasProp(defining, name)) { 12741 throw new Error('No ' + name); 12742 } 12743 return defined[name]; 12744 } 12745 12746 //Turns a plugin!resource to [plugin, resource] 12747 //with the plugin being undefined if the name 12748 //did not have a plugin prefix. 12749 function splitPrefix(name) { 12750 var prefix, 12751 index = name ? name.indexOf('!') : -1; 12752 if (index > -1) { 12753 prefix = name.substring(0, index); 12754 name = name.substring(index + 1, name.length); 12755 } 12756 return [prefix, name]; 12757 } 12758 12759 /** 12760 * Makes a name map, normalizing the name, and using a plugin 12761 * for normalization if necessary. Grabs a ref to plugin 12762 * too, as an optimization. 12763 */ 12764 makeMap = function (name, relName) { 12765 var plugin, 12766 parts = splitPrefix(name), 12767 prefix = parts[0]; 12768 12769 name = parts[1]; 12770 12771 if (prefix) { 12772 prefix = normalize(prefix, relName); 12773 plugin = callDep(prefix); 12774 } 12775 12776 //Normalize according 12777 if (prefix) { 12778 if (plugin && plugin.normalize) { 12779 name = plugin.normalize(name, makeNormalize(relName)); 12780 } else { 12781 name = normalize(name, relName); 12782 } 12783 } else { 12784 name = normalize(name, relName); 12785 parts = splitPrefix(name); 12786 prefix = parts[0]; 12787 name = parts[1]; 12788 if (prefix) { 12789 plugin = callDep(prefix); 12790 } 12791 } 12792 12793 //Using ridiculous property names for space reasons 12794 return { 12795 f: prefix ? prefix + '!' + name : name, //fullName 12796 n: name, 12797 pr: prefix, 12798 p: plugin 12799 }; 12800 }; 12801 12802 function makeConfig(name) { 12803 return function () { 12804 return (config && config.config && config.config[name]) || {}; 12805 }; 12806 } 12807 12808 handlers = { 12809 require: function (name) { 12810 return makeRequire(name); 12811 }, 12812 exports: function (name) { 12813 var e = defined[name]; 12814 if (typeof e !== 'undefined') { 12815 return e; 12816 } else { 12817 return (defined[name] = {}); 12818 } 12819 }, 12820 module: function (name) { 12821 return { 12822 id: name, 12823 uri: '', 12824 exports: defined[name], 12825 config: makeConfig(name) 12826 }; 12827 } 12828 }; 12829 12830 main = function (name, deps, callback, relName) { 12831 var cjsModule, depName, ret, map, i, 12832 args = [], 12833 callbackType = typeof callback, 12834 usingExports; 12835 12836 //Use name if no relName 12837 relName = relName || name; 12838 12839 //Call the callback to define the module, if necessary. 12840 if (callbackType === 'undefined' || callbackType === 'function') { 12841 //Pull out the defined dependencies and pass the ordered 12842 //values to the callback. 12843 //Default to [require, exports, module] if no deps 12844 deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps; 12845 for (i = 0; i < deps.length; i += 1) { 12846 map = makeMap(deps[i], relName); 12847 depName = map.f; 12848 12849 //Fast path CommonJS standard dependencies. 12850 if (depName === "require") { 12851 args[i] = handlers.require(name); 12852 } else if (depName === "exports") { 12853 //CommonJS module spec 1.1 12854 args[i] = handlers.exports(name); 12855 usingExports = true; 12856 } else if (depName === "module") { 12857 //CommonJS module spec 1.1 12858 cjsModule = args[i] = handlers.module(name); 12859 } else if (hasProp(defined, depName) || 12860 hasProp(waiting, depName) || 12861 hasProp(defining, depName)) { 12862 args[i] = callDep(depName); 12863 } else if (map.p) { 12864 map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {}); 12865 args[i] = defined[depName]; 12866 } else { 12867 throw new Error(name + ' missing ' + depName); 12868 } 12869 } 12870 12871 ret = callback ? callback.apply(defined[name], args) : undefined; 12872 12873 if (name) { 12874 //If setting exports via "module" is in play, 12875 //favor that over return value and exports. After that, 12876 //favor a non-undefined return value over exports use. 12877 if (cjsModule && cjsModule.exports !== undef && 12878 cjsModule.exports !== defined[name]) { 12879 defined[name] = cjsModule.exports; 12880 } else if (ret !== undef || !usingExports) { 12881 //Use the return value from the function. 12882 defined[name] = ret; 12883 } 12884 } 12885 } else if (name) { 12886 //May just be an object definition for the module. Only 12887 //worry about defining if have a module name. 12888 defined[name] = callback; 12889 } 12890 }; 12891 12892 requirejs = require = req = function (deps, callback, relName, forceSync, alt) { 12893 if (typeof deps === "string") { 12894 if (handlers[deps]) { 12895 //callback in this case is really relName 12896 return handlers[deps](callback); 12897 } 12898 //Just return the module wanted. In this scenario, the 12899 //deps arg is the module name, and second arg (if passed) 12900 //is just the relName. 12901 //Normalize module name, if it contains . or .. 12902 return callDep(makeMap(deps, callback).f); 12903 } else if (!deps.splice) { 12904 //deps is a config object, not an array.
vendor: 38,023 bytes, lines 12905-14414
12905 config = deps; 12906 if (config.deps) { 12907 req(config.deps, config.callback); 12908 } 12909 if (!callback) { 12910 return; 12911 } 12912 12913 if (callback.splice) { 12914 //callback is an array, which means it is a dependency list. 12915 //Adjust args if there are dependencies 12916 deps = callback; 12917 callback = relName; 12918 relName = null; 12919 } else { 12920 deps = undef; 12921 } 12922 } 12923 12924 //Support require(['a']) 12925 callback = callback || function () {}; 12926 12927 //If relName is a function, it is an errback handler, 12928 //so remove it. 12929 if (typeof relName === 'function') { 12930 relName = forceSync; 12931 forceSync = alt; 12932 } 12933 12934 //Simulate async callback; 12935 if (forceSync) { 12936 main(undef, deps, callback, relName); 12937 } else { 12938 //Using a non-zero value because of concern for what old browsers 12939 //do, and latest browsers "upgrade" to 4 if lower value is used: 12940 //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout: 12941 //If want a value immediately, use require('id') instead -- something 12942 //that works in almond on the global level, but not guaranteed and 12943 //unlikely to work in other AMD implementations. 12944 setTimeout(function () { 12945 main(undef, deps, callback, relName); 12946 }, 4); 12947 } 12948 12949 return req; 12950 }; 12951 12952 /** 12953 * Just drops the config on the floor, but returns req in case 12954 * the config return value is used. 12955 */ 12956 req.config = function (cfg) { 12957 return req(cfg); 12958 }; 12959 12960 /** 12961 * Expose module registry for debugging and tooling 12962 */ 12963 requirejs._defined = defined; 12964 12965 define = function (name, deps, callback) { 12966 if (typeof name !== 'string') { 12967 throw new Error('See almond README: incorrect module build, no module name'); 12968 } 12969 12970 //This module may not have dependencies 12971 if (!deps.splice) { 12972 //deps is not an array, so probably means 12973 //an object literal or factory function for 12974 //the value. Adjust args. 12975 callback = deps; 12976 deps = []; 12977 } 12978 12979 if (!hasProp(defined, name) && !hasProp(waiting, name)) { 12980 waiting[name] = [name, deps, callback]; 12981 } 12982 }; 12983 12984 define.amd = { 12985 jQuery: true 12986 }; 12987}()); 12988 12989S2.requirejs = requirejs;S2.require = require;S2.define = define; 12990} 12991}()); 12992S2.define("almond", function(){}); 12993 12994/* global jQuery:false, $:false */ 12995S2.define('jquery',[],function () { 12996 var _$ = jQuery || $; 12997 12998 if (_$ == null && console && console.error) { 12999 console.error( 13000 'Select2: An instance of jQuery or a jQuery-compatible library was not ' + 13001 'found. Make sure that you are including jQuery before Select2 on your ' + 13002 'web page.' 13003 ); 13004 } 13005 13006 return _$; 13007}); 13008 13009S2.define('select2/utils',[ 13010 'jquery' 13011], function ($) { 13012 var Utils = {}; 13013 13014 Utils.Extend = function (ChildClass, SuperClass) { 13015 var __hasProp = {}.hasOwnProperty; 13016 13017 function BaseConstructor () { 13018 this.constructor = ChildClass; 13019 } 13020 13021 for (var key in SuperClass) { 13022 if (__hasProp.call(SuperClass, key)) { 13023 ChildClass[key] = SuperClass[key]; 13024 } 13025 } 13026 13027 BaseConstructor.prototype = SuperClass.prototype; 13028 ChildClass.prototype = new BaseConstructor(); 13029 ChildClass.__super__ = SuperClass.prototype; 13030 13031 return ChildClass; 13032 }; 13033 13034 function getMethods (theClass) { 13035 var proto = theClass.prototype; 13036 13037 var methods = []; 13038 13039 for (var methodName in proto) { 13040 var m = proto[methodName]; 13041 13042 if (typeof m !== 'function') { 13043 continue; 13044 } 13045 13046 if (methodName === 'constructor') { 13047 continue; 13048 } 13049 13050 methods.push(methodName); 13051 } 13052 13053 return methods; 13054 } 13055 13056 Utils.Decorate = function (SuperClass, DecoratorClass) { 13057 var decoratedMethods = getMethods(DecoratorClass); 13058 var superMethods = getMethods(SuperClass); 13059 13060 function DecoratedClass () { 13061 var unshift = Array.prototype.unshift; 13062 13063 var argCount = DecoratorClass.prototype.constructor.length; 13064 13065 var calledConstructor = SuperClass.prototype.constructor; 13066 13067 if (argCount > 0) { 13068 unshift.call(arguments, SuperClass.prototype.constructor); 13069 13070 calledConstructor = DecoratorClass.prototype.constructor; 13071 } 13072 13073 calledConstructor.apply(this, arguments); 13074 } 13075 13076 DecoratorClass.displayName = SuperClass.displayName; 13077 13078 function ctr () { 13079 this.constructor = DecoratedClass; 13080 } 13081 13082 DecoratedClass.prototype = new ctr(); 13083 13084 for (var m = 0; m < superMethods.length; m++) { 13085 var superMethod = superMethods[m]; 13086 13087 DecoratedClass.prototype[superMethod] = 13088 SuperClass.prototype[superMethod]; 13089 } 13090 13091 var calledMethod = function (methodName) { 13092 // Stub out the original method if it's not decorating an actual method 13093 var originalMethod = function () {}; 13094 13095 if (methodName in DecoratedClass.prototype) { 13096 originalMethod = DecoratedClass.prototype[methodName]; 13097 } 13098 13099 var decoratedMethod = DecoratorClass.prototype[methodName]; 13100 13101 return function () { 13102 var unshift = Array.prototype.unshift; 13103 13104 unshift.call(arguments, originalMethod); 13105 13106 return decoratedMethod.apply(this, arguments); 13107 }; 13108 }; 13109 13110 for (var d = 0; d < decoratedMethods.length; d++) { 13111 var decoratedMethod = decoratedMethods[d]; 13112 13113 DecoratedClass.prototype[decoratedMethod] = calledMethod(decoratedMethod); 13114 } 13115 13116 return DecoratedClass; 13117 }; 13118 13119 var Observable = function () { 13120 this.listeners = {}; 13121 }; 13122 13123 Observable.prototype.on = function (event, callback) { 13124 this.listeners = this.listeners || {}; 13125 13126 if (event in this.listeners) { 13127 this.listeners[event].push(callback); 13128 } else { 13129 this.listeners[event] = [callback]; 13130 } 13131 }; 13132 13133 Observable.prototype.trigger = function (event) { 13134 var slice = Array.prototype.slice; 13135 13136 this.listeners = this.listeners || {}; 13137 13138 if (event in this.listeners) { 13139 this.invoke(this.listeners[event], slice.call(arguments, 1)); 13140 } 13141 13142 if ('*' in this.listeners) { 13143 this.invoke(this.listeners['*'], arguments); 13144 } 13145 }; 13146 13147 Observable.prototype.invoke = function (listeners, params) { 13148 for (var i = 0, len = listeners.length; i < len; i++) { 13149 listeners[i].apply(this, params); 13150 } 13151 }; 13152 13153 Utils.Observable = Observable; 13154 13155 Utils.generateChars = function (length) { 13156 var chars = ''; 13157 13158 for (var i = 0; i < length; i++) { 13159 var randomChar = Math.floor(Math.random() * 36); 13160 chars += randomChar.toString(36); 13161 } 13162 13163 return chars; 13164 }; 13165 13166 Utils.bind = function (func, context) { 13167 return function () { 13168 func.apply(context, arguments); 13169 }; 13170 }; 13171 13172 Utils._convertData = function (data) { 13173 for (var originalKey in data) { 13174 var keys = originalKey.split('-'); 13175 13176 var dataLevel = data; 13177 13178 if (keys.length === 1) { 13179 continue; 13180 } 13181 13182 for (var k = 0; k < keys.length; k++) { 13183 var key = keys[k]; 13184 13185 // Lowercase the first letter 13186 // By default, dash-separated becomes camelCase 13187 key = key.substring(0, 1).toLowerCase() + key.substring(1); 13188 13189 if (!(key in dataLevel)) { 13190 dataLevel[key] = {}; 13191 } 13192 13193 if (k == keys.length - 1) { 13194 dataLevel[key] = data[originalKey]; 13195 } 13196 13197 dataLevel = dataLevel[key]; 13198 } 13199 13200 delete data[originalKey]; 13201 } 13202 13203 return data; 13204 }; 13205 13206 Utils.hasScroll = function (index, el) { 13207 // Adapted from the function created by @ShadowScripter 13208 // and adapted by @BillBarry on the Stack Exchange Code Review website. 13209 // The original code can be found at 13210 // http://codereview.stackexchange.com/q/13338 13211 // and was designed to be used with the Sizzle selector engine. 13212 13213 var $el = $(el); 13214 var overflowX = el.style.overflowX; 13215 var overflowY = el.style.overflowY; 13216 13217 //Check both x and y declarations 13218 if (overflowX === overflowY && 13219 (overflowY === 'hidden' || overflowY === 'visible')) { 13220 return false; 13221 } 13222 13223 if (overflowX === 'scroll' || overflowY === 'scroll') { 13224 return true; 13225 } 13226 13227 return ($el.innerHeight() < el.scrollHeight || 13228 $el.innerWidth() < el.scrollWidth); 13229 }; 13230 13231 Utils.escapeMarkup = function (markup) { 13232 var replaceMap = { 13233 '\\': '\', 13234 '&': '&', 13235 '<': '<', 13236 '>': '>', 13237 '"': '"', 13238 '\'': ''', 13239 '/': '/' 13240 }; 13241 13242 // Do not try to escape the markup if it's not a string 13243 if (typeof markup !== 'string') { 13244 return markup; 13245 } 13246 13247 return String(markup).replace(/[&<>"'\/\\]/g, function (match) { 13248 return replaceMap[match]; 13249 }); 13250 }; 13251 13252 // Append an array of jQuery nodes to a given element. 13253 Utils.appendMany = function ($element, $nodes) { 13254 // jQuery 1.7.x does not support $.fn.append() with an array 13255 // Fall back to a jQuery object collection using $.fn.add() 13256 if ($.fn.jquery.substr(0, 3) === '1.7') { 13257 var $jqNodes = $(); 13258 13259 $.map($nodes, function (node) { 13260 $jqNodes = $jqNodes.add(node); 13261 }); 13262 13263 $nodes = $jqNodes; 13264 } 13265 13266 $element.append($nodes); 13267 }; 13268 13269 return Utils; 13270}); 13271 13272S2.define('select2/results',[ 13273 'jquery', 13274 './utils' 13275], function ($, Utils) { 13276 function Results ($element, options, dataAdapter) { 13277 this.$element = $element; 13278 this.data = dataAdapter; 13279 this.options = options; 13280 13281 Results.__super__.constructor.call(this); 13282 } 13283 13284 Utils.Extend(Results, Utils.Observable); 13285 13286 Results.prototype.render = function () { 13287 var $results = $( 13288 '<ul class="select2-results__options" role="tree"></ul>' 13289 ); 13290 13291 if (this.options.get('multiple')) { 13292 $results.attr('aria-multiselectable', 'true'); 13293 } 13294 13295 this.$results = $results; 13296 13297 return $results; 13298 }; 13299 13300 Results.prototype.clear = function () { 13301 this.$results.empty(); 13302 }; 13303 13304 Results.prototype.displayMessage = function (params) { 13305 var escapeMarkup = this.options.get('escapeMarkup'); 13306 13307 this.clear(); 13308 this.hideLoading(); 13309 13310 var $message = $( 13311 '<li role="treeitem" aria-live="assertive"' + 13312 ' class="select2-results__option"></li>' 13313 ); 13314 13315 var message = this.options.get('translations').get(params.message); 13316 13317 $message.append( 13318 escapeMarkup( 13319 message(params.args) 13320 ) 13321 ); 13322 13323 $message[0].className += ' select2-results__message'; 13324 13325 this.$results.append($message); 13326 }; 13327 13328 Results.prototype.hideMessages = function () { 13329 this.$results.find('.select2-results__message').remove(); 13330 }; 13331 13332 Results.prototype.append = function (data) { 13333 this.hideLoading(); 13334 13335 var $options = []; 13336 13337 if (data.results == null || data.results.length === 0) { 13338 if (this.$results.children().length === 0) { 13339 this.trigger('results:message', { 13340 message: 'noResults' 13341 }); 13342 } 13343 13344 return; 13345 } 13346 13347 data.results = this.sort(data.results); 13348 13349 for (var d = 0; d < data.results.length; d++) { 13350 var item = data.results[d]; 13351 13352 var $option = this.option(item); 13353 13354 $options.push($option); 13355 } 13356 13357 this.$results.append($options); 13358 }; 13359 13360 Results.prototype.position = function ($results, $dropdown) { 13361 var $resultsContainer = $dropdown.find('.select2-results'); 13362 $resultsContainer.append($results); 13363 }; 13364 13365 Results.prototype.sort = function (data) { 13366 var sorter = this.options.get('sorter'); 13367 13368 return sorter(data); 13369 }; 13370 13371 Results.prototype.setClasses = function () { 13372 var self = this; 13373 13374 this.data.current(function (selected) { 13375 var selectedIds = $.map(selected, function (s) { 13376 return s.id.toString(); 13377 }); 13378 13379 var $options = self.$results 13380 .find('.select2-results__option[aria-selected]'); 13381 13382 $options.each(function () { 13383 var $option = $(this); 13384 13385 var item = $.data(this, 'data'); 13386 13387 // id needs to be converted to a string when comparing 13388 var id = '' + item.id; 13389 13390 if ((item.element != null && item.element.selected) || 13391 (item.element == null && $.inArray(id, selectedIds) > -1)) { 13392 $option.attr('aria-selected', 'true'); 13393 } else { 13394 $option.attr('aria-selected', 'false'); 13395 } 13396 }); 13397 13398 var $selected = $options.filter('[aria-selected=true]'); 13399 13400 // Check if there are any selected options 13401 if ($selected.length > 0) { 13402 // If there are selected options, highlight the first 13403 $selected.first().trigger('mouseenter'); 13404 } else { 13405 // If there are no selected options, highlight the first option 13406 // in the dropdown 13407 $options.first().trigger('mouseenter'); 13408 } 13409 }); 13410 }; 13411 13412 Results.prototype.showLoading = function (params) { 13413 this.hideLoading(); 13414 13415 var loadingMore = this.options.get('translations').get('searching'); 13416 13417 var loading = { 13418 disabled: true, 13419 loading: true, 13420 text: loadingMore(params) 13421 }; 13422 var $loading = this.option(loading); 13423 $loading.className += ' loading-results'; 13424 13425 this.$results.prepend($loading); 13426 }; 13427 13428 Results.prototype.hideLoading = function () { 13429 this.$results.find('.loading-results').remove(); 13430 }; 13431 13432 Results.prototype.option = function (data) { 13433 var option = document.createElement('li'); 13434 option.className = 'select2-results__option'; 13435 13436 var attrs = { 13437 'role': 'treeitem', 13438 'aria-selected': 'false' 13439 }; 13440 13441 if (data.disabled) { 13442 delete attrs['aria-selected']; 13443 attrs['aria-disabled'] = 'true'; 13444 } 13445 13446 if (data.id == null) { 13447 delete attrs['aria-selected']; 13448 } 13449 13450 if (data._resultId != null) { 13451 option.id = data._resultId; 13452 } 13453 13454 if (data.title) { 13455 option.title = data.title; 13456 } 13457 13458 if (data.children) { 13459 attrs.role = 'group'; 13460 attrs['aria-label'] = data.text; 13461 delete attrs['aria-selected']; 13462 } 13463 13464 for (var attr in attrs) { 13465 var val = attrs[attr]; 13466 13467 option.setAttribute(attr, val); 13468 } 13469 13470 if (data.children) { 13471 var $option = $(option); 13472 13473 var label = document.createElement('strong'); 13474 label.className = 'select2-results__group'; 13475 13476 var $label = $(label); 13477 this.template(data, label); 13478 13479 var $children = []; 13480 13481 for (var c = 0; c < data.children.length; c++) { 13482 var child = data.children[c]; 13483 13484 var $child = this.option(child); 13485 13486 $children.push($child); 13487 } 13488 13489 var $childrenContainer = $('<ul></ul>', { 13490 'class': 'select2-results__options select2-results__options--nested' 13491 }); 13492 13493 $childrenContainer.append($children); 13494 13495 $option.append(label); 13496 $option.append($childrenContainer); 13497 } else { 13498 this.template(data, option); 13499 } 13500 13501 $.data(option, 'data', data); 13502 13503 return option; 13504 }; 13505 13506 Results.prototype.bind = function (container, $container) { 13507 var self = this; 13508 13509 var id = container.id + '-results'; 13510 13511 this.$results.attr('id', id); 13512 13513 container.on('results:all', function (params) { 13514 self.clear(); 13515 self.append(params.data); 13516 13517 if (container.isOpen()) { 13518 self.setClasses(); 13519 } 13520 }); 13521 13522 container.on('results:append', function (params) { 13523 self.append(params.data); 13524 13525 if (container.isOpen()) { 13526 self.setClasses(); 13527 } 13528 }); 13529 13530 container.on('query', function (params) { 13531 self.hideMessages(); 13532 self.showLoading(params); 13533 }); 13534 13535 container.on('select', function () { 13536 if (!container.isOpen()) { 13537 return; 13538 } 13539 13540 self.setClasses(); 13541 }); 13542 13543 container.on('unselect', function () { 13544 if (!container.isOpen()) { 13545 return; 13546 } 13547 13548 self.setClasses(); 13549 }); 13550 13551 container.on('open', function () { 13552 // When the dropdown is open, aria-expended="true" 13553 self.$results.attr('aria-expanded', 'true'); 13554 self.$results.attr('aria-hidden', 'false'); 13555 13556 self.setClasses(); 13557 self.ensureHighlightVisible(); 13558 }); 13559 13560 container.on('close', function () { 13561 // When the dropdown is closed, aria-expended="false" 13562 self.$results.attr('aria-expanded', 'false'); 13563 self.$results.attr('aria-hidden', 'true'); 13564 self.$results.removeAttr('aria-activedescendant'); 13565 }); 13566 13567 container.on('results:toggle', function () { 13568 var $highlighted = self.getHighlightedResults(); 13569 13570 if ($highlighted.length === 0) { 13571 return; 13572 } 13573 13574 $highlighted.trigger('mouseup'); 13575 }); 13576 13577 container.on('results:select', function () { 13578 var $highlighted = self.getHighlightedResults(); 13579 13580 if ($highlighted.length === 0) { 13581 return; 13582 } 13583 13584 var data = $highlighted.data('data'); 13585 13586 if ($highlighted.attr('aria-selected') == 'true') { 13587 self.trigger('close', {}); 13588 } else { 13589 self.trigger('select', { 13590 data: data 13591 }); 13592 } 13593 }); 13594 13595 container.on('results:previous', function () { 13596 var $highlighted = self.getHighlightedResults(); 13597 13598 var $options = self.$results.find('[aria-selected]'); 13599 13600 var currentIndex = $options.index($highlighted); 13601 13602 // If we are already at te top, don't move further 13603 if (currentIndex === 0) { 13604 return; 13605 } 13606 13607 var nextIndex = currentIndex - 1; 13608 13609 // If none are highlighted, highlight the first 13610 if ($highlighted.length === 0) { 13611 nextIndex = 0; 13612 } 13613 13614 var $next = $options.eq(nextIndex); 13615 13616 $next.trigger('mouseenter'); 13617 13618 var currentOffset = self.$results.offset().top; 13619 var nextTop = $next.offset().top; 13620 var nextOffset = self.$results.scrollTop() + (nextTop - currentOffset); 13621 13622 if (nextIndex === 0) { 13623 self.$results.scrollTop(0); 13624 } else if (nextTop - currentOffset < 0) { 13625 self.$results.scrollTop(nextOffset); 13626 } 13627 }); 13628 13629 container.on('results:next', function () { 13630 var $highlighted = self.getHighlightedResults(); 13631 13632 var $options = self.$results.find('[aria-selected]'); 13633 13634 var currentIndex = $options.index($highlighted); 13635 13636 var nextIndex = currentIndex + 1; 13637 13638 // If we are at the last option, stay there 13639 if (nextIndex >= $options.length) { 13640 return; 13641 } 13642 13643 var $next = $options.eq(nextIndex); 13644 13645 $next.trigger('mouseenter'); 13646 13647 var currentOffset = self.$results.offset().top + 13648 self.$results.outerHeight(false); 13649 var nextBottom = $next.offset().top + $next.outerHeight(false); 13650 var nextOffset = self.$results.scrollTop() + nextBottom - currentOffset; 13651 13652 if (nextIndex === 0) { 13653 self.$results.scrollTop(0); 13654 } else if (nextBottom > currentOffset) { 13655 self.$results.scrollTop(nextOffset); 13656 } 13657 }); 13658 13659 container.on('results:focus', function (params) { 13660 params.element.addClass('select2-results__option--highlighted'); 13661 }); 13662 13663 container.on('results:message', function (params) { 13664 self.displayMessage(params); 13665 }); 13666 13667 if ($.fn.mousewheel) { 13668 // this.$results.on('mousewheel', function (e) { 13669 // var top = self.$results.scrollTop(); 13670 // 13671 // var bottom = ( 13672 // self.$results.get(0).scrollHeight - 13673 // self.$results.scrollTop() + 13674 // e.deltaY 13675 // ); 13676 // 13677 // var isAtTop = e.deltaY > 0 && top - e.deltaY <= 0; 13678 // var isAtBottom = e.deltaY < 0 && bottom <= self.$results.height(); 13679 // 13680 // if (isAtTop) { 13681 // self.$results.scrollTop(0); 13682 // 13683 // e.preventDefault(); 13684 // e.stopPropagation(); 13685 // } else if (isAtBottom) { 13686 // self.$results.scrollTop( 13687 // self.$results.get(0).scrollHeight - self.$results.height() 13688 // ); 13689 // 13690 // e.preventDefault(); 13691 // e.stopPropagation(); 13692 // } 13693 // }); 13694 } 13695 13696 this.$results.on('mouseup', '.select2-results__option[aria-selected]', 13697 function (evt) { 13698 var $this = $(this); 13699 13700 var data = $this.data('data'); 13701 13702 if ($this.attr('aria-selected') === 'true') { 13703 if (self.options.get('multiple')) { 13704 self.trigger('unselect', { 13705 originalEvent: evt, 13706 data: data 13707 }); 13708 } else { 13709 self.trigger('close', {}); 13710 } 13711 13712 return; 13713 } 13714 13715 self.trigger('select', { 13716 originalEvent: evt, 13717 data: data 13718 }); 13719 }); 13720 13721 this.$results.on('mouseenter', '.select2-results__option[aria-selected]', 13722 function (evt) { 13723 var data = $(this).data('data'); 13724 13725 self.getHighlightedResults() 13726 .removeClass('select2-results__option--highlighted'); 13727 13728 self.trigger('results:focus', { 13729 data: data, 13730 element: $(this) 13731 }); 13732 }); 13733 }; 13734 13735 Results.prototype.getHighlightedResults = function () { 13736 var $highlighted = this.$results 13737 .find('.select2-results__option--highlighted'); 13738 13739 return $highlighted; 13740 }; 13741 13742 Results.prototype.destroy = function () { 13743 this.$results.remove(); 13744 }; 13745 13746 Results.prototype.ensureHighlightVisible = function () { 13747 var $highlighted = this.getHighlightedResults(); 13748 13749 if ($highlighted.length === 0) { 13750 return; 13751 } 13752 13753 var $options = this.$results.find('[aria-selected]'); 13754 13755 var currentIndex = $options.index($highlighted); 13756 13757 var currentOffset = this.$results.offset().top; 13758 var nextTop = $highlighted.offset().top; 13759 var nextOffset = this.$results.scrollTop() + (nextTop - currentOffset); 13760 13761 var offsetDelta = nextTop - currentOffset; 13762 nextOffset -= $highlighted.outerHeight(false) * 2; 13763 13764 if (currentIndex <= 2) { 13765 this.$results.scrollTop(0); 13766 } else if (offsetDelta > this.$results.outerHeight() || offsetDelta < 0) { 13767 this.$results.scrollTop(nextOffset); 13768 } 13769 }; 13770 13771 Results.prototype.template = function (result, container) { 13772 var template = this.options.get('templateResult'); 13773 var escapeMarkup = this.options.get('escapeMarkup'); 13774 13775 var content = template(result, container); 13776 13777 if (content == null) { 13778 container.style.display = 'none'; 13779 } else if (typeof content === 'string') { 13780 container.innerHTML = escapeMarkup(content); 13781 } else { 13782 $(container).append(content); 13783 } 13784 }; 13785 13786 return Results; 13787}); 13788 13789S2.define('select2/keys',[ 13790 13791], function () { 13792 var KEYS = { 13793 BACKSPACE: 8, 13794 TAB: 9, 13795 ENTER: 13, 13796 SHIFT: 16, 13797 CTRL: 17, 13798 ALT: 18, 13799 ESC: 27, 13800 SPACE: 32, 13801 PAGE_UP: 33, 13802 PAGE_DOWN: 34, 13803 END: 35, 13804 HOME: 36, 13805 LEFT: 37, 13806 UP: 38, 13807 RIGHT: 39, 13808 DOWN: 40, 13809 DELETE: 46 13810 }; 13811 13812 return KEYS; 13813}); 13814 13815S2.define('select2/selection/base',[ 13816 'jquery', 13817 '../utils', 13818 '../keys' 13819], function ($, Utils, KEYS) { 13820 function BaseSelection ($element, options) { 13821 this.$element = $element; 13822 this.options = options; 13823 13824 BaseSelection.__super__.constructor.call(this); 13825 } 13826 13827 Utils.Extend(BaseSelection, Utils.Observable); 13828 13829 BaseSelection.prototype.render = function () { 13830 var $selection = $( 13831 '<span class="select2-selection" role="combobox" ' + 13832 ' aria-haspopup="true" aria-expanded="false">' + 13833 '</span>' 13834 ); 13835 13836 this._tabindex = 0; 13837 13838 if (this.$element.data('old-tabindex') != null) { 13839 this._tabindex = this.$element.data('old-tabindex'); 13840 } else if (this.$element.attr('tabindex') != null) { 13841 this._tabindex = this.$element.attr('tabindex'); 13842 } 13843 13844 $selection.attr('title', this.$element.attr('title')); 13845 $selection.attr('tabindex', this._tabindex); 13846 13847 this.$selection = $selection; 13848 13849 return $selection; 13850 }; 13851 13852 BaseSelection.prototype.bind = function (container, $container) { 13853 var self = this; 13854 13855 var id = container.id + '-container'; 13856 var resultsId = container.id + '-results'; 13857 13858 this.container = container; 13859 13860 this.$selection.on('focus', function (evt) { 13861 self.trigger('focus', evt); 13862 }); 13863 13864 this.$selection.on('blur', function (evt) { 13865 self._handleBlur(evt); 13866 }); 13867 13868 this.$selection.on('keydown', function (evt) { 13869 self.trigger('keypress', evt); 13870 13871 if (evt.which === KEYS.SPACE) { 13872 evt.preventDefault(); 13873 } 13874 }); 13875 13876 container.on('results:focus', function (params) { 13877 self.$selection.attr('aria-activedescendant', params.data._resultId); 13878 }); 13879 13880 container.on('selection:update', function (params) { 13881 self.update(params.data); 13882 }); 13883 13884 container.on('open', function () { 13885 // When the dropdown is open, aria-expanded="true" 13886 self.$selection.attr('aria-expanded', 'true'); 13887 self.$selection.attr('aria-owns', resultsId); 13888 13889 self._attachCloseHandler(container); 13890 }); 13891 13892 container.on('close', function () { 13893 // When the dropdown is closed, aria-expanded="false" 13894 self.$selection.attr('aria-expanded', 'false'); 13895 self.$selection.removeAttr('aria-activedescendant'); 13896 self.$selection.removeAttr('aria-owns'); 13897 13898 self.$selection.focus(); 13899 13900 self._detachCloseHandler(container); 13901 }); 13902 13903 container.on('enable', function () { 13904 self.$selection.attr('tabindex', self._tabindex); 13905 }); 13906 13907 container.on('disable', function () { 13908 self.$selection.attr('tabindex', '-1'); 13909 }); 13910 }; 13911 13912 BaseSelection.prototype._handleBlur = function (evt) { 13913 var self = this; 13914 13915 // This needs to be delayed as the active element is the body when the tab 13916 // key is pressed, possibly along with others. 13917 window.setTimeout(function () { 13918 // Don't trigger `blur` if the focus is still in the selection 13919 if ( 13920 (document.activeElement == self.$selection[0]) || 13921 ($.contains(self.$selection[0], document.activeElement)) 13922 ) { 13923 return; 13924 } 13925 13926 self.trigger('blur', evt); 13927 }, 1); 13928 }; 13929 13930 BaseSelection.prototype._attachCloseHandler = function (container) { 13931 var self = this; 13932 13933 $(document.body).on('mousedown.select2.' + container.id, function (e) { 13934 var $target = $(e.target); 13935 13936 var $select = $target.closest('.select2'); 13937 13938 var $all = $('.select2.select2-container--open'); 13939 13940 $all.each(function () { 13941 var $this = $(this); 13942 13943 if (this == $select[0]) { 13944 return; 13945 } 13946 13947 var $element = $this.data('element'); 13948 13949 $element.select2('close'); 13950 }); 13951 }); 13952 }; 13953 13954 BaseSelection.prototype._detachCloseHandler = function (container) { 13955 $(document.body).off('mousedown.select2.' + container.id); 13956 }; 13957 13958 BaseSelection.prototype.position = function ($selection, $container) { 13959 var $selectionContainer = $container.find('.selection'); 13960 $selectionContainer.append($selection); 13961 }; 13962 13963 BaseSelection.prototype.destroy = function () { 13964 this._detachCloseHandler(this.container); 13965 }; 13966 13967 BaseSelection.prototype.update = function (data) { 13968 throw new Error('The `update` method must be defined in child classes.'); 13969 }; 13970 13971 return BaseSelection; 13972}); 13973 13974S2.define('select2/selection/single',[ 13975 'jquery', 13976 './base', 13977 '../utils', 13978 '../keys' 13979], function ($, BaseSelection, Utils, KEYS) { 13980 function SingleSelection () { 13981 SingleSelection.__super__.constructor.apply(this, arguments); 13982 } 13983 13984 Utils.Extend(SingleSelection, BaseSelection); 13985 13986 SingleSelection.prototype.render = function () { 13987 var $selection = SingleSelection.__super__.render.call(this); 13988 13989 $selection.addClass('select2-selection--single'); 13990 13991 $selection.html( 13992 '<span class="select2-selection__rendered"></span>' + 13993 '<span class="select2-selection__arrow" role="presentation">' + 13994 '<b role="presentation"></b>' + 13995 '</span>' 13996 ); 13997 13998 return $selection; 13999 }; 14000 14001 SingleSelection.prototype.bind = function (container, $container) { 14002 var self = this; 14003 14004 SingleSelection.__super__.bind.apply(this, arguments); 14005 14006 var id = container.id + '-container'; 14007 14008 this.$selection.find('.select2-selection__rendered').attr('id', id); 14009 this.$selection.attr('aria-labelledby', id); 14010 14011 this.$selection.on('mousedown', function (evt) { 14012 // Only respond to left clicks 14013 if (evt.which !== 1) { 14014 return; 14015 } 14016 14017 self.trigger('toggle', { 14018 originalEvent: evt 14019 }); 14020 }); 14021 14022 this.$selection.on('focus', function (evt) { 14023 // User focuses on the container 14024 }); 14025 14026 this.$selection.on('blur', function (evt) { 14027 // User exits the container 14028 }); 14029 14030 container.on('selection:update', function (params) { 14031 self.update(params.data); 14032 }); 14033 }; 14034 14035 SingleSelection.prototype.clear = function () { 14036 this.$selection.find('.select2-selection__rendered').empty(); 14037 }; 14038 14039 SingleSelection.prototype.display = function (data, container) { 14040 var template = this.options.get('templateSelection'); 14041 var escapeMarkup = this.options.get('escapeMarkup'); 14042 14043 return escapeMarkup(template(data, container)); 14044 }; 14045 14046 SingleSelection.prototype.selectionContainer = function () { 14047 return $('<span></span>'); 14048 }; 14049 14050 SingleSelection.prototype.update = function (data) { 14051 if (data.length === 0) { 14052 this.clear(); 14053 return; 14054 } 14055 14056 var selection = data[0]; 14057 14058 var $rendered = this.$selection.find('.select2-selection__rendered'); 14059 var formatted = this.display(selection, $rendered); 14060 14061 $rendered.empty().append(formatted); 14062 $rendered.prop('title', selection.title || selection.text); 14063 }; 14064 14065 return SingleSelection; 14066}); 14067 14068S2.define('select2/selection/multiple',[ 14069 'jquery', 14070 './base', 14071 '../utils' 14072], function ($, BaseSelection, Utils) { 14073 function MultipleSelection ($element, options) { 14074 MultipleSelection.__super__.constructor.apply(this, arguments); 14075 } 14076 14077 Utils.Extend(MultipleSelection, BaseSelection); 14078 14079 MultipleSelection.prototype.render = function () { 14080 var $selection = MultipleSelection.__super__.render.call(this); 14081 14082 $selection.addClass('select2-selection--multiple'); 14083 14084 $selection.html( 14085 '<ul class="select2-selection__rendered"></ul>' 14086 ); 14087 14088 return $selection; 14089 }; 14090 14091 MultipleSelection.prototype.bind = function (container, $container) { 14092 var self = this; 14093 14094 MultipleSelection.__super__.bind.apply(this, arguments); 14095 14096 this.$selection.on('click', function (evt) { 14097 self.trigger('toggle', { 14098 originalEvent: evt 14099 }); 14100 }); 14101 14102 this.$selection.on( 14103 'click', 14104 '.select2-selection__choice__remove', 14105 function (evt) { 14106 // Ignore the event if it is disabled 14107 if (self.options.get('disabled')) { 14108 return; 14109 } 14110 14111 var $remove = $(this); 14112 var $selection = $remove.parent(); 14113 14114 var data = $selection.data('data'); 14115 14116 self.trigger('unselect', { 14117 originalEvent: evt, 14118 data: data 14119 }); 14120 } 14121 ); 14122 }; 14123 14124 MultipleSelection.prototype.clear = function () { 14125 this.$selection.find('.select2-selection__rendered').empty(); 14126 }; 14127 14128 MultipleSelection.prototype.display = function (data, container) { 14129 var template = this.options.get('templateSelection'); 14130 var escapeMarkup = this.options.get('escapeMarkup'); 14131 14132 return escapeMarkup(template(data, container)); 14133 }; 14134 14135 MultipleSelection.prototype.selectionContainer = function () { 14136 var $container = $( 14137 '<li class="select2-selection__choice">' + 14138 '<span class="select2-selection__choice__remove" role="presentation">' + 14139 '×' + 14140 '</span>' + 14141 '</li>' 14142 ); 14143 14144 return $container; 14145 }; 14146 14147 MultipleSelection.prototype.update = function (data) { 14148 this.clear(); 14149 14150 if (data.length === 0) { 14151 return; 14152 } 14153 14154 var $selections = []; 14155 14156 for (var d = 0; d < data.length; d++) { 14157 var selection = data[d]; 14158 14159 var $selection = this.selectionContainer(); 14160 var formatted = this.display(selection, $selection); 14161 14162 $selection.append(formatted); 14163 $selection.prop('title', selection.title || selection.text); 14164 14165 $selection.data('data', selection); 14166 14167 $selections.push($selection); 14168 } 14169 14170 var $rendered = this.$selection.find('.select2-selection__rendered'); 14171 14172 Utils.appendMany($rendered, $selections); 14173 }; 14174 14175 return MultipleSelection; 14176}); 14177 14178S2.define('select2/selection/placeholder',[ 14179 '../utils' 14180], function (Utils) { 14181 function Placeholder (decorated, $element, options) { 14182 this.placeholder = this.normalizePlaceholder(options.get('placeholder')); 14183 14184 decorated.call(this, $element, options); 14185 } 14186 14187 Placeholder.prototype.normalizePlaceholder = function (_, placeholder) { 14188 if (typeof placeholder === 'string') { 14189 placeholder = { 14190 id: '', 14191 text: placeholder 14192 }; 14193 } 14194 14195 return placeholder; 14196 }; 14197 14198 Placeholder.prototype.createPlaceholder = function (decorated, placeholder) { 14199 var $placeholder = this.selectionContainer(); 14200 14201 $placeholder.html(this.display(placeholder)); 14202 $placeholder.addClass('select2-selection__placeholder') 14203 .removeClass('select2-selection__choice'); 14204 14205 return $placeholder; 14206 }; 14207 14208 Placeholder.prototype.update = function (decorated, data) { 14209 var singlePlaceholder = ( 14210 data.length == 1 && data[0].id != this.placeholder.id 14211 ); 14212 var multipleSelections = data.length > 1; 14213 14214 if (multipleSelections || singlePlaceholder) { 14215 return decorated.call(this, data); 14216 } 14217 14218 this.clear(); 14219 14220 var $placeholder = this.createPlaceholder(this.placeholder); 14221 14222 this.$selection.find('.select2-selection__rendered').append($placeholder); 14223 }; 14224 14225 return Placeholder; 14226}); 14227 14228S2.define('select2/selection/allowClear',[ 14229 'jquery', 14230 '../keys' 14231], function ($, KEYS) { 14232 function AllowClear () { } 14233 14234 AllowClear.prototype.bind = function (decorated, container, $container) { 14235 var self = this; 14236 14237 decorated.call(this, container, $container); 14238 14239 if (this.placeholder == null) { 14240 if (this.options.get('debug') && window.console && console.error) { 14241 console.error( 14242 'Select2: The `allowClear` option should be used in combination ' + 14243 'with the `placeholder` option.' 14244 ); 14245 } 14246 } 14247 14248 this.$selection.on('mousedown', '.select2-selection__clear', 14249 function (evt) { 14250 self._handleClear(evt); 14251 }); 14252 14253 container.on('keypress', function (evt) { 14254 self._handleKeyboardClear(evt, container); 14255 }); 14256 }; 14257 14258 AllowClear.prototype._handleClear = function (_, evt) { 14259 // Ignore the event if it is disabled 14260 if (this.options.get('disabled')) { 14261 return; 14262 } 14263 14264 var $clear = this.$selection.find('.select2-selection__clear'); 14265 14266 // Ignore the event if nothing has been selected 14267 if ($clear.length === 0) { 14268 return; 14269 } 14270 14271 evt.stopPropagation(); 14272 14273 var data = $clear.data('data'); 14274 14275 for (var d = 0; d < data.length; d++) { 14276 var unselectData = { 14277 data: data[d] 14278 }; 14279 14280 // Trigger the `unselect` event, so people can prevent it from being 14281 // cleared. 14282 this.trigger('unselect', unselectData); 14283 14284 // If the event was prevented, don't clear it out. 14285 if (unselectData.prevented) { 14286 return; 14287 } 14288 } 14289 14290 this.$element.val(this.placeholder.id).trigger('change'); 14291 14292 this.trigger('toggle', {}); 14293 }; 14294 14295 AllowClear.prototype._handleKeyboardClear = function (_, evt, container) { 14296 if (container.isOpen()) { 14297 return; 14298 } 14299 14300 if (evt.which == KEYS.DELETE || evt.which == KEYS.BACKSPACE) { 14301 this._handleClear(evt); 14302 } 14303 }; 14304 14305 AllowClear.prototype.update = function (decorated, data) { 14306 decorated.call(this, data); 14307 14308 if (this.$selection.find('.select2-selection__placeholder').length > 0 || 14309 data.length === 0) { 14310 return; 14311 } 14312 14313 var $remove = $( 14314 '<span class="select2-selection__clear">' + 14315 '×' + 14316 '</span>' 14317 ); 14318 $remove.data('data', data); 14319 14320 this.$selection.find('.select2-selection__rendered').prepend($remove); 14321 }; 14322 14323 return AllowClear; 14324}); 14325 14326S2.define('select2/selection/search',[ 14327 'jquery', 14328 '../utils', 14329 '../keys' 14330], function ($, Utils, KEYS) { 14331 function Search (decorated, $element, options) { 14332 decorated.call(this, $element, options); 14333 } 14334 14335 Search.prototype.render = function (decorated) { 14336 var $search = $( 14337 '<li class="select2-search select2-search--inline">' + 14338 '<input class="select2-search__field" type="search" tabindex="-1"' + 14339 ' autocomplete="off" autocorrect="off" autocapitalize="off"' + 14340 ' spellcheck="false" role="textbox" aria-autocomplete="list" />' + 14341 '</li>' 14342 ); 14343 14344 this.$searchContainer = $search; 14345 this.$search = $search.find('input'); 14346 14347 var $rendered = decorated.call(this); 14348 14349 this._transferTabIndex(); 14350 14351 return $rendered; 14352 }; 14353 14354 Search.prototype.bind = function (decorated, container, $container) { 14355 var self = this; 14356 14357 decorated.call(this, container, $container); 14358 14359 container.on('open', function () { 14360 self.$search.trigger('focus'); 14361 }); 14362 14363 container.on('close', function () { 14364 self.$search.val(''); 14365 self.$search.removeAttr('aria-activedescendant'); 14366 self.$search.trigger('focus'); 14367 }); 14368 14369 container.on('enable', function () { 14370 self.$search.prop('disabled', false); 14371 14372 self._transferTabIndex(); 14373 }); 14374 14375 container.on('disable', function () { 14376 self.$search.prop('disabled', true); 14377 }); 14378 14379 container.on('focus', function (evt) { 14380 self.$search.trigger('focus'); 14381 }); 14382 14383 container.on('results:focus', function (params) { 14384 self.$search.attr('aria-activedescendant', params.id); 14385 }); 14386 14387 this.$selection.on('focusin', '.select2-search--inline', function (evt) { 14388 self.trigger('focus', evt); 14389 }); 14390 14391 this.$selection.on('focusout', '.select2-search--inline', function (evt) { 14392 self._handleBlur(evt); 14393 }); 14394 14395 this.$selection.on('keydown', '.select2-search--inline', function (evt) { 14396 evt.stopPropagation(); 14397 14398 self.trigger('keypress', evt); 14399 14400 self._keyUpPrevented = evt.isDefaultPrevented(); 14401 14402 var key = evt.which; 14403 14404 if (key === KEYS.BACKSPACE && self.$search.val() === '') { 14405 var $previousChoice = self.$searchContainer 14406 .prev('.select2-selection__choice'); 14407 14408 if ($previousChoice.length > 0) { 14409 var item = $previousChoice.data('data'); 14410 14411 self.searchRemoveChoice(item); 14412 14413 evt.preventDefault(); 14414 }
vendor: 22,668 bytes, lines 14414-15506
14414 14415 } 14416 }); 14417 14418 // Try to detect the IE version should the `documentMode` property that 14419 // is stored on the document. This is only implemented in IE and is 14420 // slightly cleaner than doing a user agent check. 14421 // This property is not available in Edge, but Edge also doesn't have 14422 // this bug. 14423 var msie = document.documentMode; 14424 var disableInputEvents = msie && msie <= 11; 14425 14426 // Workaround for browsers which do not support the `input` event 14427 // This will prevent double-triggering of events for browsers which support 14428 // both the `keyup` and `input` events. 14429 this.$selection.on( 14430 'input.searchcheck', 14431 '.select2-search--inline', 14432 function (evt) { 14433 // IE will trigger the `input` event when a placeholder is used on a 14434 // search box. To get around this issue, we are forced to ignore all 14435 // `input` events in IE and keep using `keyup`. 14436 if (disableInputEvents) { 14437 self.$selection.off('input.search input.searchcheck'); 14438 return; 14439 } 14440 14441 // Unbind the duplicated `keyup` event 14442 self.$selection.off('keyup.search'); 14443 } 14444 ); 14445 14446 this.$selection.on( 14447 'keyup.search input.search', 14448 '.select2-search--inline', 14449 function (evt) { 14450 // IE will trigger the `input` event when a placeholder is used on a 14451 // search box. To get around this issue, we are forced to ignore all 14452 // `input` events in IE and keep using `keyup`. 14453 if (disableInputEvents && evt.type === 'input') { 14454 self.$selection.off('input.search input.searchcheck'); 14455 return; 14456 } 14457 14458 var key = evt.which; 14459 14460 // We can freely ignore events from modifier keys 14461 if (key == KEYS.SHIFT || key == KEYS.CTRL || key == KEYS.ALT) { 14462 return; 14463 } 14464 14465 // Tabbing will be handled during the `keydown` phase 14466 if (key == KEYS.TAB) { 14467 return; 14468 } 14469 14470 self.handleSearch(evt); 14471 } 14472 ); 14473 }; 14474 14475 /** 14476 * This method will transfer the tabindex attribute from the rendered 14477 * selection to the search box. This allows for the search box to be used as 14478 * the primary focus instead of the selection container. 14479 * 14480 * @private 14481 */ 14482 Search.prototype._transferTabIndex = function (decorated) { 14483 this.$search.attr('tabindex', this.$selection.attr('tabindex')); 14484 this.$selection.attr('tabindex', '-1'); 14485 }; 14486 14487 Search.prototype.createPlaceholder = function (decorated, placeholder) { 14488 this.$search.attr('placeholder', placeholder.text); 14489 }; 14490 14491 Search.prototype.update = function (decorated, data) { 14492 var searchHadFocus = this.$search[0] == document.activeElement; 14493 14494 this.$search.attr('placeholder', ''); 14495 14496 decorated.call(this, data); 14497 14498 this.$selection.find('.select2-selection__rendered') 14499 .append(this.$searchContainer); 14500 14501 this.resizeSearch(); 14502 if (searchHadFocus) { 14503 this.$search.focus(); 14504 } 14505 }; 14506 14507 Search.prototype.handleSearch = function () { 14508 this.resizeSearch(); 14509 14510 if (!this._keyUpPrevented) { 14511 var input = this.$search.val(); 14512 14513 this.trigger('query', { 14514 term: input 14515 }); 14516 } 14517 14518 this._keyUpPrevented = false; 14519 }; 14520 14521 Search.prototype.searchRemoveChoice = function (decorated, item) { 14522 this.trigger('unselect', { 14523 data: item 14524 }); 14525 14526 this.$search.val(item.text); 14527 this.handleSearch(); 14528 }; 14529 14530 Search.prototype.resizeSearch = function () { 14531 this.$search.css('width', '25px'); 14532 14533 var width = ''; 14534 14535 if (this.$search.attr('placeholder') !== '') { 14536 width = this.$selection.find('.select2-selection__rendered').innerWidth(); 14537 } else { 14538 var minimumWidth = this.$search.val().length + 1; 14539 14540 width = (minimumWidth * 0.75) + 'em'; 14541 } 14542 14543 this.$search.css('width', width); 14544 }; 14545 14546 return Search; 14547}); 14548 14549S2.define('select2/selection/eventRelay',[ 14550 'jquery' 14551], function ($) { 14552 function EventRelay () { } 14553 14554 EventRelay.prototype.bind = function (decorated, container, $container) { 14555 var self = this; 14556 var relayEvents = [ 14557 'open', 'opening', 14558 'close', 'closing', 14559 'select', 'selecting', 14560 'unselect', 'unselecting' 14561 ]; 14562 14563 var preventableEvents = ['opening', 'closing', 'selecting', 'unselecting']; 14564 14565 decorated.call(this, container, $container); 14566 14567 container.on('*', function (name, params) { 14568 // Ignore events that should not be relayed 14569 if ($.inArray(name, relayEvents) === -1) { 14570 return; 14571 } 14572 14573 // The parameters should always be an object 14574 params = params || {}; 14575 14576 // Generate the jQuery event for the Select2 event 14577 var evt = $.Event('select2:' + name, { 14578 params: params 14579 }); 14580 14581 self.$element.trigger(evt); 14582 14583 // Only handle preventable events if it was one 14584 if ($.inArray(name, preventableEvents) === -1) { 14585 return; 14586 } 14587 14588 params.prevented = evt.isDefaultPrevented(); 14589 }); 14590 }; 14591 14592 return EventRelay; 14593}); 14594 14595S2.define('select2/translation',[ 14596 'jquery', 14597 'require' 14598], function ($, require) { 14599 function Translation (dict) { 14600 this.dict = dict || {}; 14601 } 14602 14603 Translation.prototype.all = function () { 14604 return this.dict; 14605 }; 14606 14607 Translation.prototype.get = function (key) { 14608 return this.dict[key]; 14609 }; 14610 14611 Translation.prototype.extend = function (translation) { 14612 this.dict = $.extend({}, translation.all(), this.dict); 14613 }; 14614 14615 // Static functions 14616 14617 Translation._cache = {}; 14618 14619 Translation.loadPath = function (path) { 14620 if (!(path in Translation._cache)) { 14621 var translations = require(path); 14622 14623 Translation._cache[path] = translations; 14624 } 14625 14626 return new Translation(Translation._cache[path]); 14627 }; 14628 14629 return Translation; 14630}); 14631 14632S2.define('select2/diacritics',[ 14633 14634], function () { 14635 var diacritics = { 14636 '\u24B6': 'A', 14637 '\uFF21': 'A', 14638 '\u00C0': 'A', 14639 '\u00C1': 'A', 14640 '\u00C2': 'A', 14641 '\u1EA6': 'A', 14642 '\u1EA4': 'A', 14643 '\u1EAA': 'A', 14644 '\u1EA8': 'A', 14645 '\u00C3': 'A', 14646 '\u0100': 'A', 14647 '\u0102': 'A', 14648 '\u1EB0': 'A', 14649 '\u1EAE': 'A', 14650 '\u1EB4': 'A', 14651 '\u1EB2': 'A', 14652 '\u0226': 'A', 14653 '\u01E0': 'A', 14654 '\u00C4': 'A', 14655 '\u01DE': 'A', 14656 '\u1EA2': 'A', 14657 '\u00C5': 'A', 14658 '\u01FA': 'A', 14659 '\u01CD': 'A', 14660 '\u0200': 'A', 14661 '\u0202': 'A', 14662 '\u1EA0': 'A', 14663 '\u1EAC': 'A', 14664 '\u1EB6': 'A', 14665 '\u1E00': 'A', 14666 '\u0104': 'A', 14667 '\u023A': 'A', 14668 '\u2C6F': 'A', 14669 '\uA732': 'AA', 14670 '\u00C6': 'AE', 14671 '\u01FC': 'AE', 14672 '\u01E2': 'AE', 14673 '\uA734': 'AO', 14674 '\uA736': 'AU', 14675 '\uA738': 'AV', 14676 '\uA73A': 'AV', 14677 '\uA73C': 'AY', 14678 '\u24B7': 'B', 14679 '\uFF22': 'B', 14680 '\u1E02': 'B', 14681 '\u1E04': 'B', 14682 '\u1E06': 'B', 14683 '\u0243': 'B', 14684 '\u0182': 'B', 14685 '\u0181': 'B', 14686 '\u24B8': 'C', 14687 '\uFF23': 'C', 14688 '\u0106': 'C', 14689 '\u0108': 'C', 14690 '\u010A': 'C', 14691 '\u010C': 'C', 14692 '\u00C7': 'C', 14693 '\u1E08': 'C', 14694 '\u0187': 'C', 14695 '\u023B': 'C', 14696 '\uA73E': 'C', 14697 '\u24B9': 'D', 14698 '\uFF24': 'D', 14699 '\u1E0A': 'D', 14700 '\u010E': 'D', 14701 '\u1E0C': 'D', 14702 '\u1E10': 'D', 14703 '\u1E12': 'D', 14704 '\u1E0E': 'D', 14705 '\u0110': 'D', 14706 '\u018B': 'D', 14707 '\u018A': 'D', 14708 '\u0189': 'D', 14709 '\uA779': 'D', 14710 '\u01F1': 'DZ', 14711 '\u01C4': 'DZ', 14712 '\u01F2': 'Dz', 14713 '\u01C5': 'Dz', 14714 '\u24BA': 'E', 14715 '\uFF25': 'E', 14716 '\u00C8': 'E', 14717 '\u00C9': 'E', 14718 '\u00CA': 'E', 14719 '\u1EC0': 'E', 14720 '\u1EBE': 'E', 14721 '\u1EC4': 'E', 14722 '\u1EC2': 'E', 14723 '\u1EBC': 'E', 14724 '\u0112': 'E', 14725 '\u1E14': 'E', 14726 '\u1E16': 'E', 14727 '\u0114': 'E', 14728 '\u0116': 'E', 14729 '\u00CB': 'E', 14730 '\u1EBA': 'E', 14731 '\u011A': 'E', 14732 '\u0204': 'E', 14733 '\u0206': 'E', 14734 '\u1EB8': 'E', 14735 '\u1EC6': 'E', 14736 '\u0228': 'E', 14737 '\u1E1C': 'E', 14738 '\u0118': 'E', 14739 '\u1E18': 'E', 14740 '\u1E1A': 'E', 14741 '\u0190': 'E', 14742 '\u018E': 'E', 14743 '\u24BB': 'F', 14744 '\uFF26': 'F', 14745 '\u1E1E': 'F', 14746 '\u0191': 'F', 14747 '\uA77B': 'F', 14748 '\u24BC': 'G', 14749 '\uFF27': 'G', 14750 '\u01F4': 'G', 14751 '\u011C': 'G', 14752 '\u1E20': 'G', 14753 '\u011E': 'G', 14754 '\u0120': 'G', 14755 '\u01E6': 'G', 14756 '\u0122': 'G', 14757 '\u01E4': 'G', 14758 '\u0193': 'G', 14759 '\uA7A0': 'G', 14760 '\uA77D': 'G', 14761 '\uA77E': 'G', 14762 '\u24BD': 'H', 14763 '\uFF28': 'H', 14764 '\u0124': 'H', 14765 '\u1E22': 'H', 14766 '\u1E26': 'H', 14767 '\u021E': 'H', 14768 '\u1E24': 'H', 14769 '\u1E28': 'H', 14770 '\u1E2A': 'H', 14771 '\u0126': 'H', 14772 '\u2C67': 'H', 14773 '\u2C75': 'H', 14774 '\uA78D': 'H', 14775 '\u24BE': 'I', 14776 '\uFF29': 'I', 14777 '\u00CC': 'I', 14778 '\u00CD': 'I', 14779 '\u00CE': 'I', 14780 '\u0128': 'I', 14781 '\u012A': 'I', 14782 '\u012C': 'I', 14783 '\u0130': 'I', 14784 '\u00CF': 'I', 14785 '\u1E2E': 'I', 14786 '\u1EC8': 'I', 14787 '\u01CF': 'I', 14788 '\u0208': 'I', 14789 '\u020A': 'I', 14790 '\u1ECA': 'I', 14791 '\u012E': 'I', 14792 '\u1E2C': 'I', 14793 '\u0197': 'I', 14794 '\u24BF': 'J', 14795 '\uFF2A': 'J', 14796 '\u0134': 'J', 14797 '\u0248': 'J', 14798 '\u24C0': 'K', 14799 '\uFF2B': 'K', 14800 '\u1E30': 'K', 14801 '\u01E8': 'K', 14802 '\u1E32': 'K', 14803 '\u0136': 'K', 14804 '\u1E34': 'K', 14805 '\u0198': 'K', 14806 '\u2C69': 'K', 14807 '\uA740': 'K', 14808 '\uA742': 'K', 14809 '\uA744': 'K', 14810 '\uA7A2': 'K', 14811 '\u24C1': 'L', 14812 '\uFF2C': 'L', 14813 '\u013F': 'L', 14814 '\u0139': 'L', 14815 '\u013D': 'L', 14816 '\u1E36': 'L', 14817 '\u1E38': 'L', 14818 '\u013B': 'L', 14819 '\u1E3C': 'L', 14820 '\u1E3A': 'L', 14821 '\u0141': 'L', 14822 '\u023D': 'L', 14823 '\u2C62': 'L', 14824 '\u2C60': 'L', 14825 '\uA748': 'L', 14826 '\uA746': 'L', 14827 '\uA780': 'L', 14828 '\u01C7': 'LJ', 14829 '\u01C8': 'Lj', 14830 '\u24C2': 'M', 14831 '\uFF2D': 'M', 14832 '\u1E3E': 'M', 14833 '\u1E40': 'M', 14834 '\u1E42': 'M', 14835 '\u2C6E': 'M', 14836 '\u019C': 'M', 14837 '\u24C3': 'N', 14838 '\uFF2E': 'N', 14839 '\u01F8': 'N', 14840 '\u0143': 'N', 14841 '\u00D1': 'N', 14842 '\u1E44': 'N', 14843 '\u0147': 'N', 14844 '\u1E46': 'N', 14845 '\u0145': 'N', 14846 '\u1E4A': 'N', 14847 '\u1E48': 'N', 14848 '\u0220': 'N', 14849 '\u019D': 'N', 14850 '\uA790': 'N', 14851 '\uA7A4': 'N', 14852 '\u01CA': 'NJ', 14853 '\u01CB': 'Nj', 14854 '\u24C4': 'O', 14855 '\uFF2F': 'O', 14856 '\u00D2': 'O', 14857 '\u00D3': 'O', 14858 '\u00D4': 'O', 14859 '\u1ED2': 'O', 14860 '\u1ED0': 'O', 14861 '\u1ED6': 'O', 14862 '\u1ED4': 'O', 14863 '\u00D5': 'O', 14864 '\u1E4C': 'O', 14865 '\u022C': 'O', 14866 '\u1E4E': 'O', 14867 '\u014C': 'O', 14868 '\u1E50': 'O', 14869 '\u1E52': 'O', 14870 '\u014E': 'O', 14871 '\u022E': 'O', 14872 '\u0230': 'O', 14873 '\u00D6': 'O', 14874 '\u022A': 'O', 14875 '\u1ECE': 'O', 14876 '\u0150': 'O', 14877 '\u01D1': 'O', 14878 '\u020C': 'O', 14879 '\u020E': 'O', 14880 '\u01A0': 'O', 14881 '\u1EDC': 'O', 14882 '\u1EDA': 'O', 14883 '\u1EE0': 'O', 14884 '\u1EDE': 'O', 14885 '\u1EE2': 'O', 14886 '\u1ECC': 'O', 14887 '\u1ED8': 'O', 14888 '\u01EA': 'O', 14889 '\u01EC': 'O', 14890 '\u00D8': 'O', 14891 '\u01FE': 'O', 14892 '\u0186': 'O', 14893 '\u019F': 'O', 14894 '\uA74A': 'O', 14895 '\uA74C': 'O', 14896 '\u01A2': 'OI', 14897 '\uA74E': 'OO', 14898 '\u0222': 'OU', 14899 '\u24C5': 'P', 14900 '\uFF30': 'P', 14901 '\u1E54': 'P', 14902 '\u1E56': 'P', 14903 '\u01A4': 'P', 14904 '\u2C63': 'P', 14905 '\uA750': 'P', 14906 '\uA752': 'P', 14907 '\uA754': 'P', 14908 '\u24C6': 'Q', 14909 '\uFF31': 'Q', 14910 '\uA756': 'Q', 14911 '\uA758': 'Q', 14912 '\u024A': 'Q', 14913 '\u24C7': 'R', 14914 '\uFF32': 'R', 14915 '\u0154': 'R', 14916 '\u1E58': 'R', 14917 '\u0158': 'R', 14918 '\u0210': 'R', 14919 '\u0212': 'R', 14920 '\u1E5A': 'R', 14921 '\u1E5C': 'R', 14922 '\u0156': 'R', 14923 '\u1E5E': 'R', 14924 '\u024C': 'R', 14925 '\u2C64': 'R', 14926 '\uA75A': 'R', 14927 '\uA7A6': 'R', 14928 '\uA782': 'R', 14929 '\u24C8': 'S', 14930 '\uFF33': 'S', 14931 '\u1E9E': 'S', 14932 '\u015A': 'S', 14933 '\u1E64': 'S', 14934 '\u015C': 'S', 14935 '\u1E60': 'S', 14936 '\u0160': 'S', 14937 '\u1E66': 'S', 14938 '\u1E62': 'S', 14939 '\u1E68': 'S', 14940 '\u0218': 'S', 14941 '\u015E': 'S', 14942 '\u2C7E': 'S', 14943 '\uA7A8': 'S', 14944 '\uA784': 'S', 14945 '\u24C9': 'T', 14946 '\uFF34': 'T', 14947 '\u1E6A': 'T', 14948 '\u0164': 'T', 14949 '\u1E6C': 'T', 14950 '\u021A': 'T', 14951 '\u0162': 'T', 14952 '\u1E70': 'T', 14953 '\u1E6E': 'T', 14954 '\u0166': 'T', 14955 '\u01AC': 'T', 14956 '\u01AE': 'T', 14957 '\u023E': 'T', 14958 '\uA786': 'T', 14959 '\uA728': 'TZ', 14960 '\u24CA': 'U', 14961 '\uFF35': 'U', 14962 '\u00D9': 'U', 14963 '\u00DA': 'U', 14964 '\u00DB': 'U', 14965 '\u0168': 'U', 14966 '\u1E78': 'U', 14967 '\u016A': 'U', 14968 '\u1E7A': 'U', 14969 '\u016C': 'U', 14970 '\u00DC': 'U', 14971 '\u01DB': 'U', 14972 '\u01D7': 'U', 14973 '\u01D5': 'U', 14974 '\u01D9': 'U', 14975 '\u1EE6': 'U', 14976 '\u016E': 'U', 14977 '\u0170': 'U', 14978 '\u01D3': 'U', 14979 '\u0214': 'U', 14980 '\u0216': 'U', 14981 '\u01AF': 'U', 14982 '\u1EEA': 'U', 14983 '\u1EE8': 'U', 14984 '\u1EEE': 'U', 14985 '\u1EEC': 'U', 14986 '\u1EF0': 'U', 14987 '\u1EE4': 'U', 14988 '\u1E72': 'U', 14989 '\u0172': 'U', 14990 '\u1E76': 'U', 14991 '\u1E74': 'U', 14992 '\u0244': 'U', 14993 '\u24CB': 'V', 14994 '\uFF36': 'V', 14995 '\u1E7C': 'V', 14996 '\u1E7E': 'V', 14997 '\u01B2': 'V', 14998 '\uA75E': 'V', 14999 '\u0245': 'V', 15000 '\uA760': 'VY', 15001 '\u24CC': 'W', 15002 '\uFF37': 'W', 15003 '\u1E80': 'W', 15004 '\u1E82': 'W', 15005 '\u0174': 'W', 15006 '\u1E86': 'W', 15007 '\u1E84': 'W', 15008 '\u1E88': 'W', 15009 '\u2C72': 'W', 15010 '\u24CD': 'X', 15011 '\uFF38': 'X', 15012 '\u1E8A': 'X', 15013 '\u1E8C': 'X', 15014 '\u24CE': 'Y', 15015 '\uFF39': 'Y', 15016 '\u1EF2': 'Y', 15017 '\u00DD': 'Y', 15018 '\u0176': 'Y', 15019 '\u1EF8': 'Y', 15020 '\u0232': 'Y', 15021 '\u1E8E': 'Y', 15022 '\u0178': 'Y', 15023 '\u1EF6': 'Y', 15024 '\u1EF4': 'Y', 15025 '\u01B3': 'Y', 15026 '\u024E': 'Y', 15027 '\u1EFE': 'Y', 15028 '\u24CF': 'Z', 15029 '\uFF3A': 'Z', 15030 '\u0179': 'Z', 15031 '\u1E90': 'Z', 15032 '\u017B': 'Z', 15033 '\u017D': 'Z', 15034 '\u1E92': 'Z', 15035 '\u1E94': 'Z', 15036 '\u01B5': 'Z', 15037 '\u0224': 'Z', 15038 '\u2C7F': 'Z', 15039 '\u2C6B': 'Z', 15040 '\uA762': 'Z', 15041 '\u24D0': 'a', 15042 '\uFF41': 'a', 15043 '\u1E9A': 'a', 15044 '\u00E0': 'a', 15045 '\u00E1': 'a', 15046 '\u00E2': 'a', 15047 '\u1EA7': 'a', 15048 '\u1EA5': 'a', 15049 '\u1EAB': 'a', 15050 '\u1EA9': 'a', 15051 '\u00E3': 'a', 15052 '\u0101': 'a', 15053 '\u0103': 'a', 15054 '\u1EB1': 'a', 15055 '\u1EAF': 'a', 15056 '\u1EB5': 'a', 15057 '\u1EB3': 'a', 15058 '\u0227': 'a', 15059 '\u01E1': 'a', 15060 '\u00E4': 'a', 15061 '\u01DF': 'a', 15062 '\u1EA3': 'a', 15063 '\u00E5': 'a', 15064 '\u01FB': 'a', 15065 '\u01CE': 'a', 15066 '\u0201': 'a', 15067 '\u0203': 'a', 15068 '\u1EA1': 'a', 15069 '\u1EAD': 'a', 15070 '\u1EB7': 'a', 15071 '\u1E01': 'a', 15072 '\u0105': 'a', 15073 '\u2C65': 'a', 15074 '\u0250': 'a', 15075 '\uA733': 'aa', 15076 '\u00E6': 'ae', 15077 '\u01FD': 'ae', 15078 '\u01E3': 'ae', 15079 '\uA735': 'ao', 15080 '\uA737': 'au', 15081 '\uA739': 'av', 15082 '\uA73B': 'av', 15083 '\uA73D': 'ay', 15084 '\u24D1': 'b', 15085 '\uFF42': 'b', 15086 '\u1E03': 'b', 15087 '\u1E05': 'b', 15088 '\u1E07': 'b', 15089 '\u0180': 'b', 15090 '\u0183': 'b', 15091 '\u0253': 'b', 15092 '\u24D2': 'c', 15093 '\uFF43': 'c', 15094 '\u0107': 'c', 15095 '\u0109': 'c', 15096 '\u010B': 'c', 15097 '\u010D': 'c', 15098 '\u00E7': 'c', 15099 '\u1E09': 'c', 15100 '\u0188': 'c', 15101 '\u023C': 'c', 15102 '\uA73F': 'c', 15103 '\u2184': 'c', 15104 '\u24D3': 'd', 15105 '\uFF44': 'd', 15106 '\u1E0B': 'd', 15107 '\u010F': 'd', 15108 '\u1E0D': 'd', 15109 '\u1E11': 'd', 15110 '\u1E13': 'd', 15111 '\u1E0F': 'd', 15112 '\u0111': 'd', 15113 '\u018C': 'd', 15114 '\u0256': 'd', 15115 '\u0257': 'd', 15116 '\uA77A': 'd', 15117 '\u01F3': 'dz', 15118 '\u01C6': 'dz', 15119 '\u24D4': 'e', 15120 '\uFF45': 'e', 15121 '\u00E8': 'e', 15122 '\u00E9': 'e', 15123 '\u00EA': 'e', 15124 '\u1EC1': 'e', 15125 '\u1EBF': 'e', 15126 '\u1EC5': 'e', 15127 '\u1EC3': 'e', 15128 '\u1EBD': 'e', 15129 '\u0113': 'e', 15130 '\u1E15': 'e', 15131 '\u1E17': 'e', 15132 '\u0115': 'e', 15133 '\u0117': 'e', 15134 '\u00EB': 'e', 15135 '\u1EBB': 'e', 15136 '\u011B': 'e', 15137 '\u0205': 'e', 15138 '\u0207': 'e', 15139 '\u1EB9': 'e', 15140 '\u1EC7': 'e', 15141 '\u0229': 'e', 15142 '\u1E1D': 'e', 15143 '\u0119': 'e', 15144 '\u1E19': 'e', 15145 '\u1E1B': 'e', 15146 '\u0247': 'e', 15147 '\u025B': 'e', 15148 '\u01DD': 'e', 15149 '\u24D5': 'f', 15150 '\uFF46': 'f', 15151 '\u1E1F': 'f', 15152 '\u0192': 'f', 15153 '\uA77C': 'f', 15154 '\u24D6': 'g', 15155 '\uFF47': 'g', 15156 '\u01F5': 'g', 15157 '\u011D': 'g', 15158 '\u1E21': 'g', 15159 '\u011F': 'g', 15160 '\u0121': 'g', 15161 '\u01E7': 'g', 15162 '\u0123': 'g', 15163 '\u01E5': 'g', 15164 '\u0260': 'g', 15165 '\uA7A1': 'g', 15166 '\u1D79': 'g', 15167 '\uA77F': 'g', 15168 '\u24D7': 'h', 15169 '\uFF48': 'h', 15170 '\u0125': 'h', 15171 '\u1E23': 'h', 15172 '\u1E27': 'h', 15173 '\u021F': 'h', 15174 '\u1E25': 'h', 15175 '\u1E29': 'h', 15176 '\u1E2B': 'h', 15177 '\u1E96': 'h', 15178 '\u0127': 'h', 15179 '\u2C68': 'h', 15180 '\u2C76': 'h', 15181 '\u0265': 'h', 15182 '\u0195': 'hv', 15183 '\u24D8': 'i', 15184 '\uFF49': 'i', 15185 '\u00EC': 'i', 15186 '\u00ED': 'i', 15187 '\u00EE': 'i', 15188 '\u0129': 'i', 15189 '\u012B': 'i', 15190 '\u012D': 'i', 15191 '\u00EF': 'i', 15192 '\u1E2F': 'i', 15193 '\u1EC9': 'i', 15194 '\u01D0': 'i', 15195 '\u0209': 'i', 15196 '\u020B': 'i', 15197 '\u1ECB': 'i', 15198 '\u012F': 'i', 15199 '\u1E2D': 'i', 15200 '\u0268': 'i', 15201 '\u0131': 'i', 15202 '\u24D9': 'j', 15203 '\uFF4A': 'j', 15204 '\u0135': 'j', 15205 '\u01F0': 'j', 15206 '\u0249': 'j', 15207 '\u24DA': 'k', 15208 '\uFF4B': 'k', 15209 '\u1E31': 'k', 15210 '\u01E9': 'k', 15211 '\u1E33': 'k', 15212 '\u0137': 'k', 15213 '\u1E35': 'k', 15214 '\u0199': 'k', 15215 '\u2C6A': 'k', 15216 '\uA741': 'k', 15217 '\uA743': 'k', 15218 '\uA745': 'k', 15219 '\uA7A3': 'k', 15220 '\u24DB': 'l', 15221 '\uFF4C': 'l', 15222 '\u0140': 'l', 15223 '\u013A': 'l', 15224 '\u013E': 'l', 15225 '\u1E37': 'l', 15226 '\u1E39': 'l', 15227 '\u013C': 'l', 15228 '\u1E3D': 'l', 15229 '\u1E3B': 'l', 15230 '\u017F': 'l', 15231 '\u0142': 'l', 15232 '\u019A': 'l', 15233 '\u026B': 'l', 15234 '\u2C61': 'l', 15235 '\uA749': 'l', 15236 '\uA781': 'l', 15237 '\uA747': 'l', 15238 '\u01C9': 'lj', 15239 '\u24DC': 'm', 15240 '\uFF4D': 'm', 15241 '\u1E3F': 'm', 15242 '\u1E41': 'm', 15243 '\u1E43': 'm', 15244 '\u0271': 'm', 15245 '\u026F': 'm', 15246 '\u24DD': 'n', 15247 '\uFF4E': 'n', 15248 '\u01F9': 'n', 15249 '\u0144': 'n', 15250 '\u00F1': 'n', 15251 '\u1E45': 'n', 15252 '\u0148': 'n', 15253 '\u1E47': 'n', 15254 '\u0146': 'n', 15255 '\u1E4B': 'n', 15256 '\u1E49': 'n', 15257 '\u019E': 'n', 15258 '\u0272': 'n', 15259 '\u0149': 'n', 15260 '\uA791': 'n', 15261 '\uA7A5': 'n', 15262 '\u01CC': 'nj', 15263 '\u24DE': 'o', 15264 '\uFF4F': 'o', 15265 '\u00F2': 'o', 15266 '\u00F3': 'o', 15267 '\u00F4': 'o', 15268 '\u1ED3': 'o', 15269 '\u1ED1': 'o', 15270 '\u1ED7': 'o', 15271 '\u1ED5': 'o', 15272 '\u00F5': 'o', 15273 '\u1E4D': 'o', 15274 '\u022D': 'o', 15275 '\u1E4F': 'o', 15276 '\u014D': 'o', 15277 '\u1E51': 'o', 15278 '\u1E53': 'o', 15279 '\u014F': 'o', 15280 '\u022F': 'o', 15281 '\u0231': 'o', 15282 '\u00F6': 'o', 15283 '\u022B': 'o', 15284 '\u1ECF': 'o', 15285 '\u0151': 'o', 15286 '\u01D2': 'o', 15287 '\u020D': 'o', 15288 '\u020F': 'o', 15289 '\u01A1': 'o', 15290 '\u1EDD': 'o', 15291 '\u1EDB': 'o', 15292 '\u1EE1': 'o', 15293 '\u1EDF': 'o', 15294 '\u1EE3': 'o', 15295 '\u1ECD': 'o', 15296 '\u1ED9': 'o', 15297 '\u01EB': 'o', 15298 '\u01ED': 'o', 15299 '\u00F8': 'o', 15300 '\u01FF': 'o', 15301 '\u0254': 'o', 15302 '\uA74B': 'o', 15303 '\uA74D': 'o', 15304 '\u0275': 'o', 15305 '\u01A3': 'oi', 15306 '\u0223': 'ou', 15307 '\uA74F': 'oo', 15308 '\u24DF': 'p', 15309 '\uFF50': 'p', 15310 '\u1E55': 'p', 15311 '\u1E57': 'p', 15312 '\u01A5': 'p', 15313 '\u1D7D': 'p', 15314 '\uA751': 'p', 15315 '\uA753': 'p', 15316 '\uA755': 'p', 15317 '\u24E0': 'q', 15318 '\uFF51': 'q', 15319 '\u024B': 'q', 15320 '\uA757': 'q', 15321 '\uA759': 'q', 15322 '\u24E1': 'r', 15323 '\uFF52': 'r', 15324 '\u0155': 'r', 15325 '\u1E59': 'r', 15326 '\u0159': 'r', 15327 '\u0211': 'r', 15328 '\u0213': 'r', 15329 '\u1E5B': 'r', 15330 '\u1E5D': 'r', 15331 '\u0157': 'r', 15332 '\u1E5F': 'r', 15333 '\u024D': 'r', 15334 '\u027D': 'r', 15335 '\uA75B': 'r', 15336 '\uA7A7': 'r', 15337 '\uA783': 'r', 15338 '\u24E2': 's', 15339 '\uFF53': 's', 15340 '\u00DF': 's', 15341 '\u015B': 's', 15342 '\u1E65': 's', 15343 '\u015D': 's', 15344 '\u1E61': 's', 15345 '\u0161': 's', 15346 '\u1E67': 's', 15347 '\u1E63': 's', 15348 '\u1E69': 's', 15349 '\u0219': 's', 15350 '\u015F': 's', 15351 '\u023F': 's', 15352 '\uA7A9': 's', 15353 '\uA785': 's', 15354 '\u1E9B': 's', 15355 '\u24E3': 't', 15356 '\uFF54': 't', 15357 '\u1E6B': 't', 15358 '\u1E97': 't', 15359 '\u0165': 't', 15360 '\u1E6D': 't', 15361 '\u021B': 't', 15362 '\u0163': 't', 15363 '\u1E71': 't', 15364 '\u1E6F': 't', 15365 '\u0167': 't', 15366 '\u01AD': 't', 15367 '\u0288': 't', 15368 '\u2C66': 't', 15369 '\uA787': 't', 15370 '\uA729': 'tz', 15371 '\u24E4': 'u', 15372 '\uFF55': 'u', 15373 '\u00F9': 'u', 15374 '\u00FA': 'u', 15375 '\u00FB': 'u', 15376 '\u0169': 'u', 15377 '\u1E79': 'u', 15378 '\u016B': 'u', 15379 '\u1E7B': 'u', 15380 '\u016D': 'u', 15381 '\u00FC': 'u', 15382 '\u01DC': 'u', 15383 '\u01D8': 'u', 15384 '\u01D6': 'u', 15385 '\u01DA': 'u', 15386 '\u1EE7': 'u', 15387 '\u016F': 'u', 15388 '\u0171': 'u', 15389 '\u01D4': 'u', 15390 '\u0215': 'u', 15391 '\u0217': 'u', 15392 '\u01B0': 'u', 15393 '\u1EEB': 'u', 15394 '\u1EE9': 'u', 15395 '\u1EEF': 'u', 15396 '\u1EED': 'u', 15397 '\u1EF1': 'u', 15398 '\u1EE5': 'u', 15399 '\u1E73': 'u', 15400 '\u0173': 'u', 15401 '\u1E77': 'u', 15402 '\u1E75': 'u', 15403 '\u0289': 'u', 15404 '\u24E5': 'v', 15405 '\uFF56': 'v', 15406 '\u1E7D': 'v', 15407 '\u1E7F': 'v', 15408 '\u028B': 'v', 15409 '\uA75F': 'v', 15410 '\u028C': 'v', 15411 '\uA761': 'vy', 15412 '\u24E6': 'w', 15413 '\uFF57': 'w', 15414 '\u1E81': 'w', 15415 '\u1E83': 'w', 15416 '\u0175': 'w', 15417 '\u1E87': 'w', 15418 '\u1E85': 'w', 15419 '\u1E98': 'w', 15420 '\u1E89': 'w', 15421 '\u2C73': 'w', 15422 '\u24E7': 'x', 15423 '\uFF58': 'x', 15424 '\u1E8B': 'x', 15425 '\u1E8D': 'x', 15426 '\u24E8': 'y', 15427 '\uFF59': 'y', 15428 '\u1EF3': 'y', 15429 '\u00FD': 'y', 15430 '\u0177': 'y', 15431 '\u1EF9': 'y', 15432 '\u0233': 'y', 15433 '\u1E8F': 'y', 15434 '\u00FF': 'y', 15435 '\u1EF7': 'y', 15436 '\u1E99': 'y', 15437 '\u1EF5': 'y', 15438 '\u01B4': 'y', 15439 '\u024F': 'y', 15440 '\u1EFF': 'y', 15441 '\u24E9': 'z', 15442 '\uFF5A': 'z', 15443 '\u017A': 'z', 15444 '\u1E91': 'z', 15445 '\u017C': 'z', 15446 '\u017E': 'z', 15447 '\u1E93': 'z', 15448 '\u1E95': 'z', 15449 '\u01B6': 'z', 15450 '\u0225': 'z', 15451 '\u0240': 'z', 15452 '\u2C6C': 'z', 15453 '\uA763': 'z', 15454 '\u0386': '\u0391', 15455 '\u0388': '\u0395', 15456 '\u0389': '\u0397', 15457 '\u038A': '\u0399', 15458 '\u03AA': '\u0399', 15459 '\u038C': '\u039F', 15460 '\u038E': '\u03A5', 15461 '\u03AB': '\u03A5', 15462 '\u038F': '\u03A9', 15463 '\u03AC': '\u03B1', 15464 '\u03AD': '\u03B5', 15465 '\u03AE': '\u03B7', 15466 '\u03AF': '\u03B9', 15467 '\u03CA': '\u03B9', 15468 '\u0390': '\u03B9', 15469 '\u03CC': '\u03BF', 15470 '\u03CD': '\u03C5', 15471 '\u03CB': '\u03C5', 15472 '\u03B0': '\u03C5', 15473 '\u03C9': '\u03C9', 15474 '\u03C2': '\u03C3' 15475 }; 15476 15477 return diacritics; 15478}); 15479 15480S2.define('select2/data/base',[ 15481 '../utils' 15482], function (Utils) { 15483 function BaseAdapter ($element, options) { 15484 BaseAdapter.__super__.constructor.call(this); 15485 } 15486 15487 Utils.Extend(BaseAdapter, Utils.Observable); 15488 15489 BaseAdapter.prototype.current = function (callback) { 15490 throw new Error('The `current` method must be defined in child classes.'); 15491 }; 15492 15493 BaseAdapter.prototype.query = function (params, callback) { 15494 throw new Error('The `query` method must be defined in child classes.'); 15495 }; 15496 15497 BaseAdapter.prototype.bind = function (container, $container) { 15498 // Can be implemented in subclasses 15499 }; 15500 15501 BaseAdapter.prototype.destroy = function () { 15502 // Can be implemented in subclasses 15503 }; 15504 15505 BaseAdapter.prototype.generateResultId = function (container, data) { 15506 var id =
vendor: 34,941 bytes, lines 15506-17003
15506container.id + '-result-'; 15507 15508 id += Utils.generateChars(4); 15509 15510 if (data.id != null) { 15511 id += '-' + data.id.toString(); 15512 } else { 15513 id += '-' + Utils.generateChars(4); 15514 } 15515 return id; 15516 }; 15517 15518 return BaseAdapter; 15519}); 15520 15521S2.define('select2/data/select',[ 15522 './base', 15523 '../utils', 15524 'jquery' 15525], function (BaseAdapter, Utils, $) { 15526 function SelectAdapter ($element, options) { 15527 this.$element = $element; 15528 this.options = options; 15529 15530 SelectAdapter.__super__.constructor.call(this); 15531 } 15532 15533 Utils.Extend(SelectAdapter, BaseAdapter); 15534 15535 SelectAdapter.prototype.current = function (callback) { 15536 var data = []; 15537 var self = this; 15538 15539 this.$element.find(':selected').each(function () { 15540 var $option = $(this); 15541 15542 var option = self.item($option); 15543 15544 data.push(option); 15545 }); 15546 15547 callback(data); 15548 }; 15549 15550 SelectAdapter.prototype.select = function (data) { 15551 var self = this; 15552 15553 data.selected = true; 15554 15555 // If data.element is a DOM node, use it instead 15556 if ($(data.element).is('option')) { 15557 data.element.selected = true; 15558 15559 this.$element.trigger('change'); 15560 15561 return; 15562 } 15563 15564 if (this.$element.prop('multiple')) { 15565 this.current(function (currentData) { 15566 var val = []; 15567 15568 data = [data]; 15569 data.push.apply(data, currentData); 15570 15571 for (var d = 0; d < data.length; d++) { 15572 var id = data[d].id; 15573 15574 if ($.inArray(id, val) === -1) { 15575 val.push(id); 15576 } 15577 } 15578 15579 self.$element.val(val); 15580 self.$element.trigger('change'); 15581 }); 15582 } else { 15583 var val = data.id; 15584 15585 this.$element.val(val); 15586 this.$element.trigger('change'); 15587 } 15588 }; 15589 15590 SelectAdapter.prototype.unselect = function (data) { 15591 var self = this; 15592 15593 if (!this.$element.prop('multiple')) { 15594 return; 15595 } 15596 15597 data.selected = false; 15598 15599 if ($(data.element).is('option')) { 15600 data.element.selected = false; 15601 15602 this.$element.trigger('change'); 15603 15604 return; 15605 } 15606 15607 this.current(function (currentData) { 15608 var val = []; 15609 15610 for (var d = 0; d < currentData.length; d++) { 15611 var id = currentData[d].id; 15612 15613 if (id !== data.id && $.inArray(id, val) === -1) { 15614 val.push(id); 15615 } 15616 } 15617 15618 self.$element.val(val); 15619 15620 self.$element.trigger('change'); 15621 }); 15622 }; 15623 15624 SelectAdapter.prototype.bind = function (container, $container) { 15625 var self = this; 15626 15627 this.container = container; 15628 15629 container.on('select', function (params) { 15630 self.select(params.data); 15631 }); 15632 15633 container.on('unselect', function (params) { 15634 self.unselect(params.data); 15635 }); 15636 }; 15637 15638 SelectAdapter.prototype.destroy = function () { 15639 // Remove anything added to child elements 15640 this.$element.find('*').each(function () { 15641 // Remove any custom data set by Select2 15642 $.removeData(this, 'data'); 15643 }); 15644 }; 15645 15646 SelectAdapter.prototype.query = function (params, callback) { 15647 var data = []; 15648 var self = this; 15649 15650 var $options = this.$element.children(); 15651 15652 $options.each(function () { 15653 var $option = $(this); 15654 15655 if (!$option.is('option') && !$option.is('optgroup')) { 15656 return; 15657 } 15658 15659 var option = self.item($option); 15660 15661 var matches = self.matches(params, option); 15662 15663 if (matches !== null) { 15664 data.push(matches); 15665 } 15666 }); 15667 15668 callback({ 15669 results: data 15670 }); 15671 }; 15672 15673 SelectAdapter.prototype.addOptions = function ($options) { 15674 Utils.appendMany(this.$element, $options); 15675 }; 15676 15677 SelectAdapter.prototype.option = function (data) { 15678 var option; 15679 15680 if (data.children) { 15681 option = document.createElement('optgroup'); 15682 option.label = data.text; 15683 } else { 15684 option = document.createElement('option'); 15685 15686 if (option.textContent !== undefined) { 15687 option.textContent = data.text; 15688 } else { 15689 option.innerText = data.text; 15690 } 15691 } 15692 15693 if (data.id) { 15694 option.value = data.id; 15695 } 15696 15697 if (data.disabled) { 15698 option.disabled = true; 15699 } 15700 15701 if (data.selected) { 15702 option.selected = true; 15703 } 15704 15705 if (data.title) { 15706 option.title = data.title; 15707 } 15708 15709 var $option = $(option); 15710 15711 var normalizedData = this._normalizeItem(data); 15712 normalizedData.element = option; 15713 15714 // Override the option's data with the combined data 15715 $.data(option, 'data', normalizedData); 15716 15717 return $option; 15718 }; 15719 15720 SelectAdapter.prototype.item = function ($option) { 15721 var data = {}; 15722 15723 data = $.data($option[0], 'data'); 15724 15725 if (data != null) { 15726 return data; 15727 } 15728 15729 if ($option.is('option')) { 15730 data = { 15731 id: $option.val(), 15732 text: $option.text(), 15733 disabled: $option.prop('disabled'), 15734 selected: $option.prop('selected'), 15735 title: $option.prop('title') 15736 }; 15737 } else if ($option.is('optgroup')) { 15738 data = { 15739 text: $option.prop('label'), 15740 children: [], 15741 title: $option.prop('title') 15742 }; 15743 15744 var $children = $option.children('option'); 15745 var children = []; 15746 15747 for (var c = 0; c < $children.length; c++) { 15748 var $child = $($children[c]); 15749 15750 var child = this.item($child); 15751 15752 children.push(child); 15753 } 15754 15755 data.children = children; 15756 } 15757 15758 data = this._normalizeItem(data); 15759 data.element = $option[0]; 15760 15761 $.data($option[0], 'data', data); 15762 15763 return data; 15764 }; 15765 15766 SelectAdapter.prototype._normalizeItem = function (item) { 15767 if (!$.isPlainObject(item)) { 15768 item = { 15769 id: item, 15770 text: item 15771 }; 15772 } 15773 15774 item = $.extend({}, { 15775 text: '' 15776 }, item); 15777 15778 var defaults = { 15779 selected: false, 15780 disabled: false 15781 }; 15782 15783 if (item.id != null) { 15784 item.id = item.id.toString(); 15785 } 15786 15787 if (item.text != null) { 15788 item.text = item.text.toString(); 15789 } 15790 15791 if (item._resultId == null && item.id && this.container != null) { 15792 item._resultId = this.generateResultId(this.container, item); 15793 } 15794 15795 return $.extend({}, defaults, item); 15796 }; 15797 15798 SelectAdapter.prototype.matches = function (params, data) { 15799 var matcher = this.options.get('matcher'); 15800 15801 return matcher(params, data); 15802 }; 15803 15804 return SelectAdapter; 15805}); 15806 15807S2.define('select2/data/array',[ 15808 './select', 15809 '../utils', 15810 'jquery' 15811], function (SelectAdapter, Utils, $) { 15812 function ArrayAdapter ($element, options) { 15813 var data = options.get('data') || []; 15814 15815 ArrayAdapter.__super__.constructor.call(this, $element, options); 15816 15817 this.addOptions(this.convertToOptions(data)); 15818 } 15819 15820 Utils.Extend(ArrayAdapter, SelectAdapter); 15821 15822 ArrayAdapter.prototype.select = function (data) { 15823 var $option = this.$element.find('option').filter(function (i, elm) { 15824 return elm.value == data.id.toString(); 15825 }); 15826 15827 if ($option.length === 0) { 15828 $option = this.option(data); 15829 15830 this.addOptions($option); 15831 } 15832 15833 ArrayAdapter.__super__.select.call(this, data); 15834 }; 15835 15836 ArrayAdapter.prototype.convertToOptions = function (data) { 15837 var self = this; 15838 15839 var $existing = this.$element.find('option'); 15840 var existingIds = $existing.map(function () { 15841 return self.item($(this)).id; 15842 }).get(); 15843 15844 var $options = []; 15845 15846 // Filter out all items except for the one passed in the argument 15847 function onlyItem (item) { 15848 return function () { 15849 return $(this).val() == item.id; 15850 }; 15851 } 15852 15853 for (var d = 0; d < data.length; d++) { 15854 var item = this._normalizeItem(data[d]); 15855 15856 // Skip items which were pre-loaded, only merge the data 15857 if ($.inArray(item.id, existingIds) >= 0) { 15858 var $existingOption = $existing.filter(onlyItem(item)); 15859 15860 var existingData = this.item($existingOption); 15861 var newData = $.extend(true, {}, existingData, item); 15862 15863 var $newOption = this.option(newData); 15864 15865 $existingOption.replaceWith($newOption); 15866 15867 continue; 15868 } 15869 15870 var $option = this.option(item); 15871 15872 if (item.children) { 15873 var $children = this.convertToOptions(item.children); 15874 15875 Utils.appendMany($option, $children); 15876 } 15877 15878 $options.push($option); 15879 } 15880 15881 return $options; 15882 }; 15883 15884 return ArrayAdapter; 15885}); 15886 15887S2.define('select2/data/ajax',[ 15888 './array', 15889 '../utils', 15890 'jquery' 15891], function (ArrayAdapter, Utils, $) { 15892 function AjaxAdapter ($element, options) { 15893 this.ajaxOptions = this._applyDefaults(options.get('ajax')); 15894 15895 if (this.ajaxOptions.processResults != null) { 15896 this.processResults = this.ajaxOptions.processResults; 15897 } 15898 15899 AjaxAdapter.__super__.constructor.call(this, $element, options); 15900 } 15901 15902 Utils.Extend(AjaxAdapter, ArrayAdapter); 15903 15904 AjaxAdapter.prototype._applyDefaults = function (options) { 15905 var defaults = { 15906 data: function (params) { 15907 return $.extend({}, params, { 15908 q: params.term 15909 }); 15910 }, 15911 transport: function (params, success, failure) { 15912 var $request = $.ajax(params); 15913 15914 $request.then(success); 15915 $request.fail(failure); 15916 15917 return $request; 15918 } 15919 }; 15920 15921 return $.extend({}, defaults, options, true); 15922 }; 15923 15924 AjaxAdapter.prototype.processResults = function (results) { 15925 return results; 15926 }; 15927 15928 AjaxAdapter.prototype.query = function (params, callback) { 15929 var matches = []; 15930 var self = this; 15931 15932 if (this._request != null) { 15933 // JSONP requests cannot always be aborted 15934 if ($.isFunction(this._request.abort)) { 15935 this._request.abort(); 15936 } 15937 15938 this._request = null; 15939 } 15940 15941 var options = $.extend({ 15942 type: 'GET' 15943 }, this.ajaxOptions); 15944 15945 if (typeof options.url === 'function') { 15946 options.url = options.url.call(this.$element, params); 15947 } 15948 15949 if (typeof options.data === 'function') { 15950 options.data = options.data.call(this.$element, params); 15951 } 15952 15953 function request () { 15954 var $request = options.transport(options, function (data) { 15955 var results = self.processResults(data, params); 15956 15957 if (self.options.get('debug') && window.console && console.error) { 15958 // Check to make sure that the response included a `results` key. 15959 if (!results || !results.results || !$.isArray(results.results)) { 15960 console.error( 15961 'Select2: The AJAX results did not return an array in the ' + 15962 '`results` key of the response.' 15963 ); 15964 } 15965 } 15966 15967 callback(results); 15968 }, function () { 15969 // TODO: Handle AJAX errors 15970 }); 15971 15972 self._request = $request; 15973 } 15974 15975 if (this.ajaxOptions.delay && params.term !== '') { 15976 if (this._queryTimeout) { 15977 window.clearTimeout(this._queryTimeout); 15978 } 15979 15980 this._queryTimeout = window.setTimeout(request, this.ajaxOptions.delay); 15981 } else { 15982 request(); 15983 } 15984 }; 15985 15986 return AjaxAdapter; 15987}); 15988 15989S2.define('select2/data/tags',[ 15990 'jquery' 15991], function ($) { 15992 function Tags (decorated, $element, options) { 15993 var tags = options.get('tags'); 15994 15995 var createTag = options.get('createTag'); 15996 15997 if (createTag !== undefined) { 15998 this.createTag = createTag; 15999 } 16000 16001 decorated.call(this, $element, options); 16002 16003 if ($.isArray(tags)) { 16004 for (var t = 0; t < tags.length; t++) { 16005 var tag = tags[t]; 16006 var item = this._normalizeItem(tag); 16007 16008 var $option = this.option(item); 16009 16010 this.$element.append($option); 16011 } 16012 } 16013 } 16014 16015 Tags.prototype.query = function (decorated, params, callback) { 16016 var self = this; 16017 16018 this._removeOldTags(); 16019 16020 if (params.term == null || params.page != null) { 16021 decorated.call(this, params, callback); 16022 return; 16023 } 16024 16025 function wrapper (obj, child) { 16026 var data = obj.results; 16027 16028 for (var i = 0; i < data.length; i++) { 16029 var option = data[i]; 16030 16031 var checkChildren = ( 16032 option.children != null && 16033 !wrapper({ 16034 results: option.children 16035 }, true) 16036 ); 16037 16038 var checkText = option.text === params.term; 16039 16040 if (checkText || checkChildren) { 16041 if (child) { 16042 return false; 16043 } 16044 16045 obj.data = data; 16046 callback(obj); 16047 16048 return; 16049 } 16050 } 16051 16052 if (child) { 16053 return true; 16054 } 16055 16056 var tag = self.createTag(params); 16057 16058 if (tag != null) { 16059 var $option = self.option(tag); 16060 $option.attr('data-select2-tag', true); 16061 16062 self.addOptions([$option]); 16063 16064 self.insertTag(data, tag); 16065 } 16066 16067 obj.results = data; 16068 16069 callback(obj); 16070 } 16071 16072 decorated.call(this, params, wrapper); 16073 }; 16074 16075 Tags.prototype.createTag = function (decorated, params) { 16076 var term = $.trim(params.term); 16077 16078 if (term === '') { 16079 return null; 16080 } 16081 16082 return { 16083 id: term, 16084 text: term 16085 }; 16086 }; 16087 16088 Tags.prototype.insertTag = function (_, data, tag) { 16089 data.unshift(tag); 16090 }; 16091 16092 Tags.prototype._removeOldTags = function (_) { 16093 var tag = this._lastTag; 16094 16095 var $options = this.$element.find('option[data-select2-tag]'); 16096 16097 $options.each(function () { 16098 if (this.selected) { 16099 return; 16100 } 16101 16102 $(this).remove(); 16103 }); 16104 }; 16105 16106 return Tags; 16107}); 16108 16109S2.define('select2/data/tokenizer',[ 16110 'jquery' 16111], function ($) { 16112 function Tokenizer (decorated, $element, options) { 16113 var tokenizer = options.get('tokenizer'); 16114 16115 if (tokenizer !== undefined) { 16116 this.tokenizer = tokenizer; 16117 } 16118 16119 decorated.call(this, $element, options); 16120 } 16121 16122 Tokenizer.prototype.bind = function (decorated, container, $container) { 16123 decorated.call(this, container, $container); 16124 16125 this.$search = container.dropdown.$search || container.selection.$search || 16126 $container.find('.select2-search__field'); 16127 }; 16128 16129 Tokenizer.prototype.query = function (decorated, params, callback) { 16130 var self = this; 16131 16132 function select (data) { 16133 self.trigger('select', { 16134 data: data 16135 }); 16136 } 16137 16138 params.term = params.term || ''; 16139 16140 var tokenData = this.tokenizer(params, this.options, select); 16141 16142 if (tokenData.term !== params.term) { 16143 // Replace the search term if we have the search box 16144 if (this.$search.length) { 16145 this.$search.val(tokenData.term); 16146 this.$search.focus(); 16147 } 16148 16149 params.term = tokenData.term; 16150 } 16151 16152 decorated.call(this, params, callback); 16153 }; 16154 16155 Tokenizer.prototype.tokenizer = function (_, params, options, callback) { 16156 var separators = options.get('tokenSeparators') || []; 16157 var term = params.term; 16158 var i = 0; 16159 16160 var createTag = this.createTag || function (params) { 16161 return { 16162 id: params.term, 16163 text: params.term 16164 }; 16165 }; 16166 16167 while (i < term.length) { 16168 var termChar = term[i]; 16169 16170 if ($.inArray(termChar, separators) === -1) { 16171 i++; 16172 16173 continue; 16174 } 16175 16176 var part = term.substr(0, i); 16177 var partParams = $.extend({}, params, { 16178 term: part 16179 }); 16180 16181 var data = createTag(partParams); 16182 16183 if (data == null) { 16184 i++; 16185 continue; 16186 } 16187 16188 callback(data); 16189 16190 // Reset the term to not include the tokenized portion 16191 term = term.substr(i + 1) || ''; 16192 i = 0; 16193 } 16194 16195 return { 16196 term: term 16197 }; 16198 }; 16199 16200 return Tokenizer; 16201}); 16202 16203S2.define('select2/data/minimumInputLength',[ 16204 16205], function () { 16206 function MinimumInputLength (decorated, $e, options) { 16207 this.minimumInputLength = options.get('minimumInputLength'); 16208 16209 decorated.call(this, $e, options); 16210 } 16211 16212 MinimumInputLength.prototype.query = function (decorated, params, callback) { 16213 params.term = params.term || ''; 16214 16215 if (params.term.length < this.minimumInputLength) { 16216 this.trigger('results:message', { 16217 message: 'inputTooShort', 16218 args: { 16219 minimum: this.minimumInputLength, 16220 input: params.term, 16221 params: params 16222 } 16223 }); 16224 16225 return; 16226 } 16227 16228 decorated.call(this, params, callback); 16229 }; 16230 16231 return MinimumInputLength; 16232}); 16233 16234S2.define('select2/data/maximumInputLength',[ 16235 16236], function () { 16237 function MaximumInputLength (decorated, $e, options) { 16238 this.maximumInputLength = options.get('maximumInputLength'); 16239 16240 decorated.call(this, $e, options); 16241 } 16242 16243 MaximumInputLength.prototype.query = function (decorated, params, callback) { 16244 params.term = params.term || ''; 16245 16246 if (this.maximumInputLength > 0 && 16247 params.term.length > this.maximumInputLength) { 16248 this.trigger('results:message', { 16249 message: 'inputTooLong', 16250 args: { 16251 maximum: this.maximumInputLength, 16252 input: params.term, 16253 params: params 16254 } 16255 }); 16256 16257 return; 16258 } 16259 16260 decorated.call(this, params, callback); 16261 }; 16262 16263 return MaximumInputLength; 16264}); 16265 16266S2.define('select2/data/maximumSelectionLength',[ 16267 16268], function (){ 16269 function MaximumSelectionLength (decorated, $e, options) { 16270 this.maximumSelectionLength = options.get('maximumSelectionLength'); 16271 16272 decorated.call(this, $e, options); 16273 } 16274 16275 MaximumSelectionLength.prototype.query = 16276 function (decorated, params, callback) { 16277 var self = this; 16278 16279 this.current(function (currentData) { 16280 var count = currentData != null ? currentData.length : 0; 16281 if (self.maximumSelectionLength > 0 && 16282 count >= self.maximumSelectionLength) { 16283 self.trigger('results:message', { 16284 message: 'maximumSelected', 16285 args: { 16286 maximum: self.maximumSelectionLength 16287 } 16288 }); 16289 return; 16290 } 16291 decorated.call(self, params, callback); 16292 }); 16293 }; 16294 16295 return MaximumSelectionLength; 16296}); 16297 16298S2.define('select2/dropdown',[ 16299 'jquery', 16300 './utils' 16301], function ($, Utils) { 16302 function Dropdown ($element, options) { 16303 this.$element = $element; 16304 this.options = options; 16305 16306 Dropdown.__super__.constructor.call(this); 16307 } 16308 16309 Utils.Extend(Dropdown, Utils.Observable); 16310 16311 Dropdown.prototype.render = function () { 16312 var $dropdown = $( 16313 '<span class="select2-dropdown">' + 16314 '<span class="select2-results"></span>' + 16315 '</span>' 16316 ); 16317 16318 $dropdown.attr('dir', this.options.get('dir')); 16319 16320 this.$dropdown = $dropdown; 16321 16322 return $dropdown; 16323 }; 16324 16325 Dropdown.prototype.bind = function () { 16326 // Should be implemented in subclasses 16327 }; 16328 16329 Dropdown.prototype.position = function ($dropdown, $container) { 16330 // Should be implmented in subclasses 16331 }; 16332 16333 Dropdown.prototype.destroy = function () { 16334 // Remove the dropdown from the DOM 16335 this.$dropdown.remove(); 16336 }; 16337 16338 return Dropdown; 16339}); 16340 16341S2.define('select2/dropdown/search',[ 16342 'jquery', 16343 '../utils' 16344], function ($, Utils) { 16345 function Search () { } 16346 16347 Search.prototype.render = function (decorated) { 16348 var $rendered = decorated.call(this); 16349 16350 var $search = $( 16351 '<span class="select2-search select2-search--dropdown">' + 16352 '<input class="select2-search__field" type="search" tabindex="-1"' + 16353 ' autocomplete="off" autocorrect="off" autocapitalize="off"' + 16354 ' spellcheck="false" role="textbox" />' + 16355 '</span>' 16356 ); 16357 16358 this.$searchContainer = $search; 16359 this.$search = $search.find('input'); 16360 16361 $rendered.prepend($search); 16362 16363 return $rendered; 16364 }; 16365 16366 Search.prototype.bind = function (decorated, container, $container) { 16367 var self = this; 16368 16369 decorated.call(this, container, $container); 16370 16371 this.$search.on('keydown', function (evt) { 16372 self.trigger('keypress', evt); 16373 16374 self._keyUpPrevented = evt.isDefaultPrevented(); 16375 }); 16376 16377 // Workaround for browsers which do not support the `input` event 16378 // This will prevent double-triggering of events for browsers which support 16379 // both the `keyup` and `input` events. 16380 this.$search.on('input', function (evt) { 16381 // Unbind the duplicated `keyup` event 16382 $(this).off('keyup'); 16383 }); 16384 16385 this.$search.on('keyup input', function (evt) { 16386 self.handleSearch(evt); 16387 }); 16388 16389 container.on('open', function () { 16390 self.$search.attr('tabindex', 0); 16391 16392 self.$search.focus(); 16393 16394 window.setTimeout(function () { 16395 self.$search.focus(); 16396 }, 0); 16397 }); 16398 16399 container.on('close', function () { 16400 self.$search.attr('tabindex', -1); 16401 16402 self.$search.val(''); 16403 }); 16404 16405 container.on('results:all', function (params) { 16406 if (params.query.term == null || params.query.term === '') { 16407 var showSearch = self.showSearch(params); 16408 16409 if (showSearch) { 16410 self.$searchContainer.removeClass('select2-search--hide'); 16411 } else { 16412 self.$searchContainer.addClass('select2-search--hide'); 16413 } 16414 } 16415 }); 16416 }; 16417 16418 Search.prototype.handleSearch = function (evt) { 16419 if (!this._keyUpPrevented) { 16420 var input = this.$search.val(); 16421 16422 this.trigger('query', { 16423 term: input 16424 }); 16425 } 16426 16427 this._keyUpPrevented = false; 16428 }; 16429 16430 Search.prototype.showSearch = function (_, params) { 16431 return true; 16432 }; 16433 16434 return Search; 16435}); 16436 16437S2.define('select2/dropdown/hidePlaceholder',[ 16438 16439], function () { 16440 function HidePlaceholder (decorated, $element, options, dataAdapter) { 16441 this.placeholder = this.normalizePlaceholder(options.get('placeholder')); 16442 16443 decorated.call(this, $element, options, dataAdapter); 16444 } 16445 16446 HidePlaceholder.prototype.append = function (decorated, data) { 16447 data.results = this.removePlaceholder(data.results); 16448 16449 decorated.call(this, data); 16450 }; 16451 16452 HidePlaceholder.prototype.normalizePlaceholder = function (_, placeholder) { 16453 if (typeof placeholder === 'string') { 16454 placeholder = { 16455 id: '', 16456 text: placeholder 16457 }; 16458 } 16459 16460 return placeholder; 16461 }; 16462 16463 HidePlaceholder.prototype.removePlaceholder = function (_, data) { 16464 var modifiedData = data.slice(0); 16465 16466 for (var d = data.length - 1; d >= 0; d--) { 16467 var item = data[d]; 16468 16469 if (this.placeholder.id === item.id) { 16470 modifiedData.splice(d, 1); 16471 } 16472 } 16473 16474 return modifiedData; 16475 }; 16476 16477 return HidePlaceholder; 16478}); 16479 16480S2.define('select2/dropdown/infiniteScroll',[ 16481 'jquery' 16482], function ($) { 16483 function InfiniteScroll (decorated, $element, options, dataAdapter) { 16484 this.lastParams = {}; 16485 16486 decorated.call(this, $element, options, dataAdapter); 16487 16488 this.$loadingMore = this.createLoadingMore(); 16489 this.loading = false; 16490 } 16491 16492 InfiniteScroll.prototype.append = function (decorated, data) { 16493 this.$loadingMore.remove(); 16494 this.loading = false; 16495 16496 decorated.call(this, data); 16497 16498 if (this.showLoadingMore(data)) { 16499 this.$results.append(this.$loadingMore); 16500 } 16501 }; 16502 16503 InfiniteScroll.prototype.bind = function (decorated, container, $container) { 16504 var self = this; 16505 16506 decorated.call(this, container, $container); 16507 16508 container.on('query', function (params) { 16509 self.lastParams = params; 16510 self.loading = true; 16511 }); 16512 16513 container.on('query:append', function (params) { 16514 self.lastParams = params; 16515 self.loading = true; 16516 }); 16517 16518 this.$results.on('scroll', function () { 16519 var isLoadMoreVisible = $.contains( 16520 document.documentElement, 16521 self.$loadingMore[0] 16522 ); 16523 16524 if (self.loading || !isLoadMoreVisible) { 16525 return; 16526 } 16527 16528 var currentOffset = self.$results.offset().top + 16529 self.$results.outerHeight(false); 16530 var loadingMoreOffset = self.$loadingMore.offset().top + 16531 self.$loadingMore.outerHeight(false); 16532 16533 if (currentOffset + 50 >= loadingMoreOffset) { 16534 self.loadMore(); 16535 } 16536 }); 16537 }; 16538 16539 InfiniteScroll.prototype.loadMore = function () { 16540 this.loading = true; 16541 16542 var params = $.extend({}, {page: 1}, this.lastParams); 16543 16544 params.page++; 16545 16546 this.trigger('query:append', params); 16547 }; 16548 16549 InfiniteScroll.prototype.showLoadingMore = function (_, data) { 16550 return data.pagination && data.pagination.more; 16551 }; 16552 16553 InfiniteScroll.prototype.createLoadingMore = function () { 16554 var $option = $( 16555 '<li ' + 16556 'class="select2-results__option select2-results__option--load-more"' + 16557 'role="treeitem" aria-disabled="true"></li>' 16558 ); 16559 16560 var message = this.options.get('translations').get('loadingMore'); 16561 16562 $option.html(message(this.lastParams)); 16563 16564 return $option; 16565 }; 16566 16567 return InfiniteScroll; 16568}); 16569 16570S2.define('select2/dropdown/attachBody',[ 16571 'jquery', 16572 '../utils' 16573], function ($, Utils) { 16574 function AttachBody (decorated, $element, options) { 16575 this.$dropdownParent = options.get('dropdownParent') || $(document.body); 16576 16577 decorated.call(this, $element, options); 16578 } 16579 16580 AttachBody.prototype.bind = function (decorated, container, $container) { 16581 var self = this; 16582 16583 var setupResultsEvents = false; 16584 16585 decorated.call(this, container, $container); 16586 16587 container.on('open', function () { 16588 self._showDropdown(); 16589 self._attachPositioningHandler(container); 16590 16591 if (!setupResultsEvents) { 16592 setupResultsEvents = true; 16593 16594 container.on('results:all', function () { 16595 self._positionDropdown(); 16596 self._resizeDropdown(); 16597 }); 16598 16599 container.on('results:append', function () { 16600 self._positionDropdown(); 16601 self._resizeDropdown(); 16602 }); 16603 } 16604 }); 16605 16606 container.on('close', function () { 16607 self._hideDropdown(); 16608 self._detachPositioningHandler(container); 16609 }); 16610 16611 this.$dropdownContainer.on('mousedown', function (evt) { 16612 evt.stopPropagation(); 16613 }); 16614 }; 16615 16616 AttachBody.prototype.destroy = function (decorated) { 16617 decorated.call(this); 16618 16619 this.$dropdownContainer.remove(); 16620 }; 16621 16622 AttachBody.prototype.position = function (decorated, $dropdown, $container) { 16623 // Clone all of the container classes 16624 $dropdown.attr('class', $container.attr('class')); 16625 16626 $dropdown.removeClass('select2'); 16627 $dropdown.addClass('select2-container--open'); 16628 16629 $dropdown.css({ 16630 position: 'absolute', 16631 top: -999999 16632 }); 16633 16634 this.$container = $container; 16635 }; 16636 16637 AttachBody.prototype.render = function (decorated) { 16638 var $container = $('<span></span>'); 16639 16640 var $dropdown = decorated.call(this); 16641 $container.append($dropdown); 16642 16643 this.$dropdownContainer = $container; 16644 16645 return $container; 16646 }; 16647 16648 AttachBody.prototype._hideDropdown = function (decorated) { 16649 this.$dropdownContainer.detach(); 16650 }; 16651 16652 AttachBody.prototype._attachPositioningHandler = 16653 function (decorated, container) { 16654 var self = this; 16655 16656 var scrollEvent = 'scroll.select2.' + container.id; 16657 var resizeEvent = 'resize.select2.' + container.id; 16658 var orientationEvent = 'orientationchange.select2.' + container.id; 16659 16660 var $watchers = this.$container.parents().filter(Utils.hasScroll); 16661 $watchers.each(function () { 16662 $(this).data('select2-scroll-position', { 16663 x: $(this).scrollLeft(), 16664 y: $(this).scrollTop() 16665 }); 16666 }); 16667 16668 $watchers.on(scrollEvent, function (ev) { 16669 var position = $(this).data('select2-scroll-position'); 16670 $(this).scrollTop(position.y); 16671 }); 16672 16673 $(window).on(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent, 16674 function (e) { 16675 self._positionDropdown(); 16676 self._resizeDropdown(); 16677 }); 16678 }; 16679 16680 AttachBody.prototype._detachPositioningHandler = 16681 function (decorated, container) { 16682 var scrollEvent = 'scroll.select2.' + container.id; 16683 var resizeEvent = 'resize.select2.' + container.id; 16684 var orientationEvent = 'orientationchange.select2.' + container.id; 16685 16686 var $watchers = this.$container.parents().filter(Utils.hasScroll); 16687 $watchers.off(scrollEvent); 16688 16689 $(window).off(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent); 16690 }; 16691 16692 AttachBody.prototype._positionDropdown = function () { 16693 var $window = $(window); 16694 16695 var isCurrentlyAbove = this.$dropdown.hasClass('select2-dropdown--above'); 16696 var isCurrentlyBelow = this.$dropdown.hasClass('select2-dropdown--below'); 16697 16698 var newDirection = null; 16699 16700 var position = this.$container.position(); 16701 var offset = this.$container.offset(); 16702 16703 offset.bottom = offset.top + this.$container.outerHeight(false); 16704 16705 var container = { 16706 height: this.$container.outerHeight(false) 16707 }; 16708 16709 container.top = offset.top; 16710 container.bottom = offset.top + container.height; 16711 16712 var dropdown = { 16713 height: this.$dropdown.outerHeight(false) 16714 }; 16715 16716 var viewport = { 16717 top: $window.scrollTop(), 16718 bottom: $window.scrollTop() + $window.height() 16719 }; 16720 16721 var enoughRoomAbove = viewport.top < (offset.top - dropdown.height); 16722 var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height); 16723 16724 var css = { 16725 left: offset.left, 16726 top: container.bottom 16727 }; 16728 16729 // Fix positioning with static parents 16730 if (this.$dropdownParent[0].style.position !== 'static') { 16731 var parentOffset = this.$dropdownParent.offset(); 16732 16733 css.top -= parentOffset.top; 16734 css.left -= parentOffset.left; 16735 } 16736 16737 if (!isCurrentlyAbove && !isCurrentlyBelow) { 16738 newDirection = 'below'; 16739 } 16740 16741 if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) { 16742 newDirection = 'above'; 16743 } else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) { 16744 newDirection = 'below'; 16745 } 16746 16747 if (newDirection == 'above' || 16748 (isCurrentlyAbove && newDirection !== 'below')) { 16749 css.top = container.top - dropdown.height; 16750 } 16751 16752 if (newDirection != null) { 16753 this.$dropdown 16754 .removeClass('select2-dropdown--below select2-dropdown--above') 16755 .addClass('select2-dropdown--' + newDirection); 16756 this.$container 16757 .removeClass('select2-container--below select2-container--above') 16758 .addClass('select2-container--' + newDirection); 16759 } 16760 16761 this.$dropdownContainer.css(css); 16762 }; 16763 16764 AttachBody.prototype._resizeDropdown = function () { 16765 var css = { 16766 width: this.$container.outerWidth(false) + 'px' 16767 }; 16768 16769 if (this.options.get('dropdownAutoWidth')) { 16770 css.minWidth = css.width; 16771 css.width = 'auto'; 16772 } 16773 16774 this.$dropdown.css(css); 16775 }; 16776 16777 AttachBody.prototype._showDropdown = function (decorated) { 16778 this.$dropdownContainer.appendTo(this.$dropdownParent); 16779 16780 this._positionDropdown(); 16781 this._resizeDropdown(); 16782 }; 16783 16784 return AttachBody; 16785}); 16786 16787S2.define('select2/dropdown/minimumResultsForSearch',[ 16788 16789], function () { 16790 function countResults (data) { 16791 var count = 0; 16792 16793 for (var d = 0; d < data.length; d++) { 16794 var item = data[d]; 16795 16796 if (item.children) { 16797 count += countResults(item.children); 16798 } else { 16799 count++; 16800 } 16801 } 16802 16803 return count; 16804 } 16805 16806 function MinimumResultsForSearch (decorated, $element, options, dataAdapter) { 16807 this.minimumResultsForSearch = options.get('minimumResultsForSearch'); 16808 16809 if (this.minimumResultsForSearch < 0) { 16810 this.minimumResultsForSearch = Infinity; 16811 } 16812 16813 decorated.call(this, $element, options, dataAdapter); 16814 } 16815 16816 MinimumResultsForSearch.prototype.showSearch = function (decorated, params) { 16817 if (countResults(params.data.results) < this.minimumResultsForSearch) { 16818 return false; 16819 } 16820 16821 return decorated.call(this, params); 16822 }; 16823 16824 return MinimumResultsForSearch; 16825}); 16826 16827S2.define('select2/dropdown/selectOnClose',[ 16828 16829], function () { 16830 function SelectOnClose () { } 16831 16832 SelectOnClose.prototype.bind = function (decorated, container, $container) { 16833 var self = this; 16834 16835 decorated.call(this, container, $container); 16836 16837 container.on('close', function () { 16838 self._handleSelectOnClose(); 16839 }); 16840 }; 16841 16842 SelectOnClose.prototype._handleSelectOnClose = function () { 16843 var $highlightedResults = this.getHighlightedResults(); 16844 16845 // Only select highlighted results 16846 if ($highlightedResults.length < 1) { 16847 return; 16848 } 16849 16850 var data = $highlightedResults.data('data'); 16851 16852 // Don't re-select already selected resulte 16853 if ( 16854 (data.element != null && data.element.selected) || 16855 (data.element == null && data.selected) 16856 ) { 16857 return; 16858 } 16859 16860 this.trigger('select', { 16861 data: data 16862 }); 16863 }; 16864 16865 return SelectOnClose; 16866}); 16867 16868S2.define('select2/dropdown/closeOnSelect',[ 16869 16870], function () { 16871 function CloseOnSelect () { } 16872 16873 CloseOnSelect.prototype.bind = function (decorated, container, $container) { 16874 var self = this; 16875 16876 decorated.call(this, container, $container); 16877 16878 container.on('select', function (evt) { 16879 self._selectTriggered(evt); 16880 }); 16881 16882 container.on('unselect', function (evt) { 16883 self._selectTriggered(evt); 16884 }); 16885 }; 16886 16887 CloseOnSelect.prototype._selectTriggered = function (_, evt) { 16888 var originalEvent = evt.originalEvent; 16889 16890 // Don't close if the control key is being held 16891 if (originalEvent && originalEvent.ctrlKey) { 16892 return; 16893 } 16894 16895 this.trigger('close', {}); 16896 }; 16897 16898 return CloseOnSelect; 16899}); 16900 16901S2.define('select2/i18n/en',[],function () { 16902 // English 16903 return { 16904 errorLoading: function () { 16905 return 'The results could not be loaded.'; 16906 }, 16907 inputTooLong: function (args) { 16908 var overChars = args.input.length - args.maximum; 16909 16910 var message = 'Please delete ' + overChars + ' character'; 16911 16912 if (overChars != 1) { 16913 message += 's'; 16914 } 16915 16916 return message; 16917 }, 16918 inputTooShort: function (args) { 16919 var remainingChars = args.minimum - args.input.length; 16920 16921 var message = 'Please enter ' + remainingChars + ' or more characters'; 16922 16923 return message; 16924 }, 16925 loadingMore: function () { 16926 return 'Loading more resultsâ¦'; 16927 }, 16928 maximumSelected: function (args) { 16929 var message = 'You can only select ' + args.maximum + ' item'; 16930 16931 if (args.maximum != 1) { 16932 message += 's'; 16933 } 16934 16935 return message; 16936 }, 16937 noResults: function () { 16938 return 'No results found'; 16939 }, 16940 searching: function () { 16941 return 'Searchingâ¦'; 16942 } 16943 }; 16944}); 16945 16946S2.define('select2/defaults',[ 16947 'jquery', 16948 'require', 16949 16950 './results', 16951 16952 './selection/single', 16953 './selection/multiple', 16954 './selection/placeholder', 16955 './selection/allowClear', 16956 './selection/search', 16957 './selection/eventRelay', 16958 16959 './utils', 16960 './translation', 16961 './diacritics', 16962 16963 './data/select', 16964 './data/array', 16965 './data/ajax', 16966 './data/tags', 16967 './data/tokenizer', 16968 './data/minimumInputLength', 16969 './data/maximumInputLength', 16970 './data/maximumSelectionLength', 16971 16972 './dropdown', 16973 './dropdown/search', 16974 './dropdown/hidePlaceholder', 16975 './dropdown/infiniteScroll', 16976 './dropdown/attachBody', 16977 './dropdown/minimumResultsForSearch', 16978 './dropdown/selectOnClose', 16979 './dropdown/closeOnSelect', 16980 16981 './i18n/en' 16982], function ($, require, 16983 16984 ResultsList, 16985 16986 SingleSelection, MultipleSelection, Placeholder, AllowClear, 16987 SelectionSearch, EventRelay, 16988 16989 Utils, Translation, DIACRITICS, 16990 16991 SelectData, ArrayData, AjaxData, Tags, Tokenizer, 16992 MinimumInputLength, MaximumInputLength, MaximumSelectionLength, 16993 16994 Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll, 16995 AttachBody, MinimumResultsForSearch, SelectOnClose, CloseOnSelect, 16996 16997 EnglishTranslation) { 16998 function Defaults () { 16999 this.reset(); 17000 } 17001 17002 Defaults.prototype.apply = function (options) { 17003 options = $.extend(
vendor: 15,268 bytes, lines 17003-17567
17003{}, this.defaults, options); 17004 17005 if (options.dataAdapter == null) { 17006 if (options.ajax != null) { 17007 options.dataAdapter = AjaxData; 17008 } else if (options.data != null) { 17009 options.dataAdapter = ArrayData; 17010 } else { 17011 options.dataAdapter = SelectData; 17012 } 17013 17014 if (options.minimumInputLength > 0) { 17015 options.dataAdapter = Utils.Decorate( 17016 options.dataAdapter, 17017 MinimumInputLength 17018 ); 17019 } 17020 17021 if (options.maximumInputLength > 0) { 17022 options.dataAdapter = Utils.Decorate( 17023 options.dataAdapter, 17024 MaximumInputLength 17025 ); 17026 } 17027 17028 if (options.maximumSelectionLength > 0) { 17029 options.dataAdapter = Utils.Decorate( 17030 options.dataAdapter, 17031 MaximumSelectionLength 17032 ); 17033 } 17034 17035 if (options.tags) { 17036 options.dataAdapter = Utils.Decorate(options.dataAdapter, Tags); 17037 } 17038 17039 if (options.tokenSeparators != null || options.tokenizer != null) { 17040 options.dataAdapter = Utils.Decorate( 17041 options.dataAdapter, 17042 Tokenizer 17043 ); 17044 } 17045 17046 if (options.query != null) { 17047 var Query = require(options.amdBase + 'compat/query'); 17048 17049 options.dataAdapter = Utils.Decorate( 17050 options.dataAdapter, 17051 Query 17052 ); 17053 } 17054 17055 if (options.initSelection != null) { 17056 var InitSelection = require(options.amdBase + 'compat/initSelection'); 17057 17058 options.dataAdapter = Utils.Decorate( 17059 options.dataAdapter, 17060 InitSelection 17061 ); 17062 } 17063 } 17064 17065 if (options.resultsAdapter == null) { 17066 options.resultsAdapter = ResultsList; 17067 17068 if (options.ajax != null) { 17069 options.resultsAdapter = Utils.Decorate( 17070 options.resultsAdapter, 17071 InfiniteScroll 17072 ); 17073 } 17074 17075 if (options.placeholder != null) { 17076 options.resultsAdapter = Utils.Decorate( 17077 options.resultsAdapter, 17078 HidePlaceholder 17079 ); 17080 } 17081 17082 if (options.selectOnClose) { 17083 options.resultsAdapter = Utils.Decorate( 17084 options.resultsAdapter, 17085 SelectOnClose 17086 ); 17087 } 17088 } 17089 17090 if (options.dropdownAdapter == null) { 17091 if (options.multiple) { 17092 options.dropdownAdapter = Dropdown; 17093 } else { 17094 var SearchableDropdown = Utils.Decorate(Dropdown, DropdownSearch); 17095 17096 options.dropdownAdapter = SearchableDropdown; 17097 } 17098 17099 if (options.minimumResultsForSearch !== 0) { 17100 options.dropdownAdapter = Utils.Decorate( 17101 options.dropdownAdapter, 17102 MinimumResultsForSearch 17103 ); 17104 } 17105 17106 if (options.closeOnSelect) { 17107 options.dropdownAdapter = Utils.Decorate( 17108 options.dropdownAdapter, 17109 CloseOnSelect 17110 ); 17111 } 17112 17113 if ( 17114 options.dropdownCssClass != null || 17115 options.dropdownCss != null || 17116 options.adaptDropdownCssClass != null 17117 ) { 17118 var DropdownCSS = require(options.amdBase + 'compat/dropdownCss'); 17119 17120 options.dropdownAdapter = Utils.Decorate( 17121 options.dropdownAdapter, 17122 DropdownCSS 17123 ); 17124 } 17125 17126 options.dropdownAdapter = Utils.Decorate( 17127 options.dropdownAdapter, 17128 AttachBody 17129 ); 17130 } 17131 17132 if (options.selectionAdapter == null) { 17133 if (options.multiple) { 17134 options.selectionAdapter = MultipleSelection; 17135 } else { 17136 options.selectionAdapter = SingleSelection; 17137 } 17138 17139 // Add the placeholder mixin if a placeholder was specified 17140 if (options.placeholder != null) { 17141 options.selectionAdapter = Utils.Decorate( 17142 options.selectionAdapter, 17143 Placeholder 17144 ); 17145 } 17146 17147 if (options.allowClear) { 17148 options.selectionAdapter = Utils.Decorate( 17149 options.selectionAdapter, 17150 AllowClear 17151 ); 17152 } 17153 17154 if (options.multiple) { 17155 options.selectionAdapter = Utils.Decorate( 17156 options.selectionAdapter, 17157 SelectionSearch 17158 ); 17159 } 17160 17161 if ( 17162 options.containerCssClass != null || 17163 options.containerCss != null || 17164 options.adaptContainerCssClass != null 17165 ) { 17166 var ContainerCSS = require(options.amdBase + 'compat/containerCss'); 17167 17168 options.selectionAdapter = Utils.Decorate( 17169 options.selectionAdapter, 17170 ContainerCSS 17171 ); 17172 } 17173 17174 options.selectionAdapter = Utils.Decorate( 17175 options.selectionAdapter, 17176 EventRelay 17177 ); 17178 } 17179 17180 if (typeof options.language === 'string') { 17181 // Check if the language is specified with a region 17182 if (options.language.indexOf('-') > 0) { 17183 // Extract the region information if it is included 17184 var languageParts = options.language.split('-'); 17185 var baseLanguage = languageParts[0]; 17186 17187 options.language = [options.language, baseLanguage]; 17188 } else { 17189 options.language = [options.language]; 17190 } 17191 } 17192 17193 if ($.isArray(options.language)) { 17194 var languages = new Translation(); 17195 options.language.push('en'); 17196 17197 var languageNames = options.language; 17198 17199 for (var l = 0; l < languageNames.length; l++) { 17200 var name = languageNames[l]; 17201 var language = {}; 17202 17203 try { 17204 // Try to load it with the original name 17205 language = Translation.loadPath(name); 17206 } catch (e) { 17207 try { 17208 // If we couldn't load it, check if it wasn't the full path 17209 name = this.defaults.amdLanguageBase + name; 17210 language = Translation.loadPath(name); 17211 } catch (ex) { 17212 // The translation could not be loaded at all. Sometimes this is 17213 // because of a configuration problem, other times this can be 17214 // because of how Select2 helps load all possible translation files. 17215 if (options.debug && window.console && console.warn) { 17216 console.warn( 17217 'Select2: The language file for "' + name + '" could not be ' + 17218 'automatically loaded. A fallback will be used instead.' 17219 ); 17220 } 17221 17222 continue; 17223 } 17224 } 17225 17226 languages.extend(language); 17227 } 17228 17229 options.translations = languages; 17230 } else { 17231 var baseTranslation = Translation.loadPath( 17232 this.defaults.amdLanguageBase + 'en' 17233 ); 17234 var customTranslation = new Translation(options.language); 17235 17236 customTranslation.extend(baseTranslation); 17237 17238 options.translations = customTranslation; 17239 } 17240 17241 return options; 17242 }; 17243 17244 Defaults.prototype.reset = function () { 17245 function stripDiacritics (text) { 17246 // Used 'uni range + named function' from http://jsperf.com/diacritics/18 17247 function match(a) { 17248 return DIACRITICS[a] || a; 17249 } 17250 17251 return text.replace(/[^\u0000-\u007E]/g, match); 17252 } 17253 17254 function matcher (params, data) { 17255 // Always return the object if there is nothing to compare 17256 if ($.trim(params.term) === '') { 17257 return data; 17258 } 17259 17260 // Do a recursive check for options with children 17261 if (data.children && data.children.length > 0) { 17262 // Clone the data object if there are children 17263 // This is required as we modify the object to remove any non-matches 17264 var match = $.extend(true, {}, data); 17265 17266 // Check each child of the option 17267 for (var c = data.children.length - 1; c >= 0; c--) { 17268 var child = data.children[c]; 17269 17270 var matches = matcher(params, child); 17271 17272 // If there wasn't a match, remove the object in the array 17273 if (matches == null) { 17274 match.children.splice(c, 1); 17275 } 17276 } 17277 17278 // If any children matched, return the new object 17279 if (match.children.length > 0) { 17280 return match; 17281 } 17282 17283 // If there were no matching children, check just the plain object 17284 return matcher(params, match); 17285 } 17286 17287 var original = stripDiacritics(data.text).toUpperCase(); 17288 var term = stripDiacritics(params.term).toUpperCase(); 17289 17290 // Check if the text contains the term 17291 if (original.indexOf(term) > -1) { 17292 return data; 17293 } 17294 17295 // If it doesn't contain the term, don't return anything 17296 return null; 17297 } 17298 17299 this.defaults = { 17300 amdBase: './', 17301 amdLanguageBase: './i18n/', 17302 closeOnSelect: true, 17303 debug: false, 17304 dropdownAutoWidth: false, 17305 escapeMarkup: Utils.escapeMarkup, 17306 language: EnglishTranslation, 17307 matcher: matcher, 17308 minimumInputLength: 0, 17309 maximumInputLength: 0, 17310 maximumSelectionLength: 0, 17311 minimumResultsForSearch: 0, 17312 selectOnClose: false, 17313 sorter: function (data) { 17314 return data; 17315 }, 17316 templateResult: function (result) { 17317 return result.text; 17318 }, 17319 templateSelection: function (selection) { 17320 return selection.text; 17321 }, 17322 theme: 'default', 17323 width: 'resolve' 17324 }; 17325 }; 17326 17327 Defaults.prototype.set = function (key, value) { 17328 var camelKey = $.camelCase(key); 17329 17330 var data = {}; 17331 data[camelKey] = value; 17332 17333 var convertedData = Utils._convertData(data); 17334 17335 $.extend(this.defaults, convertedData); 17336 }; 17337 17338 var defaults = new Defaults(); 17339 17340 return defaults; 17341}); 17342 17343S2.define('select2/options',[ 17344 'require', 17345 'jquery', 17346 './defaults', 17347 './utils' 17348], function (require, $, Defaults, Utils) { 17349 function Options (options, $element) { 17350 this.options = options; 17351 17352 if ($element != null) { 17353 this.fromElement($element); 17354 } 17355 17356 this.options = Defaults.apply(this.options); 17357 17358 if ($element && $element.is('input')) { 17359 var InputCompat = require(this.get('amdBase') + 'compat/inputData'); 17360 17361 this.options.dataAdapter = Utils.Decorate( 17362 this.options.dataAdapter, 17363 InputCompat 17364 ); 17365 } 17366 } 17367 17368 Options.prototype.fromElement = function ($e) { 17369 var excludedData = ['select2']; 17370 17371 if (this.options.multiple == null) { 17372 this.options.multiple = $e.prop('multiple'); 17373 } 17374 17375 if (this.options.disabled == null) { 17376 this.options.disabled = $e.prop('disabled'); 17377 } 17378 17379 if (this.options.language == null) { 17380 if ($e.prop('lang')) { 17381 this.options.language = $e.prop('lang').toLowerCase(); 17382 } else if ($e.closest('[lang]').prop('lang')) { 17383 this.options.language = $e.closest('[lang]').prop('lang'); 17384 } 17385 } 17386 17387 if (this.options.dir == null) { 17388 if ($e.prop('dir')) { 17389 this.options.dir = $e.prop('dir'); 17390 } else if ($e.closest('[dir]').prop('dir')) { 17391 this.options.dir = $e.closest('[dir]').prop('dir'); 17392 } else { 17393 this.options.dir = 'ltr'; 17394 } 17395 } 17396 17397 $e.prop('disabled', this.options.disabled); 17398 $e.prop('multiple', this.options.multiple); 17399 17400 if ($e.data('select2Tags')) { 17401 if (this.options.debug && window.console && console.warn) { 17402 console.warn( 17403 'Select2: The `data-select2-tags` attribute has been changed to ' + 17404 'use the `data-data` and `data-tags="true"` attributes and will be ' + 17405 'removed in future versions of Select2.' 17406 ); 17407 } 17408 17409 $e.data('data', $e.data('select2Tags')); 17410 $e.data('tags', true); 17411 } 17412 17413 if ($e.data('ajaxUrl')) { 17414 if (this.options.debug && window.console && console.warn) { 17415 console.warn( 17416 'Select2: The `data-ajax-url` attribute has been changed to ' + 17417 '`data-ajax--url` and support for the old attribute will be removed' + 17418 ' in future versions of Select2.' 17419 ); 17420 } 17421 17422 $e.attr('ajax--url', $e.data('ajaxUrl')); 17423 $e.data('ajax--url', $e.data('ajaxUrl')); 17424 } 17425 17426 var dataset = {}; 17427 17428 // Prefer the element's `dataset` attribute if it exists 17429 // jQuery 1.x does not correctly handle data attributes with multiple dashes 17430 if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) { 17431 dataset = $.extend(true, {}, $e[0].dataset, $e.data()); 17432 } else { 17433 dataset = $e.data(); 17434 } 17435 17436 var data = $.extend(true, {}, dataset); 17437 17438 data = Utils._convertData(data); 17439 17440 for (var key in data) { 17441 if ($.inArray(key, excludedData) > -1) { 17442 continue; 17443 } 17444 17445 if ($.isPlainObject(this.options[key])) { 17446 $.extend(this.options[key], data[key]); 17447 } else { 17448 this.options[key] = data[key]; 17449 } 17450 } 17451 17452 return this; 17453 }; 17454 17455 Options.prototype.get = function (key) { 17456 return this.options[key]; 17457 }; 17458 17459 Options.prototype.set = function (key, val) { 17460 this.options[key] = val; 17461 }; 17462 17463 return Options; 17464}); 17465 17466S2.define('select2/core',[ 17467 'jquery', 17468 './options', 17469 './utils', 17470 './keys' 17471], function ($, Options, Utils, KEYS) { 17472 var Select2 = function ($element, options) { 17473 if ($element.data('select2') != null) { 17474 $element.data('select2').destroy(); 17475 } 17476 17477 this.$element = $element; 17478 17479 this.id = this._generateId($element); 17480 17481 options = options || {}; 17482 17483 this.options = new Options(options, $element); 17484 17485 Select2.__super__.constructor.call(this); 17486 17487 // Set up the tabindex 17488 17489 var tabindex = $element.attr('tabindex') || 0; 17490 $element.data('old-tabindex', tabindex); 17491 $element.attr('tabindex', '-1'); 17492 17493 // Set up containers and adapters 17494 17495 var DataAdapter = this.options.get('dataAdapter'); 17496 this.dataAdapter = new DataAdapter($element, this.options); 17497 17498 var $container = this.render(); 17499 17500 this._placeContainer($container); 17501 17502 var SelectionAdapter = this.options.get('selectionAdapter'); 17503 this.selection = new SelectionAdapter($element, this.options); 17504 this.$selection = this.selection.render(); 17505 17506 this.selection.position(this.$selection, $container); 17507 17508 var DropdownAdapter = this.options.get('dropdownAdapter'); 17509 this.dropdown = new DropdownAdapter($element, this.options); 17510 this.$dropdown = this.dropdown.render(); 17511 17512 this.dropdown.position(this.$dropdown, $container); 17513 17514 var ResultsAdapter = this.options.get('resultsAdapter'); 17515 this.results = new ResultsAdapter($element, this.options, this.dataAdapter); 17516 this.$results = this.results.render(); 17517 17518 this.results.position(this.$results, this.$dropdown); 17519 17520 // Bind events 17521 17522 var self = this; 17523 17524 // Bind the container to all of the adapters 17525 this._bindAdapters(); 17526 17527 // Register any DOM event handlers 17528 this._registerDomEvents(); 17529 17530 // Register any internal event handlers 17531 this._registerDataEvents(); 17532 this._registerSelectionEvents(); 17533 this._registerDropdownEvents(); 17534 this._registerResultsEvents(); 17535 this._registerEvents(); 17536 17537 // Set the initial state 17538 this.dataAdapter.current(function (initialData) { 17539 self.trigger('selection:update', { 17540 data: initialData 17541 }); 17542 }); 17543 17544 // Hide the original select 17545 $element.addClass('select2-hidden-accessible'); 17546 $element.attr('aria-hidden', 'true'); 17547 17548 // Synchronize any monitored attributes 17549 this._syncAttributes(); 17550 17551 $element.data('select2', this); 17552 }; 17553 17554 Utils.Extend(Select2, Utils.Observable); 17555 17556 Select2.prototype._generateId = function ($element) { 17557 var id = ''; 17558 17559 if ($element.attr('id') != null) { 17560 id = $element.attr('id'); 17561 } else if ($element.attr('name') != null) { 17562 id = $element.attr('name') + '-' + Utils.generateChars(2); 17563 } else { 17564 id = Utils.generateChars(4); 17565 } 17566 17567 id =
vendor: 40,193 bytes, lines 17567-19007
17567'select2-' + id; 17568 17569 return id; 17570 }; 17571 17572 Select2.prototype._placeContainer = function ($container) { 17573 $container.insertAfter(this.$element); 17574 17575 var width = this._resolveWidth(this.$element, this.options.get('width')); 17576 17577 if (width != null) { 17578 $container.css('width', width); 17579 } 17580 }; 17581 17582 Select2.prototype._resolveWidth = function ($element, method) { 17583 var WIDTH = /^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i; 17584 17585 if (method == 'resolve') { 17586 var styleWidth = this._resolveWidth($element, 'style'); 17587 17588 if (styleWidth != null) { 17589 return styleWidth; 17590 } 17591 17592 return this._resolveWidth($element, 'element'); 17593 } 17594 17595 if (method == 'element') { 17596 var elementWidth = $element.outerWidth(false); 17597 17598 if (elementWidth <= 0) { 17599 return 'auto'; 17600 } 17601 17602 return elementWidth + 'px'; 17603 } 17604 17605 if (method == 'style') { 17606 var style = $element.attr('style'); 17607 17608 if (typeof(style) !== 'string') { 17609 return null; 17610 } 17611 17612 var attrs = style.split(';'); 17613 17614 for (var i = 0, l = attrs.length; i < l; i = i + 1) { 17615 var attr = attrs[i].replace(/\s/g, ''); 17616 var matches = attr.match(WIDTH); 17617 17618 if (matches !== null && matches.length >= 1) { 17619 return matches[1]; 17620 } 17621 } 17622 17623 return null; 17624 } 17625 17626 return method; 17627 }; 17628 17629 Select2.prototype._bindAdapters = function () { 17630 this.dataAdapter.bind(this, this.$container); 17631 this.selection.bind(this, this.$container); 17632 17633 this.dropdown.bind(this, this.$container); 17634 this.results.bind(this, this.$container); 17635 }; 17636 17637 Select2.prototype._registerDomEvents = function () { 17638 var self = this; 17639 17640 this.$element.on('change.select2', function () { 17641 self.dataAdapter.current(function (data) { 17642 self.trigger('selection:update', { 17643 data: data 17644 }); 17645 }); 17646 }); 17647 17648 this._sync = Utils.bind(this._syncAttributes, this); 17649 17650 if (this.$element[0].attachEvent) { 17651 this.$element[0].attachEvent('onpropertychange', this._sync); 17652 } 17653 17654 var observer = window.MutationObserver || 17655 window.WebKitMutationObserver || 17656 window.MozMutationObserver 17657 ; 17658 17659 if (observer != null) { 17660 this._observer = new observer(function (mutations) { 17661 $.each(mutations, self._sync); 17662 }); 17663 this._observer.observe(this.$element[0], { 17664 attributes: true, 17665 subtree: false 17666 }); 17667 } else if (this.$element[0].addEventListener) { 17668 this.$element[0].addEventListener('DOMAttrModified', self._sync, false); 17669 } 17670 }; 17671 17672 Select2.prototype._registerDataEvents = function () { 17673 var self = this; 17674 17675 this.dataAdapter.on('*', function (name, params) { 17676 self.trigger(name, params); 17677 }); 17678 }; 17679 17680 Select2.prototype._registerSelectionEvents = function () { 17681 var self = this; 17682 var nonRelayEvents = ['toggle', 'focus']; 17683 17684 this.selection.on('toggle', function () { 17685 self.toggleDropdown(); 17686 }); 17687 17688 this.selection.on('focus', function (params) { 17689 self.focus(params); 17690 }); 17691 17692 this.selection.on('*', function (name, params) { 17693 if ($.inArray(name, nonRelayEvents) !== -1) { 17694 return; 17695 } 17696 17697 self.trigger(name, params); 17698 }); 17699 }; 17700 17701 Select2.prototype._registerDropdownEvents = function () { 17702 var self = this; 17703 17704 this.dropdown.on('*', function (name, params) { 17705 self.trigger(name, params); 17706 }); 17707 }; 17708 17709 Select2.prototype._registerResultsEvents = function () { 17710 var self = this; 17711 17712 this.results.on('*', function (name, params) { 17713 self.trigger(name, params); 17714 }); 17715 }; 17716 17717 Select2.prototype._registerEvents = function () { 17718 var self = this; 17719 17720 this.on('open', function () { 17721 self.$container.addClass('select2-container--open'); 17722 }); 17723 17724 this.on('close', function () { 17725 self.$container.removeClass('select2-container--open'); 17726 }); 17727 17728 this.on('enable', function () { 17729 self.$container.removeClass('select2-container--disabled'); 17730 }); 17731 17732 this.on('disable', function () { 17733 self.$container.addClass('select2-container--disabled'); 17734 }); 17735 17736 this.on('blur', function () { 17737 self.$container.removeClass('select2-container--focus'); 17738 }); 17739 17740 this.on('query', function (params) { 17741 if (!self.isOpen()) { 17742 self.trigger('open', {}); 17743 } 17744 17745 this.dataAdapter.query(params, function (data) { 17746 self.trigger('results:all', { 17747 data: data, 17748 query: params 17749 }); 17750 }); 17751 }); 17752 17753 this.on('query:append', function (params) { 17754 this.dataAdapter.query(params, function (data) { 17755 self.trigger('results:append', { 17756 data: data, 17757 query: params 17758 }); 17759 }); 17760 }); 17761 17762 this.on('keypress', function (evt) { 17763 var key = evt.which; 17764 17765 if (self.isOpen()) { 17766 if (key === KEYS.ESC || key === KEYS.TAB || 17767 (key === KEYS.UP && evt.altKey)) { 17768 self.close(); 17769 17770 evt.preventDefault(); 17771 } else if (key === KEYS.ENTER) { 17772 self.trigger('results:select', {}); 17773 17774 evt.preventDefault(); 17775 } else if ((key === KEYS.SPACE && evt.ctrlKey)) { 17776 self.trigger('results:toggle', {}); 17777 17778 evt.preventDefault(); 17779 } else if (key === KEYS.UP) { 17780 self.trigger('results:previous', {}); 17781 17782 evt.preventDefault(); 17783 } else if (key === KEYS.DOWN) { 17784 self.trigger('results:next', {}); 17785 17786 evt.preventDefault(); 17787 } 17788 } else { 17789 if (key === KEYS.ENTER || key === KEYS.SPACE || 17790 (key === KEYS.DOWN && evt.altKey)) { 17791 self.open(); 17792 17793 evt.preventDefault(); 17794 } 17795 } 17796 }); 17797 }; 17798 17799 Select2.prototype._syncAttributes = function () { 17800 this.options.set('disabled', this.$element.prop('disabled')); 17801 17802 if (this.options.get('disabled')) { 17803 if (this.isOpen()) { 17804 this.close(); 17805 } 17806 17807 this.trigger('disable', {}); 17808 } else { 17809 this.trigger('enable', {}); 17810 } 17811 }; 17812 17813 /** 17814 * Override the trigger method to automatically trigger pre-events when 17815 * there are events that can be prevented. 17816 */ 17817 Select2.prototype.trigger = function (name, args) { 17818 var actualTrigger = Select2.__super__.trigger; 17819 var preTriggerMap = { 17820 'open': 'opening', 17821 'close': 'closing', 17822 'select': 'selecting', 17823 'unselect': 'unselecting' 17824 }; 17825 17826 if (args === undefined) { 17827 args = {}; 17828 } 17829 17830 if (name in preTriggerMap) { 17831 var preTriggerName = preTriggerMap[name]; 17832 var preTriggerArgs = { 17833 prevented: false, 17834 name: name, 17835 args: args 17836 }; 17837 17838 actualTrigger.call(this, preTriggerName, preTriggerArgs); 17839 17840 if (preTriggerArgs.prevented) { 17841 args.prevented = true; 17842 17843 return; 17844 } 17845 } 17846 17847 actualTrigger.call(this, name, args); 17848 }; 17849 17850 Select2.prototype.toggleDropdown = function () { 17851 if (this.options.get('disabled')) { 17852 return; 17853 } 17854 17855 if (this.isOpen()) { 17856 this.close(); 17857 } else { 17858 this.open(); 17859 } 17860 }; 17861 17862 Select2.prototype.open = function () { 17863 if (this.isOpen()) { 17864 return; 17865 } 17866 17867 this.trigger('query', {}); 17868 }; 17869 17870 Select2.prototype.close = function () { 17871 if (!this.isOpen()) { 17872 return; 17873 } 17874 17875 this.trigger('close', {}); 17876 }; 17877 17878 Select2.prototype.isOpen = function () { 17879 return this.$container.hasClass('select2-container--open'); 17880 }; 17881 17882 Select2.prototype.hasFocus = function () { 17883 return this.$container.hasClass('select2-container--focus'); 17884 }; 17885 17886 Select2.prototype.focus = function (data) { 17887 // No need to re-trigger focus events if we are already focused 17888 if (this.hasFocus()) { 17889 return; 17890 } 17891 17892 this.$container.addClass('select2-container--focus'); 17893 this.trigger('focus', {}); 17894 }; 17895 17896 Select2.prototype.enable = function (args) { 17897 if (this.options.get('debug') && window.console && console.warn) { 17898 console.warn( 17899 'Select2: The `select2("enable")` method has been deprecated and will' + 17900 ' be removed in later Select2 versions. Use $element.prop("disabled")' + 17901 ' instead.' 17902 ); 17903 } 17904 17905 if (args == null || args.length === 0) { 17906 args = [true]; 17907 } 17908 17909 var disabled = !args[0]; 17910 17911 this.$element.prop('disabled', disabled); 17912 }; 17913 17914 Select2.prototype.data = function () { 17915 if (this.options.get('debug') && 17916 arguments.length > 0 && window.console && console.warn) { 17917 console.warn( 17918 'Select2: Data can no longer be set using `select2("data")`. You ' + 17919 'should consider setting the value instead using `$element.val()`.' 17920 ); 17921 } 17922 17923 var data = []; 17924 17925 this.dataAdapter.current(function (currentData) { 17926 data = currentData; 17927 }); 17928 17929 return data; 17930 }; 17931 17932 Select2.prototype.val = function (args) { 17933 if (this.options.get('debug') && window.console && console.warn) { 17934 console.warn( 17935 'Select2: The `select2("val")` method has been deprecated and will be' + 17936 ' removed in later Select2 versions. Use $element.val() instead.' 17937 ); 17938 } 17939 17940 if (args == null || args.length === 0) { 17941 return this.$element.val(); 17942 } 17943 17944 var newVal = args[0]; 17945 17946 if ($.isArray(newVal)) { 17947 newVal = $.map(newVal, function (obj) { 17948 return obj.toString(); 17949 }); 17950 } 17951 17952 this.$element.val(newVal).trigger('change'); 17953 }; 17954 17955 Select2.prototype.destroy = function () { 17956 this.$container.remove(); 17957 17958 if (this.$element[0].detachEvent) { 17959 this.$element[0].detachEvent('onpropertychange', this._sync); 17960 } 17961 17962 if (this._observer != null) { 17963 this._observer.disconnect(); 17964 this._observer = null; 17965 } else if (this.$element[0].removeEventListener) { 17966 this.$element[0] 17967 .removeEventListener('DOMAttrModified', this._sync, false); 17968 } 17969 17970 this._sync = null; 17971 17972 this.$element.off('.select2'); 17973 this.$element.attr('tabindex', this.$element.data('old-tabindex')); 17974 17975 this.$element.removeClass('select2-hidden-accessible'); 17976 this.$element.attr('aria-hidden', 'false'); 17977 this.$element.removeData('select2'); 17978 17979 this.dataAdapter.destroy(); 17980 this.selection.destroy(); 17981 this.dropdown.destroy(); 17982 this.results.destroy(); 17983 17984 this.dataAdapter = null; 17985 this.selection = null; 17986 this.dropdown = null; 17987 this.results = null; 17988 }; 17989 17990 Select2.prototype.render = function () { 17991 var $container = $( 17992 '<span class="select2 select2-container">' + 17993 '<span class="selection"></span>' + 17994 '<span class="dropdown-wrapper" aria-hidden="true"></span>' + 17995 '</span>' 17996 ); 17997 17998 $container.attr('dir', this.options.get('dir')); 17999 18000 this.$container = $container; 18001 18002 this.$container.addClass('select2-container--' + this.options.get('theme')); 18003 18004 $container.data('element', this.$element); 18005 18006 return $container; 18007 }; 18008 18009 return Select2; 18010}); 18011 18012S2.define('select2/compat/utils',[ 18013 'jquery' 18014], function ($) { 18015 function syncCssClasses ($dest, $src, adapter) { 18016 var classes, replacements = [], adapted; 18017 18018 classes = $.trim($dest.attr('class')); 18019 18020 if (classes) { 18021 classes = '' + classes; // for IE which returns object 18022 18023 $(classes.split(/\s+/)).each(function () { 18024 // Save all Select2 classes 18025 if (this.indexOf('select2-') === 0) { 18026 replacements.push(this); 18027 } 18028 }); 18029 } 18030 18031 classes = $.trim($src.attr('class')); 18032 18033 if (classes) { 18034 classes = '' + classes; // for IE which returns object 18035 18036 $(classes.split(/\s+/)).each(function () { 18037 // Only adapt non-Select2 classes 18038 if (this.indexOf('select2-') !== 0) { 18039 adapted = adapter(this); 18040 18041 if (adapted != null) { 18042 replacements.push(adapted); 18043 } 18044 } 18045 }); 18046 } 18047 18048 $dest.attr('class', replacements.join(' ')); 18049 } 18050 18051 return { 18052 syncCssClasses: syncCssClasses 18053 }; 18054}); 18055 18056S2.define('select2/compat/containerCss',[ 18057 'jquery', 18058 './utils' 18059], function ($, CompatUtils) { 18060 // No-op CSS adapter that discards all classes by default 18061 function _containerAdapter (clazz) { 18062 return null; 18063 } 18064 18065 function ContainerCSS () { } 18066 18067 ContainerCSS.prototype.render = function (decorated) { 18068 var $container = decorated.call(this); 18069 18070 var containerCssClass = this.options.get('containerCssClass') || ''; 18071 18072 if ($.isFunction(containerCssClass)) { 18073 containerCssClass = containerCssClass(this.$element); 18074 } 18075 18076 var containerCssAdapter = this.options.get('adaptContainerCssClass'); 18077 containerCssAdapter = containerCssAdapter || _containerAdapter; 18078 18079 if (containerCssClass.indexOf(':all:') !== -1) { 18080 containerCssClass = containerCssClass.replace(':all:', ''); 18081 18082 var _cssAdapter = containerCssAdapter; 18083 18084 containerCssAdapter = function (clazz) { 18085 var adapted = _cssAdapter(clazz); 18086 18087 if (adapted != null) { 18088 // Append the old one along with the adapted one 18089 return adapted + ' ' + clazz; 18090 } 18091 18092 return clazz; 18093 }; 18094 } 18095 18096 var containerCss = this.options.get('containerCss') || {}; 18097 18098 if ($.isFunction(containerCss)) { 18099 containerCss = containerCss(this.$element); 18100 } 18101 18102 CompatUtils.syncCssClasses($container, this.$element, containerCssAdapter); 18103 18104 $container.css(containerCss); 18105 $container.addClass(containerCssClass); 18106 18107 return $container; 18108 }; 18109 18110 return ContainerCSS; 18111}); 18112 18113S2.define('select2/compat/dropdownCss',[ 18114 'jquery', 18115 './utils' 18116], function ($, CompatUtils) { 18117 // No-op CSS adapter that discards all classes by default 18118 function _dropdownAdapter (clazz) { 18119 return null; 18120 } 18121 18122 function DropdownCSS () { } 18123 18124 DropdownCSS.prototype.render = function (decorated) { 18125 var $dropdown = decorated.call(this); 18126 18127 var dropdownCssClass = this.options.get('dropdownCssClass') || ''; 18128 18129 if ($.isFunction(dropdownCssClass)) { 18130 dropdownCssClass = dropdownCssClass(this.$element); 18131 } 18132 18133 var dropdownCssAdapter = this.options.get('adaptDropdownCssClass'); 18134 dropdownCssAdapter = dropdownCssAdapter || _dropdownAdapter; 18135 18136 if (dropdownCssClass.indexOf(':all:') !== -1) { 18137 dropdownCssClass = dropdownCssClass.replace(':all:', ''); 18138 18139 var _cssAdapter = dropdownCssAdapter; 18140 18141 dropdownCssAdapter = function (clazz) { 18142 var adapted = _cssAdapter(clazz); 18143 18144 if (adapted != null) { 18145 // Append the old one along with the adapted one 18146 return adapted + ' ' + clazz; 18147 } 18148 18149 return clazz; 18150 }; 18151 } 18152 18153 var dropdownCss = this.options.get('dropdownCss') || {}; 18154 18155 if ($.isFunction(dropdownCss)) { 18156 dropdownCss = dropdownCss(this.$element); 18157 } 18158 18159 CompatUtils.syncCssClasses($dropdown, this.$element, dropdownCssAdapter); 18160 18161 $dropdown.css(dropdownCss); 18162 $dropdown.addClass(dropdownCssClass); 18163 18164 return $dropdown; 18165 }; 18166 18167 return DropdownCSS; 18168}); 18169 18170S2.define('select2/compat/initSelection',[ 18171 'jquery' 18172], function ($) { 18173 function InitSelection (decorated, $element, options) { 18174 if (options.get('debug') && window.console && console.warn) { 18175 console.warn( 18176 'Select2: The `initSelection` option has been deprecated in favor' + 18177 ' of a custom data adapter that overrides the `current` method. ' + 18178 'This method is now called multiple times instead of a single ' + 18179 'time when the instance is initialized. Support will be removed ' + 18180 'for the `initSelection` option in future versions of Select2' 18181 ); 18182 } 18183 18184 this.initSelection = options.get('initSelection'); 18185 this._isInitialized = false; 18186 18187 decorated.call(this, $element, options); 18188 } 18189 18190 InitSelection.prototype.current = function (decorated, callback) { 18191 var self = this; 18192 18193 if (this._isInitialized) { 18194 decorated.call(this, callback); 18195 18196 return; 18197 } 18198 18199 this.initSelection.call(null, this.$element, function (data) { 18200 self._isInitialized = true; 18201 18202 if (!$.isArray(data)) { 18203 data = [data]; 18204 } 18205 18206 callback(data); 18207 }); 18208 }; 18209 18210 return InitSelection; 18211}); 18212 18213S2.define('select2/compat/inputData',[ 18214 'jquery' 18215], function ($) { 18216 function InputData (decorated, $element, options) { 18217 this._currentData = []; 18218 this._valueSeparator = options.get('valueSeparator') || ','; 18219 18220 if ($element.prop('type') === 'hidden') { 18221 if (options.get('debug') && console && console.warn) { 18222 console.warn( 18223 'Select2: Using a hidden input with Select2 is no longer ' + 18224 'supported and may stop working in the future. It is recommended ' + 18225 'to use a `<select>` element instead.' 18226 ); 18227 } 18228 } 18229 18230 decorated.call(this, $element, options); 18231 } 18232 18233 InputData.prototype.current = function (_, callback) { 18234 function getSelected (data, selectedIds) { 18235 var selected = []; 18236 18237 if (data.selected || $.inArray(data.id, selectedIds) !== -1) { 18238 data.selected = true; 18239 selected.push(data); 18240 } else { 18241 data.selected = false; 18242 } 18243 18244 if (data.children) { 18245 selected.push.apply(selected, getSelected(data.children, selectedIds)); 18246 } 18247 18248 return selected; 18249 } 18250 18251 var selected = []; 18252 18253 for (var d = 0; d < this._currentData.length; d++) { 18254 var data = this._currentData[d]; 18255 18256 selected.push.apply( 18257 selected, 18258 getSelected( 18259 data, 18260 this.$element.val().split( 18261 this._valueSeparator 18262 ) 18263 ) 18264 ); 18265 } 18266 18267 callback(selected); 18268 }; 18269 18270 InputData.prototype.select = function (_, data) { 18271 if (!this.options.get('multiple')) { 18272 this.current(function (allData) { 18273 $.map(allData, function (data) { 18274 data.selected = false; 18275 }); 18276 }); 18277 18278 this.$element.val(data.id); 18279 this.$element.trigger('change'); 18280 } else { 18281 var value = this.$element.val(); 18282 value += this._valueSeparator + data.id; 18283 18284 this.$element.val(value); 18285 this.$element.trigger('change'); 18286 } 18287 }; 18288 18289 InputData.prototype.unselect = function (_, data) { 18290 var self = this; 18291 18292 data.selected = false; 18293 18294 this.current(function (allData) { 18295 var values = []; 18296 18297 for (var d = 0; d < allData.length; d++) { 18298 var item = allData[d]; 18299 18300 if (data.id == item.id) { 18301 continue; 18302 } 18303 18304 values.push(item.id); 18305 } 18306 18307 self.$element.val(values.join(self._valueSeparator)); 18308 self.$element.trigger('change'); 18309 }); 18310 }; 18311 18312 InputData.prototype.query = function (_, params, callback) { 18313 var results = []; 18314 18315 for (var d = 0; d < this._currentData.length; d++) { 18316 var data = this._currentData[d]; 18317 18318 var matches = this.matches(params, data); 18319 18320 if (matches !== null) { 18321 results.push(matches); 18322 } 18323 } 18324 18325 callback({ 18326 results: results 18327 }); 18328 }; 18329 18330 InputData.prototype.addOptions = function (_, $options) { 18331 var options = $.map($options, function ($option) { 18332 return $.data($option[0], 'data'); 18333 }); 18334 18335 this._currentData.push.apply(this._currentData, options); 18336 }; 18337 18338 return InputData; 18339}); 18340 18341S2.define('select2/compat/matcher',[ 18342 'jquery' 18343], function ($) { 18344 function oldMatcher (matcher) { 18345 function wrappedMatcher (params, data) { 18346 var match = $.extend(true, {}, data); 18347 18348 if (params.term == null || $.trim(params.term) === '') { 18349 return match; 18350 } 18351 18352 if (data.children) { 18353 for (var c = data.children.length - 1; c >= 0; c--) { 18354 var child = data.children[c]; 18355 18356 // Check if the child object matches 18357 // The old matcher returned a boolean true or false 18358 var doesMatch = matcher(params.term, child.text, child); 18359 18360 // If the child didn't match, pop it off 18361 if (!doesMatch) { 18362 match.children.splice(c, 1); 18363 } 18364 } 18365 18366 if (match.children.length > 0) { 18367 return match; 18368 } 18369 } 18370 18371 if (matcher(params.term, data.text, data)) { 18372 return match; 18373 } 18374 18375 return null; 18376 } 18377 18378 return wrappedMatcher; 18379 } 18380 18381 return oldMatcher; 18382}); 18383 18384S2.define('select2/compat/query',[ 18385 18386], function () { 18387 function Query (decorated, $element, options) { 18388 if (options.get('debug') && window.console && console.warn) { 18389 console.warn( 18390 'Select2: The `query` option has been deprecated in favor of a ' + 18391 'custom data adapter that overrides the `query` method. Support ' + 18392 'will be removed for the `query` option in future versions of ' + 18393 'Select2.' 18394 ); 18395 } 18396 18397 decorated.call(this, $element, options); 18398 } 18399 18400 Query.prototype.query = function (_, params, callback) { 18401 params.callback = callback; 18402 18403 var query = this.options.get('query'); 18404 18405 query.call(null, params); 18406 }; 18407 18408 return Query; 18409}); 18410 18411S2.define('select2/dropdown/attachContainer',[ 18412 18413], function () { 18414 function AttachContainer (decorated, $element, options) { 18415 decorated.call(this, $element, options); 18416 } 18417 18418 AttachContainer.prototype.position = 18419 function (decorated, $dropdown, $container) { 18420 var $dropdownContainer = $container.find('.dropdown-wrapper'); 18421 $dropdownContainer.append($dropdown); 18422 18423 $dropdown.addClass('select2-dropdown--below'); 18424 $container.addClass('select2-container--below'); 18425 }; 18426 18427 return AttachContainer; 18428}); 18429 18430S2.define('select2/dropdown/stopPropagation',[ 18431 18432], function () { 18433 function StopPropagation () { } 18434 18435 StopPropagation.prototype.bind = function (decorated, container, $container) { 18436 decorated.call(this, container, $container); 18437 18438 var stoppedEvents = [ 18439 'blur', 18440 'change', 18441 'click', 18442 'dblclick', 18443 'focus', 18444 'focusin', 18445 'focusout', 18446 'input', 18447 'keydown', 18448 'keyup', 18449 'keypress', 18450 'mousedown', 18451 'mouseenter', 18452 'mouseleave', 18453 'mousemove', 18454 'mouseover', 18455 'mouseup', 18456 'search', 18457 'touchend', 18458 'touchstart' 18459 ]; 18460 18461 this.$dropdown.on(stoppedEvents.join(' '), function (evt) { 18462 evt.stopPropagation(); 18463 }); 18464 }; 18465 18466 return StopPropagation; 18467}); 18468 18469S2.define('select2/selection/stopPropagation',[ 18470 18471], function () { 18472 function StopPropagation () { } 18473 18474 StopPropagation.prototype.bind = function (decorated, container, $container) { 18475 decorated.call(this, container, $container); 18476 18477 var stoppedEvents = [ 18478 'blur', 18479 'change', 18480 'click', 18481 'dblclick', 18482 'focus', 18483 'focusin', 18484 'focusout', 18485 'input', 18486 'keydown', 18487 'keyup', 18488 'keypress', 18489 'mousedown', 18490 'mouseenter', 18491 'mouseleave', 18492 'mousemove', 18493 'mouseover', 18494 'mouseup', 18495 'search', 18496 'touchend', 18497 'touchstart' 18498 ]; 18499 18500 this.$selection.on(stoppedEvents.join(' '), function (evt) { 18501 evt.stopPropagation(); 18502 }); 18503 }; 18504 18505 return StopPropagation; 18506}); 18507 18508/*! 18509 * jQuery Mousewheel 3.1.13 18510 * 18511 * Copyright jQuery Foundation and other contributors 18512 * Released under the MIT license 18513 * http://jquery.org/license 18514 */ 18515 18516(function (factory) { 18517 if ( typeof S2.define === 'function' && S2.define.amd ) { 18518 // AMD. Register as an anonymous module. 18519 S2.define('jquery-mousewheel',['jquery'], factory); 18520 } else if (typeof exports === 'object') { 18521 // Node/CommonJS style for Browserify 18522 module.exports = factory; 18523 } else { 18524 // Browser globals 18525 factory(jQuery); 18526 } 18527}(function ($) { 18528 18529 var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'], 18530 toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ? 18531 ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'], 18532 slice = Array.prototype.slice, 18533 nullLowestDeltaTimeout, lowestDelta; 18534 18535 if ( $.event.fixHooks ) { 18536 for ( var i = toFix.length; i; ) { 18537 $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks; 18538 } 18539 } 18540 18541 var special = $.event.special.mousewheel = { 18542 version: '3.1.12', 18543 18544 setup: function() { 18545 if ( this.addEventListener ) { 18546 for ( var i = toBind.length; i; ) { 18547 this.addEventListener( toBind[--i], handler, false ); 18548 } 18549 } else { 18550 this.onmousewheel = handler; 18551 } 18552 // Store the line height and page height for this particular element 18553 $.data(this, 'mousewheel-line-height', special.getLineHeight(this)); 18554 $.data(this, 'mousewheel-page-height', special.getPageHeight(this)); 18555 }, 18556 18557 teardown: function() { 18558 if ( this.removeEventListener ) { 18559 for ( var i = toBind.length; i; ) { 18560 this.removeEventListener( toBind[--i], handler, false ); 18561 } 18562 } else { 18563 this.onmousewheel = null; 18564 } 18565 // Clean up the data we added to the element 18566 $.removeData(this, 'mousewheel-line-height'); 18567 $.removeData(this, 'mousewheel-page-height'); 18568 }, 18569 18570 getLineHeight: function(elem) { 18571 var $elem = $(elem), 18572 $parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent'](); 18573 if (!$parent.length) { 18574 $parent = $('body'); 18575 } 18576 return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16; 18577 }, 18578 18579 getPageHeight: function(elem) { 18580 return $(elem).height(); 18581 }, 18582 18583 settings: { 18584 adjustOldDeltas: true, // see shouldAdjustOldDeltas() below 18585 normalizeOffset: true // calls getBoundingClientRect for each event 18586 } 18587 }; 18588 18589 $.fn.extend({ 18590 // mousewheel: function(fn) { 18591 // return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel'); 18592 // }, 18593 // 18594 // unmousewheel: function(fn) { 18595 // return this.unbind('mousewheel', fn); 18596 // } 18597 }); 18598 18599 18600 function handler(event) { 18601 var orgEvent = event || window.event, 18602 args = slice.call(arguments, 1), 18603 delta = 0, 18604 deltaX = 0, 18605 deltaY = 0, 18606 absDelta = 0, 18607 offsetX = 0, 18608 offsetY = 0; 18609 event = $.event.fix(orgEvent); 18610 event.type = 'mousewheel'; 18611 18612 // Old school scrollwheel delta 18613 if ( 'detail' in orgEvent ) { deltaY = orgEvent.detail * -1; } 18614 if ( 'wheelDelta' in orgEvent ) { deltaY = orgEvent.wheelDelta; } 18615 if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY; } 18616 if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; } 18617 18618 // Firefox < 17 horizontal scrolling related to DOMMouseScroll event 18619 if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) { 18620 deltaX = deltaY * -1; 18621 deltaY = 0; 18622 } 18623 18624 // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy 18625 delta = deltaY === 0 ? deltaX : deltaY; 18626 18627 // New school wheel delta (wheel event) 18628 if ( 'deltaY' in orgEvent ) { 18629 deltaY = orgEvent.deltaY * -1; 18630 delta = deltaY; 18631 } 18632 if ( 'deltaX' in orgEvent ) { 18633 deltaX = orgEvent.deltaX; 18634 if ( deltaY === 0 ) { delta = deltaX * -1; } 18635 } 18636 18637 // No change actually happened, no reason to go any further 18638 if ( deltaY === 0 && deltaX === 0 ) { return; } 18639 18640 // Need to convert lines and pages to pixels if we aren't already in pixels 18641 // There are three delta modes: 18642 // * deltaMode 0 is by pixels, nothing to do 18643 // * deltaMode 1 is by lines 18644 // * deltaMode 2 is by pages 18645 if ( orgEvent.deltaMode === 1 ) { 18646 var lineHeight = $.data(this, 'mousewheel-line-height'); 18647 delta *= lineHeight; 18648 deltaY *= lineHeight; 18649 deltaX *= lineHeight; 18650 } else if ( orgEvent.deltaMode === 2 ) { 18651 var pageHeight = $.data(this, 'mousewheel-page-height'); 18652 delta *= pageHeight; 18653 deltaY *= pageHeight; 18654 deltaX *= pageHeight; 18655 } 18656 18657 // Store lowest absolute delta to normalize the delta values 18658 absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) ); 18659 18660 if ( !lowestDelta || absDelta < lowestDelta ) { 18661 lowestDelta = absDelta; 18662 18663 // Adjust older deltas if necessary 18664 if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) { 18665 lowestDelta /= 40; 18666 } 18667 } 18668 18669 // Adjust older deltas if necessary 18670 if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) { 18671 // Divide all the things by 40! 18672 delta /= 40; 18673 deltaX /= 40; 18674 deltaY /= 40; 18675 } 18676 18677 // Get a whole, normalized value for the deltas 18678 delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta); 18679 deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta); 18680 deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta); 18681 18682 // Normalise offsetX and offsetY properties 18683 if ( special.settings.normalizeOffset && this.getBoundingClientRect ) { 18684 var boundingRect = this.getBoundingClientRect(); 18685 offsetX = event.clientX - boundingRect.left; 18686 offsetY = event.clientY - boundingRect.top; 18687 } 18688 18689 // Add information to the event object 18690 event.deltaX = deltaX; 18691 event.deltaY = deltaY; 18692 event.deltaFactor = lowestDelta; 18693 event.offsetX = offsetX; 18694 event.offsetY = offsetY; 18695 // Go ahead and set deltaMode to 0 since we converted to pixels 18696 // Although this is a little odd since we overwrite the deltaX/Y 18697 // properties with normalized deltas. 18698 event.deltaMode = 0; 18699 18700 // Add event and delta to the front of the arguments 18701 args.unshift(event, delta, deltaX, deltaY); 18702 18703 // Clearout lowestDelta after sometime to better 18704 // handle multiple device types that give different 18705 // a different lowestDelta 18706 // Ex: trackpad = 3 and mouse wheel = 120 18707 if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); } 18708 nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200); 18709 18710 return ($.event.dispatch || $.event.handle).apply(this, args); 18711 } 18712 18713 function nullLowestDelta() { 18714 lowestDelta = null; 18715 } 18716 18717 function shouldAdjustOldDeltas(orgEvent, absDelta) { 18718 // If this is an older event and the delta is divisable by 120, 18719 // then we are assuming that the browser is treating this as an 18720 // older mouse wheel event and that we should divide the deltas 18721 // by 40 to try and get a more usable deltaFactor. 18722 // Side note, this actually impacts the reported scroll distance 18723 // in older browsers and can cause scrolling to be slower than native. 18724 // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false. 18725 return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0; 18726 } 18727 18728})); 18729 18730S2.define('jquery.select2',[ 18731 'jquery', 18732 'jquery-mousewheel', 18733 18734 './select2/core', 18735 './select2/defaults' 18736], function ($, _, Select2, Defaults) { 18737 if ($.fn.select2 == null) { 18738 // All methods that should return the element 18739 var thisMethods = ['open', 'close', 'destroy']; 18740 18741 $.fn.select2 = function (options) { 18742 options = options || {}; 18743 18744 if (typeof options === 'object') { 18745 this.each(function () { 18746 var instanceOptions = $.extend(true, {}, options); 18747 18748 var instance = new Select2($(this), instanceOptions); 18749 }); 18750 18751 return this; 18752 } else if (typeof options === 'string') { 18753 var ret; 18754 18755 this.each(function () { 18756 var instance = $(this).data('select2'); 18757 18758 if (instance == null && window.console && console.error) { 18759 console.error( 18760 'The select2(\'' + options + '\') method was called on an ' + 18761 'element that is not using Select2.' 18762 ); 18763 } 18764 18765 var args = Array.prototype.slice.call(arguments, 1); 18766 18767 ret = instance[options].apply(instance, args); 18768 }); 18769 18770 // Check if we should be returning `this` 18771 if ($.inArray(options, thisMethods) > -1) { 18772 return this; 18773 } 18774 18775 return ret; 18776 } else { 18777 throw new Error('Invalid arguments for Select2: ' + options); 18778 } 18779 }; 18780 } 18781 18782 if ($.fn.select2.defaults == null) { 18783 $.fn.select2.defaults = Defaults; 18784 } 18785 18786 return Select2; 18787}); 18788 18789 // Return the AMD loader configuration so it can be used outside of this file 18790 return { 18791 define: S2.define, 18792 require: S2.require 18793 }; 18794}()); 18795 18796 // Autoload the jQuery bindings 18797 // We know that all of the modules exist above this, so we're safe 18798 var select2 = S2.require('jquery.select2'); 18799 18800 // Hold the AMD module references on the jQuery function that was just loaded 18801 // This allows Select2 to use the internal loader outside of this file, such 18802 // as in the language files. 18803 jQuery.fn.select2.amd = S2; 18804 18805 // Return the Select2 instance for anyone who is importing it. 18806 return select2; 18807})); 18808 18809/*! 18810 * jQuery Mousewheel 3.1.13 18811 * 18812 * Copyright jQuery Foundation and other contributors 18813 * Released under the MIT license 18814 * http://jquery.org/license 18815 */ 18816 18817(function (factory) { 18818 if ( typeof define === 'function' && define.amd ) { 18819 // AMD. Register as an anonymous module. 18820 define(['jquery'], factory); 18821 } else if (typeof exports === 'object') { 18822 // Node/CommonJS style for Browserify 18823 module.exports = factory; 18824 } else { 18825 // Browser globals 18826 factory(jQuery); 18827 } 18828}(function ($) { 18829 18830 var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'], 18831 toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ? 18832 ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'], 18833 slice = Array.prototype.slice, 18834 nullLowestDeltaTimeout, lowestDelta; 18835 18836 if ( $.event.fixHooks ) { 18837 for ( var i = toFix.length; i; ) { 18838 $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks; 18839 } 18840 } 18841 18842 var special = $.event.special.mousewheel = { 18843 version: '3.1.12', 18844 18845 setup: function() { 18846 if ( this.addEventListener ) { 18847 for ( var i = toBind.length; i; ) { 18848 this.addEventListener( toBind[--i], handler, false ); 18849 } 18850 } else { 18851 this.onmousewheel = handler; 18852 } 18853 // Store the line height and page height for this particular element 18854 $.data(this, 'mousewheel-line-height', special.getLineHeight(this)); 18855 $.data(this, 'mousewheel-page-height', special.getPageHeight(this)); 18856 }, 18857 18858 teardown: function() { 18859 if ( this.removeEventListener ) { 18860 for ( var i = toBind.length; i; ) { 18861 this.removeEventListener( toBind[--i], handler, false ); 18862 } 18863 } else { 18864 this.onmousewheel = null; 18865 } 18866 // Clean up the data we added to the element 18867 $.removeData(this, 'mousewheel-line-height'); 18868 $.removeData(this, 'mousewheel-page-height'); 18869 }, 18870 18871 getLineHeight: function(elem) { 18872 var $elem = $(elem), 18873 $parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent'](); 18874 if (!$parent.length) { 18875 $parent = $('body'); 18876 } 18877 return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16; 18878 }, 18879 18880 getPageHeight: function(elem) { 18881 return $(elem).height(); 18882 }, 18883 18884 settings: { 18885 adjustOldDeltas: true, // see shouldAdjustOldDeltas() below 18886 normalizeOffset: true // calls getBoundingClientRect for each event 18887 } 18888 }; 18889 18890 $.fn.extend({ 18891 mousewheel: function(fn) { 18892 return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel'); 18893 }, 18894 18895 unmousewheel: function(fn) { 18896 return this.unbind('mousewheel', fn); 18897 } 18898 }); 18899 18900 18901 function handler(event) { 18902 var orgEvent = event || window.event, 18903 args = slice.call(arguments, 1), 18904 delta = 0, 18905 deltaX = 0, 18906 deltaY = 0, 18907 absDelta = 0, 18908 offsetX = 0, 18909 offsetY = 0; 18910 event = $.event.fix(orgEvent); 18911 event.type = 'mousewheel'; 18912 18913 // Old school scrollwheel delta 18914 if ( 'detail' in orgEvent ) { deltaY = orgEvent.detail * -1; } 18915 if ( 'wheelDelta' in orgEvent ) { deltaY = orgEvent.wheelDelta; } 18916 if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY; } 18917 if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; } 18918 18919 // Firefox < 17 horizontal scrolling related to DOMMouseScroll event 18920 if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) { 18921 deltaX = deltaY * -1; 18922 deltaY = 0; 18923 } 18924 18925 // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy 18926 delta = deltaY === 0 ? deltaX : deltaY; 18927 18928 // New school wheel delta (wheel event) 18929 if ( 'deltaY' in orgEvent ) { 18930 deltaY = orgEvent.deltaY * -1; 18931 delta = deltaY; 18932 } 18933 if ( 'deltaX' in orgEvent ) { 18934 deltaX = orgEvent.deltaX; 18935 if ( deltaY === 0 ) { delta = deltaX * -1; } 18936 } 18937 18938 // No change actually happened, no reason to go any further 18939 if ( deltaY === 0 && deltaX === 0 ) { return; } 18940 18941 // Need to convert lines and pages to pixels if we aren't already in pixels 18942 // There are three delta modes: 18943 // * deltaMode 0 is by pixels, nothing to do 18944 // * deltaMode 1 is by lines 18945 // * deltaMode 2 is by pages 18946 if ( orgEvent.deltaMode === 1 ) { 18947 var lineHeight = $.data(this, 'mousewheel-line-height'); 18948 delta *= lineHeight; 18949 deltaY *= lineHeight; 18950 deltaX *= lineHeight; 18951 } else if ( orgEvent.deltaMode === 2 ) { 18952 var pageHeight = $.data(this, 'mousewheel-page-height'); 18953 delta *= pageHeight; 18954 deltaY *= pageHeight; 18955 deltaX *= pageHeight; 18956 } 18957 18958 // Store lowest absolute delta to normalize the delta values 18959 absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) ); 18960 18961 if ( !lowestDelta || absDelta < lowestDelta ) { 18962 lowestDelta = absDelta; 18963 18964 // Adjust older deltas if necessary 18965 if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) { 18966 lowestDelta /= 40; 18967 } 18968 } 18969 18970 // Adjust older deltas if necessary 18971 if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) { 18972 // Divide all the things by 40! 18973 delta /= 40; 18974 deltaX /= 40; 18975 deltaY /= 40; 18976 } 18977 18978 // Get a whole, normalized value for the deltas 18979 delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta); 18980 deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta); 18981 deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta); 18982 18983 // Normalise offsetX and offsetY properties 18984 if ( special.settings.normalizeOffset && this.getBoundingClientRect ) { 18985 var boundingRect = this.getBoundingClientRect(); 18986 offsetX = event.clientX - boundingRect.left; 18987 offsetY = event.clientY - boundingRect.top; 18988 } 18989 18990 // Add information to the event object 18991 event.deltaX = deltaX; 18992 event.deltaY = deltaY; 18993 event.deltaFactor = lowestDelta; 18994 event.offsetX = offsetX; 18995 event.offsetY = offsetY; 18996 // Go ahead and set deltaMode to 0 since we converted to pixels 18997 // Although this is a little odd since we overwrite the deltaX/Y 18998 // properties with normalized deltas. 18999 event.deltaMode = 0; 19000 19001 // Add event and delta to the front of the arguments 19002 args.unshift(event, delta, deltaX, deltaY); 19003 19004 // Clearout lowestDelta after sometime to better 19005 // handle multiple device types that give different 19006 // a different lowestDelta 19007 // Ex: trackpad = 3 and mouse wheel = 120
19008 if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); } 19009 nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200); 19010 19011 return ($.event.dispatch || $.event.handle).apply(this, args); 19012 } 19013 19014 function nullLowestDelta() { 19015 lowestDelta = null; 19016 } 19017 19018 function shouldAdjustOldDeltas(orgEvent, absDelta) { 19019 // If this is an older event and the delta is divisable by 120, 19020 // then we are assuming that the browser is treating this as an 19021 // older mouse wheel event and that we should divide the deltas 19022 // by 40 to try and get a more usable deltaFactor. 19023 // Side note, this actually impacts the reported scroll distance 19024 // in older browsers and can cause scrolling to be slower than native. 19025 // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false. 19026 return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0; 19027 } 19028 19029})); 19030 19031/* jquery.nicescroll 19032-- version 3.6.6 19033-- copyright 2015-11-17 InuYaksa*2015 19034-- licensed under the MIT 19035-- 19036-- http://nicescroll.areaaperta.com/ 19037-- https://github.com/inuyaksa/jquery.nicescroll 19038-- 19039*/ 19040 19041(function(factory) { 19042 if (typeof define === 'function' && define.amd) { 19043 // AMD. Register as anonymous module. 19044 define(['jquery'], factory); 19045 } else if (typeof exports === 'object') { 19046 // Node/CommonJS. 19047 module.exports = factory(require('jquery')); 19048 } else { 19049 // Browser globals. 19050 factory(jQuery); 19051 } 19052}(function(jQuery) { 19053 "use strict"; 19054 19055 // globals 19056 var domfocus = false; 19057 var mousefocus = false; 19058 var tabindexcounter = 0; 19059 var ascrailcounter = 2000; 19060 var globalmaxzindex = 0; 19061 19062 var $ = jQuery; // sandbox 19063 19064 // http://stackoverflow.com/questions/2161159/get-script-path 19065 function getScriptPath() { 19066 var scripts = document.getElementsByTagName('script'); 19067 var path = scripts.length ? scripts[scripts.length - 1].src.split('?')[0] : ''; 19068 return (path.split('/').length > 0) ? path.split('/').slice(0, -1).join('/') + '/' : ''; 19069 } 19070 19071 var vendors = ['webkit','ms','moz','o']; 19072 19073 var setAnimationFrame = window.requestAnimationFrame || false; 19074 var clearAnimationFrame = window.cancelAnimationFrame || false; 19075 19076 if (!setAnimationFrame) { // legacy detection 19077 for (var vx in vendors) { 19078 var v = vendors[vx]; 19079 if (!setAnimationFrame) setAnimationFrame = window[v + 'RequestAnimationFrame']; 19080 if (!clearAnimationFrame) clearAnimationFrame = window[v + 'CancelAnimationFrame'] || window[v + 'CancelRequestAnimationFrame']; 19081 } 19082 } 19083 19084 var ClsMutationObserver = window.MutationObserver || window.WebKitMutationObserver || false; 19085 19086 var _globaloptions = { 19087 zindex: "auto", 19088 cursoropacitymin: 0, 19089 cursoropacitymax: 1, 19090 cursorcolor: "#424242", 19091 cursorwidth: "5px", 19092 cursorborder: "1px solid #fff", 19093 cursorborderradius: "5px", 19094 scrollspeed: 60, 19095 mousescrollstep: 8 * 3, 19096 touchbehavior: false, 19097 hwacceleration: true, 19098 usetransition: true, 19099 boxzoom: false, 19100 dblclickzoom: true, 19101 gesturezoom: true, 19102 grabcursorenabled: true, 19103 autohidemode: true, 19104 background: "", 19105 iframeautoresize: true, 19106 cursorminheight: 32, 19107 preservenativescrolling: true, 19108 railoffset: false, 19109 railhoffset: false, 19110 bouncescroll: true, 19111 spacebarenabled: true, 19112 railpadding: { 19113 top: 0, 19114 right: 0, 19115 left: 0, 19116 bottom: 0 19117 }, 19118 disableoutline: true, 19119 horizrailenabled: true, 19120 railalign: "right", 19121 railvalign: "bottom", 19122 enabletranslate3d: true, 19123 enablemousewheel: true, 19124 enablekeyboard: true, 19125 smoothscroll: true, 19126 sensitiverail: true, 19127 enablemouselockapi: true, 19128 // cursormaxheight:false, 19129 cursorfixedheight: false, 19130 directionlockdeadzone: 6, 19131 hidecursordelay: 400, 19132 nativeparentscrolling: true, 19133 enablescrollonselection: true, 19134 overflowx: true, 19135 overflowy: true, 19136 cursordragspeed: 0.3, 19137 rtlmode: "auto", 19138 cursordragontouch: false, 19139 oneaxismousemode: "auto", 19140 scriptpath: getScriptPath(), 19141 preventmultitouchscrolling: true 19142 }; 19143 19144 var browserdetected = false;
19145 19146 var getBrowserDetection = function() { 19147 19148 if (browserdetected) return browserdetected; 19149 19150 var _el = document.createElement('DIV'), 19151 _style = _el.style, 19152 _agent = navigator.userAgent, 19153 _platform = navigator.platform, 19154 d = {}; 19155 19156 d.haspointerlock = "pointerLockElement" in document || "webkitPointerLockElement" in document || "mozPointerLockElement" in document; 19157 19158 d.isopera = ("opera" in window); // 12- 19159 d.isopera12 = (d.isopera && ("getUserMedia" in navigator)); 19160 d.isoperamini = (Object.prototype.toString.call(window.operamini) === "[object OperaMini]"); 19161 19162 d.isie = (("all" in document) && ("attachEvent" in _el) && !d.isopera); //IE10- 19163 d.isieold = (d.isie && !("msInterpolationMode" in _style)); // IE6 and older 19164 d.isie7 = d.isie && !d.isieold && (!("documentMode" in document) || (document.documentMode == 7)); 19165 d.isie8 = d.isie && ("documentMode" in document) && (document.documentMode == 8); 19166 d.isie9 = d.isie && ("performance" in window) && (document.documentMode >= 9); 19167 d.isie10 = d.isie && ("performance" in window) && (document.documentMode == 10); 19168 d.isie11 = ("msRequestFullscreen" in _el) && (document.documentMode >= 11); // IE11+ 19169 d.isieedge = (navigator.userAgent.match(/Edge\/12\./)); 19170 19171 d.isie9mobile = /iemobile.9/i.test(_agent); //wp 7.1 mango 19172 if (d.isie9mobile) d.isie9 = false; 19173 d.isie7mobile = (!d.isie9mobile && d.isie7) && /iemobile/i.test(_agent); //wp 7.0 19174 19175 d.ismozilla = ("MozAppearance" in _style); 19176 19177 d.iswebkit = ("WebkitAppearance" in _style); 19178 19179 d.ischrome = ("chrome" in window); 19180 d.ischrome22 = (d.ischrome && d.haspointerlock); 19181 d.ischrome26 = (d.ischrome && ("transition" in _style)); // issue with transform detection (maintain prefix) 19182 19183 d.cantouch = ("ontouchstart" in document.documentElement) || ("ontouchstart" in window); // detection for Chrome Touch Emulation 19184 d.hasmstouch = (window.MSPointerEvent || false); // IE10 pointer events 19185 d.hasw3ctouch = (window.PointerEvent || false) && ((navigator.MaxTouchPoints > 0)||(navigator.msMaxTouchPoints > 0)); //IE11 pointer events, following W3C Pointer Events spec 19186 19187 d.ismac = /^mac$/i.test(_platform); 19188 19189 d.isios = (d.cantouch && /iphone|ipad|ipod/i.test(_platform)); 19190 d.isios4 = ((d.isios) && !("seal" in Object)); 19191 d.isios7 = ((d.isios)&&("webkitHidden" in document)); //iOS 7+ 19192 19193 d.isandroid = (/android/i.test(_agent)); 19194 19195 d.haseventlistener = ("addEventListener" in _el); 19196 19197 d.trstyle = false; 19198 d.hastransform = false; 19199 d.hastranslate3d = false; 19200 d.transitionstyle = false; 19201 d.hastransition = false; 19202 d.transitionend = false; 19203 19204 var a; 19205 var check = ['transform', 'msTransform', 'webkitTransform', 'MozTransform', 'OTransform']; 19206 for (a = 0; a < check.length; a++) { 19207 if (typeof _style[check[a]] != "undefined") { 19208 d.trstyle = check[a]; 19209 break; 19210 } 19211 } 19212 d.hastransform = (!!d.trstyle); 19213 if (d.hastransform) { 19214 _style[d.trstyle] = "translate3d(1px,2px,3px)"; 19215 d.hastranslate3d = /translate3d/.test(_style[d.trstyle]); 19216 } 19217 19218 d.transitionstyle = false; 19219 d.prefixstyle = ''; 19220 d.transitionend = false; 19221 check = ['transition', 'webkitTransition', 'msTransition', 'MozTransition', 'OTransition', 'OTransition', 'KhtmlTransition']; 19222 var prefix = ['', '-webkit-', '-ms-', '-moz-', '-o-', '-o', '-khtml-']; 19223 var evs = ['transitionend', 'webkitTransitionEnd', 'msTransitionEnd', 'transitionend', 'otransitionend', 'oTransitionEnd', 'KhtmlTransitionEnd']; 19224 for (a = 0; a < check.length; a++) { 19225 if (check[a] in _style) { 19226 d.transitionstyle = check[a]; 19227 d.prefixstyle = prefix[a]; 19228 d.transitionend = evs[a]; 19229 break; 19230 } 19231 } 19232 if (d.ischrome26) { // always use prefix 19233 d.prefixstyle = prefix[1]; 19234 } 19235 19236 d.hastransition = (d.transitionstyle); 19237 19238 function detectCursorGrab() { 19239 var lst = ['-webkit-grab', '-moz-grab', 'grab']; 19240 if ((d.ischrome && !d.ischrome22) || d.isie) lst = []; // force setting for IE returns false positive and chrome cursor bug 19241 for (var a = 0; a < lst.length; a++) { 19242 var p = lst[a]; 19243 _style.cursor = p; 19244 if (_style.cursor == p) return p; 19245 } 19246 return 'url(//mail.google.com/mail/images/2/openhand.cur),n-resize'; // thank you google for custom cursor! 19247 } 19248 d.cursorgrabvalue = detectCursorGrab(); 19249 19250 d.hasmousecapture = ("setCapture" in _el); 19251 19252 d.hasMutationObserver = (ClsMutationObserver !== false); 19253 19254 _el = null; //memory released 19255 19256 browserdetected = d; 19257 19258 return d; 19259 }; 19260 19261 var NiceScrollClass = function(myopt, me) { 19262 19263 var self = this; 19264 19265 this.version = '3.6.6'; 19266 this.name = 'nicescroll'; 19267 19268 this.me = me; 19269 19270 this.opt = { 19271 doc: $("body"), 19272 win: false 19273 }; 19274 19275 $.extend(this.opt, _globaloptions); // clone opts 19276 19277 // Options for internal use 19278 this.opt.snapbackspeed = 80; 19279 19280 if (myopt || false) { 19281 for (var a in self.opt) { 19282 if (typeof myopt[a] != "undefined") self.opt[a] = myopt[a]; 19283 } 19284 } 19285 19286 this.doc = self.opt.doc; 19287 this.iddoc = (this.doc && this.doc[0]) ? this.doc[0].id || '' : ''; 19288 this.ispage = /^BODY|HTML/.test((self.opt.win) ? self.opt.win[0].nodeName : this.doc[0].nodeName); 19289 this.haswrapper = (self.opt.win !== false); 19290 this.win = self.opt.win || (this.ispage ? $(window) : this.doc); 19291 this.docscroll = (this.ispage && !this.haswrapper) ? $(window) : this.win; 19292 this.body = $("body"); 19293 this.viewport = false;
19294 19295 this.isfixed = false; 19296 19297 this.iframe = false; 19298 this.isiframe = ((this.doc[0].nodeName == 'IFRAME') && (this.win[0].nodeName == 'IFRAME')); 19299 19300 this.istextarea = (this.win[0].nodeName == 'TEXTAREA'); 19301 19302 this.forcescreen = false; //force to use screen position on events 19303 19304 this.canshowonmouseevent = (self.opt.autohidemode != "scroll"); 19305 19306 // Events jump table 19307 this.onmousedown = false; 19308 this.onmouseup = false; 19309 this.onmousemove = false; 19310 this.onmousewheel = false; 19311 this.onkeypress = false; 19312 this.ongesturezoom = false; 19313 this.onclick = false; 19314 19315 // Nicescroll custom events 19316 this.onscrollstart = false; 19317 this.onscrollend = false; 19318 this.onscrollcancel = false; 19319 19320 this.onzoomin = false; 19321 this.onzoomout = false; 19322 19323 // Let's start! 19324 this.view = false; 19325 this.page = false; 19326 19327 this.scroll = { 19328 x: 0, 19329 y: 0 19330 }; 19331 this.scrollratio = { 19332 x: 0, 19333 y: 0 19334 }; 19335 this.cursorheight = 20; 19336 this.scrollvaluemax = 0; 19337 19338 this.isrtlmode = (this.opt.rtlmode == "auto") ? ((this.win[0] == window ? this.body : this.win).css("direction") == "rtl") : (this.opt.rtlmode === true); 19339 // this.checkrtlmode = false;
19340 19341 this.scrollrunning = false; 19342 19343 this.scrollmom = false; 19344 19345 this.observer = false; // observer div changes 19346 this.observerremover = false; // observer on parent for remove detection 19347 this.observerbody = false; // observer on body for position change 19348 19349 do { 19350 this.id = "ascrail" + (ascrailcounter++); 19351 } while (document.getElementById(this.id)); 19352 19353 this.rail = false; 19354 this.cursor = false; 19355 this.cursorfreezed = false; 19356 this.selectiondrag = false; 19357 19358 this.zoom = false; 19359 this.zoomactive = false; 19360 19361 this.hasfocus = false; 19362 this.hasmousefocus = false; 19363 19364 this.visibility = true; 19365 this.railslocked = false; // locked by resize 19366 this.locked = false; // prevent lost of locked status sets by user 19367 this.hidden = false; // rails always hidden 19368 this.cursoractive = true; // user can interact with cursors 19369 19370 this.wheelprevented = false; //prevent mousewheel event 19371 19372 this.overflowx = self.opt.overflowx; 19373 this.overflowy = self.opt.overflowy; 19374 19375 this.nativescrollingarea = false; 19376 this.checkarea = 0; 19377 19378 this.events = []; // event list for unbind 19379 19380 this.saved = {}; // style saved 19381 19382 this.delaylist = {}; 19383 this.synclist = {}; 19384 19385 this.lastdeltax = 0; 19386 this.lastdeltay = 0; 19387 19388 this.detected = getBrowserDetection(); 19389 19390 var cap = $.extend({}, this.detected); 19391 19392 this.canhwscroll = (cap.hastransform && self.opt.hwacceleration); 19393 this.ishwscroll = (this.canhwscroll && self.haswrapper); 19394 19395 this.hasreversehr = (this.isrtlmode&&!cap.iswebkit); //RTL mode with reverse horizontal axis 19396 19397 this.istouchcapable = false; // desktop devices with touch screen support 19398 19399 //## Check WebKit-based desktop with touch support 19400 //## + Firefox 18 nightly build (desktop) false positive (or desktop with touch support) 19401 if (cap.cantouch && !cap.isios && !cap.isandroid && (cap.iswebkit || cap.ismozilla)) { 19402 this.istouchcapable = true; 19403 cap.cantouch = false; // parse normal desktop events 19404 } 19405 19406 //## disable MouseLock API on user request 19407 if (!self.opt.enablemouselockapi) { 19408 cap.hasmousecapture = false; 19409 cap.haspointerlock = false; 19410 } 19411 19412/* deprecated 19413 this.delayed = function(name, fn, tm, lazy) { 19414 }; 19415*/ 19416 19417 this.debounced = function(name, fn, tm) { 19418 var dd = self.delaylist[name]; 19419 self.delaylist[name] = fn; 19420 if (!dd) { 19421 self.debouncedelayed = setTimeout(function() { 19422 if (!self) return; 19423 var fn = self.delaylist[name]; 19424 self.delaylist[name] = false; 19425 fn.call(self); 19426 }, tm); 19427 } 19428 }; 19429 19430 var _onsync = false; 19431 19432 this.synched = function(name, fn) { 19433 19434 function requestSync() { 19435 if (_onsync) return; 19436 setAnimationFrame(function() { 19437 _onsync = false; 19438 for (var nn in self.synclist) { 19439 var fn = self.synclist[nn]; 19440 if (fn) fn.call(self); 19441 self.synclist[nn] = false; 19442 } 19443 }); 19444 _onsync = true; 19445 } 19446 19447 self.synclist[name] = fn; 19448 requestSync(); 19449 return name; 19450 }; 19451 19452 this.unsynched = function(name) { 19453 if (self.synclist[name]) self.synclist[name] = false; 19454 }; 19455 19456 this.css = function(el, pars) { // save & set 19457 for (var n in pars) { 19458 self.saved.css.push([el, n, el.css(n)]); 19459 el.css(n, pars[n]); 19460 } 19461 }; 19462 19463 this.scrollTop = function(val) { 19464 return (typeof val == "undefined") ? self.getScrollTop() : self.setScrollTop(val); 19465 }; 19466 19467 this.scrollLeft = function(val) { 19468 return (typeof val == "undefined") ? self.getScrollLeft() : self.setScrollLeft(val); 19469 }; 19470 19471 // derived by by Dan Pupius www.pupius.net 19472 var BezierClass = function(st, ed, spd, p1, p2, p3, p4) { 19473 19474 this.st = st; 19475 this.ed = ed; 19476 this.spd = spd; 19477 19478 this.p1 = p1 || 0; 19479 this.p2 = p2 || 1; 19480 this.p3 = p3 || 0; 19481 this.p4 = p4 || 1; 19482 19483 this.ts = (new Date()).getTime(); 19484 this.df = this.ed - this.st; 19485 }; 19486 BezierClass.prototype = { 19487 B2: function(t) { 19488 return 3 * t * t * (1 - t); 19489 }, 19490 B3: function(t) { 19491 return 3 * t * (1 - t) * (1 - t); 19492 }, 19493 B4: function(t) { 19494 return (1 - t) * (1 - t) * (1 - t); 19495 }, 19496 getNow: function() { 19497 var nw = (new Date()).getTime(); 19498 var pc = 1 - ((nw - this.ts) / this.spd); 19499 var bz = this.B2(pc) + this.B3(pc) + this.B4(pc); 19500 return (pc < 0) ? this.ed : this.st + Math.round(this.df * bz); 19501 }, 19502 update: function(ed, spd) { 19503 this.st = this.getNow(); 19504 this.ed = ed; 19505 this.spd = spd;
vendor: 3,300 bytes, lines 19506-19588
19506 this.ts = (new Date()).getTime(); 19507 this.df = this.ed - this.st; 19508 return this; 19509 } 19510 }; 19511 19512 //derived from http://stackoverflow.com/questions/11236090/ 19513 function getMatrixValues() { 19514 var tr = self.doc.css(cap.trstyle); 19515 if (tr && (tr.substr(0, 6) == "matrix")) { 19516 return tr.replace(/^.*\((.*)\)$/g, "$1").replace(/px/g, '').split(/, +/); 19517 } 19518 return false; 19519 } 19520 19521 if (this.ishwscroll) { 19522 // hw accelerated scroll 19523 this.doc.translate = { 19524 x: 0, 19525 y: 0, 19526 tx: "0px", 19527 ty: "0px" 19528 }; 19529 19530 //this one can help to enable hw accel on ios6 http://indiegamr.com/ios6-html-hardware-acceleration-changes-and-how-to-fix-them/ 19531 if (cap.hastranslate3d && cap.isios) this.doc.css("-webkit-backface-visibility", "hidden"); // prevent flickering http://stackoverflow.com/questions/3461441/ 19532 19533 this.getScrollTop = function(last) { 19534 if (!last) { 19535 var mtx = getMatrixValues(); 19536 if (mtx) return (mtx.length == 16) ? -mtx[13] : -mtx[5]; //matrix3d 16 on IE10 19537 if (self.timerscroll && self.timerscroll.bz) return self.timerscroll.bz.getNow(); 19538 } 19539 return self.doc.translate.y; 19540 }; 19541 19542 this.getScrollLeft = function(last) { 19543 if (!last) { 19544 var mtx = getMatrixValues(); 19545 if (mtx) return (mtx.length == 16) ? -mtx[12] : -mtx[4]; //matrix3d 16 on IE10 19546 if (self.timerscroll && self.timerscroll.bh) return self.timerscroll.bh.getNow(); 19547 } 19548 return self.doc.translate.x; 19549 }; 19550 19551 this.notifyScrollEvent = function(el) { 19552 var e = document.createEvent("UIEvents"); 19553 e.initUIEvent("scroll", false, true, window, 1); 19554 e.niceevent = true; 19555 el.dispatchEvent(e); 19556 }; 19557 19558 var cxscrollleft = (this.isrtlmode) ? 1 : -1; 19559 19560 if (cap.hastranslate3d && self.opt.enabletranslate3d) { 19561 this.setScrollTop = function(val, silent) { 19562 self.doc.translate.y = val; 19563 self.doc.translate.ty = (val * -1) + "px"; 19564 self.doc.css(cap.trstyle, "translate3d(" + self.doc.translate.tx + "," + self.doc.translate.ty + ",0px)"); 19565 if (!silent) self.notifyScrollEvent(self.win[0]); 19566 }; 19567 this.setScrollLeft = function(val, silent) { 19568 self.doc.translate.x = val; 19569 self.doc.translate.tx = (val * cxscrollleft) + "px"; 19570 self.doc.css(cap.trstyle, "translate3d(" + self.doc.translate.tx + "," + self.doc.translate.ty + ",0px)"); 19571 if (!silent) self.notifyScrollEvent(self.win[0]); 19572 }; 19573 } else { 19574 this.setScrollTop = function(val, silent) { 19575 self.doc.translate.y = val; 19576 self.doc.translate.ty = (val * -1) + "px"; 19577 self.doc.css(cap.trstyle, "translate(" + self.doc.translate.tx + "," + self.doc.translate.ty + ")"); 19578 if (!silent) self.notifyScrollEvent(self.win[0]); 19579 }; 19580 this.setScrollLeft = function(val, silent) { 19581 self.doc.translate.x = val; 19582 self.doc.translate.tx = (val * cxscrollleft) + "px"; 19583 self.doc.css(cap.trstyle, "translate(" + self.doc.translate.tx + "," + self.doc.translate.ty + ")"); 19584 if (!silent) self.notifyScrollEvent(self.win[0]); 19585 }; 19586 } 19587 } else { 19588 // native scroll
19589 this.getScrollTop = function() { 19590 return self.docscroll.scrollTop(); 19591 }; 19592 this.setScrollTop = function(val) { 19593 return setTimeout(function() {self.docscroll.scrollTop(val)}, 1); 19594 }; 19595 this.getScrollLeft = function() { 19596 if (self.detected.ismozilla && self.isrtlmode) 19597 return Math.abs(self.docscroll.scrollLeft()); 19598 return self.docscroll.scrollLeft(); 19599 }; 19600 this.setScrollLeft = function(val) { 19601 return setTimeout(function() {self.docscroll.scrollLeft((self.detected.ismozilla && self.isrtlmode) ? -val : val)}, 1); 19602 }; 19603 } 19604 19605 this.getTarget = function(e) { 19606 if (!e) return false; 19607 if (e.target) return e.target; 19608 if (e.srcElement) return e.srcElement; 19609 return false; 19610 }; 19611 19612 this.hasParent = function(e, id) { 19613 if (!e) return false; 19614 var el = e.target || e.srcElement || e || false; 19615 while (el && el.id != id) { 19616 el = el.parentNode || false; 19617 } 19618 return (el !== false); 19619 }; 19620 19621 function getZIndex() { 19622 var dom = self.win; 19623 if ("zIndex" in dom) return dom.zIndex(); // use jQuery UI method when available 19624 while (dom.length > 0) { 19625 if (dom[0].nodeType == 9) return false; 19626 var zi = dom.css('zIndex'); 19627 if (!isNaN(zi) && zi != 0) return parseInt(zi); 19628 dom = dom.parent(); 19629 } 19630 return false; 19631 } 19632 19633 //inspired by http://forum.jquery.com/topic/width-includes-border-width-when-set-to-thin-medium-thick-in-ie 19634 var _convertBorderWidth = { 19635 "thin": 1, 19636 "medium": 3, 19637 "thick": 5 19638 }; 19639 19640 function getWidthToPixel(dom, prop, chkheight) { 19641 var wd = dom.css(prop); 19642 var px = parseFloat(wd); 19643 if (isNaN(px)) { 19644 px = _convertBorderWidth[wd] || 0; 19645 var brd = (px == 3) ? ((chkheight) ? (self.win.outerHeight() - self.win.innerHeight()) : (self.win.outerWidth() - self.win.innerWidth())) : 1; //DON'T TRUST CSS 19646 if (self.isie8 && px) px += 1; 19647 return (brd) ? px : 0; 19648 } 19649 return px; 19650 } 19651 19652 this.getDocumentScrollOffset = function() { 19653 return {top:window.pageYOffset||document.documentElement.scrollTop, 19654 left:window.pageXOffset||document.documentElement.scrollLeft}; 19655 } 19656 19657 this.getOffset = function() { 19658 if (self.isfixed) { 19659 var ofs = self.win.offset(); // fix Chrome auto issue (when right/bottom props only) 19660 var scrl = self.getDocumentScrollOffset(); 19661 ofs.top-=scrl.top; 19662 ofs.left-=scrl.left; 19663 return ofs; 19664 } 19665 var ww = self.win.offset(); 19666 if (!self.viewport) return ww; 19667 var vp = self.viewport.offset(); 19668 return { 19669 top: ww.top - vp.top,// + self.viewport.scrollTop(), 19670 left: ww.left - vp.left // + self.viewport.scrollLeft() 19671 }; 19672 }; 19673 19674 this.updateScrollBar = function(len) { 19675 if (self.ishwscroll) { 19676 self.rail.css({ //** 19677 height: self.win.innerHeight() - (self.opt.railpadding.top + self.opt.railpadding.bottom) 19678 }); 19679 if (self.railh) self.railh.css({ //** 19680 width: self.win.innerWidth() - (self.opt.railpadding.left + self.opt.railpadding.right) 19681 }); 19682 19683 } else { 19684 var wpos = self.getOffset(); 19685 var pos = { 19686 top: wpos.top, 19687 left: wpos.left - (self.opt.railpadding.left + self.opt.railpadding.right) 19688 }; 19689 pos.top += getWidthToPixel(self.win, 'border-top-width', true); 19690 pos.left += (self.rail.align) ? self.win.outerWidth() - getWidthToPixel(self.win, 'border-right-width') - self.rail.width : getWidthToPixel(self.win, 'border-left-width'); 19691 19692 var off = self.opt.railoffset; 19693 if (off) { 19694 if (off.top) pos.top += off.top; 19695 if (off.left) pos.left += off.left; 19696 } 19697 19698 if (!self.railslocked) self.rail.css({ 19699 top: pos.top, 19700 left: pos.left, 19701 height: ((len) ? len.h : self.win.innerHeight()) - (self.opt.railpadding.top + self.opt.railpadding.bottom) 19702 }); 19703 19704 if (self.zoom) { 19705 self.zoom.css({ 19706 top: pos.top + 1, 19707 left: (self.rail.align == 1) ? pos.left - 20 : pos.left + self.rail.width + 4 19708 }); 19709 } 19710 19711 if (self.railh && !self.railslocked) { 19712 var pos = { 19713 top: wpos.top, 19714 left: wpos.left 19715 }; 19716 var off = self.opt.railhoffset; 19717 if (!!off) { 19718 if (!!off.top) pos.top += off.top; 19719 if (!!off.left) pos.left += off.left; 19720 } 19721 var y = (self.railh.align) ? pos.top + getWidthToPixel(self.win, 'border-top-width', true) + self.win.innerHeight() - self.railh.height : pos.top + getWidthToPixel(self.win, 'border-top-width', true); 19722 var x = pos.left + getWidthToPixel(self.win, 'border-left-width'); 19723 self.railh.css({ 19724 top: y - (self.opt.railpadding.top + self.opt.railpadding.bottom), 19725 left: x, 19726 width: self.railh.width 19727 }); 19728 } 19729 19730 19731 } 19732 }; 19733 19734 this.doRailClick = function(e, dbl, hr) { 19735 var fn, pg, cur, pos; 19736 19737 if (self.railslocked) return; 19738 self.cancelEvent(e); 19739 19740 if (dbl) { 19741 fn = (hr) ? self.doScrollLeft : self.doScrollTop; 19742 cur = (hr) ? ((e.pageX - self.railh.offset().left - (self.cursorwidth / 2)) * self.scrollratio.x) : ((e.pageY - self.rail.offset().top - (self.cursorheight / 2)) * self.scrollratio.y); 19743 fn(cur); 19744 } else { 19745 fn = (hr) ? self.doScrollLeftBy : self.doScrollBy; 19746 cur = (hr) ? self.scroll.x : self.scroll.y; 19747 pos = (hr) ? e.pageX - self.railh.offset().left : e.pageY - self.rail.offset().top; 19748 pg = (hr) ? self.view.w : self.view.h; 19749 fn((cur >= pos) ? pg: -pg);// (cur >= pos) ? fn(pg): fn(-pg); 19750 } 19751 19752 }; 19753 19754 self.hasanimationframe = (setAnimationFrame); 19755 self.hascancelanimationframe = (clearAnimationFrame); 19756 19757 if (!self.hasanimationframe) { 19758 setAnimationFrame = function(fn) { 19759 return setTimeout(fn, 15 - Math.floor((+new Date()) / 1000) % 16); 19760 }; // 1000/60)}; 19761 clearAnimationFrame = clearInterval; 19762 } else if (!self.hascancelanimationframe) clearAnimationFrame = function() { 19763 self.cancelAnimationFrame = true; 19764 }; 19765 19766 this.init = function() { 19767 19768 self.saved.css = []; 19769 19770 if (cap.isie7mobile) return true; // SORRY, DO NOT WORK! 19771 if (cap.isoperamini) return true; // SORRY, DO NOT WORK! 19772 19773 if (cap.hasmstouch) self.css((self.ispage) ? $("html") : self.win, {
19774 '-ms-touch-action': 'none' 19775 }); 19776 19777 self.zindex = "auto"; 19778 if (!self.ispage && self.opt.zindex == "auto") { 19779 self.zindex = getZIndex() || "auto"; 19780 } else { 19781 self.zindex = self.opt.zindex; 19782 } 19783 19784 if (!self.ispage && self.zindex != "auto") { 19785 if (self.zindex > globalmaxzindex) globalmaxzindex = self.zindex; 19786 } 19787 19788 if (self.isie && self.zindex == 0 && self.opt.zindex == "auto") { // fix IE auto == 0 19789 self.zindex = "auto"; 19790 } 19791 19792 if (!self.ispage || (!cap.cantouch && !cap.isieold && !cap.isie9mobile)) { 19793 19794 var cont = self.docscroll; 19795 if (self.ispage) cont = (self.haswrapper) ? self.win : self.doc; 19796 19797 if (!cap.isie9mobile) self.css(cont, { 19798 'overflow-y': 'hidden' 19799 }); 19800 19801 if (self.ispage && cap.isie7) { 19802 if (self.doc[0].nodeName == 'BODY') self.css($("html"), { 19803 'overflow-y': 'hidden' 19804 }); //IE7 double scrollbar issue 19805 else if (self.doc[0].nodeName == 'HTML') self.css($("body"), { 19806 'overflow-y': 'hidden' 19807 }); //IE7 double scrollbar issue 19808 } 19809 19810 if (cap.isios && !self.ispage && !self.haswrapper) self.css($("body"), { 19811 "-webkit-overflow-scrolling": "touch" 19812 }); //force hw acceleration 19813 19814 var cursor = $(document.createElement('div')); 19815 cursor.css({ 19816 position: "relative", 19817 top: 0, 19818 "float": "right", 19819 width: self.opt.cursorwidth, 19820 height: "0px", 19821 'background-color': self.opt.cursorcolor, 19822 border: self.opt.cursorborder, 19823 'background-clip': 'padding-box', 19824 '-webkit-border-radius': self.opt.cursorborderradius, 19825 '-moz-border-radius': self.opt.cursorborderradius, 19826 'border-radius': self.opt.cursorborderradius 19827 }); 19828 19829 cursor.hborder = parseFloat(cursor.outerHeight() - cursor.innerHe
19829ight()); 19830 19831 cursor.addClass('nicescroll-cursors'); 19832 19833 self.cursor = cursor; 19834 19835 var rail = $(document.createElement('div')); 19836 rail.attr('id', self.id); 19837 rail.addClass('nicescroll-rails nicescroll-rails-vr'); 19838 19839 var v, a, kp = ["left","right","top","bottom"]; //** 19840 for (var n in kp) { 19841 a = kp[n]; 19842 v = self.opt.railpadding[a]; 19843 (v) ? rail.css("padding-"+a,v+"px") : self.opt.railpadding[a] = 0; 19844 } 19845 19846 rail.append(cursor); 19847 19848 rail.width = Math.max(parseFloat(self.opt.cursorwidth), cursor.outerWidth()); 19849 rail.css({ 19850 width: rail.width + "px", 19851 'zIndex': self.zindex, 19852 "background": self.opt.background, 19853 cursor: "default" 19854 }); 19855 19856 rail.visibility = true; 19857 rail.scrollable = true; 19858 19859 rail.align = (self.opt.railalign == "left") ? 0 : 1; 19860 19861 self.rail = rail; 19862 19863 self.rail.drag = false; 19864 19865 var zoom = false; 19866 if (self.opt.boxzoom && !self.ispage && !cap.isieold) { 19867 zoom = document.createElement('div'); 19868 19869 self.bind(zoom, "click", self.doZoom); 19870 self.bind(zoom, "mouseenter", function() { 19871 self.zoom.css('opacity', self.opt.cursoropacitymax); 19872 }); 19873 self.bind(zoom, "mouseleave", function() { 19874 self.zoom.css('opacity', self.opt.cursoropacitymin); 19875 }); 19876 19877 self.zoom = $(zoom); 19878 self.zoom.css({ 19879 "cursor": "pointer", 19880 'z-index': self.zindex, 19881 'backgroundImage': 'url(' + self.opt.scriptpath + 'zoomico.png)', 19882 'height': 18, 19883 'width': 18, 19884 'backgroundPosition': '0px 0px' 19885 }); 19886 if (self.opt.dblclickzoom) self.bind(self.win, "dblclick", self.doZoom); 19887 if (cap.cantouch && self.opt.gesturezoom) { 19888 self.ongesturezoom = function(e) { 19889 if (e.scale > 1.5) self.doZoomIn(e); 19890 if (e.scale < 0.8) self.doZoomOut(e); 19891 return self.cancelEvent(e); 19892 }; 19893 self.bind(self.win, "gestureend", self.ongesturezoom); 19894 } 19895 } 19896 19897 // init HORIZ 19898 19899 self.railh = false; 19900 var railh; 19901 19902 if (self.opt.horizrailenabled) { 19903 19904 self.css(cont, { 19905 'overflow-x': 'hidden' 19906 }); 19907 19908 var cursor = $(document.createElement('div')); 19909 cursor.css({ 19910 position: "absolute", 19911 top: 0, 19912 height: self.opt.cursorwidth, 19913 width: "0px", 19914 'background-color': self.opt.cursorcolor, 19915 border: self.opt.cursorborder, 19916 'background-clip': 'padding-box', 19917 '-webkit-border-radius': self.opt.cursorborderradius, 19918 '-moz-border-radius': self.opt.cursorborderradius, 19919 'border-radius': self.opt.cursorborderradius 19920 }); 19921 19922 if (cap.isieold) cursor.css({'overflow':'hidden'}); //IE6 horiz scrollbar issue 19923 19924 cursor.wborder = parseFloat(cursor.outerWidth() - cursor.innerWidth()); 19925 19926 cursor.addClass('nicescroll-cursors'); 19927 19928 self.cursorh = cursor; 19929 19930 railh = $(document.createElement('div')); 19931 railh.attr('id', self.id + '-hr'); 19932 railh.addClass('nicescroll-rails nicescroll-rails-hr'); 19933 railh.height = Math.max(parseFloat(self.opt.cursorwidth), cursor.outerHeight()); 19934 railh.css({ 19935 height: railh.height + "px", 19936 'zIndex': self.zindex, 19937 "background": self.opt.background 19938 }); 19939 19940 railh.append(cursor); 19941 19942 railh.visibility = true; 19943 railh.scrollable = true; 19944 19945 railh.align = (self.opt.railvalign == "top") ? 0 : 1; 19946 19947 self.railh = railh; 19948 19949 self.railh.drag = false; 19950 19951 } 19952 19953 // 19954 19955 if (self.ispage) { 19956 rail.css({ 19957 position: "fixed", 19958 top: "0px", 19959 height: "100%" 19960 }); 19961 (rail.align) ? rail.css({ 19962 right: "0px" 19963 }): rail.css({ 19964 left: "0px" 19965 }); 19966 self.body.append(rail); 19967 if (self.railh) { 19968 railh.css({ 19969 position: "fixed", 19970 left: "0px", 19971 width: "100%" 19972 }); 19973 (railh.align) ? railh.css({ 19974 bottom: "0px" 19975 }): railh.css({ 19976 top: "0px" 19977 }); 19978 self.body.append(railh); 19979 } 19980 } else { 19981 if (self.ishwscroll) { 19982 if (self.win.css('position') == 'static') self.css(self.win, { 19983 'position': 'relative' 19984 }); 19985 var bd = (self.win[0].nodeName == 'HTML') ? self.body : self.win; 19986 $(bd).scrollTop(0).scrollLeft(0); // fix rail position if content already scrolled 19987 if (self.zoom) { 19988 self.zoom.css({ 19989 position: "absolute", 19990 top: 1, 19991 right: 0, 19992 "margin-right": rail.width + 4 19993 }); 19994 bd.append(self.zoom); 19995 } 19996 rail.css({ 19997 position: "absolute", 19998 top: 0 19999 }); 20000 (rail.align) ? rail.css({ 20001 right: 0 20002 }): rail.css({ 20003 left: 0 20004 }); 20005 bd.append(rail); 20006 if (railh) { 20007 railh.css({ 20008 position: "absolute", 20009 left: 0, 20010 bottom: 0 20011 }); 20012 (railh.align) ? railh.css({ 20013 bottom: 0 20014 }): railh.css({ 20015 top: 0 20016 }); 20017 bd.append(railh); 20018 } 20019 } else { 20020 self.isfixed = (self.win.css("position") == "fixed"); 20021 var rlpos = (self.isfixed) ? "fixed" : "absolute"; 20022 20023 if (!self.isfixed) self.viewport = self.getViewport(self.win[0]); 20024 if (self.viewport) { 20025 self.body = self.viewport; 20026 if ((/fixed|absolute/.test(self.viewport.css("position"))) == false) self.css(self.viewport, { 20027 "position": "relative" 20028 }); 20029 } 20030 20031 rail.css({ 20032 position: rlpos 20033 }); 20034 if (self.zoom) self.zoom.css({ 20035 position: rlpos 20036 }); 20037 self.updateScrollBar(); 20038 self.body.append(rail); 20039 if (self.zoom) self.body.append(self.zoom); 20040 if (self.railh) { 20041 railh.css({ 20042 position: rlpos 20043 }); 20044 self.body.append(railh); 20045 } 20046 } 20047 20048 if (cap.isios) self.css(self.win, {
20049 '-webkit-tap-highlight-color': 'rgba(0,0,0,0)', 20050 '-webkit-touch-callout': 'none' 20051 }); // prevent grey layer on click 20052 20053 if (cap.isie && self.opt.disableoutline) self.win.attr("hideFocus", "true"); // IE, prevent dotted rectangle on focused div 20054 if (cap.iswebkit && self.opt.disableoutline) self.win.css({"outline": "none"}); // Webkit outline 20055 //if (cap.isopera&&self.opt.disableoutline) self.win.css({"outline":"0"}); // Opera 12- to test [TODO] 20056 20057 } 20058 20059 if (self.opt.autohidemode === false) { 20060 self.autohidedom = false; 20061 self.rail.css({ 20062 opacity: self.opt.cursoropacitymax 20063 }); 20064 if (self.railh) self.railh.css({ 20065 opacity: self.opt.cursoropacitymax 20066 }); 20067 } else if ((self.opt.autohidemode === true) || (self.opt.autohidemode === "leave")) { 20068 self.autohidedom = $().add(self.rail); 20069 if (cap.isie8) self.autohidedom = self.autohidedom.add(self.cursor); 20070 if (self.railh) self.autohidedom = self.autohidedom.add(self.railh); 20071 if (self.railh && cap.isie8) self.autohidedom = self.autohidedom.add(self.cursorh); 20072 } else if (self.opt.autohidemode == "scroll") { 20073 self.autohidedom = $().add(self.rail); 20074 if (self.railh) self.autohidedom = self.autohidedom.add(self.railh); 20075 } else if (self.opt.autohidemode == "cursor") { 20076 self.autohidedom = $().add(self.cursor); 20077 if (self.railh) self.autohidedom = self.autohidedom.add(self.cursorh); 20078 } else if (self.opt.autohidemode == "hidden") { 20079 self.autohidedom = false; 20080 self.hide(); 20081 self.railslocked = false; 20082 } 20083 20084 if (cap.isie9mobile) { 20085 20086 self.scrollmom = new ScrollMomentumClass2D(self); 20087 20088 self.onmangotouch = function() { 20089 var py = self.getScrollTop(); 20090 var px = self.getScrollLeft(); 20091 20092 if ((py == self.scrollmom.lastscrolly) && (px == self.scrollmom.lastscrollx)) return true; 20093 20094 var dfy = py - self.mangotouch.sy; 20095 var dfx = px - self.mangotouch.sx; 20096 var df = Math.round(Math.sqrt(Math.pow(dfx, 2) + Math.pow(dfy, 2))); 20097 if (df == 0) return; 20098 20099 var dry = (dfy < 0) ? -1 : 1; 20100 var drx = (dfx < 0) ? -1 : 1; 20101 20102 var tm = +new Date(); 20103 if (self.mangotouch.lazy) clearTimeout(self.mangotouch.lazy); 20104 20105 if (((tm - self.mangotouch.tm) > 80) || (self.mangotouch.dry != dry) || (self.mangotouch.drx != drx)) { 20106 self.scrollmom.stop(); 20107 self.scrollmom.reset(px, py); 20108 self.mangotouch.sy = py; 20109 self.mangotouch.ly = py; 20110 self.mangotouch.sx = px; 20111 self.mangotouch.lx = px; 20112 self.mangotouch.dry = dry; 20113 self.mangotouch.drx = drx; 20114 self.mangotouch.tm = tm; 20115 } else { 20116 20117 self.scrollmom.stop(); 20118 self.scrollmom.update(self.mangotouch.sx - dfx, self.mangotouch.sy - dfy); 20119 self.mangotouch.tm = tm; 20120 20121 var ds = Math.max(Math.abs(self.mangotouch.ly - py), Math.abs(self.mangotouch.lx - px)); 20122 self.mangotouch.ly = py; 20123 self.mangotouch.lx = px; 20124 20125 if (ds > 2) { 20126 self.mangotouch.lazy = setTimeout(function() { 20127 self.mangotouch.lazy = false; 20128 self.mangotouch.dry = 0; 20129 self.mangotouch.drx = 0; 20130 self.mangotouch.tm = 0; 20131 self.scrollmom.doMomentum(30); 20132 }, 100); 20133 } 20134 } 20135 }; 20136 20137 var top = self.getScrollTop(); 20138 var lef = self.getScrollLeft(); 20139 self.mangotouch = { 20140 sy: top, 20141 ly: top, 20142 dry: 0, 20143 sx: lef, 20144 lx: lef, 20145 drx: 0, 20146 lazy: false, 20147 tm: 0 20148 }; 20149 20150 self.bind(self.docscroll, "scroll", self.onmangotouch); 20151 20152 } else { 20153 20154 if (cap.cantouch || self.istouchcapable || self.opt.touchbehavior || cap.hasmstouch) { 20155 20156 self.scrollmom = new ScrollMomentumClass2D(self); 20157 20158 self.ontouchstart = function(e) { 20159 if (e.pointerType && e.pointerType != 2 && e.pointerType != "touch") return false;
20160 20161 self.hasmoving = false; 20162 20163 if (!self.railslocked) { 20164 20165 var tg; 20166 if (cap.hasmstouch) { 20167 tg = (e.target) ? e.target : false; 20168 while (tg) { 20169 var nc = $(tg).getNiceScroll(); 20170 if ((nc.length > 0) && (nc[0].me == self.me)) break; 20171 if (nc.length > 0) return false; 20172 if ((tg.nodeName == 'DIV') && (tg.id == self.id)) break; 20173 tg = (tg.parentNode) ? tg.parentNode : false; 20174 } 20175 } 20176 20177 self.cancelScroll(); 20178 20179 tg = self.getTarget(e); 20180 20181 if (tg) { 20182 var skp = (/INPUT/i.test(tg.nodeName)) && (/range/i.test(tg.type)); 20183 if (skp) return self.stopPropagation(e); 20184 } 20185 20186 if (!("clientX" in e) && ("changedTouches" in e)) { 20187 e.clientX = e.changedTouches[0].clientX; 20188 e.clientY = e.changedTouches[0].clientY; 20189 } 20190 20191 if (self.forcescreen) { 20192 var le = e; 20193 e = { 20194 "original": (e.original) ? e.original : e 20195 }; 20196 e.clientX = le.screenX; 20197 e.clientY = le.screenY; 20198 } 20199 20200 self.rail.drag = { 20201 x: e.clientX, 20202 y: e.clientY, 20203 sx: self.scroll.x, 20204 sy: self.scroll.y, 20205 st: self.getScrollTop(), 20206 sl: self.getScrollLeft(), 20207 pt: 2, 20208 dl: false 20209 }; 20210 20211 if (self.ispage || !self.opt.directionlockdeadzone) { 20212 self.rail.drag.dl = "f"; 20213 } else { 20214 20215 var view = { 20216 w: $(window).width(), 20217 h: $(window).height() 20218 }; 20219 20220 var page = { 20221 w: Math.max(document.body.scrollWidth, document.documentElement.scrollWidth), 20222 h: Math.max(document.body.scrollHeight, document.documentElement.scrollHeight) 20223 }; 20224 20225 var maxh = Math.max(0, page.h - view.h); 20226 var maxw = Math.max(0, page.w - view.w); 20227 20228 if (!self.rail.scrollable && self.railh.scrollable) self.rail.drag.ck = (maxh > 0) ? "v" : false; 20229 else if (self.rail.scrollable && !self.railh.scrollable) self.rail.drag.ck = (maxw > 0) ? "h" : false; 20230 else self.rail.drag.ck = false; 20231 if (!self.rail.drag.ck) self.rail.drag.dl = "f"; 20232 } 20233 20234 if (self.opt.touchbehavior && self.isiframe && cap.isie) { 20235 var wp = self.win.position(); 20236 self.rail.drag.x += wp.left; 20237 self.rail.drag.y += wp.top; 20238 } 20239 20240 self.hasmoving = false; 20241 self.lastmouseup = false; 20242 self.scrollmom.reset(e.clientX, e.clientY); 20243 20244 if (!cap.cantouch && !this.istouchcapable && !e.pointerType) { 20245 20246 var ip = (tg) ? /INPUT|SELECT|TEXTAREA/i.test(tg.nodeName) : false; 20247 if (!ip) { 20248 if (!self.ispage && cap.hasmousecapture) tg.setCapture(); 20249 if (self.opt.touchbehavior) { 20250 if (tg.onclick && !(tg._onclick || false)) { // intercept DOM0 onclick event 20251 tg._onclick = tg.onclick; 20252 tg.onclick = function(e) { 20253 if (self.hasmoving) return false; 20254 tg._onclick.call(this, e); 20255 }; 20256 } 20257 return self.cancelEvent(e); 20258 } 20259 return self.stopPropagation(e); 20260 } 20261 20262 if (/SUBMIT|CANCEL|BUTTON/i.test($(tg).attr('type'))) { 20263 pc = { 20264 "tg": tg, 20265 "click": false 20266 }; 20267 self.preventclick = pc; 20268 } 20269 20270 } 20271 } 20272 20273 }; 20274 20275 self.ontouchend = function(e) { 20276 if (!self.rail.drag) return true; 20277 if (self.rail.drag.pt == 2) { 20278 if (e.pointerType && e.pointerType != 2 && e.pointerType != "touch") return false;
20279 self.scrollmom.doMomentum(); 20280 self.rail.drag = false; 20281 if (self.hasmoving) { 20282 self.lastmouseup = true; 20283 self.hideCursor(); 20284 if (cap.hasmousecapture) document.releaseCapture(); 20285 if (!cap.cantouch) return self.cancelEvent(e); 20286 } 20287 } 20288 else if (self.rail.drag.pt == 1) { 20289 return self.onmouseup(e); 20290 } 20291 20292 }; 20293 20294 var moveneedoffset = (self.opt.touchbehavior && self.isiframe && !cap.hasmousecapture); 20295 20296 self.ontouchmove = function(e, byiframe) { 20297 20298 if (!self.rail.drag) return false; 20299 20300 if (e.targetTouches && self.opt.preventmultitouchscrolling) { 20301 if (e.targetTouches.length > 1) return false; // multitouch 20302 } 20303 20304 if (e.pointerType && e.pointerType != 2 && e.pointerType != "touch") return false; 20305 20306 if (self.rail.drag.pt == 2) { 20307 if (cap.cantouch && (cap.isios) && (typeof e.original == "undefined")) return true; // prevent ios "ghost" events by clickable elements 20308 20309 self.hasmoving = true; 20310 20311 if (self.preventclick && !self.preventclick.click) { 20312 self.preventclick.click = self.preventclick.tg.onclick || false; 20313 self.preventclick.tg.onclick = self.onpreventclick; 20314 } 20315 20316 var ev = $.extend({ 20317 "original": e 20318 }, e); 20319 e = ev; 20320 20321 if (("changedTouches" in e)) { 20322 e.clientX = e.changedTouches[0].clientX; 20323 e.clientY = e.changedTouches[0].clientY; 20324 } 20325 20326 if (self.forcescreen) { 20327 var le = e; 20328 e = { 20329 "original": (e.original) ? e.original : e 20330 }; 20331 e.clientX = le.screenX; 20332 e.clientY = le.screenY; 20333 } 20334 20335 var ofy,ofx; 20336 ofx = ofy = 0; 20337 20338 if (moveneedoffset && !byiframe) { 20339 var wp = self.win.position(); 20340 ofx = -wp.left; 20341 ofy = -wp.top; 20342 } 20343 20344 var fy = e.clientY + ofy; 20345 var my = (fy - self.rail.drag.y); 20346 var fx = e.clientX + ofx; 20347 var mx = (fx - self.rail.drag.x); 20348 20349 var ny = self.rail.drag.st - my; 20350 20351 if (self.ishwscroll && self.opt.bouncescroll) { 20352 if (ny < 0) { 20353 ny = Math.round(ny / 2); 20354 // fy = 0; 20355 } else if (ny > self.page.maxh) { 20356 ny = self.page.maxh + Math.round((ny - self.page.maxh) / 2); 20357 // fy = 0; 20358 } 20359 } else { 20360 if (ny < 0) { 20361 ny = 0; 20362 fy = 0; 20363 } 20364 if (ny > self.page.maxh) { 20365 ny = self.page.maxh; 20366 fy = 0; 20367 } 20368 } 20369 20370 var nx; 20371 if (self.railh && self.railh.scrollable) { 20372 nx = (self.isrtlmode) ? mx - self.rail.drag.sl : self.rail.drag.sl - mx; 20373 20374 if (self.ishwscroll && self.opt.bouncescroll) { 20375 if (nx < 0) { 20376 nx = Math.round(nx / 2); 20377 // fx = 0; 20378 } else if (nx > self.page.maxw) { 20379 nx = self.page.maxw + Math.round((nx - self.page.maxw) / 2); 20380 // fx = 0; 20381 } 20382 } else { 20383 if (nx < 0) { 20384 nx = 0; 20385 fx = 0; 20386 } 20387 if (nx > self.page.maxw) { 20388 nx = self.page.maxw; 20389 fx = 0; 20390 } 20391 } 20392 20393 } 20394 20395 var grabbed = false;
20396 if (self.rail.drag.dl) { 20397 grabbed = true; 20398 if (self.rail.drag.dl == "v") nx = self.rail.drag.sl; 20399 else if (self.rail.drag.dl == "h") ny = self.rail.drag.st; 20400 } else { 20401 var ay = Math.abs(my); 20402 var ax = Math.abs(mx); 20403 var dz = self.opt.directionlockdeadzone; 20404 if (self.rail.drag.ck == "v") { 20405 if (ay > dz && (ax <= (ay * 0.3))) { 20406 self.rail.drag = false; 20407 return true; 20408 } else if (ax > dz) { 20409 self.rail.drag.dl = "f"; 20410 $("body").scrollTop($("body").scrollTop()); // stop iOS native scrolling (when active javascript has blocked) 20411 } 20412 } else if (self.rail.drag.ck == "h") { 20413 if (ax > dz && (ay <= (ax * 0.3))) { 20414 self.rail.drag = false; 20415 return true; 20416 } else if (ay > dz) { 20417 self.rail.drag.dl = "f"; 20418 $("body").scrollLeft($("body").scrollLeft()); // stop iOS native scrolling (when active javascript has blocked) 20419 } 20420 } 20421 } 20422 20423 self.synched("touchmove", function() { 20424 if (self.rail.drag && (self.rail.drag.pt == 2)) { 20425 if (self.prepareTransition) self.prepareTransition(0); 20426 if (self.rail.scrollable) self.setScrollTop(ny); 20427 self.scrollmom.update(fx, fy); 20428 if (self.railh && self.railh.scrollable) { 20429 self.setScrollLeft(nx); 20430 self.showCursor(ny, nx); 20431 } else { 20432 self.showCursor(ny); 20433 } 20434 if (cap.isie10) document.selection.clear(); 20435 } 20436 }); 20437 20438 if (cap.ischrome && self.istouchcapable) grabbed = false; //chrome touch emulation doesn't like! 20439 if (grabbed) return self.cancelEvent(e); 20440 } 20441 else if (self.rail.drag.pt == 1) { // drag on cursor 20442 return self.onmousemove(e); 20443 } 20444 20445 }; 20446 20447 } 20448 20449 self.onmousedown = function(e, hronly) { 20450 if (self.rail.drag && self.rail.drag.pt != 1) return; 20451 if (self.railslocked) return self.cancelEvent(e); 20452 self.cancelScroll(); 20453 self.rail.drag = { 20454 x: e.clientX, 20455 y: e.clientY, 20456 sx: self.scroll.x, 20457 sy: self.scroll.y, 20458 pt: 1, 20459 hr: (!!hronly) 20460 }; 20461 var tg = self.getTarget(e); 20462 if (!self.ispage && cap.hasmousecapture) tg.setCapture(); 20463 if (self.isiframe && !cap.hasmousecapture) { 20464 self.saved.csspointerevents = self.doc.css("pointer-events"); 20465 self.css(self.doc, { 20466 "pointer-events": "none" 20467 }); 20468 } 20469 self.hasmoving = false; 20470 return self.cancelEvent(e); 20471 }; 20472 20473 self.onmouseup = function(e) { 20474 if (self.rail.drag) { 20475 if (self.rail.drag.pt != 1) return true; 20476 if (cap.hasmousecapture) document.releaseCapture(); 20477 if (self.isiframe && !cap.hasmousecapture) self.doc.css("pointer-events", self.saved.csspointerevents); 20478 self.rail.drag = false; 20479 //if (!self.rail.active) self.hideCursor(); 20480 if (self.hasmoving) self.triggerScrollEnd(); // TODO - check &&!self.scrollrunning 20481 return self.cancelEvent(e); 20482 } 20483 }; 20484 20485 self.onmousemove = function(e) { 20486 if (self.rail.drag) { 20487 if (self.rail.drag.pt != 1) return; 20488 20489 if (cap.ischrome && e.which == 0) return self.onmouseup(e); 20490 20491 self.cursorfreezed = true; 20492 self.hasmoving = true; 20493 20494 if (self.rail.drag.hr) { 20495 self.scroll.x = self.rail.drag.sx + (e.clientX - self.rail.drag.x); 20496 if (self.scroll.x < 0) self.scroll.x = 0; 20497 var mw = self.scrollvaluemaxw; 20498 if (self.scroll.x > mw) self.scroll.x = mw; 20499 } else { 20500 self.scroll.y = self.rail.drag.sy + (e.clientY - self.rail.drag.y); 20501 if (self.scroll.y < 0) self.scroll.y = 0; 20502 var my = self.scrollvaluemax; 20503 if (self.scroll.y > my) self.scroll.y = my; 20504 } 20505 20506 self.synched('mousemove', function() { 20507 if (self.rail.drag && (self.rail.drag.pt == 1)) { 20508 self.showCursor(); 20509 if (self.rail.drag.hr) { 20510 if (self.hasreversehr) { 20511 self.doScrollLeft(self.scrollvaluemaxw-Math.round(self.scroll.x * self.scrollratio.x), self.opt.cursordragspeed); 20512 } else { 20513 self.doScrollLeft(Math.round(self.scroll.x * self.scrollratio.x), self.opt.cursordragspeed); 20514 } 20515 } 20516 else self.doScrollTop(Math.round(self.scroll.y * self.scrollratio.y), self.opt.cursordragspeed); 20517 } 20518 }); 20519 20520 return self.cancelEvent(e); 20521 } 20522 else { 20523 self.checkarea = 0; 20524 } 20525 }; 20526 20527 if (cap.cantouch || self.opt.touchbehavior) { 20528 20529 self.onpreventclick = function(e) { 20530 if (self.preventclick) {
20531 self.preventclick.tg.onclick = self.preventclick.click; 20532 self.preventclick = false; 20533 return self.cancelEvent(e); 20534 } 20535 } 20536 20537 self.bind(self.win, "mousedown", self.ontouchstart); // control content dragging 20538 20539 self.onclick = (cap.isios) ? false : function(e) { 20540 if (self.lastmouseup) { 20541 self.lastmouseup = false; 20542 return self.cancelEvent(e); 20543 } else { 20544 return true; 20545 } 20546 }; 20547 20548 if (self.opt.grabcursorenabled && cap.cursorgrabvalue) { 20549 self.css((self.ispage) ? self.doc : self.win, { 20550 'cursor': cap.cursorgrabvalue 20551 }); 20552 self.css(self.rail, { 20553 'cursor': cap.cursorgrabvalue 20554 }); 20555 } 20556 20557 } else { 20558 20559 var checkSelectionScroll = function(e) { 20560 if (!self.selectiondrag) return; 20561 20562 if (e) { 20563 var ww = self.win.outerHeight(); 20564 var df = (e.pageY - self.selectiondrag.top); 20565 if (df > 0 && df < ww) df = 0; 20566 if (df >= ww) df -= ww; 20567 self.selectiondrag.df = df; 20568 } 20569 if (self.selectiondrag.df == 0) return; 20570 20571 var rt = -Math.floor(self.selectiondrag.df / 6) * 2; 20572 self.doScrollBy(rt); 20573 20574 self.debounced("doselectionscroll", function() { 20575 checkSelectionScroll() 20576 }, 50); 20577 }; 20578 20579 if ("getSelection" in document) { // A grade - Major browsers 20580 self.hasTextSelected = function() { 20581 return (document.getSelection().rangeCount > 0); 20582 }; 20583 } else if ("selection" in document) { //IE9- 20584 self.hasTextSelected = function() { 20585 return (document.selection.type != "None"); 20586 }; 20587 } else { 20588 self.hasTextSelected = function() { // no support 20589 return false; 20590 }; 20591 } 20592 20593 self.onselectionstart = function(e) { 20594/* More testing - severe chrome issues 20595 if (!self.haswrapper&&(e.which&&e.which==2)) { // fool browser to manage middle button scrolling 20596 self.win.css({'overflow':'auto'}); 20597 setTimeout(function(){ 20598 self.win.css({'overflow':''}); 20599 },10); 20600 return true; 20601 } 20602*/ 20603 if (self.ispage) return; 20604 self.selectiondrag = self.win.offset(); 20605 }; 20606 20607 self.onselectionend = function(e) { 20608 self.selectiondrag = false; 20609 }; 20610 self.onselectiondrag = function(e) { 20611 if (!self.selectiondrag) return; 20612 if (self.hasTextSelected()) self.debounced("selectionscroll", function() { 20613 checkSelectionScroll(e) 20614 }, 250); 20615 }; 20616 20617 20618 } 20619 20620 if (cap.hasw3ctouch) { //IE11+ 20621 self.css(self.rail, { 20622 'touch-action': 'none' 20623 }); 20624 self.css(self.cursor, { 20625 'touch-action': 'none' 20626 }); 20627 self.bind(self.win, "pointerdown", self.ontouchstart); 20628 self.bind(document, "pointerup", self.ontouchend); 20629 self.bind(document, "pointermove", self.ontouchmove); 20630 } else if (cap.hasmstouch) { //IE10 20631 self.css(self.rail, { 20632 '-ms-touch-action': 'none' 20633 }); 20634 self.css(self.cursor, { 20635 '-ms-touch-action': 'none' 20636 }); 20637 self.bind(self.win, "MSPointerDown", self.ontouchstart); 20638 self.bind(document, "MSPointerUp", self.ontouchend); 20639 self.bind(document, "MSPointerMove", self.ontouchmove); 20640 self.bind(self.cursor, "MSGestureHold", function(e) { 20641 e.preventDefault() 20642 }); 20643 self.bind(self.cursor, "contextmenu", function(e) { 20644 e.preventDefault() 20645 }); 20646 } else if (this.istouchcapable) { //desktop with screen touch enabled 20647 self.bind(self.win, "touchstart", self.ontouchstart); 20648 self.bind(document, "touchend", self.ontouchend); 20649 self.bind(document, "touchcancel", self.ontouchend); 20650 self.bind(document, "touchmove", self.ontouchmove); 20651 } 20652 20653 20654 if (self.opt.cursordragontouch || (!cap.cantouch && !self.opt.touchbehavior)) { 20655 20656 self.rail.css({
20657 "cursor": "default" 20658 }); 20659 self.railh && self.railh.css({ 20660 "cursor": "default" 20661 }); 20662 20663 self.jqbind(self.rail, "mouseenter", function() { 20664 if (!self.ispage && !self.win.is(":visible")) return false; 20665 if (self.canshowonmouseevent) self.showCursor(); 20666 self.rail.active = true; 20667 }); 20668 self.jqbind(self.rail, "mouseleave", function() { 20669 self.rail.active = false; 20670 if (!self.rail.drag) self.hideCursor(); 20671 }); 20672 20673 if (self.opt.sensitiverail) { 20674 self.bind(self.rail, "click", function(e) { 20675 self.doRailClick(e, false, false) 20676 }); 20677 self.bind(self.rail, "dblclick", function(e) { 20678 self.doRailClick(e, true, false) 20679 }); 20680 self.bind(self.cursor, "click", function(e) { 20681 self.cancelEvent(e) 20682 }); 20683 self.bind(self.cursor, "dblclick", function(e) { 20684 self.cancelEvent(e) 20685 }); 20686 } 20687 20688 if (self.railh) { 20689 self.jqbind(self.railh, "mouseenter", function() { 20690 if (!self.ispage && !self.win.is(":visible")) return false; 20691 if (self.canshowonmouseevent) self.showCursor(); 20692 self.rail.active = true; 20693 }); 20694 self.jqbind(self.railh, "mouseleave", function() { 20695 self.rail.active = false; 20696 if (!self.rail.drag) self.hideCursor(); 20697 }); 20698 20699 if (self.opt.sensitiverail) { 20700 self.bind(self.railh, "click", function(e) { 20701 self.doRailClick(e, false, true) 20702 }); 20703 self.bind(self.railh, "dblclick", function(e) { 20704 self.doRailClick(e, true, true) 20705 }); 20706 self.bind(self.cursorh, "click", function(e) { 20707 self.cancelEvent(e) 20708 }); 20709 self.bind(self.cursorh, "dblclick", function(e) { 20710 self.cancelEvent(e) 20711 }); 20712 } 20713 20714 } 20715 20716 } 20717 20718 if (!cap.cantouch && !self.opt.touchbehavior) { 20719 20720 self.bind((cap.hasmousecapture) ? self.win : document, "mouseup", self.onmouseup); 20721 self.bind(document, "mousemove", self.onmousemove); 20722 if (self.onclick) self.bind(document, "click", self.onclick); 20723 20724 self.bind(self.cursor, "mousedown", self.onmousedown); 20725 self.bind(self.cursor, "mouseup", self.onmouseup); 20726 20727 if (self.railh) { 20728 self.bind(self.cursorh, "mousedown", function(e) { 20729 self.onmousedown(e, true) 20730 }); 20731 self.bind(self.cursorh, "mouseup", self.onmouseup); 20732 } 20733 20734 if (!self.ispage && self.opt.enablescrollonselection) { 20735 self.bind(self.win[0], "mousedown", self.onselectionstart); 20736 self.bind(document, "mouseup", self.onselectionend); 20737 self.bind(self.cursor, "mouseup", self.onselectionend); 20738 if (self.cursorh) self.bind(self.cursorh, "mouseup", self.onselectionend); 20739 self.bind(document, "mousemove", self.onselectiondrag); 20740 } 20741 20742 if (self.zoom) { 20743 self.jqbind(self.zoom, "mouseenter", function() { 20744 if (self.canshowonmouseevent) self.showCursor(); 20745 self.rail.active = true; 20746 }); 20747 self.jqbind(self.zoom, "mouseleave", function() { 20748 self.rail.active = false; 20749 if (!self.rail.drag) self.hideCursor(); 20750 }); 20751 } 20752 20753 } else { 20754 20755 self.bind((cap.hasmousecapture) ? self.win : document, "mouseup", self.ontouchend); 20756 self.bind(document, "mousemove", self.ontouchmove); 20757 if (self.onclick) self.bind(document, "click", self.onclick); 20758 20759 if (self.opt.cursordragontouch) { 20760 self.bind(self.cursor, "mousedown", self.onmousedown); 20761 self.bind(self.cursor, "mouseup", self.onmouseup); 20762 //self.bind(self.cursor, "mousemove", self.onmousemove); 20763 self.cursorh && self.bind(self.cursorh, "mousedown", function(e) { 20764 self.onmousedown(e, true) 20765 }); 20766 //self.cursorh && self.bind(self.cursorh, "mousemove", self.onmousemove); 20767 self.cursorh && self.bind(self.cursorh, "mouseup", self.onmouseup); 20768 } 20769 20770 } 20771 20772 if (self.opt.enablemousewheel) { 20773 if (!self.isiframe) self.bind((cap.isie && self.ispage) ? document : self.win /*self.docscroll*/ , "mousewheel", self.onmousewheel); 20774 self.bind(self.rail, "mousewheel", self.onmousewheel); 20775 if (self.railh) self.bind(self.railh, "mousewheel", self.onmousewheelhr); 20776 } 20777 20778 if (!self.ispage && !cap.cantouch && !(/HTML|^BODY/.test(self.win[0].nodeName))) { 20779 if (!self.win.attr("tabindex")) self.win.attr({ 20780 "tabindex": tabindexcounter++ 20781 }); 20782 20783 self.jqbind(self.win, "focus", function(e) { 20784 domfocus = (self.getTarget(e)).id || true; 20785 self.hasfocus = true; 20786 if (self.canshowonmouseevent) self.noticeCursor(); 20787 }); 20788 self.jqbind(self.win, "blur", function(e) { 20789 domfocus = false;
20790 self.hasfocus = false; 20791 }); 20792 20793 self.jqbind(self.win, "mouseenter", function(e) { 20794 mousefocus = (self.getTarget(e)).id || true; 20795 self.hasmousefocus = true; 20796 if (self.canshowonmouseevent) self.noticeCursor(); 20797 }); 20798 self.jqbind(self.win, "mouseleave", function() { 20799 mousefocus = false; 20800 self.hasmousefocus = false; 20801 if (!self.rail.drag) self.hideCursor(); 20802 }); 20803 20804 } 20805 20806 } // !ie9mobile 20807 20808 //Thanks to http://www.quirksmode.org !! 20809 self.onkeypress = function(e) { 20810 if (self.railslocked && self.page.maxh == 0) return true; 20811 20812 e = (e) ? e : window.e; 20813 var tg = self.getTarget(e); 20814 if (tg && /INPUT|TEXTAREA|SELECT|OPTION/.test(tg.nodeName)) { 20815 var tp = tg.getAttribute('type') || tg.type || false; 20816 if ((!tp) || !(/submit|button|cancel/i.tp)) return true; 20817 } 20818 20819 if ($(tg).attr('contenteditable')) return true; 20820 20821 if (self.hasfocus || (self.hasmousefocus && !domfocus) || (self.ispage && !domfocus && !mousefocus)) { 20822 var key = e.keyCode; 20823 20824 if (self.railslocked && key != 27) return self.cancelEvent(e); 20825 20826 var ctrl = e.ctrlKey || false; 20827 var shift = e.shiftKey || false; 20828 20829 var ret = false;
vendor: 4,889 bytes, lines 20830-20959
20830 switch (key) { 20831 case 38: 20832 case 63233: //safari 20833 self.doScrollBy(24 * 3); 20834 ret = true; 20835 break; 20836 case 40: 20837 case 63235: //safari 20838 self.doScrollBy(-24 * 3); 20839 ret = true; 20840 break; 20841 case 37: 20842 case 63232: //safari 20843 if (self.railh) { 20844 (ctrl) ? self.doScrollLeft(0): self.doScrollLeftBy(24 * 3); 20845 ret = true; 20846 } 20847 break; 20848 case 39: 20849 case 63234: //safari 20850 if (self.railh) { 20851 (ctrl) ? self.doScrollLeft(self.page.maxw): self.doScrollLeftBy(-24 * 3); 20852 ret = true; 20853 } 20854 break; 20855 case 33: 20856 case 63276: // safari 20857 self.doScrollBy(self.view.h); 20858 ret = true; 20859 break; 20860 case 34: 20861 case 63277: // safari 20862 self.doScrollBy(-self.view.h); 20863 ret = true; 20864 break; 20865 case 36: 20866 case 63273: // safari 20867 (self.railh && ctrl) ? self.doScrollPos(0, 0): self.doScrollTo(0); 20868 ret = true; 20869 break; 20870 case 35: 20871 case 63275: // safari 20872 (self.railh && ctrl) ? self.doScrollPos(self.page.maxw, self.page.maxh): self.doScrollTo(self.page.maxh); 20873 ret = true; 20874 break; 20875 case 32: 20876 if (self.opt.spacebarenabled) { 20877 (shift) ? self.doScrollBy(self.view.h): self.doScrollBy(-self.view.h); 20878 ret = true; 20879 } 20880 break; 20881 case 27: // ESC 20882 if (self.zoomactive) { 20883 self.doZoom(); 20884 ret = true; 20885 } 20886 break; 20887 } 20888 if (ret) return self.cancelEvent(e); 20889 } 20890 }; 20891 20892 if (self.opt.enablekeyboard) self.bind(document, (cap.isopera && !cap.isopera12) ? "keypress" : "keydown", self.onkeypress); 20893 20894 self.bind(document, "keydown", function(e) { 20895 var ctrl = e.ctrlKey || false; 20896 if (ctrl) self.wheelprevented = true; 20897 }); 20898 self.bind(document, "keyup", function(e) { 20899 var ctrl = e.ctrlKey || false; 20900 if (!ctrl) self.wheelprevented = false; 20901 }); 20902 self.bind(window,"blur",function(e){ 20903 self.wheelprevented = false; 20904 }); 20905 20906 self.bind(window, 'resize', self.lazyResize); 20907 self.bind(window, 'orientationchange', self.lazyResize); 20908 20909 self.bind(window, "load", self.lazyResize); 20910 20911 if (cap.ischrome && !self.ispage && !self.haswrapper) { //chrome void scrollbar bug - it persists in version 26 20912 var tmp = self.win.attr("style"); 20913 var ww = parseFloat(self.win.css("width")) + 1; 20914 self.win.css('width', ww); 20915 self.synched("chromefix", function() { 20916 self.win.attr("style", tmp) 20917 }); 20918 } 20919 20920 20921 // Trying a cross-browser implementation - good luck! 20922 20923 self.onAttributeChange = function(e) { 20924 self.lazyResize(self.isieold ? 250 : 30); 20925 }; 20926 20927 if (ClsMutationObserver !== false) { 20928 self.observerbody = new ClsMutationObserver(function(mutations) { 20929 mutations.forEach(function(mut){ 20930 if (mut.type=="attributes") { 20931 return ($("body").hasClass("modal-open") && !$.contains($('.modal-dialog')[0],self.doc[0])) ? self.hide() : self.show(); // Support for Bootstrap modal; Added check if the nice scroll element is inside a modal 20932 } 20933 }); 20934 if (document.body.scrollHeight!=self.page.maxh) return self.lazyResize(30); 20935 }); 20936 self.observerbody.observe(document.body, { 20937 childList: true, 20938 subtree: true, 20939 characterData: false, 20940 attributes: true, 20941 attributeFilter: ['class'] 20942 }); 20943 } 20944 20945 if (!self.ispage && !self.haswrapper) { 20946 // redesigned MutationObserver for Chrome18+/Firefox14+/iOS6+ with support for: remove div, add/remove content 20947 if (ClsMutationObserver !== false) { 20948 self.observer = new ClsMutationObserver(function(mutations) { 20949 mutations.forEach(self.onAttributeChange); 20950 }); 20951 self.observer.observe(self.win[0], { 20952 childList: true, 20953 characterData: false, 20954 attributes: true, 20955 subtree: false 20956 }); 20957 self.observerremover = new ClsMutationObserver(function(mutations) { 20958 mutations.forEach(function(mo) { 20959 if (mo.removedNodes.length > 0) {
20960 for (var dd in mo.removedNodes) { 20961 if (!!self && (mo.removedNodes[dd] == self.win[0])) return self.remove(); 20962 } 20963 } 20964 }); 20965 }); 20966 self.observerremover.observe(self.win[0].parentNode, { 20967 childList: true, 20968 characterData: false, 20969 attributes: false, 20970 subtree: false 20971 }); 20972 } else { 20973 self.bind(self.win, (cap.isie && !cap.isie9) ? "propertychange" : "DOMAttrModified", self.onAttributeChange); 20974 if (cap.isie9) self.win[0].attachEvent("onpropertychange", self.onAttributeChange); //IE9 DOMAttrModified bug 20975 self.bind(self.win, "DOMNodeRemoved", function(e) { 20976 if (e.target == self.win[0]) self.remove(); 20977 }); 20978 } 20979 } 20980 20981 // 20982 20983 if (!self.ispage && self.opt.boxzoom) self.bind(window, "resize", self.resizeZoom); 20984 if (self.istextarea) { 20985 self.bind(self.win, "keydown", self.lazyResize); 20986 self.bind(self.win, "mouseup", self.lazyResize); 20987 } 20988 20989 // self.checkrtlmode = true; 20990 self.lazyResize(30); 20991 20992 } 20993 20994 if (this.doc[0].nodeName == 'IFRAME') { 20995 var oniframeload = function() { 20996 self.iframexd = false; 20997 var doc; 20998 try { 20999 doc = 'contentDocument' in this ? this.contentDocument : this.contentWindow.document; 21000 var a = doc.domain; 21001 } catch (e) { 21002 self.iframexd = true; 21003 doc = false 21004 } 21005 21006 if (self.iframexd) { 21007 if ("console" in window) console.log('NiceScroll error: policy restriced iframe'); 21008 return true; //cross-domain - I can't manage this 21009 } 21010 21011 self.forcescreen = true; 21012 21013 if (self.isiframe) { 21014 self.iframe = { 21015 "doc": $(doc), 21016 "html": self.doc.contents().find('html')[0], 21017 "body": self.doc.contents().find('body')[0] 21018 }; 21019 self.getContentSize = function() { 21020 return { 21021 w: Math.max(self.iframe.html.scrollWidth, self.iframe.body.scrollWidth), 21022 h: Math.max(self.iframe.html.scrollHeight, self.iframe.body.scrollHeight) 21023 }; 21024 }; 21025 self.docscroll = $(self.iframe.body); //$(this.contentWindow); 21026 } 21027 21028 if (!cap.isios && self.opt.iframeautoresize && !self.isiframe) { 21029 self.win.scrollTop(0); // reset position 21030 self.doc.height(""); //reset height to fix browser bug 21031 var hh = Math.max(doc.getElementsByTagName('html')[0].scrollHeight, doc.body.scrollHeight); 21032 self.doc.height(hh); 21033 } 21034 self.lazyResize(30); 21035 21036 if (cap.isie7) self.css($(self.iframe.html), { 21037 'overflow-y': 'hidden' 21038 }); 21039 self.css($(self.iframe.body), { 21040 'overflow-y': 'hidden' 21041 }); 21042 21043 if (cap.isios && self.haswrapper) { 21044 self.css($(doc.body), { 21045 '-webkit-transform': 'translate3d(0,0,0)' 21046 }); // avoid iFrame content clipping - thanks to http://blog.derraab.com/2012/04/02/avoid-iframe-content-clipping-with-css-transform-on-ios/ 21047 } 21048 21049 if ('contentWindow' in this) { 21050 self.bind(this.contentWindow, "scroll", self.onscroll); //IE8 & minor 21051 } else { 21052 self.bind(doc, "scroll", self.onscroll); 21053 } 21054 21055 if (self.opt.enablemousewheel) { 21056 self.bind(doc, "mousewheel", self.onmousewheel); 21057 } 21058 21059 if (self.opt.enablekeyboard) self.bind(doc, (cap.isopera) ? "keypress" : "keydown", self.onkeypress); 21060 21061 if (cap.cantouch || self.opt.touchbehavior) { 21062 self.bind(doc, "mousedown", self.ontouchstart); 21063 self.bind(doc, "mousemove", function(e) { 21064 return self.ontouchmove(e, true) 21065 }); 21066 if (self.opt.grabcursorenabled && cap.cursorgrabvalue) self.css($(doc.body), { 21067 'cursor': cap.cursorgrabvalue 21068 }); 21069 } 21070 21071 self.bind(doc, "mouseup", self.ontouchend); 21072 21073 if (self.zoom) { 21074 if (self.opt.dblclickzoom) self.bind(doc, 'dblclick', self.doZoom); 21075 if (self.ongesturezoom) self.bind(doc, "gestureend", self.ongesturezoom); 21076 } 21077 }; 21078 21079 if (this.doc[0].readyState && this.doc[0].readyState == "complete") { 21080 setTimeout(function() { 21081 oniframeload.call(self.doc[0], false) 21082 }, 500); 21083 } 21084 self.bind(this.doc, "load", oniframeload); 21085 21086 } 21087 21088 }; 21089 21090 this.showCursor = function(py, px) { 21091 if (self.cursortimeout) { 21092 clearTimeout(self.cursortimeout); 21093 self.cursortimeout = 0; 21094 } 21095 if (!self.rail) return; 21096 if (self.autohidedom) { 21097 self.autohidedom.stop().css({ 21098 opacity: self.opt.cursoropacitymax 21099 }); 21100 self.cursoractive = true; 21101 } 21102 21103 if (!self.rail.drag || self.rail.drag.pt != 1) { 21104 if ((typeof py != "undefined") && (py !== false)) { 21105 self.scroll.y = Math.round(py * 1 / self.scrollratio.y); 21106 } 21107 if (typeof px != "undefined") { 21108 self.scroll.x = Math.round(px * 1 / self.scrollratio.x); 21109 } 21110 } 21111 21112 self.cursor.css({ 21113 height: self.cursorheight, 21114 top: self.scroll.y 21115 }); 21116 if (self.cursorh) { 21117 var lx = (self.hasreversehr) ? self.scrollvaluemaxw-self.scroll.x : self.scroll.x; 21118 (!self.rail.align && self.rail.visibility) ? self.cursorh.css({ 21119 width: self.cursorwidth, 21120 left: lx + self.rail.width 21121 }): self.cursorh.css({ 21122 width: self.cursorwidth, 21123 left: lx 21124 }); 21125 self.cursoractive = true; 21126 } 21127 21128 if (self.zoom) self.zoom.stop().css({ 21129 opacity: self.opt.cursoropacitymax 21130 }); 21131 }; 21132 21133 this.hideCursor = function(tm) { 21134 if (self.cursortimeout) return; 21135 if (!self.rail) return; 21136 if (!self.autohidedom) return; 21137 if (self.hasmousefocus && self.opt.autohidemode == "leave") return; 21138 self.cursortimeout = setTimeout(function() { 21139 if (!self.rail.active || !self.showonmouseevent) { 21140 self.autohidedom.stop().animate({ 21141 opacity: self.opt.cursoropacitymin 21142 }); 21143 if (self.zoom) self.zoom.stop().animate({ 21144 opacity: self.opt.cursoropacitymin 21145 }); 21146 self.cursoractive = false;
21147 } 21148 self.cursortimeout = 0; 21149 }, tm || self.opt.hidecursordelay); 21150 }; 21151 21152 this.noticeCursor = function(tm, py, px) { 21153 self.showCursor(py, px); 21154 if (!self.rail.active) self.hideCursor(tm); 21155 }; 21156 21157 this.getContentSize = 21158 (self.ispage) ? 21159 function() { 21160 return { 21161 w: Math.max(document.body.scrollWidth, document.documentElement.scrollWidth), 21162 h: Math.max(document.body.scrollHeight, document.documentElement.scrollHeight) 21163 } 21164 } : (self.haswrapper) ? 21165 function() { 21166 return { 21167 w: self.doc.outerWidth() + parseInt(self.win.css('paddingLeft')) + parseInt(self.win.css('paddingRight')), 21168 h: self.doc.outerHeight() + parseInt(self.win.css('paddingTop')) + parseInt(self.win.css('paddingBottom')) 21169 } 21170 } : function() { 21171 return { 21172 w: self.docscroll[0].scrollWidth, 21173 h: self.docscroll[0].scrollHeight 21174 } 21175 }; 21176 21177 this.onResize = function(e, page) { 21178 21179 if (!self || !self.win) return false; 21180 21181 if (!self.haswrapper && !self.ispage) { 21182 if (self.win.css('display') == 'none') { 21183 if (self.visibility) self.hideRail().hideRailHr(); 21184 return false; 21185 } else { 21186 if (!self.hidden && !self.visibility) self.showRail().showRailHr(); 21187 } 21188 } 21189 21190 var premaxh = self.page.maxh; 21191 var premaxw = self.page.maxw; 21192 21193 var preview = { 21194 h: self.view.h, 21195 w: self.view.w 21196 }; 21197 21198 self.view = { 21199 w: (self.ispage) ? self.win.width() : parseInt(self.win[0].clientWidth), 21200 h: (self.ispage) ? self.win.height() : parseInt(self.win[0].clientHeight) 21201 }; 21202 21203 self.page = (page) ? page : self.getContentSize(); 21204 21205 self.page.maxh = Math.max(0, self.page.h - self.view.h); 21206 self.page.maxw = Math.max(0, self.page.w - self.view.w); 21207 21208 if ((self.page.maxh == premaxh) && (self.page.maxw == premaxw) && (self.view.w == preview.w) && (self.view.h == preview.h)) { 21209 // test position 21210 if (!self.ispage) { 21211 var pos = self.win.offset(); 21212 if (self.lastposition) { 21213 var lst = self.lastposition; 21214 if ((lst.top == pos.top) && (lst.left == pos.left)) return self; //nothing to do 21215 } 21216 self.lastposition = pos; 21217 } else { 21218 return self; //nothing to do 21219 } 21220 } 21221 21222 if (self.page.maxh == 0) { 21223 self.hideRail(); 21224 self.scrollvaluemax = 0; 21225 self.scroll.y = 0; 21226 self.scrollratio.y = 0; 21227 self.cursorheight = 0; 21228 self.setScrollTop(0); 21229 if (self.rail) self.rail.scrollable = false; 21230 } else { 21231 self.page.maxh -= (self.opt.railpadding.top + self.opt.railpadding.bottom); //** 21232 self.rail.scrollable = true; 21233 } 21234 21235 if (self.page.maxw == 0) { 21236 self.hideRailHr(); 21237 self.scrollvaluemaxw = 0; 21238 self.scroll.x = 0; 21239 self.scrollratio.x = 0; 21240 self.cursorwidth = 0; 21241 self.setScrollLeft(0); 21242 if (self.railh) { 21243 self.railh.scrollable = false; 21244 } 21245 } else { 21246 self.page.maxw -= (self.opt.railpadding.left + self.opt.railpadding.right); //** 21247 if (self.railh) self.railh.scrollable = (self.opt.horizrailenabled); 21248 } 21249 21250 self.railslocked = (self.locked) || ((self.page.maxh == 0) && (self.page.maxw == 0)); 21251 if (self.railslocked) { 21252 if (!self.ispage) self.updateScrollBar(self.view); 21253 return false; 21254 } 21255 21256 if (!self.hidden && !self.visibility) { 21257 self.showRail().showRailHr(); 21258 } 21259 else if (self.railh && (!self.hidden && !self.railh.visibility)) self.showRailHr(); 21260 21261 if (self.istextarea && self.win.css('resize') && self.win.css('resize') != 'none') self.view.h -= 20; 21262 21263 self.cursorheight = Math.min(self.view.h, Math.round(self.view.h * (self.view.h / self.page.h))); 21264 self.cursorheight = (self.opt.cursorfixedheight) ? self.opt.cursorfixedheight : Math.max(self.opt.cursorminheight, self.cursorheight); 21265 21266 self.cursorwidth = Math.min(self.view.w, Math.round(self.view.w * (self.view.w / self.page.w))); 21267 self.cursorwidth = (self.opt.cursorfixedheight) ? self.opt.cursorfixedheight : Math.max(self.opt.cursorminheight, self.cursorwidth); 21268 21269 self.scrollvaluemax = self.view.h - self.cursorheight - self.cursor.hborder - (self.opt.railpadding.top + self.opt.railpadding.bottom); //** 21270 21271 if (self.railh) { 21272 self.railh.width = (self.page.maxh > 0) ? (self.view.w - self.rail.width) : self.view.w; 21273 self.scrollvaluemaxw = self.railh.width - self.cursorwidth - self.cursorh.wborder - (self.opt.railpadding.left + self.opt.railpadding.right); //** 21274 } 21275 21276 /* 21277 if (self.checkrtlmode&&self.railh) { 21278 self.checkrtlmode = false;
21279 if (self.opt.rtlmode&&self.scroll.x==0) self.setScrollLeft(self.page.maxw); 21280 } 21281*/ 21282 21283 if (!self.ispage) self.updateScrollBar(self.view); 21284 21285 self.scrollratio = { 21286 x: (self.page.maxw / self.scrollvaluemaxw), 21287 y: (self.page.maxh / self.scrollvaluemax) 21288 }; 21289 21290 var sy = self.getScrollTop(); 21291 if (sy > self.page.maxh) { 21292 self.doScrollTop(self.page.maxh); 21293 } else { 21294 self.scroll.y = Math.round(self.getScrollTop() * (1 / self.scrollratio.y)); 21295 self.scroll.x = Math.round(self.getScrollLeft() * (1 / self.scrollratio.x)); 21296 if (self.cursoractive) self.noticeCursor(); 21297 } 21298 21299 if (self.scroll.y && (self.getScrollTop() == 0)) self.doScrollTo(Math.floor(self.scroll.y * self.scrollratio.y)); 21300 21301 return self; 21302 }; 21303 21304 this.resize = self.onResize; 21305 21306 this.lazyResize = function(tm) { // event debounce 21307 tm = (isNaN(tm)) ? 30 : tm; 21308 self.debounced('resize', self.resize, tm); 21309 return self; 21310 }; 21311 21312 // modified by MDN https://developer.mozilla.org/en-US/docs/DOM/Mozilla_event_reference/wheel 21313 function _modernWheelEvent(dom, name, fn, bubble) { 21314 self._bind(dom, name, function(e) { 21315 var e = (e) ? e : window.event; 21316 var event = { 21317 original: e, 21318 target: e.target || e.srcElement, 21319 type: "wheel", 21320 deltaMode: e.type == "MozMousePixelScroll" ? 0 : 1, 21321 deltaX: 0, 21322 deltaZ: 0, 21323 preventDefault: function() { 21324 e.preventDefault ? e.preventDefault() : e.returnValue = false; 21325 return false; 21326 }, 21327 stopImmediatePropagation: function() { 21328 (e.stopImmediatePropagation) ? e.stopImmediatePropagation(): e.cancelBubble = true; 21329 } 21330 }; 21331 21332 if (name == "mousewheel") { 21333 event.deltaY = -1 / 40 * e.wheelDelta; 21334 e.wheelDeltaX && (event.deltaX = -1 / 40 * e.wheelDeltaX); 21335 } else { 21336 event.deltaY = e.detail; 21337 } 21338 21339 return fn.call(dom, event); 21340 }, bubble); 21341 }; 21342 21343 21344 21345 this.jqbind = function(dom, name, fn) { // use jquery bind for non-native events (mouseenter/mouseleave) 21346 self.events.push({ 21347 e: dom, 21348 n: name, 21349 f: fn, 21350 q: true 21351 }); 21352 $(dom).bind(name, fn); 21353 }; 21354 21355 this.bind = function(dom, name, fn, bubble) { // touch-oriented & fixing jquery bind 21356 var el = ("jquery" in dom) ? dom[0] : dom; 21357 21358 if (name == 'mousewheel') { 21359 if ("onwheel" in self.win) { // modern brosers & IE9 detection fix 21360 self._bind(el, "wheel", fn, bubble || false); 21361 } else { 21362 var wname = (typeof document.onmousewheel != "undefined") ? "mousewheel" : "DOMMouseScroll"; // older IE/Firefox 21363 _modernWheelEvent(el, wname, fn, bubble || false); 21364 21365 if (wname == "DOMMouseScroll") _modernWheelEvent(el, "MozMousePixelScroll", fn, bubble || false); // Firefox legacy 21366 } 21367 } else if (el.addEventListener) { 21368 if (cap.cantouch && /mouseup|mousedown|mousemove/.test(name)) { // touch device support 21369 var tt = (name == 'mousedown') ? 'touchstart' : (name == 'mouseup') ? 'touchend' : 'touchmove'; 21370 self._bind(el, tt, function(e) { 21371 if (e.touches) { 21372 if (e.touches.length < 2) { 21373 var ev = (e.touches.length) ? e.touches[0] : e; 21374 ev.original = e; 21375 fn.call(this, ev); 21376 } 21377 } else if (e.changedTouches) { 21378 var ev = e.changedTouches[0]; 21379 ev.original = e; 21380 fn.call(this, ev); 21381 } //blackberry 21382 }, bubble || false); 21383 } 21384 self._bind(el, name, fn, bubble || false); 21385 if (cap.cantouch && name == "mouseup") self._bind(el, "touchcancel", fn, bubble || false); 21386 } else { 21387 self._bind(el, name, function(e) { 21388 e = e || window.event || false; 21389 if (e) { 21390 if (e.srcElement) e.target = e.srcElement; 21391 } 21392 if (!("pageY" in e)) { 21393 e.pageX = e.clientX + document.documentElement.scrollLeft; 21394 e.pageY = e.clientY + document.documentElement.scrollTop; 21395 } 21396 return ((fn.call(el, e) === false) || bubble === false) ? self.cancelEvent(e) : true; 21397 }); 21398 } 21399 }; 21400 21401 if (cap.haseventlistener) { // W3C standard model 21402 this._bind = function(el, name, fn, bubble) { // primitive bind 21403 self.events.push({ 21404 e: el, 21405 n: name, 21406 f: fn, 21407 b: bubble, 21408 q: false 21409 }); 21410 el.addEventListener(name, fn, bubble || false); 21411 }; 21412 this.cancelEvent = function(e) { 21413 if (!e) return false;
21414 var e = (e.original) ? e.original : e; 21415 e.preventDefault(); 21416 e.stopPropagation(); 21417 if (e.preventManipulation) e.preventManipulation(); //IE10 21418 return false; 21419 }; 21420 this.stopPropagation = function(e) { 21421 if (!e) return false; 21422 var e = (e.original) ? e.original : e; 21423 e.stopPropagation(); 21424 return false; 21425 }; 21426 this._unbind = function(el, name, fn, bub) { // primitive unbind 21427 el.removeEventListener(name, fn, bub); 21428 }; 21429 } else { // old IE model 21430 this._bind = function(el, name, fn, bubble) { // primitive bind 21431 self.events.push({ 21432 e: el, 21433 n: name, 21434 f: fn, 21435 b: bubble, 21436 q: false 21437 }); 21438 if (el.attachEvent) { 21439 el.attachEvent("on" + name, fn); 21440 } else { 21441 el["on" + name] = fn; 21442 } 21443 }; 21444 // Thanks to http://www.switchonthecode.com !! 21445 this.cancelEvent = function(e) { 21446 var e = window.event || false; 21447 if (!e) return false; 21448 e.cancelBubble = true; 21449 e.cancel = true; 21450 e.returnValue = false; 21451 return false; 21452 }; 21453 this.stopPropagation = function(e) { 21454 var e = window.event || false; 21455 if (!e) return false; 21456 e.cancelBubble = true; 21457 return false; 21458 }; 21459 this._unbind = function(el, name, fn, bub) { // primitive unbind IE old 21460 if (el.detachEvent) { 21461 el.detachEvent('on' + name, fn); 21462 } else { 21463 el['on' + name] = false; 21464 } 21465 }; 21466 } 21467 21468 this.unbindAll = function() { 21469 for (var a = 0; a < self.events.length; a++) { 21470 var r = self.events[a]; 21471 (r.q) ? r.e.unbind(r.n, r.f): self._unbind(r.e, r.n, r.f, r.b); 21472 } 21473 }; 21474 21475 this.showRail = function() { 21476 if ((self.page.maxh != 0) && (self.ispage || self.win.css('display') != 'none')) { 21477 self.visibility = true; 21478 self.rail.visibility = true; 21479 self.rail.css('display', 'block'); 21480 } 21481 return self; 21482 }; 21483 21484 this.showRailHr = function() { 21485 if (!self.railh) return self; 21486 if ((self.page.maxw != 0) && (self.ispage || self.win.css('display') != 'none')) { 21487 self.railh.visibility = true; 21488 self.railh.css('display', 'block'); 21489 } 21490 return self; 21491 }; 21492 21493 this.hideRail = function() { 21494 self.visibility = false; 21495 self.rail.visibility = false; 21496 self.rail.css('display', 'none'); 21497 return self; 21498 }; 21499 21500 this.hideRailHr = function() { 21501 if (!self.railh) return self; 21502 self.railh.visibility = false; 21503 self.railh.css('display', 'none'); 21504 return self; 21505 }; 21506 21507 this.show = function() { 21508 self.hidden = false; 21509 self.railslocked = false; 21510 return self.showRail().showRailHr(); 21511 }; 21512 21513 this.hide = function() { 21514 self.hidden = true; 21515 self.railslocked = true; 21516 return self.hideRail().hideRailHr(); 21517 }; 21518 21519 this.toggle = function() { 21520 return (self.hidden) ? self.show() : self.hide(); 21521 }; 21522 21523 this.remove = function() { 21524 self.stop(); 21525 if (self.cursortimeout) clearTimeout(self.cursortimeout); 21526 if (self.debouncedelayed) clearTimeout(self.debouncedelayed); 21527 self.doZoomOut(); 21528 self.unbindAll(); 21529 21530 if (cap.isie9) self.win[0].detachEvent("onpropertychange", self.onAttributeChange); //IE9 DOMAttrModified bug 21531 21532 if (self.observer !== false) self.observer.disconnect(); 21533 if (self.observerremover !== false) self.observerremover.disconnect(); 21534 if (self.observerbody !== false) self.observerbody.disconnect(); 21535 21536 self.events = null; 21537 21538 if (self.cursor) { 21539 self.cursor.remove(); 21540 } 21541 if (self.cursorh) { 21542 self.cursorh.remove(); 21543 } 21544 if (self.rail) { 21545 self.rail.remove(); 21546 } 21547 if (self.railh) { 21548 self.railh.remove(); 21549 } 21550 if (self.zoom) { 21551 self.zoom.remove(); 21552 } 21553 for (var a = 0; a < self.saved.css.length; a++) { 21554 var d = self.saved.css[a]; 21555 d[0].css(d[1], (typeof d[2] == "undefined") ? '' : d[2]); 21556 } 21557 self.saved = false;
21558 self.me.data('__nicescroll', ''); //erase all traces 21559 21560 // memory leak fixed by GianlucaGuarini - thanks a lot! 21561 // remove the current nicescroll from the $.nicescroll array & normalize array 21562 var lst = $.nicescroll; 21563 lst.each(function(i) { 21564 if (!this) return; 21565 if (this.id === self.id) { 21566 delete lst[i]; 21567 for (var b = ++i; b < lst.length; b++, i++) lst[i] = lst[b]; 21568 lst.length--; 21569 if (lst.length) delete lst[lst.length]; 21570 } 21571 }); 21572 21573 for (var i in self) { 21574 self[i] = null; 21575 delete self[i]; 21576 } 21577 21578 self = null; 21579 21580 }; 21581 21582 this.scrollstart = function(fn) { 21583 this.onscrollstart = fn; 21584 return self; 21585 }; 21586 this.scrollend = function(fn) { 21587 this.onscrollend = fn; 21588 return self; 21589 }; 21590 this.scrollcancel = function(fn) { 21591 this.onscrollcancel = fn; 21592 return self; 21593 }; 21594 21595 this.zoomin = function(fn) { 21596 this.onzoomin = fn; 21597 return self; 21598 }; 21599 this.zoomout = function(fn) { 21600 this.onzoomout = fn; 21601 return self; 21602 }; 21603 21604 this.isScrollable = function(e) { 21605 var dom = (e.target) ? e.target : e; 21606 if (dom.nodeName == 'OPTION') return true; 21607 while (dom && (dom.nodeType == 1) && !(/^BODY|HTML/.test(dom.nodeName))) { 21608 var dd = $(dom); 21609 var ov = dd.css('overflowY') || dd.css('overflowX') || dd.css('overflow') || ''; 21610 if (/scroll|auto/.test(ov)) return (dom.clientHeight != dom.scrollHeight); 21611 dom = (dom.parentNode) ? dom.parentNode : false; 21612 } 21613 return false; 21614 }; 21615 21616 this.getViewport = function(me) { 21617 var dom = (me && me.parentNode) ? me.parentNode : false; 21618 while (dom && (dom.nodeType == 1) && !(/^BODY|HTML/.test(dom.nodeName))) { 21619 var dd = $(dom); 21620 if (/fixed|absolute/.test(dd.css("position"))) return dd; 21621 var ov = dd.css('overflowY') || dd.css('overflowX') || dd.css('overflow') || ''; 21622 if ((/scroll|auto/.test(ov)) && (dom.clientHeight != dom.scrollHeight)) return dd; 21623 if (dd.getNiceScroll().length > 0) return dd; 21624 dom = (dom.parentNode) ? dom.parentNode : false; 21625 } 21626 return false; //(dom) ? $(dom) : false; 21627 }; 21628 21629 this.triggerScrollEnd = function() { 21630 if (!self.onscrollend) return; 21631 21632 var px = self.getScrollLeft(); 21633 var py = self.getScrollTop(); 21634 21635 var info = { 21636 "type": "scrollend", 21637 "current": { 21638 "x": px, 21639 "y": py 21640 }, 21641 "end": { 21642 "x": px, 21643 "y": py 21644 } 21645 }; 21646 self.onscrollend.call(self, info); 21647 } 21648 21649 function execScrollWheel(e, hr, chkscroll) { 21650 var px, py; 21651 21652 if (e.deltaMode == 0) { // PIXEL 21653 px = -Math.floor(e.deltaX * (self.opt.mousescrollstep / (18 * 3))); 21654 py = -Math.floor(e.deltaY * (self.opt.mousescrollstep / (18 * 3))); 21655 } else if (e.deltaMode == 1) { // LINE 21656 px = -Math.floor(e.deltaX * self.opt.mousescrollstep); 21657 py = -Math.floor(e.deltaY * self.opt.mousescrollstep); 21658 } 21659 21660 if (hr && self.opt.oneaxismousemode && (px == 0) && py) { // classic vertical-only mousewheel + browser with x/y support 21661 px = py; 21662 py = 0; 21663 21664 if (chkscroll) { 21665 var hrend = (px < 0) ? (self.getScrollLeft() >= self.page.maxw) : (self.getScrollLeft() <= 0); 21666 if (hrend) { // preserve vertical scrolling 21667 py = px; 21668 px = 0; 21669 } 21670 } 21671 21672 } 21673 21674 if (px) { 21675 if (self.scrollmom) { 21676 self.scrollmom.stop() 21677 } 21678 self.lastdeltax += px; 21679 self.debounced("mousewheelx", function() { 21680 var dt = self.lastdeltax; 21681 self.lastdeltax = 0; 21682 if (!self.rail.drag) { 21683 self.doScrollLeftBy(dt) 21684 } 21685 }, 15); 21686 } 21687 if (py) { 21688 if (self.opt.nativeparentscrolling && chkscroll && !self.ispage && !self.zoomactive) { 21689 if (py < 0) { 21690 if (self.getScrollTop() >= self.page.maxh) return true; 21691 } else { 21692 if (self.getScrollTop() <= 0) return true; 21693 } 21694 } 21695 if (self.scrollmom) { 21696 self.scrollmom.stop() 21697 } 21698 self.lastdeltay += py; 21699 self.debounced("mousewheely", function() { 21700 var dt = self.lastdeltay; 21701 self.lastdeltay = 0; 21702 if (!self.rail.drag) { 21703 self.doScrollBy(dt) 21704 } 21705 }, 15); 21706 } 21707 21708 e.stopImmediatePropagation(); 21709 return e.preventDefault(); 21710 }; 21711 21712 this.onmousewheel = function(e) { 21713 if (self.wheelprevented) return; 21714 if (self.railslocked) { 21715 self.debounced("checkunlock", self.resize, 250); 21716 return true; 21717 } 21718 if (self.rail.drag) return self.cancelEvent(e); 21719 21720 if (self.opt.oneaxismousemode == "auto" && e.deltaX != 0) self.opt.oneaxismousemode = false; // check two-axis mouse support (not very elegant) 21721 21722 if (self.opt.oneaxismousemode && e.deltaX == 0) { 21723 if (!self.rail.scrollable) { 21724 if (self.railh && self.railh.scrollable) { 21725 return self.onmousewheelhr(e); 21726 } else { 21727 return true; 21728 } 21729 } 21730 } 21731 21732 var nw = +(new Date()); 21733 var chk = false;
21734 if (self.opt.preservenativescrolling && ((self.checkarea + 600) < nw)) { 21735 self.nativescrollingarea = self.isScrollable(e); 21736 chk = true; 21737 } 21738 self.checkarea = nw; 21739 if (self.nativescrollingarea) return true; // this isn't my business 21740 var ret = execScrollWheel(e, false, chk); 21741 if (ret) self.checkarea = 0; 21742 return ret; 21743 }; 21744 21745 this.onmousewheelhr = function(e) { 21746 if (self.wheelprevented) return; 21747 if (self.railslocked || !self.railh.scrollable) return true; 21748 if (self.rail.drag) return self.cancelEvent(e); 21749 21750 var nw = +(new Date()); 21751 var chk = false; 21752 if (self.opt.preservenativescrolling && ((self.checkarea + 600) < nw)) { 21753 self.nativescrollingarea = self.isScrollable(e); 21754 chk = true; 21755 } 21756 self.checkarea = nw; 21757 if (self.nativescrollingarea) return true; // this isn't my business 21758 if (self.railslocked) return self.cancelEvent(e); 21759 21760 return execScrollWheel(e, true, chk); 21761 }; 21762 21763 this.stop = function() { 21764 self.cancelScroll(); 21765 if (self.scrollmon) self.scrollmon.stop(); 21766 self.cursorfreezed = false; 21767 self.scroll.y = Math.round(self.getScrollTop() * (1 / self.scrollratio.y)); 21768 self.noticeCursor(); 21769 return self; 21770 }; 21771 21772 this.getTransitionSpeed = function(dif) { 21773 var sp = Math.round(self.opt.scrollspeed * 10); 21774 var ex = Math.min(sp, Math.round((dif / 20) * self.opt.scrollspeed)); 21775 return (ex > 20) ? ex : 0; 21776 }; 21777 21778 if (!self.opt.smoothscroll) { 21779 this.doScrollLeft = function(x, spd) { //direct 21780 var y = self.getScrollTop(); 21781 self.doScrollPos(x, y, spd); 21782 }; 21783 this.doScrollTop = function(y, spd) { //direct 21784 var x = self.getScrollLeft(); 21785 self.doScrollPos(x, y, spd); 21786 }; 21787 this.doScrollPos = function(x, y, spd) { //direct 21788 var nx = (x > self.page.maxw) ? self.page.maxw : x; 21789 if (nx < 0) nx = 0; 21790 var ny = (y > self.page.maxh) ? self.page.maxh : y; 21791 if (ny < 0) ny = 0; 21792 self.synched('scroll', function() { 21793 self.setScrollTop(ny); 21794 self.setScrollLeft(nx); 21795 }); 21796 }; 21797 this.cancelScroll = function() {}; // direct 21798 } else if (self.ishwscroll && cap.hastransition && self.opt.usetransition && !!self.opt.smoothscroll) { 21799 this.prepareTransition = function(dif, istime) { 21800 var ex = (istime) ? ((dif > 20) ? dif : 0) : self.getTransitionSpeed(dif); 21801 var trans = (ex) ? cap.prefixstyle + 'transform ' + ex + 'ms ease-out' : ''; 21802 if (!self.lasttransitionstyle || self.lasttransitionstyle != trans) { 21803 self.lasttransitionstyle = trans; 21804 self.doc.css(cap.transitionstyle, trans); 21805 } 21806 return ex; 21807 }; 21808 21809 this.doScrollLeft = function(x, spd) { //trans 21810 var y = (self.scrollrunning) ? self.newscrolly : self.getScrollTop(); 21811 self.doScrollPos(x, y, spd); 21812 }; 21813 21814 this.doScrollTop = function(y, spd) { //trans 21815 var x = (self.scrollrunning) ? self.newscrollx : self.getScrollLeft(); 21816 self.doScrollPos(x, y, spd); 21817 }; 21818 21819 this.doScrollPos = function(x, y, spd) { //trans 21820 21821 var py = self.getScrollTop(); 21822 var px = self.getScrollLeft(); 21823 21824 if (((self.newscrolly - py) * (y - py) < 0) || ((self.newscrollx - px) * (x - px) < 0)) self.cancelScroll(); //inverted movement detection 21825 21826 if (self.opt.bouncescroll == false) { 21827 if (y < 0) y = 0; 21828 else if (y > self.page.maxh) y = self.page.maxh; 21829 if (x < 0) x = 0; 21830 else if (x > self.page.maxw) x = self.page.maxw; 21831 } 21832 21833 if (self.scrollrunning && x == self.newscrollx && y == self.newscrolly) return false; 21834 21835 self.newscrolly = y; 21836 self.newscrollx = x; 21837 21838 self.newscrollspeed = spd || false; 21839 21840 if (self.timer) return false; 21841 21842 self.timer = setTimeout(function() { 21843 21844 var top = self.getScrollTop(); 21845 var lft = self.getScrollLeft(); 21846 21847 var dst = {}; 21848 dst.x = x - lft; 21849 dst.y = y - top; 21850 dst.px = lft; 21851 dst.py = top; 21852 21853 var dd = Math.round(Math.sqrt(Math.pow(dst.x, 2) + Math.pow(dst.y, 2))); 21854 var ms = (self.newscrollspeed && self.newscrollspeed > 1) ? self.newscrollspeed : self.getTransitionSpeed(dd); 21855 if (self.newscrollspeed && self.newscrollspeed <= 1) ms *= self.newscrollspeed; 21856 21857 self.prepareTransition(ms, true); 21858 21859 if (self.timerscroll && self.timerscroll.tm) clearInterval(self.timerscroll.tm); 21860 21861 if (ms > 0) { 21862 21863 if (!self.scrollrunning && self.onscrollstart) { 21864 var info = { 21865 "type": "scrollstart", 21866 "current": { 21867 "x": lft, 21868 "y": top 21869 }, 21870 "request": { 21871 "x": x, 21872 "y": y 21873 }, 21874 "end": { 21875 "x": self.newscrollx, 21876 "y": self.newscrolly 21877 }, 21878 "speed": ms 21879 }; 21880 self.onscrollstart.call(self, info); 21881 } 21882 21883 if (cap.transitionend) { 21884 if (!self.scrollendtrapped) { 21885 self.scrollendtrapped = true; 21886 self.bind(self.doc, cap.transitionend, self.onScrollTransitionEnd, false); //I have got to do something usefull!! 21887 } 21888 } else { 21889 if (self.scrollendtrapped) clearTimeout(self.scrollendtrapped); 21890 self.scrollendtrapped = setTimeout(self.onScrollTransitionEnd, ms); // simulate transitionend event 21891 } 21892 21893 var py = top; 21894 var px = lft; 21895 self.timerscroll = { 21896 bz: new BezierClass(py, self.newscrolly, ms, 0, 0, 0.58, 1), 21897 bh: new BezierClass(px, self.newscrollx, ms, 0, 0, 0.58, 1) 21898 }; 21899 if (!self.cursorfreezed) self.timerscroll.tm = setInterval(function() { 21900 self.showCursor(self.getScrollTop(), self.getScrollLeft()) 21901 }, 60); 21902 21903 } 21904 21905 self.synched("doScroll-set", function() { 21906 self.timer = 0; 21907 if (self.scrollendtrapped) self.scrollrunning = true; 21908 self.setScrollTop(self.newscrolly); 21909 self.setScrollLeft(self.newscrollx); 21910 if (!self.scrollendtrapped) self.onScrollTransitionEnd(); 21911 }); 21912 21913 21914 }, 50); 21915 21916 }; 21917 21918 this.cancelScroll = function() { 21919 if (!self.scrollendtrapped) return true; 21920 var py = self.getScrollTop(); 21921 var px = self.getScrollLeft(); 21922 self.scrollrunning = false;
21923 if (!cap.transitionend) clearTimeout(cap.transitionend); 21924 self.scrollendtrapped = false; 21925 self._unbind(self.doc[0], cap.transitionend, self.onScrollTransitionEnd); 21926 self.prepareTransition(0); 21927 self.setScrollTop(py); // fire event onscroll 21928 if (self.railh) self.setScrollLeft(px); 21929 if (self.timerscroll && self.timerscroll.tm) clearInterval(self.timerscroll.tm); 21930 self.timerscroll = false; 21931 21932 self.cursorfreezed = false; 21933 21934 self.showCursor(py, px); 21935 return self; 21936 }; 21937 this.onScrollTransitionEnd = function() { 21938 if (self.scrollendtrapped) self._unbind(self.doc[0], cap.transitionend, self.onScrollTransitionEnd); 21939 self.scrollendtrapped = false; 21940 self.prepareTransition(0); 21941 if (self.timerscroll && self.timerscroll.tm) clearInterval(self.timerscroll.tm); 21942 self.timerscroll = false; 21943 var py = self.getScrollTop(); 21944 var px = self.getScrollLeft(); 21945 self.setScrollTop(py); // fire event onscroll 21946 if (self.railh) self.setScrollLeft(px); // fire event onscroll left 21947 21948 self.noticeCursor(false, py, px); 21949 21950 self.cursorfreezed = false; 21951 21952 if (py < 0) py = 0 21953 else if (py > self.page.maxh) py = self.page.maxh; 21954 if (px < 0) px = 0 21955 else if (px > self.page.maxw) px = self.page.maxw; 21956 if ((py != self.newscrolly) || (px != self.newscrollx)) return self.doScrollPos(px, py, self.opt.snapbackspeed); 21957 21958 if (self.onscrollend && self.scrollrunning) { 21959 self.triggerScrollEnd(); 21960 } 21961 self.scrollrunning = false; 21962 21963 }; 21964 21965 } else { 21966 21967 this.doScrollLeft = function(x, spd) { //no-trans 21968 var y = (self.scrollrunning) ? self.newscrolly : self.getScrollTop(); 21969 self.doScrollPos(x, y, spd); 21970 }; 21971 21972 this.doScrollTop = function(y, spd) { //no-trans 21973 var x = (self.scrollrunning) ? self.newscrollx : self.getScrollLeft(); 21974 self.doScrollPos(x, y, spd); 21975 }; 21976 21977 this.doScrollPos = function(x, y, spd) { //no-trans 21978 var y = ((typeof y == "undefined") || (y === false)) ? self.getScrollTop(true) : y; 21979 21980 if ((self.timer) && (self.newscrolly == y) && (self.newscrollx == x)) return true; 21981 21982 if (self.timer) clearAnimationFrame(self.timer); 21983 self.timer = 0; 21984 21985 var py = self.getScrollTop(); 21986 var px = self.getScrollLeft(); 21987 21988 if (((self.newscrolly - py) * (y - py) < 0) || ((self.newscrollx - px) * (x - px) < 0)) self.cancelScroll(); //inverted movement detection 21989 21990 self.newscrolly = y; 21991 self.newscrollx = x; 21992 21993 if (!self.bouncescroll || !self.rail.visibility) { 21994 if (self.newscrolly < 0) { 21995 self.newscrolly = 0; 21996 } else if (self.newscrolly > self.page.maxh) { 21997 self.newscrolly = self.page.maxh; 21998 } 21999 } 22000 if (!self.bouncescroll || !self.railh.visibility) { 22001 if (self.newscrollx < 0) { 22002 self.newscrollx = 0; 22003 } else if (self.newscrollx > self.page.maxw) { 22004 self.newscrollx = self.page.maxw; 22005 } 22006 } 22007 22008 self.dst = {}; 22009 self.dst.x = x - px; 22010 self.dst.y = y - py; 22011 self.dst.px = px; 22012 self.dst.py = py; 22013 22014 var dst = Math.round(Math.sqrt(Math.pow(self.dst.x, 2) + Math.pow(self.dst.y, 2))); 22015 22016 self.dst.ax = self.dst.x / dst; 22017 self.dst.ay = self.dst.y / dst; 22018 22019 var pa = 0; 22020 var pe = dst; 22021 22022 if (self.dst.x == 0) { 22023 pa = py; 22024 pe = y; 22025 self.dst.ay = 1; 22026 self.dst.py = 0; 22027 } else if (self.dst.y == 0) { 22028 pa = px; 22029 pe = x; 22030 self.dst.ax = 1; 22031 self.dst.px = 0; 22032 } 22033 22034 var ms = self.getTransitionSpeed(dst); 22035 if (spd && spd <= 1) ms *= spd; 22036 if (ms > 0) { 22037 self.bzscroll = (self.bzscroll) ? self.bzscroll.update(pe, ms) : new BezierClass(pa, pe, ms, 0, 1, 0, 1); 22038 } else { 22039 self.bzscroll = false; 22040 } 22041 22042 if (self.timer) return; 22043 22044 if ((py == self.page.maxh && y >= self.page.maxh) || (px == self.page.maxw && x >= self.page.maxw)) self.checkContentSize(); 22045 22046 var sync = 1; 22047 22048 function scrolling() { 22049 if (self.cancelAnimationFrame) return true; 22050 22051 self.scrollrunning = true; 22052 22053 sync = 1 - sync; 22054 if (sync) return (self.timer = setAnimationFrame(scrolling) || 1); 22055 22056 var done = 0; 22057 var sx, sy; 22058 22059 var sc = sy = self.getScrollTop(); 22060 if (self.dst.ay) { 22061 sc = (self.bzscroll) ? self.dst.py + (self.bzscroll.getNow() * self.dst.ay) : self.newscrolly; 22062 var dr = sc - sy; 22063 if ((dr < 0 && sc < self.newscrolly) || (dr > 0 && sc > self.newscrolly)) sc = self.newscrolly; 22064 self.setScrollTop(sc); 22065 if (sc == self.newscrolly) done = 1; 22066 } else { 22067 done = 1; 22068 } 22069 22070 var scx = sx = self.getScrollLeft(); 22071 if (self.dst.ax) { 22072 scx = (self.bzscroll) ? self.dst.px + (self.bzscroll.getNow() * self.dst.ax) : self.newscrollx; 22073 var dr = scx - sx; 22074 if ((dr < 0 && scx < self.newscrollx) || (dr > 0 && scx > self.newscrollx)) scx = self.newscrollx; 22075 self.setScrollLeft(scx); 22076 if (scx == self.newscrollx) done += 1; 22077 } else { 22078 done += 1; 22079 } 22080 22081 if (done == 2) { 22082 self.timer = 0; 22083 self.cursorfreezed = false;
22084 self.bzscroll = false; 22085 self.scrollrunning = false; 22086 if (sc < 0) sc = 0; 22087 else if (sc > self.page.maxh) sc = self.page.maxh; 22088 if (scx < 0) scx = 0; 22089 else if (scx > self.page.maxw) scx = self.page.maxw; 22090 if ((scx != self.newscrollx) || (sc != self.newscrolly)) self.doScrollPos(scx, sc); 22091 else { 22092 if (self.onscrollend) { 22093 self.triggerScrollEnd(); 22094 } 22095 } 22096 } else { 22097 self.timer = setAnimationFrame(scrolling) || 1; 22098 } 22099 }; 22100 self.cancelAnimationFrame = false; 22101 self.timer = 1; 22102 22103 if (self.onscrollstart && !self.scrollrunning) { 22104 var info = { 22105 "type": "scrollstart", 22106 "current": { 22107 "x": px, 22108 "y": py 22109 }, 22110 "request": { 22111 "x": x, 22112 "y": y 22113 }, 22114 "end": { 22115 "x": self.newscrollx, 22116 "y": self.newscrolly 22117 }, 22118 "speed": ms 22119 }; 22120 self.onscrollstart.call(self, info); 22121 } 22122 22123 scrolling(); 22124 22125 if ((py == self.page.maxh && y >= py) || (px == self.page.maxw && x >= px)) self.checkContentSize(); 22126 22127 self.noticeCursor(); 22128 }; 22129 22130 this.cancelScroll = function() { 22131 if (self.timer) clearAnimationFrame(self.timer); 22132 self.timer = 0; 22133 self.bzscroll = false; 22134 self.scrollrunning = false; 22135 return self; 22136 }; 22137 22138 } 22139 22140 this.doScrollBy = function(stp, relative) { 22141 var ny = 0; 22142 if (relative) { 22143 ny = Math.floor((self.scroll.y - stp) * self.scrollratio.y) 22144 } else { 22145 var sy = (self.timer) ? self.newscrolly : self.getScrollTop(true); 22146 ny = sy - stp; 22147 } 22148 if (self.bouncescroll) { 22149 var haf = Math.round(self.view.h / 2); 22150 if (ny < -haf) ny = -haf 22151 else if (ny > (self.page.maxh + haf)) ny = (self.page.maxh + haf); 22152 } 22153 self.cursorfreezed = false; 22154 22155 var py = self.getScrollTop(true); 22156 if (ny < 0 && py <= 0) return self.noticeCursor(); 22157 else if (ny > self.page.maxh && py >= self.page.maxh) { 22158 self.checkContentSize(); 22159 return self.noticeCursor(); 22160 } 22161 22162 self.doScrollTop(ny); 22163 }; 22164 22165 this.doScrollLeftBy = function(stp, relative) { 22166 var nx = 0; 22167 if (relative) { 22168 nx = Math.floor((self.scroll.x - stp) * self.scrollratio.x) 22169 } else { 22170 var sx = (self.timer) ? self.newscrollx : self.getScrollLeft(true); 22171 nx = sx - stp; 22172 } 22173 if (self.bouncescroll) { 22174 var haf = Math.round(self.view.w / 2); 22175 if (nx < -haf) nx = -haf; 22176 else if (nx > (self.page.maxw + haf)) nx = (self.page.maxw + haf); 22177 } 22178 self.cursorfreezed = false; 22179 22180 var px = self.getScrollLeft(true); 22181 if (nx < 0 && px <= 0) return self.noticeCursor(); 22182 else if (nx > self.page.maxw && px >= self.page.maxw) return self.noticeCursor(); 22183 22184 self.doScrollLeft(nx); 22185 }; 22186 22187 this.doScrollTo = function(pos, relative) { 22188 var ny = (relative) ? Math.round(pos * self.scrollratio.y) : pos; 22189 if (ny < 0) ny = 0; 22190 else if (ny > self.page.maxh) ny = self.page.maxh; 22191 self.cursorfreezed = false; 22192 self.doScrollTop(pos); 22193 }; 22194 22195 this.checkContentSize = function() { 22196 var pg = self.getContentSize(); 22197 if ((pg.h != self.page.h) || (pg.w != self.page.w)) self.resize(false, pg); 22198 }; 22199 22200 self.onscroll = function(e) { 22201 if (self.rail.drag) return; 22202 if (!self.cursorfreezed) { 22203 self.synched('scroll', function() { 22204 self.scroll.y = Math.round(self.getScrollTop() * (1 / self.scrollratio.y)); 22205 if (self.railh) self.scroll.x = Math.round(self.getScrollLeft() * (1 / self.scrollratio.x)); 22206 self.noticeCursor(); 22207 }); 22208 } 22209 }; 22210 self.bind(self.docscroll, "scroll", self.onscroll); 22211 22212 this.doZoomIn = function(e) { 22213 if (self.zoomactive) return; 22214 self.zoomactive = true; 22215 22216 self.zoomrestore = { 22217 style: {} 22218 }; 22219 var lst = ['position', 'top', 'left', 'zIndex', 'backgroundColor', 'marginTop', 'marginBottom', 'marginLeft', 'marginRight']; 22220 var win = self.win[0].style; 22221 for (var a in lst) { 22222 var pp = lst[a]; 22223 self.zoomrestore.style[pp] = (typeof win[pp] != "undefined") ? win[pp] : ''; 22224 } 22225 22226 self.zoomrestore.style.width = self.win.css('width'); 22227 self.zoomrestore.style.height = self.win.css('height'); 22228 22229 self.zoomrestore.padding = { 22230 w: self.win.outerWidth() - self.win.width(), 22231 h: self.win.outerHeight() - self.win.height() 22232 }; 22233 22234 if (cap.isios4) { 22235 self.zoomrestore.scrollTop = $(window).scrollTop(); 22236 $(window).scrollTop(0); 22237 } 22238 22239 self.win.css({ 22240 "position": (cap.isios4) ? "absolute" : "fixed", 22241 "top": 0, 22242 "left": 0, 22243 "z-index": globalmaxzindex + 100, 22244 "margin": "0px" 22245 }); 22246 var bkg = self.win.css("backgroundColor");
vendor: 8,483 bytes, lines 22247-22561
22247 if (bkg == "" || /transparent|rgba\(0, 0, 0, 0\)|rgba\(0,0,0,0\)/.test(bkg)) self.win.css("backgroundColor", "#fff"); 22248 self.rail.css({ 22249 "z-index": globalmaxzindex + 101 22250 }); 22251 self.zoom.css({ 22252 "z-index": globalmaxzindex + 102 22253 }); 22254 self.zoom.css('backgroundPosition', '0px -18px'); 22255 self.resizeZoom(); 22256 22257 if (self.onzoomin) self.onzoomin.call(self); 22258 22259 return self.cancelEvent(e); 22260 }; 22261 22262 this.doZoomOut = function(e) { 22263 if (!self.zoomactive) return; 22264 self.zoomactive = false; 22265 22266 self.win.css("margin", ""); 22267 self.win.css(self.zoomrestore.style); 22268 22269 if (cap.isios4) { 22270 $(window).scrollTop(self.zoomrestore.scrollTop); 22271 } 22272 22273 self.rail.css({ 22274 "z-index": self.zindex 22275 }); 22276 self.zoom.css({ 22277 "z-index": self.zindex 22278 }); 22279 self.zoomrestore = false; 22280 self.zoom.css('backgroundPosition', '0px 0px'); 22281 self.onResize(); 22282 22283 if (self.onzoomout) self.onzoomout.call(self); 22284 22285 return self.cancelEvent(e); 22286 }; 22287 22288 this.doZoom = function(e) { 22289 return (self.zoomactive) ? self.doZoomOut(e) : self.doZoomIn(e); 22290 }; 22291 22292 this.resizeZoom = function() { 22293 if (!self.zoomactive) return; 22294 22295 var py = self.getScrollTop(); //preserve scrolling position 22296 self.win.css({ 22297 width: $(window).width() - self.zoomrestore.padding.w + "px", 22298 height: $(window).height() - self.zoomrestore.padding.h + "px" 22299 }); 22300 self.onResize(); 22301 22302 self.setScrollTop(Math.min(self.page.maxh, py)); 22303 }; 22304 22305 this.init(); 22306 22307 $.nicescroll.push(this); 22308 22309 }; 22310 22311 // Inspired by the work of Kin Blas 22312 // http://webpro.host.adobe.com/people/jblas/momentum/includes/jquery.momentum.0.7.js 22313 22314 22315 var ScrollMomentumClass2D = function(nc) { 22316 var self = this; 22317 this.nc = nc; 22318 22319 this.lastx = 0; 22320 this.lasty = 0; 22321 this.speedx = 0; 22322 this.speedy = 0; 22323 this.lasttime = 0; 22324 this.steptime = 0; 22325 this.snapx = false; 22326 this.snapy = false; 22327 this.demulx = 0; 22328 this.demuly = 0; 22329 22330 this.lastscrollx = -1; 22331 this.lastscrolly = -1; 22332 22333 this.chkx = 0; 22334 this.chky = 0; 22335 22336 this.timer = 0; 22337 22338 this.time = function() { 22339 return +new Date(); //beautifull hack 22340 }; 22341 22342 this.reset = function(px, py) { 22343 self.stop(); 22344 var now = self.time(); 22345 self.steptime = 0; 22346 self.lasttime = now; 22347 self.speedx = 0; 22348 self.speedy = 0; 22349 self.lastx = px; 22350 self.lasty = py; 22351 self.lastscrollx = -1; 22352 self.lastscrolly = -1; 22353 }; 22354 22355 this.update = function(px, py) { 22356 var now = self.time(); 22357 self.steptime = now - self.lasttime; 22358 self.lasttime = now; 22359 var dy = py - self.lasty; 22360 var dx = px - self.lastx; 22361 var sy = self.nc.getScrollTop(); 22362 var sx = self.nc.getScrollLeft(); 22363 var newy = sy + dy; 22364 var newx = sx + dx; 22365 self.snapx = (newx < 0) || (newx > self.nc.page.maxw); 22366 self.snapy = (newy < 0) || (newy > self.nc.page.maxh); 22367 self.speedx = dx; 22368 self.speedy = dy; 22369 self.lastx = px; 22370 self.lasty = py; 22371 }; 22372 22373 this.stop = function() { 22374 self.nc.unsynched("domomentum2d"); 22375 if (self.timer) clearTimeout(self.timer); 22376 self.timer = 0; 22377 self.lastscrollx = -1; 22378 self.lastscrolly = -1; 22379 }; 22380 22381 this.doSnapy = function(nx, ny) { 22382 var snap = false; 22383 22384 if (ny < 0) { 22385 ny = 0; 22386 snap = true; 22387 } else if (ny > self.nc.page.maxh) { 22388 ny = self.nc.page.maxh; 22389 snap = true; 22390 } 22391 22392 if (nx < 0) { 22393 nx = 0; 22394 snap = true; 22395 } else if (nx > self.nc.page.maxw) { 22396 nx = self.nc.page.maxw; 22397 snap = true; 22398 } 22399 22400 (snap) ? self.nc.doScrollPos(nx, ny, self.nc.opt.snapbackspeed): self.nc.triggerScrollEnd(); 22401 }; 22402 22403 this.doMomentum = function(gp) { 22404 var t = self.time(); 22405 var l = (gp) ? t + gp : self.lasttime; 22406 22407 var sl = self.nc.getScrollLeft(); 22408 var st = self.nc.getScrollTop(); 22409 22410 var pageh = self.nc.page.maxh; 22411 var pagew = self.nc.page.maxw; 22412 22413 self.speedx = (pagew > 0) ? Math.min(60, self.speedx) : 0; 22414 self.speedy = (pageh > 0) ? Math.min(60, self.speedy) : 0; 22415 22416 var chk = l && (t - l) <= 60; 22417 22418 if ((st < 0) || (st > pageh) || (sl < 0) || (sl > pagew)) chk = false; 22419 22420 var sy = (self.speedy && chk) ? self.speedy : false; 22421 var sx = (self.speedx && chk) ? self.speedx : false; 22422 22423 if (sy || sx) { 22424 var tm = Math.max(16, self.steptime); //timeout granularity 22425 22426 if (tm > 50) { // do smooth 22427 var xm = tm / 50; 22428 self.speedx *= xm; 22429 self.speedy *= xm; 22430 tm = 50; 22431 } 22432 22433 self.demulxy = 0; 22434 22435 self.lastscrollx = self.nc.getScrollLeft(); 22436 self.chkx = self.lastscrollx; 22437 self.lastscrolly = self.nc.getScrollTop(); 22438 self.chky = self.lastscrolly; 22439 22440 var nx = self.lastscrollx; 22441 var ny = self.lastscrolly; 22442 22443 var onscroll = function() { 22444 var df = ((self.time() - t) > 600) ? 0.04 : 0.02; 22445 22446 if (self.speedx) { 22447 nx = Math.floor(self.lastscrollx - (self.speedx * (1 - self.demulxy))); 22448 self.lastscrollx = nx; 22449 if ((nx < 0) || (nx > pagew)) df = 0.10; 22450 } 22451 22452 if (self.speedy) { 22453 ny = Math.floor(self.lastscrolly - (self.speedy * (1 - self.demulxy))); 22454 self.lastscrolly = ny; 22455 if ((ny < 0) || (ny > pageh)) df = 0.10; 22456 } 22457 22458 self.demulxy = Math.min(1, self.demulxy + df); 22459 22460 self.nc.synched("domomentum2d", function() { 22461 22462 if (self.speedx) { 22463 var scx = self.nc.getScrollLeft(); 22464 if (scx != self.chkx) self.stop(); 22465 self.chkx = nx; 22466 self.nc.setScrollLeft(nx); 22467 } 22468 22469 if (self.speedy) { 22470 var scy = self.nc.getScrollTop(); 22471 if (scy != self.chky) self.stop(); 22472 self.chky = ny; 22473 self.nc.setScrollTop(ny); 22474 } 22475 22476 if (!self.timer) { 22477 self.nc.hideCursor(); 22478 self.doSnapy(nx, ny); 22479 } 22480 22481 }); 22482 22483 if (self.demulxy < 1) { 22484 self.timer = setTimeout(onscroll, tm); 22485 } else { 22486 self.stop(); 22487 self.nc.hideCursor(); 22488 self.doSnapy(nx, ny); 22489 } 22490 }; 22491 22492 onscroll(); 22493 22494 } else { 22495 self.doSnapy(self.nc.getScrollLeft(), self.nc.getScrollTop()); 22496 } 22497 22498 } 22499 22500 }; 22501 22502 22503 // override jQuery scrollTop 22504 22505 var _scrollTop = jQuery.fn.scrollTop; // preserve original function 22506 22507 jQuery.cssHooks["pageYOffset"] = { 22508 get: function(elem, computed, extra) { 22509 var nice = $.data(elem, '__nicescroll') || false; 22510 return (nice && nice.ishwscroll) ? nice.getScrollTop() : _scrollTop.call(elem); 22511 }, 22512 set: function(elem, value) { 22513 var nice = $.data(elem, '__nicescroll') || false; 22514 (nice && nice.ishwscroll) ? nice.setScrollTop(parseInt(value)): _scrollTop.call(elem, value); 22515 return this; 22516 } 22517 }; 22518 22519 /* 22520 $.fx.step["scrollTop"] = function(fx){ 22521 $.cssHooks["scrollTop"].set( fx.elem, fx.now + fx.unit ); 22522 }; 22523*/ 22524 22525 jQuery.fn.scrollTop = function(value) { 22526 if (typeof value == "undefined") { 22527 var nice = (this[0]) ? $.data(this[0], '__nicescroll') || false : false; 22528 return (nice && nice.ishwscroll) ? nice.getScrollTop() : _scrollTop.call(this); 22529 } else { 22530 return this.each(function() { 22531 var nice = $.data(this, '__nicescroll') || false; 22532 (nice && nice.ishwscroll) ? nice.setScrollTop(parseInt(value)): _scrollTop.call($(this), value); 22533 }); 22534 } 22535 }; 22536 22537 // override jQuery scrollLeft 22538 22539 var _scrollLeft = jQuery.fn.scrollLeft; // preserve original function 22540 22541 $.cssHooks.pageXOffset = { 22542 get: function(elem, computed, extra) { 22543 var nice = $.data(elem, '__nicescroll') || false; 22544 return (nice && nice.ishwscroll) ? nice.getScrollLeft() : _scrollLeft.call(elem); 22545 }, 22546 set: function(elem, value) { 22547 var nice = $.data(elem, '__nicescroll') || false; 22548 (nice && nice.ishwscroll) ? nice.setScrollLeft(parseInt(value)): _scrollLeft.call(elem, value); 22549 return this; 22550 } 22551 }; 22552 22553 /* 22554 $.fx.step["scrollLeft"] = function(fx){ 22555 $.cssHooks["scrollLeft"].set( fx.elem, fx.now + fx.unit ); 22556 }; 22557*/ 22558 22559 jQuery.fn.scrollLeft = function(value) { 22560 if (typeof value == "undefined") { 22561 var nice = (this[0]) ? $.data(this[0], '__nicescroll') || false : false;
22562 return (nice && nice.ishwscroll) ? nice.getScrollLeft() : _scrollLeft.call(this); 22563 } else { 22564 return this.each(function() { 22565 var nice = $.data(this, '__nicescroll') || false; 22566 (nice && nice.ishwscroll) ? nice.setScrollLeft(parseInt(value)): _scrollLeft.call($(this), value); 22567 }); 22568 } 22569 }; 22570 22571 var NiceScrollArray = function(doms) { 22572 var self = this; 22573 this.length = 0; 22574 this.name = "nicescrollarray"; 22575 22576 this.each = function(fn) { 22577 for (var a = 0, i = 0; a < self.length; a++) fn.call(self[a], i++); 22578 return self; 22579 }; 22580 22581 this.push = function(nice) { 22582 self[self.length] = nice; 22583 self.length++; 22584 }; 22585 22586 this.eq = function(idx) { 22587 return self[idx]; 22588 }; 22589 22590 if (doms) { 22591 for (var a = 0; a < doms.length; a++) { 22592 var nice = $.data(doms[a], '__nicescroll') || false; 22593 if (nice) { 22594 this[this.length] = nice; 22595 this.length++; 22596 } 22597 }; 22598 } 22599 22600 return this; 22601 }; 22602 22603 function mplex(el, lst, fn) { 22604 for (var a = 0; a < lst.length; a++) fn(el, lst[a]); 22605 }; 22606 mplex( 22607 NiceScrollArray.prototype, ['show', 'hide', 'toggle', 'onResize', 'resize', 'remove', 'stop', 'doScrollPos'], 22608 function(e, n) { 22609 e[n] = function() { 22610 var args = arguments; 22611 return this.each(function() { 22612 this[n].apply(this, args); 22613 }); 22614 }; 22615 } 22616 ); 22617 22618 jQuery.fn.getNiceScroll = function(index) { 22619 if (typeof index == "undefined") { 22620 return new NiceScrollArray(this); 22621 } else { 22622 var nice = this[index] && $.data(this[index], '__nicescroll') || false; 22623 return nice; 22624 } 22625 }; 22626 22627 jQuery.extend(jQuery.expr[':'], { 22628 nicescroll: function(a) { 22629 return ($.data(a, '__nicescroll')) ? true : false; 22630 } 22631 }); 22632 22633 $.fn.niceScroll = function(wrapper, opt) { 22634 if (typeof opt == "undefined") { 22635 if ((typeof wrapper == "object") && !("jquery" in wrapper)) { 22636 opt = wrapper; 22637 wrapper = false;
22638 } 22639 } 22640 opt = $.extend({},opt); // cloning 22641 var ret = new NiceScrollArray(); 22642 if (typeof opt == "undefined") opt = {}; 22643 22644 if (wrapper || false) { 22645 opt.doc = $(wrapper); 22646 opt.win = $(this); 22647 } 22648 var docundef = !("doc" in opt); 22649 if (!docundef && !("win" in opt)) opt.win = $(this); 22650 22651 this.each(function() { 22652 var nice = $(this).data('__nicescroll') || false; 22653 if (!nice) { 22654 opt.doc = (docundef) ? $(this) : opt.doc; 22655 nice = new NiceScrollClass(opt, $(this)); 22656 $(this).data('__nicescroll', nice); 22657 } 22658 ret.push(nice); 22659 }); 22660 return (ret.length == 1) ? ret[0] : ret; 22661 }; 22662 22663 window.NiceScroll = { 22664 getjQuery: function() { 22665 return jQuery 22666 } 22667 }; 22668 22669 if (!$.nicescroll) { 22670 $.nicescroll = new NiceScrollArray(); 22671 $.nicescroll.options = _globaloptions; 22672 } 22673 22674})); 22675 22676/* 22677 * validate2.js 0.0.2 22678 * 22679 * (c) Alex Buturlakin [email protected] 22680 */ 22681(function (window, document, undefined) { 22682 /* 22683 * Use the setMessage() function to overwrite specific messages. 22684 * Or $.validatorMessages() if you use jquery 22685 * Or set message directly in rule 22686 * 22687 * "{0}" - field name, {1...} - rule parameters 22688 */ 22689 var defaults = { 22690 messages: { 22691 required: 'The {0} field is required.', 22692 matches: 'The {0} field does not match the {1} field.', 22693 "default": 'The {0} field is still set to default, please change.', 22694 valid_email: 'The {0} field must contain a valid email address.', 22695 valid_emails: 'The {0} field must contain all valid email addresses.', 22696 english: 'The {0} field must contain only english characters', 22697 english_numeric: 'The {0} field must contain only english characters or numeric', 22698 company_name: 'The {0} field shoould be a valid comapny name', 22699 min_length: 'The {0} field must be at least {1} characters in length.', 22700 max_length: 'The {0} field must not exceed {1} characters in length.', 22701 exact_length: 'The {0} field must be exactly {1} characters in length.', 22702 length_one_or_two: 'The {0} field must be exactly {1} or {2} characters in length.', 22703 greater_than: 'The {0} field must contain a number greater than {1}.', 22704 less_than: 'The {0} field must contain a number less than {1}.', 22705 alpha: 'The {0} field must only contain alphabetical characters.', 22706 alpha_numeric: 'The {0} field must only contain alpha-numeric characters.', 22707 alpha_numeric_space: 'The {0} field must only contain alpha-numeric and space characters.', 22708 alpha_numeric_space_dots: 'The {0} field must only contain alpha-numeric, space and dots characters.', 22709 alpha_dash: 'The {0} field must only contain alpha-numeric characters, underscores, and dashes.', 22710 numeric: 'The {0} field must contain only numbers.', 22711 integer: 'The {0} field must contain an integer.', 22712 decimal: 'The {0} field must contain a decimal number.', 22713 is_natural: 'The {0} field must contain only positive numbers.', 22714 is_natural_no_zero: 'The {0} field must contain a number greater than zero.', 22715 valid_ip: 'The {0} field must contain a valid IP.', 22716 valid_base64: 'The {0} field must contain a base64 string.', 22717 valid_credit_card: 'The {0} field must contain a valid credit card number.', 22718 is_file_type: 'The {0} field must contain only {1} files.', 22719 valid_url: 'The {0} field must contain a valid URL.', 22720 greater_than_date: 'The {0} field must contain a more recent date than {1}.', 22721 less_than_date: 'The {0} field must contain an older date than {1}.', 22722 greater_than_or_equal_date: 'The {0} field must contain a date that\'s at least as recent as {1}.', 22723 less_than_or_equal_date: 'The {0} field must contain a date that\'s {1} or older.', 22724 password: 'At least eight characters: one number and one uppercase or lowercase English or Hebrew letter.', 22725 one_word: 'The {0} field must contain only one word.', 22726 two_words: 'The {0} field must contain only two words.', 22727 words_count: 'The {0} field must contain only {1} words.', 22728 words_count_max: 'The {0} field must contain a words less than {1}.', 22729 words_count_min: 'The {0} field must have at least {1} words.', 22730 street: 'The {0} field must contain a valid street address.' 22731 }, 22732 formCallback: function (status, errors) { }, 22733 fieldCallback: function (status, field, errors) { } 22734 }; 22735 22736 /* 22737 * Define the regular expressions that will be used 22738 */ 22739 var ruleRegex = /^(.+?)\[(.+)\]$/, 22740 numericRegex = /^[0-9]+$/, 22741 integerRegex = /^\-?[0-9]+$/, 22742 decimalRegex = /^\-?[0-9]*\.?[0-9]+$/, 22743 // emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/, 22744 emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/, 22745 alphaRegex = /^[a-z]+$/i, 22746 alphaNumericRegex = /^[a-z0-9]+$/i, 22747 alphaDashRegex = /^[a-z0-9_\-]+$/i, 22748 naturalRegex = /^[0-9]+$/i, 22749 naturalNoZeroRegex = /^[1-9][0-9]*$/i, 22750 ipRegex = /^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})$/i, 22751 base64Regex = /[^a-zA-Z0-9\/\+=]/i, 22752 numericDashRegex = /^[\d\-\s]+$/, 22753 urlRegex = /^((http|https):\/\/(\w+:{0,1}\w*@)?(\S+)|)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/, 22754 dateRegex = /\d{4}-\d{1,2}-\d{1,2}/, 22755 englishRegex = /^[a-zA-Z\s]+$/, 22756 englishNumericRegex = /^[a-zA-Z0-9\s]+$/, 22757 passwordRegex = /^(?=.*[0-9])(?=.*[a-z|A-Z]).{8,}$/, 22758 wordsCountRegex = /\b\S+\b/g, 22759 alphaNumericSpaceRegex = /^[a-z0-9\s]+$/i, 22760 alphaNumericSpaceDotRegex = /^[a-z0-9\s\.]+$/i, 22761 streetRegex = /^\s*\S+(?:\s+\S+){1}/, 22762 hasHebrewCharsRegex = /[\u0590-\u05FF]/, 22763 // companyRegex = /(?:^|\s)(?:Corporation|Corp|Inc|Incorporated|Company|LTD|PLLC|P\.C)\.?$/ig 22764 companyRegex = /\bLTD\b/; 22765 22766 22767 /* 22768 * The exposed public object to validate a form: 22769 * 22770 * @param formNameOrNode - String - The name attribute of the form (i.e. <form name="myForm"></form>) or node of the form element 22771 * @param fields - Array - [{ 22772 * name: The name of the element (i.e. <input name="myField" />) 22773 * display: 'Field Name' 22774 * rules: required|matches[password_confirm], 22775 * messages: { 22776 * 'rule_name': 'Custom message' 22777 * } 22778 * }] 22779 * 22780 * @param options - Options 22781 */ 22782 var FormValidator = function (formNameOrNode, fields, options) { 22783 this.o = { 22784 callbacks: { 22785 fields: [defaults.fieldCallback], 22786 form: [defaults.formCallback] 22787 } 22788 }; 22789 22790 // todo@alexbuturlakin: Remove jQuery usage 22791 jQuery.extend(this.o, options); 22792 22793 this.errors = {}; 22794 this.fields = {};
22795 this.form = this._formByNameOrNode(formNameOrNode) || {}; 22796 this.messages = {}; 22797 this.handlers = {}; 22798 this.conditionals = {}; 22799 this.defaultGroup = 'default'; 22800 this.disableGroupValidation = false; 22801 22802 for (var i = 0, fieldLength = fields.length; i < fieldLength; i++) { 22803 var field = fields[i]; 22804 22805 // If passed in incorrectly, we need to skip the field. 22806 if ((!field.name && !field.names) || !field.rules) { 22807 continue; 22808 } 22809 22810 /* 22811 * Build the master fields array that has all the information needed to validate 22812 */ 22813 if (field.names) { 22814 for (var j = 0, fieldNamesLength = field.names.length; j < fieldNamesLength; j++) { 22815 this._addField(field, field.names[j]); 22816 } 22817 } else { 22818 this._addField(field, field.name); 22819 } 22820 } 22821 }; 22822 22823 /** 22824 * Get element attribute. 22825 * 22826 * @param {HTMLInputElement} element 22827 * @param {String} attributeName 22828 * 22829 * @returns {String} 22830 */ 22831 FormValidator.prototype.getAttributeValue = function (element, attributeName) { 22832 var i; 22833 22834 if ((element.length > 0) && (element[0].type === 'radio' || element[0].type === 'checkbox')) { 22835 for (i = 0, elementLength = element.length; i < elementLength; i++) { 22836 if (element[i].checked) { 22837 return element[i][attributeName]; 22838 } 22839 } 22840 22841 return ''; 22842 } 22843 22844 return element[attributeName]; 22845 }; 22846 22847 /* 22848 * @public 22849 * Sets a custom message for one of the rules 22850 */ 22851 22852 FormValidator.prototype.setMessage = function (rule, message) { 22853 this.messages[rule] = message; 22854 22855 // return this for chaining 22856 return this; 22857 }; 22858 22859 /* 22860 * @public 22861 * Registers a callback for a custom rule (i.e. callback_username_check) 22862 */ 22863 22864 FormValidator.prototype.registerCallback = function (name, handler) { 22865 if (name && typeof name === 'string' && handler && typeof handler === 'function') { 22866 this.handlers[name] = handler; 22867 } 22868 22869 // return this for chaining 22870 return this; 22871 }; 22872 22873 /* 22874 * @public 22875 * Registers a conditional for a custom 'depends' rule 22876 */ 22877 22878 FormValidator.prototype.registerConditional = function (name, conditional) { 22879 if (name && typeof name === 'string' && conditional && typeof conditional === 'function') { 22880 this.conditionals[name] = conditional; 22881 } 22882 22883 // return this for chaining 22884 return this; 22885 }; 22886 22887 /* 22888 * @private 22889 * Determines if a form dom node was passed in or just a string representing the form name 22890 */ 22891 22892 FormValidator.prototype._formByNameOrNode = function (formNameOrNode) { 22893 return (typeof formNameOrNode === 'object') ? formNameOrNode : document.forms[formNameOrNode]; 22894 }; 22895 22896 /* 22897 * @private 22898 * Adds a file to the master fields array 22899 */ 22900 22901 FormValidator.prototype._addField = function (field, nameValue) { 22902 this.fields[nameValue] = { 22903 name: nameValue, 22904 display: field.display || nameValue, 22905 rules: field.rules, 22906 depends: field.depends, 22907 group: typeof field.group === typeof undefined ? this.defaultGroup : field.group, 22908 id: null, 22909 element: null, 22910 type: null, 22911 value: null, 22912 checked: null 22913 }; 22914 22915 // add custom validation rules for current field 22916 if('custom' in field) { 22917 for(var k in field.custom) { 22918 if('function' == typeof field.custom[k]) { 22919 this._hooks[k + '.' + nameValue] = field.custom[k]; 22920 } 22921 } 22922 } 22923 }; 22924 22925 /** 22926 * Change rules for field. 22927 * 22928 * @param {String} name 22929 * @param {String} rules 22930 * @param {{}} [messages] 22931 * @returns {boolean} 22932 */ 22933 FormValidator.prototype.changeFiledRules = function (name, rules, messages) { 22934 messages = messages || {}; 22935 22936 // field not exists 22937 if(!(name in this.fields)) { 22938 return false; 22939 } 22940 22941 // set rules 22942 this.fields[name]['rules'] = rules; 22943 22944 // set messages 22945 for(var k in messages) { 22946 this.setMessage(name+'.'+k, messages[k]); 22947 } 22948 }; 22949 22950 /* 22951 * @private 22952 * Runs the validation when the form is submitted. 22953 */ 22954 22955 FormValidator.prototype._validateForm = function (groups) { 22956 groups = groups || []; 22957 22958 // clean errors 22959 this.cleanErrors(); 22960 22961 // validate fields 22962 for (var key in this.fields) { 22963 this.validateField(key, 'form', groups); 22964 } 22965 22966 // execute callbacks 22967 this._executeCallbacks('form', [ 22968 0 === Object.keys(this.errors).length, 22969 this.errors, 22970 0 == groups.length ? ['default'] : groups 22971 ], this.form); 22972 22973 // result 22974 var result = 0 == Object.keys(this.errors).length; 22975 this.cleanErrors(); 22976 22977 return result; 22978 }; 22979 22980 /** 22981 * Execute callbacks. 22982 * 22983 * @param {String} type 22984 * @param {[]} params 22985 * @param {Object} [context] 22986 * 22987 * @returns {boolean} 22988 * 22989 * @private 22990 */ 22991 FormValidator.prototype._executeCallbacks = function (type, params, context) { 22992 context = context || this; 22993 22994 if (this.o.callbacks === typeof undefined || this.o.callbacks[type] === typeof undefined) { 22995 return false;
22996 } 22997 22998 var callbacks = this.o.callbacks[type]; 22999 23000 for (var k in callbacks) { 23001 var callback = callbacks[k]; 23002 callback.apply(context, params); 23003 } 23004 23005 return true; 23006 }; 23007 23008 /** 23009 * @param {String} fieldName 23010 */ 23011 FormValidator.prototype.validateField = function (fieldName, type, groups) { 23012 type = type || 'single'; 23013 groups = groups || []; 23014 23015 if (this.fields.hasOwnProperty(fieldName)) { 23016 var field = this.fields[fieldName] || {}, 23017 group = field.group, 23018 element = this.form[field.name]; 23019 23020 if (element && element !== undefined && 23021 (false === this.disableGroupValidation || group != this.disableGroupValidation) && 23022 (0 == groups.length || groups.indexOf(group) > -1)) { 23023 field.id = this.getAttributeValue(element, 'id'); 23024 field.element = element; 23025 field.type = (element.length > 0) ? element[0].type : element.type; 23026 field.value = this.getAttributeValue(element, 'value'); 23027 field.checked = this.getAttributeValue(element, 'checked'); 23028 23029 /* 23030 * Run through the rules for each field. 23031 * If the field has a depends conditional, only validate the field 23032 * if it passes the custom function 23033 */ 23034 if (field.depends && typeof field.depends === "function") { 23035 if (field.depends.call(this, field)) { 23036 this._validateField(field); 23037 } 23038 } else if (field.depends && typeof field.depends === "string" && this.conditionals[field.depends]) { 23039 if (this.conditionals[field.depends].call(this, field)) { 23040 this._validateField(field); 23041 } 23042 } else { 23043 this._validateField(field); 23044 } 23045 } 23046 23047 this._executeCallbacks('fields', [ 23048 !(fieldName in this.errors), 23049 type, 23050 field, 23051 fieldName in this.errors ? this.errors[fieldName] : [], 23052 0 == groups.length ? ['default'] : groups 23053 ], field.element); 23054 } 23055 }; 23056 23057 /* 23058 * @private 23059 * Looks at the fields value and evaluates it against the given rules 23060 */ 23061 FormValidator.prototype._validateField = function (field) { 23062 var rules = field.rules.split('|'), 23063 indexOfRequired = field.rules.indexOf('required'), 23064 isEmpty = (!field.value || field.value === '' || field.value === undefined); 23065 23066 /* 23067 * Run through the rules and execute the validation methods as needed 23068 */ 23069 for (var i = 0, ruleLength = rules.length; i < ruleLength; i++) { 23070 var method = rules[i], 23071 param = null, 23072 failed = false, 23073 parts = ruleRegex.exec(method); 23074 23075 /* 23076 * If this field is not required and the value is empty, continue on to the next rule unless it's a callback. 23077 * This ensures that a callback will always be called but other rules will be skipped. 23078 */ 23079 if (indexOfRequired === -1 && method.indexOf('!callback_') === -1 && isEmpty) { 23080 continue; 23081 } 23082 23083 /* 23084 * If the rule has a parameter (i.e. matches[param]) split it out 23085 */ 23086 if (parts) { 23087 method = parts[1]; 23088 param = this._getParams(parts); 23089 } 23090 23091 if (method.charAt(0) === '!') { 23092 method = method.substring(1, method.length); 23093 } 23094 23095 /* 23096 * If the hook is defined, run it to find any validation errors 23097 */ 23098 if (typeof this._hooks[method] === 'function') { 23099 if (!this._hooks[method].apply(this, [field, param])) { 23100 failed = true; 23101 } 23102 23103 // personal custom rule 23104 } else if(typeof this._hooks[method + '.' + field.name] === 'function') { 23105 if (!this._hooks[method + '.' + field.name].apply(this, [field, param])) { 23106 failed = true; 23107 } 23108 } else if (method.substring(0, 9) === 'callback_') { 23109 // Custom method. Execute the handler if it was registered 23110 method = method.substring(9, method.length); 23111 23112 if (typeof this.handlers[method] === 'function') { 23113 if (this.handlers[method].apply(this, [field.value, param, field]) === false) { 23114 failed = true; 23115 } 23116 } 23117 } 23118 23119 /* 23120 * If the hook failed, add a message to the errors array 23121 */ 23122 if (failed) { 23123 this._addError(field.name, { 23124 id: field.id, 23125 element: field.element, 23126 name: field.name, 23127 message: this._getMessage(field.name, method, param), 23128 rule: method 23129 }); 23130 23131 // Break out so as to not spam with validation errors (i.e. required and valid_email) 23132 // break; 23133 } 23134 } 23135 }; 23136 23137 /** 23138 * Add related error. 23139 * 23140 * @param {String} name 23141 * @param {{}} data 23142 * 23143 * @private 23144 */ 23145 FormValidator.prototype._addError = function (name, data) { 23146 if (!(name in this.errors)) { 23147 this.errors[name] = []; 23148 } 23149 23150 this.errors[name].push(data); 23151 }; 23152 23153 /** 23154 * Disable validation. 23155 * 23156 * @param {String} [group] 23157 */ 23158 FormValidator.prototype.disable = function (group) { 23159 group = group || this.defaultGroup; 23160 23161 this.disableGroupValidation = group; 23162 }; 23163 23164 /** 23165 * Disable validation. 23166 */ 23167 FormValidator.prototype.enable = function () { 23168 this.disableGroupValidation = false;
23169 }; 23170 23171 /** 23172 * private function _getValidDate: helper function to convert a string date to a Date object 23173 * @param date (String) must be in format yyyy-mm-dd or use keyword: today 23174 * @returns {Date} returns false if invalid 23175 */ 23176 FormValidator.prototype._getValidDate = function (date) { 23177 if (!date.match('today') && !date.match(dateRegex)) { 23178 return false; 23179 } 23180 23181 var validDate = new Date(), 23182 validDateArray; 23183 23184 if (!date.match('today')) { 23185 validDateArray = date.split('-'); 23186 validDate.setFullYear(validDateArray[0]); 23187 validDate.setMonth(validDateArray[1] - 1); 23188 validDate.setDate(validDateArray[2]); 23189 } 23190 return validDate; 23191 }; 23192 23193 /** 23194 * Get error message 23195 * 23196 * @param {String} fieldName 23197 * @param {String} method 23198 * @param {String} [param] 23199 * 23200 * @returns {string} 23201 */ 23202 FormValidator.prototype._getMessage = function (fieldName, method, param) { 23203 var field = this.fields[fieldName] || {}, 23204 source = this.messages[fieldName + '.' + method] || this.messages[method] || defaults.messages[method], 23205 message = 'An error has occurred with the ' + field.display + ' field.', 23206 params = param ? this.fields[param] ? this.fields[param].display : param : []; 23207 23208 if (null === source) { 23209 return ''; 23210 } 23211 23212 if (source) { 23213 message = this.replace(source, field.display, params); 23214 } 23215 23216 return message; 23217 }; 23218 23219 23220 /** 23221 * Replace in message. 23222 * 23223 * @param {String|String[]} source 23224 * @param {String|String[]} display 23225 * @param {String|String[]} params 23226 */ 23227 FormValidator.prototype.replace = function (source, display, params) { 23228 var replace = []; 23229 23230 source = Array.isArray(source) ? source : [source]; 23231 params = Array.isArray(params) ? params : [params]; 23232 23233 replace.push(display); 23234 replace = replace.concat(params); 23235 23236 for(var s in source) { 23237 source[s] = FormValidator.prototype.formatString.apply(source[s], replace); 23238 } 23239 23240 return 1 == source.length ? source[0] : source; 23241 }; 23242 23243 /** 23244 * Format string 23245 * 23246 * @returns {FormValidator} 23247 */ 23248 FormValidator.prototype.formatString = function() { 23249 var s = this, 23250 i = arguments.length; 23251 23252 while (i--) { 23253 s = s.replace(new RegExp('\\{' + i + '\\}', 'gm'), arguments[i]); 23254 } 23255 23256 return s; 23257 }; 23258 23259 /** 23260 * Clean errors. 23261 */ 23262 FormValidator.prototype.cleanErrors = function () { 23263 this.errors = {}; 23264 }; 23265 23266 /** 23267 * Get rule info 23268 * 23269 * @param {String} rule 23270 * @returns {{}} 23271 */ 23272 FormValidator.prototype._getRuleInfo = function (rule) { 23273 var parts = ruleRegex.exec(rule); 23274 23275 if (parts) { 23276 return { 23277 'method': parts[1], 23278 'params': this._getParams(parts) 23279 }; 23280 } 23281 23282 return { 23283 'method': rule, 23284 'params': false 23285 }; 23286 }; 23287 23288 /** 23289 * Get params for method. 23290 * 23291 * @param {Array|*} parts 23292 * 23293 * @returns {*} 23294 * 23295 * @private 23296 */ 23297 FormValidator.prototype._getParams = function (parts) { 23298 if (false == parts) { 23299 return false; 23300 } 23301 23302 var params = parts[2]; 23303 23304 if (false == params) { 23305 return false; 23306 } 23307 23308 params = params.split(','); 23309 23310 return 1 === params.length ? params[0] : params; 23311 }; 23312 23313 /* 23314 * @private 23315 * Object containing all of the validation hooks 23316 */ 23317 23318 FormValidator.prototype._hooks = { 23319 required: function (field) { 23320 var value = field.value; 23321 23322 if ((field.type === 'checkbox') || (field.type === 'radio')) { 23323 return (field.checked === true); 23324 } 23325 23326 return (value !== null && value !== ''); 23327 }, 23328 23329 "default": function (field, defaultName) { 23330 return field.value !== defaultName; 23331 }, 23332 23333 matches: function (field, matchName) { 23334 var el = this.form[matchName]; 23335 23336 if (el) { 23337 return field.value === el.value; 23338 } 23339 23340 return false; 23341 }, 23342 23343 valid_email: function (field) { 23344 return emailRegex.test(field.value); 23345 }, 23346 23347 english: function (field) { 23348 return englishRegex.test(field.value); 23349 }, 23350 23351 english_numeric: function (field) { 23352 return englishNumericRegex.test(field.value) 23353 }, 23354 23355 company_name: function (field) { 23356 return companyRegex.test(field.value); 23357 }, 23358 23359 valid_emails: function (field) { 23360 var result = field.value.split(/\s*,\s*/g); 23361 23362 for (var i = 0, resultLength = result.length; i < resultLength; i++) { 23363 if (!emailRegex.test(result[i])) { 23364 return false;
23365 } 23366 } 23367 23368 return true; 23369 }, 23370 23371 min_length: function (field, length) { 23372 if (!numericRegex.test(length)) { 23373 return false; 23374 } 23375 23376 return (field.value.length >= parseInt(length, 10)); 23377 }, 23378 23379 max_length: function (field, length) { 23380 if (!numericRegex.test(length)) { 23381 return false; 23382 } 23383 23384 return (field.value.length <= parseInt(length, 10)); 23385 }, 23386 23387 exact_length: function (field, length) { 23388 if (!numericRegex.test(length)) { 23389 return false; 23390 } 23391 23392 return (field.value.length === parseInt(length, 10)); 23393 }, 23394 23395 greater_than: function (field, param) { 23396 if (!decimalRegex.test(field.value)) { 23397 return false; 23398 } 23399 23400 return (parseFloat(field.value) > parseFloat(param)); 23401 }, 23402 23403 less_than: function (field, param) { 23404 if (!decimalRegex.test(field.value)) { 23405 return false; 23406 } 23407 23408 return (parseFloat(field.value) < parseFloat(param)); 23409 }, 23410 23411 length_one_or_two: function (field, params) { 23412 23413 for (var k in params) { 23414 if (field.value.length === parseInt(params[k], 10)) { 23415 return true; 23416 } 23417 } 23418 23419 return false; 23420 }, 23421 23422 alpha: function (field) { 23423 return (alphaRegex.test(field.value)); 23424 }, 23425 23426 alpha_numeric: function (field) { 23427 return (alphaNumericRegex.test(field.value)); 23428 }, 23429 23430 street: function (field) { 23431 return (streetRegex.test(field.value)); 23432 }, 23433 23434 alpha_numeric_space: function(field) { 23435 return (alphaNumericSpaceRegex.test(field.value)); 23436 }, 23437 23438 alpha_numeric_space_dot: function(field) { 23439 return (alphaNumericSpaceDotRegex.test(field.value)); 23440 }, 23441 23442 alpha_dash: function (field) { 23443 return (alphaDashRegex.test(field.value)); 23444 }, 23445 23446 numeric: function (field) { 23447 return (numericRegex.test(field.value)); 23448 }, 23449 23450 integer: function (field) { 23451 return (integerRegex.test(field.value)); 23452 }, 23453 23454 decimal: function (field) { 23455 return (decimalRegex.test(field.value)); 23456 }, 23457 23458 is_natural: function (field) { 23459 return (naturalRegex.test(field.value)); 23460 }, 23461 23462 is_natural_no_zero: function (field) { 23463 return (naturalNoZeroRegex.test(field.value)); 23464 }, 23465 23466 valid_ip: function (field) { 23467 return (ipRegex.test(field.value)); 23468 }, 23469 23470 valid_base64: function (field) { 23471 return (base64Regex.test(field.value)); 23472 }, 23473 23474 valid_url: function (field) { 23475 return (urlRegex.test(field.value)); 23476 }, 23477 23478 password: function (field) { 23479 return passwordRegex.test(field.value) && !hasHebrewCharsRegex.test(field.value); 23480 }, 23481 23482 words_count: function (field, value) { 23483 var count = field.value.split(wordsCountRegex).length - 1; 23484 23485 return count == value; 23486 }, 23487 23488 words_count_max: function (field, max) { 23489 var count = field.value.split(wordsCountRegex).length - 1; 23490 23491 return count <= max; 23492 }, 23493 23494 words_count_min: function (field, min) { 23495 var count = field.value.split(wordsCountRegex).length - 1; 23496 23497 return count >= min; 23498 }, 23499 23500 // todo@alexbuturlakin: remove one_word and two_words or add words_count validator 23501 one_word: function (field) { 23502 var count = field.value.split(wordsCountRegex).length; 23503 23504 return 1 === count - 1 || 2 <= count - 1; 23505 }, 23506 23507 two_words: function (field) { 23508 var count = field.value.split(wordsCountRegex).length; 23509 23510 return 2 <= count - 1; 23511 }, 23512 23513 valid_credit_card: function (field) { 23514 // Luhn Check Code from https://gist.github.com/4075533 23515 // accept only digits, dashes or spaces 23516 if (!numericDashRegex.test(field.value)) return false; 23517 23518 // The Luhn Algorithm. It's so pretty. 23519 var nCheck = 0, nDigit = 0, bEven = false; 23520 var strippedField = field.value.replace(/\D/g, ""); 23521 23522 for (var n = strippedField.length - 1; n >= 0; n--) { 23523 var cDigit = strippedField.charAt(n); 23524 nDigit = parseInt(cDigit, 10); 23525 if (bEven) { 23526 if ((nDigit *= 2) > 9) nDigit -= 9; 23527 } 23528 23529 nCheck += nDigit; 23530 bEven = !bEven; 23531 } 23532 23533 return (nCheck % 10) === 0; 23534 }, 23535 23536 is_file_type: function (field, type) { 23537 if (field.type !== 'file') { 23538 return true; 23539 } 23540 23541 var ext = field.value.substr((field.value.lastIndexOf('.') + 1)), 23542 typeArray = type.split(','), 23543 inArray = false, 23544 i = 0, 23545 len = typeArray.length; 23546 23547 for (i; i < len; i++) { 23548 if (ext == typeArray[i]) inArray = true; 23549 } 23550 23551 return inArray; 23552 }, 23553 23554 greater_than_date: function (field, date) { 23555 var enteredDate = this._getValidDate(field.value), 23556 validDate = this._getValidDate(date); 23557 23558 if (!validDate || !enteredDate) { 23559 return false;
23560 } 23561 23562 return enteredDate > validDate; 23563 }, 23564 23565 less_than_date: function (field, date) { 23566 var enteredDate = this._getValidDate(field.value), 23567 validDate = this._getValidDate(date); 23568 23569 if (!validDate || !enteredDate) { 23570 return false; 23571 } 23572 23573 return enteredDate < validDate; 23574 }, 23575 23576 greater_than_or_equal_date: function (field, date) { 23577 var enteredDate = this._getValidDate(field.value), 23578 validDate = this._getValidDate(date); 23579 23580 if (!validDate || !enteredDate) { 23581 return false; 23582 } 23583 23584 return enteredDate >= validDate; 23585 }, 23586 23587 less_than_or_equal_date: function (field, date) { 23588 var enteredDate = this._getValidDate(field.value), 23589 validDate = this._getValidDate(date); 23590 23591 if (!validDate || !enteredDate) { 23592 return false; 23593 } 23594 23595 return enteredDate <= validDate; 23596 } 23597 }; 23598 23599 window.FormValidator = FormValidator; 23600 23601 // jQuery integration 23602 (function ($) { 23603 /** 23604 * Get or set messages for validation errors. 23605 * 23606 * @param {{}} [messages] 23607 */ 23608 $.validatorMessages = function (messages) { 23609 messages = messages || {}; 23610 23611 return $.extend(defaults.messages, messages); 23612 }; 23613 23614 })(jQuery); 23615 23616})(window, document); 23617 23618/* 23619 * Export as a CommonJS module 23620 */ 23621if (typeof module !== 'undefined' && module.exports) { 23622 module.exports = FormValidator; 23623} 23624/* 23625 * jQuery Storage API Plugin 23626 * 23627 * Copyright (c) 2013 Julien Maurel 23628 * 23629 * Licensed under the MIT license: 23630 * http://www.opensource.org/licenses/mit-license.php 23631 * 23632 * Project home: 23633 * https://github.com/julien-maurel/jQuery-Storage-API 23634 * 23635 * Version: 1.9.2 23636 */ 23637(function (factory) { 23638 if (typeof define === 'function' && define.amd) { 23639 // AMD 23640 define(['jquery'], factory); 23641 } else if (typeof exports === 'object') { 23642 // CommonJS 23643 factory(require('jquery')); 23644 } else { 23645 // Browser globals 23646 factory(jQuery); 23647 } 23648}(function ($) { 23649 // Prefix to use with cookie fallback 23650 var cookie_local_prefix = "ls_"; 23651 var cookie_session_prefix = "ss_"; 23652 23653 // Get items from a storage 23654 function _get() { 23655 var storage = this._type, l = arguments.length, s = window[storage], a = arguments, a0 = a[0], vi, ret, tmp; 23656 if (l < 1) { 23657 throw new Error('Minimum 1 argument must be given'); 23658 } else if ($.isArray(a0)) { 23659 // If second argument is an array, return an object with value of storage for each item in this array 23660 ret = {}; 23661 for (var i in a0) { 23662 vi = a0[i]; 23663 try { 23664 ret[vi] = JSON.parse(s.getItem(vi)); 23665 } catch (e) { 23666 ret[vi] = s.getItem(vi); 23667 } 23668 } 23669 return ret; 23670 } else if (l == 1) { 23671 // If only 1 argument, return value directly 23672 try { 23673 return JSON.parse(s.getItem(a0)); 23674 } catch (e) { 23675 return s.getItem(a0); 23676 } 23677 } else { 23678 // If more than 1 argument, parse storage to retrieve final value to return it 23679 // Get first level 23680 try { 23681 ret = JSON.parse(s.getItem(a0)); 23682 } catch (e) { 23683 throw new ReferenceError(a0 + ' is not defined in this storage'); 23684 } 23685 // Parse next levels 23686 for (var i = 1; i < l - 1; i++) { 23687 ret = ret[a[i]]; 23688 if (ret === undefined) { 23689 throw new ReferenceError([].slice.call(a, 1, i + 1).join('.') + ' is not defined in this storage'); 23690 } 23691 } 23692 // If last argument is an array, return an object with value for each item in this array 23693 // Else return value normally 23694 if ($.isArray(a[i])) { 23695 tmp = ret; 23696 ret = {}; 23697 for (var j in a[i]) { 23698 ret[a[i][j]] = tmp[a[i][j]]; 23699 } 23700 return ret; 23701 } else { 23702 return ret[a[i]]; 23703 } 23704 } 23705 } 23706 23707 // Set items of a storage 23708 function _set() { 23709 var storage = this._type, l = arguments.length, s = window[storage], a = arguments, a0 = a[0], a1 = a[1], vi, to_store = isNaN(a1)?{}:[], type, tmp; 23710 if (l < 1 || !$.isPlainObject(a0) && l < 2) { 23711 throw new Error('Minimum 2 arguments must be given or first parameter must be an object'); 23712 } else if ($.isPlainObject(a0)) { 23713 // If first argument is an object, set values of storage for each property of this object 23714 for (var i in a0) { 23715 vi = a0[i]; 23716 if (!$.isPlainObject(vi) && !this.alwaysUseJson) { 23717 s.setItem(i, vi); 23718 } else { 23719 s.setItem(i, JSON.stringify(vi)); 23720 } 23721 } 23722 return a0; 23723 } else if (l == 2) { 23724 // If only 2 arguments, set value of storage directly 23725 if (typeof a1 === 'object' || this.alwaysUseJson) { 23726 s.setItem(a0, JSON.stringify(a1)); 23727 } else { 23728 s.setItem(a0, a1); 23729 } 23730 return a1; 23731 } else { 23732 // If more than 3 arguments, parse storage to retrieve final node and set value 23733 // Get first level 23734 try { 23735 tmp = s.getItem(a0); 23736 if (tmp != null) { 23737 to_store = JSON.parse(tmp); 23738 } 23739 } catch (e) { 23740 } 23741 tmp = to_store; 23742 // Parse next levels and set value 23743 for (var i = 1; i < l - 2; i++) { 23744 vi = a[i]; 23745 type = isNaN(a[i+1])?"object":"array"; 23746 if (!tmp[vi] || type == "object" && !$.isPlainObject(tmp[vi]) || type=="array" && !$.isArray(tmp[vi])) { 23747 if(type=="array") tmp[vi] = []; 23748 else tmp[vi] = {}; 23749 } 23750 tmp = tmp[vi]; 23751 } 23752 tmp[a[i]] = a[i + 1]; 23753 s.setItem(a0, JSON.stringify(to_store)); 23754 return to_store; 23755 } 23756 } 23757 23758 // Remove items from a storage 23759 function _remove() { 23760 var storage = this._type, l = arguments.length, s = window[storage], a = arguments, a0 = a[0], to_store, tmp; 23761 if (l < 1) { 23762 throw new Error('Minimum 1 argument must be given'); 23763 } else if ($.isArray(a0)) { 23764 // If first argument is an array, remove values from storage for each item of this array 23765 for (var i in a0) { 23766 s.removeItem(a0[i]); 23767 } 23768 return true; 23769 } else if (l == 1) { 23770 // If only 2 arguments, remove value from storage directly 23771 s.removeItem(a0); 23772 return true; 23773 } else { 23774 // If more than 2 arguments, parse storage to retrieve final node and remove value 23775 // Get first level 23776 try { 23777 to_store = tmp = JSON.parse(s.getItem(a0)); 23778 } catch (e) { 23779 throw new ReferenceError(a0 + ' is not defined in this storage'); 23780 } 23781 // Parse next levels and remove value 23782 for (var i = 1; i < l - 1; i++) { 23783 tmp = tmp[a[i]]; 23784 if (tmp === undefined) { 23785 throw new ReferenceError([].slice.call(a, 1, i).join('.') + ' is not defined in this storage'); 23786 } 23787 } 23788 // If last argument is an array,remove value for each item in this array 23789 // Else remove value normally 23790 if ($.isArray(a[i])) { 23791 for (var j in a[i]) { 23792 delete tmp[a[i][j]]; 23793 } 23794 } else { 23795 delete tmp[a[i]]; 23796 } 23797 s.setItem(a0, JSON.stringify(to_store)); 23798 return true; 23799 } 23800 } 23801 23802 // Remove all items from a storage 23803 function _removeAll(reinit_ns) { 23804 var keys = _keys.call(this); 23805 for (var i in keys) { 23806 _remove.call(this, keys[i]); 23807 } 23808 // Reinitialize all namespace storages 23809 if (reinit_ns) { 23810 for (var i in $.namespaceStorages) { 23811 _createNamespace(i); 23812 } 23813 } 23814 } 23815 23816 // Check if items of a storage are empty 23817 function _isEmpty() { 23818 var l = arguments.length, a = arguments, a0 = a[0]; 23819 if (l == 0) { 23820 // If no argument, test if storage is empty 23821 return (_keys.call(this).length == 0); 23822 } else if ($.isArray(a0)) { 23823 // If first argument is an array, test each item of this array and return true only if all items are empty 23824 for (var i = 0; i < a0.length; i++) { 23825 if (!_isEmpty.call(this, a0[i])) { 23826 return false;
23827 } 23828 } 23829 return true; 23830 } else { 23831 // If at least 1 argument, try to get value and test it 23832 try { 23833 var v = _get.apply(this, arguments); 23834 // Convert result to an object (if last argument is an array, _get return already an object) and test each item 23835 if (!$.isArray(a[l - 1])) { 23836 v = {'totest': v}; 23837 } 23838 for (var i in v) { 23839 if (!( 23840 ($.isPlainObject(v[i]) && $.isEmptyObject(v[i])) || 23841 ($.isArray(v[i]) && !v[i].length) || 23842 (!v[i]) 23843 )) { 23844 return false; 23845 } 23846 } 23847 return true; 23848 } catch (e) { 23849 return true; 23850 } 23851 } 23852 } 23853 23854 // Check if items of a storage exist 23855 function _isSet() { 23856 var l = arguments.length, a = arguments, a0 = a[0]; 23857 if (l < 1) { 23858 throw new Error('Minimum 1 argument must be given'); 23859 } 23860 if ($.isArray(a0)) { 23861 // If first argument is an array, test each item of this array and return true only if all items exist 23862 for (var i = 0; i < a0.length; i++) { 23863 if (!_isSet.call(this, a0[i])) { 23864 return false; 23865 } 23866 } 23867 return true; 23868 } else { 23869 // For other case, try to get value and test it 23870 try { 23871 var v = _get.apply(this, arguments); 23872 // Convert result to an object (if last argument is an array, _get return already an object) and test each item 23873 if (!$.isArray(a[l - 1])) { 23874 v = {'totest': v}; 23875 } 23876 for (var i in v) { 23877 if (!(v[i] !== undefined && v[i] !== null)) { 23878 return false; 23879 } 23880 } 23881 return true; 23882 } catch (e) { 23883 return false; 23884 } 23885 } 23886 } 23887 23888 // Get keys of a storage or of an item of the storage 23889 function _keys() { 23890 var storage = this._type, l = arguments.length, s = window[storage], a = arguments, keys = [], o = {}; 23891 // If at least 1 argument, get value from storage to retrieve keys 23892 // Else, use storage to retrieve keys 23893 if (l > 0) { 23894 o = _get.apply(this, a); 23895 } else { 23896 o = s; 23897 } 23898 if (o && o._cookie) { 23899 // If storage is a cookie, use js-cookie to retrieve keys 23900 for (var key in Cookies.get()) { 23901 if (key != '') { 23902 keys.push(key.replace(o._prefix, '')); 23903 } 23904 } 23905 } else { 23906 for (var i in o) { 23907 if (o.hasOwnProperty(i)) { 23908 keys.push(i); 23909 } 23910 } 23911 } 23912 return keys; 23913 } 23914 23915 // Create new namespace storage 23916 function _createNamespace(name) { 23917 if (!name || typeof name != "string") { 23918 throw new Error('First parameter must be a string'); 23919 } 23920 if (storage_available) { 23921 if (!window.localStorage.getItem(name)) { 23922 window.localStorage.setItem(name, '{}'); 23923 } 23924 if (!window.sessionStorage.getItem(name)) { 23925 window.sessionStorage.setItem(name, '{}'); 23926 } 23927 } else { 23928 if (!window.localCookieStorage.getItem(name)) { 23929 window.localCookieStorage.setItem(name, '{}'); 23930 } 23931 if (!window.sessionCookieStorage.getItem(name)) { 23932 window.sessionCookieStorage.setItem(name, '{}'); 23933 } 23934 } 23935 var ns = { 23936 localStorage: $.extend({}, $.localStorage, {_ns: name}), 23937 sessionStorage: $.extend({}, $.sessionStorage, {_ns: name}) 23938 }; 23939 if (typeof Cookies === 'object') { 23940 if (!window.cookieStorage.getItem(name)) { 23941 window.cookieStorage.setItem(name, '{}'); 23942 } 23943 ns.cookieStorage = $.extend({}, $.cookieStorage, {_ns: name}); 23944 } 23945 $.namespaceStorages[name] = ns; 23946 return ns; 23947 } 23948 23949 // Test if storage is natively available on browser 23950 function _testStorage(name) { 23951 var foo = 'jsapi'; 23952 try { 23953 if (!window[name]) { 23954 return false;
23955 } 23956 window[name].setItem(foo, foo); 23957 window[name].removeItem(foo); 23958 return true; 23959 } catch (e) { 23960 return false; 23961 } 23962 } 23963 23964 // Check if storages are natively available on browser 23965 var storage_available = _testStorage('localStorage'); 23966 23967 // Namespace object 23968 var storage = { 23969 _type: '', 23970 _ns: '', 23971 _callMethod: function (f, a) { 23972 var p = [], a = Array.prototype.slice.call(a), a0 = a[0]; 23973 23974 if (this._ns) { 23975 p.push(this._ns); 23976 } 23977 if (typeof a0 === 'string' && a0.indexOf('.') !== -1) { 23978 a.shift(); 23979 [].unshift.apply(a, a0.split('.')); 23980 } 23981 [].push.apply(p, a); 23982 return f.apply(this, p); 23983 }, 23984 // Define if plugin always use JSON to store values (even to store simple values like string, int...) or not 23985 alwaysUseJson: false, 23986 // Get items. If no parameters and storage have a namespace, return all namespace 23987 get: function () { 23988 return this._callMethod(_get, arguments); 23989 }, 23990 // Set items 23991 set: function () { 23992 var l = arguments.length, a = arguments, a0 = a[0]; 23993 if (l < 1 || !$.isPlainObject(a0) && l < 2) { 23994 throw new Error('Minimum 2 arguments must be given or first parameter must be an object'); 23995 } 23996 // If first argument is an object and storage is a namespace storage, set values individually 23997 if ($.isPlainObject(a0) && this._ns) { 23998 for (var i in a0) { 23999 this._callMethod(_set, [i, a0[i]]); 24000 } 24001 return a0; 24002 } else { 24003 var r = this._callMethod(_set, a); 24004 if (this._ns) { 24005 return r[a0.split('.')[0]]; 24006 } else { 24007 return r; 24008 } 24009 } 24010 }, 24011 // Delete items 24012 remove: function () { 24013 if (arguments.length < 1) { 24014 throw new Error('Minimum 1 argument must be given'); 24015 } 24016 return this._callMethod(_remove, arguments); 24017 }, 24018 // Delete all items 24019 removeAll: function (reinit_ns) { 24020 if (this._ns) { 24021 this._callMethod(_set, [{}]); 24022 return true; 24023 } else { 24024 return this._callMethod(_removeAll, [reinit_ns]); 24025 } 24026 }, 24027 // Items empty 24028 isEmpty: function () { 24029 return this._callMethod(_isEmpty, arguments); 24030 }, 24031 // Items exists 24032 isSet: function () { 24033 if (arguments.length < 1) { 24034 throw new Error('Minimum 1 argument must be given'); 24035 } 24036 return this._callMethod(_isSet, arguments); 24037 }, 24038 // Get keys of items 24039 keys: function () { 24040 return this._callMethod(_keys, arguments); 24041 } 24042 }; 24043 24044 // Use js-cookie for compatibility with old browsers and give access to cookieStorage 24045 if (typeof Cookies === 'object') { 24046 // sessionStorage is valid for one window/tab. To simulate that with cookie, we set a name for the window and use it for the name of the cookie 24047 if (!window.name) { 24048 window.name = Math.floor(Math.random() * 100000000); 24049 } 24050 var cookie_storage = { 24051 _cookie: true, 24052 _prefix: '', 24053 _expires: null, 24054 _path: null, 24055 _domain: null, 24056 setItem: function (n, v) { 24057 Cookies.set(this._prefix + n, v, {expires: this._expires, path: this._path, domain: this._domain}); 24058 }, 24059 getItem: function (n) { 24060 return Cookies.get(this._prefix + n); 24061 }, 24062 removeItem: function (n) { 24063 return Cookies.remove(this._prefix + n, {path: this._path}); 24064 }, 24065 clear: function () { 24066 for (var key in Cookies.get()) { 24067 if (key != '') { 24068 if (!this._prefix && key.indexOf(cookie_local_prefix) === -1 && key.indexOf(cookie_session_prefix) === -1 || this._prefix && key.indexOf(this._prefix) === 0) { 24069 $.removeCookie(key); 24070 } 24071 } 24072 } 24073 }, 24074 setExpires: function (e) { 24075 this._expires = e; 24076 return this; 24077 }, 24078 setPath: function (p) { 24079 this._path = p; 24080 return this; 24081 }, 24082 setDomain: function (d) { 24083 this._domain = d; 24084 return this; 24085 }, 24086 setConf: function (c) { 24087 if (c.path) { 24088 this._path = c.path; 24089 } 24090 if (c.domain) { 24091 this._domain = c.domain; 24092 } 24093 if (c.expires) { 24094 this._expires = c.expires; 24095 } 24096 return this; 24097 }, 24098 setDefaultConf: function () { 24099 this._path = this._domain = this._expires = null; 24100 } 24101 }; 24102 if (!storage_available) { 24103 window.localCookieStorage = $.extend({}, cookie_storage, { 24104 _prefix: cookie_local_prefix, 24105 _expires: 365 * 10 24106 }); 24107 window.sessionCookieStorage = $.extend({}, cookie_storage, {_prefix: cookie_session_prefix + window.name + '_'}); 24108 } 24109 window.cookieStorage = $.extend({}, cookie_storage); 24110 // cookieStorage API 24111 $.cookieStorage = $.extend({}, storage, { 24112 _type: 'cookieStorage', 24113 setExpires: function (e) { 24114 window.cookieStorage.setExpires(e); 24115 return this; 24116 }, 24117 setPath: function (p) { 24118 window.cookieStorage.setPath(p); 24119 return this; 24120 }, 24121 setDomain: function (d) { 24122 window.cookieStorage.setDomain(d); 24123 return this; 24124 }, 24125 setConf: function (c) { 24126 window.cookieStorage.setConf(c); 24127 return this; 24128 }, 24129 setDefaultConf: function () { 24130 window.cookieStorage.setDefaultConf(); 24131 return this; 24132 } 24133 }); 24134 } 24135 24136 // Get a new API on a namespace 24137 $.initNamespaceStorage = function (ns) { 24138 return _createNamespace(ns); 24139 }; 24140 if (storage_available) { 24141 // About alwaysUseJson 24142 // By default, all values are string on html storages and the plugin don't use json to store simple values (strings, int, float...) 24143 // So by default, if you do storage.setItem('test',2), value in storage will be "2", not 2 24144 // If you set this property to true, all values set with the plugin will be stored as json to have typed values in any cases 24145 24146 // localStorage API 24147 $.localStorage = $.extend({}, storage, {_type: 'localStorage'}); 24148 // sessionStorage API 24149 $.sessionStorage = $.extend({}, storage, {_type: 'sessionStorage'}); 24150 } else { 24151 // localStorage API 24152 $.localStorage = $.extend({}, storage, {_type: 'localCookieStorage'}); 24153 // sessionStorage API 24154 $.sessionStorage = $.extend({}, storage, {_type: 'sessionCookieStorage'}); 24155 } 24156 // List of all namespace storage 24157 $.namespaceStorages = {}; 24158 // Remove all items in all storages 24159 $.removeAllStorages = function (reinit_ns) { 24160 $.localStorage.removeAll(reinit_ns); 24161 $.sessionStorage.removeAll(reinit_ns); 24162 if ($.cookieStorage) { 24163 $.cookieStorage.removeAll(reinit_ns); 24164 } 24165 if (!reinit_ns) { 24166 $.namespaceStorages = {}; 24167 } 24168 } 24169 $.alwaysUseJsonInStorage = function (value) { 24170 storage.alwaysUseJson = value; 24171 $.localStorage.alwaysUseJson = value; 24172 $.sessionStorage.alwaysUseJson = value; 24173 if ($.cookieStorage) { 24174 $.cookieStorage.alwaysUseJson = value; 24175 } 24176 } 24177})); 24178 24179/*! 24180 * imagesLoaded v4.1.0 24181 * JavaScript is all like "You images are done yet or what?" 24182 * MIT License 24183 */ 24184 24185( function( window, factory ) { 'use strict'; 24186 // universal module definition 24187 24188 /*global define: false, module: false, require: false */ 24189 24190 if ( typeof define == 'function' && define.amd ) { 24191 // AMD 24192 define( [ 24193 'ev-emitter/ev-emitter' 24194 ], function( EvEmitter ) { 24195 return factory( window, EvEmitter ); 24196 }); 24197 } else if ( typeof module == 'object' && module.exports ) { 24198 // CommonJS 24199 module.exports = factory( 24200 window, 24201 require('ev-emitter') 24202 ); 24203 } else { 24204 // browser global 24205 window.imagesLoaded = factory( 24206 window, 24207 window.EvEmitter 24208 ); 24209 } 24210 24211})( window, 24212 24213// -------------------------- factory -------------------------- // 24214 24215function factory( window, EvEmitter ) { 24216 24217'use strict'; 24218 24219var $ = window.jQuery; 24220var console = window.console; 24221 24222// -------------------------- helpers -------------------------- // 24223 24224// extend objects 24225function extend( a, b ) { 24226 for ( var prop in b ) { 24227 a[ prop ] = b[ prop ]; 24228 } 24229 return a; 24230} 24231 24232// turn element or nodeList into an array 24233function makeArray( obj ) { 24234 var ary = []; 24235 if ( Array.isArray( obj ) ) { 24236 // use object if already an array 24237 ary = obj; 24238 } else if ( typeof obj.length == 'number' ) { 24239 // convert nodeList to array 24240 for ( var i=0; i < obj.length; i++ ) { 24241 ary.push( obj[i] ); 24242 } 24243 } else { 24244 // array of single index 24245 ary.push( obj ); 24246 } 24247 return ary; 24248} 24249 24250// -------------------------- imagesLoaded -------------------------- // 24251 24252/** 24253 * @param {Array, Element, NodeList, String} elem 24254 * @param {Object or Function} options - if function, use as callback 24255 * @param {Function} onAlways - callback function 24256 */ 24257function ImagesLoaded( elem, options, onAlways ) { 24258 // coerce ImagesLoaded() without new, to be new ImagesLoaded() 24259 if ( !( this instanceof ImagesLoaded ) ) { 24260 return new ImagesLoaded( elem, options, onAlways ); 24261 } 24262 // use elem as selector string 24263 if ( typeof elem == 'string' ) { 24264 elem = document.querySelectorAll( elem ); 24265 } 24266 24267 this.elements = makeArray( elem ); 24268 this.options = extend( {}, this.options ); 24269 24270 if ( typeof options == 'function' ) { 24271 onAlways = options; 24272 } else { 24273 extend( this.options, options ); 24274 } 24275 24276 if ( onAlways ) { 24277 this.on( 'always', onAlways ); 24278 } 24279 24280 this.getImages(); 24281 24282 if ( $ ) { 24283 // add jQuery Deferred object 24284 this.jqDeferred = new $.Deferred(); 24285 } 24286 24287 // HACK check async to allow time to bind listeners 24288 setTimeout( function() { 24289 this.check(); 24290 }.bind( this )); 24291} 24292 24293ImagesLoaded.prototype = Object.create( EvEmitter.prototype ); 24294 24295ImagesLoaded.prototype.options = {}; 24296 24297ImagesLoaded.prototype.getImages = function() { 24298 this.images = []; 24299 24300 // filter & find items if we have an item selector
vendor: 6,811 bytes, lines 24301-24549
24301 this.elements.forEach( this.addElementImages, this ); 24302}; 24303 24304/** 24305 * @param {Node} element 24306 */ 24307ImagesLoaded.prototype.addElementImages = function( elem ) { 24308 // filter siblings 24309 if ( elem.nodeName == 'IMG' ) { 24310 this.addImage( elem ); 24311 } 24312 // get background image on element 24313 if ( this.options.background === true ) { 24314 this.addElementBackgroundImages( elem ); 24315 } 24316 24317 // find children 24318 // no non-element nodes, #143 24319 var nodeType = elem.nodeType; 24320 if ( !nodeType || !elementNodeTypes[ nodeType ] ) { 24321 return; 24322 } 24323 var childImgs = elem.querySelectorAll('img'); 24324 // concat childElems to filterFound array 24325 for ( var i=0; i < childImgs.length; i++ ) { 24326 var img = childImgs[i]; 24327 this.addImage( img ); 24328 } 24329 24330 // get child background images 24331 if ( typeof this.options.background == 'string' ) { 24332 var children = elem.querySelectorAll( this.options.background ); 24333 for ( i=0; i < children.length; i++ ) { 24334 var child = children[i]; 24335 this.addElementBackgroundImages( child ); 24336 } 24337 } 24338}; 24339 24340var elementNodeTypes = { 24341 1: true, 24342 9: true, 24343 11: true 24344}; 24345 24346ImagesLoaded.prototype.addElementBackgroundImages = function( elem ) { 24347 var style = getComputedStyle( elem ); 24348 if ( !style ) { 24349 // Firefox returns null if in a hidden iframe https://bugzil.la/548397 24350 return; 24351 } 24352 // get url inside url("...") 24353 var reURL = /url\((['"])?(.*?)\1\)/gi; 24354 var matches = reURL.exec( style.backgroundImage ); 24355 while ( matches !== null ) { 24356 var url = matches && matches[2]; 24357 if ( url ) { 24358 this.addBackground( url, elem ); 24359 } 24360 matches = reURL.exec( style.backgroundImage ); 24361 } 24362}; 24363 24364/** 24365 * @param {Image} img 24366 */ 24367ImagesLoaded.prototype.addImage = function( img ) { 24368 var loadingImage = new LoadingImage( img ); 24369 this.images.push( loadingImage ); 24370}; 24371 24372ImagesLoaded.prototype.addBackground = function( url, elem ) { 24373 var background = new Background( url, elem ); 24374 this.images.push( background ); 24375}; 24376 24377ImagesLoaded.prototype.check = function() { 24378 var _this = this; 24379 this.progressedCount = 0; 24380 this.hasAnyBroken = false; 24381 // complete if no images 24382 if ( !this.images.length ) { 24383 this.complete(); 24384 return; 24385 } 24386 24387 function onProgress( image, elem, message ) { 24388 // HACK - Chrome triggers event before object properties have changed. #83 24389 setTimeout( function() { 24390 _this.progress( image, elem, message ); 24391 }); 24392 } 24393 24394 this.images.forEach( function( loadingImage ) { 24395 loadingImage.once( 'progress', onProgress ); 24396 loadingImage.check(); 24397 }); 24398}; 24399 24400ImagesLoaded.prototype.progress = function( image, elem, message ) { 24401 this.progressedCount++; 24402 this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded; 24403 // progress event 24404 this.emitEvent( 'progress', [ this, image, elem ] ); 24405 if ( this.jqDeferred && this.jqDeferred.notify ) { 24406 this.jqDeferred.notify( this, image ); 24407 } 24408 // check if completed 24409 if ( this.progressedCount == this.images.length ) { 24410 this.complete(); 24411 } 24412 24413 if ( this.options.debug && console ) { 24414 console.log( 'progress: ' + message, image, elem ); 24415 } 24416}; 24417 24418ImagesLoaded.prototype.complete = function() { 24419 var eventName = this.hasAnyBroken ? 'fail' : 'done'; 24420 this.isComplete = true; 24421 this.emitEvent( eventName, [ this ] ); 24422 this.emitEvent( 'always', [ this ] ); 24423 if ( this.jqDeferred ) { 24424 var jqMethod = this.hasAnyBroken ? 'reject' : 'resolve'; 24425 this.jqDeferred[ jqMethod ]( this ); 24426 } 24427}; 24428 24429// -------------------------- -------------------------- // 24430 24431function LoadingImage( img ) { 24432 this.img = img; 24433} 24434 24435LoadingImage.prototype = Object.create( EvEmitter.prototype ); 24436 24437LoadingImage.prototype.check = function() { 24438 // If complete is true and browser supports natural sizes, 24439 // try to check for image status manually. 24440 var isComplete = this.getIsImageComplete(); 24441 if ( isComplete ) { 24442 // report based on naturalWidth 24443 this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' ); 24444 return; 24445 } 24446 24447 // If none of the checks above matched, simulate loading on detached element. 24448 this.proxyImage = new Image(); 24449 this.proxyImage.addEventListener( 'load', this ); 24450 this.proxyImage.addEventListener( 'error', this ); 24451 // bind to image as well for Firefox. #191 24452 this.img.addEventListener( 'load', this ); 24453 this.img.addEventListener( 'error', this ); 24454 this.proxyImage.src = this.img.src; 24455}; 24456 24457LoadingImage.prototype.getIsImageComplete = function() { 24458 return this.img.complete && this.img.naturalWidth !== undefined; 24459}; 24460 24461LoadingImage.prototype.confirm = function( isLoaded, message ) { 24462 this.isLoaded = isLoaded; 24463 this.emitEvent( 'progress', [ this, this.img, message ] ); 24464}; 24465 24466// ----- events ----- // 24467 24468// trigger specified handler for event type 24469LoadingImage.prototype.handleEvent = function( event ) { 24470 var method = 'on' + event.type; 24471 if ( this[ method ] ) { 24472 this[ method ]( event ); 24473 } 24474}; 24475 24476LoadingImage.prototype.onload = function() { 24477 this.confirm( true, 'onload' ); 24478 this.unbindEvents(); 24479}; 24480 24481LoadingImage.prototype.onerror = function() { 24482 this.confirm( false, 'onerror' ); 24483 this.unbindEvents(); 24484}; 24485 24486LoadingImage.prototype.unbindEvents = function() { 24487 this.proxyImage.removeEventListener( 'load', this ); 24488 this.proxyImage.removeEventListener( 'error', this ); 24489 this.img.removeEventListener( 'load', this ); 24490 this.img.removeEventListener( 'error', this ); 24491}; 24492 24493// -------------------------- Background -------------------------- // 24494 24495function Background( url, element ) { 24496 this.url = url; 24497 this.element = element; 24498 this.img = new Image(); 24499} 24500 24501// inherit LoadingImage prototype 24502Background.prototype = Object.create( LoadingImage.prototype ); 24503 24504Background.prototype.check = function() { 24505 this.img.addEventListener( 'load', this ); 24506 this.img.addEventListener( 'error', this ); 24507 this.img.src = this.url; 24508 // check if image is already complete 24509 var isComplete = this.getIsImageComplete(); 24510 if ( isComplete ) { 24511 this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' ); 24512 this.unbindEvents(); 24513 } 24514}; 24515 24516Background.prototype.unbindEvents = function() { 24517 this.img.removeEventListener( 'load', this ); 24518 this.img.removeEventListener( 'error', this ); 24519}; 24520 24521Background.prototype.confirm = function( isLoaded, message ) { 24522 this.isLoaded = isLoaded; 24523 this.emitEvent( 'progress', [ this, this.element, message ] ); 24524}; 24525 24526// -------------------------- jQuery -------------------------- // 24527 24528ImagesLoaded.makeJQueryPlugin = function( jQuery ) { 24529 jQuery = jQuery || window.jQuery; 24530 if ( !jQuery ) { 24531 return; 24532 } 24533 // set local variable 24534 $ = jQuery; 24535 // $().imagesLoaded() 24536 $.fn.imagesLoaded = function( options, callback ) { 24537 var instance = new ImagesLoaded( this, options, callback ); 24538 return instance.jqDeferred.promise( $(this) ); 24539 }; 24540}; 24541// try making plugin 24542ImagesLoaded.makeJQueryPlugin(); 24543 24544// -------------------------- -------------------------- // 24545 24546return ImagesLoaded; 24547 24548}); 24549
vendor: 44,277 bytes, lines 24550-26381
24550/*! 24551 * fancyBox - jQuery Plugin 24552 * version: 2.1.5 (Fri, 14 Jun 2013) 24553 * requires jQuery v1.6 or later 24554 * 24555 * Examples at http://fancyapps.com/fancybox/ 24556 * License: www.fancyapps.com/fancybox/#license 24557 * 24558 * Copyright 2012 Janis Skarnelis - [email protected] 24559 * 24560 */ 24561 24562;(function (window, document, $, undefined) { 24563 "use strict"; 24564 24565 var H = $("html"), 24566 W = $(window), 24567 D = $(document), 24568 F = $.fancybox = function () { 24569 F.open.apply( this, arguments ); 24570 }, 24571 IE = navigator.userAgent.match(/msie/i), 24572 didUpdate = null, 24573 isTouch = document.createTouch !== undefined, 24574 24575 isQuery = function(obj) { 24576 return obj && obj.hasOwnProperty && obj instanceof $; 24577 }, 24578 isString = function(str) { 24579 return str && $.type(str) === "string"; 24580 }, 24581 isPercentage = function(str) { 24582 return isString(str) && str.indexOf('%') > 0; 24583 }, 24584 isScrollable = function(el) { 24585 return (el && !(el.style.overflow && el.style.overflow === 'hidden') && ((el.clientWidth && el.scrollWidth > el.clientWidth) || (el.clientHeight && el.scrollHeight > el.clientHeight))); 24586 }, 24587 getScalar = function(orig, dim) { 24588 var value = parseInt(orig, 10) || 0; 24589 24590 if (dim && isPercentage(orig)) { 24591 value = F.getViewport()[ dim ] / 100 * value; 24592 } 24593 24594 return Math.ceil(value); 24595 }, 24596 getValue = function(value, dim) { 24597 return getScalar(value, dim) + 'px'; 24598 }; 24599 24600 $.extend(F, { 24601 // The current version of fancyBox 24602 version: '2.1.5', 24603 24604 defaults: { 24605 padding : 15, 24606 margin : 20, 24607 24608 width : 800, 24609 height : 600, 24610 minWidth : 100, 24611 minHeight : 100, 24612 maxWidth : 9999, 24613 maxHeight : 9999, 24614 pixelRatio: 1, // Set to 2 for retina display support 24615 24616 autoSize : true, 24617 autoHeight : false, 24618 autoWidth : false, 24619 24620 autoResize : true, 24621 autoCenter : !isTouch, 24622 fitToView : true, 24623 aspectRatio : false, 24624 topRatio : 0.5, 24625 leftRatio : 0.5, 24626 24627 scrolling : 'auto', // 'auto', 'yes' or 'no' 24628 wrapCSS : '', 24629 24630 arrows : true, 24631 closeBtn : true, 24632 closeClick : false, 24633 nextClick : false, 24634 mouseWheel : true, 24635 autoPlay : false, 24636 playSpeed : 3000, 24637 preload : 3, 24638 modal : false, 24639 loop : true, 24640 24641 ajax : { 24642 dataType : 'html', 24643 headers : { 'X-fancyBox': true } 24644 }, 24645 iframe : { 24646 scrolling : 'auto', 24647 preload : true 24648 }, 24649 swf : { 24650 wmode: 'transparent', 24651 allowfullscreen : 'true', 24652 allowscriptaccess : 'always' 24653 }, 24654 24655 keys : { 24656 next : { 24657 13 : 'left', // enter 24658 34 : 'up', // page down 24659 39 : 'left', // right arrow 24660 40 : 'up' // down arrow 24661 }, 24662 prev : { 24663 8 : 'right', // backspace 24664 33 : 'down', // page up 24665 37 : 'right', // left arrow 24666 38 : 'down' // up arrow 24667 }, 24668 close : [27], // escape key 24669 play : [32], // space - start/stop slideshow 24670 toggle : [70] // letter "f" - toggle fullscreen 24671 }, 24672 24673 direction : { 24674 next : 'left', 24675 prev : 'right' 24676 }, 24677 24678 scrollOutside : true, 24679 24680 // Override some properties 24681 index : 0, 24682 type : null, 24683 href : null, 24684 content : null, 24685 title : null, 24686 24687 // HTML templates 24688 tpl: { 24689 wrap : '<div class="fancybox-wrap" tabIndex="-1"><div class="fancybox-skin"><div class="fancybox-outer"><div class="fancybox-inner"></div></div></div></div>', 24690 image : '<img class="fancybox-image" src="{href}" alt="" />', 24691 iframe : '<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" frameborder="0" vspace="0" hspace="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen' + (IE ? ' allowtransparency="true"' : '') + '></iframe>', 24692 error : '<p class="fancybox-error">The requested content cannot be loaded.<br/>Please try again later.</p>', 24693 closeBtn : '<a title="Close" class="fancybox-item fancybox-close" href="javascript:;"></a>', 24694 next : '<a title="Next" class="fancybox-nav fancybox-next" href="javascript:;"><span></span></a>', 24695 prev : '<a title="Previous" class="fancybox-nav fancybox-prev" href="javascript:;"><span></span></a>', 24696 loading : '<div id="fancybox-loading"><div></div></div>' 24697 }, 24698 24699 // Properties for each animation type 24700 // Opening fancyBox 24701 openEffect : 'fade', // 'elastic', 'fade' or 'none' 24702 openSpeed : 250, 24703 openEasing : 'swing', 24704 openOpacity : true, 24705 openMethod : 'zoomIn', 24706 24707 // Closing fancyBox 24708 closeEffect : 'fade', // 'elastic', 'fade' or 'none' 24709 closeSpeed : 250, 24710 closeEasing : 'swing', 24711 closeOpacity : true, 24712 closeMethod : 'zoomOut', 24713 24714 // Changing next gallery item 24715 nextEffect : 'elastic', // 'elastic', 'fade' or 'none' 24716 nextSpeed : 250, 24717 nextEasing : 'swing', 24718 nextMethod : 'changeIn', 24719 24720 // Changing previous gallery item 24721 prevEffect : 'elastic', // 'elastic', 'fade' or 'none' 24722 prevSpeed : 250, 24723 prevEasing : 'swing', 24724 prevMethod : 'changeOut', 24725 24726 // Enable default helpers 24727 helpers : { 24728 overlay : true, 24729 title : true 24730 }, 24731 24732 // Callbacks 24733 onCancel : $.noop, // If canceling 24734 beforeLoad : $.noop, // Before loading 24735 afterLoad : $.noop, // After loading 24736 beforeShow : $.noop, // Before changing in current item 24737 afterShow : $.noop, // After opening 24738 beforeChange : $.noop, // Before changing gallery item 24739 beforeClose : $.noop, // Before closing 24740 afterClose : $.noop // After closing 24741 }, 24742 24743 //Current state 24744 group : {}, // Selected group 24745 opts : {}, // Group options 24746 previous : null, // Previous element 24747 coming : null, // Element being loaded 24748 current : null, // Currently loaded element 24749 isActive : false, // Is activated 24750 isOpen : false, // Is currently open 24751 isOpened : false, // Have been fully opened at least once 24752 24753 wrap : null, 24754 skin : null, 24755 outer : null, 24756 inner : null, 24757 24758 player : { 24759 timer : null, 24760 isActive : false 24761 }, 24762 24763 // Loaders 24764 ajaxLoad : null, 24765 imgPreload : null, 24766 24767 // Some collections 24768 transitions : {}, 24769 helpers : {}, 24770 24771 /* 24772 * Static methods 24773 */ 24774 24775 open: function (group, opts) { 24776 if (!group) { 24777 return; 24778 } 24779 24780 if (!$.isPlainObject(opts)) { 24781 opts = {}; 24782 } 24783 24784 // Close if already active 24785 if (false === F.close(true)) { 24786 return; 24787 } 24788 24789 // Normalize group 24790 if (!$.isArray(group)) { 24791 group = isQuery(group) ? $(group).get() : [group]; 24792 } 24793 24794 // Recheck if the type of each element is `object` and set content type (image, ajax, etc) 24795 $.each(group, function(i, element) { 24796 var obj = {}, 24797 href, 24798 title, 24799 content, 24800 type, 24801 rez, 24802 hrefParts, 24803 selector; 24804 24805 if ($.type(element) === "object") { 24806 // Check if is DOM element 24807 if (element.nodeType) { 24808 element = $(element); 24809 } 24810 24811 if (isQuery(element)) { 24812 obj = { 24813 href : element.data('fancybox-href') || element.attr('href'), 24814 title : $('<div/>').text( element.data('fancybox-title') || element.attr('title') || '' ).html(), 24815 isDom : true, 24816 element : element 24817 }; 24818 24819 if ($.metadata) { 24820 $.extend(true, obj, element.metadata()); 24821 } 24822 24823 } else { 24824 obj = element; 24825 } 24826 } 24827 24828 href = opts.href || obj.href || (isString(element) ? element : null); 24829 title = opts.title !== undefined ? opts.title : obj.title || ''; 24830 24831 content = opts.content || obj.content; 24832 type = content ? 'html' : (opts.type || obj.type); 24833 24834 if (!type && obj.isDom) { 24835 type = element.data('fancybox-type'); 24836 24837 if (!type) { 24838 rez = element.prop('class').match(/fancybox\.(\w+)/); 24839 type = rez ? rez[1] : null; 24840 } 24841 } 24842 24843 if (isString(href)) { 24844 // Try to guess the content type 24845 if (!type) { 24846 if (F.isImage(href)) { 24847 type = 'image'; 24848 24849 } else if (F.isSWF(href)) { 24850 type = 'swf'; 24851 24852 } else if (href.charAt(0) === '#') { 24853 type = 'inline'; 24854 24855 } else if (isString(element)) { 24856 type = 'html'; 24857 content = element; 24858 } 24859 } 24860 24861 // Split url into two pieces with source url and content selector, e.g, 24862 // "/mypage.html #my_id" will load "/mypage.html" and display element having id "my_id" 24863 if (type === 'ajax') { 24864 hrefParts = href.split(/\s+/, 2); 24865 href = hrefParts.shift(); 24866 selector = hrefParts.shift(); 24867 } 24868 } 24869 24870 if (!content) { 24871 if (type === 'inline') { 24872 if (href) { 24873 content = $( isString(href) ? href.replace(/.*(?=#[^\s]+$)/, '') : href ); //strip for ie7 24874 24875 } else if (obj.isDom) { 24876 content = element; 24877 } 24878 24879 } else if (type === 'html') { 24880 content = href; 24881 24882 } else if (!type && !href && obj.isDom) { 24883 type = 'inline'; 24884 content = element; 24885 } 24886 } 24887 24888 $.extend(obj, { 24889 href : href, 24890 type : type, 24891 content : content, 24892 title : title, 24893 selector : selector 24894 }); 24895 24896 group[ i ] = obj; 24897 }); 24898 24899 // Extend the defaults 24900 F.opts = $.extend(true, {}, F.defaults, opts); 24901 24902 // All options are merged recursive except keys 24903 if (opts.keys !== undefined) { 24904 F.opts.keys = opts.keys ? $.extend({}, F.defaults.keys, opts.keys) : false; 24905 } 24906 24907 F.group = group; 24908 24909 return F._start(F.opts.index); 24910 }, 24911 24912 // Cancel image loading or abort ajax request 24913 cancel: function () { 24914 var coming = F.coming; 24915 24916 if (coming && false === F.trigger('onCancel')) { 24917 return; 24918 } 24919 24920 F.hideLoading(); 24921 24922 if (!coming) { 24923 return; 24924 } 24925 24926 if (F.ajaxLoad) { 24927 F.ajaxLoad.abort(); 24928 } 24929 24930 F.ajaxLoad = null; 24931 24932 if (F.imgPreload) { 24933 F.imgPreload.onload = F.imgPreload.onerror = null; 24934 } 24935 24936 if (coming.wrap) { 24937 coming.wrap.stop(true, true).trigger('onReset').remove(); 24938 } 24939 24940 F.coming = null; 24941 24942 // If the first item has been canceled, then clear everything 24943 if (!F.current) { 24944 F._afterZoomOut( coming ); 24945 } 24946 }, 24947 24948 // Start closing animation if is open; remove immediately if opening/closing 24949 close: function (event) { 24950 F.cancel(); 24951 24952 if (false === F.trigger('beforeClose')) { 24953 return; 24954 } 24955 24956 F.unbindEvents(); 24957 24958 if (!F.isActive) { 24959 return; 24960 } 24961 24962 if (!F.isOpen || event === true) { 24963 $('.fancybox-wrap').stop(true).trigger('onReset').remove(); 24964 24965 F._afterZoomOut(); 24966 24967 } else { 24968 F.isOpen = F.isOpened = false; 24969 F.isClosing = true; 24970 24971 $('.fancybox-item, .fancybox-nav').remove(); 24972 24973 F.wrap.stop(true, true).removeClass('fancybox-opened'); 24974 24975 F.transitions[ F.current.closeMethod ](); 24976 } 24977 }, 24978 24979 // Manage slideshow: 24980 // $.fancybox.play(); - toggle slideshow 24981 // $.fancybox.play( true ); - start 24982 // $.fancybox.play( false ); - stop 24983 play: function ( action ) { 24984 var clear = function () { 24985 clearTimeout(F.player.timer); 24986 }, 24987 set = function () { 24988 clear(); 24989 24990 if (F.current && F.player.isActive) { 24991 F.player.timer = setTimeout(F.next, F.current.playSpeed); 24992 } 24993 }, 24994 stop = function () { 24995 clear(); 24996 24997 D.unbind('.player'); 24998 24999 F.player.isActive = false; 25000 25001 F.trigger('onPlayEnd'); 25002 }, 25003 start = function () { 25004 if (F.current && (F.current.loop || F.current.index < F.group.length - 1)) { 25005 F.player.isActive = true; 25006 25007 D.bind({ 25008 'onCancel.player beforeClose.player' : stop, 25009 'onUpdate.player' : set, 25010 'beforeLoad.player' : clear 25011 }); 25012 25013 set(); 25014 25015 F.trigger('onPlayStart'); 25016 } 25017 }; 25018 25019 if (action === true || (!F.player.isActive && action !== false)) { 25020 start(); 25021 } else { 25022 stop(); 25023 } 25024 }, 25025 25026 // Navigate to next gallery item 25027 next: function ( direction ) { 25028 var current = F.current; 25029 25030 if (current) { 25031 if (!isString(direction)) { 25032 direction = current.direction.next; 25033 } 25034 25035 F.jumpto(current.index + 1, direction, 'next'); 25036 } 25037 }, 25038 25039 // Navigate to previous gallery item 25040 prev: function ( direction ) { 25041 var current = F.current; 25042 25043 if (current) { 25044 if (!isString(direction)) { 25045 direction = current.direction.prev; 25046 } 25047 25048 F.jumpto(current.index - 1, direction, 'prev'); 25049 } 25050 }, 25051 25052 // Navigate to gallery item by index 25053 jumpto: function ( index, direction, router ) { 25054 var current = F.current; 25055 25056 if (!current) { 25057 return; 25058 } 25059 25060 index = getScalar(index); 25061 25062 F.direction = direction || current.direction[ (index >= current.index ? 'next' : 'prev') ]; 25063 F.router = router || 'jumpto'; 25064 25065 if (current.loop) { 25066 if (index < 0) { 25067 index = current.group.length + (index % current.group.length); 25068 } 25069 25070 index = index % current.group.length; 25071 } 25072 25073 if (current.group[ index ] !== undefined) { 25074 F.cancel(); 25075 25076 F._start(index); 25077 } 25078 }, 25079 25080 // Center inside viewport and toggle position type to fixed or absolute if needed 25081 reposition: function (e, onlyAbsolute) { 25082 var current = F.current, 25083 wrap = current ? current.wrap : null, 25084 pos; 25085 25086 if (wrap) { 25087 pos = F._getPosition(onlyAbsolute); 25088 25089 if (e && e.type === 'scroll') { 25090 delete pos.position; 25091 25092 wrap.stop(true, true).animate(pos, 200); 25093 25094 } else { 25095 wrap.css(pos); 25096 25097 current.pos = $.extend({}, current.dim, pos); 25098 } 25099 } 25100 }, 25101 25102 update: function (e) { 25103 var type = (e && e.originalEvent && e.originalEvent.type), 25104 anyway = !type || type === 'orientationchange'; 25105 25106 if (anyway) { 25107 clearTimeout(didUpdate); 25108 25109 didUpdate = null; 25110 } 25111 25112 if (!F.isOpen || didUpdate) { 25113 return; 25114 } 25115 25116 didUpdate = setTimeout(function() { 25117 var current = F.current; 25118 25119 if (!current || F.isClosing) { 25120 return; 25121 } 25122 25123 F.wrap.removeClass('fancybox-tmp'); 25124 25125 if (anyway || type === 'load' || (type === 'resize' && current.autoResize)) { 25126 F._setDimension(); 25127 } 25128 25129 if (!(type === 'scroll' && current.canShrink)) { 25130 F.reposition(e); 25131 } 25132 25133 F.trigger('onUpdate'); 25134 25135 didUpdate = null; 25136 25137 }, (anyway && !isTouch ? 0 : 300)); 25138 }, 25139 25140 // Shrink content to fit inside viewport or restore if resized 25141 toggle: function ( action ) { 25142 if (F.isOpen) { 25143 F.current.fitToView = $.type(action) === "boolean" ? action : !F.current.fitToView; 25144 25145 // Help browser to restore document dimensions 25146 if (isTouch) { 25147 F.wrap.removeAttr('style').addClass('fancybox-tmp'); 25148 25149 F.trigger('onUpdate'); 25150 } 25151 25152 F.update(); 25153 } 25154 }, 25155 25156 hideLoading: function () { 25157 D.unbind('.loading'); 25158 25159 $('#fancybox-loading').remove(); 25160 }, 25161 25162 showLoading: function () { 25163 var el, viewport; 25164 25165 F.hideLoading(); 25166 25167 el = $(F.opts.tpl.loading).click(F.cancel).appendTo('body'); 25168 25169 // If user will press the escape-button, the request will be canceled 25170 D.bind('keydown.loading', function(e) { 25171 if ((e.which || e.keyCode) === 27) { 25172 e.preventDefault(); 25173 25174 F.cancel(); 25175 } 25176 }); 25177 25178 if (!F.defaults.fixed) { 25179 viewport = F.getViewport(); 25180 25181 el.css({ 25182 position : 'absolute', 25183 top : (viewport.h * 0.5) + viewport.y, 25184 left : (viewport.w * 0.5) + viewport.x 25185 }); 25186 } 25187 25188 F.trigger('onLoading'); 25189 }, 25190 25191 getViewport: function () { 25192 var locked = (F.current && F.current.locked) || false, 25193 rez = { 25194 x: W.scrollLeft(), 25195 y: W.scrollTop() 25196 }; 25197 25198 if (locked && locked.length) { 25199 rez.w = locked[0].clientWidth; 25200 rez.h = locked[0].clientHeight; 25201 25202 } else { 25203 // See http://bugs.jquery.com/ticket/6724 25204 rez.w = isTouch && window.innerWidth ? window.innerWidth : W.width(); 25205 rez.h = isTouch && window.innerHeight ? window.innerHeight : W.height(); 25206 } 25207 25208 return rez; 25209 }, 25210 25211 // Unbind the keyboard / clicking actions 25212 unbindEvents: function () { 25213 if (F.wrap && isQuery(F.wrap)) { 25214 F.wrap.unbind('.fb'); 25215 } 25216 25217 D.unbind('.fb'); 25218 W.unbind('.fb'); 25219 }, 25220 25221 bindEvents: function () { 25222 var current = F.current, 25223 keys; 25224 25225 if (!current) { 25226 return; 25227 } 25228 25229 // Changing document height on iOS devices triggers a 'resize' event, 25230 // that can change document height... repeating infinitely 25231 W.bind('orientationchange.fb' + (isTouch ? '' : ' resize.fb') + (current.autoCenter && !current.locked ? ' scroll.fb' : ''), F.update); 25232 25233 keys = current.keys; 25234 25235 if (keys) { 25236 D.bind('keydown.fb', function (e) { 25237 var code = e.which || e.keyCode, 25238 target = e.target || e.srcElement; 25239 25240 // Skip esc key if loading, because showLoading will cancel preloading 25241 if (code === 27 && F.coming) { 25242 return false; 25243 } 25244 25245 // Ignore key combinations and key events within form elements 25246 if (!e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey && !(target && (target.type || $(target).is('[contenteditable]')))) { 25247 $.each(keys, function(i, val) { 25248 if (current.group.length > 1 && val[ code ] !== undefined) { 25249 F[ i ]( val[ code ] ); 25250 25251 e.preventDefault(); 25252 return false; 25253 } 25254 25255 if ($.inArray(code, val) > -1) { 25256 F[ i ] (); 25257 25258 e.preventDefault(); 25259 return false; 25260 } 25261 }); 25262 } 25263 }); 25264 } 25265 25266 if ($.fn.mousewheel && current.mouseWheel) { 25267 F.wrap.bind('mousewheel.fb', function (e, delta, deltaX, deltaY) { 25268 var target = e.target || null, 25269 parent = $(target), 25270 canScroll = false; 25271 25272 while (parent.length) { 25273 if (canScroll || parent.is('.fancybox-skin') || parent.is('.fancybox-wrap')) { 25274 break; 25275 } 25276 25277 canScroll = isScrollable( parent[0] ); 25278 parent = $(parent).parent(); 25279 } 25280 25281 if (delta !== 0 && !canScroll) { 25282 if (F.group.length > 1 && !current.canShrink) { 25283 if (deltaY > 0 || deltaX > 0) { 25284 F.prev( deltaY > 0 ? 'down' : 'left' ); 25285 25286 } else if (deltaY < 0 || deltaX < 0) { 25287 F.next( deltaY < 0 ? 'up' : 'right' ); 25288 } 25289 25290 e.preventDefault(); 25291 } 25292 } 25293 }); 25294 } 25295 }, 25296 25297 trigger: function (event, o) { 25298 var ret, obj = o || F.coming || F.current; 25299 25300 if (obj) { 25301 if ($.isFunction( obj[event] )) { 25302 ret = obj[event].apply(obj, Array.prototype.slice.call(arguments, 1)); 25303 } 25304 25305 if (ret === false) { 25306 return false; 25307 } 25308 25309 if (obj.helpers) { 25310 $.each(obj.helpers, function (helper, opts) { 25311 if (opts && F.helpers[helper] && $.isFunction(F.helpers[helper][event])) { 25312 F.helpers[helper][event]($.extend(true, {}, F.helpers[helper].defaults, opts), obj); 25313 } 25314 }); 25315 } 25316 } 25317 25318 D.trigger(event); 25319 }, 25320 25321 isImage: function (str) { 25322 return isString(str) && str.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i); 25323 }, 25324 25325 isSWF: function (str) { 25326 return isString(str) && str.match(/\.(swf)((\?|#).*)?$/i); 25327 }, 25328 25329 _start: function (index) { 25330 var coming = {}, 25331 obj, 25332 href, 25333 type, 25334 margin, 25335 padding; 25336 25337 index = getScalar( index ); 25338 obj = F.group[ index ] || null; 25339 25340 if (!obj) { 25341 return false; 25342 } 25343 25344 coming = $.extend(true, {}, F.opts, obj); 25345 25346 // Convert margin and padding properties to array - top, right, bottom, left 25347 margin = coming.margin; 25348 padding = coming.padding; 25349 25350 if ($.type(margin) === 'number') { 25351 coming.margin = [margin, margin, margin, margin]; 25352 } 25353 25354 if ($.type(padding) === 'number') { 25355 coming.padding = [padding, padding, padding, padding]; 25356 } 25357 25358 // 'modal' propery is just a shortcut 25359 if (coming.modal) { 25360 $.extend(true, coming, { 25361 closeBtn : false, 25362 closeClick : false, 25363 nextClick : false, 25364 arrows : false, 25365 mouseWheel : false, 25366 keys : null, 25367 helpers: { 25368 overlay : { 25369 closeClick : false 25370 } 25371 } 25372 }); 25373 } 25374 25375 // 'autoSize' property is a shortcut, too 25376 if (coming.autoSize) { 25377 coming.autoWidth = coming.autoHeight = true; 25378 } 25379 25380 if (coming.width === 'auto') { 25381 coming.autoWidth = true; 25382 } 25383 25384 if (coming.height === 'auto') { 25385 coming.autoHeight = true; 25386 } 25387 25388 /* 25389 * Add reference to the group, so it`s possible to access from callbacks, example: 25390 * afterLoad : function() { 25391 * this.title = 'Image ' + (this.index + 1) + ' of ' + this.group.length + (this.title ? ' - ' + this.title : ''); 25392 * } 25393 */ 25394 25395 coming.group = F.group; 25396 coming.index = index; 25397 25398 // Give a chance for callback or helpers to update coming item (type, title, etc) 25399 F.coming = coming; 25400 25401 if (false === F.trigger('beforeLoad')) { 25402 F.coming = null; 25403 25404 return; 25405 } 25406 25407 type = coming.type; 25408 href = coming.href; 25409 25410 if (!type) { 25411 F.coming = null; 25412 25413 //If we can not determine content type then drop silently or display next/prev item if looping through gallery 25414 if (F.current && F.router && F.router !== 'jumpto') { 25415 F.current.index = index; 25416 25417 return F[ F.router ]( F.direction ); 25418 } 25419 25420 return false; 25421 } 25422 25423 F.isActive = true; 25424 25425 if (type === 'image' || type === 'swf') { 25426 coming.autoHeight = coming.autoWidth = false; 25427 coming.scrolling = 'visible'; 25428 } 25429 25430 if (type === 'image') { 25431 coming.aspectRatio = true; 25432 } 25433 25434 if (type === 'iframe' && isTouch) { 25435 coming.scrolling = 'scroll'; 25436 } 25437 25438 // Build the neccessary markup 25439 coming.wrap = $(coming.tpl.wrap).addClass('fancybox-' + (isTouch ? 'mobile' : 'desktop') + ' fancybox-type-' + type + ' fancybox-tmp ' + coming.wrapCSS).appendTo( coming.parent || 'body' ); 25440 25441 $.extend(coming, { 25442 skin : $('.fancybox-skin', coming.wrap), 25443 outer : $('.fancybox-outer', coming.wrap), 25444 inner : $('.fancybox-inner', coming.wrap) 25445 }); 25446 25447 $.each(["Top", "Right", "Bottom", "Left"], function(i, v) { 25448 coming.skin.css('padding' + v, getValue(coming.padding[ i ])); 25449 }); 25450 25451 F.trigger('onReady'); 25452 25453 // Check before try to load; 'inline' and 'html' types need content, others - href 25454 if (type === 'inline' || type === 'html') { 25455 if (!coming.content || !coming.content.length) { 25456 return F._error( 'content' ); 25457 } 25458 25459 } else if (!href) { 25460 return F._error( 'href' ); 25461 } 25462 25463 if (type === 'image') { 25464 F._loadImage(); 25465 25466 } else if (type === 'ajax') { 25467 F._loadAjax(); 25468 25469 } else if (type === 'iframe') { 25470 F._loadIframe(); 25471 25472 } else { 25473 F._afterLoad(); 25474 } 25475 }, 25476 25477 _error: function ( type ) { 25478 $.extend(F.coming, { 25479 type : 'html', 25480 autoWidth : true, 25481 autoHeight : true, 25482 minWidth : 0, 25483 minHeight : 0, 25484 scrolling : 'no', 25485 hasError : type, 25486 content : F.coming.tpl.error 25487 }); 25488 25489 F._afterLoad(); 25490 }, 25491 25492 _loadImage: function () { 25493 // Reset preload image so it is later possible to check "complete" property 25494 var img = F.imgPreload = new Image(); 25495 25496 img.onload = function () { 25497 this.onload = this.onerror = null; 25498 25499 F.coming.width = this.width / F.opts.pixelRatio; 25500 F.coming.height = this.height / F.opts.pixelRatio; 25501 25502 F._afterLoad(); 25503 }; 25504 25505 img.onerror = function () { 25506 this.onload = this.onerror = null; 25507 25508 F._error( 'image' ); 25509 }; 25510 25511 img.src = F.coming.href; 25512 25513 if (img.complete !== true) { 25514 F.showLoading(); 25515 } 25516 }, 25517 25518 _loadAjax: function () { 25519 var coming = F.coming; 25520 25521 F.showLoading(); 25522 25523 F.ajaxLoad = $.ajax($.extend({}, coming.ajax, { 25524 url: coming.href, 25525 error: function (jqXHR, textStatus) { 25526 if (F.coming && textStatus !== 'abort') { 25527 F._error( 'ajax', jqXHR ); 25528 25529 } else { 25530 F.hideLoading(); 25531 } 25532 }, 25533 success: function (data, textStatus) { 25534 if (textStatus === 'success') { 25535 coming.content = data; 25536 25537 F._afterLoad(); 25538 } 25539 } 25540 })); 25541 }, 25542 25543 _loadIframe: function() { 25544 var coming = F.coming, 25545 iframe = $(coming.tpl.iframe.replace(/\{rnd\}/g, new Date().getTime())) 25546 .attr('scrolling', isTouch ? 'auto' : coming.iframe.scrolling) 25547 .attr('src', coming.href); 25548 25549 // This helps IE 25550 $(coming.wrap).bind('onReset', function () { 25551 try { 25552 $(this).find('iframe').hide().attr('src', '//about:blank').end().empty(); 25553 } catch (e) {} 25554 }); 25555 25556 if (coming.iframe.preload) { 25557 F.showLoading(); 25558 25559 iframe.one('load', function() { 25560 $(this).data('ready', 1); 25561 25562 // iOS will lose scrolling if we resize 25563 if (!isTouch) { 25564 $(this).bind('load.fb', F.update); 25565 } 25566 25567 // Without this trick: 25568 // - iframe won't scroll on iOS devices 25569 // - IE7 sometimes displays empty iframe 25570 $(this).parents('.fancybox-wrap').width('100%').removeClass('fancybox-tmp').show(); 25571 25572 F._afterLoad(); 25573 }); 25574 } 25575 25576 coming.content = iframe.appendTo( coming.inner ); 25577 25578 if (!coming.iframe.preload) { 25579 F._afterLoad(); 25580 } 25581 }, 25582 25583 _preloadImages: function() { 25584 var group = F.group, 25585 current = F.current, 25586 len = group.length, 25587 cnt = current.preload ? Math.min(current.preload, len - 1) : 0, 25588 item, 25589 i; 25590 25591 for (i = 1; i <= cnt; i += 1) { 25592 item = group[ (current.index + i ) % len ]; 25593 25594 if (item.type === 'image' && item.href) { 25595 new Image().src = item.href; 25596 } 25597 } 25598 }, 25599 25600 _afterLoad: function () { 25601 var coming = F.coming, 25602 previous = F.current, 25603 placeholder = 'fancybox-placeholder', 25604 current, 25605 content, 25606 type, 25607 scrolling, 25608 href, 25609 embed; 25610 25611 F.hideLoading(); 25612 25613 if (!coming || F.isActive === false) { 25614 return; 25615 } 25616 25617 if (false === F.trigger('afterLoad', coming, previous)) { 25618 coming.wrap.stop(true).trigger('onReset').remove(); 25619 25620 F.coming = null; 25621 25622 return; 25623 } 25624 25625 if (previous) { 25626 F.trigger('beforeChange', previous); 25627 25628 previous.wrap.stop(true).removeClass('fancybox-opened') 25629 .find('.fancybox-item, .fancybox-nav') 25630 .remove(); 25631 } 25632 25633 F.unbindEvents(); 25634 25635 current = coming; 25636 content = coming.content; 25637 type = coming.type; 25638 scrolling = coming.scrolling; 25639 25640 $.extend(F, { 25641 wrap : current.wrap, 25642 skin : current.skin, 25643 outer : current.outer, 25644 inner : current.inner, 25645 current : current, 25646 previous : previous 25647 }); 25648 25649 href = current.href; 25650 25651 switch (type) { 25652 case 'inline': 25653 case 'ajax': 25654 case 'html': 25655 if (current.selector) { 25656 content = $('<div>').html(content).find(current.selector); 25657 25658 } else if (isQuery(content)) { 25659 if (!content.data(placeholder)) { 25660 content.data(placeholder, $('<div class="' + placeholder + '"></div>').insertAfter( content ).hide() ); 25661 } 25662 25663 content = content.show().detach(); 25664 25665 current.wrap.bind('onReset', function () { 25666 if ($(this).find(content).length) { 25667 content.hide().replaceAll( content.data(placeholder) ).data(placeholder, false); 25668 } 25669 }); 25670 } 25671 break; 25672 25673 case 'image': 25674 content = current.tpl.image.replace(/\{href\}/g, href); 25675 break; 25676 25677 case 'swf': 25678 content = '<object id="fancybox-swf" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%"><param name="movie" value="' + href + '"></param>'; 25679 embed = ''; 25680 25681 $.each(current.swf, function(name, val) { 25682 content += '<param name="' + name + '" value="' + val + '"></param>'; 25683 embed += ' ' + name + '="' + val + '"'; 25684 }); 25685 25686 content += '<embed src="' + href + '" type="application/x-shockwave-flash" width="100%" height="100%"' + embed + '></embed></object>'; 25687 break; 25688 } 25689 25690 if (!(isQuery(content) && content.parent().is(current.inner))) { 25691 current.inner.append( content ); 25692 } 25693 25694 // Give a chance for helpers or callbacks to update elements 25695 F.trigger('beforeShow'); 25696 25697 // Set scrolling before calculating dimensions 25698 current.inner.css('overflow', scrolling === 'yes' ? 'scroll' : (scrolling === 'no' ? 'hidden' : scrolling)); 25699 25700 // Set initial dimensions and start position 25701 F._setDimension(); 25702 25703 F.reposition(); 25704 25705 F.isOpen = false; 25706 F.coming = null; 25707 25708 F.bindEvents(); 25709 25710 if (!F.isOpened) { 25711 $('.fancybox-wrap').not( current.wrap ).stop(true).trigger('onReset').remove(); 25712 25713 } else if (previous.prevMethod) { 25714 F.transitions[ previous.prevMethod ](); 25715 } 25716 25717 F.transitions[ F.isOpened ? current.nextMethod : current.openMethod ](); 25718 25719 F._preloadImages(); 25720 }, 25721 25722 _setDimension: function () { 25723 var viewport = F.getViewport(), 25724 steps = 0, 25725 canShrink = false, 25726 canExpand = false, 25727 wrap = F.wrap, 25728 skin = F.skin, 25729 inner = F.inner, 25730 current = F.current, 25731 width = current.width, 25732 height = current.height, 25733 minWidth = current.minWidth, 25734 minHeight = current.minHeight, 25735 maxWidth = current.maxWidth, 25736 maxHeight = current.maxHeight, 25737 scrolling = current.scrolling, 25738 scrollOut = current.scrollOutside ? current.scrollbarWidth : 0, 25739 margin = current.margin, 25740 wMargin = getScalar(margin[1] + margin[3]), 25741 hMargin = getScalar(margin[0] + margin[2]), 25742 wPadding, 25743 hPadding, 25744 wSpace, 25745 hSpace, 25746 origWidth, 25747 origHeight, 25748 origMaxWidth, 25749 origMaxHeight, 25750 ratio, 25751 width_, 25752 height_, 25753 maxWidth_, 25754 maxHeight_, 25755 iframe, 25756 body; 25757 25758 // Reset dimensions so we could re-check actual size 25759 wrap.add(skin).add(inner).width('auto').height('auto').removeClass('fancybox-tmp'); 25760 25761 wPadding = getScalar(skin.outerWidth(true) - skin.width()); 25762 hPadding = getScalar(skin.outerHeight(true) - skin.height()); 25763 25764 // Any space between content and viewport (margin, padding, border, title) 25765 wSpace = wMargin + wPadding; 25766 hSpace = hMargin + hPadding; 25767 25768 origWidth = isPercentage(width) ? (viewport.w - wSpace) * getScalar(width) / 100 : width; 25769 origHeight = isPercentage(height) ? (viewport.h - hSpace) * getScalar(height) / 100 : height; 25770 25771 if (current.type === 'iframe') { 25772 iframe = current.content; 25773 25774 if (current.autoHeight && iframe.data('ready') === 1) { 25775 try { 25776 if (iframe[0].contentWindow.document.location) { 25777 inner.width( origWidth ).height(9999); 25778 25779 body = iframe.contents().find('body'); 25780 25781 if (scrollOut) { 25782 body.css('overflow-x', 'hidden'); 25783 } 25784 25785 origHeight = body.outerHeight(true); 25786 } 25787 25788 } catch (e) {} 25789 } 25790 25791 } else if (current.autoWidth || current.autoHeight) { 25792 inner.addClass( 'fancybox-tmp' ); 25793 25794 // Set width or height in case we need to calculate only one dimension 25795 if (!current.autoWidth) { 25796 inner.width( origWidth ); 25797 } 25798 25799 if (!current.autoHeight) { 25800 inner.height( origHeight ); 25801 } 25802 25803 if (current.autoWidth) { 25804 origWidth = inner.width(); 25805 } 25806 25807 if (current.autoHeight) { 25808 origHeight = inner.height(); 25809 } 25810 25811 inner.removeClass( 'fancybox-tmp' ); 25812 } 25813 25814 width = getScalar( origWidth ); 25815 height = getScalar( origHeight ); 25816 25817 ratio = origWidth / origHeight; 25818 25819 // Calculations for the content 25820 minWidth = getScalar(isPercentage(minWidth) ? getScalar(minWidth, 'w') - wSpace : minWidth); 25821 maxWidth = getScalar(isPercentage(maxWidth) ? getScalar(maxWidth, 'w') - wSpace : maxWidth); 25822 25823 minHeight = getScalar(isPercentage(minHeight) ? getScalar(minHeight, 'h') - hSpace : minHeight); 25824 maxHeight = getScalar(isPercentage(maxHeight) ? getScalar(maxHeight, 'h') - hSpace : maxHeight); 25825 25826 // These will be used to determine if wrap can fit in the viewport 25827 origMaxWidth = maxWidth; 25828 origMaxHeight = maxHeight; 25829 25830 if (current.fitToView) { 25831 maxWidth = Math.min(viewport.w - wSpace, maxWidth); 25832 maxHeight = Math.min(viewport.h - hSpace, maxHeight); 25833 } 25834 25835 maxWidth_ = viewport.w - wMargin; 25836 maxHeight_ = viewport.h - hMargin; 25837 25838 if (current.aspectRatio) { 25839 if (width > maxWidth) { 25840 width = maxWidth; 25841 height = getScalar(width / ratio); 25842 } 25843 25844 if (height > maxHeight) { 25845 height = maxHeight; 25846 width = getScalar(height * ratio); 25847 } 25848 25849 if (width < minWidth) { 25850 width = minWidth; 25851 height = getScalar(width / ratio); 25852 } 25853 25854 if (height < minHeight) { 25855 height = minHeight; 25856 width = getScalar(height * ratio); 25857 } 25858 25859 } else { 25860 width = Math.max(minWidth, Math.min(width, maxWidth)); 25861 25862 if (current.autoHeight && current.type !== 'iframe') { 25863 inner.width( width ); 25864 25865 height = inner.height(); 25866 } 25867 25868 height = Math.max(minHeight, Math.min(height, maxHeight)); 25869 } 25870 25871 // Try to fit inside viewport (including the title) 25872 if (current.fitToView) { 25873 inner.width( width ).height( height ); 25874 25875 wrap.width( width + wPadding ); 25876 25877 // Real wrap dimensions 25878 width_ = wrap.width(); 25879 height_ = wrap.height(); 25880 25881 if (current.aspectRatio) { 25882 while ((width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight) { 25883 if (steps++ > 19) { 25884 break; 25885 } 25886 25887 height = Math.max(minHeight, Math.min(maxHeight, height - 10)); 25888 width = getScalar(height * ratio); 25889 25890 if (width < minWidth) { 25891 width = minWidth; 25892 height = getScalar(width / ratio); 25893 } 25894 25895 if (width > maxWidth) { 25896 width = maxWidth; 25897 height = getScalar(width / ratio); 25898 } 25899 25900 inner.width( width ).height( height ); 25901 25902 wrap.width( width + wPadding ); 25903 25904 width_ = wrap.width(); 25905 height_ = wrap.height(); 25906 } 25907 25908 } else { 25909 width = Math.max(minWidth, Math.min(width, width - (width_ - maxWidth_))); 25910 height = Math.max(minHeight, Math.min(height, height - (height_ - maxHeight_))); 25911 } 25912 } 25913 25914 if (scrollOut && scrolling === 'auto' && height < origHeight && (width + wPadding + scrollOut) < maxWidth_) { 25915 width += scrollOut; 25916 } 25917 25918 inner.width( width ).height( height ); 25919 25920 wrap.width( width + wPadding ); 25921 25922 width_ = wrap.width(); 25923 height_ = wrap.height(); 25924 25925 canShrink = (width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight; 25926 canExpand = current.aspectRatio ? (width < origMaxWidth && height < origMaxHeight && width < origWidth && height < origHeight) : ((width < origMaxWidth || height < origMaxHeight) && (width < origWidth || height < origHeight)); 25927 25928 $.extend(current, { 25929 dim : { 25930 width : getValue( width_ ), 25931 height : getValue( height_ ) 25932 }, 25933 origWidth : origWidth, 25934 origHeight : origHeight, 25935 canShrink : canShrink, 25936 canExpand : canExpand, 25937 wPadding : wPadding, 25938 hPadding : hPadding, 25939 wrapSpace : height_ - skin.outerHeight(true), 25940 skinSpace : skin.height() - height 25941 }); 25942 25943 if (!iframe && current.autoHeight && height > minHeight && height < maxHeight && !canExpand) { 25944 inner.height('auto'); 25945 } 25946 }, 25947 25948 _getPosition: function (onlyAbsolute) { 25949 var current = F.current, 25950 viewport = F.getViewport(), 25951 margin = current.margin, 25952 width = F.wrap.width() + margin[1] + margin[3], 25953 height = F.wrap.height() + margin[0] + margin[2], 25954 rez = { 25955 position: 'absolute', 25956 top : margin[0], 25957 left : margin[3] 25958 }; 25959 25960 if (current.autoCenter && current.fixed && !onlyAbsolute && height <= viewport.h && width <= viewport.w) { 25961 rez.position = 'fixed'; 25962 25963 } else if (!current.locked) { 25964 rez.top += viewport.y; 25965 rez.left += viewport.x; 25966 } 25967 25968 rez.top = getValue(Math.max(rez.top, rez.top + ((viewport.h - height) * current.topRatio))); 25969 rez.left = getValue(Math.max(rez.left, rez.left + ((viewport.w - width) * current.leftRatio))); 25970 25971 return rez; 25972 }, 25973 25974 _afterZoomIn: function () { 25975 var current = F.current; 25976 25977 if (!current) { 25978 return; 25979 } 25980 25981 F.isOpen = F.isOpened = true; 25982 25983 F.wrap.css('overflow', 'visible').addClass('fancybox-opened').hide().show(0); 25984 25985 F.update(); 25986 25987 // Assign a click event 25988 if ( current.closeClick || (current.nextClick && F.group.length > 1) ) { 25989 F.inner.css('cursor', 'pointer').bind('click.fb', function(e) { 25990 if (!$(e.target).is('a') && !$(e.target).parent().is('a')) { 25991 e.preventDefault(); 25992 25993 F[ current.closeClick ? 'close' : 'next' ](); 25994 } 25995 }); 25996 } 25997 25998 // Create a close button 25999 if (current.closeBtn) { 26000 $(current.tpl.closeBtn).appendTo(F.skin).bind('click.fb', function(e) { 26001 e.preventDefault(); 26002 26003 F.close(); 26004 }); 26005 } 26006 26007 // Create navigation arrows 26008 if (current.arrows && F.group.length > 1) { 26009 if (current.loop || current.index > 0) { 26010 $(current.tpl.prev).appendTo(F.outer).bind('click.fb', F.prev); 26011 } 26012 26013 if (current.loop || current.index < F.group.length - 1) { 26014 $(current.tpl.next).appendTo(F.outer).bind('click.fb', F.next); 26015 } 26016 } 26017 26018 F.trigger('afterShow'); 26019 26020 // Stop the slideshow if this is the last item 26021 if (!current.loop && current.index === current.group.length - 1) { 26022 26023 F.play( false ); 26024 26025 } else if (F.opts.autoPlay && !F.player.isActive) { 26026 F.opts.autoPlay = false; 26027 26028 F.play(true); 26029 } 26030 }, 26031 26032 _afterZoomOut: function ( obj ) { 26033 obj = obj || F.current; 26034 26035 $('.fancybox-wrap').trigger('onReset').remove(); 26036 26037 $.extend(F, { 26038 group : {}, 26039 opts : {}, 26040 router : false, 26041 current : null, 26042 isActive : false, 26043 isOpened : false, 26044 isOpen : false, 26045 isClosing : false, 26046 wrap : null, 26047 skin : null, 26048 outer : null, 26049 inner : null 26050 }); 26051 26052 F.trigger('afterClose', obj); 26053 } 26054 }); 26055 26056 /* 26057 * Default transitions 26058 */ 26059 26060 F.transitions = { 26061 getOrigPosition: function () { 26062 var current = F.current, 26063 element = current.element, 26064 orig = current.orig, 26065 pos = {}, 26066 width = 50, 26067 height = 50, 26068 hPadding = current.hPadding, 26069 wPadding = current.wPadding, 26070 viewport = F.getViewport(); 26071 26072 if (!orig && current.isDom && element.is(':visible')) { 26073 orig = element.find('img:first'); 26074 26075 if (!orig.length) { 26076 orig = element; 26077 } 26078 } 26079 26080 if (isQuery(orig)) { 26081 pos = orig.offset(); 26082 26083 if (orig.is('img')) { 26084 width = orig.outerWidth(); 26085 height = orig.outerHeight(); 26086 } 26087 26088 } else { 26089 pos.top = viewport.y + (viewport.h - height) * current.topRatio; 26090 pos.left = viewport.x + (viewport.w - width) * current.leftRatio; 26091 } 26092 26093 if (F.wrap.css('position') === 'fixed' || current.locked) { 26094 pos.top -= viewport.y; 26095 pos.left -= viewport.x; 26096 } 26097 26098 pos = { 26099 top : getValue(pos.top - hPadding * current.topRatio), 26100 left : getValue(pos.left - wPadding * current.leftRatio), 26101 width : getValue(width + wPadding), 26102 height : getValue(height + hPadding) 26103 }; 26104 26105 return pos; 26106 }, 26107 26108 step: function (now, fx) { 26109 var ratio, 26110 padding, 26111 value, 26112 prop = fx.prop, 26113 current = F.current, 26114 wrapSpace = current.wrapSpace, 26115 skinSpace = current.skinSpace; 26116 26117 if (prop === 'width' || prop === 'height') { 26118 ratio = fx.end === fx.start ? 1 : (now - fx.start) / (fx.end - fx.start); 26119 26120 if (F.isClosing) { 26121 ratio = 1 - ratio; 26122 } 26123 26124 padding = prop === 'width' ? current.wPadding : current.hPadding; 26125 value = now - padding; 26126 26127 F.skin[ prop ]( getScalar( prop === 'width' ? value : value - (wrapSpace * ratio) ) ); 26128 F.inner[ prop ]( getScalar( prop === 'width' ? value : value - (wrapSpace * ratio) - (skinSpace * ratio) ) ); 26129 } 26130 }, 26131 26132 zoomIn: function () { 26133 var current = F.current, 26134 startPos = current.pos, 26135 effect = current.openEffect, 26136 elastic = effect === 'elastic', 26137 endPos = $.extend({opacity : 1}, startPos); 26138 26139 // Remove "position" property that breaks older IE 26140 delete endPos.position; 26141 26142 if (elastic) { 26143 startPos = this.getOrigPosition(); 26144 26145 if (current.openOpacity) { 26146 startPos.opacity = 0.1; 26147 } 26148 26149 } else if (effect === 'fade') { 26150 startPos.opacity = 0.1; 26151 } 26152 26153 F.wrap.css(startPos).animate(endPos, { 26154 duration : effect === 'none' ? 0 : current.openSpeed, 26155 easing : current.openEasing, 26156 step : elastic ? this.step : null, 26157 complete : F._afterZoomIn 26158 }); 26159 }, 26160 26161 zoomOut: function () { 26162 var current = F.current, 26163 effect = current.closeEffect, 26164 elastic = effect === 'elastic', 26165 endPos = {opacity : 0.1}; 26166 26167 if (elastic) { 26168 endPos = this.getOrigPosition(); 26169 26170 if (current.closeOpacity) { 26171 endPos.opacity = 0.1; 26172 } 26173 } 26174 26175 F.wrap.animate(endPos, { 26176 duration : effect === 'none' ? 0 : current.closeSpeed, 26177 easing : current.closeEasing, 26178 step : elastic ? this.step : null, 26179 complete : F._afterZoomOut 26180 }); 26181 }, 26182 26183 changeIn: function () { 26184 var current = F.current, 26185 effect = current.nextEffect, 26186 startPos = current.pos, 26187 endPos = { opacity : 1 }, 26188 direction = F.direction, 26189 distance = 200, 26190 field; 26191 26192 startPos.opacity = 0.1; 26193 26194 if (effect === 'elastic') { 26195 field = direction === 'down' || direction === 'up' ? 'top' : 'left'; 26196 26197 if (direction === 'down' || direction === 'right') { 26198 startPos[ field ] = getValue(getScalar(startPos[ field ]) - distance); 26199 endPos[ field ] = '+=' + distance + 'px'; 26200 26201 } else { 26202 startPos[ field ] = getValue(getScalar(startPos[ field ]) + distance); 26203 endPos[ field ] = '-=' + distance + 'px'; 26204 } 26205 } 26206 26207 // Workaround for http://bugs.jquery.com/ticket/12273 26208 if (effect === 'none') { 26209 F._afterZoomIn(); 26210 26211 } else { 26212 F.wrap.css(startPos).animate(endPos, { 26213 duration : current.nextSpeed, 26214 easing : current.nextEasing, 26215 complete : F._afterZoomIn 26216 }); 26217 } 26218 }, 26219 26220 changeOut: function () { 26221 var previous = F.previous, 26222 effect = previous.prevEffect, 26223 endPos = { opacity : 0.1 }, 26224 direction = F.direction, 26225 distance = 200; 26226 26227 if (effect === 'elastic') { 26228 endPos[ direction === 'down' || direction === 'up' ? 'top' : 'left' ] = ( direction === 'up' || direction === 'left' ? '-' : '+' ) + '=' + distance + 'px'; 26229 } 26230 26231 previous.wrap.animate(endPos, { 26232 duration : effect === 'none' ? 0 : previous.prevSpeed, 26233 easing : previous.prevEasing, 26234 complete : function () { 26235 $(this).trigger('onReset').remove(); 26236 } 26237 }); 26238 } 26239 }; 26240 26241 /* 26242 * Overlay helper 26243 */ 26244 26245 F.helpers.overlay = { 26246 defaults : { 26247 closeClick : true, // if true, fancyBox will be closed when user clicks on the overlay 26248 speedOut : 200, // duration of fadeOut animation 26249 showEarly : true, // indicates if should be opened immediately or wait until the content is ready 26250 css : {}, // custom CSS properties 26251 locked : !isTouch, // if true, the content will be locked into overlay 26252 fixed : true // if false, the overlay CSS position property will not be set to "fixed" 26253 }, 26254 26255 overlay : null, // current handle 26256 fixed : false, // indicates if the overlay has position "fixed" 26257 el : $('html'), // element that contains "the lock" 26258 26259 // Public methods 26260 create : function(opts) { 26261 var parent; 26262 26263 opts = $.extend({}, this.defaults, opts); 26264 26265 if (this.overlay) { 26266 this.close(); 26267 } 26268 26269 parent = F.coming ? F.coming.parent : opts.parent; 26270 26271 this.overlay = $('<div class="fancybox-overlay"></div>').appendTo( parent && parent.length ? parent : 'body' ); 26272 this.fixed = false; 26273 26274 if (opts.fixed && F.defaults.fixed) { 26275 this.overlay.addClass('fancybox-overlay-fixed'); 26276 26277 this.fixed = true; 26278 } 26279 }, 26280 26281 open : function(opts) { 26282 var that = this; 26283 26284 opts = $.extend({}, this.defaults, opts); 26285 26286 if (this.overlay) { 26287 this.overlay.unbind('.overlay').width('auto').height('auto'); 26288 26289 } else { 26290 this.create(opts); 26291 } 26292 26293 if (!this.fixed) { 26294 W.bind('resize.overlay', $.proxy( this.update, this) ); 26295 26296 this.update(); 26297 } 26298 26299 if (opts.closeClick) { 26300 this.overlay.bind('click.overlay', function(e) { 26301 if ($(e.target).hasClass('fancybox-overlay')) { 26302 if (F.isActive) { 26303 F.close(); 26304 } else { 26305 that.close(); 26306 } 26307 26308 return false; 26309 } 26310 }); 26311 } 26312 26313 this.overlay.css( opts.css ).show(); 26314 }, 26315 26316 close : function() { 26317 W.unbind('resize.overlay'); 26318 26319 if (this.el.hasClass('fancybox-lock')) { 26320 $('.fancybox-margin').removeClass('fancybox-margin'); 26321 26322 this.el.removeClass('fancybox-lock'); 26323 26324 W.scrollTop( this.scrollV ).scrollLeft( this.scrollH ); 26325 } 26326 26327 $('.fancybox-overlay').remove().hide(); 26328 26329 $.extend(this, { 26330 overlay : null, 26331 fixed : false 26332 }); 26333 }, 26334 26335 // Private, callbacks 26336 26337 update : function () { 26338 var width = '100%', offsetWidth; 26339 26340 // Reset width/height so it will not mess 26341 this.overlay.width(width).height('100%'); 26342 26343 // jQuery does not return reliable result for IE 26344 if (IE) { 26345 offsetWidth = Math.max(document.documentElement.offsetWidth, document.body.offsetWidth); 26346 26347 if (D.width() > offsetWidth) { 26348 width = D.width(); 26349 } 26350 26351 } else if (D.width() > W.width()) { 26352 width = D.width(); 26353 } 26354 26355 this.overlay.width(width).height(D.height()); 26356 }, 26357 26358 // This is where we can manipulate DOM, because later it would cause iframes to reload 26359 onReady : function (opts, obj) { 26360 var overlay = this.overlay; 26361 26362 $('.fancybox-overlay').stop(true, true); 26363 26364 if (!overlay) { 26365 this.create(opts); 26366 } 26367 26368 if (opts.locked && this.fixed && obj.fixed) { 26369 obj.locked = this.overlay.append( obj.wrap ); 26370 obj.fixed = false; 26371 } 26372 26373 if (opts.showEarly === true) { 26374 this.beforeShow.apply(this, arguments); 26375 } 26376 }, 26377 26378 beforeShow : function(opts, obj) { 26379 if (obj.locked && !this.el.hasClass('fancybox-lock')) { 26380 if (this.fixPosition !== false) { 26381 $('*
vendor: 1,346 bytes, lines 26381-26439
26381:not(object)').filter(function(){ 26382 return ($(this).css('position') === 'fixed' && !$(this).hasClass("fancybox-overlay") && !$(this).hasClass("fancybox-wrap") ); 26383 }).addClass('fancybox-margin'); 26384 } 26385 26386 this.el.addClass('fancybox-margin'); 26387 26388 this.scrollV = W.scrollTop(); 26389 this.scrollH = W.scrollLeft(); 26390 26391 this.el.addClass('fancybox-lock'); 26392 26393 W.scrollTop( this.scrollV ).scrollLeft( this.scrollH ); 26394 } 26395 26396 this.open(opts); 26397 }, 26398 26399 onUpdate : function() { 26400 if (!this.fixed) { 26401 this.update(); 26402 } 26403 }, 26404 26405 afterClose: function (opts) { 26406 // Remove overlay if exists and fancyBox is not opening 26407 // (e.g., it is not being open using afterClose callback) 26408 if (this.overlay && !F.coming) { 26409 this.overlay.fadeOut(opts.speedOut, $.proxy( this.close, this )); 26410 } 26411 } 26412 }; 26413 26414 /* 26415 * Title helper 26416 */ 26417 26418 F.helpers.title = { 26419 defaults : { 26420 type : 'float', // 'float', 'inside', 'outside' or 'over', 26421 position : 'bottom' // 'top' or 'bottom' 26422 }, 26423 26424 beforeShow: function (opts) { 26425 var current = F.current, 26426 text = current.title, 26427 type = opts.type, 26428 title, 26429 target; 26430 26431 if ($.isFunction(text)) { 26432 text = text.call(current.element, current); 26433 } 26434 26435 if (!isString(text) || $.trim(text) === '') { 26436 return; 26437 } 26438 26439 title = $('<div class="fancybox-title fancybox-title-' + type + '-wrap">
vendor: 3,163 bytes, lines 26439-26568
26439' + text + '</div>'); 26440 26441 switch (type) { 26442 case 'inside': 26443 target = F.skin; 26444 break; 26445 26446 case 'outside': 26447 target = F.wrap; 26448 break; 26449 26450 case 'over': 26451 target = F.inner; 26452 break; 26453 26454 default: // 'float' 26455 target = F.skin; 26456 26457 title.appendTo('body'); 26458 26459 if (IE) { 26460 title.width( title.width() ); 26461 } 26462 26463 title.wrapInner('<span class="child"></span>'); 26464 26465 //Increase bottom margin so this title will also fit into viewport 26466 F.current.margin[2] += Math.abs( getScalar(title.css('margin-bottom')) ); 26467 break; 26468 } 26469 26470 title[ (opts.position === 'top' ? 'prependTo' : 'appendTo') ](target); 26471 } 26472 }; 26473 26474 // jQuery plugin initialization 26475 $.fn.fancybox = function (options) { 26476 var index, 26477 that = $(this), 26478 selector = this.selector || '', 26479 run = function(e) { 26480 var what = $(this).blur(), idx = index, relType, relVal; 26481 26482 if (!(e.ctrlKey || e.altKey || e.shiftKey || e.metaKey) && !what.is('.fancybox-wrap')) { 26483 relType = options.groupAttr || 'data-fancybox-group'; 26484 relVal = what.attr(relType); 26485 26486 if (!relVal) { 26487 relType = 'rel'; 26488 relVal = what.get(0)[ relType ]; 26489 } 26490 26491 if (relVal && relVal !== '' && relVal !== 'nofollow') { 26492 what = selector.length ? $(selector) : that; 26493 what = what.filter('[' + relType + '="' + relVal + '"]'); 26494 idx = what.index(this); 26495 } 26496 26497 options.index = idx; 26498 26499 // Stop an event from bubbling if everything is fine 26500 if (F.open(what, options) !== false) { 26501 e.preventDefault(); 26502 } 26503 } 26504 }; 26505 26506 options = options || {}; 26507 index = options.index || 0; 26508 26509 if (!selector || options.live === false) { 26510 that.unbind('click.fb-start').bind('click.fb-start', run); 26511 26512 } else { 26513 D.undelegate(selector, 'click.fb-start').delegate(selector + ":not('.fancybox-item, .fancybox-nav')", 'click.fb-start', run); 26514 } 26515 26516 this.filter('[data-fancybox-start=1]').trigger('click'); 26517 26518 return this; 26519 }; 26520 26521 // Tests that need a body at doc ready 26522 D.ready(function() { 26523 var w1, w2; 26524 26525 if ( $.scrollbarWidth === undefined ) { 26526 // http://benalman.com/projects/jquery-misc-plugins/#scrollbarwidth 26527 $.scrollbarWidth = function() { 26528 var parent = $('<div style="width:50px;height:50px;overflow:auto"><div/></div>').appendTo('body'), 26529 child = parent.children(), 26530 width = child.innerWidth() - child.height( 99 ).innerWidth(); 26531 26532 parent.remove(); 26533 26534 return width; 26535 }; 26536 } 26537 26538 if ( $.support.fixedPosition === undefined ) { 26539 $.support.fixedPosition = (function() { 26540 var elem = $('<div style="position:fixed;top:20px;"></div>').appendTo('body'), 26541 fixed = ( elem[0].offsetTop === 20 || elem[0].offsetTop === 15 ); 26542 26543 elem.remove(); 26544 26545 return fixed; 26546 }()); 26547 } 26548 26549 $.extend(F.defaults, { 26550 scrollbarWidth : $.scrollbarWidth(), 26551 fixed : $.support.fixedPosition, 26552 parent : $('body') 26553 }); 26554 26555 //Get real width of page scroll-bar 26556 w1 = $(window).width(); 26557 26558 H.addClass('fancybox-lock-test'); 26559 26560 w2 = $(window).width(); 26561 26562 H.removeClass('fancybox-lock-test'); 26563 26564 $("<style type='text/css'>.fancybox-margin{margin-right:" + (w2 - w1) + "px;}</style>").appendTo("head"); 26565 }); 26566 26567}(window, document, jQuery)); 26568
vendor: 23,187 bytes, lines 26569-26614
26569/*! fancyBox v2.1.5 fancyapps.com | fancyapps.com/fancybox/#license */ 26570(function(s,H,f,w){var K=f("html"),q=f(s),p=f(H),b=f.fancybox=function(){b.open.apply(this,arguments)},J=navigator.userAgent.match(/msie/i),C=null,t=H.createTouch!==w,u=function(a){return a&&a.hasOwnProperty&&a instanceof f},r=function(a){return a&&"string"===f.type(a)},F=function(a){return r(a)&&0<a.indexOf("%")},m=function(a,d){var e=parseInt(a,10)||0;d&&F(a)&&(e*=b.getViewport()[d]/100);return Math.ceil(e)},x=function(a,b){return m(a,b)+"px"};f.extend(b,{version:"2.1.5",defaults:{padding:15,margin:20, 26571width:800,height:600,minWidth:100,minHeight:100,maxWidth:9999,maxHeight:9999,pixelRatio:1,autoSize:!0,autoHeight:!1,autoWidth:!1,autoResize:!0,autoCenter:!t,fitToView:!0,aspectRatio:!1,topRatio:0.5,leftRatio:0.5,scrolling:"auto",wrapCSS:"",arrows:!0,closeBtn:!0,closeClick:!1,nextClick:!1,mouseWheel:!0,autoPlay:!1,playSpeed:3E3,preload:3,modal:!1,loop:!0,ajax:{dataType:"html",headers:{"X-fancyBox":!0}},iframe:{scrolling:"auto",preload:!0},swf:{wmode:"transparent",allowfullscreen:"true",allowscriptaccess:"always"}, 26572keys:{next:{13:"left",34:"up",39:"left",40:"up"},prev:{8:"right",33:"down",37:"right",38:"down"},close:[27],play:[32],toggle:[70]},direction:{next:"left",prev:"right"},scrollOutside:!0,index:0,type:null,href:null,content:null,title:null,tpl:{wrap:'<div class="fancybox-wrap" tabIndex="-1"><div class="fancybox-skin"><div class="fancybox-outer"><div class="fancybox-inner"></div></div></div></div>',image:'<img class="fancybox-image" src="{href}" alt="" />',iframe:'<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" frameborder="0" vspace="0" hspace="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen'+ 26573(J?' allowtransparency="true"':"")+"></iframe>",error:'<p class="fancybox-error">The requested content cannot be loaded.<br/>Please try again later.</p>',closeBtn:'<a title="Close" class="fancybox-item fancybox-close" href="javascript:;"></a>',next:'<a title="Next" class="fancybox-nav fancybox-next" href="javascript:;"><span></span></a>',prev:'<a title="Previous" class="fancybox-nav fancybox-prev" href="javascript:;"><span></span></a>'},openEffect:"fade",openSpeed:250,openEasing:"swing",openOpacity:!0, 26574openMethod:"zoomIn",closeEffect:"fade",closeSpeed:250,closeEasing:"swing",closeOpacity:!0,closeMethod:"zoomOut",nextEffect:"elastic",nextSpeed:250,nextEasing:"swing",nextMethod:"changeIn",prevEffect:"elastic",prevSpeed:250,prevEasing:"swing",prevMethod:"changeOut",helpers:{overlay:!0,title:!0},onCancel:f.noop,beforeLoad:f.noop,afterLoad:f.noop,beforeShow:f.noop,afterShow:f.noop,beforeChange:f.noop,beforeClose:f.noop,afterClose:f.noop},group:{},opts:{},previous:null,coming:null,current:null,isActive:!1, 26575isOpen:!1,isOpened:!1,wrap:null,skin:null,outer:null,inner:null,player:{timer:null,isActive:!1},ajaxLoad:null,imgPreload:null,transitions:{},helpers:{},open:function(a,d){if(a&&(f.isPlainObject(d)||(d={}),!1!==b.close(!0)))return f.isArray(a)||(a=u(a)?f(a).get():[a]),f.each(a,function(e,c){var l={},g,h,k,n,m;"object"===f.type(c)&&(c.nodeType&&(c=f(c)),u(c)?(l={href:c.data("fancybox-href")||c.attr("href"),title:f("<div/>").text(c.data("fancybox-title")||c.attr("title")).html(),isDom:!0,element:c}, 26576f.metadata&&f.extend(!0,l,c.metadata())):l=c);g=d.href||l.href||(r(c)?c:null);h=d.title!==w?d.title:l.title||"";n=(k=d.content||l.content)?"html":d.type||l.type;!n&&l.isDom&&(n=c.data("fancybox-type"),n||(n=(n=c.prop("class").match(/fancybox\.(\w+)/))?n[1]:null));r(g)&&(n||(b.isImage(g)?n="image":b.isSWF(g)?n="swf":"#"===g.charAt(0)?n="inline":r(c)&&(n="html",k=c)),"ajax"===n&&(m=g.split(/\s+/,2),g=m.shift(),m=m.shift()));k||("inline"===n?g?k=f(r(g)?g.replace(/.*(?=#[^\s]+$)/,""):g):l.isDom&&(k=c): 26577"html"===n?k=g:n||g||!l.isDom||(n="inline",k=c));f.extend(l,{href:g,type:n,content:k,title:h,selector:m});a[e]=l}),b.opts=f.extend(!0,{},b.defaults,d),d.keys!==w&&(b.opts.keys=d.keys?f.extend({},b.defaults.keys,d.keys):!1),b.group=a,b._start(b.opts.index)},cancel:function(){var a=b.coming;a&&!1===b.trigger("onCancel")||(b.hideLoading(),a&&(b.ajaxLoad&&b.ajaxLoad.abort(),b.ajaxLoad=null,b.imgPreload&&(b.imgPreload.onload=b.imgPreload.onerror=null),a.wrap&&a.wrap.stop(!0,!0).trigger("onReset").remove(), 26578b.coming=null,b.current||b._afterZoomOut(a)))},close:function(a){b.cancel();!1!==b.trigger("beforeClose")&&(b.unbindEvents(),b.isActive&&(b.isOpen&&!0!==a?(b.isOpen=b.isOpened=!1,b.isClosing=!0,f(".fancybox-item, .fancybox-nav").remove(),b.wrap.stop(!0,!0).removeClass("fancybox-opened"),b.transitions[b.current.closeMethod]()):(f(".fancybox-wrap").stop(!0).trigger("onReset").remove(),b._afterZoomOut())))},play:function(a){var d=function(){clearTimeout(b.player.timer)},e=function(){d();b.current&&b.player.isActive&& 26579(b.player.timer=setTimeout(b.next,b.current.playSpeed))},c=function(){d();p.unbind(".player");b.player.isActive=!1;b.trigger("onPlayEnd")};!0===a||!b.player.isActive&&!1!==a?b.current&&(b.current.loop||b.current.index<b.group.length-1)&&(b.player.isActive=!0,p.bind({"onCancel.player beforeClose.player":c,"onUpdate.player":e,"beforeLoad.player":d}),e(),b.trigger("onPlayStart")):c()},next:function(a){var d=b.current;d&&(r(a)||(a=d.direction.next),b.jumpto(d.index+1,a,"next"))},prev:function(a){var d= 26580b.current;d&&(r(a)||(a=d.direction.prev),b.jumpto(d.index-1,a,"prev"))},jumpto:function(a,d,e){var c=b.current;c&&(a=m(a),b.direction=d||c.direction[a>=c.index?"next":"prev"],b.router=e||"jumpto",c.loop&&(0>a&&(a=c.group.length+a%c.group.length),a%=c.group.length),c.group[a]!==w&&(b.cancel(),b._start(a)))},reposition:function(a,d){var e=b.current,c=e?e.wrap:null,l;c&&(l=b._getPosition(d),a&&"scroll"===a.type?(delete l.position,c.stop(!0,!0).animate(l,200)):(c.css(l),e.pos=f.extend({},e.dim,l)))}, 26581update:function(a){var d=a&&a.originalEvent&&a.originalEvent.type,e=!d||"orientationchange"===d;e&&(clearTimeout(C),C=null);b.isOpen&&!C&&(C=setTimeout(function(){var c=b.current;c&&!b.isClosing&&(b.wrap.removeClass("fancybox-tmp"),(e||"load"===d||"resize"===d&&c.autoResize)&&b._setDimension(),"scroll"===d&&c.canShrink||b.reposition(a),b.trigger("onUpdate"),C=null)},e&&!t?0:300))},toggle:function(a){b.isOpen&&(b.current.fitToView="boolean"===f.type(a)?a:!b.current.fitToView,t&&(b.wrap.removeAttr("style").addClass("fancybox-tmp"), 26582b.trigger("onUpdate")),b.update())},hideLoading:function(){p.unbind(".loading");f("#fancybox-loading").remove()},showLoading:function(){var a,d;b.hideLoading();a=f('<div id="fancybox-loading"><div></div></div>').click(b.cancel).appendTo("body");p.bind("keydown.loading",function(a){27===(a.which||a.keyCode)&&(a.preventDefault(),b.cancel())});b.defaults.fixed||(d=b.getViewport(),a.css({position:"absolute",top:0.5*d.h+d.y,left:0.5*d.w+d.x}));b.trigger("onLoading")},getViewport:function(){var a=b.current&& 26583b.current.locked||!1,d={x:q.scrollLeft(),y:q.scrollTop()};a&&a.length?(d.w=a[0].clientWidth,d.h=a[0].clientHeight):(d.w=t&&s.innerWidth?s.innerWidth:q.width(),d.h=t&&s.innerHeight?s.innerHeight:q.height());return d},unbindEvents:function(){b.wrap&&u(b.wrap)&&b.wrap.unbind(".fb");p.unbind(".fb");q.unbind(".fb")},bindEvents:function(){var a=b.current,d;a&&(q.bind("orientationchange.fb"+(t?"":" resize.fb")+(a.autoCenter&&!a.locked?" scroll.fb":""),b.update),(d=a.keys)&&p.bind("keydown.fb",function(e){var c= 26584e.which||e.keyCode,l=e.target||e.srcElement;if(27===c&&b.coming)return!1;e.ctrlKey||e.altKey||e.shiftKey||e.metaKey||l&&(l.type||f(l).is("[contenteditable]"))||f.each(d,function(d,l){if(1<a.group.length&&l[c]!==w)return b[d](l[c]),e.preventDefault(),!1;if(-1<f.inArray(c,l))return b[d](),e.preventDefault(),!1})}),f.fn.mousewheel&&a.mouseWheel&&b.wrap.bind("mousewheel.fb",function(d,c,l,g){for(var h=f(d.target||null),k=!1;h.length&&!(k||h.is(".fancybox-skin")||h.is(".fancybox-wrap"));)k=h[0]&&!(h[0].style.overflow&& 26585"hidden"===h[0].style.overflow)&&(h[0].clientWidth&&h[0].scrollWidth>h[0].clientWidth||h[0].clientHeight&&h[0].scrollHeight>h[0].clientHeight),h=f(h).parent();0!==c&&!k&&1<b.group.length&&!a.canShrink&&(0<g||0<l?b.prev(0<g?"down":"left"):(0>g||0>l)&&b.next(0>g?"up":"right"),d.preventDefault())}))},trigger:function(a,d){var e,c=d||b.coming||b.current;if(c){f.isFunction(c[a])&&(e=c[a].apply(c,Array.prototype.slice.call(arguments,1)));if(!1===e)return!1;c.helpers&&f.each(c.helpers,function(d,e){if(e&& 26586b.helpers[d]&&f.isFunction(b.helpers[d][a]))b.helpers[d][a](f.extend(!0,{},b.helpers[d].defaults,e),c)})}p.trigger(a)},isImage:function(a){return r(a)&&a.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i)},isSWF:function(a){return r(a)&&a.match(/\.(swf)((\?|#).*)?$/i)},_start:function(a){var d={},e,c;a=m(a);e=b.group[a]||null;if(!e)return!1;d=f.extend(!0,{},b.opts,e);e=d.margin;c=d.padding;"number"===f.type(e)&&(d.margin=[e,e,e,e]);"number"===f.type(c)&&(d.padding=[c,c, 26587c,c]);d.modal&&f.extend(!0,d,{closeBtn:!1,closeClick:!1,nextClick:!1,arrows:!1,mouseWheel:!1,keys:null,helpers:{overlay:{closeClick:!1}}});d.autoSize&&(d.autoWidth=d.autoHeight=!0);"auto"===d.width&&(d.autoWidth=!0);"auto"===d.height&&(d.autoHeight=!0);d.group=b.group;d.index=a;b.coming=d;if(!1===b.trigger("beforeLoad"))b.coming=null;else{c=d.type;e=d.href;if(!c)return b.coming=null,b.current&&b.router&&"jumpto"!==b.router?(b.current.index=a,b[b.router](b.direction)):!1;b.isActive=!0;if("image"=== 26588c||"swf"===c)d.autoHeight=d.autoWidth=!1,d.scrolling="visible";"image"===c&&(d.aspectRatio=!0);"iframe"===c&&t&&(d.scrolling="scroll");d.wrap=f(d.tpl.wrap).addClass("fancybox-"+(t?"mobile":"desktop")+" fancybox-type-"+c+" fancybox-tmp "+d.wrapCSS).appendTo(d.parent||"body");f.extend(d,{skin:f(".fancybox-skin",d.wrap),outer:f(".fancybox-outer",d.wrap),inner:f(".fancybox-inner",d.wrap)});f.each(["Top","Right","Bottom","Left"],function(a,b){d.skin.css("padding"+b,x(d.padding[a]))});b.trigger("onReady"); 26589if("inline"===c||"html"===c){if(!d.content||!d.content.length)return b._error("content")}else if(!e)return b._error("href");"image"===c?b._loadImage():"ajax"===c?b._loadAjax():"iframe"===c?b._loadIframe():b._afterLoad()}},_error:function(a){f.extend(b.coming,{type:"html",autoWidth:!0,autoHeight:!0,minWidth:0,minHeight:0,scrolling:"no",hasError:a,content:b.coming.tpl.error});b._afterLoad()},_loadImage:function(){var a=b.imgPreload=new Image;a.onload=function(){this.onload=this.onerror=null;b.coming.width= 26590this.width/b.opts.pixelRatio;b.coming.height=this.height/b.opts.pixelRatio;b._afterLoad()};a.onerror=function(){this.onload=this.onerror=null;b._error("image")};a.src=b.coming.href;!0!==a.complete&&b.showLoading()},_loadAjax:function(){var a=b.coming;b.showLoading();b.ajaxLoad=f.ajax(f.extend({},a.ajax,{url:a.href,error:function(a,e){b.coming&&"abort"!==e?b._error("ajax",a):b.hideLoading()},success:function(d,e){"success"===e&&(a.content=d,b._afterLoad())}}))},_loadIframe:function(){var a=b.coming, 26591d=f(a.tpl.iframe.replace(/\{rnd\}/g,(new Date).getTime())).attr("scrolling",t?"auto":a.iframe.scrolling).attr("src",a.href);f(a.wrap).bind("onReset",function(){try{f(this).find("iframe").hide().attr("src","//about:blank").end().empty()}catch(a){}});a.iframe.preload&&(b.showLoading(),d.one("load",function(){f(this).data("ready",1);t||f(this).bind("load.fb",b.update);f(this).parents(".fancybox-wrap").width("100%").removeClass("fancybox-tmp").show();b._afterLoad()}));a.content=d.appendTo(a.inner);a.iframe.preload|| 26592b._afterLoad()},_preloadImages:function(){var a=b.group,d=b.current,e=a.length,c=d.preload?Math.min(d.preload,e-1):0,f,g;for(g=1;g<=c;g+=1)f=a[(d.index+g)%e],"image"===f.type&&f.href&&((new Image).src=f.href)},_afterLoad:function(){var a=b.coming,d=b.current,e,c,l,g,h;b.hideLoading();if(a&&!1!==b.isActive)if(!1===b.trigger("afterLoad",a,d))a.wrap.stop(!0).trigger("onReset").remove(),b.coming=null;else{d&&(b.trigger("beforeChange",d),d.wrap.stop(!0).removeClass("fancybox-opened").find(".fancybox-item, .fancybox-nav").remove()); 26593b.unbindEvents();e=a.content;c=a.type;l=a.scrolling;f.extend(b,{wrap:a.wrap,skin:a.skin,outer:a.outer,inner:a.inner,current:a,previous:d});g=a.href;switch(c){case "inline":case "ajax":case "html":a.selector?e=f("<div>").html(e).find(a.selector):u(e)&&(e.data("fancybox-placeholder")||e.data("fancybox-placeholder",f('<div class="fancybox-placeholder"></div>').insertAfter(e).hide()),e=e.show().detach(),a.wrap.bind("onReset",function(){f(this).find(e).length&&e.hide().replaceAll(e.data("fancybox-placeholder")).data("fancybox-placeholder", 26594!1)}));break;case "image":e=a.tpl.image.replace(/\{href\}/g,g);break;case "swf":e='<object id="fancybox-swf" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%"><param name="movie" value="'+g+'"></param>',h="",f.each(a.swf,function(a,b){e+='<param name="'+a+'" value="'+b+'"></param>';h+=" "+a+'="'+b+'"'}),e+='<embed src="'+g+'" type="application/x-shockwave-flash" width="100%" height="100%"'+h+"></embed></object>"}u(e)&&e.parent().is(a.inner)||a.inner.append(e);b.trigger("beforeShow"); 26595a.inner.css("overflow","yes"===l?"scroll":"no"===l?"hidden":l);b._setDimension();b.reposition();b.isOpen=!1;b.coming=null;b.bindEvents();if(!b.isOpened)f(".fancybox-wrap").not(a.wrap).stop(!0).trigger("onReset").remove();else if(d.prevMethod)b.transitions[d.prevMethod]();b.transitions[b.isOpened?a.nextMethod:a.openMethod]();b._preloadImages()}},_setDimension:function(){var a=b.getViewport(),d=0,e=!1,c=!1,e=b.wrap,l=b.skin,g=b.inner,h=b.current,c=h.width,k=h.height,n=h.minWidth,v=h.minHeight,p=h.maxWidth, 26596q=h.maxHeight,t=h.scrolling,r=h.scrollOutside?h.scrollbarWidth:0,y=h.margin,z=m(y[1]+y[3]),s=m(y[0]+y[2]),w,A,u,D,B,G,C,E,I;e.add(l).add(g).width("auto").height("auto").removeClass("fancybox-tmp");y=m(l.outerWidth(!0)-l.width());w=m(l.outerHeight(!0)-l.height());A=z+y;u=s+w;D=F(c)?(a.w-A)*m(c)/100:c;B=F(k)?(a.h-u)*m(k)/100:k;if("iframe"===h.type){if(I=h.content,h.autoHeight&&1===I.data("ready"))try{I[0].contentWindow.document.location&&(g.width(D).height(9999),G=I.contents().find("body"),r&&G.css("overflow-x", 26597"hidden"),B=G.outerHeight(!0))}catch(H){}}else if(h.autoWidth||h.autoHeight)g.addClass("fancybox-tmp"),h.autoWidth||g.width(D),h.autoHeight||g.height(B),h.autoWidth&&(D=g.width()),h.autoHeight&&(B=g.height()),g.removeClass("fancybox-tmp");c=m(D);k=m(B);E=D/B;n=m(F(n)?m(n,"w")-A:n);p=m(F(p)?m(p,"w")-A:p);v=m(F(v)?m(v,"h")-u:v);q=m(F(q)?m(q,"h")-u:q);G=p;C=q;h.fitToView&&(p=Math.min(a.w-A,p),q=Math.min(a.h-u,q));A=a.w-z;s=a.h-s;h.aspectRatio?(c>p&&(c=p,k=m(c/E)),k>q&&(k=q,c=m(k*E)),c<n&&(c=n,k=m(c/ 26598E)),k<v&&(k=v,c=m(k*E))):(c=Math.max(n,Math.min(c,p)),h.autoHeight&&"iframe"!==h.type&&(g.width(c),k=g.height()),k=Math.max(v,Math.min(k,q)));if(h.fitToView)if(g.width(c).height(k),e.width(c+y),a=e.width(),z=e.height(),h.aspectRatio)for(;(a>A||z>s)&&c>n&&k>v&&!(19<d++);)k=Math.max(v,Math.min(q,k-10)),c=m(k*E),c<n&&(c=n,k=m(c/E)),c>p&&(c=p,k=m(c/E)),g.width(c).height(k),e.width(c+y),a=e.width(),z=e.height();else c=Math.max(n,Math.min(c,c-(a-A))),k=Math.max(v,Math.min(k,k-(z-s)));r&&"auto"===t&&k<B&& 26599c+y+r<A&&(c+=r);g.width(c).height(k);e.width(c+y);a=e.width();z=e.height();e=(a>A||z>s)&&c>n&&k>v;c=h.aspectRatio?c<G&&k<C&&c<D&&k<B:(c<G||k<C)&&(c<D||k<B);f.extend(h,{dim:{width:x(a),height:x(z)},origWidth:D,origHeight:B,canShrink:e,canExpand:c,wPadding:y,hPadding:w,wrapSpace:z-l.outerHeight(!0),skinSpace:l.height()-k});!I&&h.autoHeight&&k>v&&k<q&&!c&&g.height("auto")},_getPosition:function(a){var d=b.current,e=b.getViewport(),c=d.margin,f=b.wrap.width()+c[1]+c[3],g=b.wrap.height()+c[0]+c[2],c={position:"absolute", 26600top:c[0],left:c[3]};d.autoCenter&&d.fixed&&!a&&g<=e.h&&f<=e.w?c.position="fixed":d.locked||(c.top+=e.y,c.left+=e.x);c.top=x(Math.max(c.top,c.top+(e.h-g)*d.topRatio));c.left=x(Math.max(c.left,c.left+(e.w-f)*d.leftRatio));return c},_afterZoomIn:function(){var a=b.current;a&&((b.isOpen=b.isOpened=!0,b.wrap.css("overflow","visible").addClass("fancybox-opened"),b.update(),(a.closeClick||a.nextClick&&1<b.group.length)&&b.inner.css("cursor","pointer").bind("click.fb",function(d){f(d.target).is("a")||f(d.target).parent().is("a")|| 26601(d.preventDefault(),b[a.closeClick?"close":"next"]())}),a.closeBtn&&f(a.tpl.closeBtn).appendTo(b.skin).bind("click.fb",function(a){a.preventDefault();b.close()}),a.arrows&&1<b.group.length&&((a.loop||0<a.index)&&f(a.tpl.prev).appendTo(b.outer).bind("click.fb",b.prev),(a.loop||a.index<b.group.length-1)&&f(a.tpl.next).appendTo(b.outer).bind("click.fb",b.next)),b.trigger("afterShow"),a.loop||a.index!==a.group.length-1)?b.opts.autoPlay&&!b.player.isActive&&(b.opts.autoPlay=!1,b.play(!0)):b.play(!1))}, 26602_afterZoomOut:function(a){a=a||b.current;f(".fancybox-wrap").trigger("onReset").remove();f.extend(b,{group:{},opts:{},router:!1,current:null,isActive:!1,isOpened:!1,isOpen:!1,isClosing:!1,wrap:null,skin:null,outer:null,inner:null});b.trigger("afterClose",a)}});b.transitions={getOrigPosition:function(){var a=b.current,d=a.element,e=a.orig,c={},f=50,g=50,h=a.hPadding,k=a.wPadding,n=b.getViewport();!e&&a.isDom&&d.is(":visible")&&(e=d.find("img:first"),e.length||(e=d));u(e)?(c=e.offset(),e.is("img")&& 26603(f=e.outerWidth(),g=e.outerHeight())):(c.top=n.y+(n.h-g)*a.topRatio,c.left=n.x+(n.w-f)*a.leftRatio);if("fixed"===b.wrap.css("position")||a.locked)c.top-=n.y,c.left-=n.x;return c={top:x(c.top-h*a.topRatio),left:x(c.left-k*a.leftRatio),width:x(f+k),height:x(g+h)}},step:function(a,d){var e,c,f=d.prop;c=b.current;var g=c.wrapSpace,h=c.skinSpace;if("width"===f||"height"===f)e=d.end===d.start?1:(a-d.start)/(d.end-d.start),b.isClosing&&(e=1-e),c="width"===f?c.wPadding:c.hPadding,c=a-c,b.skin[f](m("width"=== 26604f?c:c-g*e)),b.inner[f](m("width"===f?c:c-g*e-h*e))},zoomIn:function(){var a=b.current,d=a.pos,e=a.openEffect,c="elastic"===e,l=f.extend({opacity:1},d);delete l.position;c?(d=this.getOrigPosition(),a.openOpacity&&(d.opacity=0.1)):"fade"===e&&(d.opacity=0.1);b.wrap.css(d).animate(l,{duration:"none"===e?0:a.openSpeed,easing:a.openEasing,step:c?this.step:null,complete:b._afterZoomIn})},zoomOut:function(){var a=b.current,d=a.closeEffect,e="elastic"===d,c={opacity:0.1};e&&(c=this.getOrigPosition(),a.closeOpacity&& 26605(c.opacity=0.1));b.wrap.animate(c,{duration:"none"===d?0:a.closeSpeed,easing:a.closeEasing,step:e?this.step:null,complete:b._afterZoomOut})},changeIn:function(){var a=b.current,d=a.nextEffect,e=a.pos,c={opacity:1},f=b.direction,g;e.opacity=0.1;"elastic"===d&&(g="down"===f||"up"===f?"top":"left","down"===f||"right"===f?(e[g]=x(m(e[g])-200),c[g]="+=200px"):(e[g]=x(m(e[g])+200),c[g]="-=200px"));"none"===d?b._afterZoomIn():b.wrap.css(e).animate(c,{duration:a.nextSpeed,easing:a.nextEasing,complete:b._afterZoomIn})}, 26606changeOut:function(){var a=b.previous,d=a.prevEffect,e={opacity:0.1},c=b.direction;"elastic"===d&&(e["down"===c||"up"===c?"top":"left"]=("up"===c||"left"===c?"-":"+")+"=200px");a.wrap.animate(e,{duration:"none"===d?0:a.prevSpeed,easing:a.prevEasing,complete:function(){f(this).trigger("onReset").remove()}})}};b.helpers.overlay={defaults:{closeClick:!0,speedOut:200,showEarly:!0,css:{},locked:!t,fixed:!0},overlay:null,fixed:!1,el:f("html"),create:function(a){var d;a=f.extend({},this.defaults,a);this.overlay&& 26607this.close();d=b.coming?b.coming.parent:a.parent;this.overlay=f('<div class="fancybox-overlay"></div>').appendTo(d&&d.lenth?d:"body");this.fixed=!1;a.fixed&&b.defaults.fixed&&(this.overlay.addClass("fancybox-overlay-fixed"),this.fixed=!0)},open:function(a){var d=this;a=f.extend({},this.defaults,a);this.overlay?this.overlay.unbind(".overlay").width("auto").height("auto"):this.create(a);this.fixed||(q.bind("resize.overlay",f.proxy(this.update,this)),this.update());a.closeClick&&this.overlay.bind("click.overlay", 26608function(a){if(f(a.target).hasClass("fancybox-overlay"))return b.isActive?b.close():d.close(),!1});this.overlay.css(a.css).show()},close:function(){q.unbind("resize.overlay");this.el.hasClass("fancybox-lock")&&(f(".fancybox-margin").removeClass("fancybox-margin"),this.el.removeClass("fancybox-lock"),q.scrollTop(this.scrollV).scrollLeft(this.scrollH));f(".fancybox-overlay").remove().hide();f.extend(this,{overlay:null,fixed:!1})},update:function(){var a="100%",b;this.overlay.width(a).height("100%"); 26609J?(b=Math.max(H.documentElement.offsetWidth,H.body.offsetWidth),p.width()>b&&(a=p.width())):p.width()>q.width()&&(a=p.width());this.overlay.width(a).height(p.height())},onReady:function(a,b){var e=this.overlay;f(".fancybox-overlay").stop(!0,!0);e||this.create(a);a.locked&&this.fixed&&b.fixed&&(b.locked=this.overlay.append(b.wrap),b.fixed=!1);!0===a.showEarly&&this.beforeShow.apply(this,arguments)},beforeShow:function(a,b){b.locked&&!this.el.hasClass("fancybox-lock")&&(!1!==this.fixPosition&&f("*").filter(function(){return"fixed"=== 26610f(this).css("position")&&!f(this).hasClass("fancybox-overlay")&&!f(this).hasClass("fancybox-wrap")}).addClass("fancybox-margin"),this.el.addClass("fancybox-margin"),this.scrollV=q.scrollTop(),this.scrollH=q.scrollLeft(),this.el.addClass("fancybox-lock"),q.scrollTop(this.scrollV).scrollLeft(this.scrollH));this.open(a)},onUpdate:function(){this.fixed||this.update()},afterClose:function(a){this.overlay&&!b.coming&&this.overlay.fadeOut(a.speedOut,f.proxy(this.close,this))}};b.helpers.title={defaults:{type:"float", 26611position:"bottom"},beforeShow:function(a){var d=b.current,e=d.title,c=a.type;f.isFunction(e)&&(e=e.call(d.element,d));if(r(e)&&""!==f.trim(e)){d=f('<div class="fancybox-title fancybox-title-'+c+'-wrap">'+e+"</div>");switch(c){case "inside":c=b.skin;break;case "outside":c=b.wrap;break;case "over":c=b.inner;break;default:c=b.skin,d.appendTo("body"),J&&d.width(d.width()),d.wrapInner('<span class="child"></span>'),b.current.margin[2]+=Math.abs(m(d.css("margin-bottom")))}d["top"===a.position?"prependTo": 26612"appendTo"](c)}}};f.fn.fancybox=function(a){var d,e=f(this),c=this.selector||"",l=function(g){var h=f(this).blur(),k=d,l,m;g.ctrlKey||g.altKey||g.shiftKey||g.metaKey||h.is(".fancybox-wrap")||(l=a.groupAttr||"data-fancybox-group",m=h.attr(l),m||(l="rel",m=h.get(0)[l]),m&&""!==m&&"nofollow"!==m&&(h=c.length?f(c):e,h=h.filter("["+l+'="'+m+'"]'),k=h.index(this)),a.index=k,!1!==b.open(h,a)&&g.preventDefault())};a=a||{};d=a.index||0;c&&!1!==a.live?p.undelegate(c,"click.fb-start").delegate(c+":not('.fancybox-item, .fancybox-nav')", 26613"click.fb-start",l):e.unbind("click.fb-start").bind("click.fb-start",l);this.filter("[data-fancybox-start=1]").trigger("click");return this};p.ready(function(){var a,d;f.scrollbarWidth===w&&(f.scrollbarWidth=function(){var a=f('<div style="width:50px;height:50px;overflow:auto"><div/></div>').appendTo("body"),b=a.children(),b=b.innerWidth()-b.height(99).innerWidth();a.remove();return b});f.support.fixedPosition===w&&(f.support.fixedPosition=function(){var a=f('<div style="position:fixed;top:20px;"></div>').appendTo("body"), 26614b=20===a[0].offsetTop||15===a[0].offsetTop;a.remove();return b}());f.extend(b.defaults,{scrollbarWidth:f.scrollbarWidth(),fixed:f.support.fixedPosition,parent:f("body")});a=f(s).width();K.addClass("fancybox-lock-test");d=f(s).width();K.removeClass("fancybox-lock-test");f("<style type='text/css'>.fancybox-margin{margin-right:"+(d-a)+"px;}</style>").appendTo("head")})})(window,document,jQuery);
vendor: 7,728 bytes, lines 26614-26919
26614 26615/* 26616 * qTip2 - Pretty powerful tooltips - v3.0.2 26617 * http://qtip2.com 26618 * 26619 * Copyright (c) 2015 26620 * Released under the MIT licenses 26621 * http://jquery.org/license 26622 * 26623 * Date: Tue Dec 8 2015 07:16 GMT+0000 26624 * Plugins: tips modal viewport svg imagemap ie6 26625 * Styles: core basic css3 26626 */ 26627/*global window: false, jQuery: false, console: false, define: false */ 26628 26629/* Cache window, document, undefined */ 26630(function( window, document, undefined ) { 26631 26632// Uses AMD or browser globals to create a jQuery plugin. 26633(function( factory ) { 26634 "use strict"; 26635 if(typeof define === 'function' && define.amd) { 26636 define(['jquery'], factory); 26637 } 26638 else if(jQuery && !jQuery.fn.qtip) { 26639 factory(jQuery); 26640 } 26641} 26642(function($) { 26643 "use strict"; // Enable ECMAScript "strict" operation for this function. See more: http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/ 26644;// Munge the primitives - Paul Irish tip 26645var TRUE = true, 26646FALSE = false, 26647NULL = null, 26648 26649// Common variables 26650X = 'x', Y = 'y', 26651WIDTH = 'width', 26652HEIGHT = 'height', 26653 26654// Positioning sides 26655TOP = 'top', 26656LEFT = 'left', 26657BOTTOM = 'bottom', 26658RIGHT = 'right', 26659CENTER = 'center', 26660 26661// Position adjustment types 26662FLIP = 'flip', 26663FLIPINVERT = 'flipinvert', 26664SHIFT = 'shift', 26665 26666// Shortcut vars 26667QTIP, PROTOTYPE, CORNER, CHECKS, 26668PLUGINS = {}, 26669NAMESPACE = 'qtip', 26670ATTR_HAS = 'data-hasqtip', 26671ATTR_ID = 'data-qtip-id', 26672WIDGET = ['ui-widget', 'ui-tooltip'], 26673SELECTOR = '.'+NAMESPACE, 26674INACTIVE_EVENTS = 'click dblclick mousedown mouseup mousemove mouseleave mouseenter'.split(' '), 26675 26676CLASS_FIXED = NAMESPACE+'-fixed', 26677CLASS_DEFAULT = NAMESPACE + '-default', 26678CLASS_FOCUS = NAMESPACE + '-focus', 26679CLASS_HOVER = NAMESPACE + '-hover', 26680CLASS_DISABLED = NAMESPACE+'-disabled', 26681 26682replaceSuffix = '_replacedByqTip', 26683oldtitle = 'oldtitle', 26684trackingBound, 26685 26686// Browser detection 26687BROWSER = { 26688 /* 26689 * IE version detection 26690 * 26691 * Adapted from: http://ajaxian.com/archives/attack-of-the-ie-conditional-comment 26692 * Credit to James Padolsey for the original implemntation! 26693 */ 26694 ie: (function() { 26695 /* eslint-disable no-empty */ 26696 var v, i; 26697 for ( 26698 v = 4, i = document.createElement('div'); 26699 (i.innerHTML = '<!--[if gt IE ' + v + ']><i></i><![endif]-->') && i.getElementsByTagName('i')[0]; 26700 v+=1 26701 ) {} 26702 return v > 4 ? v : NaN; 26703 /* eslint-enable no-empty */ 26704 })(), 26705 26706 /* 26707 * iOS version detection 26708 */ 26709 iOS: parseFloat( 26710 ('' + (/CPU.*OS ([0-9_]{1,5})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent) || [0,''])[1]) 26711 .replace('undefined', '3_2').replace('_', '.').replace('_', '') 26712 ) || FALSE 26713}; 26714;function QTip(target, options, id, attr) { 26715 // Elements and ID 26716 this.id = id; 26717 this.target = target; 26718 this.tooltip = NULL; 26719 this.elements = { target: target }; 26720 26721 // Internal constructs 26722 this._id = NAMESPACE + '-' + id; 26723 this.timers = { img: {} }; 26724 this.options = options; 26725 this.plugins = {}; 26726 26727 // Cache object 26728 this.cache = { 26729 event: {}, 26730 target: $(), 26731 disabled: FALSE, 26732 attr: attr, 26733 onTooltip: FALSE, 26734 lastClass: '' 26735 }; 26736 26737 // Set the initial flags 26738 this.rendered = this.destroyed = this.disabled = this.waiting = 26739 this.hiddenDuringWait = this.positioning = this.triggering = FALSE; 26740} 26741PROTOTYPE = QTip.prototype; 26742 26743PROTOTYPE._when = function(deferreds) { 26744 return $.when.apply($, deferreds); 26745}; 26746 26747PROTOTYPE.render = function(show) { 26748 if(this.rendered || this.destroyed) { return this; } // If tooltip has already been rendered, exit 26749 26750 var self = this, 26751 options = this.options, 26752 cache = this.cache, 26753 elements = this.elements, 26754 text = options.content.text, 26755 title = options.content.title, 26756 button = options.content.button, 26757 posOptions = options.position, 26758 deferreds = []; 26759 26760 // Add ARIA attributes to target 26761 $.attr(this.target[0], 'aria-describedby', this._id); 26762 26763 // Create public position object that tracks current position corners 26764 cache.posClass = this._createPosClass( 26765 (this.position = { my: posOptions.my, at: posOptions.at }).my 26766 ); 26767 26768 // Create tooltip element 26769 this.tooltip = elements.tooltip = $('<div/>', { 26770 'id': this._id, 26771 'class': [ NAMESPACE, CLASS_DEFAULT, options.style.classes, cache.posClass ].join(' '), 26772 'width': options.style.width || '', 26773 'height': options.style.height || '', 26774 'tracking': posOptions.target === 'mouse' && posOptions.adjust.mouse, 26775 26776 /* ARIA specific attributes */ 26777 'role': 'alert', 26778 'aria-live': 'polite', 26779 'aria-atomic': FALSE, 26780 'aria-describedby': this._id + '-content', 26781 'aria-hidden': TRUE 26782 }) 26783 .toggleClass(CLASS_DISABLED, this.disabled) 26784 .attr(ATTR_ID, this.id) 26785 .data(NAMESPACE, this) 26786 .appendTo(posOptions.container) 26787 .append( 26788 // Create content element 26789 elements.content = $('<div />', { 26790 'class': NAMESPACE + '-content', 26791 'id': this._id + '-content', 26792 'aria-atomic': TRUE 26793 }) 26794 ); 26795 26796 // Set rendered flag and prevent redundant reposition calls for now 26797 this.rendered = -1; 26798 this.positioning = TRUE; 26799 26800 // Create title... 26801 if(title) { 26802 this._createTitle(); 26803 26804 // Update title only if its not a callback (called in toggle if so) 26805 if(!$.isFunction(title)) { 26806 deferreds.push( this._updateTitle(title, FALSE) ); 26807 } 26808 } 26809 26810 // Create button 26811 if(button) { this._createButton(); } 26812 26813 // Set proper rendered flag and update content if not a callback function (called in toggle) 26814 if(!$.isFunction(text)) { 26815 deferreds.push( this._updateContent(text, FALSE) ); 26816 } 26817 this.rendered = TRUE; 26818 26819 // Setup widget classes 26820 this._setWidget(); 26821 26822 // Initialize 'render' plugins 26823 $.each(PLUGINS, function(name) { 26824 var instance; 26825 if(this.initialize === 'render' && (instance = this(self))) { 26826 self.plugins[name] = instance; 26827 } 26828 }); 26829 26830 // Unassign initial events and assign proper events 26831 this._unassignEvents(); 26832 this._assignEvents(); 26833 26834 // When deferreds have completed 26835 this._when(deferreds).then(function() { 26836 // tooltiprender event 26837 self._trigger('render'); 26838 26839 // Reset flags 26840 self.positioning = FALSE; 26841 26842 // Show tooltip if not hidden during wait period 26843 if(!self.hiddenDuringWait && (options.show.ready || show)) { 26844 self.toggle(TRUE, cache.event, FALSE); 26845 } 26846 self.hiddenDuringWait = FALSE; 26847 }); 26848 26849 // Expose API 26850 QTIP.api[this.id] = this; 26851 26852 return this; 26853}; 26854 26855PROTOTYPE.destroy = function(immediate) { 26856 // Set flag the signify destroy is taking place to plugins 26857 // and ensure it only gets destroyed once! 26858 if(this.destroyed) { return this.target; } 26859 26860 function process() { 26861 if(this.destroyed) { return; } 26862 this.destroyed = TRUE; 26863 26864 var target = this.target, 26865 title = target.attr(oldtitle), 26866 timer; 26867 26868 // Destroy tooltip if rendered 26869 if(this.rendered) { 26870 this.tooltip.stop(1,0).find('*').remove().end().remove(); 26871 } 26872 26873 // Destroy all plugins 26874 $.each(this.plugins, function() { 26875 this.destroy && this.destroy(); 26876 }); 26877 26878 // Clear timers 26879 for (timer in this.timers) { 26880 if (this.timers.hasOwnProperty(timer)) { 26881 clearTimeout(this.timers[timer]); 26882 } 26883 } 26884 26885 // Remove api object and ARIA attributes 26886 target.removeData(NAMESPACE) 26887 .removeAttr(ATTR_ID) 26888 .removeAttr(ATTR_HAS) 26889 .removeAttr('aria-describedby'); 26890 26891 // Reset old title attribute if removed 26892 if(this.options.suppress && title) { 26893 target.attr('title', title).removeAttr(oldtitle); 26894 } 26895 26896 // Remove qTip events associated with this API 26897 this._unassignEvents(); 26898 26899 // Remove ID from used id objects, and delete object references 26900 // for better garbage collection and leak protection 26901 this.options = this.elements = this.cache = this.timers = 26902 this.plugins = this.mouse = NULL; 26903 26904 // Delete epoxsed API object 26905 delete QTIP.api[this.id]; 26906 } 26907 26908 // If an immediate destroy is needed 26909 if((immediate !== TRUE || this.triggering === 'hide') && this.rendered) { 26910 this.tooltip.one('tooltiphidden', $.proxy(process, this)); 26911 !this.triggering && this.hide(); 26912 } 26913 26914 // If we're not in the process of hiding... process 26915 else { process.call(this); } 26916 26917 return this.target; 26918}; 26919;
26919function invalidOpt(a) { 26920 return a === NULL || $.type(a) !== 'object'; 26921} 26922 26923function invalidContent(c) { 26924 return !($.isFunction(c) || c && c.attr) || c.length || $.type(c) === 'object' && (c.jquery || c.then
vendor: 13,218 bytes, lines 26924-27396
26924); 26925} 26926 26927// Option object sanitizer 26928function sanitizeOptions(opts) { 26929 var content, text, ajax, once; 26930 26931 if(invalidOpt(opts)) { return FALSE; } 26932 26933 if(invalidOpt(opts.metadata)) { 26934 opts.metadata = { type: opts.metadata }; 26935 } 26936 26937 if('content' in opts) { 26938 content = opts.content; 26939 26940 if(invalidOpt(content) || content.jquery || content.done) { 26941 text = invalidContent(content) ? FALSE : content; 26942 content = opts.content = { 26943 text: text 26944 }; 26945 } 26946 else { text = content.text; } 26947 26948 // DEPRECATED - Old content.ajax plugin functionality 26949 // Converts it into the proper Deferred syntax 26950 if('ajax' in content) { 26951 ajax = content.ajax; 26952 once = ajax && ajax.once !== FALSE; 26953 delete content.ajax; 26954 26955 content.text = function(event, api) { 26956 var loading = text || $(this).attr(api.options.content.attr) || 'Loading...', 26957 26958 deferred = $.ajax( 26959 $.extend({}, ajax, { context: api }) 26960 ) 26961 .then(ajax.success, NULL, ajax.error) 26962 .then(function(newContent) { 26963 if(newContent && once) { api.set('content.text', newContent); } 26964 return newContent; 26965 }, 26966 function(xhr, status, error) { 26967 if(api.destroyed || xhr.status === 0) { return; } 26968 api.set('content.text', status + ': ' + error); 26969 }); 26970 26971 return !once ? (api.set('content.text', loading), deferred) : loading; 26972 }; 26973 } 26974 26975 if('title' in content) { 26976 if($.isPlainObject(content.title)) { 26977 content.button = content.title.button; 26978 content.title = content.title.text; 26979 } 26980 26981 if(invalidContent(content.title || FALSE)) { 26982 content.title = FALSE; 26983 } 26984 } 26985 } 26986 26987 if('position' in opts && invalidOpt(opts.position)) { 26988 opts.position = { my: opts.position, at: opts.position }; 26989 } 26990 26991 if('show' in opts && invalidOpt(opts.show)) { 26992 opts.show = opts.show.jquery ? { target: opts.show } : 26993 opts.show === TRUE ? { ready: TRUE } : { event: opts.show }; 26994 } 26995 26996 if('hide' in opts && invalidOpt(opts.hide)) { 26997 opts.hide = opts.hide.jquery ? { target: opts.hide } : { event: opts.hide }; 26998 } 26999 27000 if('style' in opts && invalidOpt(opts.style)) { 27001 opts.style = { classes: opts.style }; 27002 } 27003 27004 // Sanitize plugin options 27005 $.each(PLUGINS, function() { 27006 this.sanitize && this.sanitize(opts); 27007 }); 27008 27009 return opts; 27010} 27011 27012// Setup builtin .set() option checks 27013CHECKS = PROTOTYPE.checks = { 27014 builtin: { 27015 // Core checks 27016 '^id$': function(obj, o, v, prev) { 27017 var id = v === TRUE ? QTIP.nextid : v, 27018 newId = NAMESPACE + '-' + id; 27019 27020 if(id !== FALSE && id.length > 0 && !$('#'+newId).length) { 27021 this._id = newId; 27022 27023 if(this.rendered) { 27024 this.tooltip[0].id = this._id; 27025 this.elements.content[0].id = this._id + '-content'; 27026 this.elements.title[0].id = this._id + '-title'; 27027 } 27028 } 27029 else { obj[o] = prev; } 27030 }, 27031 '^prerender': function(obj, o, v) { 27032 v && !this.rendered && this.render(this.options.show.ready); 27033 }, 27034 27035 // Content checks 27036 '^content.text$': function(obj, o, v) { 27037 this._updateContent(v); 27038 }, 27039 '^content.attr$': function(obj, o, v, prev) { 27040 if(this.options.content.text === this.target.attr(prev)) { 27041 this._updateContent( this.target.attr(v) ); 27042 } 27043 }, 27044 '^content.title$': function(obj, o, v) { 27045 // Remove title if content is null 27046 if(!v) { return this._removeTitle(); } 27047 27048 // If title isn't already created, create it now and update 27049 v && !this.elements.title && this._createTitle(); 27050 this._updateTitle(v); 27051 }, 27052 '^content.button$': function(obj, o, v) { 27053 this._updateButton(v); 27054 }, 27055 '^content.title.(text|button)$': function(obj, o, v) { 27056 this.set('content.'+o, v); // Backwards title.text/button compat 27057 }, 27058 27059 // Position checks 27060 '^position.(my|at)$': function(obj, o, v){ 27061 if('string' === typeof v) { 27062 this.position[o] = obj[o] = new CORNER(v, o === 'at'); 27063 } 27064 }, 27065 '^position.container$': function(obj, o, v){ 27066 this.rendered && this.tooltip.appendTo(v); 27067 }, 27068 27069 // Show checks 27070 '^show.ready$': function(obj, o, v) { 27071 v && (!this.rendered && this.render(TRUE) || this.toggle(TRUE)); 27072 }, 27073 27074 // Style checks 27075 '^style.classes$': function(obj, o, v, p) { 27076 this.rendered && this.tooltip.removeClass(p).addClass(v); 27077 }, 27078 '^style.(width|height)': function(obj, o, v) { 27079 this.rendered && this.tooltip.css(o, v); 27080 }, 27081 '^style.widget|content.title': function() { 27082 this.rendered && this._setWidget(); 27083 }, 27084 '^style.def': function(obj, o, v) { 27085 this.rendered && this.tooltip.toggleClass(CLASS_DEFAULT, !!v); 27086 }, 27087 27088 // Events check 27089 '^events.(render|show|move|hide|focus|blur)$': function(obj, o, v) { 27090 this.rendered && this.tooltip[($.isFunction(v) ? '' : 'un') + 'bind']('tooltip'+o, v); 27091 }, 27092 27093 // Properties which require event reassignment 27094 '^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)': function() { 27095 if(!this.rendered) { return; } 27096 27097 // Set tracking flag 27098 var posOptions = this.options.position; 27099 this.tooltip.attr('tracking', posOptions.target === 'mouse' && posOptions.adjust.mouse); 27100 27101 // Reassign events 27102 this._unassignEvents(); 27103 this._assignEvents(); 27104 } 27105 } 27106}; 27107 27108// Dot notation converter 27109function convertNotation(options, notation) { 27110 var i = 0, obj, option = options, 27111 27112 // Split notation into array 27113 levels = notation.split('.'); 27114 27115 // Loop through 27116 while(option = option[ levels[i++] ]) { 27117 if(i < levels.length) { obj = option; } 27118 } 27119 27120 return [obj || options, levels.pop()]; 27121} 27122 27123PROTOTYPE.get = function(notation) { 27124 if(this.destroyed) { return this; } 27125 27126 var o = convertNotation(this.options, notation.toLowerCase()), 27127 result = o[0][ o[1] ]; 27128 27129 return result.precedance ? result.string() : result; 27130}; 27131 27132function setCallback(notation, args) { 27133 var category, rule, match; 27134 27135 for(category in this.checks) { 27136 if (!this.checks.hasOwnProperty(category)) { continue; } 27137 27138 for(rule in this.checks[category]) { 27139 if (!this.checks[category].hasOwnProperty(rule)) { continue; } 27140 27141 if(match = (new RegExp(rule, 'i')).exec(notation)) { 27142 args.push(match); 27143 27144 if(category === 'builtin' || this.plugins[category]) { 27145 this.checks[category][rule].apply( 27146 this.plugins[category] || this, args 27147 ); 27148 } 27149 } 27150 } 27151 } 27152} 27153 27154var rmove = /^position\.(my|at|adjust|target|container|viewport)|style|content|show\.ready/i, 27155 rrender = /^prerender|show\.ready/i; 27156 27157PROTOTYPE.set = function(option, value) { 27158 if(this.destroyed) { return this; } 27159 27160 var rendered = this.rendered, 27161 reposition = FALSE, 27162 options = this.options, 27163 name; 27164 27165 // Convert singular option/value pair into object form 27166 if('string' === typeof option) { 27167 name = option; option = {}; option[name] = value; 27168 } 27169 else { option = $.extend({}, option); } 27170 27171 // Set all of the defined options to their new values 27172 $.each(option, function(notation, val) { 27173 if(rendered && rrender.test(notation)) { 27174 delete option[notation]; return; 27175 } 27176 27177 // Set new obj value 27178 var obj = convertNotation(options, notation.toLowerCase()), previous; 27179 previous = obj[0][ obj[1] ]; 27180 obj[0][ obj[1] ] = val && val.nodeType ? $(val) : val; 27181 27182 // Also check if we need to reposition 27183 reposition = rmove.test(notation) || reposition; 27184 27185 // Set the new params for the callback 27186 option[notation] = [obj[0], obj[1], val, previous]; 27187 }); 27188 27189 // Re-sanitize options 27190 sanitizeOptions(options); 27191 27192 /* 27193 * Execute any valid callbacks for the set options 27194 * Also set positioning flag so we don't get loads of redundant repositioning calls. 27195 */ 27196 this.positioning = TRUE; 27197 $.each(option, $.proxy(setCallback, this)); 27198 this.positioning = FALSE; 27199 27200 // Update position if needed 27201 if(this.rendered && this.tooltip[0].offsetWidth > 0 && reposition) { 27202 this.reposition( options.position.target === 'mouse' ? NULL : this.cache.event ); 27203 } 27204 27205 return this; 27206}; 27207;PROTOTYPE._update = function(content, element) { 27208 var self = this, 27209 cache = this.cache; 27210 27211 // Make sure tooltip is rendered and content is defined. If not return 27212 if(!this.rendered || !content) { return FALSE; } 27213 27214 // Use function to parse content 27215 if($.isFunction(content)) { 27216 content = content.call(this.elements.target, cache.event, this) || ''; 27217 } 27218 27219 // Handle deferred content 27220 if($.isFunction(content.then)) { 27221 cache.waiting = TRUE; 27222 return content.then(function(c) { 27223 cache.waiting = FALSE; 27224 return self._update(c, element); 27225 }, NULL, function(e) { 27226 return self._update(e, element); 27227 }); 27228 } 27229 27230 // If content is null... return false 27231 if(content === FALSE || !content && content !== '') { return FALSE; } 27232 27233 // Append new content if its a DOM array and show it if hidden 27234 if(content.jquery && content.length > 0) { 27235 element.empty().append( 27236 content.css({ display: 'block', visibility: 'visible' }) 27237 ); 27238 } 27239 27240 // Content is a regular string, insert the new content 27241 else { element.html(content); } 27242 27243 // Wait for content to be loaded, and reposition 27244 return this._waitForContent(element).then(function(images) { 27245 if(self.rendered && self.tooltip[0].offsetWidth > 0) { 27246 self.reposition(cache.event, !images.length); 27247 } 27248 }); 27249}; 27250 27251PROTOTYPE._waitForContent = function(element) { 27252 var cache = this.cache; 27253 27254 // Set flag 27255 cache.waiting = TRUE; 27256 27257 // If imagesLoaded is included, ensure images have loaded and return promise 27258 return ( $.fn.imagesLoaded ? element.imagesLoaded() : new $.Deferred().resolve([]) ) 27259 .done(function() { cache.waiting = FALSE; }) 27260 .promise(); 27261}; 27262 27263PROTOTYPE._updateContent = function(content, reposition) { 27264 this._update(content, this.elements.content, reposition); 27265}; 27266 27267PROTOTYPE._updateTitle = function(content, reposition) { 27268 if(this._update(content, this.elements.title, reposition) === FALSE) { 27269 this._removeTitle(FALSE); 27270 } 27271}; 27272 27273PROTOTYPE._createTitle = function() 27274{ 27275 var elements = this.elements, 27276 id = this._id+'-title'; 27277 27278 // Destroy previous title element, if present 27279 if(elements.titlebar) { this._removeTitle(); } 27280 27281 // Create title bar and title elements 27282 elements.titlebar = $('<div />', { 27283 'class': NAMESPACE + '-titlebar ' + (this.options.style.widget ? createWidgetClass('header') : '') 27284 }) 27285 .append( 27286 elements.title = $('<div />', { 27287 'id': id, 27288 'class': NAMESPACE + '-title', 27289 'aria-atomic': TRUE 27290 }) 27291 ) 27292 .insertBefore(elements.content) 27293 27294 // Button-specific events 27295 .delegate('.qtip-close', 'mousedown keydown mouseup keyup mouseout', function(event) { 27296 $(this).toggleClass('ui-state-active ui-state-focus', event.type.substr(-4) === 'down'); 27297 }) 27298 .delegate('.qtip-close', 'mouseover mouseout', function(event){ 27299 $(this).toggleClass('ui-state-hover', event.type === 'mouseover'); 27300 }); 27301 27302 // Create button if enabled 27303 if(this.options.content.button) { this._createButton(); } 27304}; 27305 27306PROTOTYPE._removeTitle = function(reposition) 27307{ 27308 var elements = this.elements; 27309 27310 if(elements.title) { 27311 elements.titlebar.remove(); 27312 elements.titlebar = elements.title = elements.button = NULL; 27313 27314 // Reposition if enabled 27315 if(reposition !== FALSE) { this.reposition(); } 27316 } 27317}; 27318;PROTOTYPE._createPosClass = function(my) { 27319 return NAMESPACE + '-pos-' + (my || this.options.position.my).abbrev(); 27320}; 27321 27322PROTOTYPE.reposition = function(event, effect) { 27323 if(!this.rendered || this.positioning || this.destroyed) { return this; } 27324 27325 // Set positioning flag 27326 this.positioning = TRUE; 27327 27328 var cache = this.cache, 27329 tooltip = this.tooltip, 27330 posOptions = this.options.position, 27331 target = posOptions.target, 27332 my = posOptions.my, 27333 at = posOptions.at, 27334 viewport = posOptions.viewport, 27335 container = posOptions.container, 27336 adjust = posOptions.adjust, 27337 method = adjust.method.split(' '), 27338 tooltipWidth = tooltip.outerWidth(FALSE), 27339 tooltipHeight = tooltip.outerHeight(FALSE), 27340 targetWidth = 0, 27341 targetHeight = 0, 27342 type = tooltip.css('position'), 27343 position = { left: 0, top: 0 }, 27344 visible = tooltip[0].offsetWidth > 0, 27345 isScroll = event && event.type === 'scroll', 27346 win = $(window), 27347 doc = container[0].ownerDocument, 27348 mouse = this.mouse, 27349 pluginCalculations, offset, adjusted, newClass; 27350 27351 // Check if absolute position was passed 27352 if($.isArray(target) && target.length === 2) { 27353 // Force left top and set position 27354 at = { x: LEFT, y: TOP }; 27355 position = { left: target[0], top: target[1] }; 27356 } 27357 27358 // Check if mouse was the target 27359 else if(target === 'mouse') { 27360 // Force left top to allow flipping 27361 at = { x: LEFT, y: TOP }; 27362 27363 // Use the mouse origin that caused the show event, if distance hiding is enabled 27364 if((!adjust.mouse || this.options.hide.distance) && cache.origin && cache.origin.pageX) { 27365 event = cache.origin; 27366 } 27367 27368 // Use cached event for resize/scroll events 27369 else if(!event || event && (event.type === 'resize' || event.type === 'scroll')) { 27370 event = cache.event; 27371 } 27372 27373 // Otherwise, use the cached mouse coordinates if available 27374 else if(mouse && mouse.pageX) { 27375 event = mouse; 27376 } 27377 27378 // Calculate body and container offset and take them into account below 27379 if(type !== 'static') { position = container.offset(); } 27380 if(doc.body.offsetWidth !== (window.innerWidth || doc.documentElement.clientWidth)) { 27381 offset = $(document.body).offset(); 27382 } 27383 27384 // Use event coordinates for position 27385 position = { 27386 left: event.pageX - position.left + (offset && offset.left || 0), 27387 top: event.pageY - position.top + (offset && offset.top || 0) 27388 }; 27389 27390 // Scroll events are a pain, some browsers 27391 if(adjust.mouse && isScroll && mouse) { 27392 position.left -= (mouse.scrollX || 0) - win.scrollLeft(); 27393 position.top -= (mouse.scrollY || 0) - win.scrollTop(); 27394 } 27395 } 27396
vendor: 8,382 bytes, lines 27397-27645
27397 // Target wasn't mouse or absolute... 27398 else { 27399 // Check if event targetting is being used 27400 if(target === 'event') { 27401 if(event && event.target && event.type !== 'scroll' && event.type !== 'resize') { 27402 cache.target = $(event.target); 27403 } 27404 else if(!event.target) { 27405 cache.target = this.elements.target; 27406 } 27407 } 27408 else if(target !== 'event'){ 27409 cache.target = $(target.jquery ? target : this.elements.target); 27410 } 27411 target = cache.target; 27412 27413 // Parse the target into a jQuery object and make sure there's an element present 27414 target = $(target).eq(0); 27415 if(target.length === 0) { return this; } 27416 27417 // Check if window or document is the target 27418 else if(target[0] === document || target[0] === window) { 27419 targetWidth = BROWSER.iOS ? window.innerWidth : target.width(); 27420 targetHeight = BROWSER.iOS ? window.innerHeight : target.height(); 27421 27422 if(target[0] === window) { 27423 position = { 27424 top: (viewport || target).scrollTop(), 27425 left: (viewport || target).scrollLeft() 27426 }; 27427 } 27428 } 27429 27430 // Check if the target is an <AREA> element 27431 else if(PLUGINS.imagemap && target.is('area')) { 27432 pluginCalculations = PLUGINS.imagemap(this, target, at, PLUGINS.viewport ? method : FALSE); 27433 } 27434 27435 // Check if the target is an SVG element 27436 else if(PLUGINS.svg && target && target[0].ownerSVGElement) { 27437 pluginCalculations = PLUGINS.svg(this, target, at, PLUGINS.viewport ? method : FALSE); 27438 } 27439 27440 // Otherwise use regular jQuery methods 27441 else { 27442 targetWidth = target.outerWidth(FALSE); 27443 targetHeight = target.outerHeight(FALSE); 27444 position = target.offset(); 27445 } 27446 27447 // Parse returned plugin values into proper variables 27448 if(pluginCalculations) { 27449 targetWidth = pluginCalculations.width; 27450 targetHeight = pluginCalculations.height; 27451 offset = pluginCalculations.offset; 27452 position = pluginCalculations.position; 27453 } 27454 27455 // Adjust position to take into account offset parents 27456 position = this.reposition.offset(target, position, container); 27457 27458 // Adjust for position.fixed tooltips (and also iOS scroll bug in v3.2-4.0 & v4.3-4.3.2) 27459 if(BROWSER.iOS > 3.1 && BROWSER.iOS < 4.1 || 27460 BROWSER.iOS >= 4.3 && BROWSER.iOS < 4.33 || 27461 !BROWSER.iOS && type === 'fixed' 27462 ){ 27463 position.left -= win.scrollLeft(); 27464 position.top -= win.scrollTop(); 27465 } 27466 27467 // Adjust position relative to target 27468 if(!pluginCalculations || pluginCalculations && pluginCalculations.adjustable !== FALSE) { 27469 position.left += at.x === RIGHT ? targetWidth : at.x === CENTER ? targetWidth / 2 : 0; 27470 position.top += at.y === BOTTOM ? targetHeight : at.y === CENTER ? targetHeight / 2 : 0; 27471 } 27472 } 27473 27474 // Adjust position relative to tooltip 27475 position.left += adjust.x + (my.x === RIGHT ? -tooltipWidth : my.x === CENTER ? -tooltipWidth / 2 : 0); 27476 position.top += adjust.y + (my.y === BOTTOM ? -tooltipHeight : my.y === CENTER ? -tooltipHeight / 2 : 0); 27477 27478 // Use viewport adjustment plugin if enabled 27479 if(PLUGINS.viewport) { 27480 adjusted = position.adjusted = PLUGINS.viewport( 27481 this, position, posOptions, targetWidth, targetHeight, tooltipWidth, tooltipHeight 27482 ); 27483 27484 // Apply offsets supplied by positioning plugin (if used) 27485 if(offset && adjusted.left) { position.left += offset.left; } 27486 if(offset && adjusted.top) { position.top += offset.top; } 27487 27488 // Apply any new 'my' position 27489 if(adjusted.my) { this.position.my = adjusted.my; } 27490 } 27491 27492 // Viewport adjustment is disabled, set values to zero 27493 else { position.adjusted = { left: 0, top: 0 }; } 27494 27495 // Set tooltip position class if it's changed 27496 if(cache.posClass !== (newClass = this._createPosClass(this.position.my))) { 27497 cache.posClass = newClass; 27498 tooltip.removeClass(cache.posClass).addClass(newClass); 27499 } 27500 27501 // tooltipmove event 27502 if(!this._trigger('move', [position, viewport.elem || viewport], event)) { return this; } 27503 delete position.adjusted; 27504 27505 // If effect is disabled, target it mouse, no animation is defined or positioning gives NaN out, set CSS directly 27506 if(effect === FALSE || !visible || isNaN(position.left) || isNaN(position.top) || target === 'mouse' || !$.isFunction(posOptions.effect)) { 27507 tooltip.css(position); 27508 } 27509 27510 // Use custom function if provided 27511 else if($.isFunction(posOptions.effect)) { 27512 posOptions.effect.call(tooltip, this, $.extend({}, position)); 27513 tooltip.queue(function(next) { 27514 // Reset attributes to avoid cross-browser rendering bugs 27515 $(this).css({ opacity: '', height: '' }); 27516 if(BROWSER.ie) { this.style.removeAttribute('filter'); } 27517 27518 next(); 27519 }); 27520 } 27521 27522 // Set positioning flag 27523 this.positioning = FALSE; 27524 27525 return this; 27526}; 27527 27528// Custom (more correct for qTip!) offset calculator 27529PROTOTYPE.reposition.offset = function(elem, pos, container) { 27530 if(!container[0]) { return pos; } 27531 27532 var ownerDocument = $(elem[0].ownerDocument), 27533 quirks = !!BROWSER.ie && document.compatMode !== 'CSS1Compat', 27534 parent = container[0], 27535 scrolled, position, parentOffset, overflow; 27536 27537 function scroll(e, i) { 27538 pos.left += i * e.scrollLeft(); 27539 pos.top += i * e.scrollTop(); 27540 } 27541 27542 // Compensate for non-static containers offset 27543 do { 27544 if((position = $.css(parent, 'position')) !== 'static') { 27545 if(position === 'fixed') { 27546 parentOffset = parent.getBoundingClientRect(); 27547 scroll(ownerDocument, -1); 27548 } 27549 else { 27550 parentOffset = $(parent).position(); 27551 parentOffset.left += parseFloat($.css(parent, 'borderLeftWidth')) || 0; 27552 parentOffset.top += parseFloat($.css(parent, 'borderTopWidth')) || 0; 27553 } 27554 27555 pos.left -= parentOffset.left + (parseFloat($.css(parent, 'marginLeft')) || 0); 27556 pos.top -= parentOffset.top + (parseFloat($.css(parent, 'marginTop')) || 0); 27557 27558 // If this is the first parent element with an overflow of "scroll" or "auto", store it 27559 if(!scrolled && (overflow = $.css(parent, 'overflow')) !== 'hidden' && overflow !== 'visible') { scrolled = $(parent); } 27560 } 27561 } 27562 while(parent = parent.offsetParent); 27563 27564 // Compensate for containers scroll if it also has an offsetParent (or in IE quirks mode) 27565 if(scrolled && (scrolled[0] !== ownerDocument[0] || quirks)) { 27566 scroll(scrolled, 1); 27567 } 27568 27569 return pos; 27570}; 27571 27572// Corner class 27573var C = (CORNER = PROTOTYPE.reposition.Corner = function(corner, forceY) { 27574 corner = ('' + corner).replace(/([A-Z])/, ' $1').replace(/middle/gi, CENTER).toLowerCase(); 27575 this.x = (corner.match(/left|right/i) || corner.match(/center/) || ['inherit'])[0].toLowerCase(); 27576 this.y = (corner.match(/top|bottom|center/i) || ['inherit'])[0].toLowerCase(); 27577 this.forceY = !!forceY; 27578 27579 var f = corner.charAt(0); 27580 this.precedance = f === 't' || f === 'b' ? Y : X; 27581}).prototype; 27582 27583C.invert = function(z, center) { 27584 this[z] = this[z] === LEFT ? RIGHT : this[z] === RIGHT ? LEFT : center || this[z]; 27585}; 27586 27587C.string = function(join) { 27588 var x = this.x, y = this.y; 27589 27590 var result = x !== y ? 27591 x === 'center' || y !== 'center' && (this.precedance === Y || this.forceY) ? 27592 [y,x] : 27593 [x,y] : 27594 [x]; 27595 27596 return join !== false ? result.join(' ') : result; 27597}; 27598 27599C.abbrev = function() { 27600 var result = this.string(false); 27601 return result[0].charAt(0) + (result[1] && result[1].charAt(0) || ''); 27602}; 27603 27604C.clone = function() { 27605 return new CORNER( this.string(), this.forceY ); 27606}; 27607 27608; 27609PROTOTYPE.toggle = function(state, event) { 27610 var cache = this.cache, 27611 options = this.options, 27612 tooltip = this.tooltip; 27613 27614 // Try to prevent flickering when tooltip overlaps show element 27615 if(event) { 27616 if((/over|enter/).test(event.type) && cache.event && (/out|leave/).test(cache.event.type) && 27617 options.show.target.add(event.target).length === options.show.target.length && 27618 tooltip.has(event.relatedTarget).length) { 27619 return this; 27620 } 27621 27622 // Cache event 27623 cache.event = $.event.fix(event); 27624 } 27625 27626 // If we're currently waiting and we've just hidden... stop it 27627 this.waiting && !state && (this.hiddenDuringWait = TRUE); 27628 27629 // Render the tooltip if showing and it isn't already 27630 if(!this.rendered) { return state ? this.render(1) : this; } 27631 else if(this.destroyed || this.disabled) { return this; } 27632 27633 var type = state ? 'show' : 'hide', 27634 opts = this.options[type], 27635 posOptions = this.options.position, 27636 contentOptions = this.options.content, 27637 width = this.tooltip.css('width'), 27638 visible = this.tooltip.is(':visible'), 27639 animate = state || opts.target.length === 1, 27640 sameTarget = !event || opts.target.length < 2 || cache.target[0] === event.target, 27641 identicalState, allow, after; 27642 27643 // Detect state if valid one isn't provided 27644 if((typeof state).search('boolean|number')) { state = !visible; } 27645
vendor: 23,703 bytes, lines 27646-28389
27646 // Check if the tooltip is in an identical state to the new would-be state 27647 identicalState = !tooltip.is(':animated') && visible === state && sameTarget; 27648 27649 // Fire tooltip(show/hide) event and check if destroyed 27650 allow = !identicalState ? !!this._trigger(type, [90]) : NULL; 27651 27652 // Check to make sure the tooltip wasn't destroyed in the callback 27653 if(this.destroyed) { return this; } 27654 27655 // If the user didn't stop the method prematurely and we're showing the tooltip, focus it 27656 if(allow !== FALSE && state) { this.focus(event); } 27657 27658 // If the state hasn't changed or the user stopped it, return early 27659 if(!allow || identicalState) { return this; } 27660 27661 // Set ARIA hidden attribute 27662 $.attr(tooltip[0], 'aria-hidden', !!!state); 27663 27664 // Execute state specific properties 27665 if(state) { 27666 // Store show origin coordinates 27667 this.mouse && (cache.origin = $.event.fix(this.mouse)); 27668 27669 // Update tooltip content & title if it's a dynamic function 27670 if($.isFunction(contentOptions.text)) { this._updateContent(contentOptions.text, FALSE); } 27671 if($.isFunction(contentOptions.title)) { this._updateTitle(contentOptions.title, FALSE); } 27672 27673 // Cache mousemove events for positioning purposes (if not already tracking) 27674 if(!trackingBound && posOptions.target === 'mouse' && posOptions.adjust.mouse) { 27675 $(document).bind('mousemove.'+NAMESPACE, this._storeMouse); 27676 trackingBound = TRUE; 27677 } 27678 27679 // Update the tooltip position (set width first to prevent viewport/max-width issues) 27680 if(!width) { tooltip.css('width', tooltip.outerWidth(FALSE)); } 27681 this.reposition(event, arguments[2]); 27682 if(!width) { tooltip.css('width', ''); } 27683 27684 // Hide other tooltips if tooltip is solo 27685 if(!!opts.solo) { 27686 (typeof opts.solo === 'string' ? $(opts.solo) : $(SELECTOR, opts.solo)) 27687 .not(tooltip).not(opts.target).qtip('hide', new $.Event('tooltipsolo')); 27688 } 27689 } 27690 else { 27691 // Clear show timer if we're hiding 27692 clearTimeout(this.timers.show); 27693 27694 // Remove cached origin on hide 27695 delete cache.origin; 27696 27697 // Remove mouse tracking event if not needed (all tracking qTips are hidden) 27698 if(trackingBound && !$(SELECTOR+'[tracking="true"]:visible', opts.solo).not(tooltip).length) { 27699 $(document).unbind('mousemove.'+NAMESPACE); 27700 trackingBound = FALSE; 27701 } 27702 27703 // Blur the tooltip 27704 this.blur(event); 27705 } 27706 27707 // Define post-animation, state specific properties 27708 after = $.proxy(function() { 27709 if(state) { 27710 // Prevent antialias from disappearing in IE by removing filter 27711 if(BROWSER.ie) { tooltip[0].style.removeAttribute('filter'); } 27712 27713 // Remove overflow setting to prevent tip bugs 27714 tooltip.css('overflow', ''); 27715 27716 // Autofocus elements if enabled 27717 if('string' === typeof opts.autofocus) { 27718 $(this.options.show.autofocus, tooltip).focus(); 27719 } 27720 27721 // If set, hide tooltip when inactive for delay period 27722 this.options.show.target.trigger('qtip-'+this.id+'-inactive'); 27723 } 27724 else { 27725 // Reset CSS states 27726 tooltip.css({ 27727 display: '', 27728 visibility: '', 27729 opacity: '', 27730 left: '', 27731 top: '' 27732 }); 27733 } 27734 27735 // tooltipvisible/tooltiphidden events 27736 this._trigger(state ? 'visible' : 'hidden'); 27737 }, this); 27738 27739 // If no effect type is supplied, use a simple toggle 27740 if(opts.effect === FALSE || animate === FALSE) { 27741 tooltip[ type ](); 27742 after(); 27743 } 27744 27745 // Use custom function if provided 27746 else if($.isFunction(opts.effect)) { 27747 tooltip.stop(1, 1); 27748 opts.effect.call(tooltip, this); 27749 tooltip.queue('fx', function(n) { 27750 after(); n(); 27751 }); 27752 } 27753 27754 // Use basic fade function by default 27755 else { tooltip.fadeTo(90, state ? 1 : 0, after); } 27756 27757 // If inactive hide method is set, active it 27758 if(state) { opts.target.trigger('qtip-'+this.id+'-inactive'); } 27759 27760 return this; 27761}; 27762 27763PROTOTYPE.show = function(event) { return this.toggle(TRUE, event); }; 27764 27765PROTOTYPE.hide = function(event) { return this.toggle(FALSE, event); }; 27766;PROTOTYPE.focus = function(event) { 27767 if(!this.rendered || this.destroyed) { return this; } 27768 27769 var qtips = $(SELECTOR), 27770 tooltip = this.tooltip, 27771 curIndex = parseInt(tooltip[0].style.zIndex, 10), 27772 newIndex = QTIP.zindex + qtips.length; 27773 27774 // Only update the z-index if it has changed and tooltip is not already focused 27775 if(!tooltip.hasClass(CLASS_FOCUS)) { 27776 // tooltipfocus event 27777 if(this._trigger('focus', [newIndex], event)) { 27778 // Only update z-index's if they've changed 27779 if(curIndex !== newIndex) { 27780 // Reduce our z-index's and keep them properly ordered 27781 qtips.each(function() { 27782 if(this.style.zIndex > curIndex) { 27783 this.style.zIndex = this.style.zIndex - 1; 27784 } 27785 }); 27786 27787 // Fire blur event for focused tooltip 27788 qtips.filter('.' + CLASS_FOCUS).qtip('blur', event); 27789 } 27790 27791 // Set the new z-index 27792 tooltip.addClass(CLASS_FOCUS)[0].style.zIndex = newIndex; 27793 } 27794 } 27795 27796 return this; 27797}; 27798 27799PROTOTYPE.blur = function(event) { 27800 if(!this.rendered || this.destroyed) { return this; } 27801 27802 // Set focused status to FALSE 27803 this.tooltip.removeClass(CLASS_FOCUS); 27804 27805 // tooltipblur event 27806 this._trigger('blur', [ this.tooltip.css('zIndex') ], event); 27807 27808 return this; 27809}; 27810;PROTOTYPE.disable = function(state) { 27811 if(this.destroyed) { return this; } 27812 27813 // If 'toggle' is passed, toggle the current state 27814 if(state === 'toggle') { 27815 state = !(this.rendered ? this.tooltip.hasClass(CLASS_DISABLED) : this.disabled); 27816 } 27817 27818 // Disable if no state passed 27819 else if('boolean' !== typeof state) { 27820 state = TRUE; 27821 } 27822 27823 if(this.rendered) { 27824 this.tooltip.toggleClass(CLASS_DISABLED, state) 27825 .attr('aria-disabled', state); 27826 } 27827 27828 this.disabled = !!state; 27829 27830 return this; 27831}; 27832 27833PROTOTYPE.enable = function() { return this.disable(FALSE); }; 27834;PROTOTYPE._createButton = function() 27835{ 27836 var self = this, 27837 elements = this.elements, 27838 tooltip = elements.tooltip, 27839 button = this.options.content.button, 27840 isString = typeof button === 'string', 27841 close = isString ? button : 'Close tooltip'; 27842 27843 if(elements.button) { elements.button.remove(); } 27844 27845 // Use custom button if one was supplied by user, else use default 27846 if(button.jquery) { 27847 elements.button = button; 27848 } 27849 else { 27850 elements.button = $('<a />', { 27851 'class': 'qtip-close ' + (this.options.style.widget ? '' : NAMESPACE+'-icon'), 27852 'title': close, 27853 'aria-label': close 27854 }) 27855 .prepend( 27856 $('<span />', { 27857 'class': 'ui-icon ui-icon-close', 27858 'html': '×' 27859 }) 27860 ); 27861 } 27862 27863 // Create button and setup attributes 27864 elements.button.appendTo(elements.titlebar || tooltip) 27865 .attr('role', 'button') 27866 .click(function(event) { 27867 if(!tooltip.hasClass(CLASS_DISABLED)) { self.hide(event); } 27868 return FALSE; 27869 }); 27870}; 27871 27872PROTOTYPE._updateButton = function(button) 27873{ 27874 // Make sure tooltip is rendered and if not, return 27875 if(!this.rendered) { return FALSE; } 27876 27877 var elem = this.elements.button; 27878 if(button) { this._createButton(); } 27879 else { elem.remove(); } 27880}; 27881;// Widget class creator 27882function createWidgetClass(cls) { 27883 return WIDGET.concat('').join(cls ? '-'+cls+' ' : ' '); 27884} 27885 27886// Widget class setter method 27887PROTOTYPE._setWidget = function() 27888{ 27889 var on = this.options.style.widget, 27890 elements = this.elements, 27891 tooltip = elements.tooltip, 27892 disabled = tooltip.hasClass(CLASS_DISABLED); 27893 27894 tooltip.removeClass(CLASS_DISABLED); 27895 CLASS_DISABLED = on ? 'ui-state-disabled' : 'qtip-disabled'; 27896 tooltip.toggleClass(CLASS_DISABLED, disabled); 27897 27898 tooltip.toggleClass('ui-helper-reset '+createWidgetClass(), on).toggleClass(CLASS_DEFAULT, this.options.style.def && !on); 27899 27900 if(elements.content) { 27901 elements.content.toggleClass( createWidgetClass('content'), on); 27902 } 27903 if(elements.titlebar) { 27904 elements.titlebar.toggleClass( createWidgetClass('header'), on); 27905 } 27906 if(elements.button) { 27907 elements.button.toggleClass(NAMESPACE+'-icon', !on); 27908 } 27909}; 27910;function delay(callback, duration) { 27911 // If tooltip has displayed, start hide timer 27912 if(duration > 0) { 27913 return setTimeout( 27914 $.proxy(callback, this), duration 27915 ); 27916 } 27917 else{ callback.call(this); } 27918} 27919 27920function showMethod(event) { 27921 if(this.tooltip.hasClass(CLASS_DISABLED)) { return; } 27922 27923 // Clear hide timers 27924 clearTimeout(this.timers.show); 27925 clearTimeout(this.timers.hide); 27926 27927 // Start show timer 27928 this.timers.show = delay.call(this, 27929 function() { this.toggle(TRUE, event); }, 27930 this.options.show.delay 27931 ); 27932} 27933 27934function hideMethod(event) { 27935 if(this.tooltip.hasClass(CLASS_DISABLED) || this.destroyed) { return; } 27936 27937 // Check if new target was actually the tooltip element 27938 var relatedTarget = $(event.relatedTarget), 27939 ontoTooltip = relatedTarget.closest(SELECTOR)[0] === this.tooltip[0], 27940 ontoTarget = relatedTarget[0] === this.options.show.target[0]; 27941 27942 // Clear timers and stop animation queue 27943 clearTimeout(this.timers.show); 27944 clearTimeout(this.timers.hide); 27945 27946 // Prevent hiding if tooltip is fixed and event target is the tooltip. 27947 // Or if mouse positioning is enabled and cursor momentarily overlaps 27948 if(this !== relatedTarget[0] && 27949 (this.options.position.target === 'mouse' && ontoTooltip) || 27950 this.options.hide.fixed && ( 27951 (/mouse(out|leave|move)/).test(event.type) && (ontoTooltip || ontoTarget)) 27952 ) 27953 { 27954 /* eslint-disable no-empty */ 27955 try { 27956 event.preventDefault(); 27957 event.stopImmediatePropagation(); 27958 } catch(e) {} 27959 /* eslint-enable no-empty */ 27960 27961 return; 27962 } 27963 27964 // If tooltip has displayed, start hide timer 27965 this.timers.hide = delay.call(this, 27966 function() { this.toggle(FALSE, event); }, 27967 this.options.hide.delay, 27968 this 27969 ); 27970} 27971 27972function inactiveMethod(event) { 27973 if(this.tooltip.hasClass(CLASS_DISABLED) || !this.options.hide.inactive) { return; } 27974 27975 // Clear timer 27976 clearTimeout(this.timers.inactive); 27977 27978 this.timers.inactive = delay.call(this, 27979 function(){ this.hide(event); }, 27980 this.options.hide.inactive 27981 ); 27982} 27983 27984function repositionMethod(event) { 27985 if(this.rendered && this.tooltip[0].offsetWidth > 0) { this.reposition(event); } 27986} 27987 27988// Store mouse coordinates 27989PROTOTYPE._storeMouse = function(event) { 27990 (this.mouse = $.event.fix(event)).type = 'mousemove'; 27991 return this; 27992}; 27993 27994// Bind events 27995PROTOTYPE._bind = function(targets, events, method, suffix, context) { 27996 if(!targets || !method || !events.length) { return; } 27997 var ns = '.' + this._id + (suffix ? '-'+suffix : ''); 27998 $(targets).bind( 27999 (events.split ? events : events.join(ns + ' ')) + ns, 28000 $.proxy(method, context || this) 28001 ); 28002 return this; 28003}; 28004PROTOTYPE._unbind = function(targets, suffix) { 28005 targets && $(targets).unbind('.' + this._id + (suffix ? '-'+suffix : '')); 28006 return this; 28007}; 28008 28009// Global delegation helper 28010function delegate(selector, events, method) { 28011 $(document.body).delegate(selector, 28012 (events.split ? events : events.join('.'+NAMESPACE + ' ')) + '.'+NAMESPACE, 28013 function() { 28014 var api = QTIP.api[ $.attr(this, ATTR_ID) ]; 28015 api && !api.disabled && method.apply(api, arguments); 28016 } 28017 ); 28018} 28019// Event trigger 28020PROTOTYPE._trigger = function(type, args, event) { 28021 var callback = new $.Event('tooltip'+type); 28022 callback.originalEvent = event && $.extend({}, event) || this.cache.event || NULL; 28023 28024 this.triggering = type; 28025 this.tooltip.trigger(callback, [this].concat(args || [])); 28026 this.triggering = FALSE; 28027 28028 return !callback.isDefaultPrevented(); 28029}; 28030 28031PROTOTYPE._bindEvents = function(showEvents, hideEvents, showTargets, hideTargets, showCallback, hideCallback) { 28032 // Get tasrgets that lye within both 28033 var similarTargets = showTargets.filter( hideTargets ).add( hideTargets.filter(showTargets) ), 28034 toggleEvents = []; 28035 28036 // If hide and show targets are the same... 28037 if(similarTargets.length) { 28038 28039 // Filter identical show/hide events 28040 $.each(hideEvents, function(i, type) { 28041 var showIndex = $.inArray(type, showEvents); 28042 28043 // Both events are identical, remove from both hide and show events 28044 // and append to toggleEvents 28045 showIndex > -1 && toggleEvents.push( showEvents.splice( showIndex, 1 )[0] ); 28046 }); 28047 28048 // Toggle events are special case of identical show/hide events, which happen in sequence 28049 if(toggleEvents.length) { 28050 // Bind toggle events to the similar targets 28051 this._bind(similarTargets, toggleEvents, function(event) { 28052 var state = this.rendered ? this.tooltip[0].offsetWidth > 0 : false; 28053 (state ? hideCallback : showCallback).call(this, event); 28054 }); 28055 28056 // Remove the similar targets from the regular show/hide bindings 28057 showTargets = showTargets.not(similarTargets); 28058 hideTargets = hideTargets.not(similarTargets); 28059 } 28060 } 28061 28062 // Apply show/hide/toggle events 28063 this._bind(showTargets, showEvents, showCallback); 28064 this._bind(hideTargets, hideEvents, hideCallback); 28065}; 28066 28067PROTOTYPE._assignInitialEvents = function(event) { 28068 var options = this.options, 28069 showTarget = options.show.target, 28070 hideTarget = options.hide.target, 28071 showEvents = options.show.event ? $.trim('' + options.show.event).split(' ') : [], 28072 hideEvents = options.hide.event ? $.trim('' + options.hide.event).split(' ') : []; 28073 28074 // Catch remove/removeqtip events on target element to destroy redundant tooltips 28075 this._bind(this.elements.target, ['remove', 'removeqtip'], function() { 28076 this.destroy(true); 28077 }, 'destroy'); 28078 28079 /* 28080 * Make sure hoverIntent functions properly by using mouseleave as a hide event if 28081 * mouseenter/mouseout is used for show.event, even if it isn't in the users options. 28082 */ 28083 if(/mouse(over|enter)/i.test(options.show.event) && !/mouse(out|leave)/i.test(options.hide.event)) { 28084 hideEvents.push('mouseleave'); 28085 } 28086 28087 /* 28088 * Also make sure initial mouse targetting works correctly by caching mousemove coords 28089 * on show targets before the tooltip has rendered. Also set onTarget when triggered to 28090 * keep mouse tracking working. 28091 */ 28092 this._bind(showTarget, 'mousemove', function(moveEvent) { 28093 this._storeMouse(moveEvent); 28094 this.cache.onTarget = TRUE; 28095 }); 28096 28097 // Define hoverIntent function 28098 function hoverIntent(hoverEvent) { 28099 // Only continue if tooltip isn't disabled 28100 if(this.disabled || this.destroyed) { return FALSE; } 28101 28102 // Cache the event data 28103 this.cache.event = hoverEvent && $.event.fix(hoverEvent); 28104 this.cache.target = hoverEvent && $(hoverEvent.target); 28105 28106 // Start the event sequence 28107 clearTimeout(this.timers.show); 28108 this.timers.show = delay.call(this, 28109 function() { this.render(typeof hoverEvent === 'object' || options.show.ready); }, 28110 options.prerender ? 0 : options.show.delay 28111 ); 28112 } 28113 28114 // Filter and bind events 28115 this._bindEvents(showEvents, hideEvents, showTarget, hideTarget, hoverIntent, function() { 28116 if(!this.timers) { return FALSE; } 28117 clearTimeout(this.timers.show); 28118 }); 28119 28120 // Prerendering is enabled, create tooltip now 28121 if(options.show.ready || options.prerender) { hoverIntent.call(this, event); } 28122}; 28123 28124// Event assignment method 28125PROTOTYPE._assignEvents = function() { 28126 var self = this, 28127 options = this.options, 28128 posOptions = options.position, 28129 28130 tooltip = this.tooltip, 28131 showTarget = options.show.target, 28132 hideTarget = options.hide.target, 28133 containerTarget = posOptions.container, 28134 viewportTarget = posOptions.viewport, 28135 documentTarget = $(document), 28136 windowTarget = $(window), 28137 28138 showEvents = options.show.event ? $.trim('' + options.show.event).split(' ') : [], 28139 hideEvents = options.hide.event ? $.trim('' + options.hide.event).split(' ') : []; 28140 28141 28142 // Assign passed event callbacks 28143 $.each(options.events, function(name, callback) { 28144 self._bind(tooltip, name === 'toggle' ? ['tooltipshow','tooltiphide'] : ['tooltip'+name], callback, null, tooltip); 28145 }); 28146 28147 // Hide tooltips when leaving current window/frame (but not select/option elements) 28148 if(/mouse(out|leave)/i.test(options.hide.event) && options.hide.leave === 'window') { 28149 this._bind(documentTarget, ['mouseout', 'blur'], function(event) { 28150 if(!/select|option/.test(event.target.nodeName) && !event.relatedTarget) { 28151 this.hide(event); 28152 } 28153 }); 28154 } 28155 28156 // Enable hide.fixed by adding appropriate class 28157 if(options.hide.fixed) { 28158 hideTarget = hideTarget.add( tooltip.addClass(CLASS_FIXED) ); 28159 } 28160 28161 /* 28162 * Make sure hoverIntent functions properly by using mouseleave to clear show timer if 28163 * mouseenter/mouseout is used for show.event, even if it isn't in the users options. 28164 */ 28165 else if(/mouse(over|enter)/i.test(options.show.event)) { 28166 this._bind(hideTarget, 'mouseleave', function() { 28167 clearTimeout(this.timers.show); 28168 }); 28169 } 28170 28171 // Hide tooltip on document mousedown if unfocus events are enabled 28172 if(('' + options.hide.event).indexOf('unfocus') > -1) { 28173 this._bind(containerTarget.closest('html'), ['mousedown', 'touchstart'], function(event) { 28174 var elem = $(event.target), 28175 enabled = this.rendered && !this.tooltip.hasClass(CLASS_DISABLED) && this.tooltip[0].offsetWidth > 0, 28176 isAncestor = elem.parents(SELECTOR).filter(this.tooltip[0]).length > 0; 28177 28178 if(elem[0] !== this.target[0] && elem[0] !== this.tooltip[0] && !isAncestor && 28179 !this.target.has(elem[0]).length && enabled 28180 ) { 28181 this.hide(event); 28182 } 28183 }); 28184 } 28185 28186 // Check if the tooltip hides when inactive 28187 if('number' === typeof options.hide.inactive) { 28188 // Bind inactive method to show target(s) as a custom event 28189 this._bind(showTarget, 'qtip-'+this.id+'-inactive', inactiveMethod, 'inactive'); 28190 28191 // Define events which reset the 'inactive' event handler 28192 this._bind(hideTarget.add(tooltip), QTIP.inactiveEvents, inactiveMethod); 28193 } 28194 28195 // Filter and bind events 28196 this._bindEvents(showEvents, hideEvents, showTarget, hideTarget, showMethod, hideMethod); 28197 28198 // Mouse movement bindings 28199 this._bind(showTarget.add(tooltip), 'mousemove', function(event) { 28200 // Check if the tooltip hides when mouse is moved a certain distance 28201 if('number' === typeof options.hide.distance) { 28202 var origin = this.cache.origin || {}, 28203 limit = this.options.hide.distance, 28204 abs = Math.abs; 28205 28206 // Check if the movement has gone beyond the limit, and hide it if so 28207 if(abs(event.pageX - origin.pageX) >= limit || abs(event.pageY - origin.pageY) >= limit) { 28208 this.hide(event); 28209 } 28210 } 28211 28212 // Cache mousemove coords on show targets 28213 this._storeMouse(event); 28214 }); 28215 28216 // Mouse positioning events 28217 if(posOptions.target === 'mouse') { 28218 // If mouse adjustment is on... 28219 if(posOptions.adjust.mouse) { 28220 // Apply a mouseleave event so we don't get problems with overlapping 28221 if(options.hide.event) { 28222 // Track if we're on the target or not 28223 this._bind(showTarget, ['mouseenter', 'mouseleave'], function(event) { 28224 if(!this.cache) {return FALSE; } 28225 this.cache.onTarget = event.type === 'mouseenter'; 28226 }); 28227 } 28228 28229 // Update tooltip position on mousemove 28230 this._bind(documentTarget, 'mousemove', function(event) { 28231 // Update the tooltip position only if the tooltip is visible and adjustment is enabled 28232 if(this.rendered && this.cache.onTarget && !this.tooltip.hasClass(CLASS_DISABLED) && this.tooltip[0].offsetWidth > 0) { 28233 this.reposition(event); 28234 } 28235 }); 28236 } 28237 } 28238 28239 // Adjust positions of the tooltip on window resize if enabled 28240 if(posOptions.adjust.resize || viewportTarget.length) { 28241 this._bind( $.event.special.resize ? viewportTarget : windowTarget, 'resize', repositionMethod ); 28242 } 28243 28244 // Adjust tooltip position on scroll of the window or viewport element if present 28245 if(posOptions.adjust.scroll) { 28246 this._bind( windowTarget.add(posOptions.container), 'scroll', repositionMethod ); 28247 } 28248}; 28249 28250// Un-assignment method 28251PROTOTYPE._unassignEvents = function() { 28252 var options = this.options, 28253 showTargets = options.show.target, 28254 hideTargets = options.hide.target, 28255 targets = $.grep([ 28256 this.elements.target[0], 28257 this.rendered && this.tooltip[0], 28258 options.position.container[0], 28259 options.position.viewport[0], 28260 options.position.container.closest('html')[0], // unfocus 28261 window, 28262 document 28263 ], function(i) { 28264 return typeof i === 'object'; 28265 }); 28266 28267 // Add show and hide targets if they're valid 28268 if(showTargets && showTargets.toArray) { 28269 targets = targets.concat(showTargets.toArray()); 28270 } 28271 if(hideTargets && hideTargets.toArray) { 28272 targets = targets.concat(hideTargets.toArray()); 28273 } 28274 28275 // Unbind the events 28276 this._unbind(targets) 28277 ._unbind(targets, 'destroy') 28278 ._unbind(targets, 'inactive'); 28279}; 28280 28281// Apply common event handlers using delegate (avoids excessive .bind calls!) 28282$(function() { 28283 delegate(SELECTOR, ['mouseenter', 'mouseleave'], function(event) { 28284 var state = event.type === 'mouseenter', 28285 tooltip = $(event.currentTarget), 28286 target = $(event.relatedTarget || event.target), 28287 options = this.options; 28288 28289 // On mouseenter... 28290 if(state) { 28291 // Focus the tooltip on mouseenter (z-index stacking) 28292 this.focus(event); 28293 28294 // Clear hide timer on tooltip hover to prevent it from closing 28295 tooltip.hasClass(CLASS_FIXED) && !tooltip.hasClass(CLASS_DISABLED) && clearTimeout(this.timers.hide); 28296 } 28297 28298 // On mouseleave... 28299 else { 28300 // When mouse tracking is enabled, hide when we leave the tooltip and not onto the show target (if a hide event is set) 28301 if(options.position.target === 'mouse' && options.position.adjust.mouse && 28302 options.hide.event && options.show.target && !target.closest(options.show.target[0]).length) { 28303 this.hide(event); 28304 } 28305 } 28306 28307 // Add hover class 28308 tooltip.toggleClass(CLASS_HOVER, state); 28309 }); 28310 28311 // Define events which reset the 'inactive' event handler 28312 delegate('['+ATTR_ID+']', INACTIVE_EVENTS, inactiveMethod); 28313}); 28314;// Initialization method 28315function init(elem, id, opts) { 28316 var obj, posOptions, attr, config, title, 28317 28318 // Setup element references 28319 docBody = $(document.body), 28320 28321 // Use document body instead of document element if needed 28322 newTarget = elem[0] === document ? docBody : elem, 28323 28324 // Grab metadata from element if plugin is present 28325 metadata = elem.metadata ? elem.metadata(opts.metadata) : NULL, 28326 28327 // If metadata type if HTML5, grab 'name' from the object instead, or use the regular data object otherwise 28328 metadata5 = opts.metadata.type === 'html5' && metadata ? metadata[opts.metadata.name] : NULL, 28329 28330 // Grab data from metadata.name (or data-qtipopts as fallback) using .data() method, 28331 html5 = elem.data(opts.metadata.name || 'qtipopts'); 28332 28333 // If we don't get an object returned attempt to parse it manualyl without parseJSON 28334 /* eslint-disable no-empty */ 28335 try { html5 = typeof html5 === 'string' ? $.parseJSON(html5) : html5; } 28336 catch(e) {} 28337 /* eslint-enable no-empty */ 28338 28339 // Merge in and sanitize metadata 28340 config = $.extend(TRUE, {}, QTIP.defaults, opts, 28341 typeof html5 === 'object' ? sanitizeOptions(html5) : NULL, 28342 sanitizeOptions(metadata5 || metadata)); 28343 28344 // Re-grab our positioning options now we've merged our metadata and set id to passed value 28345 posOptions = config.position; 28346 config.id = id; 28347 28348 // Setup missing content if none is detected 28349 if('boolean' === typeof config.content.text) { 28350 attr = elem.attr(config.content.attr); 28351 28352 // Grab from supplied attribute if available 28353 if(config.content.attr !== FALSE && attr) { config.content.text = attr; } 28354 28355 // No valid content was found, abort render 28356 else { return FALSE; } 28357 } 28358 28359 // Setup target options 28360 if(!posOptions.container.length) { posOptions.container = docBody; } 28361 if(posOptions.target === FALSE) { posOptions.target = newTarget; } 28362 if(config.show.target === FALSE) { config.show.target = newTarget; } 28363 if(config.show.solo === TRUE) { config.show.solo = posOptions.container.closest('body'); } 28364 if(config.hide.target === FALSE) { config.hide.target = newTarget; } 28365 if(config.position.viewport === TRUE) { config.position.viewport = posOptions.container; } 28366 28367 // Ensure we only use a single container 28368 posOptions.container = posOptions.container.eq(0); 28369 28370 // Convert position corner values into x and y strings 28371 posOptions.at = new CORNER(posOptions.at, TRUE); 28372 posOptions.my = new CORNER(posOptions.my); 28373 28374 // Destroy previous tooltip if overwrite is enabled, or skip element if not 28375 if(elem.data(NAMESPACE)) { 28376 if(config.overwrite) { 28377 elem.qtip('destroy', true); 28378 } 28379 else if(config.overwrite === FALSE) { 28380 return FALSE; 28381 } 28382 } 28383 28384 // Add has-qtip attribute 28385 elem.attr(ATTR_HAS, id); 28386 28387 // Remove title attribute and store it if present 28388 if(config.suppress && (title = elem.attr('title'))) { 28389 // Final attr call fixes event delegatio
vendor: 4,438 bytes, lines 28389-28545
28389m and IE default tooltip showing problem 28390 elem.removeAttr('title').attr(oldtitle, title).attr('title', ''); 28391 } 28392 28393 // Initialize the tooltip and add API reference 28394 obj = new QTip(elem, config, id, !!attr); 28395 elem.data(NAMESPACE, obj); 28396 28397 return obj; 28398} 28399 28400// jQuery $.fn extension method 28401QTIP = $.fn.qtip = function(options, notation, newValue) 28402{ 28403 var command = ('' + options).toLowerCase(), // Parse command 28404 returned = NULL, 28405 args = $.makeArray(arguments).slice(1), 28406 event = args[args.length - 1], 28407 opts = this[0] ? $.data(this[0], NAMESPACE) : NULL; 28408 28409 // Check for API request 28410 if(!arguments.length && opts || command === 'api') { 28411 return opts; 28412 } 28413 28414 // Execute API command if present 28415 else if('string' === typeof options) { 28416 this.each(function() { 28417 var api = $.data(this, NAMESPACE); 28418 if(!api) { return TRUE; } 28419 28420 // Cache the event if possible 28421 if(event && event.timeStamp) { api.cache.event = event; } 28422 28423 // Check for specific API commands 28424 if(notation && (command === 'option' || command === 'options')) { 28425 if(newValue !== undefined || $.isPlainObject(notation)) { 28426 api.set(notation, newValue); 28427 } 28428 else { 28429 returned = api.get(notation); 28430 return FALSE; 28431 } 28432 } 28433 28434 // Execute API command 28435 else if(api[command]) { 28436 api[command].apply(api, args); 28437 } 28438 }); 28439 28440 return returned !== NULL ? returned : this; 28441 } 28442 28443 // No API commands. validate provided options and setup qTips 28444 else if('object' === typeof options || !arguments.length) { 28445 // Sanitize options first 28446 opts = sanitizeOptions($.extend(TRUE, {}, options)); 28447 28448 return this.each(function(i) { 28449 var api, id; 28450 28451 // Find next available ID, or use custom ID if provided 28452 id = $.isArray(opts.id) ? opts.id[i] : opts.id; 28453 id = !id || id === FALSE || id.length < 1 || QTIP.api[id] ? QTIP.nextid++ : id; 28454 28455 // Initialize the qTip and re-grab newly sanitized options 28456 api = init($(this), id, opts); 28457 if(api === FALSE) { return TRUE; } 28458 else { QTIP.api[id] = api; } 28459 28460 // Initialize plugins 28461 $.each(PLUGINS, function() { 28462 if(this.initialize === 'initialize') { this(api); } 28463 }); 28464 28465 // Assign initial pre-render events 28466 api._assignInitialEvents(event); 28467 }); 28468 } 28469}; 28470 28471// Expose class 28472$.qtip = QTip; 28473 28474// Populated in render method 28475QTIP.api = {}; 28476;$.each({ 28477 /* Allow other plugins to successfully retrieve the title of an element with a qTip applied */ 28478 attr: function(attr, val) { 28479 if(this.length) { 28480 var self = this[0], 28481 title = 'title', 28482 api = $.data(self, 'qtip'); 28483 28484 if(attr === title && api && api.options && 'object' === typeof api && 'object' === typeof api.options && api.options.suppress) { 28485 if(arguments.length < 2) { 28486 return $.attr(self, oldtitle); 28487 } 28488 28489 // If qTip is rendered and title was originally used as content, update it 28490 if(api && api.options.content.attr === title && api.cache.attr) { 28491 api.set('content.text', val); 28492 } 28493 28494 // Use the regular attr method to set, then cache the result 28495 return this.attr(oldtitle, val); 28496 } 28497 } 28498 28499 return $.fn['attr'+replaceSuffix].apply(this, arguments); 28500 }, 28501 28502 /* Allow clone to correctly retrieve cached title attributes */ 28503 clone: function(keepData) { 28504 // Clone our element using the real clone method 28505 var elems = $.fn['clone'+replaceSuffix].apply(this, arguments); 28506 28507 // Grab all elements with an oldtitle set, and change it to regular title attribute, if keepData is false 28508 if(!keepData) { 28509 elems.filter('['+oldtitle+']').attr('title', function() { 28510 return $.attr(this, oldtitle); 28511 }) 28512 .removeAttr(oldtitle); 28513 } 28514 28515 return elems; 28516 } 28517}, function(name, func) { 28518 if(!func || $.fn[name+replaceSuffix]) { return TRUE; } 28519 28520 var old = $.fn[name+replaceSuffix] = $.fn[name]; 28521 $.fn[name] = function() { 28522 return func.apply(this, arguments) || old.apply(this, arguments); 28523 }; 28524}); 28525 28526/* Fire off 'removeqtip' handler in $.cleanData if jQuery UI not present (it already does similar). 28527 * This snippet is taken directly from jQuery UI source code found here: 28528 * http://code.jquery.com/ui/jquery-ui-git.js 28529 */ 28530if(!$.ui) { 28531 $['cleanData'+replaceSuffix] = $.cleanData; 28532 $.cleanData = function( elems ) { 28533 for(var i = 0, elem; (elem = $( elems[i] )).length; i++) { 28534 if(elem.attr(ATTR_HAS)) { 28535 /* eslint-disable no-empty */ 28536 try { elem.triggerHandler('removeqtip'); } 28537 catch( e ) {} 28538 /* eslint-enable no-empty */ 28539 } 28540 } 28541 $['cleanData'+replaceSuffix].apply(this, arguments); 28542 }; 28543} 28544;// qTip version 28545QTIP.version = '3.0.2
vendor: 45,032 bytes, lines 28545-30099
28545'; 28546 28547// Base ID for all qTips 28548QTIP.nextid = 0; 28549 28550// Inactive events array 28551QTIP.inactiveEvents = INACTIVE_EVENTS; 28552 28553// Base z-index for all qTips 28554QTIP.zindex = 15000; 28555 28556// Define configuration defaults 28557QTIP.defaults = { 28558 prerender: FALSE, 28559 id: FALSE, 28560 overwrite: TRUE, 28561 suppress: TRUE, 28562 content: { 28563 text: TRUE, 28564 attr: 'title', 28565 title: FALSE, 28566 button: FALSE 28567 }, 28568 position: { 28569 my: 'top left', 28570 at: 'bottom right', 28571 target: FALSE, 28572 container: FALSE, 28573 viewport: FALSE, 28574 adjust: { 28575 x: 0, y: 0, 28576 mouse: TRUE, 28577 scroll: TRUE, 28578 resize: TRUE, 28579 method: 'flipinvert flipinvert' 28580 }, 28581 effect: function(api, pos) { 28582 $(this).animate(pos, { 28583 duration: 200, 28584 queue: FALSE 28585 }); 28586 } 28587 }, 28588 show: { 28589 target: FALSE, 28590 event: 'mouseenter', 28591 effect: TRUE, 28592 delay: 90, 28593 solo: FALSE, 28594 ready: FALSE, 28595 autofocus: FALSE 28596 }, 28597 hide: { 28598 target: FALSE, 28599 event: 'mouseleave', 28600 effect: TRUE, 28601 delay: 0, 28602 fixed: FALSE, 28603 inactive: FALSE, 28604 leave: 'window', 28605 distance: FALSE 28606 }, 28607 style: { 28608 classes: '', 28609 widget: FALSE, 28610 width: FALSE, 28611 height: FALSE, 28612 def: TRUE 28613 }, 28614 events: { 28615 render: NULL, 28616 move: NULL, 28617 show: NULL, 28618 hide: NULL, 28619 toggle: NULL, 28620 visible: NULL, 28621 hidden: NULL, 28622 focus: NULL, 28623 blur: NULL 28624 } 28625}; 28626;var TIP, 28627createVML, 28628SCALE, 28629PIXEL_RATIO, 28630BACKING_STORE_RATIO, 28631 28632// Common CSS strings 28633MARGIN = 'margin', 28634BORDER = 'border', 28635COLOR = 'color', 28636BG_COLOR = 'background-color', 28637TRANSPARENT = 'transparent', 28638IMPORTANT = ' !important', 28639 28640// Check if the browser supports <canvas/> elements 28641HASCANVAS = !!document.createElement('canvas').getContext, 28642 28643// Invalid colour values used in parseColours() 28644INVALID = /rgba?\(0, 0, 0(, 0)?\)|transparent|#123456/i; 28645 28646// Camel-case method, taken from jQuery source 28647// http://code.jquery.com/jquery-1.8.0.js 28648function camel(s) { return s.charAt(0).toUpperCase() + s.slice(1); } 28649 28650/* 28651 * Modified from Modernizr's testPropsAll() 28652 * http://modernizr.com/downloads/modernizr-latest.js 28653 */ 28654var cssProps = {}, cssPrefixes = ['Webkit', 'O', 'Moz', 'ms']; 28655function vendorCss(elem, prop) { 28656 var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1), 28657 props = (prop + ' ' + cssPrefixes.join(ucProp + ' ') + ucProp).split(' '), 28658 cur, val, i = 0; 28659 28660 // If the property has already been mapped... 28661 if(cssProps[prop]) { return elem.css(cssProps[prop]); } 28662 28663 while(cur = props[i++]) { 28664 if((val = elem.css(cur)) !== undefined) { 28665 cssProps[prop] = cur; 28666 return val; 28667 } 28668 } 28669} 28670 28671// Parse a given elements CSS property into an int 28672function intCss(elem, prop) { 28673 return Math.ceil(parseFloat(vendorCss(elem, prop))); 28674} 28675 28676 28677// VML creation (for IE only) 28678if(!HASCANVAS) { 28679 createVML = function(tag, props, style) { 28680 return '<qtipvml:'+tag+' xmlns="urn:schemas-microsoft.com:vml" class="qtip-vml" '+(props||'')+ 28681 ' style="behavior: url(#default#VML); '+(style||'')+ '" />'; 28682 }; 28683} 28684 28685// Canvas only definitions 28686else { 28687 PIXEL_RATIO = window.devicePixelRatio || 1; 28688 BACKING_STORE_RATIO = (function() { 28689 var context = document.createElement('canvas').getContext('2d'); 28690 return context.backingStorePixelRatio || context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio || 28691 context.msBackingStorePixelRatio || context.oBackingStorePixelRatio || 1; 28692 })(); 28693 SCALE = PIXEL_RATIO / BACKING_STORE_RATIO; 28694} 28695 28696 28697function Tip(qtip, options) { 28698 this._ns = 'tip'; 28699 this.options = options; 28700 this.offset = options.offset; 28701 this.size = [ options.width, options.height ]; 28702 28703 // Initialize 28704 this.qtip = qtip; 28705 this.init(qtip); 28706} 28707 28708$.extend(Tip.prototype, { 28709 init: function(qtip) { 28710 var context, tip; 28711 28712 // Create tip element and prepend to the tooltip 28713 tip = this.element = qtip.elements.tip = $('<div />', { 'class': NAMESPACE+'-tip' }).prependTo(qtip.tooltip); 28714 28715 // Create tip drawing element(s) 28716 if(HASCANVAS) { 28717 // save() as soon as we create the canvas element so FF2 doesn't bork on our first restore()! 28718 context = $('<canvas />').appendTo(this.element)[0].getContext('2d'); 28719 28720 // Setup constant parameters 28721 context.lineJoin = 'miter'; 28722 context.miterLimit = 100000; 28723 context.save(); 28724 } 28725 else { 28726 context = createVML('shape', 'coordorigin="0,0"', 'position:absolute;'); 28727 this.element.html(context + context); 28728 28729 // Prevent mousing down on the tip since it causes problems with .live() handling in IE due to VML 28730 qtip._bind( $('*', tip).add(tip), ['click', 'mousedown'], function(event) { event.stopPropagation(); }, this._ns); 28731 } 28732 28733 // Bind update events 28734 qtip._bind(qtip.tooltip, 'tooltipmove', this.reposition, this._ns, this); 28735 28736 // Create it 28737 this.create(); 28738 }, 28739 28740 _swapDimensions: function() { 28741 this.size[0] = this.options.height; 28742 this.size[1] = this.options.width; 28743 }, 28744 _resetDimensions: function() { 28745 this.size[0] = this.options.width; 28746 this.size[1] = this.options.height; 28747 }, 28748 28749 _useTitle: function(corner) { 28750 var titlebar = this.qtip.elements.titlebar; 28751 return titlebar && ( 28752 corner.y === TOP || corner.y === CENTER && this.element.position().top + this.size[1] / 2 + this.options.offset < titlebar.outerHeight(TRUE) 28753 ); 28754 }, 28755 28756 _parseCorner: function(corner) { 28757 var my = this.qtip.options.position.my; 28758 28759 // Detect corner and mimic properties 28760 if(corner === FALSE || my === FALSE) { 28761 corner = FALSE; 28762 } 28763 else if(corner === TRUE) { 28764 corner = new CORNER( my.string() ); 28765 } 28766 else if(!corner.string) { 28767 corner = new CORNER(corner); 28768 corner.fixed = TRUE; 28769 } 28770 28771 return corner; 28772 }, 28773 28774 _parseWidth: function(corner, side, use) { 28775 var elements = this.qtip.elements, 28776 prop = BORDER + camel(side) + 'Width'; 28777 28778 return (use ? intCss(use, prop) : 28779 intCss(elements.content, prop) || 28780 intCss(this._useTitle(corner) && elements.titlebar || elements.content, prop) || 28781 intCss(elements.tooltip, prop) 28782 ) || 0; 28783 }, 28784 28785 _parseRadius: function(corner) { 28786 var elements = this.qtip.elements, 28787 prop = BORDER + camel(corner.y) + camel(corner.x) + 'Radius'; 28788 28789 return BROWSER.ie < 9 ? 0 : 28790 intCss(this._useTitle(corner) && elements.titlebar || elements.content, prop) || 28791 intCss(elements.tooltip, prop) || 0; 28792 }, 28793 28794 _invalidColour: function(elem, prop, compare) { 28795 var val = elem.css(prop); 28796 return !val || compare && val === elem.css(compare) || INVALID.test(val) ? FALSE : val; 28797 }, 28798 28799 _parseColours: function(corner) { 28800 var elements = this.qtip.elements, 28801 tip = this.element.css('cssText', ''), 28802 borderSide = BORDER + camel(corner[ corner.precedance ]) + camel(COLOR), 28803 colorElem = this._useTitle(corner) && elements.titlebar || elements.content, 28804 css = this._invalidColour, color = []; 28805 28806 // Attempt to detect the background colour from various elements, left-to-right precedance 28807 color[0] = css(tip, BG_COLOR) || css(colorElem, BG_COLOR) || css(elements.content, BG_COLOR) || 28808 css(elements.tooltip, BG_COLOR) || tip.css(BG_COLOR); 28809 28810 // Attempt to detect the correct border side colour from various elements, left-to-right precedance 28811 color[1] = css(tip, borderSide, COLOR) || css(colorElem, borderSide, COLOR) || 28812 css(elements.content, borderSide, COLOR) || css(elements.tooltip, borderSide, COLOR) || elements.tooltip.css(borderSide); 28813 28814 // Reset background and border colours 28815 $('*', tip).add(tip).css('cssText', BG_COLOR+':'+TRANSPARENT+IMPORTANT+';'+BORDER+':0'+IMPORTANT+';'); 28816 28817 return color; 28818 }, 28819 28820 _calculateSize: function(corner) { 28821 var y = corner.precedance === Y, 28822 width = this.options.width, 28823 height = this.options.height, 28824 isCenter = corner.abbrev() === 'c', 28825 base = (y ? width: height) * (isCenter ? 0.5 : 1), 28826 pow = Math.pow, 28827 round = Math.round, 28828 bigHyp, ratio, result, 28829 28830 smallHyp = Math.sqrt( pow(base, 2) + pow(height, 2) ), 28831 hyp = [ 28832 this.border / base * smallHyp, 28833 this.border / height * smallHyp 28834 ]; 28835 28836 hyp[2] = Math.sqrt( pow(hyp[0], 2) - pow(this.border, 2) ); 28837 hyp[3] = Math.sqrt( pow(hyp[1], 2) - pow(this.border, 2) ); 28838 28839 bigHyp = smallHyp + hyp[2] + hyp[3] + (isCenter ? 0 : hyp[0]); 28840 ratio = bigHyp / smallHyp; 28841 28842 result = [ round(ratio * width), round(ratio * height) ]; 28843 return y ? result : result.reverse(); 28844 }, 28845 28846 // Tip coordinates calculator 28847 _calculateTip: function(corner, size, scale) { 28848 scale = scale || 1; 28849 size = size || this.size; 28850 28851 var width = size[0] * scale, 28852 height = size[1] * scale, 28853 width2 = Math.ceil(width / 2), height2 = Math.ceil(height / 2), 28854 28855 // Define tip coordinates in terms of height and width values 28856 tips = { 28857 br: [0,0, width,height, width,0], 28858 bl: [0,0, width,0, 0,height], 28859 tr: [0,height, width,0, width,height], 28860 tl: [0,0, 0,height, width,height], 28861 tc: [0,height, width2,0, width,height], 28862 bc: [0,0, width,0, width2,height], 28863 rc: [0,0, width,height2, 0,height], 28864 lc: [width,0, width,height, 0,height2] 28865 }; 28866 28867 // Set common side shapes 28868 tips.lt = tips.br; tips.rt = tips.bl; 28869 tips.lb = tips.tr; tips.rb = tips.tl; 28870 28871 return tips[ corner.abbrev() ]; 28872 }, 28873 28874 // Tip coordinates drawer (canvas) 28875 _drawCoords: function(context, coords) { 28876 context.beginPath(); 28877 context.moveTo(coords[0], coords[1]); 28878 context.lineTo(coords[2], coords[3]); 28879 context.lineTo(coords[4], coords[5]); 28880 context.closePath(); 28881 }, 28882 28883 create: function() { 28884 // Determine tip corner 28885 var c = this.corner = (HASCANVAS || BROWSER.ie) && this._parseCorner(this.options.corner); 28886 28887 // If we have a tip corner... 28888 this.enabled = !!this.corner && this.corner.abbrev() !== 'c'; 28889 if(this.enabled) { 28890 // Cache it 28891 this.qtip.cache.corner = c.clone(); 28892 28893 // Create it 28894 this.update(); 28895 } 28896 28897 // Toggle tip element 28898 this.element.toggle(this.enabled); 28899 28900 return this.corner; 28901 }, 28902 28903 update: function(corner, position) { 28904 if(!this.enabled) { return this; } 28905 28906 var elements = this.qtip.elements, 28907 tip = this.element, 28908 inner = tip.children(), 28909 options = this.options, 28910 curSize = this.size, 28911 mimic = options.mimic, 28912 round = Math.round, 28913 color, precedance, context, 28914 coords, bigCoords, translate, newSize, border; 28915 28916 // Re-determine tip if not already set 28917 if(!corner) { corner = this.qtip.cache.corner || this.corner; } 28918 28919 // Use corner property if we detect an invalid mimic value 28920 if(mimic === FALSE) { mimic = corner; } 28921 28922 // Otherwise inherit mimic properties from the corner object as necessary 28923 else { 28924 mimic = new CORNER(mimic); 28925 mimic.precedance = corner.precedance; 28926 28927 if(mimic.x === 'inherit') { mimic.x = corner.x; } 28928 else if(mimic.y === 'inherit') { mimic.y = corner.y; } 28929 else if(mimic.x === mimic.y) { 28930 mimic[ corner.precedance ] = corner[ corner.precedance ]; 28931 } 28932 } 28933 precedance = mimic.precedance; 28934 28935 // Ensure the tip width.height are relative to the tip position 28936 if(corner.precedance === X) { this._swapDimensions(); } 28937 else { this._resetDimensions(); } 28938 28939 // Update our colours 28940 color = this.color = this._parseColours(corner); 28941 28942 // Detect border width, taking into account colours 28943 if(color[1] !== TRANSPARENT) { 28944 // Grab border width 28945 border = this.border = this._parseWidth(corner, corner[corner.precedance]); 28946 28947 // If border width isn't zero, use border color as fill if it's not invalid (1.0 style tips) 28948 if(options.border && border < 1 && !INVALID.test(color[1])) { color[0] = color[1]; } 28949 28950 // Set border width (use detected border width if options.border is true) 28951 this.border = border = options.border !== TRUE ? options.border : border; 28952 } 28953 28954 // Border colour was invalid, set border to zero 28955 else { this.border = border = 0; } 28956 28957 // Determine tip size 28958 newSize = this.size = this._calculateSize(corner); 28959 tip.css({ 28960 width: newSize[0], 28961 height: newSize[1], 28962 lineHeight: newSize[1]+'px' 28963 }); 28964 28965 // Calculate tip translation 28966 if(corner.precedance === Y) { 28967 translate = [ 28968 round(mimic.x === LEFT ? border : mimic.x === RIGHT ? newSize[0] - curSize[0] - border : (newSize[0] - curSize[0]) / 2), 28969 round(mimic.y === TOP ? newSize[1] - curSize[1] : 0) 28970 ]; 28971 } 28972 else { 28973 translate = [ 28974 round(mimic.x === LEFT ? newSize[0] - curSize[0] : 0), 28975 round(mimic.y === TOP ? border : mimic.y === BOTTOM ? newSize[1] - curSize[1] - border : (newSize[1] - curSize[1]) / 2) 28976 ]; 28977 } 28978 28979 // Canvas drawing implementation 28980 if(HASCANVAS) { 28981 // Grab canvas context and clear/save it 28982 context = inner[0].getContext('2d'); 28983 context.restore(); context.save(); 28984 context.clearRect(0,0,6000,6000); 28985 28986 // Calculate coordinates 28987 coords = this._calculateTip(mimic, curSize, SCALE); 28988 bigCoords = this._calculateTip(mimic, this.size, SCALE); 28989 28990 // Set the canvas size using calculated size 28991 inner.attr(WIDTH, newSize[0] * SCALE).attr(HEIGHT, newSize[1] * SCALE); 28992 inner.css(WIDTH, newSize[0]).css(HEIGHT, newSize[1]); 28993 28994 // Draw the outer-stroke tip 28995 this._drawCoords(context, bigCoords); 28996 context.fillStyle = color[1]; 28997 context.fill(); 28998 28999 // Draw the actual tip 29000 context.translate(translate[0] * SCALE, translate[1] * SCALE); 29001 this._drawCoords(context, coords); 29002 context.fillStyle = color[0]; 29003 context.fill(); 29004 } 29005 29006 // VML (IE Proprietary implementation) 29007 else { 29008 // Calculate coordinates 29009 coords = this._calculateTip(mimic); 29010 29011 // Setup coordinates string 29012 coords = 'm' + coords[0] + ',' + coords[1] + ' l' + coords[2] + 29013 ',' + coords[3] + ' ' + coords[4] + ',' + coords[5] + ' xe'; 29014 29015 // Setup VML-specific offset for pixel-perfection 29016 translate[2] = border && /^(r|b)/i.test(corner.string()) ? 29017 BROWSER.ie === 8 ? 2 : 1 : 0; 29018 29019 // Set initial CSS 29020 inner.css({ 29021 coordsize: newSize[0]+border + ' ' + newSize[1]+border, 29022 antialias: ''+(mimic.string().indexOf(CENTER) > -1), 29023 left: translate[0] - translate[2] * Number(precedance === X), 29024 top: translate[1] - translate[2] * Number(precedance === Y), 29025 width: newSize[0] + border, 29026 height: newSize[1] + border 29027 }) 29028 .each(function(i) { 29029 var $this = $(this); 29030 29031 // Set shape specific attributes 29032 $this[ $this.prop ? 'prop' : 'attr' ]({ 29033 coordsize: newSize[0]+border + ' ' + newSize[1]+border, 29034 path: coords, 29035 fillcolor: color[0], 29036 filled: !!i, 29037 stroked: !i 29038 }) 29039 .toggle(!!(border || i)); 29040 29041 // Check if border is enabled and add stroke element 29042 !i && $this.html( createVML( 29043 'stroke', 'weight="'+border*2+'px" color="'+color[1]+'" miterlimit="1000" joinstyle="miter"' 29044 ) ); 29045 }); 29046 } 29047 29048 // Opera bug #357 - Incorrect tip position 29049 // https://github.com/Craga89/qTip2/issues/367 29050 window.opera && setTimeout(function() { 29051 elements.tip.css({ 29052 display: 'inline-block', 29053 visibility: 'visible' 29054 }); 29055 }, 1); 29056 29057 // Position if needed 29058 if(position !== FALSE) { this.calculate(corner, newSize); } 29059 }, 29060 29061 calculate: function(corner, size) { 29062 if(!this.enabled) { return FALSE; } 29063 29064 var self = this, 29065 elements = this.qtip.elements, 29066 tip = this.element, 29067 userOffset = this.options.offset, 29068 position = {}, 29069 precedance, corners; 29070 29071 // Inherit corner if not provided 29072 corner = corner || this.corner; 29073 precedance = corner.precedance; 29074 29075 // Determine which tip dimension to use for adjustment 29076 size = size || this._calculateSize(corner); 29077 29078 // Setup corners and offset array 29079 corners = [ corner.x, corner.y ]; 29080 if(precedance === X) { corners.reverse(); } 29081 29082 // Calculate tip position 29083 $.each(corners, function(i, side) { 29084 var b, bc, br; 29085 29086 if(side === CENTER) { 29087 b = precedance === Y ? LEFT : TOP; 29088 position[ b ] = '50%'; 29089 position[MARGIN+'-' + b] = -Math.round(size[ precedance === Y ? 0 : 1 ] / 2) + userOffset; 29090 } 29091 else { 29092 b = self._parseWidth(corner, side, elements.tooltip); 29093 bc = self._parseWidth(corner, side, elements.content); 29094 br = self._parseRadius(corner); 29095 29096 position[ side ] = Math.max(-self.border, i ? bc : userOffset + (br > b ? br : -b)); 29097 } 29098 }); 29099 29100 // Adjust for tip size 29101 position[ corner[precedance] ] -= size[ precedance === X ? 0 : 1 ]; 29102 29103 // Set and return new position 29104 tip.css({ margin: '', top: '', bottom: '', left: '', right: '' }).css(position); 29105 return position; 29106 }, 29107 29108 reposition: function(event, api, pos) { 29109 if(!this.enabled) { return; } 29110 29111 var cache = api.cache, 29112 newCorner = this.corner.clone(), 29113 adjust = pos.adjusted, 29114 method = api.options.position.adjust.method.split(' '), 29115 horizontal = method[0], 29116 vertical = method[1] || method[0], 29117 shift = { left: FALSE, top: FALSE, x: 0, y: 0 }, 29118 offset, css = {}, props; 29119 29120 function shiftflip(direction, precedance, popposite, side, opposite) { 29121 // Horizontal - Shift or flip method 29122 if(direction === SHIFT && newCorner.precedance === precedance && adjust[side] && newCorner[popposite] !== CENTER) { 29123 newCorner.precedance = newCorner.precedance === X ? Y : X; 29124 } 29125 else if(direction !== SHIFT && adjust[side]){ 29126 newCorner[precedance] = newCorner[precedance] === CENTER ? 29127 adjust[side] > 0 ? side : opposite : 29128 newCorner[precedance] === side ? opposite : side; 29129 } 29130 } 29131 29132 function shiftonly(xy, side, opposite) { 29133 if(newCorner[xy] === CENTER) { 29134 css[MARGIN+'-'+side] = shift[xy] = offset[MARGIN+'-'+side] - adjust[side]; 29135 } 29136 else { 29137 props = offset[opposite] !== undefined ? 29138 [ adjust[side], -offset[side] ] : [ -adjust[side], offset[side] ]; 29139 29140 if( (shift[xy] = Math.max(props[0], props[1])) > props[0] ) { 29141 pos[side] -= adjust[side]; 29142 shift[side] = FALSE; 29143 } 29144 29145 css[ offset[opposite] !== undefined ? opposite : side ] = shift[xy]; 29146 } 29147 } 29148 29149 // If our tip position isn't fixed e.g. doesn't adjust with viewport... 29150 if(this.corner.fixed !== TRUE) { 29151 // Perform shift/flip adjustments 29152 shiftflip(horizontal, X, Y, LEFT, RIGHT); 29153 shiftflip(vertical, Y, X, TOP, BOTTOM); 29154 29155 // Update and redraw the tip if needed (check cached details of last drawn tip) 29156 if(newCorner.string() !== cache.corner.string() || cache.cornerTop !== adjust.top || cache.cornerLeft !== adjust.left) { 29157 this.update(newCorner, FALSE); 29158 } 29159 } 29160 29161 // Setup tip offset properties 29162 offset = this.calculate(newCorner); 29163 29164 // Readjust offset object to make it left/top 29165 if(offset.right !== undefined) { offset.left = -offset.right; } 29166 if(offset.bottom !== undefined) { offset.top = -offset.bottom; } 29167 offset.user = this.offset; 29168 29169 // Perform shift adjustments 29170 shift.left = horizontal === SHIFT && !!adjust.left; 29171 if(shift.left) { 29172 shiftonly(X, LEFT, RIGHT); 29173 } 29174 shift.top = vertical === SHIFT && !!adjust.top; 29175 if(shift.top) { 29176 shiftonly(Y, TOP, BOTTOM); 29177 } 29178 29179 /* 29180 * If the tip is adjusted in both dimensions, or in a 29181 * direction that would cause it to be anywhere but the 29182 * outer border, hide it! 29183 */ 29184 this.element.css(css).toggle( 29185 !(shift.x && shift.y || newCorner.x === CENTER && shift.y || newCorner.y === CENTER && shift.x) 29186 ); 29187 29188 // Adjust position to accomodate tip dimensions 29189 pos.left -= offset.left.charAt ? offset.user : 29190 horizontal !== SHIFT || shift.top || !shift.left && !shift.top ? offset.left + this.border : 0; 29191 pos.top -= offset.top.charAt ? offset.user : 29192 vertical !== SHIFT || shift.left || !shift.left && !shift.top ? offset.top + this.border : 0; 29193 29194 // Cache details 29195 cache.cornerLeft = adjust.left; cache.cornerTop = adjust.top; 29196 cache.corner = newCorner.clone(); 29197 }, 29198 29199 destroy: function() { 29200 // Unbind events 29201 this.qtip._unbind(this.qtip.tooltip, this._ns); 29202 29203 // Remove the tip element(s) 29204 if(this.qtip.elements.tip) { 29205 this.qtip.elements.tip.find('*') 29206 .remove().end().remove(); 29207 } 29208 } 29209}); 29210 29211TIP = PLUGINS.tip = function(api) { 29212 return new Tip(api, api.options.style.tip); 29213}; 29214 29215// Initialize tip on render 29216TIP.initialize = 'render'; 29217 29218// Setup plugin sanitization options 29219TIP.sanitize = function(options) { 29220 if(options.style && 'tip' in options.style) { 29221 var opts = options.style.tip; 29222 if(typeof opts !== 'object') { opts = options.style.tip = { corner: opts }; } 29223 if(!(/string|boolean/i).test(typeof opts.corner)) { opts.corner = TRUE; } 29224 } 29225}; 29226 29227// Add new option checks for the plugin 29228CHECKS.tip = { 29229 '^position.my|style.tip.(corner|mimic|border)$': function() { 29230 // Make sure a tip can be drawn 29231 this.create(); 29232 29233 // Reposition the tooltip 29234 this.qtip.reposition(); 29235 }, 29236 '^style.tip.(height|width)$': function(obj) { 29237 // Re-set dimensions and redraw the tip 29238 this.size = [ obj.width, obj.height ]; 29239 this.update(); 29240 29241 // Reposition the tooltip 29242 this.qtip.reposition(); 29243 }, 29244 '^content.title|style.(classes|widget)$': function() { 29245 this.update(); 29246 } 29247}; 29248 29249// Extend original qTip defaults 29250$.extend(TRUE, QTIP.defaults, { 29251 style: { 29252 tip: { 29253 corner: TRUE, 29254 mimic: FALSE, 29255 width: 6, 29256 height: 6, 29257 border: TRUE, 29258 offset: 0 29259 } 29260 } 29261}); 29262;var MODAL, OVERLAY, 29263 MODALCLASS = 'qtip-modal', 29264 MODALSELECTOR = '.'+MODALCLASS; 29265 29266OVERLAY = function() 29267{ 29268 var self = this, 29269 focusableElems = {}, 29270 current, 29271 prevState, 29272 elem; 29273 29274 // Modified code from jQuery UI 1.10.0 source 29275 // http://code.jquery.com/ui/1.10.0/jquery-ui.js 29276 function focusable(element) { 29277 // Use the defined focusable checker when possible 29278 if($.expr[':'].focusable) { return $.expr[':'].focusable; } 29279 29280 var isTabIndexNotNaN = !isNaN($.attr(element, 'tabindex')), 29281 nodeName = element.nodeName && element.nodeName.toLowerCase(), 29282 map, mapName, img; 29283 29284 if('area' === nodeName) { 29285 map = element.parentNode; 29286 mapName = map.name; 29287 if(!element.href || !mapName || map.nodeName.toLowerCase() !== 'map') { 29288 return false; 29289 } 29290 img = $('img[usemap=#' + mapName + ']')[0]; 29291 return !!img && img.is(':visible'); 29292 } 29293 29294 return /input|select|textarea|button|object/.test( nodeName ) ? 29295 !element.disabled : 29296 'a' === nodeName ? 29297 element.href || isTabIndexNotNaN : 29298 isTabIndexNotNaN 29299 ; 29300 } 29301 29302 // Focus inputs using cached focusable elements (see update()) 29303 function focusInputs(blurElems) { 29304 // Blurring body element in IE causes window.open windows to unfocus! 29305 if(focusableElems.length < 1 && blurElems.length) { blurElems.not('body').blur(); } 29306 29307 // Focus the inputs 29308 else { focusableElems.first().focus(); } 29309 } 29310 29311 // Steal focus from elements outside tooltip 29312 function stealFocus(event) { 29313 if(!elem.is(':visible')) { return; } 29314 29315 var target = $(event.target), 29316 tooltip = current.tooltip, 29317 container = target.closest(SELECTOR), 29318 targetOnTop; 29319 29320 // Determine if input container target is above this 29321 targetOnTop = container.length < 1 ? FALSE : 29322 parseInt(container[0].style.zIndex, 10) > parseInt(tooltip[0].style.zIndex, 10); 29323 29324 // If we're showing a modal, but focus has landed on an input below 29325 // this modal, divert focus to the first visible input in this modal 29326 // or if we can't find one... the tooltip itself 29327 if(!targetOnTop && target.closest(SELECTOR)[0] !== tooltip[0]) { 29328 focusInputs(target); 29329 } 29330 } 29331 29332 $.extend(self, { 29333 init: function() { 29334 // Create document overlay 29335 elem = self.elem = $('<div />', { 29336 id: 'qtip-overlay', 29337 html: '<div></div>', 29338 mousedown: function() { return FALSE; } 29339 }) 29340 .hide(); 29341 29342 // Make sure we can't focus anything outside the tooltip 29343 $(document.body).bind('focusin'+MODALSELECTOR, stealFocus); 29344 29345 // Apply keyboard "Escape key" close handler 29346 $(document).bind('keydown'+MODALSELECTOR, function(event) { 29347 if(current && current.options.show.modal.escape && event.keyCode === 27) { 29348 current.hide(event); 29349 } 29350 }); 29351 29352 // Apply click handler for blur option 29353 elem.bind('click'+MODALSELECTOR, function(event) { 29354 if(current && current.options.show.modal.blur) { 29355 current.hide(event); 29356 } 29357 }); 29358 29359 return self; 29360 }, 29361 29362 update: function(api) { 29363 // Update current API reference 29364 current = api; 29365 29366 // Update focusable elements if enabled 29367 if(api.options.show.modal.stealfocus !== FALSE) { 29368 focusableElems = api.tooltip.find('*').filter(function() { 29369 return focusable(this); 29370 }); 29371 } 29372 else { focusableElems = []; } 29373 }, 29374 29375 toggle: function(api, state, duration) { 29376 var tooltip = api.tooltip, 29377 options = api.options.show.modal, 29378 effect = options.effect, 29379 type = state ? 'show': 'hide', 29380 visible = elem.is(':visible'), 29381 visibleModals = $(MODALSELECTOR).filter(':visible:not(:animated)').not(tooltip); 29382 29383 // Set active tooltip API reference 29384 self.update(api); 29385 29386 // If the modal can steal the focus... 29387 // Blur the current item and focus anything in the modal we an 29388 if(state && options.stealfocus !== FALSE) { 29389 focusInputs( $(':focus') ); 29390 } 29391 29392 // Toggle backdrop cursor style on show 29393 elem.toggleClass('blurs', options.blur); 29394 29395 // Append to body on show 29396 if(state) { 29397 elem.appendTo(document.body); 29398 } 29399 29400 // Prevent modal from conflicting with show.solo, and don't hide backdrop is other modals are visible 29401 if(elem.is(':animated') && visible === state && prevState !== FALSE || !state && visibleModals.length) { 29402 return self; 29403 } 29404 29405 // Stop all animations 29406 elem.stop(TRUE, FALSE); 29407 29408 // Use custom function if provided 29409 if($.isFunction(effect)) { 29410 effect.call(elem, state); 29411 } 29412 29413 // If no effect type is supplied, use a simple toggle 29414 else if(effect === FALSE) { 29415 elem[ type ](); 29416 } 29417 29418 // Use basic fade function 29419 else { 29420 elem.fadeTo( parseInt(duration, 10) || 90, state ? 1 : 0, function() { 29421 if(!state) { elem.hide(); } 29422 }); 29423 } 29424 29425 // Reset position and detach from body on hide 29426 if(!state) { 29427 elem.queue(function(next) { 29428 elem.css({ left: '', top: '' }); 29429 if(!$(MODALSELECTOR).length) { elem.detach(); } 29430 next(); 29431 }); 29432 } 29433 29434 // Cache the state 29435 prevState = state; 29436 29437 // If the tooltip is destroyed, set reference to null 29438 if(current.destroyed) { current = NULL; } 29439 29440 return self; 29441 } 29442 }); 29443 29444 self.init(); 29445}; 29446OVERLAY = new OVERLAY(); 29447 29448function Modal(api, options) { 29449 this.options = options; 29450 this._ns = '-modal'; 29451 29452 this.qtip = api; 29453 this.init(api); 29454} 29455 29456$.extend(Modal.prototype, { 29457 init: function(qtip) { 29458 var tooltip = qtip.tooltip; 29459 29460 // If modal is disabled... return 29461 if(!this.options.on) { return this; } 29462 29463 // Set overlay reference 29464 qtip.elements.overlay = OVERLAY.elem; 29465 29466 // Add unique attribute so we can grab modal tooltips easily via a SELECTOR, and set z-index 29467 tooltip.addClass(MODALCLASS).css('z-index', QTIP.modal_zindex + $(MODALSELECTOR).length); 29468 29469 // Apply our show/hide/focus modal events 29470 qtip._bind(tooltip, ['tooltipshow', 'tooltiphide'], function(event, api, duration) { 29471 var oEvent = event.originalEvent; 29472 29473 // Make sure mouseout doesn't trigger a hide when showing the modal and mousing onto backdrop 29474 if(event.target === tooltip[0]) { 29475 if(oEvent && event.type === 'tooltiphide' && /mouse(leave|enter)/.test(oEvent.type) && $(oEvent.relatedTarget).closest(OVERLAY.elem[0]).length) { 29476 /* eslint-disable no-empty */ 29477 try { event.preventDefault(); } 29478 catch(e) {} 29479 /* eslint-enable no-empty */ 29480 } 29481 else if(!oEvent || oEvent && oEvent.type !== 'tooltipsolo') { 29482 this.toggle(event, event.type === 'tooltipshow', duration); 29483 } 29484 } 29485 }, this._ns, this); 29486 29487 // Adjust modal z-index on tooltip focus 29488 qtip._bind(tooltip, 'tooltipfocus', function(event, api) { 29489 // If focus was cancelled before it reached us, don't do anything 29490 if(event.isDefaultPrevented() || event.target !== tooltip[0]) { return; } 29491 29492 var qtips = $(MODALSELECTOR), 29493 29494 // Keep the modal's lower than other, regular qtips 29495 newIndex = QTIP.modal_zindex + qtips.length, 29496 curIndex = parseInt(tooltip[0].style.zIndex, 10); 29497 29498 // Set overlay z-index 29499 OVERLAY.elem[0].style.zIndex = newIndex - 1; 29500 29501 // Reduce modal z-index's and keep them properly ordered 29502 qtips.each(function() { 29503 if(this.style.zIndex > curIndex) { 29504 this.style.zIndex -= 1; 29505 } 29506 }); 29507 29508 // Fire blur event for focused tooltip 29509 qtips.filter('.' + CLASS_FOCUS).qtip('blur', event.originalEvent); 29510 29511 // Set the new z-index 29512 tooltip.addClass(CLASS_FOCUS)[0].style.zIndex = newIndex; 29513 29514 // Set current 29515 OVERLAY.update(api); 29516 29517 // Prevent default handling 29518 /* eslint-disable no-empty */ 29519 try { event.preventDefault(); } 29520 catch(e) {} 29521 /* eslint-enable no-empty */ 29522 }, this._ns, this); 29523 29524 // Focus any other visible modals when this one hides 29525 qtip._bind(tooltip, 'tooltiphide', function(event) { 29526 if(event.target === tooltip[0]) { 29527 $(MODALSELECTOR).filter(':visible').not(tooltip).last().qtip('focus', event); 29528 } 29529 }, this._ns, this); 29530 }, 29531 29532 toggle: function(event, state, duration) { 29533 // Make sure default event hasn't been prevented 29534 if(event && event.isDefaultPrevented()) { return this; } 29535 29536 // Toggle it 29537 OVERLAY.toggle(this.qtip, !!state, duration); 29538 }, 29539 29540 destroy: function() { 29541 // Remove modal class 29542 this.qtip.tooltip.removeClass(MODALCLASS); 29543 29544 // Remove bound events 29545 this.qtip._unbind(this.qtip.tooltip, this._ns); 29546 29547 // Delete element reference 29548 OVERLAY.toggle(this.qtip, FALSE); 29549 delete this.qtip.elements.overlay; 29550 } 29551}); 29552 29553 29554MODAL = PLUGINS.modal = function(api) { 29555 return new Modal(api, api.options.show.modal); 29556}; 29557 29558// Setup sanitiztion rules 29559MODAL.sanitize = function(opts) { 29560 if(opts.show) { 29561 if(typeof opts.show.modal !== 'object') { opts.show.modal = { on: !!opts.show.modal }; } 29562 else if(typeof opts.show.modal.on === 'undefined') { opts.show.modal.on = TRUE; } 29563 } 29564}; 29565 29566// Base z-index for all modal tooltips (use qTip core z-index as a base) 29567/* eslint-disable camelcase */ 29568QTIP.modal_zindex = QTIP.zindex - 200; 29569/* eslint-enable camelcase */ 29570 29571// Plugin needs to be initialized on render 29572MODAL.initialize = 'render'; 29573 29574// Setup option set checks 29575CHECKS.modal = { 29576 '^show.modal.(on|blur)$': function() { 29577 // Initialise 29578 this.destroy(); 29579 this.init(); 29580 29581 // Show the modal if not visible already and tooltip is visible 29582 this.qtip.elems.overlay.toggle( 29583 this.qtip.tooltip[0].offsetWidth > 0 29584 ); 29585 } 29586}; 29587 29588// Extend original api defaults 29589$.extend(TRUE, QTIP.defaults, { 29590 show: { 29591 modal: { 29592 on: FALSE, 29593 effect: TRUE, 29594 blur: TRUE, 29595 stealfocus: TRUE, 29596 escape: TRUE 29597 } 29598 } 29599}); 29600;PLUGINS.viewport = function(api, position, posOptions, targetWidth, targetHeight, elemWidth, elemHeight) 29601{ 29602 var target = posOptions.target, 29603 tooltip = api.elements.tooltip, 29604 my = posOptions.my, 29605 at = posOptions.at, 29606 adjust = posOptions.adjust, 29607 method = adjust.method.split(' '), 29608 methodX = method[0], 29609 methodY = method[1] || method[0], 29610 viewport = posOptions.viewport, 29611 container = posOptions.container, 29612 adjusted = { left: 0, top: 0 }, 29613 fixed, newMy, containerOffset, containerStatic, 29614 viewportWidth, viewportHeight, viewportScroll, viewportOffset; 29615 29616 // If viewport is not a jQuery element, or it's the window/document, or no adjustment method is used... return 29617 if(!viewport.jquery || target[0] === window || target[0] === document.body || adjust.method === 'none') { 29618 return adjusted; 29619 } 29620 29621 // Cach container details 29622 containerOffset = container.offset() || adjusted; 29623 containerStatic = container.css('position') === 'static'; 29624 29625 // Cache our viewport details 29626 fixed = tooltip.css('position') === 'fixed'; 29627 viewportWidth = viewport[0] === window ? viewport.width() : viewport.outerWidth(FALSE); 29628 viewportHeight = viewport[0] === window ? viewport.height() : viewport.outerHeight(FALSE); 29629 viewportScroll = { left: fixed ? 0 : viewport.scrollLeft(), top: fixed ? 0 : viewport.scrollTop() }; 29630 viewportOffset = viewport.offset() || adjusted; 29631 29632 // Generic calculation method 29633 function calculate(side, otherSide, type, adjustment, side1, side2, lengthName, targetLength, elemLength) { 29634 var initialPos = position[side1], 29635 mySide = my[side], 29636 atSide = at[side], 29637 isShift = type === SHIFT, 29638 myLength = mySide === side1 ? elemLength : mySide === side2 ? -elemLength : -elemLength / 2, 29639 atLength = atSide === side1 ? targetLength : atSide === side2 ? -targetLength : -targetLength / 2, 29640 sideOffset = viewportScroll[side1] + viewportOffset[side1] - (containerStatic ? 0 : containerOffset[side1]), 29641 overflow1 = sideOffset - initialPos, 29642 overflow2 = initialPos + elemLength - (lengthName === WIDTH ? viewportWidth : viewportHeight) - sideOffset, 29643 offset = myLength - (my.precedance === side || mySide === my[otherSide] ? atLength : 0) - (atSide === CENTER ? targetLength / 2 : 0); 29644 29645 // shift 29646 if(isShift) { 29647 offset = (mySide === side1 ? 1 : -1) * myLength; 29648 29649 // Adjust position but keep it within viewport dimensions 29650 position[side1] += overflow1 > 0 ? overflow1 : overflow2 > 0 ? -overflow2 : 0; 29651 position[side1] = Math.max( 29652 -containerOffset[side1] + viewportOffset[side1], 29653 initialPos - offset, 29654 Math.min( 29655 Math.max( 29656 -containerOffset[side1] + viewportOffset[side1] + (lengthName === WIDTH ? viewportWidth : viewportHeight), 29657 initialPos + offset 29658 ), 29659 position[side1], 29660 29661 // Make sure we don't adjust complete off the element when using 'center' 29662 mySide === 'center' ? initialPos - myLength : 1E9 29663 ) 29664 ); 29665 29666 } 29667 29668 // flip/flipinvert 29669 else { 29670 // Update adjustment amount depending on if using flipinvert or flip 29671 adjustment *= type === FLIPINVERT ? 2 : 0; 29672 29673 // Check for overflow on the left/top 29674 if(overflow1 > 0 && (mySide !== side1 || overflow2 > 0)) { 29675 position[side1] -= offset + adjustment; 29676 newMy.invert(side, side1); 29677 } 29678 29679 // Check for overflow on the bottom/right 29680 else if(overflow2 > 0 && (mySide !== side2 || overflow1 > 0) ) { 29681 position[side1] -= (mySide === CENTER ? -offset : offset) + adjustment; 29682 newMy.invert(side, side2); 29683 } 29684 29685 // Make sure we haven't made things worse with the adjustment and reset if so 29686 if(position[side1] < viewportScroll[side1] && -position[side1] > overflow2) { 29687 position[side1] = initialPos; newMy = my.clone(); 29688 } 29689 } 29690 29691 return position[side1] - initialPos; 29692 } 29693 29694 // Set newMy if using flip or flipinvert methods 29695 if(methodX !== 'shift' || methodY !== 'shift') { newMy = my.clone(); } 29696 29697 // Adjust position based onviewport and adjustment options 29698 adjusted = { 29699 left: methodX !== 'none' ? calculate( X, Y, methodX, adjust.x, LEFT, RIGHT, WIDTH, targetWidth, elemWidth ) : 0, 29700 top: methodY !== 'none' ? calculate( Y, X, methodY, adjust.y, TOP, BOTTOM, HEIGHT, targetHeight, elemHeight ) : 0, 29701 my: newMy 29702 }; 29703 29704 return adjusted; 29705}; 29706;PLUGINS.polys = { 29707 // POLY area coordinate calculator 29708 // Special thanks to Ed Cradock for helping out with this. 29709 // Uses a binary search algorithm to find suitable coordinates. 29710 polygon: function(baseCoords, corner) { 29711 var result = { 29712 width: 0, height: 0, 29713 position: { 29714 top: 1e10, right: 0, 29715 bottom: 0, left: 1e10 29716 }, 29717 adjustable: FALSE 29718 }, 29719 i = 0, next, 29720 coords = [], 29721 compareX = 1, compareY = 1, 29722 realX = 0, realY = 0, 29723 newWidth, newHeight; 29724 29725 // First pass, sanitize coords and determine outer edges 29726 i = baseCoords.length; 29727 while(i--) { 29728 next = [ parseInt(baseCoords[--i], 10), parseInt(baseCoords[i+1], 10) ]; 29729 29730 if(next[0] > result.position.right){ result.position.right = next[0]; } 29731 if(next[0] < result.position.left){ result.position.left = next[0]; } 29732 if(next[1] > result.position.bottom){ result.position.bottom = next[1]; } 29733 if(next[1] < result.position.top){ result.position.top = next[1]; } 29734 29735 coords.push(next); 29736 } 29737 29738 // Calculate height and width from outer edges 29739 newWidth = result.width = Math.abs(result.position.right - result.position.left); 29740 newHeight = result.height = Math.abs(result.position.bottom - result.position.top); 29741 29742 // If it's the center corner... 29743 if(corner.abbrev() === 'c') { 29744 result.position = { 29745 left: result.position.left + result.width / 2, 29746 top: result.position.top + result.height / 2 29747 }; 29748 } 29749 else { 29750 // Second pass, use a binary search algorithm to locate most suitable coordinate 29751 while(newWidth > 0 && newHeight > 0 && compareX > 0 && compareY > 0) 29752 { 29753 newWidth = Math.floor(newWidth / 2); 29754 newHeight = Math.floor(newHeight / 2); 29755 29756 if(corner.x === LEFT){ compareX = newWidth; } 29757 else if(corner.x === RIGHT){ compareX = result.width - newWidth; } 29758 else{ compareX += Math.floor(newWidth / 2); } 29759 29760 if(corner.y === TOP){ compareY = newHeight; } 29761 else if(corner.y === BOTTOM){ compareY = result.height - newHeight; } 29762 else{ compareY += Math.floor(newHeight / 2); } 29763 29764 i = coords.length; 29765 while(i--) 29766 { 29767 if(coords.length < 2){ break; } 29768 29769 realX = coords[i][0] - result.position.left; 29770 realY = coords[i][1] - result.position.top; 29771 29772 if( 29773 corner.x === LEFT && realX >= compareX || 29774 corner.x === RIGHT && realX <= compareX || 29775 corner.x === CENTER && (realX < compareX || realX > result.width - compareX) || 29776 corner.y === TOP && realY >= compareY || 29777 corner.y === BOTTOM && realY <= compareY || 29778 corner.y === CENTER && (realY < compareY || realY > result.height - compareY)) { 29779 coords.splice(i, 1); 29780 } 29781 } 29782 } 29783 result.position = { left: coords[0][0], top: coords[0][1] }; 29784 } 29785 29786 return result; 29787 }, 29788 29789 rect: function(ax, ay, bx, by) { 29790 return { 29791 width: Math.abs(bx - ax), 29792 height: Math.abs(by - ay), 29793 position: { 29794 left: Math.min(ax, bx), 29795 top: Math.min(ay, by) 29796 } 29797 }; 29798 }, 29799 29800 _angles: { 29801 tc: 3 / 2, tr: 7 / 4, tl: 5 / 4, 29802 bc: 1 / 2, br: 1 / 4, bl: 3 / 4, 29803 rc: 2, lc: 1, c: 0 29804 }, 29805 ellipse: function(cx, cy, rx, ry, corner) { 29806 var c = PLUGINS.polys._angles[ corner.abbrev() ], 29807 rxc = c === 0 ? 0 : rx * Math.cos( c * Math.PI ), 29808 rys = ry * Math.sin( c * Math.PI ); 29809 29810 return { 29811 width: rx * 2 - Math.abs(rxc), 29812 height: ry * 2 - Math.abs(rys), 29813 position: { 29814 left: cx + rxc, 29815 top: cy + rys 29816 }, 29817 adjustable: FALSE 29818 }; 29819 }, 29820 circle: function(cx, cy, r, corner) { 29821 return PLUGINS.polys.ellipse(cx, cy, r, r, corner); 29822 } 29823}; 29824;PLUGINS.svg = function(api, svg, corner) 29825{ 29826 var elem = svg[0], 29827 root = $(elem.ownerSVGElement), 29828 ownerDocument = elem.ownerDocument, 29829 strokeWidth2 = (parseInt(svg.css('stroke-width'), 10) || 0) / 2, 29830 frameOffset, mtx, transformed, 29831 len, next, i, points, 29832 result, position; 29833 29834 // Ascend the parentNode chain until we find an element with getBBox() 29835 while(!elem.getBBox) { elem = elem.parentNode; } 29836 if(!elem.getBBox || !elem.parentNode) { return FALSE; } 29837 29838 // Determine which shape calculation to use 29839 switch(elem.nodeName) { 29840 case 'ellipse': 29841 case 'circle': 29842 result = PLUGINS.polys.ellipse( 29843 elem.cx.baseVal.value, 29844 elem.cy.baseVal.value, 29845 (elem.rx || elem.r).baseVal.value + strokeWidth2, 29846 (elem.ry || elem.r).baseVal.value + strokeWidth2, 29847 corner 29848 ); 29849 break; 29850 29851 case 'line': 29852 case 'polygon': 29853 case 'polyline': 29854 // Determine points object (line has none, so mimic using array) 29855 points = elem.points || [ 29856 { x: elem.x1.baseVal.value, y: elem.y1.baseVal.value }, 29857 { x: elem.x2.baseVal.value, y: elem.y2.baseVal.value } 29858 ]; 29859 29860 for(result = [], i = -1, len = points.numberOfItems || points.length; ++i < len;) { 29861 next = points.getItem ? points.getItem(i) : points[i]; 29862 result.push.apply(result, [next.x, next.y]); 29863 } 29864 29865 result = PLUGINS.polys.polygon(result, corner); 29866 break; 29867 29868 // Unknown shape or rectangle? Use bounding box 29869 default: 29870 result = elem.getBBox(); 29871 result = { 29872 width: result.width, 29873 height: result.height, 29874 position: { 29875 left: result.x, 29876 top: result.y 29877 } 29878 }; 29879 break; 29880 } 29881 29882 // Shortcut assignments 29883 position = result.position; 29884 root = root[0]; 29885 29886 // Convert position into a pixel value 29887 if(root.createSVGPoint) { 29888 mtx = elem.getScreenCTM(); 29889 points = root.createSVGPoint(); 29890 29891 points.x = position.left; 29892 points.y = position.top; 29893 transformed = points.matrixTransform( mtx ); 29894 position.left = transformed.x; 29895 position.top = transformed.y; 29896 } 29897 29898 // Check the element is not in a child document, and if so, adjust for frame elements offset 29899 if(ownerDocument !== document && api.position.target !== 'mouse') { 29900 frameOffset = $((ownerDocument.defaultView || ownerDocument.parentWindow).frameElement).offset(); 29901 if(frameOffset) { 29902 position.left += frameOffset.left; 29903 position.top += frameOffset.top; 29904 } 29905 } 29906 29907 // Adjust by scroll offset of owner document 29908 ownerDocument = $(ownerDocument); 29909 position.left += ownerDocument.scrollLeft(); 29910 position.top += ownerDocument.scrollTop(); 29911 29912 return result; 29913}; 29914;PLUGINS.imagemap = function(api, area, corner) 29915{ 29916 if(!area.jquery) { area = $(area); } 29917 29918 var shape = (area.attr('shape') || 'rect').toLowerCase().replace('poly', 'polygon'), 29919 image = $('img[usemap="#'+area.parent('map').attr('name')+'"]'), 29920 coordsString = $.trim(area.attr('coords')), 29921 coordsArray = coordsString.replace(/,$/, '').split(','), 29922 imageOffset, coords, i, result, len; 29923 29924 // If we can't find the image using the map... 29925 if(!image.length) { return FALSE; } 29926 29927 // Pass coordinates string if polygon 29928 if(shape === 'polygon') { 29929 result = PLUGINS.polys.polygon(coordsArray, corner); 29930 } 29931 29932 // Otherwise parse the coordinates and pass them as arguments 29933 else if(PLUGINS.polys[shape]) { 29934 for(i = -1, len = coordsArray.length, coords = []; ++i < len;) { 29935 coords.push( parseInt(coordsArray[i], 10) ); 29936 } 29937 29938 result = PLUGINS.polys[shape].apply( 29939 this, coords.concat(corner) 29940 ); 29941 } 29942 29943 // If no shapre calculation method was found, return false 29944 else { return FALSE; } 29945 29946 // Make sure we account for padding and borders on the image 29947 imageOffset = image.offset(); 29948 imageOffset.left += Math.ceil((image.outerWidth(FALSE) - image.width()) / 2); 29949 imageOffset.top += Math.ceil((image.outerHeight(FALSE) - image.height()) / 2); 29950 29951 // Add image position to offset coordinates 29952 result.position.left += imageOffset.left; 29953 result.position.top += imageOffset.top; 29954 29955 return result; 29956}; 29957;var IE6, 29958 29959/* 29960 * BGIFrame adaption (http://plugins.jquery.com/project/bgiframe) 29961 * Special thanks to Brandon Aaron 29962 */ 29963BGIFRAME = '<iframe class="qtip-bgiframe" frameborder="0" tabindex="-1" src="javascript:\'\';" ' + 29964 ' style="display:block; position:absolute; z-index:-1; filter:alpha(opacity=0); ' + 29965 '-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";"></iframe>'; 29966 29967function Ie6(api) { 29968 this._ns = 'ie6'; 29969 29970 this.qtip = api; 29971 this.init(api); 29972} 29973 29974$.extend(Ie6.prototype, { 29975 _scroll : function() { 29976 var overlay = this.qtip.elements.overlay; 29977 overlay && (overlay[0].style.top = $(window).scrollTop() + 'px'); 29978 }, 29979 29980 init: function(qtip) { 29981 var tooltip = qtip.tooltip; 29982 29983 // Create the BGIFrame element if needed 29984 if($('select, object').length < 1) { 29985 this.bgiframe = qtip.elements.bgiframe = $(BGIFRAME).appendTo(tooltip); 29986 29987 // Update BGIFrame on tooltip move 29988 qtip._bind(tooltip, 'tooltipmove', this.adjustBGIFrame, this._ns, this); 29989 } 29990 29991 // redraw() container for width/height calculations 29992 this.redrawContainer = $('<div/>', { id: NAMESPACE+'-rcontainer' }) 29993 .appendTo(document.body); 29994 29995 // Fixup modal plugin if present too 29996 if( qtip.elements.overlay && qtip.elements.overlay.addClass('qtipmodal-ie6fix') ) { 29997 qtip._bind(window, ['scroll', 'resize'], this._scroll, this._ns, this); 29998 qtip._bind(tooltip, ['tooltipshow'], this._scroll, this._ns, this); 29999 } 30000 30001 // Set dimensions 30002 this.redraw(); 30003 }, 30004 30005 adjustBGIFrame: function() { 30006 var tooltip = this.qtip.tooltip, 30007 dimensions = { 30008 height: tooltip.outerHeight(FALSE), 30009 width: tooltip.outerWidth(FALSE) 30010 }, 30011 plugin = this.qtip.plugins.tip, 30012 tip = this.qtip.elements.tip, 30013 tipAdjust, offset; 30014 30015 // Adjust border offset 30016 offset = parseInt(tooltip.css('borderLeftWidth'), 10) || 0; 30017 offset = { left: -offset, top: -offset }; 30018 30019 // Adjust for tips plugin 30020 if(plugin && tip) { 30021 tipAdjust = plugin.corner.precedance === 'x' ? [WIDTH, LEFT] : [HEIGHT, TOP]; 30022 offset[ tipAdjust[1] ] -= tip[ tipAdjust[0] ](); 30023 } 30024 30025 // Update bgiframe 30026 this.bgiframe.css(offset).css(dimensions); 30027 }, 30028 30029 // Max/min width simulator function 30030 redraw: function() { 30031 if(this.qtip.rendered < 1 || this.drawing) { return this; } 30032 30033 var tooltip = this.qtip.tooltip, 30034 style = this.qtip.options.style, 30035 container = this.qtip.options.position.container, 30036 perc, width, max, min; 30037 30038 // Set drawing flag 30039 this.qtip.drawing = 1; 30040 30041 // If tooltip has a set height/width, just set it... like a boss! 30042 if(style.height) { tooltip.css(HEIGHT, style.height); } 30043 if(style.width) { tooltip.css(WIDTH, style.width); } 30044 30045 // Simulate max/min width if not set width present... 30046 else { 30047 // Reset width and add fluid class 30048 tooltip.css(WIDTH, '').appendTo(this.redrawContainer); 30049 30050 // Grab our tooltip width (add 1 if odd so we don't get wrapping problems.. huzzah!) 30051 width = tooltip.width(); 30052 if(width % 2 < 1) { width += 1; } 30053 30054 // Grab our max/min properties 30055 max = tooltip.css('maxWidth') || ''; 30056 min = tooltip.css('minWidth') || ''; 30057 30058 // Parse into proper pixel values 30059 perc = (max + min).indexOf('%') > -1 ? container.width() / 100 : 0; 30060 max = (max.indexOf('%') > -1 ? perc : 1 * parseInt(max, 10)) || width; 30061 min = (min.indexOf('%') > -1 ? perc : 1 * parseInt(min, 10)) || 0; 30062 30063 // Determine new dimension size based on max/min/current values 30064 width = max + min ? Math.min(Math.max(width, min), max) : width; 30065 30066 // Set the newly calculated width and remvoe fluid class 30067 tooltip.css(WIDTH, Math.round(width)).appendTo(container); 30068 } 30069 30070 // Set drawing flag 30071 this.drawing = 0; 30072 30073 return this; 30074 }, 30075 30076 destroy: function() { 30077 // Remove iframe 30078 this.bgiframe && this.bgiframe.remove(); 30079 30080 // Remove bound events 30081 this.qtip._unbind([window, this.qtip.tooltip], this._ns); 30082 } 30083}); 30084 30085IE6 = PLUGINS.ie6 = function(api) { 30086 // Proceed only if the browser is IE6 30087 return BROWSER.ie === 6 ? new Ie6(api) : FALSE; 30088}; 30089 30090IE6.initialize = 'render'; 30091 30092CHECKS.ie6 = { 30093 '^content|style$': function() { 30094 this.redraw(); 30095 } 30096}; 30097;})); 30098}( window, document )); 30099
30100// Avoid `console` errors in browsers that lack a console. 30101(function () { 30102 var method; 30103 var noop = function () { 30104 }; 30105 var methods = ['assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error', 'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log', 'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd', 'timeStamp', 'trace', 'warn']; 30106 var length = methods.length; 30107 var console = (window.console = window.console || {}); 30108 30109 while (length--) { 30110 method = methods[length]; 30111 30112 // Only stub undefined methods. 30113 if (!console[method]) { 30114 console[method] = noop; 30115 } 30116 } 30117}()); 30118 30119// Place any jQuery/helper plugins in here. 30120function setCookie(cname, cvalue, exdays) { 30121 var d = new Date(); 30122 d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000)); 30123 var expires = "expires=" + d.toUTCString(); 30124 document.cookie = cname + "=" + cvalue + "; " + expires; 30125 // $.post(Storage.getData('app_url')); 30126} 30127function getCookie(cname) { 30128 var name = cname + "="; 30129 var ca = document.cookie.split(';'); 30130 for (var i = 0; i < ca.length; i++) { 30131 var c = ca[i]; 30132 while (c.charAt(0) == ' ') { 30133 c = c.substring(1); 30134 } 30135 if (c.indexOf(name) != -1) { 30136 return c.substring(name.length, c.length); 30137 } 30138 } 30139 return ""; 30140} 30141 30142if (window.history.pushState === undefined) { 30143 //adding fake support for fucked up browsers 30144 window.history.pushState = function (state, url, title) { 30145 document.location.href = url; 30146 } 30147} 30148 30149function updateUrl(title, url) { 30150 window.history.pushState(null, title, url); 30151 document.title = title; 30152} 30153 30154function updateLlb(data) { 30155 $('#loginLogout').text(data.loginLogout).attr('href', data.loginLogoutUrl); 30156} 30157 30158function stristr(haystack, needle, bool) { 30159 var pos = 0; 30160 30161 haystack += ''; 30162 pos = haystack.toLowerCase() 30163 .indexOf((needle + '') 30164 .toLowerCase()); 30165 if (pos == -1) { 30166 return false; 30167 } else { 30168 if (bool) { 30169 return haystack.substr(0, pos); 30170 } else { 30171 return haystack.slice(pos); 30172 } 30173 } 30174} 30175 30176function isReadyToBuy() { 30177 if (false == $('.ownerDetails .ok').hasClass('hidden') && 30178 false == $('.adminDetails .ok').hasClass('hidden') 30179 ) { 30180 $('.success-btn-girl img').removeClass('hidden'); 30181 $('.isReady .ok').removeClass('hidden').parent().find('.error').addClass('hidden'); 30182 $('#domainCheckout').removeAttr('disabled'); 30183 return true; 30184 } else { 30185 $('.isReady .error').removeClass('hidden').parent().find('.ok').addClass('hidden'); 30186 $('#domainCheckout').attr('disabled', 'disabled'); 30187 $('#creditCardDetails').addClass('hidden'); 30188 30189 return false; 30190 } 30191} 30192 30193function nl2br(str, is_xhtml) { 30194 var breakTag = (is_xhtml || typeof is_xhtml === 'undefined') ? '<br />' : '<br>'; 30195 return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2'); 30196} 30197 30198function ctype_print(str) { 30199 var allowed = 'abcdefghijklmnopqrstuvwxyz0123456789*!@#$%^?:&*~=_.,<>{}"|-;`+()[]/\\\' '; 30200 allowed = allowed.split(''); 30201 30202 str = str.replace(/\u200E/g, ''); 30203 var chars = str.split(''); 30204 var status = true; 30205 30206 for (var i = 0; i < chars.length; i++) { 30207 var singleChar = chars[i].toLowerCase(); 30208 if (allowed.indexOf(singleChar) === -1) { 30209 status = false; 30210 break; 30211 } 30212 } 30213 return status; 30214} 30215 30216function enom_ctype_print(str) { 30217 var allowed = 'abcdefghijklmnopqrstuvwxyz0123456789*!@#$%^?:&*~=_.,<>{}"|-;`+()[]/\\\' '; 30218 allowed = allowed.split(''); 30219 30220 str = str.replace(/\u200E/g, ''); 30221 var chars = str.split(''); 30222 var status = true; 30223 30224 for (var i = 0; i < chars.length; i++) { 30225 var singleChar = chars[i].toLowerCase(); 30226 if (allowed.indexOf(singleChar) === -1) { 30227 status = false; 30228 break; 30229 } 30230 } 30231 return status; 30232} 30233 30234function ctype_print_heb(str) { 30235 var allowed = '××××××××××××××××× ×¡×¢×£×¤×¥×¦×§×¨×©×ªabcdefghijklmnopqrstuvwxyz0123456789*!@#$%^?:&*~=_.,<>{}"|-;`+()[]/\\\' '; 30236 allowed = allowed.split(''); 30237 30238 str = str.replace(/\u200E/g, ''); 30239 var chars = str.split(''); 30240 var status = true; 30241 30242 for (var i = 0; i < chars.length; i++) { 30243 var singleChar = chars[i].toLowerCase(); 30244 if (allowed.indexOf(singleChar) === -1) { 30245 status = false;
30246 break; 30247 } 30248 } 30249 return status; 30250} 30251 30252function validatePerf(num) { 30253 if ('string' == typeof num && num.charAt(0) == '0') { 30254 num = num.slice(1, 5); 30255 } 30256 return num; 30257} 30258 30259jQuery.extend({ 30260 30261 getQueryParameters: function (str) { 30262 return (str || document.location.search).replace(/(^\?)/, '').split("&").map(function (n) { 30263 return n = n.split("="), this[n[0]] = n[1], this 30264 }.bind({}))[0]; 30265 } 30266 30267}); 30268/** 30269 * This file is part of the "box.co.il" project. 30270 * 30271 * (c) Alex Buturlakin [email protected] 30272 */ 30273 30274;(function($) { 30275 /** 30276 * Get Storage value by key. 30277 * 30278 * @param {String} key 30279 * @param {*} [defaultValue] 30280 * 30281 * @return {*} 30282 */ 30283 Storage.getData = function(key, defaultValue) { 30284 defaultValue = defaultValue || undefined; 30285 30286 if(typeof undefined == typeof this['data'] || !(key in this['data'])) { 30287 return defaultValue; 30288 } 30289 30290 return this['data'][key]; 30291 }; 30292 30293 /** 30294 * Check value by key in storage. 30295 * 30296 * @param {String} key 30297 * @return {boolean} 30298 */ 30299 Storage.hasData = function(key) { 30300 return !(typeof undefined == typeof this['data'] || !(key in this['data'])); 30301 }; 30302})(jQuery); 30303/** 30304 * This file is part of the "box.co.il" project. 30305 * 30306 * (c) Alex Buturlakin [email protected] 30307 */ 30308;(function($) { 30309 30310 /** 30311 * Translate message. 30312 * 30313 * @param {String} message 30314 * @param {String} [locale] 30315 * 30316 * @return {String} 30317 */ 30318 $.translate = function(message, locale) { 30319 locale = locale || 'he'; 30320 30321 if(typeof undefined === typeof Storage) { 30322 return message; 30323 } 30324 30325 var localization = Storage.getData('localization', false); 30326 30327 if(false == localization || !(locale in localization) || !(message in localization[locale])) { 30328 return message; 30329 } 30330 30331 return localization[locale][message]; 30332 } 30333})(jQuery); 30334/** 30335 * This file is part of the EXP project. 30336 * (c) Alex Buturlakin [email protected] 30337 * Date: 10.01.15 30338 * Time: 3:07 30339 */ 30340 30341// Keep small extensions and helper functions here. 30342 30343;(function($) { 30344 30345 /** 30346 * Checking image for existing by url. 30347 * 30348 * @param url 30349 * @returns {boolean} 30350 */ 30351 jQuery.imageExists = function(url){ 30352 30353 if(null == url || undefined == url){ 30354 return false; 30355 } 30356 30357 var image = $('<img src="' + url + '" />'); 30358 return image.prop('width') > 0; 30359 }; 30360 30361 /** 30362 * Get url from background 30363 * 30364 * @returns {XML|string|jQuery} 30365 */ 30366 jQuery.fn.parseUrlFromBackground = function (){ 30367 var background = $(this).css('background-image'); 30368 30369 if(undefined == background){ 30370 return null; 30371 } 30372 30373 return background.replace('url("','').replace('")',''); 30374 }; 30375 30376 /** 30377 * Format function. Usage 'Hello, {0}!'.format('Alex'); Output 'Hello, Alex!' 30378 * 30379 * @returns String 30380 */ 30381 String.prototype.format = function() { 30382 var s = this, 30383 i = arguments.length; 30384 30385 while (i--) { 30386 s = s.replace(new RegExp('\\{' + i + '\\}', 'gm'), arguments[i]); 30387 } 30388 return s; 30389 }; 30390 30391 /** 30392 * Update property by path. 30393 * Have var hash = {a:{a: 'optionONE'}} n 30394 * Need to change 'optionOne' to 'optionTwo'. 30395 * Call updatePropertyByPath(hash, 'a.a', 'optionTwo'); 30396 * 30397 * @returns {Object} 30398 */ 30399 function updatePropertyByPath (object, path, value){ 30400 var i, tmp; 30401 var parts = path.split('.'); 30402 30403 for(i = 0; i < parts.length; i++) { 30404 tmp = object[parts[i]]; 30405 if(value !== undefined && i == parts.length - 1) { 30406 tmp = object[parts[i]] = value; 30407 } 30408 else if(tmp === undefined) { 30409 tmp = object[parts[i]] = {}; 30410 } 30411 object = tmp; 30412 } 30413 return object; 30414 } 30415 30416 /** 30417 * 30418 * @param uri 30419 * @param key 30420 * @param value 30421 * @return {*} 30422 */ 30423 $.updateQueryStringParameter = function(uri, key, value) { 30424 var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i"); 30425 var separator = uri.indexOf('?') !== -1 ? "&" : "?"; 30426 if (uri.match(re)) { 30427 return uri.replace(re, '$1' + key + "=" + value + '$2'); 30428 } 30429 else { 30430 return uri + separator + key + "=" + value; 30431 } 30432 }; 30433 30434 /** 30435 * Works like php ucfirst() function 30436 * 30437 * @param {string} str 30438 * @returns {string} 30439 */ 30440 $.ucfirst = function(str) { 30441 var f = str.charAt(0).toUpperCase(); 30442 return f + str.substr(1, str.length-1); 30443 }; 30444 30445 /** 30446 * 30447 * @param {String} str 30448 * @param {String} [charlist] 30449 * @return {XML|void|*|string} 30450 */ 30451 function rtrim(str, charlist) { 30452 charlist = !charlist ? ' \s\xA0' : charlist.replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g, '\$1'); 30453 var re = new RegExp('[' + charlist + ']+$', 'g'); 30454 return str.replace(re, ''); 30455 } 30456 30457 /** 30458 * Display twitter bootstrap alert. 30459 * 30460 * @param {String} message 30461 * @param {String} type 30462 * @param {int} [delay] Delay in ms before alert will dismissed. 30463 * If delay is not defined, alert will not dismiss automatically. 30464 * 30465 * @param {String} [insertMethod] possible values is 'prepend' and 'after'. 30466 * Default value is 'prepend' 30467 * 30468 * @param {String} [customClass] 30469 * @param {boolean} [showClose] 30470 */ 30471 jQuery.fn.showAlert = function(message, type, delay, insertMethod, customClass, showClose) { 30472 showClose = typeof undefined == typeof showClose ? true : showClose; 30473 30474 var container = $(this); 30475 var alertClass = 'display-none alert alert-dismissible alert-{0}'.format(type); 30476 var closeButton = $('<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>'); 30477 30478 insertMethod = insertMethod || 'prepend'; 30479 30480 if(customClass) { 30481 alertClass += ' {0}'.format(customClass); 30482 } 30483
30484 if(0 == container.length) { 30485 return false; 30486 } 30487 30488 var alert = $('<div>', { 30489 'class': alertClass, 30490 'role': 'alert' 30491 }); 30492 30493 var text = $('<span>', { 30494 'class': 'alert-message', 30495 'html': message 30496 }); 30497 30498 if(showClose) { 30499 alert.prepend(closeButton); 30500 } 30501 30502 alert.prepend(text); 30503 30504 var id = $(document).find('.alert').length; 30505 ++id; 30506 alert.attr('id', 'alert-{0}'.format(id)); 30507 30508 // insert to 30509 switch (insertMethod) { 30510 case 'prepend': container.prepend(alert); 30511 break; 30512 30513 case 'append' : container.append(alert); 30514 break; 30515 30516 case 'before' : container.before(alert); 30517 break; 30518 30519 case 'after' : alert.insertAfter(container); 30520 break; 30521 30522 default: alert.insertAfter(container); 30523 } 30524 30525 alert = $('#{0}'.format(alert.attr('id'))); 30526 30527 alert.slideDown(600, function (){ 30528 // close alerts automatically 30529 if(undefined !== delay && null != delay) { 30530 window.setTimeout(function() { 30531 alert.slideUp(600, function() { 30532 alert.alert('close'); 30533 }); 30534 }, delay); 30535 } 30536 }); 30537 30538 return alert; 30539 }; 30540 30541 /** 30542 * Add tooltip to element. 30543 * 30544 * @param {String} [title] 30545 * @param {String} [type] 30546 * @param {String} [effect] 30547 * @param {String} [position] 30548 */ 30549 jQuery.fn.addTooltip = function (title, type, effect, position) { 30550 30551 var defaultType = 'default'; 30552 var defaultEffect = 'fade'; 30553 var defaultPosition = 'top'; 30554 var defaultTitle = 'ToolTip'; 30555 30556 var template = '<div class="tooltip tooltip-{0} {1} {2} in"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'; 30557 30558 $.each($(this), function () { 30559 30560 var el = $(this); 30561 30562 if(!el.is(':visible')) { 30563 return true; 30564 } 30565 30566 var elementDataType = el.data('tooltip-type'); 30567 var elementDataEffect = el.data('tooltip-effect'); 30568 var elementDataPosition = el.data('tooltip-position'); 30569 var elementDataTitle = el.data('tooltip-title'); 30570 30571 var currentType = type || (elementDataType || defaultType); 30572 var currentEffect = effect || (elementDataEffect || defaultEffect); 30573 var currentPosition = position || (elementDataPosition || defaultPosition); 30574 var currentTitle = title || (elementDataTitle || defaultTitle); 30575 30576 el.siblings('.tooltip').remove(); 30577 30578 el.tooltip('destroy').tooltip({ 30579 template: template.format(currentType, currentEffect, currentPosition), 30580 title: currentTitle, 30581 html: true 30582 }); 30583 }); 30584 30585 return $(this); 30586 }; 30587 30588 /** 30589 * Bind values to form elements. 30590 * 30591 * @param {Object} data 30592 * @param {String} selectorType 30593 * @param {String} [name] 30594 */ 30595 jQuery.formBindElements = function(data, selectorType, name) { 30596 name = name || null; 30597 var selectorTpl = ''; 30598 30599 switch (selectorType) { 30600 case 'class': selectorTpl = '.{0}'; 30601 break; 30602 case 'id': selectorTpl = '#{0}'; 30603 break; 30604 case 'data': selectorTpl = '[data-{1}="{0}"]'; 30605 break; 30606 default : 30607 selectorTpl = false; 30608 } 30609 30610 $.each(data, function(id, val) { 30611 var elementSelector = selectorTpl ? selectorTpl.format(id, name) : id; 30612 var element = $(elementSelector); 30613 30614 if(element.length) { 30615 element.val(val); 30616 } 30617 }); 30618 }; 30619 30620 /** 30621 * Add loading state to button. 30622 * 30623 * @param {String} type Possible values are "loading" and "reset" 30624 * @returns {*|HTMLElement} 30625 */ 30626 jQuery.fn.buttonLoading = function(type) { 30627 var button = $(this); 30628 var isDisabled = 'reset' != type; 30629 30630 button.button(type); 30631 button.prop('disabled', isDisabled); 30632 30633 return button; 30634 }; 30635 30636 /** 30637 * Pass twitter devices types ("xs", "xm", "md", "lg"). 30638 * If device have passed type(s), return true, otherwise - false. 30639 * 30640 * @returns {boolean} 30641 */ 30642 jQuery.checkDeviceType = function() { 30643 var args = arguments; 30644 var detected = false; 30645 30646 $.each(args, function() { 30647 if($('body').hasClass('screen-{0}'.format(this))) { 30648 detected = true; 30649 return false; 30650 } 30651 }); 30652 30653 return detected; 30654 }; 30655 30656 /** 30657 * Provide to scroll screen to element. 30658 * 30659 * @param {int} [time] Animation time in ms. Default time is 500ms. 30660 * @param {int} [offsetTop] 30661 * @param {function} [callback] 30662 * 30663 * @returns {*|HTMLElement} 30664 */ 30665 jQuery.fn.scrollToElement = function(time, offsetTop, callback) { 30666 var el = $(this); 30667 time = time || 500; 30668 offsetTop = offsetTop || 0; 30669 callback = 'function' == typeof callback ? callback : function () {}; 30670
30671 if(0 == el.length) { 30672 return el; 30673 } 30674 30675 $('html, body').animate({ 30676 scrollTop: el.offset().top + offsetTop 30677 }, time, callback); 30678 30679 return el; 30680 }; 30681 30682 /** 30683 * Merge jQuery object to one object. 30684 * 30685 * @param {Array} objects 30686 */ 30687 jQuery.mergeJQueryObjects = function (objects) { 30688 return $($.map(objects, function(el){return el.get();})); 30689 }; 30690 30691 /** 30692 * Filter elements by data name and value 30693 * Working with jQuery.data(..) setter 30694 * 30695 * @param {String} prop 30696 * @param {String|Array} [val] 30697 * @returns {*} 30698 */ 30699 $.fn.filterByData = function (prop, val) { 30700 var el = $(this); 30701 30702 if (typeof val === 'undefined') { 30703 return el.filter(function() { 30704 return 'undefined' !== typeof $(this).data(prop); 30705 }); 30706 } 30707 // 15374 30708 30709 return el.filter(function() { 30710 return val instanceof Array ? -1 !== $.inArray($(this).data(prop), val) : val == $(this).data(prop); 30711 }); 30712 }; 30713 30714 /** 30715 * Remove classes by prefix 30716 * 30717 * @param {String} prefix 30718 * @returns {jQuery} 30719 */ 30720 $.fn.removeClassPrefix = function(prefix) { 30721 this.each(function(i, el) { 30722 var classes = el.className.split(" ").filter(function(c) { 30723 return c.lastIndexOf(prefix, 0) !== 0; 30724 }); 30725 el.className = $.trim(classes.join(" ")); 30726 }); 30727 return this; 30728 }; 30729 30730 /** 30731 * Reset form data. 30732 * 30733 * @param {String[]} [exclude] 30734 */ 30735 $.fn.resetForm = function(exclude) { 30736 exclude = exclude || []; 30737 var el = $(this); 30738 30739 // reset text fields. 30740 var elements = el.find('input[type=text], input[type="email"], input[type="password"], textarea, select'); 30741 30742 $.each(elements, function() { 30743 var element = $(this); 30744 30745 if(-1 !== $.inArray(element.attr('name'), exclude)) { 30746 return true; 30747 } 30748 30749 element.val(''); 30750 30751 // select boxes 30752 if('select' == element.prop('tagName').toLowerCase()) { 30753 // un-select 30754 element.find('option:selected').prop('selected', false); 30755 30756 // select first 30757 element.find('option:first').prop('selected', true); 30758 } 30759 }); 30760 }; 30761 30762 /** 30763 * Lock form fields 30764 * 30765 * @param {Boolean} state 30766 * @param {String[]} [exclude] 30767 */ 30768 $.fn.lockForm = function(state, exclude) { 30769 var el = $(this); 30770 30771 // lock form fields. 30772 var elements = el.find('input[type=text], input[type="email"], input[type="password"], textarea, select'); 30773 30774 $.each(elements, function() { 30775 var element = $(this), 30776 tag = element.prop('tagName').toLowerCase() 30777 30778 if(-1 !== $.inArray(element.attr('name'), exclude)) { 30779 return true; 30780 } 30781 30782 if('select' == tag) { 30783 var pe = state ? 'none' : 'auto'; 30784 30785 element.css('pointer-events', pe); 30786 30787 return true; 30788 } 30789 30790 element.prop('readonly', state); 30791 }); 30792 }; 30793 30794 /** 30795 * Populate form elements with selected option. 30796 * // todo@alexbuturlakin: need merge this function with $.fn.populateDefaultData 30797 * @param {jQuery} option 30798 * @param {String[]} exclude 30799 */ 30800 $.fn.populateDefaultDataSelect = function(option, exclude) { 30801 exclude = exclude || []; 30802 var el = $(this), 30803 elements = option.data('default-elements'); 30804 30805 if(typeof elements === typeof undefined || false == elements) { 30806 return false; 30807 } 30808 30809 // reset form 30810 el.resetForm(exclude); 30811 30812 // update data 30813 var data = elements.split('||'); 30814 30815 $.each(data, function() { 30816 var params = this.split('::'); 30817 30818 // check that data has right format 30819 if(false == Array.isArray(params) || 0 == params.length) { 30820 return true; 30821 } 30822 30823 // check in excluded elements 30824 if(-1 !== $.inArray(params[0], exclude)) { 30825 return true; 30826 } 30827 30828 // get element 30829 var element = el.find('[name="{0}"]'.format(params[0])); 30830 30831 // no element found 30832 if(0 == element.length) { 30833 return true; 30834 } 30835 30836 var tag = element.prop('tagName').toLowerCase(); 30837 30838 // if select or text input 30839 if(('select' == tag)) { 30840 element.val(params[1]); 30841 30842 return true; 30843 } 30844 30845 var type = element.attr('type'); 30846 30847 // no type 30848 if(typeof type === typeof undefined) { 30849 element.val(params[1]); 30850 30851 return true; 30852 } 30853 30854 // if text input 30855 if('input' == tag && -1 !== $.inArray(type.toLowerCase(), ['text', 'email'])) { 30856 element.val(params[1]); 30857 } 30858 30859 // if radio 30860 if('input' == tag && 'radio' == type.toLowerCase()) { 30861 params[1] == element.val() ? element.prop('checked', true) : element.prop('checked', false); 30862 } 30863 30864 // trigger event 30865 element.trigger('default-data-populated', [params[1], 'select']); 30866 }); 30867 30868 el.trigger('default-data-populated', [[], 'select']); 30869 }; 30870 30871 /** 30872 * Populate form elements with default data. 30873 * 30874 * @param {Boolean} populate 30875 * @param {String[]} exclude 30876 */ 30877 $.fn.populateDefaultData = function(populate, exclude) { 30878 exclude = exclude || []; 30879 var el = $(this); 30880 30881 // reset form 30882 if(false == populate) { 30883 el.resetForm(exclude); 30884 30885 return el; 30886 } 30887 30888 // or populate values 30889 el.find('[data-default]').each(function() { 30890 var element = $(this), 30891 data = element.data('default'), 30892 tag = element.prop('tagName').toLowerCase(); 30893 30894 // check in excluded elements 30895 if(-1 !== $.inArray(element.attr('name'), exclude)) { 30896 return true; 30897 } 30898 30899 // if select or text input 30900 if(('select' == tag)) { 30901 element.val(data); 30902 30903 return true; 30904 } 30905 30906 var type = element.attr('type'); 30907 30908 // no type 30909 if(typeof type === typeof undefined) { 30910 element.val(data); 30911 30912 return true; 30913 } 30914 30915 // if text input 30916 if('input' == tag && -1 !== $.inArray(type.toLowerCase(), ['text', 'email'])) { 30917 element.val(data); 30918 } 30919 30920 // if radio 30921 if('input' == tag && 'radio' == type.toLowerCase()) { 30922 data == element.val() ? element.prop('checked', true) : element.prop('checked', false); 30923 } 30924 30925 // ?? 30926 30927 // trigger event 30928 element.trigger('default-data-populated', [data, 'checkbox']); 30929 }); 30930 30931 el.trigger('default-data-populated', [[], 'checkbox']); 30932 }; 30933 30934 /** 30935 * Get submit path for form. 30936 * 30937 * @return {String} 30938 */ 30939 $.fn.getFormSubmitPath = function() { 30940 var form = $(this); 30941 30942 // if not a form or form not have action. 30943 if('form' != form.prop('tagName').toLowerCase() || typeof undefined == typeof form.attr('action')) { 30944 return document.URL; 30945 } 30946 30947 var url = form.attr('action'); 30948 30949 url = rtrim(url, '/'); 30950 url += window.location.search; 30951 30952 return url; 30953 }; 30954 30955 /** 30956 * Page reload 30957 * 30958 * @param {{}} [query] 30959 */ 30960 $.pageReload = function(query) { 30961 var url = window.location.href; 30962 30963 if(undefined != query) { 30964 var queryArr = []; 30965 $.each(query, function(key, value) {
30966 queryArr.push('{0}={1}'.format(key, value)); 30967 }); 30968 30969 if(queryArr.length > 0) { 30970 var queryStr = queryArr.join('&'), 30971 sep = url.indexOf('?') > -1 ? '&' : '?'; 30972 30973 url += sep + queryStr; 30974 } 30975 } 30976 30977 window.location.href = url; 30978 }; 30979 30980 /** 30981 * from here - http://stackoverflow.com/questions/1090948/change-url-parameters 30982 * @return {string} 30983 */ 30984 $.updateUrlParam = function(url, param, paramVal) { 30985 var TheAnchor = null; 30986 var newAdditionalURL = ""; 30987 var tempArray = url.split("?"); 30988 var baseURL = tempArray[0]; 30989 var additionalURL = tempArray[1]; 30990 var temp = ""; 30991 30992 if (additionalURL) { 30993 var tmpAnchor = additionalURL.split("#"); 30994 var TheParams = tmpAnchor[0]; 30995 TheAnchor = tmpAnchor[1]; 30996 if(TheAnchor) { 30997 additionalURL = TheParams; 30998 } 30999 31000 tempArray = additionalURL.split("&"); 31001 31002 for (var i=0; i<tempArray.length; i++) { 31003 if(tempArray[i].split('=')[0] != param) { 31004 newAdditionalURL += temp + tempArray[i]; 31005 temp = "&"; 31006 } 31007 } 31008 } else { 31009 var tmpAnchor = baseURL.split("#"); 31010 var TheParams = tmpAnchor[0]; 31011 TheAnchor = tmpAnchor[1]; 31012 31013 if(TheParams) { 31014 baseURL = TheParams; 31015 } 31016 } 31017 31018 if(TheAnchor) { 31019 paramVal += "#" + TheAnchor; 31020 } 31021 31022 var rows_txt = temp + "" + param + "=" + paramVal; 31023 return baseURL + "?" + newAdditionalURL + rows_txt; 31024 }; 31025 31026 /** 31027 * From here - http://stackoverflow.com/a/1634841/1156253 31028 * 31029 * @param {String} url 31030 * @param {String} parameter 31031 */ 31032 $.removeUrlParam = function(url, parameter) { 31033 //prefer to use l.search if you have a location/link object 31034 var urlparts = url.split('?'); 31035 if (urlparts.length>=2) { 31036 31037 var prefix= encodeURIComponent(parameter)+'='; 31038 var pars= urlparts[1].split(/[&;]/g); 31039 31040 //reverse iteration as may be destructive 31041 for (var i= pars.length; i-- > 0;) { 31042 //idiom for string.startsWith 31043 if (pars[i].lastIndexOf(prefix, 0) !== -1) { 31044 pars.splice(i, 1); 31045 } 31046 } 31047 31048 url= urlparts[0] + (pars.length > 0 ? '?' + pars.join('&') : ""); 31049 return url; 31050 } else { 31051 return url; 31052 } 31053 }; 31054 31055 /** 31056 * Show simple ajax modal 31057 * 31058 * @param {string} path 31059 * @param {function} callback 31060 * @param {{}} params 31061 */ 31062 $.showXHRModal = function(path, callback, params) { 31063 callback = callback || function() {}; 31064 params = params || {}; 31065 31066 var options = { 31067 type: 'iframe', 31068 padding: 0 31069 }; 31070 31071 options = $.merge(options, params); 31072 31073 $.get(path, function (response) { 31074 // user not loggined 31075 if (3 == response.status) { 31076 window.location = Storage.getData('app_url') + 'user/login'; 31077 31078 return; 31079 } 31080 31081 // on error 31082 if(0 == response.status) { 31083 return; 31084 } 31085 31086 options.content = response.html; 31087 options.afterShow = function() { callback.call(this, params, response) }; 31088 31089 $.fancybox.open(options); 31090 }); 31091 }; 31092 31093 /** 31094 * Show error in modal window. 31095 * 31096 * @param {String} message 31097 */ 31098 $.showError = function(message) { 31099 var html = '<div class="modal-error"><div class="modal-header"><h3>{0}</h3></div><div class="modal-body">{1}</div></div>'; 31100 31101 $.fancybox.open({ 31102 type: 'iframe', 31103 padding: 0, 31104 // autoSize: false, 31105 // width: '400px', 31106 content: html.format($.translate('Error!'), message) 31107 }); 31108 }; 31109 31110 /** 31111 * Show success modal window 31112 * 31113 * @param {String} title 31114 * @param {String} text 31115 * @param {String|Boolean} [destination] 31116 * @param {Boolean} [disableRedirect] 31117 */ 31118 $.showSuccess = function (title, text, destination, disableRedirect) { 31119 disableRedirect = disableRedirect || false; 31120 31121 var html = '<div class="modal-ok">', 31122 head = '<div class="modal-header"><span class="UISectionTitleSummary UILabelIconValid">{0}</span></div>'.format(title), 31123 body = '<div class="modal-body">{0}</div>'.format(text), 31124 foot = '<div class="modal-footer"><button class="btn btn-primary close-window">{0}</button></div>'.format($.translate('Close')); 31125 31126 html = html + head + body + foot + '</div>'; 31127 31128 var redirect = function() { 31129 if(disableRedirect) { 31130 return true; 31131 } 31132 31133 if(typeof undefined === typeof destination) { 31134 window.location.href = window.location.href; 31135 } else { 31136 window.location.href = destination; 31137 } 31138 }; 31139 31140 $.fancybox.open({ 31141 content: html, 31142 padding: 0, 31143 type: 'iframe', 31144 afterShow: function () { 31145 var btn = $('button.close-window'); 31146 btn.click(function(){ 31147 $.fancybox.close(); 31148 redirect(); 31149 }); 31150 }, 31151 afterClose: function () { 31152 redirect(); 31153 } 31154 }); 31155 }; 31156})(jQuery); 31157 31158 31159 31160;(function($) { 31161 $(document).ready(function() { 31162 31163 var regVerifyForm = $("#domain-registrant-verification"); 31164 31165 let regexName = /^[a-zA-Z\s]+$/; 31166 let regexCity = /^[a-zA-Z\s]+$/;
31167 let regexStreet = /^[A-Za-z0-9 .,-]+$/; 31168 let regexZip = /^\d{5,7}$/; 31169 let regexOrgID = /^5\d{8}$/; 31170 let regexOrgName = /^[a-zA-Z0-9.&\-"' ]+$/; 31171 31172 function validateInput(input, regex) { 31173 let value = $(input).val(); 31174 if (!regex.test(value)) { 31175 $(input).addClass("input-error"); 31176 return false; 31177 } else { 31178 $(input).removeClass("input-error"); 31179 return true; 31180 } 31181 } 31182 31183 //name 31184 regVerifyForm.find('input[name="name"]').on("input", function () { 31185 31186 let value = $(this).val(); 31187 if (!regexName.test(value)) { 31188 $(this).val(value.replace(/[^a-zA-Z\s]/g, '').substring(0, 150)); 31189 } 31190 validateInput(this, regexName); 31191 }); 31192 31193 //city 31194 regVerifyForm.find('input[name="address_city"]').on("input", function () { 31195 31196 let value = $(this).val(); 31197 if (!regexCity.test(value)) { 31198 $(this).val(value.replace(/[^a-zA-Z\s]/g, '').substring(0, 150)); 31199 } 31200 validateInput(this, regexCity); 31201 }); 31202 31203 //street 31204 regVerifyForm.find('input[name="address_street"]').on("input", function () { 31205 31206 let value = $(this).val(); 31207 if (!regexStreet.test(value)) { 31208 $(this).val(value.replace(/[^A-Za-z0-9 .,-]/g, '').substring(0, 150)); 31209 } 31210 validateInput(this, regexStreet); 31211 }); 31212 31213 //zip 31214 regVerifyForm.find('input[name="address_zip"]').on("input", function () { 31215 validateInput(this, regexZip); 31216 }); 31217 31218 //organization_number 31219 regVerifyForm.find('input[name="organization_number"]').on("input", function () { 31220 31221 let value = $(this).val(); 31222 31223 if (!regexOrgID.test(value)) { 31224 $(this).val(value.replace(/\D/g, '').replace(/^(\d{1})/, '5').substring(0, 9)); 31225 } 31226 validateInput(this, regexOrgID); 31227 }); 31228 31229 //organization_name 31230 regVerifyForm.find('input[name="organization_name"]').on("input", function () { 31231 31232 let value = $(this).val(); 31233 31234 validateInput(this, regexOrgName); 31235 }); 31236 31237 //phone 31238 regVerifyForm.find('input[name="phone_number"]').on("input", function () { 31239 31240 let value = $(this).val(); 31241 31242 value.replace(/\D/g, ''); 31243 31244 if (!isValidIsraeliPhone(value)) { 31245 $(this).addClass("input-error"); 31246 $(this).val(value.replace(/\D/g, '').substring(0, 10)); 31247 } else { 31248 $(this).removeClass("input-error"); 31249 } 31250 }); 31251 31252 31253 regVerifyForm.find(":input").on("invalid", function() { 31254 this.setCustomValidity(translations['this input is required field'] || key); 31255 }).on("input", function() { 31256 this.setCustomValidity(""); 31257 }); 31258 31259 regVerifyForm.on("submit", function (e) { 31260 31261 let valid = true; 31262 31263 $("#domain-registrant-verification-errors").empty(); 31264 31265 if ($("#name").length) { 31266 valid &= validateInput("#name", regexName) ? true : (addErrorMessage("Name Is Invalid"), false); 31267 } 31268 valid &= validateInput("#address_city", regexCity) ? true : (addErrorMessage("City Is Invalid"), false); 31269 valid &= validateInput("#address_street", regexStreet) ? true : (addErrorMessage("Address Is Invalid"), false); 31270 valid &= validateInput("#address_zip", regexZip) ? true : (addErrorMessage("Zip is required"), false); 31271 if ($("#organization_number").length) { 31272 valid &= validateInput("#organization_number", regexOrgID) ? true : (addErrorMessage("Org ID Is Invalid"), false); 31273 } 31274 if ($("#organization_name").length) { 31275 valid &= validateInput("#organization_name", regexOrgName) ? true : (addErrorMessage("Org Name Is Invalid"), false); 31276 } 31277 valid &= isValidIsraeliPhone($("#phone_number").val()) ? true : (addErrorMessage("Phone Number Is Invalid"), false); 31278 valid &= validateVerificationForm()? true : (addErrorMessage("Please select at least one file for verification documents"), false); 31279 31280 31281 if (!valid) { 31282 e.preventDefault(); 31283 } 31284 31285 }); 31286 31287 function addErrorMessage(key) { 31288 errMsgDiv = $('#domain-registrant-verification-errors'); 31289 var message = translations[key] || key; 31290 errMsgDiv.append('<p>' + message + '</p>'); 31291 } 31292 31293 function isValidIsraeliPhone(phone) { 31294 31295 if (phone.length !== 9 && phone.length !== 10) { 31296 $('#phone_number').addClass("input-error"); 31297 return false;
31298 } 31299 31300 var regex = /^((\+972|0)([2-9])[0-9]{7}|(\+972|0)(2|3|4|7|8|9)[0-9]{7}|(\+972|0)5[0-9]{8}|(\+972|0)7[0-9]{8})$/; 31301 if (phone.startsWith('07') && phone.length !== 10) { 31302 $('#phone_number').addClass("input-error"); 31303 return false; 31304 } 31305 if (phone.startsWith('05') && phone.length !== 10) { 31306 $('#phone_number').addClass("input-error"); 31307 return false; 31308 } 31309 $('#phone_number').removeClass("input-error"); 31310 return regex.test(phone); 31311 } 31312 31313 let maxIdentityFiles = 5; 31314 let currentVisible = 1; 31315 31316 $('#addButton').click(function() { 31317 if (currentVisible < maxIdentityFiles) { 31318 currentVisible++; 31319 $('#identity' + currentVisible).show(); 31320 } 31321 }); 31322 31323 $('#removeButton').click(function() { 31324 if (currentVisible > 1) { 31325 $('#identity' + currentVisible).hide().val(''); 31326 currentVisible--; 31327 } 31328 }); 31329 31330 31331 }); 31332})(jQuery); 31333 31334 31335// document.addEventListener('DOMContentLoaded', () => { 31336// const addButton = document.getElementById('addButton'); 31337// const removeButton = document.getElementById('removeButton'); 31338// const maxInputs = 5; // Total number of inputs 31339// let visibleInputs = 1; // Start with only one input visible 31340 31341// // Add button functionality 31342// addButton.addEventListener('click', () => { 31343// if (visibleInputs < maxInputs) { 31344// visibleInputs++; 31345// const nextInput = document.getElementById(`identity${visibleInputs}`); 31346// if (nextInput) { 31347// nextInput.style.display = 'block'; 31348// } 31349// } 31350// }); 31351 31352// // Remove button functionality 31353// removeButton.addEventListener('click', () => { 31354// if (visibleInputs > 1) { 31355// const currentInput = document.getElementById(`identity${visibleInputs}`); 31356// if (currentInput) { 31357// currentInput.value = ''; // Clear the value 31358// currentInput.style.display = 'none'; 31359// } 31360// visibleInputs--; 31361// } 31362// }); 31363// }); 31364/** 31365 * This file is part of the box.co.il project. 31366 31367 * (c) Alex Buturlakin [email protected] 31368 */ 31369;(function($) { 31370 31371 // set custom messages for validation errors 31372 $.validatorMessages({ 31373 valid_email: $.translate('Only English letters (a-z), numbers, periods, @<br><span>Example: [email protected]</span>'), 31374 english: $.translate('Only English letters (a-z)'), 31375 // company_name: $.translate('Name Company Limited'), 31376 is_natural: $.translate('Only digits (0-9)'), 31377 max_length: $.translate('Up to {1} Characters'), 31378 length_one_or_two: $.translate('{1} characters'), 31379 password: [ 31380 $.translate('At least 8 characters'), 31381 $.translate('At least one English letter (a-z)'), 31382 $.translate('Contain the number one (9-0)') 31383 ], 31384 one_word: $.translate('First Name'), 31385 two_words: $.translate('Last Name'), 31386 street: $.translate('Street is required with house num'), 31387 alpha_numeric_space_dot: $.translate('Only English letters (a-z), numbers (0-9)'), 31388 english_numeric: $.translate('Only English letters (a-z), numbers (0-9)') 31389 31390 }); 31391 31392 // forms validation rules 31393 window.validationRules = {}; 31394 31395 var registerZipFieldRules = { 31396 rules: 'required|is_natural|length_one_or_two[7]|callback_valid_zip_code', 31397 messages: { 31398 required: false, 31399 callback_valid_zip_code: $.translate('Zip is invalid') 31400 }, 31401 custom: { 31402 callback_valid_zip_code: function(field) { 31403 return !window.isInvalidZipCode(field.value); 31404 } 31405 } 31406 }; 31407 31408 // #user-auth-register-company form 31409 window.validationRules.registerCompanyRules = { 31410 email: { 31411 rules: 'required|valid_email', 31412 messages: { 31413 required: false 31414 } 31415 }, 31416 name: { 31417 rules: 'required|company_name|english_numeric|words_count_min[2]', 31418 messages: { 31419 required: false, 31420 words_count_min: false, 31421 company_name: false 31422 } 31423 }, 31424 id: { 31425 rules: 'required|is_natural', 31426 messages: { 31427 required: false 31428 } 31429 }, 31430 invoice: { 31431 rules: 'required|english_numeric', 31432 messages: { 31433 required: false 31434 } 31435 }, 31436 tel1: { 31437 rules: 'required|is_natural', 31438 messages: { 31439 required: false 31440 } 31441 }, 31442 tel3: { 31443 rules: 'required|is_natural', 31444 messages: { 31445 required: false 31446 } 31447 }, 31448 tel4: { 31449 rules: 'required|is_natural', 31450 // disable validation if element is hidden 31451 depends: function(field) { 31452 var el = $(field.element); 31453 31454 return !el.closest('.form-control-inner').hasClass('hidden'); 31455 }, 31456 messages: { 31457 required: false 31458 } 31459 }, 31460 street_name: { 31461 rules: 'required|english', 31462 messages: { 31463 required: false 31464 } 31465 }, 31466 street_number: { 31467 rules: 'required|is_natural', 31468 messages: { 31469 required: false 31470 } 31471 }, 31472 city: { 31473 rules: 'required|english', 31474 messages: { 31475 required: false 31476 } 31477 }, 31478 zip: registerZipFieldRules, 31479 password: { 31480 rules: 'required|password', 31481 messages: { 31482 required: false 31483 } 31484 }, 31485 password2: { 31486 rules: 'required|matches[password]', 31487 messages: { 31488 required: false, 31489 matches: $.translate('The passwords does not match') 31490 } 31491 }, 31492 approve_terms: { 31493 rules: 'required', 31494 messages: { 31495 required: false 31496 } 31497 } 31498 }; 31499 31500 // #user-auth-register-user form 31501 window.validationRules.registerUserRules = { 31502 email: { 31503 rules: 'required|valid_email', 31504 messages: { 31505 required: false 31506 } 31507 }, 31508 name: { 31509 rules: 'required|one_word|two_words|english', 31510 messages: { 31511 required: false 31512 } 31513 }, 31514 tel1: { 31515 rules: 'required|is_natural', 31516 messages: { 31517 required: false 31518 } 31519 }, 31520 tel3: { 31521 rules: 'required|is_natural', 31522 messages: { 31523 required: false 31524 } 31525 }, 31526 street_name: { 31527 rules: 'required|english', 31528 messages: { 31529 required: false 31530 } 31531 }, 31532 street_number: { 31533 rules: 'required|is_natural', 31534 messages: { 31535 required: false 31536 } 31537 }, 31538 city: { 31539 rules: 'required|english', 31540 messages: { 31541 required: false 31542 } 31543 }, 31544 zip: registerZipFieldRules, 31545 password: { 31546 rules: 'required|password', 31547 messages: { 31548 required: false 31549 } 31550 }, 31551 password2: { 31552 rules: 'required|matches[password]', 31553 messages: { 31554 required: false, 31555 matches: $.translate('The passwords does not match') 31556 } 31557 }, 31558 approve_terms: { 31559 rules: 'required', 31560 messages: { 31561 required: false 31562 } 31563 }, 31564 tel4: { 31565 rules: 'required|is_natural', 31566 // disable validation if element is hidden 31567 depends: function(field) { 31568 var el = $(field.element); 31569 31570 return !el.closest('.form-control-inner').hasClass('hidden'); 31571 }, 31572 messages: { 31573 required: false 31574 } 31575 } 31576 }; 31577 31578 // Unified register form (private + company) 31579 window.validationRules.registerRules = { 31580 email: { 31581 rules: 'required|valid_email', 31582 messages: { 31583 required: false 31584 } 31585 }, 31586 name: { 31587 rules: 'required|one_word|two_words|english', 31588 messages: { 31589 required: false 31590 } 31591 }, 31592 id: { 31593 rules: 'required|is_natural', 31594 depends: function(field) { 31595 var form = $(field.element).closest('form'); 31596 return form.find('[name="clientType"]:checked').val() === 'company'; 31597 }, 31598 messages: { 31599 required: false 31600 } 31601 }, 31602 invoice: { 31603 rules: 'required|english_numeric', 31604 depends: function(field) { 31605 var form = $(field.element).closest('form'); 31606 return form.find('[name="clientType"]:checked').val() === 'company'; 31607 }, 31608 messages: { 31609 required: false 31610 } 31611 }, 31612 tel1: { 31613 rules: 'required|is_natural', 31614 messages: { 31615 required: false 31616 } 31617 }, 31618 tel3: { 31619 rules: 'required|is_natural', 31620 messages: { 31621 required: false 31622 } 31623 }, 31624 tel4: { 31625 rules: 'required|is_natural', 31626 depends: function(field) { 31627 var el = $(field.element); 31628 return !el.closest('.form-control-inner').hasClass('hidden'); 31629 }, 31630 messages: { 31631 required: false 31632 } 31633 }, 31634 street_name: { 31635 rules: 'required|english', 31636 messages: { 31637 required: false 31638 } 31639 }, 31640 street_number: { 31641 rules: 'required|is_natural', 31642 messages: { 31643 required: false 31644 } 31645 }, 31646 city: { 31647 rules: 'required|english', 31648 messages: { 31649 required: false 31650 } 31651 }, 31652 zip: registerZipFieldRules, 31653 password: { 31654 rules: 'required|password', 31655 messages: { 31656 required: false 31657 } 31658 }, 31659 password2: { 31660 rules: 'required|matches[password]', 31661 messages: { 31662 required: false, 31663 matches: $.translate('The passwords does not match') 31664 } 31665 }, 31666 approve_terms: { 31667 rules: 'required', 31668 messages: { 31669 required: false 31670 } 31671 } 31672 }; 31673 31674 // password reset 2 form rules 31675 window.validationRules.resetPasswordRules = { 31676 password: { 31677 rules: 'required|password', 31678 messages: { 31679 required: false 31680 } 31681 }, 31682 password2: { 31683 rules: 'required|matches[password]', 31684 messages: { 31685 required: false, 31686 matches: $.translate('The passwords does not match') 31687 } 31688 } 31689 }; 31690 31691 window.validationRules.purchaseDomainRulesOwnerName = { 31692 user: { 31693 rules: 'required|one_word|two_words|english', 31694 group: 'owner', 31695 messages: { 31696 required: $.translate('full name is required') 31697 } 31698 }, 31699 company: { 31700 rules: 'required|english_numeric|words_count_min[2]', 31701 group: 'owner', 31702 messages: {
31703 required: $.translate('Company name is invalid'), 31704 words_count_min: $.translate('Company name is invalid') 31705 } 31706 } 31707 } 31708 31709 // domain purchase domain admin rules 31710 window.validationRules.purchaseDomainRules = { 31711 // owner info section 31712 ownerEmail: { 31713 rules: 'required|valid_email', 31714 group: 'owner', 31715 messages: { 31716 required: $.translate('Email Is Required') 31717 } 31718 }, 31719 ownerFullName: { 31720 rules: window.validationRules.purchaseDomainRulesOwnerName.user.rules, 31721 group: 'owner', 31722 messages: window.validationRules.purchaseDomainRulesOwnerName.user.messages 31723 }, 31724 ownerCompanyId: { 31725 rules: 'is_natural|callback_israeli_company_id', 31726 group: 'owner', 31727 messages: { 31728 required: $.translate('Company number is required'), 31729 callback_israeli_company_id: $.translate('Company ID must be 9 digits starting with 5') 31730 }, 31731 custom: { 31732 callback_israeli_company_id: function(field) { 31733 // Get the form element 31734 var form = $(field.element).closest('form'); 31735 if (form.length === 0) { 31736 form = $('#ownerModal'); 31737 } 31738 31739 // Get the country field value 31740 var countryEl = form.find('[name="ownerAddressCountry"], #ownerAddressCountry'); 31741 var country = countryEl.length > 0 ? countryEl.val() : ''; 31742 31743 // Get the client type to check if company ID is required 31744 var clientType = form.find('[name="clientType"]:checked').val(); 31745 var isRequired = clientType === 'company'; 31746 31747 // Get the company ID value 31748 var companyId = field.value || ''; 31749 31750 // If not required or country is not IL, skip this validation 31751 if (!isRequired || country !== 'IL' || !companyId) { 31752 return true; 31753 } 31754 31755 // Validate: must be 9 digits and start with 5 31756 var isValid = /^5\d{8}$/.test(companyId); 31757 31758 return isValid; 31759 } 31760 } 31761 }, 31762 ownerAddressStreet: { 31763 rules: 'required|street|alpha_numeric_space_dot', 31764 group: 'owner', 31765 messages: { 31766 required: $.translate('Street is required') 31767 } 31768 }, 31769 ownerAddressCity: { 31770 rules: 'required|english', 31771 group: 'owner', 31772 messages: { 31773 required: $.translate('City is required') 31774 } 31775 }, 31776 ownerAddressZip: { 31777 rules: 'required|is_natural|length_one_or_two[7]', 31778 group: 'owner', 31779 messages: { 31780 required: $.translate('Zip is required'), 31781 length_one_or_two: $.translate('{1} characters') 31782 } 31783 }, 31784 ownerTel1: { 31785 rules: 'required|is_natural', 31786 group: 'owner' 31787 }, 31788 ownerTel3: { 31789 rules: 'required|is_natural', 31790 group: 'owner' 31791 }, 31792 ownerTel4: { 31793 rules: 'required|is_natural', 31794 group: 'owner', 31795 // disable validation if element is hidden 31796 depends: function(field) { 31797 var el = $(field.element); 31798 return !el.hasClass('hidden'); 31799 } 31800 }, 31801 ownerFax1: { 31802 rules: 'is_natural', 31803 group: 'owner' 31804 }, 31805 ownerFax2: { 31806 rules: 'is_natural', 31807 group: 'owner' 31808 }, 31809 ownerFax3: { 31810 rules: 'is_natural', 31811 group: 'owner' 31812 }, 31813 31814 // admin info section 31815
31816 adminEmail: { 31817 rules: 'required|valid_email', 31818 group: 'admin', 31819 messages: { 31820 required: $.translate('Email Is Required') 31821 } 31822 }, 31823 adminFullName: { 31824 rules: 'required|one_word|two_words|english', 31825 group: 'admin', 31826 messages: { 31827 required: $.translate('full name is required') 31828 } 31829 }, 31830 adminAddressStreet: { 31831 rules: 'required|street|alpha_numeric_space_dot', 31832 group: 'admin', 31833 messages: { 31834 required: $.translate('Street is required') 31835 } 31836 }, 31837 adminAddressCity: { 31838 rules: 'required|english', 31839 group: 'admin', 31840 messages: { 31841 required: $.translate('City is required') 31842 } 31843 }, 31844 adminAddressZip: { 31845 rules: 'required|is_natural|length_one_or_two[7]', 31846 group: 'admin', 31847 messages: { 31848 required: $.translate('Zip is required'), 31849 length_one_or_two: $.translate('{1} characters') 31850 } 31851 }, 31852 adminTel1: { 31853 rules: 'required|is_natural', 31854 group: 'admin' 31855 }, 31856 adminTel3: { 31857 rules: 'required|is_natural', 31858 group: 'admin' 31859 }, 31860 adminTel4: { 31861 rules: 'required|is_natural', 31862 group: 'admin', 31863 // disable validation if element is hidden 31864 depends: function(field) { 31865 var el = $(field.element); 31866 return !el.hasClass('hidden'); 31867 } 31868 }, 31869 adminFax1: { 31870 rules: 'is_natural', 31871 group: 'admin' 31872 }, 31873 adminFax2: { 31874 rules: 'is_natural', 31875 group: 'admin' 31876 }, 31877 adminFax3: { 31878 rules: 'is_natural', 31879 group: 'admin' 31880 }, 31881 31882 // purchase credit number validation 31883 creditNumber: { 31884 rules: 'required|valid_credit_card', 31885 messages: { 31886 required: false, 31887 valid_credit_card: $.translate('id is invalid') 31888 }, 31889 group: 'payment' 31890 }, 31891 creditExpirationYear: { 31892 rules: 'required|greater_than_current_year', 31893 messages: { 31894 greater_than_current_year: 'Year' 31895 }, 31896 group: 'payment', 31897 custom: { 31898 greater_than_current_year: function(field) { 31899 return false; 31900 } 31901 } 31902 }, 31903 creditExpirationMonth: { 31904 rules: 'required|greater_than_current_month', 31905 messages: { 31906 'greater_than_current_month': 'Month error' 31907 }, 31908 group: 'payment', 31909 custom: { 31910 greater_than_current_month: function(field) { 31911 return false; 31912 } 31913 } 31914 } 31915 }; 31916 31917})(jQuery); 31918/** 31919 * This file is part of the box.co.il project. 31920 31921 * (c) Alex Buturlakin [email protected] 31922 */ 31923;(function($) { 31924 window.isInvalidZipCode = function(zip) { 31925 if (!/^\d{7}$/.test(zip)) { 31926 return false; 31927 } 31928 31929 if (/^(\d)\1{6}$/.test(zip)) { 31930 return true; 31931 } 31932 31933 var ascending = true; 31934 var descending = true; 31935 var i; 31936 var current; 31937 var previous; 31938 31939 for (i = 1; i < zip.length; i++) { 31940 current = parseInt(zip.charAt(i), 10); 31941 previous = parseInt(zip.charAt(i - 1), 10); 31942 31943 if (current !== previous + 1) { 31944 ascending = false; 31945 } 31946 if (current !== previous - 1) { 31947 descending = false; 31948 } 31949 } 31950 31951 return ascending || descending; 31952 }; 31953 31954 window.isInvalidOptionalPhone = function(phone) { 31955 phone = $.trim(phone); 31956 31957 if (phone === '') { 31958 return false; 31959 } 31960 31961 if (!/^[\d\s+\-().]+$/.test(phone)) { 31962 return true; 31963 } 31964 31965 var digits = phone.replace(/\D/g, ''); 31966 31967 return digits.length < 9 || digits.length > 15; 31968 }; 31969 31970 /** 31971 * Get list of validation rules with messages. 31972 * 31973 * @returns {{}} 31974 */ 31975 jQuery.fn.getValidationRulesList = function () { 31976 31977 var rules = $(this).data('validation-rules'); 31978 31979 return typeof rules === typeof undefined || rules === false ? {} : rules; 31980 }; 31981 31982 /** 31983 * Get list of validation rules with messages. 31984 * 31985 * @returns {{}} 31986 */ 31987 jQuery.fn.hasValidationRule = function (rule) { 31988 31989 var rules = $(this).getValidationRulesList(); 31990 31991 return rule in rules; 31992 }; 31993 31994 /** 31995 * Add status to validated form field 31996 * 31997 * @param {String} status 31998 */ 31999 jQuery.fn.validationSetStatus = function(status) { 32000 var container = $(this).closest('.validation'); 32001 32002 // add indicator if not exists 32003 if(false == container.hasClass('validation-no-indicate') && 0 == container.find('.validation-state').length) { 32004 container.append('<span class="validation-state">'); 32005 } 32006 32007 // remove all statuses 32008 if('none' == status) { 32009 container.removeClass('validation-valid validation-not-valid'); 32010 } 32011 32012 // valid 32013 if('valid' == status) { 32014 container.removeClass('validation-not-valid'); 32015 container.addClass('validation-valid'); 32016 } 32017
32018 // not valid 32019 if('not-valid' == status) { 32020 container.removeClass('validation-valid'); 32021 container.addClass('validation-not-valid'); 32022 } 32023 }; 32024 32025 /** 32026 * Remove validation errors 32027 */ 32028 jQuery.fn.validatorClearErrors = function() { 32029 var el = $(this); 32030 32031 el.find('.alert-danger').remove(); 32032 el.find('.has-error').removeClass('has-error'); 32033 }; 32034 32035 /** 32036 * This extensions provide default validation. 32037 * Creates tooltips for validation errors. 32038 * 32039 * todo@alexbuturlakin: refactoring - create jquery plugin for validate2 package 32040 * 32041 * @param {{}} rules 32042 * @param {String|function} [container] 32043 * @param [errorHandler] 32044 */ 32045 jQuery.fn.validatorEnableDefaultValidation = function (rules, container, errorHandler) { 32046 var form = $(this); 32047 32048 // validation callback for form 32049 var callbackForm = function (status, errors, groups) { 32050 var errorsList = {}, 32051 errorContainer; 32052 32053 if('function' == typeof container) { 32054 errorContainer = container(status, errors, groups); 32055 } else { 32056 errorContainer = $(container); 32057 errorContainer = 0 == container.length ? form : container; 32058 } 32059 32060 // clear container 32061 errorContainer.validatorClearErrors(); 32062 32063 // all is ok 32064 if(status) { 32065 return true; 32066 } 32067 32068 // get all errors 32069 $.each(errors, function(name, values) { 32070 var el = form.find('[name="{0}"]'.format(name)), 32071 label = el.data('error-label'), 32072 elContainer = el.closest('.form-group'); 32073 32074 elContainer.addClass('has-error'); 32075 32076 if(null == label) { 32077 label = elContainer.find('label') 32078 .clone() //clone the element 32079 .children(':not(span)') //select all the children 32080 .remove() //remove all the children 32081 .end() //again go back to selected element 32082 .text().trim(); 32083 } 32084 32085 if(typeof undefined == typeof label || null == label) { 32086 label = null; 32087 } else { 32088 label = '<span class="error-field">{0}</span>'.format(label); 32089 } 32090 32091 errorsList[name] = { 32092 error: values[0]['message'], 32093 label: label, 32094 rule: values[0]['rule'] 32095 }; 32096 }); 32097 32098 // call callback 32099 if('function' == typeof errorHandler) { 32100 errorsList = errorHandler(errorsList); 32101 } 32102 32103 // show errors in container 32104 if($.isPlainObject(errorsList)) { 32105 var message = $.map(errorsList, function(data) { 32106 return null == data['label'] ? data['error'] : '{0}: {1}'.format(data['label'], data['error']); 32107 }).join('<br>'); 32108 32109 errorContainer.showAlert(message, 'danger', null, 'append', null, false); 32110 } 32111 }; 32112 32113 // init validator 32114 var validator = new FormValidator(form.attr('name'), [], { 32115 callbacks: {form: [callbackForm]} 32116 }); 32117 32118 // add rules to FormValidator 32119 $.each(rules, function(name, data) { 32120 var el = form.find('[name="{0}"]'.format(name)); 32121 var dataRules = {}; 32122 var messages = 'messages' in data ? data.messages : {}; 32123 32124 // add validation handler 32125 validator._addField(data, name); 32126 32127 // save rules in el data 32128 var rulesArr = data.rules.split('|'); 32129 32130 for (var k in rulesArr) { 32131 var info = validator._getRuleInfo(rulesArr[k]); 32132 32133 // if message was overridden 32134 if (0 !== Object.keys(messages).length && info.method in messages) { 32135 // ping about it validator 32136 validator.setMessage(name + '.' + info.method, messages[info.method]); 32137 dataRules[info.method] = messages[info.method]; 32138 } else { 32139 dataRules[info.method] = validator._getMessage(name, info.method, info.params); 32140 } 32141 } 32142 32143 // set default status 32144 if(undefined !== el.val() && null !== el.val() && '' != el.val()) { 32145 el.addClass('has-predefined-value'); 32146 32147 // set status 32148 el.validationSetStatus('valid') 32149 } 32150 32151 // add rules to data 32152 el.data('validation-rules', dataRules); 32153 }); 32154 32155 form.data('validator', validator); 32156 }; 32157 32158 /** 32159 * This extensions provide to validate forms fields and show errors in qtip2 tooltips. 32160 * Creates tooltips for validation errors. 32161 * 32162 * todo@alexbuturlakin: refactoring - create jquery plugin for validate2 package 32163 * 32164 * @param rules 32165 */ 32166 jQuery.fn.validatorEnableTooltipValidation = function (rules) { 32167 // validation callback for form 32168 var callbackForm = function (status, errors) { 32169 var form = $(this); 32170 32171 if(true == status) { 32172 return true; 32173 } 32174 32175 // get elements with errors 32176 var selectors = []; 32177 32178 $.each(errors, function(name, values) { 32179 selectors.push('[name="{0}"]'.format(name)); 32180 }); 32181 32182 var inputs = form.find(selectors.join(','));
32183 var controls = inputs.closest('.validation'); 32184 32185 // highlight 32186 controls.addClass('validation-not-valid'); 32187 inputs.addClass('highlight'); 32188 32189 setTimeout(function(){ 32190 inputs.removeClass('highlight'); 32191 }, 2000); 32192 32193 // focus to first error 32194 var inputFirst = inputs.eq(0); 32195 inputFirst.scrollToElement(500, -60, function() { 32196 inputFirst.focus(); 32197 32198 // if select2 32199 if(inputFirst.hasClass('select2')) { 32200 inputFirst.select2("open"); 32201 } 32202 }); 32203 }; 32204 32205 // validation callback for fields 32206 var callbackFields = function (status, type, field, errors) { 32207 var el = $(this); 32208 var tooltip = el.qtip().tooltip; 32209 32210 // =) 32211 if('form' == type) { 32212 return true; 32213 } 32214 32215 if(status) { 32216 // disable tooltip 32217 el.qtip('hide'); 32218 el.qtip('disable'); 32219 32220 // set status 32221 el.validationSetStatus('valid') 32222 } else { 32223 // enable tooltip 32224 el.qtip('disable', false); 32225 el.qtip('show'); 32226 32227 // hide error messages in tooltip 32228 32229 // get selectors 32230 var liSelectors = ['[data-rule="rule-default"]']; 32231 for(var k in errors) { 32232 var rule = errors[k]['rule']; 32233 32234 liSelectors.push('[data-rule="{0}"]'.format(rule)); 32235 } 32236 32237 // hide not actual errors and show actual 32238 if(tooltip && 0 !== tooltip.length) { 32239 var notActual = tooltip.find('li:not({0})'.format(liSelectors.join(','))); 32240 var actual = tooltip.find(liSelectors.join(',')); 32241 32242 notActual.hide(500); 32243 actual.show(500); 32244 } 32245 32246 // set status 32247 '' == el.val() ? el.validationSetStatus('none') : el.validationSetStatus('not-valid'); 32248 } 32249 }; 32250 32251 var form = $(this); 32252 var validator = new FormValidator(form.attr('name'), [], { 32253 callbacks: {fields: [callbackFields], form: [callbackForm]} 32254 }); 32255 32256 // add rules to FormValidator 32257 $.each(rules, function(name, data) { 32258 var el = form.find('[name="{0}"]'.format(name)); 32259 var dataRules = {}; 32260 var messages = 'messages' in data ? data.messages : {}; 32261 32262 // add validation handler 32263 validator._addField(data, name); 32264 32265 // save rules in el data 32266 var rulesArr = data.rules.split('|'); 32267 32268 for(var k in rulesArr) { 32269 var info = validator._getRuleInfo(rulesArr[k]); 32270 32271 // if message was overridden 32272 if(0 !== Object.keys(messages).length && info.method in messages) { 32273 // ping about it validator 32274 validator.setMessage(name+'.'+info.method, messages[info.method]); 32275 dataRules[info.method] = messages[info.method]; 32276 } else { 32277 dataRules[info.method] = validator._getMessage(name, info.method, info.params); 32278 } 32279 } 32280 32281 // set default status 32282 if(undefined !== el.val() && null !== el.val() && '' != el.val()) { 32283 el.addClass('has-predefined-value'); 32284 32285 // set status 32286 el.validationSetStatus('valid') 32287 } 32288 32289 el.data('validation-rules', dataRules); 32290 32291 // form validation on key up 32292 // text inputs integration 32293 el.keyup(function() { 32294 validator.validateField(name); 32295 validator.cleanErrors(); 32296 32297 // fast fix for password and password confirm 32298 if(el.hasValidationRule('password')) { 32299 var el2 = el.closest('form').find('[name="password2"]'); 32300 32301 if(el2.val() == el.val() && '' != el.val()) { 32302 el2.validationSetStatus('valid'); 32303 } else { 32304 el2.validationSetStatus('not-valid'); 32305 } 32306 } 32307 }); 32308 32309 // checkboxes integration 32310 if('checkbox' == el.attr('type')) { 32311 el.on('change', function() { 32312 validator.validateField(name); 32313 validator.cleanErrors(); 32314 }); 32315 } 32316 32317 // select boxes integration 32318 if(undefined != el.prop('tagName') && 'select' == el.prop('tagName').toLowerCase()) { 32319 el.on('change', function() { 32320 validator.validateField(name); 32321 validator.cleanErrors(); 32322 }); 32323 } 32324 }); 32325 32326 form.data('validator', validator); 32327 }; 32328 32329 /** 32330 * Validate form. 32331 * 32332 * @param {[]} [groups] 32333 * 32334 * @returns {boolean} 32335 */ 32336 jQuery.fn.validateForm = function(groups) { 32337 groups = groups || []; 32338 32339 var form = $(this), 32340 validator = form.getValidator(); 32341 32342 // if not a form 32343 if(false == validator) { 32344 return false;
32345 } 32346 32347 // validate 32348 return validator._validateForm(groups); 32349 }; 32350 32351 /** 32352 * Get form validator. 32353 * 32354 * @returns FormValidator 32355 */ 32356 jQuery.fn.getValidator = function() { 32357 var form = $(this), 32358 validator = $(this).data('validator'); 32359 32360 // if not a form 32361 if('form' != form.prop('tagName').toLowerCase()) { 32362 return false; 32363 } 32364 32365 // form don't have validator 32366 if(null == validator || 'object' !== typeof validator) { 32367 return false; 32368 } 32369 32370 return validator; 32371 }; 32372 32373 /** 32374 * Disable or enable validation for form. 32375 * 32376 * @param {Boolean} state 32377 * @param {String} [group] 32378 * @returns {boolean} 32379 */ 32380 jQuery.fn.disableValidation = function(state, group) { 32381 var form = $(this), 32382 validator = form.getValidator(); 32383 32384 // if not a form 32385 if(false == validator) { 32386 return false; 32387 } 32388 32389 state ? validator.disable(group) : validator.enable(); 32390 }; 32391 32392 /** 32393 * Change validator field rules 32394 * 32395 * @param {String} name 32396 * @param {String} rules 32397 * @param {{}} [messages] 32398 * 32399 * @returns {boolean} 32400 */ 32401 jQuery.fn.validatorChangeFieldRules = function (name, rules, messages) { 32402 var form = $(this), 32403 validator = form.getValidator(); 32404 32405 // if not a form 32406 if(false == validator) { 32407 return false; 32408 } 32409 32410 validator.changeFiledRules(name, rules, messages); 32411 }; 32412 32413 /** 32414 * Register custom rule. 32415 * 32416 * @param {String} name 32417 * @param {function} callback 32418 * @param {String} [message] 32419 * 32420 * @returns {boolean} 32421 */ 32422 jQuery.fn.validatorAddRule = function(name, callback, message) { 32423 var form = $(this), 32424 validator = form.getValidator(); 32425 32426 // if not a form 32427 if(false == validator) { 32428 return false; 32429 } 32430 32431 validator.registerCallback(name, callback); 32432 }; 32433 32434 /** 32435 * Box form submissions 32436 */ 32437 jQuery.fn.validateSubmit = function() { 32438 var form = $(this); 32439 var submit = form.find('button[type="submit"]'); 32440 32441 // add data loading 32442 submit.buttonLoading('loading'); 32443 32444 $.post(form.getFormSubmitPath(), form.serialize(), function (data) { 32445 32446 if(data.status) { 32447 window.location.href = data.page; 32448 } else { 32449 form.showAlert(nl2br(data.msg, true), 'danger', null, 'prepend').scrollToElement(500, -60); 32450 } 32451 32452 submit.buttonLoading('reset'); 32453 }); 32454 }; 32455 32456 /** 32457 * Concat form values 32458 * 32459 * @param {[]} elements 32460 * @param {String} [sep] 32461 * 32462 * @returns {string} 32463 */ 32464 jQuery.fn.concatFormValues = function(elements, sep) { 32465 sep = sep || ''; 32466 var res = ''; 32467 32468 for(var k in elements) { 32469 var el = elements[k]; 32470 var val = el instanceof jQuery ? el.val().trim() : $(this).find(el).val().trim(); 32471 32472 res += sep + val; 32473 } 32474 32475 return res.trim(); 32476 }; 32477 32478 /** 32479 * Returns actual fields for phone number. 32480 * 32481 * @returns {string[]} 32482 */ 32483 jQuery.fn.getTelFields = function() { 32484 var tel2 = $(this).find('.tel-2'); 32485 32486 // fast fix for compatibility on different pages 32487 return tel2.closest('.form-control-inner').hasClass('hidden') || tel2.hasClass('hidden') ? 32488 [ 32489 '.tel-3', 32490 '.tel-4', 32491 '.tel-1' 32492 ] : 32493 [ 32494 '.tel-3', 32495 '.tel-2', 32496 '.tel-1' 32497 ]; 32498 }; 32499 32500})(jQuery); 32501/** 32502 * This file is part of the box.co.il project. 32503 32504 * (c) Alex Buturlakin [email protected] 32505 */ 32506 32507;(function($) { 32508 // company registration form 32509 // #user-auth-register-company form 32510 32511 var registerCompanyForm = $('#user-auth-register-company').find('form'); 32512 32513 // enable validation 32514 if (registerCompanyForm.length) { 32515 registerCompanyForm.validatorEnableTooltipValidation(window.validationRules.registerCompanyRules); 32516 32517 // form submit handler 32518 registerCompanyForm.on('submit', function(e) { 32519 e.preventDefault(); 32520 32521 var form = $(this); 32522 32523 // pre submit 32524 form.find('[name="primary_phone"]').val(form.concatFormValues(form.getTelFields(), ' ')); 32525 32526 // validate and submit 32527 if(form.validateForm()) { 32528 $.localStorage.set('domains_bulk', []); 32529 form.validateSubmit(); 32530 } 32531 32532 return false;
32533 }); 32534 } 32535 32536 32537 // user registration form 32538 // #user-auth-register-user form 32539 32540 // enable validation 32541 var registerUserForm = $('#user-auth-register-user').find('form'); 32542 32543 // enable validation 32544 if (registerUserForm.length) { 32545 registerUserForm.validatorEnableTooltipValidation(window.validationRules.registerUserRules); 32546 32547 // form submit handler 32548 registerUserForm.on('submit', function(e) { 32549 e.preventDefault(); 32550 32551 var form = $(this); 32552 32553 // prepare before submit 32554 32555 form.find('[name="primary_phone"]').val(form.concatFormValues(form.getTelFields(), ' ')); 32556 32557 // validate and submit 32558 if(form.validateForm()) { 32559 $.localStorage.set('domains_bulk', []); 32560 form.validateSubmit(); 32561 } 32562 32563 return false; 32564 }); 32565 } 32566 32567 // Unified registration form (#user-auth-register) 32568 var registerForm = $('#user-auth-register').find('form.js-register-form'); 32569 32570 if (registerForm.length && window.validationRules.registerRules) { 32571 registerForm.validatorEnableTooltipValidation(window.validationRules.registerRules); 32572 32573 function setRegisterClientType(type) { 32574 var isCompany = type === 'company'; 32575 var $companyFields = registerForm.find('.js-register-company-fields'); 32576 var $name = registerForm.find('[name="name"]'); 32577 var $id = registerForm.find('[name="id"]'); 32578 var $invoice = registerForm.find('[name="invoice"]'); 32579 32580 registerForm.find('.js-register-label-private').toggleClass('hidden', isCompany); 32581 registerForm.find('.js-register-label-company').toggleClass('hidden', !isCompany); 32582 $companyFields.toggleClass('hidden', !isCompany); 32583 32584 $id.prop('disabled', !isCompany); 32585 $invoice.prop('disabled', !isCompany); 32586 32587 if (!isCompany) { 32588 $id.val(''); 32589 $invoice.val(''); 32590 } 32591 32592 if ($name.length) { 32593 var placeholder = isCompany 32594 ? $name.attr('data-placeholder-company') 32595 : $name.attr('data-placeholder-private'); 32596 if (placeholder) { 32597 $name.attr('placeholder', placeholder); 32598 } 32599 } 32600 32601 if (isCompany) { 32602 registerForm.validatorChangeFieldRules('name', 'required|company_name|english_numeric|words_count_min[2]', { 32603 company_name: false, 32604 words_count_min: false 32605 }); 32606 registerForm.validatorChangeFieldRules('id', 'required|is_natural', { required: false }); 32607 registerForm.validatorChangeFieldRules('invoice', 'required|english_numeric', { required: false }); 32608 } else { 32609 registerForm.validatorChangeFieldRules('name', 'required|one_word|two_words|english', { 32610 required: false 32611 }); 32612 registerForm.validatorChangeFieldRules('id', 'custom', {'custom': function () { return true; }}); 32613 registerForm.validatorChangeFieldRules('invoice', 'custom', {'custom': function () { return true; }}); 32614 } 32615 } 32616 32617 registerForm.find('[name="clientType"]').on('change', function() { 32618 setRegisterClientType($(this).val()); 32619 }); 32620 32621 setRegisterClientType(registerForm.find('[name="clientType"]:checked').val() || 'private'); 32622 32623 registerForm.on('submit', function(e) { 32624 e.preventDefault(); 32625 32626 var form = $(this); 32627 32628 form.find('[name="primary_phone"]').val(form.concatFormValues(form.getTelFields(), ' ')); 32629 32630 if (form.validateForm()) { 32631 $.localStorage.set('domains_bulk', []); 32632 form.validateSubmit(); 32633 } 32634 32635 return false; 32636 }); 32637 } 32638 // user reset password 2 form 32639 // #user-auth-register-company form 32640 32641 // enable validation 32642 var resetPasswordForm = $('#user-auth-password-reset2').find('form'); 32643 32644 // enable validation 32645 resetPasswordForm.validatorEnableTooltipValidation(window.validationRules.resetPasswordRules); 32646 32647 // form submit handler 32648 resetPasswordForm.on('submit', function(e) { 32649 e.preventDefault(); 32650 32651 var form = $(this); 32652 32653 // validate and submit 32654 if(form.validateForm()) { 32655 $.localStorage.set('domains_bulk', []); 32656 form.validateSubmit(); 32657 } 32658 32659 return false; 32660 }); 32661 32662 // domain purchase 32663 // domain owner info 32664 // enable validation 32665 32666 // enable validation 32667 var domainPurchaseForm = $('#domain-purchase-form'); 32668 32669 var errorHandler = function (errors) { 32670 // if one of tel1, tel2, tel3 or tel4 is empty => show one message 32671 var phoneFields = ['ownerTel3', 'ownerTel4', 'ownerTel1', 'adminTel3', 'adminTel4', 'adminTel1']; 32672 var telRequired = false;
32673 32674 $.each(errors, function(name, data) { 32675 if(phoneFields.indexOf(name) > -1 && 'required' == data.rule) { 32676 telRequired = true; 32677 32678 return false; 32679 } 32680 }); 32681 32682 if(telRequired) { 32683 for (var key in errors) { 32684 if (errors.hasOwnProperty(key) && phoneFields.indexOf(key) > -1) { 32685 delete errors[key]; 32686 } 32687 } 32688 32689 errors['phone'] = { 32690 'label': '<span class="error-field">{0}</span>'.format($.translate('Primary Phone')), 32691 'error': $.translate('Primary phone is required') 32692 } 32693 } 32694 32695 return errors; 32696 }; 32697 32698 // enable validation 32699 domainPurchaseForm.validatorEnableDefaultValidation(window.validationRules.purchaseDomainRules, 32700 function(status, errors, groups) { 32701 if(-1 !== $.inArray('owner', groups)) { 32702 return $('#ownerModal').find('.modal-base-content'); 32703 } 32704 32705 if(-1 !== $.inArray('admin', groups)) { 32706 return $('#adminModal').find('.modal-base-content'); 32707 } 32708 32709 if(-1 !== $.inArray('default', groups)) { 32710 return $('#creditDetails').find('.modal-base-content'); 32711 } 32712 32713 return $('#domain-purchase-form'); 32714 }, 32715 errorHandler 32716 ); 32717 32718 // save owner info 32719 domainPurchaseForm.find('#ownerModal button').on('click', function(e) { 32720 e.preventDefault(); 32721 32722 var name = $('#ownerFullName'), 32723 modal = $('#ownerModal'), 32724 primaryPhone = modal.find('[name="ownerPrimaryPhone"]'), 32725 faxNumber = modal.find('[name="ownerFaxNumber"]'); 32726 32727 // add LTD 32728 if ($('input[name=clientType]:checked').val() == 'company' && name.val() != '' && !stristr(name.val(), 'LTD')) { 32729 name.val(name.val().trim() + ' LTD'); 32730 } 32731 32732 // copy paste from domain.purchase.js 32733 if(domainPurchaseForm.validateForm(['owner'])) { 32734 $('.ownerDetails .error').hide(); 32735 $('.ownerDetails .ok').removeClass('hidden'); 32736 modal.modal('hide'); 32737 32738 // set primary phone and fax 32739 primaryPhone.val(modal.concatFormValues(modal.getTelFields(), ' ')); 32740 faxNumber.val(modal.concatFormValues(['[name="ownerFax3"]', '[name="ownerFax2"]', '[name="ownerFax1"]'], ' ')); 32741 } else { 32742 $('.ownerDetails .error').show(); 32743 $('.ownerDetails .ok').addClass('hidden'); 32744 } 32745 32746 isReadyToBuy(); 32747 }); 32748 32749 // save admin info 32750 domainPurchaseForm.find('#adminModal button').on('click', function(e) { 32751 e.preventDefault(); 32752 32753 var modal = $('#adminModal'), 32754 primaryPhone = modal.find('[name="adminPrimaryPhone"]'), 32755 faxNumber = modal.find('[name="adminFaxNumber"]'); 32756 32757 // copy paste from domain.purchase.js 32758 if(domainPurchaseForm.validateForm(['admin'])) { 32759 $('.adminDetails .error').hide(); 32760 $('.adminDetails .ok').removeClass('hidden'); 32761 modal.modal('hide'); 32762 // set primary phone and fax number 32763 primaryPhone.val(modal.concatFormValues(modal.getTelFields(), ' ')); 32764 faxNumber.val(modal.concatFormValues(['[name="adminFax3"]', '[name="adminFax2"]', '[name="adminFax1"]'], ' ')); 32765 32766 } else { 32767 $('.adminDetails .error').show(); 32768 $('.adminDetails .ok').addClass('hidden'); 32769 } 32770 32771 isReadyToBuy(); 32772 }); 32773 32774 // admin info use default values or not 32775 domainPurchaseForm.find('input[name="contact"]').change(function() { 32776 var select = domainPurchaseForm.find('#contacts'), 32777 exclude = ['adminContacts', 'contact'], 32778 modal = $('#adminModal'); 32779 32780 if('contacts' == $(this).val()) { 32781 select.prop('disabled', false); 32782 modal.lockForm(true, exclude); 32783 select.trigger('change'); 32784 domainPurchaseForm.disableValidation(true, 'admin'); 32785 } else { 32786 select.prop('disabled', true); 32787 modal.lockForm(false, exclude); 32788 modal.resetForm(exclude); 32789 domainPurchaseForm.disableValidation(false); 32790 } 32791 }); 32792 32793 // clear error on default data populated 32794 $('#ownerModal, #adminModal').on('default-data-populated', function() { 32795 $(this).validatorClearErrors(); 32796 }); 32797 32798 // change owner validation if client type was changed 32799 $.purchaseOwnerValidationRules = function(type) { 32800 if('company' == type) { 32801 domainPurchaseForm.validatorChangeFieldRules('ownerFullName', 'required|company_name|english|words_count_min[2]', { 32802 company_name: $.translate('Name Company Limited') 32803 }); 32804 domainPurchaseForm.validatorChangeFieldRules('ownerCompanyId', 'required|is_natural|callback_israeli_company_id', { 32805 required: $.translate('Company number is required'), 32806 callback_israeli_company_id: $.translate('Company ID must be 9 digits starting with 5') 32807 }); 32808 } else { 32809 domainPurchaseForm.validatorChangeFieldRules('ownerFullName', 'required|one_word|two_words|english'); 32810 domainPurchaseForm.validatorChangeFieldRules('ownerCompanyId', 'custom', {'custom': function () {return true;}}
32810); 32811 } 32812 }; 32813 32814 // listener to change domain purchase owner validation 32815 $('#ownerModal').find('[type="radio"]').on('change', function() { 32816 $.purchaseOwnerValidationRules($(this).val()); 32817 }); 32818 32819 // fast hard code to set default validation for adminFullName 32820 if(0 != domainPurchaseForm.length) { 32821 var clientType = $('#ownerModal').find('[type="radio"]:checked').trigger('change'); 32822 32823 if(0 != clientType.length) { 32824 $.purchaseOwnerValidationRules(clientType.val()); 32825 } 32826 } 32827 32828 32829 var purchaseSubmitting = false; 32830 $(document).on('click', '#infoSubmit', function (e) { 32831 e.preventDefault(); 32832 if (purchaseSubmitting) return; 32833 var form = $(this).closest('form'); 32834 var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; 32835 var emailEl = form.find('#ownerEmail'); 32836 var urlRe = /[a-zA-Z0-9]+\.[a-zA-Z0-9]+|[a-zA-Z0-9]+\.[a-zA-Z0-9]+(\.[a-zA-Z0-9]+(\.[a-zA-Z0-9]+)?)/g; 32837 var creditReg = /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|6(?:011|5[0-9]{2})[0-9]{12}|(?:2131|1800|35\d{3})\d{11})$/; 32838 var stringRe = /^[A-Za-z\s][A-Za-z0-9\s]*$/; 32839 var fullNameEl = form.find('#ownerFullName'); 32840 var ownerCompanyIdEl = form.find('#ownerCompanyId'); 32841 var priPhoneEl = form.find('#ownerPrimaryPhone'); 32842 var ownerFaxEl = form.find('#ownerFaxNumber'); 32843 var streetEl = form.find('#ownerAddressStreet'); 32844 var cityEl = form.find('#ownerAddressCity'); 32845 var countryEl = form.find('#ownerAddressCountry'); 32846 var zipEl = form.find('#ownerAddressZip'); 32847 var creditCardEl = form.find('#creditNumber'); 32848 var creditYrEl = form.find('#creditExpirationYear'); 32849 var creditMoEl = form.find('#creditExpirationMonth'); 32850 var creditCardCvvEl = form.find('#creditCvv'); 32851 var creditIdEl = form.find('#creditId'); 32852 var approve_termsEl = form.find('#approve_terms'); 32853 var approve_terms = approve_termsEl.is(":checked"); 32854 var date = new Date(); 32855 var domainPeriodEl = form.find('#domainPeriod'); 32856 var creditCard = creditCardEl.val(); 32857 var creditCardYr = creditYrEl.val(); 32858 var creditCardMo = creditMoEl.val(); 32859 var creditCardCvv = creditCardCvvEl.val(); 32860 var creditCardId = creditIdEl.val(); 32861 32862 var email = emailEl.val(); 32863 var fullName = fullNameEl.val(); 32864 var ownerCompanyId = ownerCompanyIdEl.val(); 32865 var street = streetEl.val(); 32866 var city = cityEl.val(); 32867 var country = countryEl.val(); 32868 var zip = zipEl.val(); 32869 var domainPeriod = parseInt($('[name=domainPeriod]:checked').val()); 32870 32871 var phone1 = form.find('#tel1').val(); 32872 var phone2 = form.find('#tel2').val(validatePerf(form.find('#tel2').val())).val(); 32873 var phone3 = form.find('#tel3').val(); 32874 32875 var fax1 = form.find('#fax1').val(); 32876 var fax2 = form.find('#fax2').val(validatePerf(form.find('#fax2').val())).val(); 32877 var fax3 = form.find('#fax3').val(); 32878 32879 var priPhone = priPhoneEl.val(); 32880 var ns = $('.domain-purchase-ns-name'); 32881 var nsvals = []; 32882 32883 ns.each(function (i) { 32884 var val = ns[i].value; 32885 if (val !== '') { 32886 nsvals[i] = val; 32887 } 32888 }); 32889 var errors = ''; 32890 if (!approve_terms) { 32891 approve_termsEl.parent().addClass('has-error'); 32892 errors += $.translate('Approve Terms is required') + '\n'; 32893 32894 } 32895 else { 32896 approve_termsEl.parent().removeClass('has-error'); 32897 } 32898 if (domainPeriod < 1 && domainPeriod > 5) { 32899 domainPeriodEl.parent().addClass('has-error'); 32900 errors += $.translate('Domain Period is invalid') + '\n'; 32901 } 32902 else { 32903 domainPeriodEl.parent().removeClass('has-error'); 32904 } 32905 if (isNaN(creditCardYr) || parseInt(creditCardYr) < date.getFullYear()) { 32906 creditYrEl.parent().addClass('has-error'); 32907 errors += $.translate('Expiry Year is invalid') + '\n'; 32908 } 32909 else { 32910 creditYrEl.parent().removeClass('has-error'); 32911 } 32912 if (isNaN(creditCardMo) || creditCardYr == date.getFullYear() && creditCardMo < date.getMonth()) { 32913 creditMoEl.parent().addClass('has-error');
32914 errors += $.translate('Expiry Month is invalid') + '\n'; 32915 } 32916 else { 32917 creditMoEl.parent().removeClass('has-error'); 32918 } 32919 if (isNaN(creditCardCvv) || creditCardCvv.length < 3 || creditCardCvv.length > 4) { 32920 creditCardCvvEl.parent().addClass('has-error'); 32921 errors += $.translate('cvv is invalid') + '\n'; 32922 } 32923 else { 32924 creditCardCvvEl.parent().removeClass('has-error'); 32925 } 32926 if (isNaN(creditCardId) || creditCardId.length < 9 || creditCardId.length > 9) { 32927 creditIdEl.parent().addClass('has-error'); 32928 errors += $.translate('id is invalid') + '\n'; 32929 } 32930 else { 32931 creditIdEl.parent().removeClass('has-error'); 32932 } 32933 if (isNaN(creditCard) || creditCard.length < 8 || creditCard.length > 17 || !creditReg.test(creditCard) && creditCard.length > 9 || creditCard[0] === 0) { 32934 creditCardEl.parent().addClass('has-error'); 32935 errors += $.translate('card is invalid') + '\n'; 32936 } 32937 else { 32938 creditCardEl.parent().removeClass('has-error'); 32939 } 32940 if (!re.test(email) || email === '') { 32941 emailEl.parent().addClass('has-error'); 32942 errors += $.translate('Email is invalid') + '\n'; 32943 } 32944 else { 32945 emailEl.parent().removeClass('has-error'); 32946 } 32947 if (fullName === '' || !stringRe.test(fullName)) { 32948 fullNameEl.parent().addClass('has-error'); 32949 errors += $.translate('full name is required') + '\n'; 32950 } else { 32951 fullNameEl.parent().removeClass('has-error'); 32952 } 32953 32954 if ($('input[name=clientType]:checked').val() == 'company') { 32955 if (ownerCompanyId === '' || ownerCompanyId.length == 0) { 32956 ownerCompanyIdEl.parent().addClass('has-error'); 32957 errors += $.translate('id is invalid') + '\n'; 32958 } else { 32959 ownerCompanyIdEl.parent().removeClass('has-error'); 32960 } 32961 } 32962 32963 if (priPhone === '' || priPhone.length < 8 || phone1 === '' || phone2 === '' || phone3 === '') { 32964 priPhoneEl.parent().addClass('has-error'); 32965 errors += $.translate('Primary phone is required') + '\n'; 32966 } 32967 else { 32968 priPhoneEl.parent().removeClass('has-error'); 32969 } 32970 if (street === '' || street.length < 2 || !/[0-9]/.test(street)) { 32971 streetEl.parent().addClass('has-error'); 32972 errors += $.translate('Street is required') + '\n'; 32973 } 32974 else { 32975 streetEl.parent().removeClass('has-error'); 32976 } 32977 if (city === '' || !stringRe.test(city)) { 32978 cityEl.parent().addClass('has-error'); 32979 errors += $.translate('City is required') + '\n'; 32980 } 32981 else { 32982 cityEl.parent().removeClass('has-error'); 32983 } 32984 if (country === '' || !stringRe.test(country)) { 32985 countryEl.parent().addClass('has-error'); 32986 errors += $.translate('Country is required') + '\n'; 32987 } 32988 else { 32989 countryEl.parent().removeClass('has-error'); 32990 } 32991 if (zip === '') { 32992 zipEl.parent().addClass('has-error'); 32993 errors += $.translate('Zip is required') + '\n'; 32994 } 32995 else { 32996 zipEl.parent().removeClass('has-error'); 32997 } 32998 32999 if (nsvals.length > 0) { 33000 $.each(nsvals, function (i) { 33001 if (nsvals[i] !== '' || !urlRe.test(nsvals[i])) { 33002 ns.parent().removeClass('has-error'); 33003 } 33004 else { 33005 ns.parent().addClass('has-error'); 33006 errors += $.translate('you must fill at least one correct Name Server') + '\n'; 33007 } 33008 }); 33009 } 33010 else { 33011 errors += $.translate('you must fill at least one Name Server') + '\n'; 33012 ns.parent().addClass('has-error'); 33013 } 33014 if (errors !== '') { 33015 $('#info-errors').html(nl2br(errors, true)).removeClass('hidden'); 33016 window.scrollTo(0, 0); 33017 return false; 33018 } else { 33019 purchaseSubmitting = true; 33020 $('#infoSubmit').button('loading'); 33021 $('#info-errors').addClass('hidden'); 33022 $.post($('#domain_order form').attr('action'), $('#domain_order form').serialize(), function (data) { 33023 if (data.status === 0) { 33024 $.showError(nl2br(data.msg, true)); 33025 33026 purchaseSubmitting = false; 33027 $('#infoSubmit').button('reset'); 33028 } 33029 33030 if (data.status === 1) { 33031 $('#main-content').html(data.msg); 33032 window.location = Storage.getData('app_url') + data.page; 33033 } 33034 33035 if (data.status == 2) { 33036 window.location = window.location; 33037 } 33038 }).fail(function () { 33039 purchaseSubmitting = false;
33040 $('#infoSubmit').button('reset'); 33041 $.showError($.translate('unkown error occured')); 33042 }); 33043 } 33044 }); 33045 33046})(jQuery); 33047 33048/** 33049 * HERE address lookup expander for unified registration form. 33050 * PHP/jQuery era compatible (no ES6). 33051 */ 33052;(function($) { 33053 'use strict'; 33054 33055 function getConfig() { 33056 var cfg = Storage.getData('here_geocode', {}); 33057 if (!cfg || typeof cfg !== 'object') { 33058 cfg = {}; 33059 } 33060 return cfg; 33061 } 33062 33063 function translate(key) { 33064 if ($.translate) { 33065 return $.translate(key); 33066 } 33067 return key; 33068 } 33069 33070 function appUrl(path) { 33071 var base = Storage.getData('app_url', '/'); 33072 if (base.charAt(base.length - 1) !== '/') { 33073 base += '/'; 33074 } 33075 return base + path.replace(/^\//, ''); 33076 } 33077 33078 function isEnabled() { 33079 var cfg = getConfig(); 33080 return !!(cfg.enabled); 33081 } 33082 33083 function RegisterAddressLookup($form) { 33084 this.$form = $form; 33085 this.$wrap = $form.find('.js-register-address'); 33086 this.$toggle = this.$wrap.find('.js-address-lookup-toggle'); 33087 this.$toggleLabel = this.$wrap.find('.js-address-lookup-toggle-label'); 33088 this.$panel = this.$wrap.find('.js-address-lookup-panel'); 33089 this.$input = this.$wrap.find('#register-address-lookup-q'); 33090 this.$results = this.$wrap.find('.js-address-lookup-results'); 33091 this.$msg = this.$wrap.find('.js-address-lookup-msg'); 33092 this.$searchBtn = this.$wrap.find('.js-address-lookup-search'); 33093 this.open = false; 33094 33095 if (!this.$wrap.length || this.$wrap.attr('data-address-lookup') !== '1' || !this.$panel.length) { 33096 return; 33097 } 33098 33099 this.bind(); 33100 } 33101 33102 RegisterAddressLookup.prototype.bind = function() { 33103 var self = this; 33104 33105 this.$toggle.on('click', function(e) { 33106 e.preventDefault(); 33107 if (!self.open && !isEnabled()) { 33108 alert(translate('Address lookup limit reached. Please fill the address manually.')); 33109 return; 33110 } 33111 self.setOpen(!self.open); 33112 }); 33113 33114 this.$searchBtn.on('click', function(e) { 33115 e.preventDefault(); 33116 self.search(); 33117 }); 33118 33119 this.$input.on('keydown', function(e) { 33120 if (e.keyCode === 13) { 33121 e.preventDefault(); 33122 self.search(); 33123 } 33124 }); 33125 33126 this.$results.on('click', '.js-address-lookup-pick', function(e) { 33127 e.preventDefault(); 33128 var address = $(this).data('address'); 33129 if (!address) { 33130 return; 33131 } 33132 self.applyAddress(address); 33133 self.$results.find('.js-address-lookup-pick').removeClass('is-selected'); 33134 $(this).addClass('is-selected'); 33135 self.setOpen(false); 33136 }); 33137 }; 33138 33139 RegisterAddressLookup.prototype.setOpen = function(open) { 33140 this.open = !!open; 33141 this.$panel.toggleClass('hidden', !this.open); 33142 this.$toggle.toggleClass('is-open', this.open); 33143 this.$wrap.toggleClass('address-lookup-expanded', this.open); 33144 33145 var label = this.open 33146 ? this.$toggle.attr('data-label-close') 33147 : this.$toggle.attr('data-label-open'); 33148 if (label) { 33149 this.$toggleLabel.text(label); 33150 } 33151 33152 if (this.open) { 33153 this.showMessage(''); 33154 var self = this; 33155 setTimeout(function() { 33156 self.$input.focus(); 33157 }, 50); 33158 } else { 33159 this.$results.empty(); 33160 this.showMessage(''); 33161 } 33162 }; 33163 33164 RegisterAddressLookup.prototype.showMessage = function(text) { 33165 if (!text) { 33166 this.$msg.addClass('hidden').text(''); 33167 return; 33168 } 33169 this.$msg.removeClass('hidden').text(text); 33170 }; 33171 33172 RegisterAddressLookup.prototype.search = function() { 33173 var self = this; 33174 var q = $.trim(this.$input.val() || ''); 33175 33176 if (!isEnabled()) { 33177 this.showMessage(translate('Address lookup limit reached. Please fill the address manually.')); 33178 return; 33179 } 33180 33181 if (q.length < 3) { 33182 this.showMessage(translate('Please enter a more complete address.')); 33183 return; 33184 } 33185 33186 this.showMessage(''); 33187 this.$results.empty(); 33188 this.$searchBtn.prop('disabled', true); 33189 if (this.$searchBtn.button) { 33190 this.$searchBtn.button('loading'); 33191 } 33192 33193 $.ajax({ 33194 url: appUrl('address-lookup/geocode'), 33195 type: 'POST', 33196 dataType: 'json', 33197 data: { 33198 q: q, 33199 csrf_token: self.$form.find('[name=csrf_token]').val(), 33200 csrf_token_name: self.$form.find('[name=csrf_token_name]').val() 33201 } 33202 }).done(function(response) { 33203 if (!response) { 33204 self.showMessage(translate('Address lookup failed. Please fill manually.')); 33205 return; 33206 } 33207 33208 if (response.status !== 1) { 33209 self.showMessage(response.msg || translate('Address lookup failed. Please fill manually.')); 33210 return; 33211 } 33212 33213 var results = response.results || []; 33214 if (!results.length) { 33215 self.showMessage(translate('No addresses found. Try a different query or fill manually.')); 33216 return; 33217 } 33218 33219 self.renderResults(results); 33220 }).fail(function() { 33221 self.showMessage(translate('Address lookup failed. Please fill manually.')); 33222 }).always(function() { 33223 self.$searchBtn.prop('disabled', false); 33224 if (self.$searchBtn.button) { 33225 self.$searchBtn.button('reset'); 33226 } 33227 }); 33228 }; 33229 33230 RegisterAddressLookup.prototype.renderResults = function(results) { 33231 var self = this; 33232 this.$results.empty(); 33233 33234 $.each(results, function(_, item) { 33235 var label = item.label || (item.street + ', ' + item.city); 33236 var $btn = $('<button type="button" class="list-group-item js-address-lookup-pick"></button>'); 33237 $btn.text(label); 33238 $btn.data('address', item); 33239 self.$results.append($btn); 33240 }); 33241 }; 33242 33243 RegisterAddressLookup.prototype.applyAddress = function(address) { 33244 if (!address) { 33245 return; 33246 } 33247 33248 var $street = this.$form.find('#user-auth-register-street'); 33249 var $number = this.$form.find('#user-auth-register-number'); 33250 var $city = this.$form.find('#user-auth-register-city'); 33251 var $zip = this.$form.find('#user-auth-register-zip'); 33252 var $country = this.$form.find('#user-auth-register-country'); 33253 33254 if ($street.length) { 33255 $street.val(address.street_name || address.street || '').trigger('change'); 33256 } 33257 if ($number.length) { 33258 $number.val(address.street_number || '').trigger('change'); 33259 } 33260 if ($city.length && address.city) { 33261 $city.val(address.city).trigger('change'); 33262 } 33263 if ($zip.length && address.zip) { 33264 $zip.val(address.zip).trigger('change'); 33265 } 33266 if ($country.length && address.country) { 33267 $country.val(address.country).trigger('change'); 33268 if ($country.hasClass('select2-hidden-accessible') || $country.data('select2')) { 33269 $country.trigger('change.select2'); 33270 } 33271 } 33272 }; 33273 33274 $(function() { 33275 var $form = $('#user-auth-register').find('form.js-register-form'); 33276 if ($form.length && isEnabled()) { 33277 new RegisterAddressLookup($form); 33278 } 33279 }); 33280})(jQuery); 33281 33282/** 33283 * This file is part of the box.co.il project. 33284 33285 * (c) Alex Buturlakin [email protected] 33286 */ 33287 33288;(function($) { 33289 33290 // Enable ALL jquery plugins here 33291 33292 // enable select2 33293 $(document).ready(function () { 33294 $('.select2').each(function() { 33295 // select2 33296 var select2 = $(this).select2({ 33297 dir: "rtl", 33298 allowClear: false, 33299 language: "he", 33300 //placeholder: '', ?? 33301 minimumResultsForSearch: 0, 33302 width: '100%', 33303 // maximumSelectionLength: 10, 33304 containerCssClass: 'select2-box-theme', 33305 dropdownCssClass: 'select2-box-theme' 33306 }).css("max-height","400px"); 33307
33308 // add focus events 33309 // select2.next(".select2").find(".select2-selection").focus(function() { 33310 // select2.select2("open"); 33311 // }); 33312 33313 // add scroll bar 33314 var scrollContent; 33315 select2.on('select2:open', function () { 33316 33317 if(scrollContent) { 33318 return true; 33319 } 33320 33321 // show scroll bar 33322 scrollContent = $('.select2-container--open .select2-results>ul').niceScroll({ 33323 autohidemode: false, 33324 cursorcolor: '#565656', 33325 cursorwidth: 5, 33326 rtlmode: true, 33327 railalign:'left', 33328 cursorborder: '1px solid #e6e6e6', 33329 // rtlmode:true, 33330 hwacceleration:false, 33331 cursorminheight: 54 33332 }); 33333 }); 33334 }); 33335 }); 33336 33337 // enable qtip2 33338 $(document).ready(function () { 33339 33340 /** 33341 * Get get value from element data attribute. 33342 * 33343 * @param {String} name 33344 * @param {String} [defaultTitle] 33345 */ 33346 var getQtipData = function(name, defaultTitle) { 33347 defaultTitle = defaultTitle || null; 33348 var title = this.data(name); 33349 33350 if (typeof title === typeof undefined || title === false) { 33351 return defaultTitle; 33352 } 33353 33354 return title; 33355 }; 33356 33357 /** 33358 * Get validation text. 33359 */ 33360 var getQtipValidationText = function() { 33361 var list = this.getValidationRulesList(); 33362 var valName = getQtipData.call(this, 'qtip2-validation-name'); 33363 var html = ''; 33364 33365 // generate html for ul li element 33366 var generateLIHtml = function (rule, message) { 33367 var html = ''; 33368 var template = '<li data-rule="{0}">{1}</li>'; 33369 33370 // if rule has more than one messages 33371 if(Array.isArray(message)) { 33372 for(var k in message) { 33373 html += template.format(rule, message[k]) 33374 } 33375 } else { 33376 html = template.format(rule, message); 33377 } 33378 33379 return html; 33380 }; 33381 33382 // if no validation rules added for element 33383 if(0 === Object.keys(list).length) { 33384 return false; 33385 } 33386 33387 // generate html for ul element 33388 html = '<ul class="qtip2-validation-content">'; 33389 33390 // default messages (not from rules). Can be separated by ||| 33391 if(valName) { 33392 var vna = valName.split('|||'); 33393 33394 for(var n in vna) { 33395 html += generateLIHtml('rule-default', vna[n]); 33396 } 33397 } 33398 33399 // all rules messages 33400 $.each(list, function (rule, message) { 33401 if(false == message || '' == message) { 33402 return true; 33403 } 33404 33405 html += generateLIHtml(rule, message); 33406 }); 33407 33408 return html + '</ul>'; 33409 }; 33410 33411 // form validation qtip 33412 $('.validation input:not(.validation-disable-qtip), .validation select:not(.validation-disable-qtip)').each(function() { 33413 var el = $(this); 33414 var title = getQtipData.call(el, 'qtip2-title', $.translate('This Field Must Contain:')); 33415 var adjustX = getQtipData.call(el, 'qtip2-x', -51); 33416 var text = getQtipValidationText.call(el); 33417 33418 el.qtip({ 33419 content: { 33420 text: text, 33421 title: function () { return title } 33422 }, 33423 hide: { 33424 event: 'blur select2:close' 33425 }, 33426 show: { 33427 event: 'focus select2:open' 33428 }, 33429 style: { 33430 classes: 'qtip-box-form-validation qtip-bootstrap', 33431 tip: false 33432 }, 33433 position: { 33434 my: 'top right', 33435 at: 'top left', 33436 adjust: { 33437 x: adjustX 33438 } 33439 } 33440 }); 33441 33442 if(el.hasClass('has-predefined-value')) { 33443 el.qtip('disable'); 33444 } 33445 33446 // fix for checkboxes 33447 if('checkbox' == el.attr('type')) { 33448 el.on('focus', function() { 33449 el.qtip('disable', false); 33450 el.qtip('show'); 33451 }); 33452 } 33453 }); 33454 }); 33455 33456 33457 // enable fancy box 33458 // ?? 33459 33460})(jQuery); 33461 33462/** 33463 * This file is part of the box.co.il project. 33464 33465 * (c) Alex Buturlakin [email protected] 33466 */ 33467;(function($) { 33468 $(document).ready(function() { 33469 33470 // enable or disable blocks by click in switch link 33471 jQuery(document).on('click', '.link-switch', function (e) { 33472 var el = $(this), 33473 open = el.data('switch-open') || '', 33474 toggle = el.data('switch-toggle') || '', 33475 close = el.data('switch-close') || ''; 33476 33477 open = $(open); 33478 close = $(close); 33479 toggle = $(toggle); 33480 33481 toggle.toggleClass('hidden'); 33482 open.removeClass('hidden'); 33483 close.addClass('hidden'); 33484 33485 e.preventDefault(); 33486 }); 33487 33488 // populate form default values 33489 $('.populate-default-values').on('change', function() { 33490 var el = $(this), 33491 selector = el.data('populate-in'), 33492 container = typeof selector === typeof undefined || selector === false ? el.closest('form') : $(selector), 33493 name = el.attr('name'), 33494 exclude = el.data('populate-exclude'); 33495 33496 exclude = typeof exclude === typeof undefined || exclude === false ? [] : exclude.split('|'); 33497 33498 // add current el to exclude 33499 if(typeof name !== typeof undefined) { 33500 exclude.push(name); 33501 } 33502 33503 if(1 == container.length) { 33504 if(undefined != el.prop('tagName') && 'select' == el.prop('tagName').toLowerCase()) { 33505 container.populateDefaultDataSelect(el.find('option:selected'), exclude); 33506 } else { 33507 container.populateDefaultData(el.prop('checked'), exclude); 33508 } 33509 } 33510 }); 33511 33512 // add/remove tel2 select box 33513 $('.tel-3').on('keyup', function() { 33514 var el = $(this), 33515 selector = el.data('tel-in'), 33516 container = typeof selector === typeof undefined || selector === false ? el.closest('form') : $(selector), 33517 tel2 = container.find('.tel-2').closest('.form-control-inner'), 33518 tel4 = container.find('.tel-4').closest('.form-control-inner'); 33519 33520 // fast fix for compatibility on different pages
33521 if(0 == tel2.length) { 33522 tel2 = container.find('.tel-2'); 33523 tel4 = container.find('.tel-4'); 33524 } 33525 33526 // if is Israel number 33527 if('972' == el.val() && tel2.hasClass('hidden')) { 33528 tel2.removeClass('hidden'); 33529 tel4.addClass('hidden'); 33530 } 33531 33532 // not Israel number 33533 if('972' != el.val() && tel4.hasClass('hidden')) { 33534 tel4.removeClass('hidden'); 33535 tel2.addClass('hidden'); 33536 } 33537 }).on('default-data-populated', function() { 33538 $(this).keyup(); 33539 }); 33540 33541 // open support window 33542 $('.zendesk-open-window').click(function() { 33543 zE('messenger', 'open'); 33544 33545 return false; 33546 }); 33547 33548 }); 33549})(jQuery); 33550/** 33551 * This file is part of the box.co.il project. 33552 33553 * (c) Alex Buturlakin [email protected] 33554 */ 33555// todo@alexbuturlakin: this file was created from inlined code in main.php template. Looks like it need some refactoring. 33556;(function($) { 33557 $(document).ready(function() { 33558 $(".domainsCheck .option:not(.current)").each(function() { 33559 var zone = $(this).attr("data-tld"); 33560 var dom = $(this).attr("data-domain"); 33561 var domain_id = $(this).attr("data-domain-id"); 33562 $(this).attr('id', 'id'+zone); 33563 var domain = dom + zone; 33564 33565 var csrfToken = $(this).find('[name=csrf_token]').val(), 33566 csrfTokenName = $(this).find('[name=csrf_token_name]').val() 33567 ; 33568 33569 if (dom.length <= 2 || dom.indexOf(' ') != -1 || $(this).hasClass('sld-not-valid')) { 33570 $(this).find('.progressWhois').css('display','none'); 33571 $(this).find('.NotSupported').css('display','block'); 33572 $(this).find('.delayed').css('display','none'); 33573 // $('#ok').attr('class','hidden'); 33574 // $('#error').removeClass('hidden'); 33575 } else { 33576 check_domain(domain_id, domain,csrfTokenName, csrfToken); 33577 } 33578 }); 33579 33580 var checkDomainFail = function(domain_id) { 33581 $('#whois_'+domain_id).css('display','none'); 33582 var id = '#taken_'+domain_id; 33583 $(id).removeClass('hidden'); 33584 }; 33585 33586 var checkDomainSuccess = function(domain_id) { 33587 $('#whois_'+domain_id).addClass('hidden'); 33588 var id = '#avilable_'+domain_id; 33589 $(id).removeClass('hidden'); 33590 }; 33591 33592 function check_domain(domain_id, domain, tokenName, token) { 33593 var 33594 csrfConfig = Storage.getData('csrf_config'), 33595 tokenKey = csrfConfig['token_key'], 33596 tokenNameKey = csrfConfig['token_name_key'], 33597 data = {} 33598 ; 33599 33600 // set request data 33601 data['domain'] = domain; 33602 data[tokenKey] = token; 33603 data[tokenNameKey] = tokenName; 33604 33605 $.ajax({ 33606 url: "/domainsCheck/", 33607 type: "GET", 33608 data: data, 33609 success: function(data) { 33610 if(true == data['free']) { 33611 checkDomainSuccess(domain_id); 33612 } else { 33613 checkDomainFail(domain_id); 33614 } 33615 }, 33616 error: function () { 33617 checkDomainFail(domain_id); 33618 } 33619 }); 33620 } 33621 33622 $(".check_btn").click(function() { 33623 var layer = $(this).closest(".option"); 33624 33625 var zone = layer.attr("data-tld"); 33626 var dom = layer.attr("data-domain"); 33627 var domain_id = layer.attr("data-domain-id"); 33628 layer.attr('id', 'id'+zone); 33629 var domain = dom + zone; 33630 layer.find(".delayed").hide(); 33631 layer.find(".progressWhois").show(); 33632 33633 check_domain(domain_id, domain); 33634 }); 33635 }); 33636})(jQuery); 33637 33638/** 33639 * This file is part of the box.co.il project. 33640 33641 * (c) Alex Buturlakin [email protected] 33642 */ 33643// todo@alexbuturlakin: this file was created from inlined code in domain/info.php template. Looks like it need some refactoring (rm -rf ??). 33644;(function($) { 33645 // hm... may be need to remove this 33646 if (typeof(ctype_print) != "function") { 33647 function ctype_print(str) { 33648 var allowed = 'abcdefghijklmnopqrstuvwxyz0123456789*!@#$%^?:&*~=_.,<>{}"|-;`+()[]/\\\' '; 33649 allowed = allowed.split(''); 33650 var chars = str.split(''); 33651 var status = true; 33652 for (var i = 0; i < chars.length; i++) { 33653 var singleChar = chars[i].toLowerCase(); 33654 if (allowed.indexOf(singleChar) === -1) { 33655 status = false;
33656 break; 33657 } 33658 } 33659 return status; 33660 } 33661 } 33662 33663 $(document).ready(function() { 33664 var isNotifiedAboutPremium = false; 33665 33666 // select domain purchase period 33667 $('input[name=domainPeriod]').change(function () { 33668 var el = $(this), 33669 validation = el.closest('label').siblings('.validation'), 33670 success = validation.find('.ok'), 33671 cardDetails = $('#creditCardDetails'); 33672 33673 // show success message 33674 if(success.hasClass('hidden')) { 33675 // hide error 33676 validation.find('.error').addClass('hidden'); 33677 33678 // show success message 33679 success.removeClass('hidden'); 33680 } 33681 33682 // change message 33683 success.find('span>span').html(' ' + el.data('date')); 33684 33685 // update price info 33686 $.updateTotalPrice(); 33687 33688 // clean card form fields 33689 cardDetails.resetForm(); 33690 $('#cpn-error').addClass('hidden'); 33691 33692 isReadyToBuy(); 33693 }); 33694 33695 // change label by selected client type 33696 $('#ownerModal').find('[name="clientType"]').on('change', function() { 33697 var el = $(this), 33698 val = el.val(), 33699 container = el.closest('.modal-body'), 33700 label = container.find('[for="ownerFullName"]'), 33701 input = container.find('[name="ownerFullName"]'); 33702 33703 // set label and placeholder 33704 label.find('span').html(input.data('label-{0}'.format(val))); 33705 input.attr('placeholder', input.data('placeholder-{0}'.format(val))); 33706 33707 // Change validation rules for owner name 33708 var nameValidation = 'clientTypeCompany' === el.attr('id') 33709 ? window.validationRules.purchaseDomainRulesOwnerName.company 33710 : window.validationRules.purchaseDomainRulesOwnerName.user 33711 ; 33712 33713 el.closest('form').validatorChangeFieldRules('ownerFullName', nameValidation.rules, nameValidation.messages); 33714 33715 // clear input 33716 input.val(''); 33717 33718 container.find('.form-group-{0}'.format(val)).removeClass('hidden'); 33719 container.find('.form-group-{0}'.format('company' === val ? 'private' : 'company')).addClass('hidden'); 33720 }); 33721 33722 $('#ownerCompanyId').on('default-data-populated', function() { 33723 if ($('input[name=clientType]:checked').val() == 'company') { 33724 $(this).closest('.form-group-company').removeClass('hidden'); 33725 } 33726 }); 33727 33728 $('input[name=clientType]').change(function () { 33729 var name = $('#ownerFullName'); 33730 if ($('input[name=clientType]:checked').val() == 'company' && $('#ownerFullName').val() != '') { 33731 if (!stristr(name.val(), 'LTD')) { 33732 name.val(name.val().trim() + ' LTD'); 33733 } 33734 } else { 33735 name.val(name.val().replace('LTD', '').trim()); 33736 } 33737 }); 33738 33739 $('input[name=ownerFullName]').focusout(function () { 33740 var name = $('#ownerFullName'); 33741 if ($('input[name=clientType]:checked').val() == 'company' && $('#ownerFullName').val() != '') { 33742 if (!stristr(name.val(), 'LTD')) { 33743 name.val(name.val().trim() + ' LTD'); 33744 } 33745 } else { 33746 name.val(name.val().replace('LTD', '').trim()); 33747 } 33748 }); 33749 33750 $('input[name=dnsType]').change(function () { 33751 var val = $('input[name=dnsType]:checked').val(); 33752 if (val == 'adv') { 33753 $('input.names').each(function () { 33754 $(this).val($(this).attr('data-value')); 33755 }); 33756 33757 $('#dnsAdv').show(); 33758 } 33759 33760 if ('cloud' == val) { 33761 $('#dnsAdv').hide(); 33762 33763 $('input.names').each(function () { 33764 $(this).val($(this).attr('data-value-cloud')); 33765 }); 33766 } 33767 33768 if (val == 'default') { 33769 $('#dnsAdv').hide(); 33770 $('input.names').each(function () { 33771 $(this).val($(this).attr('data-value')); 33772 }); 33773 } 33774 }); 33775 33776 $('#creditCardDetails .cvvhelp').hover(function () { 33777 $(this).find('img').show(); 33778 }, function () { 33779 $(this).find('img').hide(); 33780 }); 33781 33782 $('#domainCheckout').click(function () { 33783 var el = $(this), 33784 next = el.attr('data-next'); 33785 if (isReadyToBuy()) { 33786 if('email-account' === next) { 33787 var eaBlock = $('#domain-purchase-email-account'); 33788 eaBlock.removeClass('hidden'); 33789 $(document).scrollTop(eaBlock.offset().top-100); 33790 // $([document.documentElement, document.body]).animate({ 33791 // scrollTop: $('.form-group.isReady').offset().top+550 33792 // }, 2000); 33793 } 33794 33795 if('card-data' === next) {
33796 $('#creditCardDetails').removeClass('hidden'); 33797 33798 $('.show-tooltip').addTooltip(); 33799 33800 $.updateTotalPrice(); 33801 $(document).scrollTop($('#domainCheckout').offset().top+100); 33802 33803 // $([document.documentElement, document.body]).animate({ 33804 // scrollTop: $(".form-group.isReady").offset().top+600 33805 // }, 2000); 33806 33807 } 33808 } 33809 }); 33810 33811 // step 2 33812 $('#domain-purchase-email-account-accept').click(function() { 33813 $('#domain-purchase-cashback').removeClass('hidden'); 33814 $(document).scrollTop($('#domain-purchase-cashback').offset().top); 33815 }); 33816 33817 $('#domain-purchase-owner-email-verify-accept').click(function() { 33818 var valid = true; 33819 33820 if (!$('#ownerEmailVerificationCode').val() || $('#ownerEmailVerificationCode').val().length != 8) { 33821 $('#domain-purchase-owner-email-verify-errors').html($.translate('Email verification code is invalid')).removeClass('hidden'); 33822 valid = false; 33823 } 33824 33825 if (isReadyToBuy() && valid) { 33826 $('#domain-purchase-owner-email-verify-errors').addClass('hidden'); 33827 $('#creditCardDetails').removeClass('hidden'); 33828 $.updateTotalPrice(); 33829 $(document).scrollTop($('#creditCardDetails').offset().top); 33830 // $([document.documentElement, document.body]).animate({ 33831 // scrollTop: $('.form-group.isReady').offset().top+300 33832 // }, 1000); 33833 // notify user about premium domain 33834 33835 $('.show-tooltip').addTooltip(); 33836 33837 33838 if (true === Storage.getData('isPremiumDomain') && false == isNotifiedAboutPremium) { 33839 $.showSuccess( 33840 $.translate('Premium Domain Purchasing'), 33841 Storage.getData('premiumMessage'), 33842 false, 33843 true 33844 ); 33845 33846 isNotifiedAboutPremium = true; 33847 } 33848 } 33849 }); 33850 33851 $('#domain-purchase-email-accounts-decline').click(function() { 33852 $('#domain-purchase-email-account input[type=checkbox]').prop('checked', false); 33853 $('#domain-purchase-email-account').addClass('hidden'); 33854 33855 $('#domain-purchase-cashback').removeClass('hidden'); 33856 }); 33857 33858 $('#domain-purchase-promo-accept').click(function() { 33859 $('.domainCashback').val('true') 33860 emailVerify(true) 33861 }); 33862 33863 $('#domain-purchase-promo-decline').click(function() { 33864 $('.domainCashback').val('false') 33865 $('#domain-purchase-cashback').addClass('hidden') 33866 emailVerify(false) 33867 }); 33868 33869 function emailVerify(scroll){ 33870 if (isReadyToBuy()) { 33871 if ($('#domain-purchase-owner-email-verify').length) { 33872 $('#domain-purchase-owner-email-verify').removeClass('hidden'); 33873 $('#domain-purchase-owner-email-verify-send-email span').text(' ' + $('#ownerEmail').val()); 33874 33875 if(scroll){ 33876 $(document).scrollTop($('#domain-purchase-owner-email-verify').offset().top - 100); 33877 } 33878 } else { 33879 $('#creditCardDetails').removeClass('hidden'); 33880 $.updateTotalPrice(); 33881 33882 if(scroll){ 33883 $(document).scrollTop($('#creditCardDetails').offset().top - 100); 33884 } 33885 33886 $('.show-tooltip').addTooltip(); 33887 33888 if (true === Storage.getData('isPremiumDomain') && false == isNotifiedAboutPremium) { 33889 $.showSuccess( 33890 $.translate('Premium Domain Purchasing'), 33891 Storage.getData('premiumMessage'), 33892 false, 33893 true 33894 ); 33895 33896 isNotifiedAboutPremium = true; 33897 } 33898 } 33899 } 33900 } 33901 33902 $('#domain-purchase-owner-email-verify-send-email,#form-domain-purchase-owner-email-verify-resend').click(function (e) { 33903 e.preventDefault(); 33904 $('#domain-purchase-owner-email-verify-send-email').button('loading'); 33905 $('#form-domain-purchase-owner-email-verify-resend').button('loading'); 33906 33907 $.ajax({ 33908 url: '/domain-email-verify/purchase', 33909 type: 'POST', 33910 data: { 33911 'email': $('#ownerEmail').val() 33912 }, 33913 success: function (response) { 33914 if (0 == response.status) { 33915 $('#domain-purchase-owner-email-verify-errors').html(nl2br(response.msg, true)).removeClass('hidden'); 33916 $('#domain-purchase-owner-email-verify-send-email').button('reset'); 33917 $('#form-domain-purchase-owner-email-verify-resend').button('reset'); 33918 } 33919 33920 if (1 == response.status) { 33921 $('.domain-purchase-owner-email-verify-step-1').addClass('hidden'); 33922 $('.domain-purchase-owner-email-verify-step-2').removeClass('hidden'); 33923 $('#domain-purchase-owner-email-verify-send-email').button('reset'); 33924 $('#form-domain-purchase-owner-email-verify-resend').button('reset'); 33925 } 33926 }, 33927 error: function (xhr) { 33928 if (403 === xhr.status) { 33929 window.location.href = '/user/login'; 33930 } 33931 33932 $('#domain-purchase-owner-email-verify-errors').html(xhr.responseJSON.error).removeClass('hidden'); 33933 } 33934 }); 33935 }); 33936 33937 $('#domain-purchase-email-account').on('click', 'input[type=checkbox]', function() { 33938 var ec = $('#domain-purchase-email-account-errors'); 33939 33940 ec.addClass('hidden'); 33941 }); 33942 33943 $('#domain-purchase-email-account .form-group > span').click(function () { 33944 $('#domain-purchase-email-account-text').focus(); 33945 }); 33946 33947 $('#domain-purchase-email-account-add').click(function() { 33948 var el = $(this), 33949 input = el.siblings('input'), 33950 value = input.val(), 33951 proto = el.attr('data-prototype'), 33952 eDomain = el.attr('data-email-domain'),
33953 cbBoxes = $('#domain-purchase-email-account input[type=checkbox]'), 33954 erCont = $('#domain-purchase-email-account-errors'), 33955 cbCount = cbBoxes.length; 33956 33957 var validator = $('#domain-purchase-form').data('validator'), 33958 emailAccount = value + eDomain, 33959 isValid = validator._hooks.valid_email({'value': emailAccount}); 33960 33961 erCont.addClass('hidden'); 33962 33963 // todo@alexbuturlakin: need to refactor 33964 if(value && value.length > 0 && isValid) { 33965 if(isValid) { 33966 if($('#domain-purchase-email-account input[value="{0}"][type="checkbox"]'.format(emailAccount)).length > 0) { 33967 erCont 33968 .html($.translate('Email account with the same name already added')) 33969 .removeClass('hidden'); 33970 } else { 33971 var cbNew = $(proto.format(cbCount, cbCount, value)); 33972 33973 cbBoxes.last().parent().after(cbNew); 33974 33975 cbNew = $('#domain-purchase-email-account-{0}'.format(cbCount)); 33976 33977 input.val(''); 33978 cbNew.val(emailAccount); 33979 33980 if(9 === cbBoxes.length) { 33981 el.parent().remove(); 33982 } 33983 } 33984 } 33985 } else { 33986 erCont 33987 .html($.translate('Only English letters (a-z), numbers, periods, @<br><span>Example: [email protected]</span>')) 33988 .removeClass('hidden'); 33989 } 33990 }); 33991 }); 33992 33993 /** 33994 * Update total price 33995 */ 33996 $.updateTotalPrice = function() { 33997 var title = $('#creditCardDetails').find('.UISection > span'), 33998 period = parseInt($('input[name=domainPeriod]:checked').val()), 33999 total = 0; 34000 34001 // update total price 34002 for (var i = 1; i < period + 1; i++) { 34003 var yearPrice = title.attr('data-price-{0}'.format(i)); 34004 34005 if (undefined !== yearPrice) { 34006 total += parseFloat(yearPrice); 34007 } 34008 } 34009 perYear = total / period; 34010 totalPerYear = Number(perYear).toFixed(2); 34011 // update total price 34012 title.find('span').html(Number(total).toFixed(2)); 34013 $("#PriceperYear").html(totalPerYear); 34014 }; 34015 34016})(jQuery); 34017 34018/** 34019 * This file is part of the "box" project. 34020 * 34021 * (c) Alex Buturlakin [email protected] 34022 */ 34023;(function($) { 34024 34025 /** 34026 * Update checked checkboxes from storage. 34027 */ 34028 $.bulkStorageUpdateCheckboxes = function () { 34029 var storage = $.localStorage, 34030 data = storage.isSet('domains_bulk') ? storage.get('domains_bulk') : []; 34031 34032 // update all checkboxes 34033 $.each(data, function() { 34034 $('[data-domain="{0}"]'.format(this)).prop('checked', true); 34035 }); 34036 34037 // update main bulk checkbox 34038 if(0 == $('.domain-bulk-op-item:not(:checked)').length && 0 != $('.domain-bulk-op-item:checked').length) { 34039 $('#domain-bulk-op-select-all').prop('checked', true); 34040 } 34041 }; 34042 34043 /** 34044 * Update bulk control block 34045 */ 34046 $.bulkStorageUpdateControl = function() { 34047 var storage = $.localStorage, 34048 bulkControl = $('#domain-bulk-control'), 34049 data = storage.isSet('domains_bulk') ? storage.get('domains_bulk') : []; 34050 34051 // update count of selected domains in table head 34052 0 == data.length ? bulkControl.addClass('hidden') : bulkControl.removeClass('hidden'); 34053 bulkControl.find('span>span').html(data.length); 34054 }; 34055 34056 /** 34057 * Clear selected domains. 34058 */ 34059 $.bulkClearSelectedDomains = function() { 34060 $.localStorage.set('domains_bulk', []); 34061 34062 // uncheck checkboxes 34063 $('.domain-bulk-op-item').prop('checked', false); 34064 $('#domain-bulk-op-select-all').prop('checked', false); 34065 34066 // hide control block 34067 $.bulkStorageUpdateControl(); 34068 }; 34069 34070 /** 34071 * Get selected domains. 34072 * 34073 * @return {Array} 34074 */ 34075 $.bulkGetSelectedDomains = function() { 34076 var checkboxes = $('.domain-bulk-op-item:checked'), 34077 storage = $.localStorage, 34078 data = storage.isSet('domains_bulk') ? storage.get('domains_bulk') : [], 34079 domains = []; 34080 34081 $.each(checkboxes, function() { 34082 domains.push($(this).data('domain')); 34083 }); 34084 34085 $.each(data, function() { 34086 if(-1 == $.inArray(this, domains)) { 34087 domains.push(this); 34088 } 34089 }); 34090 34091 return domains; 34092 }; 34093 34094 $(document).ready(function(e) { 34095 34096 // update checkboxes 34097 $.bulkStorageUpdateCheckboxes(); 34098 34099 // update bulk control block 34100 $.bulkStorageUpdateControl(); 34101 34102 // clear selected domains 34103 $('#domain-bulk-control').find('a').click(function(e) { 34104 $.bulkClearSelectedDomains(); 34105 34106 e.preventDefault(); 34107 }); 34108 34109 // change domains per page 34110 $('#domains-per-page').change(function () { 34111 $.pageReload({'domains_qty': $(this).val()}); 34112 }); 34113 34114 // check/uncheck all checkboxes
34115 $('#domain-bulk-op-select-all').change(function () { 34116 $('.domain-bulk-op-item').not(':disabled').prop('checked', $(this).prop("checked")); 34117 $.bulkStorageDomainsUpdate(); 34118 }); 34119 34120 // update bulk control 34121 $('.domain-bulk-op-item').change(function () { 34122 $.bulkStorageDomainsUpdate(); 34123 }); 34124 34125 // bulk renew 34126 $('#domain-bulk-renew-action').click(function(e) { 34127 var el = $(this); 34128 34129 el.buttonLoading('loading'); 34130 34131 // get selected domains 34132 var domains = $.bulkGetSelectedDomains(); 34133 34134 // no domains selected 34135 if(0 == domains.length) { 34136 el.buttonLoading('reset'); 34137 34138 $.showError($.translate('Please select domains.')); 34139 34140 e.preventDefault(); 34141 return; 34142 } 34143 34144 // get form 34145 $.get(el.attr('href'), {domains: domains}, function(response) { 34146 el.buttonLoading('reset'); 34147 34148 // if user is anonymous 34149 if(0 == response.status && undefined != response.page) { 34150 window.location = Storage.getData('app_url') + response.page; 34151 34152 return; 34153 } 34154 34155 // if error message and need to show errors 34156 if(0 == response.status && undefined != response.message) { 34157 $.showError(response.message); 34158 34159 return; 34160 } 34161 34162 // show form 34163 $.fancybox.open({ 34164 type: 'iframe', 34165 padding: 0, 34166 content: response.html, 34167 afterShow: function () { 34168 // vars 34169 var form = $('#renew-domain-bulk-op'), 34170 years = form.find('input[type="radio"]'), 34171 domains = form.find('#bulk-op-domains-list input[type="checkbox"]'), 34172 cvvHelp = form.find('.cvvhelp'), 34173 cvvHelpImage = form.find('.cvvhelp img'), 34174 checkCoupon = form.find('#checkCoupon'), 34175 couponCode = form.find('#couponCode'); 34176 couponError = form.find('#cpn-error'), 34177 couponMessage = form.find('#cpnDis'), 34178 button = $('button#renew'); 34179 34180 // tooltips name 34181 $('.show-tooltip').addTooltip(); 34182 34183 // cvv help image 34184 cvvHelp.hover(function () { 34185 cvvHelpImage.show(); 34186 }, function () { 34187 cvvHelpImage.hide(); 34188 }); 34189 34190 // update price 34191 years.change(function() { 34192 $.bulkOpUpdatePrice(form, years, domains); 34193 }); 34194 34195 domains.change(function() { 34196 $.bulkOpUpdatePrice(form, years, domains); 34197 }); 34198 34199 $.bulkUpdateYearlyPrices(); 34200 34201 // check coupon 34202 couponCode.on('keyup change', function() { 34203 var el = $(this), state = false; 34204 34205 if('' == el.val() || 0 == years.filter(':checked').length || 0 == domains.filter(':checked').length) { 34206 state = true; 34207 } 34208 34209 checkCoupon.prop('disabled', state); 34210 }); 34211 34212 checkCoupon.click(function (e) { 34213 var code = $('#couponCode').val(); 34214 checkCoupon.buttonLoading('loading'); 34215 34216 $.get(Storage.getData('app_url') + 'checkCpn/' + code, '', function (response) { 34217 $.bulkOpUpdatePrice(form, years, domains, parseFloat(response)); 34218 34219 checkCoupon.button('reset'); 34220 }); 34221 }); 34222 34223 // submit form 34224 var bulkRenewSubmitting = false; 34225 form.on('submit', function() { 34226 e.preventDefault(); 34227 if (bulkRenewSubmitting) return false; 34228 button.buttonLoading('loading'); 34229 34230 // validate form 34231 var errors = $.domainBulkValidatePurchase(form); 34232 34233 // hide/show errors 34234 $.bulkOpShowErrors(form, errors, form.find('.modal-footer>div>div')); 34235 34236 if(errors.length > 0) { 34237 button.buttonLoading('reset'); 34238 34239 return false; 34240 } 34241 34242 bulkRenewSubmitting = true; 34243 34244 // submit form 34245 var url = Storage.getData('app_url') + 'domain/bulk-renew/submit'; 34246 var postData = $(this).serialize(); 34247 34248 $.post(url, postData, function (response) { 34249 bulkRenewSubmitting = false;
34250 button.buttonLoading('reset'); 34251 34252 if (0 == response.status && undefined != response.premiumDomains) { 34253 // show warning about new price 34254 $.bulkOpShowWarnings(form, [{message: response.message}], form.find('.modal-footer>div>div')); 34255 34256 // update form 34257 $('#domain-purchase-is-premium').val(1); 34258 34259 // update prices 34260 $.each(response.premiumDomains, function(key, value) { 34261 var domain = form.find('[name="domains[{0}]"]'.format(key)); 34262 34263 for (var year in value) { 34264 domain.attr('data-price-{0}'.format(year), value[year]) 34265 } 34266 }); 34267 34268 $.bulkOpUpdatePrice(form, years, domains); 34269 } else if ( 34270 undefined !== response.format 34271 && undefined !== response.type 34272 && 'popin' === response.format 34273 && 'pendingRenew' === response.type 34274 ) { 34275 if (0 !== $('#domain-renew-confirm-pending-bulk').length) { 34276 $('#domain-renew-confirm-pending-bulk').modal('show'); 34277 } else { 34278 $(response.msg).modal('show'); 34279 } 34280 } else { 34281 // show error message 34282 if (0 == response.status && undefined != response.message) { 34283 $.bulkOpShowErrors(form, [{message: response.message}], form.find('.modal-footer>div>div')); 34284 } 34285 34286 // do redirect 34287 if(0 == response.status && undefined != response.page) { 34288 window.location = Storage.getData('app_url') + response.page; 34289 } 34290 } 34291 34292 // all is ok 34293 if (response.status == 1) { 34294 $.fancybox.close(); 34295 $.bulkClearSelectedDomains(); 34296 34297 if(undefined != response.message && undefined != response.message.text && undefined != response.message.title) { 34298 $.showSuccess(response.message.title, response.message.text); 34299 } 34300 } 34301 }).fail(function () { 34302 bulkRenewSubmitting = false; 34303 button.buttonLoading('reset'); 34304 }); 34305 34306 return false; 34307 }); 34308 } 34309 }); 34310 }); 34311 34312 e.preventDefault(); 34313 }); 34314 34315 // bulk op update price 34316 $.bulkOpUpdatePrice = function(form, years, domains, coupon) { 34317 $.bulkUpdateYearlyPrices(); 34318 34319 34320 var years = years.filter(':checked'), 34321 domains = domains.filter(':checked'), 34322 price = form.find('#domain-bulk-op-total-prise'), 34323 paymentSection = $('#renew-domain-bulk-op-payment-section'), 34324 couponError = form.find('#cpn-error'), 34325 couponMessage = form.find('#cpnDis'), 34326 checkCoupon = form.find('#checkCoupon'), 34327 couponInput = $('#couponCode'); 34328 34329 // set default price 34330 if(0 == years.length || 0 == domains.length) { 34331 price.html('0.00'); 34332 34333 return; 34334 } 34335 34336 // calculate price 34337 var totalYears = parseInt(years.val()), 34338 total = 0 34339 ; 34340 34341 $.each(domains, function() { 34342 var 34343 domainPrice = 0 34344 ; 34345 34346 for (var i = 1; i < totalYears + 1; i++) { 34347 var yearPrice = $(this).attr('data-price-{0}'.format(i)); 34348 34349 if (undefined !== yearPrice) { 34350 domainPrice += parseFloat(yearPrice); 34351 } 34352 } 34353 34354 total += domainPrice; 34355 }); 34356 34357 price.html(Number(total).toFixed(2)); 34358 34359 // coupon feature 34360 // no coupon defined - hide discount messages 34361 if(typeof undefined == typeof coupon) { 34362 couponError.addClass('hidden'); 34363 couponMessage.addClass('hidden'); 34364 paymentSection.removeClass('hidden'); 34365 couponInput.val(''); 34366 checkCoupon.prop('disabled', true); 34367 } else if (coupon <= 0) { 34368 // wrong response or wrong coupon - show error message 34369 couponError.removeClass('hidden'); 34370 couponMessage.addClass('hidden'); 34371 paymentSection.removeClass('hidden') 34372 } else { 34373 // all is ok 34374 couponError.addClass('hidden'); 34375 couponMessage.removeClass('hidden'); 34376 34377 // calculate discount 34378 var afterCoupon = total - coupon; 34379 34380 afterCoupon <= 0 ? paymentSection.addClass('hidden') : paymentSection.removeClass('hidden'); 34381 form.find('#cpnDis .amount').html(total); 34382 form.find('#cpnDis .sum').html(afterCoupon >= 0 ? Number(afterCoupon).toFixed(2) : 0); 34383 } 34384 }; 34385 34386 $.bulkUpdateYearlyPrices = function(){ 34387 var form = $('#renew-domain-bulk-op'), 34388 periods = form.find('input[type="radio"]'), 34389 domains = form.find('#bulk-op-domains-list input[type="checkbox"]').filter(':checked'), 34390 total = 0.0; 34391 34392 const periodValues = Array.from(periods).map(radio => parseInt(radio.value)).sort((a, b) => a - b); 34393
34394 periodValues.forEach(period => { 34395 //loop all selected domains 34396 $.each(domains, function() { 34397 var yearPrice = $(this).attr(`data-price-${period}`); 34398 34399 if (undefined !== yearPrice) { 34400 total += parseFloat(yearPrice); 34401 } 34402 }); 34403 34404 $(`#price-total-year${period}`).html(Number(total).toFixed(2)); 34405 $(`#price-per-year-year${period}`).html(Number(total/period).toFixed(2)); 34406 }) 34407 } 34408 34409 /** 34410 * Update bulk domains storage. 34411 */ 34412 $.bulkStorageDomainsUpdate = function() { 34413 var storage = $.localStorage, 34414 checked = $('.domain-bulk-op-item:checked'), 34415 unchecked = $('.domain-bulk-op-item:not(:checked)'), 34416 data = storage.isSet('domains_bulk') ? storage.get('domains_bulk') : []; 34417 34418 // add checked domains 34419 $.each(checked, function() { 34420 var id = $(this).data('domain'); 34421 34422 if(-1 == jQuery.inArray(id, data)) { 34423 data.push(id); 34424 } 34425 }); 34426 34427 // remove unchecked 34428 $.each(unchecked, function() { 34429 var id = $(this).data('domain'); 34430 34431 if(-1 != jQuery.inArray(id, data)) { 34432 var index = data.indexOf(id); 34433 data.splice(index, 1); 34434 } 34435 }); 34436 34437 // update storage 34438 storage.set('domains_bulk', data); 34439 34440 // update control block 34441 $.bulkStorageUpdateControl(); 34442 }; 34443 34444 /** 34445 * Show errors 34446 * todo@alexbuturlakin: need to remove this method after validation will be refactored. 34447 * 34448 * @param {jQuery} form 34449 * @param {[]} errors 34450 * @param {jQuery} el 34451 */ 34452 $.bulkOpShowErrors = function(form, errors, el) { 34453 var messages = []; 34454 34455 // clear errors 34456 form.find('.has-error').removeClass('has-error'); 34457 form.find('.alert-danger').remove(); 34458 34459 $.each(errors, function(k, v) { 34460 if(undefined != v['el']) { 34461 $(v['el']).parent().addClass('has-error'); 34462 } 34463 34464 messages.push(v['message']); 34465 }); 34466 34467 if(messages.length > 0) { 34468 el.showAlert(messages.join('<br/>'), 'danger'); 34469 } 34470 }; 34471 34472 /** 34473 * Show errors 34474 * todo@alexbuturlakin: need to remove this method after validation will be refactored. 34475 * 34476 * @param {jQuery} form 34477 * @param {[]} errors 34478 * @param {jQuery} el 34479 */ 34480 $.bulkOpShowWarnings = function(form, errors, el) { 34481 var messages = []; 34482 34483 // clear warnings 34484 form.find('.alert-warning').remove(); 34485 34486 $.each(errors, function(k, v) { 34487 if(undefined != v['el']) { 34488 $(v['el']).parent().addClass('has-error'); 34489 } 34490 34491 messages.push(v['message']); 34492 }); 34493 34494 if(messages.length > 0) { 34495 el.showAlert(messages.join('<br/>'), 'warning'); 34496 } 34497 }; 34498 34499 // validate card 34500 // todo@alexbuturlakin: this is hardcode from domain renew. Need to refactor and use plugin for validation. 34501 $.domainBulkValidatePurchase = function (form) { 34502 var creditReg = /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|6(?:011|5[0-9]{2})[0-9]{12}|(?:2131|1800|35\d{3})\d{11})$/; 34503 var creditCardEl = form.find('#creditNumber'); 34504 var creditYrEl = form.find('#creditExpirationYear'); 34505 var creditMoEl = form.find('#creditExpirationMonth'); 34506 var creditCardCvvEl = form.find('#creditCvv'); 34507 var creditIdEl = form.find('#creditId'); 34508 var domainPeriodEl = form.find('#domainPeriod'); 34509 var date = new Date(); 34510 var creditCard = creditCardEl.val(); 34511 var creditCardYr = creditYrEl.val(); 34512 var creditCardMo = creditMoEl.val(); 34513 var creditCardCvv = creditCardCvvEl.val(); 34514 var creditCardId = creditIdEl.val(); 34515 var domainPeriod = parseInt($('[name=domainPeriod]:checked').val()); 34516 var approve_termsEl = $('#approve_terms'); 34517 var approve_terms = approve_termsEl.is(":checked"); 34518 var errors = []; 34519 34520 var addError = function(el, message) { 34521 errors.push({el: el, message: message}); 34522 }; 34523 34524 if(approve_terms != undefined) { 34525 if (!approve_terms) { 34526 addError(approve_termsEl, $.translate('Approve Terms is required')); 34527 } 34528 } 34529 34530 if(false == $('#renew-domain-bulk-op-payment-section').hasClass('hidden')) { 34531 if (isNaN(creditCardYr) || parseInt(creditCardYr) < date.getFullYear()) { 34532 addError(creditYrEl, $.translate('Expiry Year is invali
34532d')); 34533 } 34534 34535 if (isNaN(creditCardMo) || creditCardYr == date.getFullYear() && creditCardMo < date.getMonth()) { 34536 addError(creditMoEl, $.translate('Expiry Month is invalid')); 34537 } 34538 34539 if (isNaN(creditCardCvv) || creditCardCvv.length < 3 || creditCardCvv.length > 4) { 34540 addError(creditCardCvvEl, $.translate('cvv is invalid')); 34541 } 34542 34543 if (isNaN(creditCardId) || creditCardId.length < 9 || creditCardId.length > 9) { 34544 addError(creditIdEl, $.translate('id is invalid')); 34545 } 34546 34547 if (isNaN(creditCard) || creditCard.length < 9 || creditCard.length > 17 || !creditReg.test(creditCard) && creditCard.length > 9 || creditCard[0] === 0) { 34548 addError(creditCardEl, $.translate('card is invalid')); 34549 } 34550 } 34551 34552 if (domainPeriod < 1 && domainPeriod > 5) { 34553 addError(domainPeriodEl, $.translate('Domain Period is invalid')); 34554 } 34555 return errors; 34556 }; 34557 34558 $(document).on('click', '#domain-renew-confirm-bulk-confirm', function() { 34559 $('#domain-renew-confirm-pending-bulk').modal('hide'); 34560 $('#domain-renew-pending-confirmed').val(1); 34561 $('#renew').trigger('click'); 34562 }); 34563 34564 $(document).on('click', '#domain-renew-confirm-bulk-cancel', function() { 34565 $('#domain-renew-confirm-pending-bulk').modal('hide'); 34566 }); 34567 34568 }); 34569})(jQuery); 34570 34571/** 34572 * This file is part of the "box" project. 34573 * 34574 * (c) Alex Buturlakin [email protected] 34575 */ 34576 34577;(function($) { 34578 34579 // copy - paste from main.js, this code needs refactoring 34580 function validateContact(form) { 34581 var priPhoneEl = form.find('#contactLanding'); 34582 var contactFax = form.find('#contactFax'); 34583 var streetEl = form.find('#contactStreet'); 34584 var cityEl = form.find('#contactCity'); 34585 var countryEl = form.find('#contactCountry'); 34586 var zipEl = form.find('#contactZip'); 34587 34588 if(0 == priPhoneEl.length && 0 == contactFax.length && 0 == cityEl.length) { 34589 return true; 34590 } 34591 34592 var street = streetEl.val(); 34593 var city = cityEl.val(); 34594 var country = countryEl.val(); 34595 var zip = zipEl.val(); 34596 var phone1 = form.find('#tel1').val(); 34597 var phone2 = form.find('#tel2').val(validatePerf(form.find('#tel2').val())).val(); 34598 var phone3 = form.find('#tel3').val(); 34599 var fax1 = form.find('#fax1').val(); 34600 var fax2 = form.find('#fax2').val(validatePerf(form.find('#fax2').val())).val(); 34601 var fax3 = form.find('#fax3').val(); 34602 priPhoneEl.val(phone3 + ' ' + phone2 + ' ' + phone1); 34603 contactFax.val(fax3 + ' ' + fax2 + ' ' + fax1); 34604 34605 var priPhone = priPhoneEl.val(); 34606 var errors = ''; 34607 var ct = true; 34608 34609 form.find('input').each(function () { 34610 if (!ctype_print($(this).val())) { 34611 ct = false; 34612 } 34613 }); 34614 34615 if (!ct) { 34616 errors += $.translate('English Only') + '\n'; 34617 } 34618 34619 if (priPhone === '' || priPhone.length < 13 || !/[0-9\s]+/.test(priPhone)) { 34620 priPhoneEl.parent().addClass('has-error'); 34621 errors += $.translate('Primary phone is required') + '\n'; 34622 } else { 34623 priPhoneEl.parent().removeClass('has-error'); 34624 } 34625 34626 if (street === '' || street.length < 2 || !/[0-9]/.test(street)) { 34627 streetEl.parent().addClass('has-error'); 34628 errors += $.translate('Street is required') + '\n'; 34629 } else { 34630 streetEl.parent().removeClass('has-error'); 34631 } 34632 34633 if (city === '' || city.length < 2 || /[0-9]/.test(city)) { 34634 cityEl.parent().addClass('has-error'); 34635 errors += $.translate('City is required') + '\n'; 34636 } else { 34637 cityEl.parent().removeClass('has-error'); 34638 } 34639 34640 if (zip === '' || zip.length !== 7) { 34641 zipEl.parent().addClass('has-error'); 34642 errors += $.translate('Zip is required') + '\n'; 34643 } else if (window.isInvalidZipCode(zip)) { 34644 zipEl.parent().addClass('has-error'); 34645 errors += $.translate('Zip is invalid') + '\n'; 34646 } else { 34647 zipEl.parent().removeClass('has-error'); 34648 } 34649 34650 if (country === '') { 34651 countryEl.parent().addClass('has-error'); 34652 errors += $.translate('Country is required') + '\n'; 34653 } else { 34654 countryEl.parent().removeClass('has-error'); 34655 } 34656 34657 if (errors !== '') { 34658 $('#updatecnt-errors').html(nl2br(errors, true)).removeClass('hidden'); 34659 34660 return false;
34661 } else { 34662 $('#updatecnt-errors').addClass('hidden'); 34663 34664 return true; 34665 } 34666 } 34667 34668 $(document).ready(function(e) { 34669 // change domain contacts 34670 $(document).on('click', '.update-cnt', function (e) { 34671 e.preventDefault(); 34672 var uid = $(this).parent().parent().data('uid'); 34673 $.get(Storage.getData('app_url') + 'domain/updatecnt/' + uid, function (response) { 34674 if (3 == response.status) { 34675 window.location = Storage.getData('app_url') + 'user/login'; 34676 return; 34677 } 34678 34679 if(0 == response.status) { 34680 return; 34681 } 34682 34683 $.fancybox.open({ 34684 type: 'iframe', 34685 padding: 0, 34686 content: response.html, 34687 afterShow: function () { 34688 $('#saveCnt').click(function (e) { 34689 e.preventDefault(); 34690 var form = $(this).closest('form'); 34691 $(this).button('loading'); 34692 if(validateContact(form)) { 34693 $.post(form.attr('action') + '/' + uid, form.serialize(), function (r) { 34694 r = JSON.parse(r); 34695 if (r.status == 1) { 34696 $('#domainflash').html(r.msg).removeClass('hidden'); 34697 $('#updatecnt-errors').addClass('hidden'); 34698 $.fancybox.close(); 34699 } 34700 if (r.status == 0) { 34701 $('#updatecnt-errors').html(nl2br(r.msg, true)).removeClass('hidden'); 34702 $('#contactEmailVerify').prop('disabled', true); 34703 $('#VerifyEmailSection').addClass('hidden'); 34704 $('#VerifyEmailSection').removeClass('has-error'); 34705 $('#updatecnt-info').addClass('hidden'); 34706 $('#saveCnt').button('reset'); 34707 } 34708 if (r.status == 4) { 34709 $('#updatecnt-errors').addClass('hidden'); 34710 $('#updatecnt-info').html(nl2br(r.msg, true)).removeClass('hidden'); 34711 $('#contactEmailVerify').prop('disabled', false); 34712 $('#VerifyEmailSection').removeClass('hidden'); 34713 $('#VerifyEmailSection').addClass('has-error'); 34714 $('.fancybox-overlay').scrollTop($('#VerifyEmailSection').offset().top); 34715 $('#saveCnt').button('reset'); 34716 } 34717 }) 34718 }else{ 34719 $('#saveCnt').button('reset'); 34720 } 34721 }) 34722 } 34723 }) 34724 }); 34725 }); 34726 34727 // domain after transfer set contact 34728 if(Storage.hasData('newTransferedDomain')) { 34729 var uid = Storage.getData('newTransferedDomain'), 34730 modalCallback = function(params) { 34731 34732 // copy - paste from user/account.php inline js code 34733 var msg = typeof undefined === typeof params.msg ? false : params.msg, 34734 ec = $('#updatecnt-errors'), 34735 uid = params.uid; 34736 34737 if (false != msg) { 34738 $('#updatecnt-suc').html(msg).removeClass('hidden'); 34739 } 34740 34741 $('#saveCnt').click(function (e) { 34742 e.preventDefault(); 34743 34744 var form = $(this).closest('form'), 34745 submit = $(this); 34746 34747 ec.addClass('hidden'); 34748 34749 submit.buttonLoading('loading'); 34750 34751 if(validateContact(form)) 34752 34753 $.post(Storage.getData('app_url') + 'domain/transfer-rcv/' + uid, $('#updatecnt').serialize(), function (response) { 34754 34755 submit.buttonLoading('reset'); 34756 34757 if (response.status == 1) { 34758 $('#domainflash').html(response.msg).removeClass('hidden'); 34759 ec.addClass('hidden'); 34760 $.fancybox.close(); 34761 } 34762 34763 if (response.status == 0) { 34764 ec.html(nl2br(response.msg, true)).removeClass('hidden'); 34765 } 34766 34767 if (response.status == 2) { 34768 ec.addClass('hidden'); 34769 $.fancybox.close(); 34770 34771 $.showXHRModal(Storage.getData('app_url') + 'domain/updatecnt/' + response.next, modalCallback, {'uid': response.next, 'msg': response.msg}); 34772 } 34773 }); 34774 }); 34775 }; 34776 34777 $.showXHRModal(Storage.getData('app_url') + 'domain/updatecnt/' + uid, modalCallback, {'uid': uid}); 34778 } 34779 }); 34780})(jQuery); 34781;(function($) { 34782 34783 $(document).ready(function() { 34784 34785 $(document).on('click', '.renew-link', function(e) { 34786 34787 e.preventDefault(); 34788 var domain = $(this).data('did'); 34789 34790 $.get(Storage.getData('app_url') + 'domain/getRenewLink/' + domain, function (response) { 34791 if(response.status == 1) { 34792 $.fancybox.open({ 34793 type: 'iframe', 34794 padding: 5, 34795 content: response.html, 34796 afterShow: function () { 34797 var form = $('#renew-link'); 34798 e.preventDefault(); 34799 form.on('submit', function(e) { 34800 e.preventDefault(); 34801 var submitButton = $(e.originalEvent && e.originalEvent.submitter || document.activeElement); 34802 submitButton.button('loading'); 34803 var userEmail = form.find('#userEmail').val(); 34804 $.post(Storage.getData('app_url') + 'domain/generateRenewLink/' + domain, { 34805 userEmail: userEmail 34806 }, function(response) { 34807 var resSection = $('#renew-link-response'); 34808 if(response.status == 1) { 34809 34810 resSection. 34811 removeClass('hidden'). 34812 removeClass('alert-danger alert'). 34813 addClass('alert-success alert'). 34814 html(response.msg) 34815 ; 34816 submitButton.button('reset'); 34817 34818 // Add click handler for the link after it's added to DOM 34819 resSection.find('a').on('click', function(e) { 34820 e.preventDefault(); 34821 34822 var linkUrl = $(this).attr('href'); 34823 var $temp = $('<textarea>'); 34824 $('body').append($temp); 34825 $temp.val(linkUrl).select(); 34826 document.execCommand('copy'); 34827 $temp.remove(); 34828 34829 // Optional: show feedback 34830 var $link = $(this); 34831 var originalText = $link.text(); 34832 $link.text('××עתק!'); 34833 setTimeout(function() { 34834 $link.text(originalText); 34835 }, 2000); 34836 }); 34837 }else{ 34838 resSection. 34839 removeClass('hidden'). 34840 removeClass('alert-success alert'). 34841 addClass('alert-danger alert'). 34842 html(response.msg) 34843 ; 34844 submitButton.button('reset'); 34845 } 34846 34847 }); 34848 34849 }); 34850 34851 } 34852 }) 34853 }else{ 34854 $(this).button('reset'); 34855 console.log(response.status, response.msg); 34856 } 34857 }); 34858 34859 }); 34860 34861 }); 34862 34863 34864 34865 34866})(jQuery); 34867;(function ($) { 34868 var showTFAReminderPopin = function (popinData) { 34869 var html = '<div id="tfa-reminder" class="modal-ok" style="width: 400px;">', 34870 head = '<div class="modal-header"><span class="UISectionTitleSummary UILabelIconValid">{0}</span></div>'.format(popinData.title), 34871 body = '<div class="modal-body">{0}</div>'.format(popinData.text), 34872 foot = 34873 '<div class="modal-footer">' + 34874 '<button class="btn btn-success">{0}</a>'.format(popinData.buttons.accept) + 34875 '<button class="btn btn-info close-window">{0}</button>'.format(popinData.buttons.cancel) + 34876 '<div class="form-group">' + 34877 '<label for="tfa-reminder-checkbox">{0}</label>'.format(popinData.checkbox) + 34878 '<input id="tfa-reminder-checkbox" type="checkbox" class="clean"/>' + 34879 '</div>' + 34880 '</div>' 34881 ; 34882 34883 html = html + head + body + foot + '</div>'; 34884 34885 var closeFancyBox = function (fancybox, notShowAgain, redirect) { 34886 if (false === notShowAgain) { 34887 fancybox.close(); 34888 34889 if (undefined !== redirect) { 34890 window.location.href = redirect; 34891 } 34892 34893 return false;
34894 } 34895 34896 var 34897 csrfConfig = Storage.getData('csrf_config'), 34898 data = { 'tfaReminder': false } 34899 ; 34900 34901 data[csrfConfig['token_name_key']] = popinData.csrf.name; 34902 data[csrfConfig['token_key']] = popinData.csrf.token; 34903 34904 $.post('/user/profile', data) 34905 .done(function() { 34906 if (undefined !== redirect) { 34907 window.location.href = redirect; 34908 } 34909 }) 34910 .fail(function (response) { 34911 if (403 === response.status) { 34912 window.location.href = '/user/login'; 34913 } 34914 }) 34915 ; 34916 34917 fancybox.close(); 34918 }; 34919 34920 $.fancybox.open({ 34921 content: html, 34922 padding: 0, 34923 type: 'iframe', 34924 afterShow: function () { 34925 $('#tfa-reminder button.close-window').click(function () { 34926 closeFancyBox($.fancybox, $('#tfa-reminder-checkbox').is(':checked')); 34927 }); 34928 34929 $('#tfa-reminder button.btn-success').click(function () { 34930 closeFancyBox($.fancybox, $('#tfa-reminder-checkbox').is(':checked'), '/user/profile/tfa'); 34931 }); 34932 34933 } 34934 }); 34935 }; 34936 34937 $(document).ready(function () { 34938 // TFA popin reminder 34939 if (Storage.hasData('tfaReminderPopin')) { 34940 showTFAReminderPopin(Storage.getData('tfaReminderPopin')); 34941 } 34942 34943 // tfa configuration 34944 if (Storage.hasData('tfaConfiguration')) { 34945 $('#form-enable-tfa-submit').click(function (e) { 34946 e.preventDefault(); 34947 34948 var next = $(this), 34949 state = next.attr('data-state'), 34950 urls = Storage.getData('tfaConfiguration').urls, 34951 csrfConfig = Storage.getData('csrf_config'), 34952 data = {} 34953 ; 34954 34955 next.buttonLoading('loading'); 34956 34957 if ('phone' === state) { 34958 $.post(urls.code, next.closest('form').serialize()) 34959 .done(function () { 34960 $('#form-enable-tfa-code').removeClass('hidden'); 34961 $('#auth-code').prop('disabled', false); 34962 $('#form-enable-tfa-phone .alert').alert('close'); 34963 34964 next.attr('data-state', 'verification'); 34965 }) 34966 .fail(function (response) { 34967 if (403 === response.status) { 34968 window.location.href = '/user/login'; 34969 } 34970 34971 $('#form-enable-tfa-phone').showAlert(response.responseJSON.error, 'danger', null, 'prepend', 'col-sm-8'); 34972 next.buttonLoading('reset'); 34973 }) 34974 .always(function () { 34975 next.buttonLoading('reset'); 34976 }) 34977 ; 34978 } 34979 34980 if ('verification' === state) { 34981 data = { 34982 phone: { 34983 number: $('#authy-cellphone').val(), 34984 code: $('#countries-input-0').val() 34985 }, 34986 code: $('#auth-code').val() 34987 }; 34988 34989 data[csrfConfig['token_name_key']] = $('input[name=csrf_token_name]').val(); 34990 data[csrfConfig['token_key']] = $('input[name=csrf_token]').val(); 34991 34992 34993 $.post(urls.verify, next.closest('form').serialize()) 34994 .done(function (response) { 34995 $('#form-enable-tfa-qr').removeClass('hidden'); 34996 $('#form-user-auth-tfa-image').attr('src', response.qr); 34997 $('#form-enable-tfa-ga').removeClass('hidden'); 34998 34999 $('#form-enable-tfa-phone input').attr('disabled', 'disabled'); 35000 $('#form-enable-tfa-code input').attr('disabled', 'disabled'); 35001 35002 next.attr('data-state', 'ga'); 35003 next.button('ga'); 35004 }) 35005 .fail(function (response) { 35006 if (403 === response.status) { 35007 window.location.href = '/user/login'; 35008 } 35009 35010 $('#form-enable-tfa-code').showAlert(response.responseJSON.error, 'danger', null, 'prepend', 'col-sm-8'); 35011 35012 next.buttonLoading('reset'); 35013 }) 35014 ; 35015 } 35016 35017 if ('ga' === state) { 35018 data = next.closest('form').serialize(); 35019 data['code'] = $('#ga-code').val(); 35020 35021 $.post(urls.ga, data) 35022 .done(function (response) { 35023 $('#form-enable-tfa-ga input').attr('disabled', 'disabled'); 35024 35025 if (undefined !== response.redirect) { 35026 window.location.href = response.redirect; 35027 return; 35028 } 35029 35030 window.location.href = urls.account; 35031 }) 35032 .fail(function (response) { 35033 if (403 === response.status) { 35034 window.location.href = '/user/login'; 35035 } 35036 35037 $('#form-enable-tfa-ga').showAlert(response.responseJSON.error, 'danger', null, 'prepend', 'col-sm-8'); 35038 35039 next.buttonLoading('ga'); 35040 }) 35041 ; 35042 } 35043 }); 35044 35045 $('#form-enable-tfa-verified-submit').click(function (e) { 35046 e.preventDefault(); 35047 35048 var 35049 next = $(this), 35050 urls = Storage.getData('tfaConfiguration').urls, 35051 data = next.closest('form').serialize() 35052 ; 35053 35054 next.buttonLoading('loading'); 35055 35056 $.post(urls.ga, data) 35057 .done(function (response) { 35058 $('#form-enable-tfa-verified-ga input').attr('disabled', 'disabled'); 35059 35060 if (undefined !== response.redirect) { 35061 window.location.href = response.redirect; 35062 return; 35063 } 35064 35065 window.location.href = urls.account; 35066 }) 35067 .fail(function (response) { 35068 if (403 === response.status) { 35069 window.location.href = '/user/login'; 35070 } 35071 35072 $('#form-enable-tfa-verified-ga').showAlert(response.responseJSON.error, 'danger', null, 'prepend', 'col-sm-8'); 35073 35074 next.buttonLoading('reset'); 35075 }) 35076 ; 35077 }); 35078 } 35079 35080 $('#tfa-backup-codes-confirm').change(function () { 35081 var continueLink = $('#tfa-backup-codes-continue'); 35082 35083 if ($(this).is(':checked')) { 35084 continueLink.removeClass('disabled').attr('aria-disabled', 'false'); 35085 } else { 35086 continueLink.addClass('disabled').attr('aria-disabled', 'true'); 35087 } 35088 }); 35089 35090 $('#tfa-backup-codes-continue').click(function (e) { 35091 if (!$('#tfa-backup-codes-confirm').is(':checked')) { 35092 e.preventDefault(); 35093 } 35094 }); 35095 35096 $('#tfa-backup-codes-download').click(function () { 35097 var button = $(this), 35098 codes = button.attr('data-codes') || '', 35099 filename = button.attr('data-filename') || 'backup-codes.txt',
35100 blob = new Blob([codes], {type: 'text/plain;charset=utf-8'}), 35101 link = document.createElement('a') 35102 ; 35103 35104 link.href = window.URL.createObjectURL(blob); 35105 link.download = filename; 35106 document.body.appendChild(link); 35107 link.click(); 35108 document.body.removeChild(link); 35109 window.URL.revokeObjectURL(link.href); 35110 }); 35111 35112 $('#update-settings-form-tfa').click(function (e) { 35113 e.preventDefault(); 35114 35115 var csrfConfig = Storage.getData('csrf_config'), 35116 form = $(this.closest('form')), 35117 button = $(this), 35118 state = 'enabled' === button.attr('data-state') ? 'disabled' : 'enabled', 35119 data = {'tfa': 'enabled' === state} 35120 ; 35121 35122 button.buttonLoading('loading'); 35123 35124 data[csrfConfig['token_name_key']] = form.find('[name=csrf_token_name]').val(); 35125 data[csrfConfig['token_key']] = form.find('[name=csrf_token]').val(); 35126 35127 $.post('/user/profile', data) 35128 .done(function (response) { 35129 if (403 === response.status) { 35130 window.location.href = '/user/login'; 35131 35132 return false; 35133 } 35134 35135 if (undefined !== response.redirect) { 35136 window.location.href = response.redirect; 35137 35138 return false; 35139 } 35140 35141 if ('enabled' === state && undefined !== response.qr) { 35142 if (0 === response.qr.length) { 35143 $('#update-settings-form-qr-view').removeClass('hidden'); 35144 } else { 35145 $('#update-settings-form-qr-actions').removeClass('hidden'); 35146 $('#update-settings-form-enable-qr img').attr('src', response.qr).removeClass('hidden'); 35147 $('#update-settings-form-qr-remove').removeClass('hidden'); 35148 $('#update-settings-form-qr-view').addClass('hidden'); 35149 } 35150 $('#update-settings-form-enable-qr').removeClass('hidden'); 35151 $('#update-settings-form-qr-generate').addClass('hidden'); 35152 35153 if (true === response.sc.profilePhone.access) { 35154 $('#user-profile-change-phone button').removeClass('hidden'); 35155 } else { 35156 $('#user-profile-change-phone button').addClass('hidden'); 35157 } 35158 } 35159 35160 if ('disabled' === state) { 35161 $('#update-settings-form-enable-qr img').attr('src', ''); 35162 $('#update-settings-form-enable-qr').addClass('hidden'); 35163 $('#user-profile-change-phone').removeClass('hidden'); 35164 $('#user-profile-change-phone button').removeClass('hidden'); 35165 } 35166 35167 button.button(state); 35168 button.attr('class', button.attr('data-class-' + state)); 35169 button.attr('data-state', state); 35170 }) 35171 .fail(function (response) { 35172 button.buttonLoading('reset'); 35173 35174 if (403 === response.status && 'session.not_verified' === response.responseJSON.type) { 35175 window.verifySession(); 35176 35177 return false; 35178 } 35179 }) 35180 }); 35181 35182 $('#update-settings-form-qr-remove').click(function (e) { 35183 e.preventDefault(); 35184 35185 var link = $(this); 35186 35187 link.buttonLoading('loading'); 35188 35189 var 35190 button = $('#update-settings-form-tfa'), 35191 csrfConfig = Storage.getData('csrf_config'), 35192 actions = $('#update-settings-form-qr-actions'), 35193 data = {} 35194 ; 35195 35196 data[csrfConfig['token_name_key']] = actions.attr('data-token-name'); 35197 data[csrfConfig['token_key']] = actions.attr('data-token'); 35198 35199 $.post('/user/profile/qr/remove', data) 35200 .done(function (response) { 35201 link.addClass('hidden'); 35202 $('#update-settings-form-qr-generate').removeClass('hidden'); 35203 $('#update-settings-form-qr-img').addClass('hidden').attr('src', ''); 35204 35205 var buttonState = 'disabled'; 35206 35207 button.button(buttonState); 35208 button.attr('class', button.attr('data-class-' + buttonState)); 35209 button.attr('data-state', buttonState); 35210 35211 $('#update-settings-form-enable-qr img').attr('src', ''); 35212 $('#update-settings-form-enable-qr').addClass('hidden'); 35213 35214 if (true === response.sc.profilePhone.access) { 35215 $('#user-profile-change-phone button').removeClass('hidden'); 35216 } else { 35217 $('#user-profile-change-phone button').addClass('hidden'); 35218 } 35219 }) 35220 .fail(function (response) { 35221 if (403 === response.status && 'session.not_verified' === response.responseJSON.type) { 35222 window.verifySession(); 35223 35224 return false;
35225 } 35226 35227 if (403 === response.status) { 35228 window.location.href = '/user/login'; 35229 35230 return false; 35231 } 35232 }). 35233 always(function() { 35234 link.buttonLoading('reset'); 35235 }) 35236 }); 35237 35238 $('#update-settings-form-qr-generate').click(function (e) { 35239 e.preventDefault(); 35240 35241 var link = $(this); 35242 35243 link.buttonLoading('loading'); 35244 35245 var 35246 csrfConfig = Storage.getData('csrf_config'), 35247 actions = $('#update-settings-form-qr-actions'), 35248 data = {} 35249 ; 35250 35251 data[csrfConfig['token_name_key']] = actions.attr('data-token-name'); 35252 data[csrfConfig['token_key']] = actions.attr('data-token'); 35253 35254 $.post('/user/profile/qr/generate', data) 35255 .done(function (response) { 35256 link.addClass('hidden'); 35257 $('#update-settings-form-qr-remove').removeClass('hidden'); 35258 $('#update-settings-form-qr-img').removeClass('hidden').attr('src', response.qr) 35259 35260 if (true === response.sc.profilePhone.access) { 35261 $('#user-profile-change-phone button').removeClass('hidden'); 35262 } else { 35263 $('#user-profile-change-phone button').addClass('hidden'); 35264 } 35265 }) 35266 .fail(function (response) { 35267 if (403 === response.status && 'session.not_verified' === response.responseJSON.type) { 35268 window.verifySession(); 35269 35270 return false; 35271 } 35272 35273 if (403 === response.status) { 35274 window.location.href = '/user/login'; 35275 35276 return false; 35277 } 35278 }).always(function() { 35279 link.buttonLoading('reset'); 35280 }) 35281 ; 35282 }); 35283 35284 $('#update-settings-form-qr-view').click(function (e) { 35285 e.preventDefault(); 35286 35287 var link = $(this); 35288 35289 link.buttonLoading('loading'); 35290 35291 var data = {}; 35292 35293 $.get('/user/profile/qr/view', data) 35294 .done(function (response) { 35295 link.addClass('hidden'); 35296 35297 if (0 < response.qr.length) { 35298 $('#update-settings-form-qr-remove').removeClass('hidden'); 35299 $('#update-settings-form-qr-generate').addClass('hidden'); 35300 $('#update-settings-form-qr-img').removeClass('hidden').attr('src', response.qr); 35301 } else { 35302 $('#update-settings-form-qr-remove').addClass('hidden'); 35303 $('#update-settings-form-qr-generate').removeClass('hidden'); 35304 } 35305 35306 $('#update-settings-form-qr-actions').removeClass('hidden'); 35307 }) 35308 .fail(function (response) { 35309 if (403 === response.status && 'session.not_verified' === response.responseJSON.type) { 35310 window.verifySession(); 35311 35312 return false; 35313 } 35314 35315 if (403 === response.status) { 35316 window.location.href = '/user/login'; 35317 35318 return false; 35319 } 35320 }) 35321 .always(function() { 35322 link.buttonLoading('reset'); 35323 }) 35324 }); 35325 35326 // update phone number 35327 if (Storage.hasData('changePhoneConfiguration')) { 35328 $('button.btn-success').click(function (e) { 35329 e.preventDefault(); 35330 35331 var next = $(this), 35332 state = next.attr('data-state'), 35333 urls = Storage.getData('changePhoneConfiguration').urls, 35334 csrfConfig = Storage.getData('csrf_config') 35335 ; 35336 35337 next.buttonLoading('loading'); 35338 35339 if ('phone' === state) { 35340 $.post(urls.code, next.closest('form').serialize()) 35341 .done(function () { 35342 $('#form-profile-change-phone-number input').prop('disabled', true); 35343 $('#form-profile-change-phone-number .alert').alert('close'); 35344 $('#form-profile-change-phone-code').removeClass('hidden'); 35345 35346 next.attr('data-state', 'verification'); 35347 next.button('verify'); 35348 }) 35349 .fail(function (response) { 35350 if (403 === response.status) { 35351 window.location.href = '/user/login'; 35352 } 35353 35354 $('#form-profile-change-phone-number').showAlert(response.responseJSON.error, 'danger', null, 'prepend', 'col-sm-8'); 35355 next.buttonLoading('reset'); 35356 }) 35357 ; 35358 } 35359 35360 if ('verification' === state) { 35361 var data = { 35362 phone: { 35363 number: $('#authy-cellphone').val(), 35364 code: $('#countries-input-0').val() 35365 }, 35366 code: $('#auth-code').val() 35367 }; 35368 35369 data[csrfConfig['token_name_key']] = $('input[name=csrf_token_name]').val(); 35370 data[csrfConfig['token_key']] = $('input[name=csrf_token]').val(); 35371 35372 $.post(urls.verify, data) 35373 .done(function (response) { 35374 $('#form-profile-change-phone-code input').attr('disabled', 'disabled'); 35375 35376 next.addClass('hidden'); 35377 35378 $('.btn-info').addClass('hidden'); 35379 $('a.btn-success').removeClass('hidden'); 35380 }) 35381 .fail(function (response) { 35382 if (403 === response.status) { 35383 window.location.href = '/user/login'; 35384 } 35385 35386 $('#form-profile-change-phone-number').showAlert(response.responseJSON.error, 'danger', null, 'prepend', 'col-sm-8'); 35387 35388 next.buttonLoading('reset'); 35389 }) 35390 ; 35391 } 35392 }); 35393 } 35394 35395 $('#update-settings-phone').click(function(e) { 35396 e.preventDefault(); 35397 35398 var button = $(this); 35399 35400 button.button('loading'); 35401 35402 window.checkAccess('profile_phone', 'update', 35403 function() { 35404 window.location.href = '/user/profile/phone'; 35405 }, 35406 function() { 35407 button.buttonLoading('reset'); 35408 } 35409 ) 35410 }); 35411 }); 35412})(jQuery); 35413;(function($) { 35414 35415 var urls = { 35416 'popin': '/security/popin', 35417 'sendCode': '/security/send-code',
35418 'verifyCode': '/security/verify-code' 35419 }; 35420 35421 var getDataValue = function(el, state, name) { 35422 return el.attr('data-' + state + '-' + name); 35423 }; 35424 35425 var getTokens = function(el, state) { 35426 var 35427 csrfConfig = Storage.getData('csrf_config'), 35428 data = {} 35429 ; 35430 35431 data[csrfConfig['token_name_key']] = getDataValue(el, state, 'token-name'); 35432 data[csrfConfig['token_key']] = getDataValue(el, state, 'token'); 35433 35434 return data; 35435 }; 35436 35437 var changeState = function(el, state) { 35438 el.button(state); 35439 el.attr('class', getDataValue(el, state, 'class')); 35440 el.attr('data-state', state); 35441 }; 35442 35443 window.verifySession = function() { 35444 $.get(urls.popin) 35445 .done(function(data) { 35446 $.fancybox.open({ 35447 content: data.html, 35448 padding: 0, 35449 type: 'iframe', 35450 afterShow: function () { 35451 $('#form-verify-session button').click(function (e) { 35452 e.preventDefault(); 35453 35454 var 35455 next = $(this), 35456 state = next.attr('data-state') 35457 ; 35458 35459 if ('send' === state) { 35460 next.buttonLoading('loading'); 35461 35462 $.post(urls.sendCode, getTokens(next, state)) 35463 .done(function () { 35464 35465 $('#form-verify-session .alert').remove(); 35466 $('#form-verify-session-code').removeClass('hidden'); 35467 35468 changeState(next, 'verify'); 35469 }) 35470 .fail(function (response) { 35471 if (403 === response.status) { 35472 window.location.href = '/user/login'; 35473 } 35474 35475 $('#form-verify-session .alert').remove(); 35476 $('#form-verify-session-code').showAlert(response.responseJSON.error, 'danger', null, 'before', '', false); 35477 35478 next.buttonLoading('reset'); 35479 }) 35480 ; 35481 } 35482 35483 if ('verify' === state) { 35484 next.buttonLoading('loading'); 35485 35486 var data = getTokens(next, state); 35487 35488 data['code'] = $('#verification-code').val(); 35489 35490 $.post(urls.verifyCode, data) 35491 .done(function () { 35492 // need to improve in future 35493 $('#update-settings-phone').removeClass('hidden'); 35494 35495 $.fancybox.close(); 35496 }) 35497 .fail(function (response) { 35498 if (403 === response.status) { 35499 window.location.href = '/user/login'; 35500 } 35501 35502 $('#form-verify-session .alert').remove(); 35503 $('#form-verify-session-code').showAlert(response.responseJSON.error, 'danger', null, 'prepend', '', false); 35504 35505 next.buttonLoading('reset'); 35506 }) 35507 ; 35508 } 35509 }); 35510 } 35511 }); 35512 }) 35513 .fail(function() {}) 35514 ; 35515 }; 35516 35517 window.checkAccess = function(context, action, onSuccess, onFail) { 35518 var 35519 data = { 35520 context: context, 35521 action: action 35522 } 35523 ; 35524 35525 $.post('/security/access', data) 35526 .done(function () { 35527 if (undefined !== onSuccess) { 35528 onSuccess(); 35529 } 35530 }) 35531 .fail(function (response) { 35532 if (undefined !== onFail) { 35533 onFail(); 35534 } 35535 35536 if (403 === response.status) { 35537 window.verifySession(); 35538 35539 return false; 35540 } 35541 35542 if (undefined !== response.responseJSON.redirect) { 35543 window.location.href = redirect; 35544 35545 return false; 35546 } 35547 }) 35548 ; 35549 } 35550})(jQuery); 35551;(function($) { 35552 var updateProfile = function (button, popin, data, onSuccess, state) { 35553 var csrfConfig = Storage.getData('csrf_config'); 35554 button.buttonLoading('loading'); 35555 35556 data[csrfConfig['token_name_key']] = popin.attr('data-csrf-name'); 35557 data[csrfConfig['token_key']] = popin.attr('data-csrf-token'); 35558 35559 $.post('/admin/user-profile/{0}'.format(popin.attr('data-user-id')), data) 35560 .done(function() { 35561 popin.find('.alert-danger').addClass('hidden'); 35562 onSuccess(); 35563 }) 35564 .fail(function (response) { 35565 if (403 === response.status) { 35566 window.location.href = '/admin/login'; 35567 35568 return false;
35569 } 35570 var 35571 message = undefined === response.responseJSON.error ? 'Undefined error' : response.responseJSON.error, 35572 error = popin.find('.alert-danger'); 35573 35574 error.removeClass('hidden'); 35575 error.text(message); 35576 }) 35577 .always(function (data, textStatus, jqXHR) { 35578 button.buttonLoading('reset'); 35579 35580 if (undefined !== state && 'success' === textStatus) { 35581 button.button(state) 35582 } 35583 }) 35584 ; 35585 }; 35586 35587 var showUserPopin = function (data) { 35588 $.fancybox.open({ 35589 content: data.popin, 35590 padding: 0, 35591 type: 'iframe', 35592 afterShow: function () { 35593 35594 var userIsActive = $('#userStatusToggle').is(':checked'); 35595 $('#userStatusLabel').css('color', userIsActive ? '#5cb85c' : '#d9534f'); 35596 $('#userStatusToggle').on('change', function() { 35597 var userIsActive = $(this).is(':checked'); 35598 var label = $('#userStatusLabel'); 35599 if (userIsActive) { 35600 label.text('פע××').css('color', '#5cb85c'); 35601 } else { 35602 label.text('×× ×¤×¢××').css('color', '#d9534f'); 35603 } 35604 35605 }); 35606 35607 $('#admin-user-popin button.close-window').click(function() { 35608 $.fancybox.close(); 35609 }); 35610 35611 $('#admin-user-popin .admin-disable-tfa-button').click(function(e) { 35612 e.preventDefault(); 35613 35614 var 35615 popin = $('#admin-user-popin'), 35616 button = $(this) 35617 ; 35618 35619 updateProfile(button, popin, {'tfa': false}, function () { 35620 popin.find('.admin-disable-tfa-disabled-text').removeClass('hidden'); 35621 popin.find('.admin-disable-tfa-enabled-text').addClass('hidden'); 35622 popin.find('.admin-tfa-reminder-button').removeClass('hidden'); 35623 popin.find('.admin-tfa-reminder-text').addClass('hidden'); 35624 button.parent().remove(); 35625 }); 35626 }); 35627 35628 $('#admin-user-popin .admin-tfa-reminder-button').click(function (e) { 35629 e.preventDefault(); 35630 35631 var 35632 button = $(this), 35633 popin = $('#admin-user-popin'), 35634 state = 'enabled' === button.attr('data-state') ? 'disabled' : 'enabled', 35635 enabled = 'enabled' === state 35636 ; 35637 35638 updateProfile(button, popin, {'tfaReminder': enabled}, function () { 35639 button.attr('data-state', state); 35640 }, state); 35641 }); 35642 35643 $('#admin-user-popin .admin-verify-phone-button').click(function (e) { 35644 var 35645 button = $(this), 35646 popin = $('#admin-user-popin'), 35647 phone = { code: button.attr('data-phone-code'), number: button.attr('data-phone-number') } 35648 ; 35649 35650 updateProfile(button, popin, {phone: phone}, function () { 35651 button.remove(); 35652 popin.find('.admin-verify-phone-text').removeClass('hidden'); 35653 }); 35654 }); 35655 35656 $('#admin-user-form-submit').click(function (e) { 35657 e.preventDefault(); 35658 35659 $(this).button('loading'); 35660 35661 var 35662 button = $(this), 35663 popin = $('#admin-user-popin'), 35664 email = $('#admin-user-email-address-input').val(), 35665 userStatus = $('#userStatusToggle').is(':checked') ? 1 : 0, 35666 errors = '', 35667 re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ 35668 ; 35669 35670 if (!re.test(email) || email === '') { 35671 errors += $.translate('Email is invalid') + '\n'; 35672 } 35673 35674 if (errors !== '') { 35675 $('#admin-user-form-errors').html(nl2br(errors, true)).removeClass('hidden'); 35676 $('#admin-user-form-submit').button('reset'); 35677 35678 return false; 35679 } else { 35680 $('#update-settings-errors').addClass('hidden'); 35681 $('#admin-user-form-errors').html(''); 35682 35683 updateProfile(button, popin, {'email': email, 'userStatus': userStatus, }, function () { 35684 $('#admin-user-form-submit').button('reset'); 35685 $.fancybox.close(); 35686 }); 35687 } 35688 }); 35689 } 35690 }); 35691 }; 35692 35693 $(document).ready(function() { 35694 $('.admin-user-settings-popin').click(function (e) { 35695 35696 e.preventDefault(); 35697 35698 var button = $(this); 35699 35700 button.buttonLoading('loading'); 35701 35702 $.get('/admin/user/{0}'.format(button.attr('data-user-id'))) 35703 .done(function (response) { 35704 showUserPopin(response) 35705 }) 35706 .fail(function (response) { 35707 if (403 === response.status) { 35708 window.location.href = '/admin/login'; 35709 } 35710 }) 35711 .always(function () { 35712 button.buttonLoading('reset') 35713 }) 35714 ; 35715 }); 35716 }); 35717})(jQuery); 35718 35719//var cur_domain = ''; 35720jQuery(document).ready(function ($) { 35721 35722 $(window).scroll(function(){ 35723 if ($(window).scrollTop() >= 100) { 35724 $('#Header').addClass('fixed-header'); 35725 // $('#topHeader,#bottomHeader').addClass('fixed-header'); 35726 // $('#bottomHeader').addClass('fixed-header1'); 35727 // $('#Header').css('height',119); 35728 $('#h-helper').css('height',119); 35729 } 35730 else { 35731 $('#Header').removeClass('fixed-header'); 35732 // $('#bottomHeader').removeClass('fixed-header1'); 35733 // $('#Header').css('height','unset'); 35734 $('#h-helper').css('height',0); 35735 } 35736 }); 35737 35738 $(".boxNavButton").click(function () { 35739 $(window).width() < 768 35740 ? $(this).hasClass("activeSideBar") 35741 ? $(this).removeClass("activeSideBar").closest("header").find("#mobileSideBar").css({ right: "100%", left: "-100%" }) 35742 : $(this).addClass("activeSideBar").closest("header").find("#mobileSideBar").css({ left
35742: "0px",right : "0" }) 35743 : $(this).hasClass("activeSideBar") 35744 ? $(this).removeClass("activeSideBar").closest("header").find("#mobileSideBar").css({ right: "100%", left: "-100%" }) 35745 : $(this) 35746 .addClass("activeSideBar") 35747 .closest("header") 35748 .find("#mobileSideBar") 35749 .css({ left: ($(window).width() - 768) / 2, right: ($(window).width() - 768) / 2 }); 35750 }) 35751 var pos = ''; 35752 var tr; 35753 $(document).on('click', '#addDnsRow button', function(e){ 35754 e.preventDefault(); 35755 pos = ''; 35756 $('#' + $(this).attr('data-target')).modal('show').find('.alert').addClass('hidden'); 35757 }); 35758 $(document).on('click', '#settings, #contacts, #invoices, #mDomains', function(e){ 35759 $([document.documentElement, document.body]).animate({ 35760 scrollTop: $("#settings").offset().top+45 35761 }, 2000); 35762 }); 35763 35764 $(document).on('click','a.editZoneEntry',function(e){ 35765 e.preventDefault(); 35766 pos = ''; 35767 tr = $(this).closest('tr'); 35768 35769 var updateCsrfToken = function (form, response) { 35770 form.find('[name=csrf_token]').val(response['csrf_token']); 35771 form.find('[name=csrf_token_name]').val(response['csrf_token_name']); 35772 }; 35773 35774 tr.find('select').each(function(){ 35775 var name_attr = $(this).attr('name'); 35776 if (name_attr.indexOf('type')>0) 35777 { 35778 var sel = $(this).val(); 35779 var uid = $(this).closest('form').attr('data-uid'); 35780 var url = Storage.getData('app_url') + 'domain/manageEditDomain/' + uid; 35781 var res = name_attr.match(/[0-9]+/gi); 35782 var zone = res[0]; 35783 var ttlSelect = $('.modal-dns-edit-record').find('select'); 35784 pos = parseInt(zone); 35785 35786 var target = tr.find('input[name$="[record]"]').val(); 35787 var domain = tr.find('input[name$="[name]"]').val(); 35788 var ttl = tr.find('select[name^="zone["][name$="[ttl]"]').val(); 35789 var sub = domain.replace(cur_d, '').replace(/\.+$/, ""); 35790 35791 var priority = tr.find('input[name^="priority["]').val(); 35792 35793 if(typeof undefined !== typeof ttl && ttlSelect.length > 0) { 35794 ttlSelect.val(ttl); 35795 } 35796 35797 if(sel === "HTTPRED"){ 35798 var redType = tr.find('input[name$="[status]"]').val(); 35799 35800 $('#editDnsRowREDModal').modal('show').find('.alert').addClass('hidden'); 35801 $('#editDnsRowREDModal').find('input[name=recordRED]').val(target); 35802 35803 if(redType == '301') 35804 { 35805 $('#typered3').prop( "checked", true ); 35806 $('#typered4').prop( "checked", false ); 35807 35808 $('#editDnsRowREDModal').find('input[id=typered3]').prop( "checked", true ); 35809 $('#editDnsRowREDModal').find('input[id=typered4]').prop( "checked", false ); 35810 } 35811 else 35812 { 35813 $('#typered3').prop( "checked", false ); 35814 $('#typered4').prop( "checked", true ); 35815 35816 $('#editDnsRowREDModal').find('input[id=typered3]').prop( "checked", false ); 35817 $('#editDnsRowREDModal').find('input[id=typered4]').prop( "checked", true ); 35818 } 35819 return; 35820 } 35821 35822 if(sel === "CNAME") 35823 { 35824 $('#editDnsRowCNAMEModal').modal('show').find('.alert').addClass('hidden'); 35825 $('#editDnsRowCNAMEModal').find('input[name=hostnameCNAME]').val(sub); 35826 $('#editDnsRowCNAMEModal').find('input[name=recordCNAME]').val(target); 35827 35828 $('#editDnsRowCNAMEModal').find('.select2').val(ttl); 35829 35830 return; 35831 } 35832 35833 if(sel === "TXT") 35834 { 35835 $('#editDnsRowTXTModal').modal('show').find('.alert').addClass('hidden'); 35836 $('#editDnsRowTXTModal').find('input[name=hostnameTXT]').val(sub); 35837 $('#editDnsRowTXTModal').find('input[name=recordTXT]').val(target); 35838 35839 $('#editDnsRowTXTModal').find('.select2').val(ttl); 35840 35841 return; 35842 } 35843 35844 if(sel === "A") 35845 { 35846 $('#editDnsRowAModal').modal('show').find('.alert').addClass('hidden'); 35847 $('#editDnsRowAModal').find('input[name=hostnameA]').val(sub); 35848 $('#editDnsRowAModal').find('input[name=recordA]').val(target); 35849 35850 $('#editDnsRowAModal').find('.select2').val(ttl); 35851 35852 return; 35853 } 35854 35855 if(sel === "AAAA") 35856 { 35857 $('#editDnsRowAAAAModal').modal('show').find('.alert').addClass('hidden'); 35858 $('#editDnsRowAAAAModal').find('input[name=hostnameAAAA]').val(sub); 35859 $('#editDnsRowAAAAModal').find('input[name=recordAAAA]').val(target); 35860 35861 $('#editDnsRowAAAAModal').find('.select2').val(ttl); 35862 35863 return; 35864 } 35865 35866 if(sel === "MX") 35867 { 35868 $('#editDnsRowMXModal').modal('show').find('.alert').addClass('hidden'); 35869 $('#editDnsRowMXModal').find('input[name=hostMX]').val(sub); 35870 $('#editDnsRowMXModal').find('input[name=hostnameMX]').val(target); 35871 $('#editDnsRowMXModal').find('input[name=recordMX]').val(priority); 35872 35873 $('#editDnsRowMXModal').find('.select2').val(ttl); 35874 35875 return; 35876 } 35877 35878 if(sel === "SRV") 35879 { 35880 $('#editDnsRowSRVModal').modal('show').find('.alert').addClass('hidden'); 35881 35882 var spl = domain.split('.'); 35883 35884 $('#editDnsRowSRVModal').find('input[name=serviceSRV]').val(spl[0]); 35885 $('#editDnsRowSRVModal').find('input[name=hostnameSRV]').val(spl[1]); 35886 $('#editDnsRowSRVModal').find('input[name=recordSRV]').val(priority); 35887 35888 var prt = target.split(' '); 35889 $('#editDnsRowSRVModal').find('input[name=weightSRV]').val(prt[0]); 35890 $('#editDnsRowSRVModal').find('input[name=portSRV]').val(prt[1]); 35891 $('#editDnsRowSRVModal').find('input[name=targetSRV]').val(prt[2]); 35892 35893 $('#editDnsRowSRVModal').find('.select2').val(ttl) 35894 35895 return; 35896 } 35897 } 35898 35899 }); 35900 35901 //$('#editDnsRowAModal').modal('show').find('.alert').addClass('hidden'); 35902 }); 35903 35904 // todo@alexbuturlakin: this hardcode need to be refactored 35905 //create new / edit 35906 $(document).on('click', '.modalDns .btn-primary', function(e){ 35907 35908 e.preventDefault(); 35909 var window = $(this).closest('div.modalDns'); 35910 var type = $('.modalDns.in').attr('data-type'); 35911 var ttl = $('.modalDns.in [name=ttl]').val(); 35912 35913 var 35914 csrfConfig = Storage.getData('csrf_config'), 35915 tokenKey = csrfConfig['token_key'], 35916 tokenNameKey = csrfConfig['token_name_key'], 35917 csrfToken = $('.modalDns.in').find('[name=csrf_token]').val(), 35918 csrfTokenName = $('.modalDns.in').find('[name=csrf_token_name]').val() 35919 ; 35920 35921 var addCSRFToDNSData = function (updatednsdata) { 35922 if (null === updatednsdata) { 35923 return updatednsdata; 35924 } 35925 35926 if ('object' === typeof updatednsdata) { 35927 updatednsdata[tokenKey] = csrfToken; 35928 updatednsdata[tokenNameKey] = csrfTokenName; 35929 35930 return updatednsdata; 35931 } 35932 35933 updatednsdata += '&'+tokenKey+'='+csrfToken+'&'+tokenNameKey+'='+csrfTokenName; 35934 35935 return updatednsdata; 35936 }; 35937 35938 var clearDNSModal = function () { 35939 $('.modalDns.in input:not([type=hidden])').val(''); 35940 }; 35941 35942 k++; 35943 switch(type){ 35944 case 'A': 35945 var ct = true; 35946 var errors = ''; 35947 $('.modalDns.in input.form-control').each(function () { 35948 if($(this).attr('name') != 'hostnameA') { 35949 if (!ctype_print($(this).val())) { 35950 ct = false;
35951 } 35952 if ($(this).val() == '') { 35953 ct = false; 35954 } 35955 } 35956 }); 35957 if (!ct) { 35958 errors += $.translate('English Only') + '\n'; 35959 } 35960 35961 if(!isValidIPv4( $('.modalDns.in [name=recordA]').val() )){ 35962 errors += $.translate('Not Valid IPV4') + '\n'; 35963 } 35964 if(!isValidSubdomain( $('.modalDns.in [name=hostnameA]').val() )){ 35965 errors += $.translate('Not Valid HostName') + '\n'; 35966 } 35967 35968 if((errors !== '')){ 35969 $('.modalDns.in .alert').html(nl2br(errors)).removeClass('hidden'); 35970 return; 35971 }else{ 35972 $('.modalDns.in .alert').addClass('hidden'); 35973 var sub = $('.modalDns.in [name=hostnameA]').val(); 35974 var dom = sub + '.' + cur_d + '.'; 35975 if(sub == '' || ('string' === typeof sub && '@' == sub.trim())){ 35976 dom = cur_d + '.'; 35977 } 35978 35979 var updatednsdata = ''; 35980 if(pos === '') { 35981 $('#updatezone .table tbody tr').eq($('#updatezone .table tbody tr').length - 1).before('\ 35982 <tr class="row-a">\ 35983 <td>\ 35984 <input readonly disabled type="text" value="'+dom+'" name="zone[' + k + '][name]">\ 35985 </td>\ 35986 <td>\ 35987 <select readonly disabled name="zone['+k+'][ttl]">\ 35988 <option value="3600">3600</option>\ 35989 <option value="' + ttl + '" selected="selected">' + ttl + '</option>\ 35990 </select>\ 35991 </td>\ 35992 <td>\ 35993 <select readonly disabled name="zone['+k+'][type]">\ 35994 <option value="NS" class="hidden">NS</option>\ 35995 <option value="A" selected="selected">A</option>\ 35996 <option value="AAAA">AAAA</option>\ 35997 <option value="MX">MX</option>\ 35998 <option value="SRV">SRV</option>\ 35999 <option value="TXT">TXT</option>\ 36000 <option value="CNAME">CNAME</option>\ 36001 <option value="HTTPRED">HTTPRED</option>\ 36002 </select>\ 36003 </td>\ 36004 <td>\ 36005 <input readonly disabled type="text" value="'+ $('.modalDns.in [name=recordA]').val() +'" name="zone['+k+'][record]">\ 36006 </td>\ 36007 <td>\ 36008 <a class="delZoneEntry" href="#del" title="××××§×">\ 36009 <span class="glyphicon glyphicon-trash"></span></a>\ 36010 <a class="editZoneEntry" href="#edit" title="××××§×">\ 36011 <span class="glyphicon glyphicon-edit"></span></a>\ 36012 </td>\ 36013 <tr>\ 36014 '); 36015 updatednsdata = 'zone[name]='+dom+'&zone[record]='+ $('.modalDns.in [name=recordA]').val()+'&zone[ttl]=' + ttl + '&zone[type]=A'; 36016 } else { 36017 $("input[name='zone\\["+pos+"\\]\\[record\\]']").val($('.modalDns.in [name=recordA]').val()); 36018 $("input[name='zone\\["+pos+"\\]\\[name\\]']").val(dom); 36019 if(typeof undefined !== typeof ttl) { 36020 $("select[name='zone\\["+pos+"\\]\\[ttl\\]']").val(ttl); 36021 } 36022 updatednsdata = 'zone[name]='+dom+'&zone[record]='+ $('.modalDns.in [name=recordA]').val()+'&zone[ttl]=' + ttl + '&zone[type]=A'; 36023 } 36024 clearDNSModal(); 36025 //ALIN: 36026 var id = window.attr('id'); 36027 36028 updatednsdata = addCSRFToDNSData(updatednsdata); 36029 36030 if (id.indexOf('addDns') >=0) 36031 { 36032 $.post(Storage.getData('app_url') + 'domain/new-record/' + $('#updatezone').attr('data-uid'), updatednsdata, function(r){ 36033 /* r = JSON.parse(r); 36034 if(r.status == 0){ 36035 $('#zone-error').html(r.msg).removeClass('hidden'); 36036 } 36037 if(r.status == 1){ 36038 $.fancybox.close(); 36039 $('#domainflash').html(r.msg).removeClass('hidden'); 36040 }*/ 36041 $('#save-zone').button('reset'); 36042 }); 36043 } 36044 else 36045 { 36046 $('#save-zone').button('reset'); 36047 } 36048 //:ALIN 36049 $('.modalDns.in').modal('hide'); 36050 } 36051 break; 36052 case 'AAAA': 36053 var ct = true; 36054 var errors = ''; 36055 $('.modalDns.in input.form-control').each(function () { 36056 if($(this).attr('name') != 'hostnameAAAA') { 36057 if (!ctype_print($(this).val())) { 36058 ct = false;
36059 } 36060 if ($(this).val() == '') { 36061 ct = false; 36062 } 36063 } 36064 }); 36065 if (!ct) { 36066 errors += $.translate('English Only') + '\n'; 36067 } 36068 36069 if(!isValidIPv6( $('.modalDns.in [name=recordAAAA]').val() )){ 36070 errors += $.translate('Not Valid IPV4') + '\n'; 36071 } 36072 if(!isValidSubdomain( $('.modalDns.in [name=hostnameAAAA]').val() )){ 36073 errors += $.translate('Not Valid HostName') + '\n'; 36074 } 36075 36076 if((errors !== '')){ 36077 $('.modalDns.in .alert').html(nl2br(errors)).removeClass('hidden'); 36078 return; 36079 }else{ 36080 $('.modalDns.in .alert').addClass('hidden'); 36081 var sub = $('.modalDns.in [name=hostnameAAAA]').val(); 36082 var dom = sub + '.' + cur_d + '.'; 36083 if(sub == '' || ('string' === typeof sub && '@' == sub.trim())){ 36084 dom = cur_d + '.'; 36085 } 36086 36087 var updatednsdata = ''; 36088 if(pos === '') { 36089 $('#updatezone .table tbody tr').eq($('#updatezone .table tbody tr').length - 1).before('\ 36090 <tr class="row-aaaa">\ 36091 <td>\ 36092 <input readonly disabled type="text" value="'+dom+'" name="zone[' + k + '][name]">\ 36093 </td>\ 36094 <td>\ 36095 <select readonly disabled name="zone['+k+'][ttl]">\ 36096 <option value="3600">3600</option>\ 36097 <option value="' + ttl + '" selected="selected">' + ttl + '</option>\ 36098 </select>\ 36099 </td>\ 36100 <td>\ 36101 <select readonly disabled name="zone['+k+'][type]">\ 36102 <option value="NS" class="hidden">NS</option>\ 36103 <option value="A">A</option>\ 36104 <option value="AAAA" selected="selected">AAAA</option>\ 36105 <option value="MX">MX</option>\ 36106 <option value="SRV">SRV</option>\ 36107 <option value="TXT">TXT</option>\ 36108 <option value="CNAME">CNAME</option>\ 36109 <option value="HTTPRED">HTTPRED</option>\ 36110 </select>\ 36111 </td>\ 36112 <td>\ 36113 <input readonly disabled type="text" value="'+ $('.modalDns.in [name=recordAAAA]').val() +'" name="zone['+k+'][record]">\ 36114 </td>\ 36115 <td>\ 36116 <a class="delZoneEntry" href="#del" title="××××§×">\ 36117 <span class="glyphicon glyphicon-trash"></span></a>\ 36118 <a class="editZoneEntry" href="#edit" title="××××§×">\ 36119 <span class="glyphicon glyphicon-edit"></span></a>\ 36120 </td>\ 36121 <tr>\ 36122 '); 36123 updatednsdata = 'zone[name]='+dom+'&zone[record]='+ $('.modalDns.in [name=recordAAAA]').val()+'&zone[ttl]=' + ttl + '&zone[type]=AAAA'; 36124 } else { 36125 $("input[name='zone\\["+pos+"\\]\\[record\\]']").val($('.modalDns.in [name=recordAAAA]').val()); 36126 $("input[name='zone\\["+pos+"\\]\\[name\\]']").val(dom); 36127 if(typeof undefined !== typeof ttl) { 36128 $("select[name='zone\\["+pos+"\\]\\[ttl\\]']").val(ttl); 36129 } 36130 updatednsdata = 'zone[name]='+dom+'&zone[record]='+ $('.modalDns.in [name=recordAAAA]').val()+'&zone[ttl]=' + ttl + '&zone[type]=AAAA'; 36131 } 36132 clearDNSModal(); 36133 //ALIN: 36134 var id = window.attr('id'); 36135 36136 updatednsdata = addCSRFToDNSData(updatednsdata); 36137 36138 if (id.indexOf('addDns') >=0) 36139 { 36140 $.post(Storage.getData('app_url') + 'domain/new-record/' + $('#updatezone').attr('data-uid'), updatednsdata, function(r){ 36141 /* r = JSON.parse(r); 36142 if(r.status == 0){ 36143 $('#zone-error').html(r.msg).removeClass('hidden'); 36144 } 36145 if(r.status == 1){ 36146 $.fancybox.close(); 36147 $('#domainflash').html(r.msg).removeClass('hidden'); 36148 }*/ 36149 $('#save-zone').button('reset'); 36150 }); 36151 } 36152 else 36153 { 36154 $('#save-zone').button('reset'); 36155 } 36156 //:ALIN 36157 $('.modalDns.in').modal('hide'); 36158 } 36159 break; 36160 case 'CNAME': 36161 var ct = true; 36162 var errors = ''; 36163 $('.modalDns.in input.form-control').each(function () { 36164 if($(this).attr('name') != 'hostnameCNAME') { 36165 36166 if (!ctype_print($(this).val())) { 36167 ct = false;
36168 } 36169 if ($(this).val() == '') { 36170 ct = false; 36171 } 36172 } 36173 }); 36174 if (!ct) { 36175 errors += $.translate('English Only') + '\n'; 36176 } 36177 if($('.modalDns.in [name=hostnameCNAME]').val().length === 0){ 36178 errors += $.translate('Cannot config CNAME for primary host') + '\n'; 36179 } 36180 36181 if (!isValidSubdomain($('.modalDns.in [name=hostnameCNAME]').val(), true)) { 36182 errors += $.translate('Not Valid HostName') + '\n'; 36183 } 36184 if (!isValidFullDomain($('.modalDns.in [name=recordCNAME]').val(), true)) { 36185 errors += $.translate('Not Valid HostName Target') + '\n'; 36186 } 36187 36188 if((errors !== '')){ 36189 $('.modalDns.in .alert').html(nl2br(errors)).removeClass('hidden'); 36190 return; 36191 }else{ 36192 $('.modalDns.in .alert').addClass('hidden'); 36193 var sub = $('.modalDns.in [name=hostnameCNAME]').val(); 36194 var dom = sub + '.' + cur_d + '.'; 36195 if(sub == '' || ('string' === typeof sub && '@' == sub.trim())){ 36196 dom = cur_d + '.'; 36197 } 36198 var updatednsdata = ''; 36199 if(pos === ''){ 36200 $('#updatezone .table tbody tr').eq($('#updatezone .table tbody tr').length - 1).before('\ 36201 <tr class="row-cname">\ 36202 <td>\ 36203 <input readonly disabled type="text" value="' + dom + '" name="zone[' + k + '][name]">\ 36204 </td>\ 36205 <td>\ 36206 <select readonly disabled name="zone['+k+'][ttl]">\ 36207 <option value="3600">3600</option>\ 36208 <option value="' + ttl + '" selected="selected">' + ttl + '</option>\ 36209 </select>\ 36210 </td>\ 36211 <td>\ 36212 <select readonly disabled name="zone['+k+'][type]">\ 36213 <option value="NS" class="hidden">NS</option>\ 36214 <option value="A">A</option>\ 36215 <option value="AAAA">AAAA</option>\ 36216 <option value="MX">MX</option>\ 36217 <option value="SRV">SRV</option>\ 36218 <option value="TXT">TXT</option>\ 36219 <option value="CNAME" selected="selected">CNAME</option>\ 36220 <option value="HTTPRED">HTTPRED</option>\ 36221 </select>\ 36222 </td>\ 36223 <td>\ 36224 <input readonly disabled type="text" value="'+ $('.modalDns.in [name=recordCNAME]').val() +'" name="zone['+k+'][record]">\ 36225 </td>\ 36226 <td>\ 36227 <a class="delZoneEntry" href="#del" title="××××§×">\ 36228 <span class="glyphicon glyphicon-trash"></span></a>\ 36229 <a class="editZoneEntry" href="#edit" title="××××§×">\ 36230 <span class="glyphicon glyphicon-edit"></span></a>\ 36231 </td>\ 36232 <tr>\ 36233 '); 36234 36235 } else { 36236 $("input[name='zone\\["+pos+"\\]\\[record\\]']").val($('.modalDns.in [name=recordCNAME]').val()); 36237 $("input[name='zone\\["+pos+"\\]\\[name\\]']").val(dom); 36238 if(typeof undefined !== typeof ttl) { 36239 $("select[name='zone\\["+pos+"\\]\\[ttl\\]']").val(ttl); 36240 } 36241 } 36242 updatednsdata = 'zone[name]='+dom+'&zone[record]='+ $('.modalDns.in [name=recordCNAME]').val()+'&zone[ttl]=' + ttl + '&zone[type]=CNAME'; 36243 var id = window.attr('id'); 36244 36245 updatednsdata = addCSRFToDNSData(updatednsdata); 36246 36247 if (id.indexOf('addDns') >=0) 36248 { 36249 $.post(Storage.getData('app_url') + 'domain/new-record/' + $('#updatezone').attr('data-uid'), updatednsdata, function(r){ 36250 /* r = JSON.parse(r); 36251 if(r.status == 0){ 36252 $('#zone-error').html(r.msg).removeClass('hidden'); 36253 } 36254 if(r.status == 1){ 36255 $.fancybox.close(); 36256 $('#domainflash').html(r.msg).removeClass('hidden'); 36257 }*/ 36258 $('#save-zone').button('reset'); 36259 }); 36260 } 36261 else { 36262 $('#save-zone').button('reset'); 36263 } 36264 //:ALIN 36265 clearDNSModal(); 36266 36267 $('.modalDns.in').modal('hide'); 36268 } 36269 break; 36270 case 'TXT': 36271 var ct = true; 36272 var errors = ''; 36273 // if(pos === ''){ 36274 $('.modalDns.in input.form-control').each(function () { 36275 if($(this).attr('name') != 'hostnameTXT') { 36276 if (!ctype_print($(this).val())) { 36277 ct = false;
36278 } 36279 if ($(this).val() == '') { 36280 ct = false; 36281 } 36282 } 36283 }); 36284 if (!ct) { 36285 errors += $.translate('English Only') + '\n'; 36286 } 36287 if (!isValidSubdomain($('.modalDns.in [name=hostnameTXT]').val(), true)) { 36288 errors += $.translate('Not Valid HostName') + '\n'; 36289 } 36290 if((errors !== '')){ 36291 $('.modalDns.in .alert').html(nl2br(errors)).removeClass('hidden'); 36292 return; 36293 } else { 36294 $('.modalDns.in .alert').addClass('hidden'); 36295 var sub = $('.modalDns.in [name=hostnameTXT]').val(); 36296 var dom = sub + '.' + cur_d + '.'; 36297 36298 if(sub == '' || ('string' === typeof sub && '@' == sub.trim())){ 36299 dom = cur_d + '.'; 36300 } 36301 36302 var updatednsdata = ''; 36303 36304 if(pos === ''){ 36305 $('#updatezone .table tbody tr').eq($('#updatezone .table tbody tr').length - 1).before('\ 36306 <tr class="row-txt">\ 36307 <td>\ 36308 <input readonly disabled type="text" value="' + dom + '" name="zone[' + k + '][name]">\ 36309 </td>\ 36310 <td>\ 36311 <select readonly disabled name="zone['+k+'][ttl]">\ 36312 <option value="3600">3600</option>\ 36313 <option value="' + ttl + '" selected="selected">' + ttl + '</option>\ 36314 </select>\ 36315 </td>\ 36316 <td>\ 36317 <select readonly disabled name="zone['+k+'][type]">\ 36318 <option value="NS" class="hidden">NS</option>\ 36319 <option value="A">A</option>\ 36320 <option value="AAAA">AAAA</option>\ 36321 <option value="MX">MX</option>\ 36322 <option value="SRV">SRV</option>\ 36323 <option value="TXT" selected="selected">TXT</option>\ 36324 <option value="CNAME">CNAME</option>\ 36325 <option value="HTTPRED">HTTPRED</option>\ 36326 </select>\ 36327 </td>\ 36328 <td>\ 36329 <input readonly disabled type="text" value="'+ $('.modalDns.in [name=recordTXT]').val() +'" name="zone['+k+'][record]">\ 36330 </td>\ 36331 <td>\ 36332 <a class="delZoneEntry" href="#del" title="××××§×">\ 36333 <span class="glyphicon glyphicon-trash"></span></a>\ 36334 <a class="editZoneEntry" href="#edit" title="××××§×">\ 36335 <span class="glyphicon glyphicon-edit"></span></a>\ 36336 </td>\ 36337 <tr>\ 36338 '); 36339 } else { 36340 $("input[name='zone\\["+pos+"\\]\\[record\\]']").val($('.modalDns.in [name=recordTXT]').val()); 36341 $("input[name='zone\\["+pos+"\\]\\[name\\]']").val(dom); 36342 if(typeof undefined !== typeof ttl) { 36343 $("select[name='zone\\["+pos+"\\]\\[ttl\\]']").val(ttl); 36344 } 36345 } 36346 36347 updatednsdata = { 36348 zone: { 36349 name_entered: sub, 36350 name: dom, 36351 record: $('.modalDns.in [name=recordTXT]').val(), 36352 ttl: ttl, 36353 type: 'TXT' 36354 } 36355 }; 36356 36357 var id = window.attr('id'); 36358 updatednsdata = addCSRFToDNSData(updatednsdata); 36359 36360 if (id.indexOf('addDns') >=0) 36361 { 36362 $.post(Storage.getData('app_url') + 'domain/new-record/' + $('#updatezone').attr('data-uid'), updatednsdata, function(r){ 36363 /* r = JSON.parse(r); 36364 if(r.status == 0){ 36365 $('#zone-error').html(r.msg).removeClass('hidden'); 36366 } 36367 if(r.status == 1){ 36368 $.fancybox.close(); 36369 $('#domainflash').html(r.msg).removeClass('hidden'); 36370 }*/ 36371 $('#save-zone').button('reset'); 36372 }); 36373 } 36374 else 36375 { 36376 $('#save-zone').button('reset'); 36377 } 36378 //:ALIN 36379 clearDNSModal(); 36380 $('.modalDns.in').modal('hide'); 36381 } 36382 break; 36383 case 'MX': 36384 var ct = true; 36385 var errors = ''; 36386 $('.modalDns.in input.form-control').each(function () { 36387 if($(this).attr('name') != 'hostMX') { 36388 if (!ctype_print($(this).val())) { 36389 ct = false;
36390 }; 36391 if($(this).val() == ''){ 36392 ct = false; 36393 } 36394 } 36395 }); 36396 if (!ct) { 36397 errors += $.translate('English Only') + '\n'; 36398 } 36399 if (!isValidFullDomain($('.modalDns.in [name=hostnameMX]').val())) { 36400 errors += $.translate('Not Valid HostName Target') + '\n'; 36401 } 36402 36403 var priority = $('.modalDns.in [name=recordMX]').val(); 36404 if(isNaN(priority) || parseInt(priority) < 0 || parseInt(priority) > 65535){ 36405 errors += $.translate('Priority must be between 0 and 65535') + '\n'; 36406 } 36407 36408 if((errors !== '')){ 36409 $('.modalDns.in .alert').html(nl2br(errors)).removeClass('hidden'); 36410 return; 36411 }else{ 36412 $('.modalDns.in .alert').addClass('hidden'); 36413 var sub = $('.modalDns.in [name=hostMX]').val(); 36414 var dom = sub + '.' + cur_d + '.'; 36415 if(sub == '' || ('string' === typeof sub && '@' == sub.trim())){ 36416 dom = cur_d + '.'; 36417 } 36418 if(pos === ''){ 36419 $('#updatezone .table tbody tr').eq($('#updatezone .table tbody tr').length - 1).before('\ 36420 <tr class="row-mx">\ 36421 <td>\ 36422 <input type="hidden" name="priority[' + k + ']" value="'+$('.modalDns.in [name=recordMX]').val()+'">\ 36423 <input readonly disabled type="text" value="'+dom+'." name="zone[' + k + '][name]">\ 36424 </td>\ 36425 <td>\ 36426 <select readonly disabled name="zone['+k+'][ttl]">\ 36427 <option value="3600">3600</option>\ 36428 <option value="' + ttl + '" selected="selected">' + ttl + '</option>\ 36429 </select>\ 36430 </td>\ 36431 <td>\ 36432 <select readonly disabled name="zone['+k+'][type]">\ 36433 <option value="NS" class="hidden">NS</option>\ 36434 <option value="A">A</option>\ 36435 <option value="AAAA">AAAA</option>\ 36436 <option value="MX" selected="selected">MX</option>\ 36437 <option value="SRV">SRV</option>\ 36438 <option value="TXT">TXT</option>\ 36439 <option value="CNAME">CNAME</option>\ 36440 <option value="HTTPRED">HTTPRED</option>\ 36441 </select>\ 36442 </td>\ 36443 <td>\ 36444 <input readonly disabled type="text" value="' + $('.modalDns.in [name=hostnameMX]').val() + '." name="zone['+k+'][record]">\ 36445 </td>\ 36446 <td>\ 36447 <a class="delZoneEntry" href="#del" title="××××§×">\ 36448 <span class="glyphicon glyphicon-trash"></span></a>\ 36449 <a class="editZoneEntry" href="#edit" title="××××§×">\ 36450 <span class="glyphicon glyphicon-edit"></span></a>\ 36451 </td>\ 36452 <tr>\ 36453 '); 36454 } else { 36455 $("input[name='zone\\["+pos+"\\]\\[record\\]']").val($('.modalDns.in [name=hostnameMX]').val()); 36456 $("input[name='zone\\["+pos+"\\]\\[name\\]']").val(dom); 36457 $("input[name='priority\\["+pos+"\\]']").val($('.modalDns.in [name=recordMX]').val()); 36458 if(typeof undefined !== typeof ttl) { 36459 $("select[name='zone\\["+pos+"\\]\\[ttl\\]']").val(ttl); 36460 } 36461 } 36462 var updatednsdata = 'zone[name]=' + dom + '&zone[priority]='+ $('.modalDns.in [name=recordMX]').val() + '&zone[record]=' + $('.modalDns.in [name=hostnameMX]').val() +'&zone[ttl]=' + ttl + '&zone[type]=MX'; 36463 var id = window.attr('id'); 36464 36465 updatednsdata = addCSRFToDNSData(updatednsdata); 36466 36467 if (id.indexOf('addDns') >=0) { 36468 $.post(Storage.getData('app_url') + 'domain/new-record/' + $('#updatezone').attr('data-uid'), updatednsdata, function(r){ 36469 /* r = JSON.parse(r); 36470 if(r.status == 0){ 36471 $('#zone-error').html(r.msg).removeClass('hidden'); 36472 } 36473 if(r.status == 1){ 36474 $.fancybox.close(); 36475 $('#domainflash').html(r.msg).removeClass('hidden'); 36476 }*/ 36477 $('#save-zone').button('reset'); 36478 }); 36479 } else { 36480 $('#save-zone').button('reset'); 36481 } 36482 //:ALIN 36483 clearDNSModal(); 36484 $('.modalDns.in').modal('hide'); 36485 } 36486 break; 36487 case 'SRV': 36488 var ct = true; 36489 var errors = ''; 36490 $('.modalDns.in input.form-control').each(function () { 36491 if (!ctype_print($(this).val())) { 36492 ct = false;
36493 }; 36494 if($(this).val() == ''){ 36495 ct = false; 36496 } 36497 }); 36498 if (!ct) { 36499 errors += $.translate('English Only') + '\n'; 36500 } 36501 if((errors !== '')){ 36502 $('.modalDns.in .alert').html(nl2br(errors)).removeClass('hidden'); 36503 return; 36504 }else{ 36505 $('.modalDns.in .alert').addClass('hidden'); 36506 var sub = $('.modalDns.in [name=hostnameSRV]').val(); 36507 var dom = sub + '.' + cur_d + '.'; 36508 if(sub == '' || ('string' === typeof sub && '@' == sub.trim())){ 36509 dom = cur_d + '.'; 36510 } 36511 if(pos === ''){ // +St: name["serviceSRV"] ==> hostnameSRV 36512 $('#updatezone .table tbody tr').eq($('#updatezone .table tbody tr').length - 1).before('\ 36513 <tr class="row-srv">\ 36514 <td>\ 36515 \<input type="hidden" name="priority[' + k + ']" value="'+$('.modalDns.in [name=recordSRV]').val()+'">\ 36516 <input readonly disabled type="text" value="' + $('.modalDns.in [name="serviceSRV"]').val() + '.' + $('.modalDns.in [name="hostnameSRV"]').val() + '.' + cur_d + '" name="zone[' + k + '][name]">\ 36517 </td>\ 36518 <td>\ 36519 <select readonly disabled name="zone['+k+'][ttl]">\ 36520 <option value="3600">3600</option>\ 36521 <option value="' + ttl + '" selected="selected">' + ttl + '</option>\ 36522 </select>\ 36523 </td>\ 36524 <td>\ 36525 <select readonly disabled name="zone['+k+'][type]">\ 36526 <option value="NS" class="hidden">NS</option>\ 36527 <option value="A">A</option>\ 36528 <option value="AAAA">AAAA</option>\ 36529 <option value="MX">MX</option>\ 36530 <option value="SRV" selected="selected">SRV</option>\ 36531 <option value="TXT">TXT</option>\ 36532 <option value="CNAME">CNAME</option>\ 36533 <option value="HTTPRED">HTTPRED</option>\ 36534 </select>\ 36535 </td>\ 36536 <td>\ 36537 <input readonly disabled type="text" value="' /*+ $('.modalDns.in [name=recordSRV]').val() + ' '*/ + $('.modalDns.in [name=weightSRV]').val() + ' ' + $('.modalDns.in [name=portSRV]').val() + ' ' + $('.modalDns.in [name=targetSRV]').val() + '" name="zone['+k+'][record]">\ 36538 </td>\ 36539 <td>\ 36540 <a class="delZoneEntry" href="#del" title="××××§×">\ 36541 <span class="glyphicon glyphicon-trash"></span></a>\ 36542 <a class="editZoneEntry" href="#edit" title="××××§×">\ 36543 <span class="glyphicon glyphicon-edit"></span></a>\ 36544 </td>\ 36545 <tr>\ 36546 '); 36547 } else { 36548 /*$("input[name='zone\\["+pos+"\\]\\[record\\]']").val( 36549 $('.modalDns.in [name=recordSRV]').val()); 36550 $("input[name='zone\\["+pos+"\\]\\[name\\]']").val(cur_d);*/ 36551 36552 $("input[name='zone\\["+pos+"\\]\\[record\\]']").val( 36553 $('.modalDns.in [name=weightSRV]').val() + ' ' 36554 + $('.modalDns.in [name=portSRV]').val() + ' ' 36555 + $('.modalDns.in [name=targetSRV]').val()); 36556 36557 $("input[name='priority\\["+pos+"\\]']").val($('.modalDns.in [name=recordSRV]').val()); 36558 36559 if(typeof undefined !== typeof ttl) { 36560 $("select[name='zone\\["+pos+"\\]\\[ttl\\]']").val(ttl); 36561 } 36562 36563 $("input[name='zone\\["+pos+"\\]\\[name\\]']").val($('.modalDns.in [name=serviceSRV]').val() + '.' + $('.modalDns.in [name=hostnameSRV]').val() + '.' + cur_d); 36564 36565 } 36566 /* 36567 var updatednsdata = 'zone[name]='+cur_d+'&zone[record]='+ $('.modalDns.in [name=recordSRV]').val()+'&zone[ttl]=14400&zone[type]=SRV'; 36568 */ 36569 // +St: 36570 var hostCode = 36571 $('.modalDns.in [name=serviceSRV]').val() + '.' 36572 + $('.modalDns.in [name=hostnameSRV]').val() + '.' 36573 /*+ $('.modalDns.in [name=recordSRV]').val() + '.'*/ + cur_d; 36574 var ValueCode = 36575 $('.modalDns.in [name=weightSRV]').val() + ' ' 36576 + $('.modalDns.in [name=portSRV]').val() + ' ' 36577 + $('.modalDns.in [name=targetSRV]').val(); 36578 36579 var updatednsdata = 36580 'zone[name]='+ hostCode + '&zone[record]='+ ValueCode+'&zone[ttl]=' + ttl + '&zone[type]=SRV&zone[priority]='+$('.modalDns.in [name=recordSRV]').val(); 36581 var id = window.attr('id'); 36582 36583 updatednsdata = addCSRFToDNSData(updatednsdata); 36584 36585 if (id.indexOf('addDns') >=0) { 36586 $.post(Storage.getData('app_url') + 'domain/new-record/' + $('#updatezone').attr('data-uid'), updatednsdata, function(r){ 36587 36588 /* r = JSON.parse(r); 36589 if(r.status == 0){ 36590 $('#zone-error').html(r.msg).removeClass('hidden'); 36591 } 36592 if(r.status == 1){ 36593 $.fancybox.close(); 36594 $('#domainflash').html(r.msg).removeClass('hidden'); 36595 }*/ 36596 $('#save-zone').button('reset'); 36597 }); 36598 } else { 36599 $('#save-zone').button('reset'); 36600 } 36601 //:ALIN 36602 36603 clearDNSModal(); 36604 $('.modalDns.in').modal('hide'); 36605 } 36606 break; 36607 case 'RED': 36608 var ct = true; 36609 var errors = ''; 36610 $('.modalDns.in input.form-control').each(function () { 36611 if (!ctype_print($(this).val())) { 36612 ct = false;
36613 }; 36614 if($(this).val() == ''){ 36615 ct = false; 36616 } 36617 }); 36618 if (!ct) { 36619 errors += $.translate('English Only') + '\n'; 36620 } 36621 if(!isValidURL( $('.modalDns.in [name=recordRED]').val() )){ 36622 errors += $.translate('Not Valid URL') + '\n'; 36623 } 36624 36625 if((errors !== '')){ 36626 $('.modalDns.in .alert').html(nl2br(errors)).removeClass('hidden'); 36627 return; 36628 }else{ 36629 $('.modalDns.in .alert').addClass('hidden'); 36630 var sub = $('.modalDns.in [name=hostnameSRV]').val(); 36631 var dom = sub + '.' + cur_d + '.'; 36632 if(sub == '' || ('string' === typeof sub && '@' == sub.trim())){ 36633 dom = cur_d + '.'; 36634 } 36635 36636 var redtype = 301; 36637 if($('#typered3').is(':checked')) { redtype=302;} 36638 36639 if(pos === ''){ 36640 $('#updatezone .table tbody tr.row-red').remove(); 36641 $('#updatezone .table tbody tr').eq($('#updatezone .table tbody tr').length - 1).before('\ 36642 <tr class="row-red">\ 36643 <td>\ 36644 <input type="hidden" value="' + redtype + '" name="zone[' + k + '][status]">\ 36645 <input readonly disabled type="text" value="' + cur_d + '" name="zone[' + k + '][name]">\ 36646 </td>\ 36647 <td>\ 36648 <select readonly disabled name="zone['+k+'][ttl]">\ 36649 <option value="3600">3600</option>\ 36650 <option value="' + ttl + '" selected="selected">' + ttl + '</option>\ 36651 </select>\ 36652 </td>\ 36653 <td>\ 36654 <select readonly disabled name="zone['+k+'][type]">\ 36655 <option value="NS" class="hidden">NS</option>\ 36656 <option value="A">A</option>\ 36657 <option value="AAAA">AAAA</option>\ 36658 <option value="MX">MX</option>\ 36659 <option value="SRV">SRV</option>\ 36660 <option value="TXT">TXT</option>\ 36661 <option value="CNAME">CNAME</option>\ 36662 <option value="HTTPRED" selected="selected">HTTPRED</option>\ 36663 </select>\ 36664 </td>\ 36665 <td>\ 36666 <input readonly disabled type="text" value="'+ $('.modalDns.in [name=recordRED]').val() +'" name="zone['+k+'][record]">\ 36667 </td>\ 36668 <td>\ 36669 <a class="delZoneEntry" href="#del" title="××××§×">\ 36670 <span class="glyphicon glyphicon-trash"></span></a>\ 36671 <a class="editZoneEntry" href="#edit" title="××××§×">\ 36672 <span class="glyphicon glyphicon-edit"></span></a>\ 36673 </td>\ 36674 <tr>\ 36675 '); 36676 } else { 36677 $("input[name='zone\\["+pos+"\\]\\[record\\]']").val($('.modalDns.in [name=recordRED]').val()); 36678 $("input[name='zone\\["+pos+"\\]\\[name\\]']").val(cur_d); 36679 $("input[name='zone\\["+pos+"\\]\\[status\\]']").val(redtype); 36680 if(typeof undefined !== typeof ttl) { 36681 $("select[name='zone\\["+pos+"\\]\\[ttl\\]']").val(ttl); 36682 } 36683 } 36684 36685 36686 var zone = { 36687 name: cur_d, 36688 redtype: redtype, 36689 record: $('.modalDns.in [name=recordRED]').val(), 36690 ttl: ttl, 36691 type: 'HTTPRED' 36692 }; 36693 36694 var updatednsdata = { 36695 zone: zone 36696 }; 36697 36698 var id = window.attr('id'); 36699 36700 updatednsdata = addCSRFToDNSData(updatednsdata); 36701 36702 if (id.indexOf('addDns') >=0) 36703 { 36704 $.post(Storage.getData('app_url') + 'domain/new-record/' + $('#updatezone').attr('data-uid'), updatednsdata, function(r){ 36705 /* r = JSON.parse(r); 36706 if(r.status == 0){ 36707 $('#zone-error').html(r.msg).removeClass('hidden'); 36708 } 36709 if(r.status == 1){ 36710 $.fancybox.close(); 36711 $('#domainflash').html(r.msg).removeClass('hidden'); 36712 }*/ 36713 $('#save-zone').button('reset'); 36714 }); 36715 } 36716 else 36717 { 36718 $.post(Storage.getData('app_url') + 'domain/update-record/' + cur_d, $.extend({}, updatednsdata, { uid: $('#updatezone').attr('data-uid') }), function(r){ 36719 /*r = JSON.parse(r); 36720 if(r.status == 0){ 36721 $('#zone-error').html(r.msg).removeClass('hidden'); 36722 } 36723 if(r.status == 1){ 36724 $.fancybox.close(); 36725 $('#domainflash').html(r.msg).removeClass('hidden'); 36726 }*/ 36727 $('#save-zone').button('reset'); 36728 }); 36729 } 36730 //:ALIN 36731 36732 clearDNSModal(); 36733 $('.modalDns.in').modal('hide'); 36734 } 36735 break; 36736 } 36737 }) 36738 $(document).on('click', '.delZoneEntry', function(e){ 36739 e.preventDefault(); 36740 36741 var 36742 del = $(this), 36743 recordID = $(this).closest('tr').find('input[name=recordID]').val(), 36744 form = del.closest('#updatezone'), 36745 csrfConfig = Storage.getData('csrf_config'), 36746 tokenKey = csrfConfig['token_key'], 36747 tokenNameKey = csrfConfig['token_name_key'], 36748 csrfToken = form.find('[name=csrf_token]').val(), 36749 csrfTokenName = form.find('[name=csrf_token_name]').val(), 36750 updatednsdata = "type="+$(this).closest('tr').find(".zoneType").val() 36751 ; 36752 36753 updatednsdata += '&'+tokenKey+'='+csrfToken+'&'+tokenNameKey+'='+csrfTokenName; 36754 36755 if ($(this).closest('tr').find(".zoneType").val() === 'HTTPRED'){ 36756 recordID = $(this).closest('tr').find(".zoneName").val(); 36757 36758 $.post(Storage.getData('app_url') + 'domain/delete-record/' + recordID, updatednsdata + '&uid=' + $('#updatezone').attr('data-uid'), function(r){ 36759 /* r = JSON.parse(r); 36760 if(r.status == 0){ 36761 $('#zone-error').html(r.msg).removeClass('hidden'); 36762 } 36763 if(r.status == 1){ 36764 $.fancybox.close(); 36765 $('#domainflash').html(r.msg).removeClass('hidden'); 36766 }*/ 36767 36768 }); 36769 } 36770 36771 36772 del.parent().parent().remove(); 36773 36774 }); 36775 $(document).on('click', '#save-zone', function(e){ 36776 e.preventDefault(); 36777 36778 var recordsCount = $("#updatezone").find('table tbody tr').length; 36779 if(recordsCount > 100){ 36780 var error = $.translate('Maximum 100 records allowed!'); 36781 $('#zone-error').html(error).removeClass('hidden'); 36782 return false;
36783 } 36784 36785 $('#zone-error').addClass('hidden'); 36786 $('#save-zone').button('loading'); 36787 var errors = ''; 36788 var ct = true; 36789 $('#updatezone input').each(function () { 36790 if (!ctype_print_heb($(this).val())) { 36791 ct = false; 36792 }; 36793 }); 36794 if (!ct) { 36795 errors += $.translate('English Only') + '\n'; 36796 } 36797 if(errors !== ''){ 36798 $('#zone-error').html(nl2br(errors, true)).removeClass('hidden'); 36799 $('#save-zone').button('reset'); 36800 } else { 36801 $("#updatezone").find(':input:disabled').prop('disabled', false); 36802 var updatednsdata = $('#updatezone').serialize(); 36803 $("#updatezone").find(':input').prop('disabled', true); 36804 36805 $.post(Storage.getData('app_url') + 'domain/update-dns/' + $('#updatezone').attr('data-uid'), updatednsdata, function(r){ 36806 r = JSON.parse(r); 36807 if(r.status == 0){ 36808 $('#zone-error').html(r.msg).removeClass('hidden'); 36809 } 36810 if(r.status == 1){ 36811 $.fancybox.close(); 36812 $('#domainflash').html(r.msg).removeClass('hidden'); 36813 } 36814 $('#save-zone').button('reset'); 36815 }) 36816 } 36817 }) 36818 $(document).on('click', '#dnsChoser a', function (e) { 36819 e.preventDefault(); 36820 if (!$(this).parent().hasClass('disabled')) { 36821 $(this).tab('show'); 36822 } 36823 }); 36824 36825 var isZoneEditorLocked = function () {
36826 var $overlay = $('#zone-editor-disclaimer'); 36827 return $overlay.length && $overlay.is(':visible'); 36828 }; 36829 36830 $(document).on('change', '#zone-editor-agree-check', function () { 36831 $('#zone-editor-agree-btn').prop('disabled', !this.checked); 36832 }); 36833 36834 $(document).on('click', '#zone-editor-agree-btn', function (e) { 36835 e.preventDefault(); 36836 if (!$('#zone-editor-agree-check').is(':checked')) { 36837 return false; 36838 } 36839 $('.zone-editor-lock-wrap').addClass('is-unlocked'); 36840 $('#zone-editor-disclaimer').hide(); 36841 }); 36842 36843 $(document).on('click', '#addDnsRow button, a.editZoneEntry, a.delZoneEntry, #save-zone', function (e) { 36844 if (isZoneEditorLocked()) { 36845 e.preventDefault(); 36846 e.stopImmediatePropagation(); 36847 return false; 36848 } 36849 }); 36850 36851 // $(document).on('click', '#action-show-terms', function (e) { 36852 // $.fancybox({ 36853 // href: $(this).attr('href'), 36854 // type: 'iframe' 36855 // }); 36856 36857 // e.preventDefault(); 36858 // }); 36859 36860 $(document).on('click', '#renew-domain #checkCoupon', function (e) { 36861 var cpn = $('#couponCode').val(); 36862 $('#cpn-error').addClass('hidden'); 36863 //$('#cpnDis').addClass('hidden'); 36864 $(this).button('loading'); 36865 $('#creditDetails input[type=text]').parent().show(); 36866 $('#creditDetails select').parent().show(); 36867 $('#creditNumber').val(''); 36868 $('#creditExpirationYear option').eq(0).prop('selected', true); 36869 $('#creditExpirationMonth option').eq(0).prop('selected', true); 36870 $('#creditCvv').val(''); 36871 $('#creditId').val(''); 36872 $.get(Storage.getData('app_url') + 'checkCpn/' + cpn, '', function (r) { 36873 r = parseFloat(r); 36874 if (r <= 0) { 36875 $('#cpn-error').removeClass('hidden'); 36876 $('#cpnDis').addClass('hidden'); 36877 } else { 36878 $('#cpn-error').addClass('hidden'); 36879 var price = $('#renew-domain .UIInfoBox > span > span').html(); 36880 var dis = price - r; 36881 if (dis <= 0) { 36882 dis = 0; 36883 $('#creditDetails input[type=text]').parent().hide(); 36884 $('#creditDetails select').parent().hide(); 36885 $('#creditNumber').val('378282246310005'); 36886 $('#creditExpirationYear').val(new Date().getFullYear() + 5); 36887 $('#creditExpirationMonth').val(12); 36888 $('#creditCvv').val(123); 36889 $('#creditId').val(123456789); 36890 } 36891 $('.amount').html(price); 36892 $('.sum').html(Number(dis).toFixed(2)) 36893 $('#cpnDis').removeClass('hidden'); 36894 } 36895 $('#checkCoupon').button('reset'); 36896 }); 36897 $('#checkCoupon').button('reset'); 36898 }) 36899 $(document).on('click', '#domain_order #checkCoupon', function (e) { 36900 var cpn = $('#couponCode').val(); 36901 var placeholder = '<div class="col-md-6" id="enomPlaceholder" style="height: 200px;"></div>'; 36902 $('#cpn-error').addClass('hidden'); 36903 //$('#cpnDis').addClass('hidden'); 36904 $(this).button('loading'); 36905 $.get(Storage.getData('app_url') + 'checkCpn/' + cpn, '', function (r) { 36906 r = parseFloat(r); 36907 $('#creditNumber').val(''); 36908 $('#creditExpirationYear option').eq(0).prop('selected', true); 36909 $('#creditExpirationMonth option').eq(0).prop('selected', true); 36910 $('#creditCvv').val(''); 36911 $('#creditId').val(''); 36912 $('#enomPlaceholder').remove(); 36913 $('#creditDetails input[type=text]').parent().show(); 36914 $('#creditDetails select').parent().show(); 36915 if (r <= 0) { 36916 $('#cpn-error').removeClass('hidden'); 36917 $('#cpnDis').addClass('hidden'); 36918 } else { 36919 $('#cpn-error').addClass('hidden'); 36920 var price = $('#creditCardDetails .UISection span span').html(); 36921 var dis = price - r; 36922 if (dis <= 0) { 36923 dis = 0; 36924 $('#creditDetails').before(placeholder); 36925 $('#creditDetails input[type=text]').parent().hide(); 36926 $('#creditDetails select').parent().hide(); 36927 $('#creditNumber').val('378282246310005'); 36928 $('#creditExpirationYear').val(new Date().getFullYear() + 5); 36929 $('#creditExpirationMonth').val(12);
36930 $('#creditCvv').val(123); 36931 $('#creditId').val(123456789); 36932 } 36933 36934 $('#cpnDis .amount').html(price); 36935 $('#cpnDis .sum').html(Number(dis).toFixed(2)) 36936 $('#cpnDis').removeClass('hidden'); 36937 // $(this).attr("disabled", disable); 36938 } 36939 $('#checkCoupon').button('reset'); 36940 }); 36941 }); 36942 36943 $(document).on('click', '.admin-domain-info', function (e) { 36944 e.preventDefault(); 36945 36946 $.showXHRModal($(this).attr('href'), function () {$('.fancybox-overlay.fancybox-overlay-fixed').css("z-index", 15104);}, {'title': 'Domain info'}); 36947 36948 }); 36949 36950 $(document).on('click', '.transfer-acc', function (e) { 36951 e.preventDefault(); 36952 var uid = $(this).parent().parent().data('uid'); 36953 $.get(Storage.getData('app_url') + 'domain/transfer-acc/' + uid, function (r) { 36954 $.fancybox.open({ 36955 type: 'iframe', 36956 padding: 0, 36957 content: r, 36958 afterShow: function () { 36959 36960 $('#transfer-acc-domain').click(function (e) { 36961 e.preventDefault(); 36962 $(this).button('loading'); 36963 var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; 36964 var emailEl = $('#userEmail'); 36965 var email = emailEl.val(); 36966 var errors = ''; 36967 if (!re.test(email) || email === '') { 36968 emailEl.parent().addClass('has-error'); 36969 errors += $.translate('Email is invalid') + '\n'; 36970 } 36971 else { 36972 emailEl.parent().removeClass('has-error'); 36973 } 36974 if (errors !== '') { 36975 $('#transfer-acc-errors').html(nl2br(errors, true)).removeClass('hidden'); 36976 $(this).button('reset'); 36977 } else { 36978 $('#transfer-acc-errors').addClass('hidden'); 36979 $.post($('#transfer-acc').attr('action') + '/' + uid, $('#transfer-acc').serialize(), function (r) { 36980 if (r.status == 1) { 36981 $('#domainflash').html(r.msg).removeClass('hidden'); 36982 $('#transfer-acc').addClass('hidden'); 36983 $('tr[data-uid="' + uid + '"]').remove(); 36984 $.fancybox.close(); 36985 } 36986 if (r.status == 0) { 36987 $('#transfer-acc-errors').html(nl2br(r.msg, true)).removeClass('hidden'); 36988 } 36989 $('#transfer-acc-domain').button('reset'); 36990 }) 36991 } 36992 }); 36993 36994 $('#transfer-security-code-confirm').click(function (e) { 36995 e.preventDefault(); 36996 $('#transfer-security-code-initial').addClass('hidden'); 36997 $('#transfer-security-code-contact').removeClass('hidden'); 36998 }); 36999 37000 37001 $('#transfer-security-code-contact-yes').click(function (e) { 37002 e.preventDefault(); 37003 $('#line-loader-transfer-security-code').removeClass('hidden'); 37004 var uid = $(this).attr('domain-id'); 37005 $('#transfer-security-code-contact').addClass('hidden'); 37006 37007 var 37008 button = $(this), 37009 errorContainer = $('#transfer-acc-errors') 37010 ; 37011 $(this).button('loading'); 37012 37013 $.get('/domain/contact-transfer-code-xhr/' + uid, function (r) { 37014 button.button('reset'); 37015 37016 if (r.status) { 37017 var msgContainer = $('#transfer-security-code-message-container'); 37018 37019 errorContainer.addClass('hidden'); 37020 37021 msgContainer.find('span').html(r.msg); 37022 37023 button.hide(function () { 37024 msgContainer.removeClass('hidden'); 37025 $('#line-loader-transfer-security-code').addClass('hidden'); 37026 }); 37027 } else { 37028 errorContainer.html(nl2br(r.msg, true)).removeClass('hidden'); 37029 $('#line-loader-transfer-security-code').addClass('hidden'); 37030 } 37031 }); 37032 37033 // TODO: Send AJAX to mark user wants callback 37034 // $.post('/domain/mark-callback-request', {domain_id: uid}); 37035 37036 // Then get transfer code 37037 //getTransferCode($(this), uid); 37038 }); 37039 37040 $('#transfer-security-code-generation').click(function (e) { 37041 $('#line-loader-transfer-security-code').removeClass('hidden'); 37042 var 37043 button = $(this), 37044 uid = button.attr('domain-id'), 37045 errorContainer = $('#transfer-acc-errors') 37046 ; 37047 $('#transfer-security-code-contact').addClass('hidden'); 37048 e.preventDefault(); 37049 $(this).button('loading'); 37050 37051 $.get('/domain/get-transfer-code-xhr/' + uid, function (r) { 37052 button.button('reset'); 37053 37054 if (r.status) { 37055 var msgContainer = $('#transfer-security-code-message-container'); 37056 37057 errorContainer.addClass('hidden'); 37058 37059 msgContainer.find('span').html(r.msg); 37060 37061 button.hide(function () { 37062 msgContainer.removeClass('hidden'); 37063 $('#line-loader-transfer-security-code').addClass('hidden'); 37064 }); 37065 } else { 37066 errorContainer.html(nl2br(r.msg, true)).removeClass('hidden'); 37067 $('#line-loader-transfer-security-code').addClass('hidden'); 37068 } 37069 }); 37070 }); 37071 37072 37073 // Remove previous handlers to prevent double registration 37074 $(document).off('change', '#lockstateToggle'); 37075 37076 $(document).on('change', '#lockstateToggle', function(e) { 37077 e.preventDefault(); 37078 e.stopImmediatePropagation(); 37079 37080 // Check if there is a request in progress 37081 var $toggle = $(this); 37082 if ($toggle.data('processing')) { 37083 return false;
37084 } 37085 37086 $toggle.data('processing', true); 37087 $('#line-loader-lockstate').removeClass('hidden'); 37088 $('.lockstateSlider').addClass('hidden'); 37089 $('#DomainLockStatusLabel').addClass('hidden'); 37090 var isLocked = $toggle.is(':checked'); 37091 var label = $('#DomainLockStatusLabel'); 37092 if (isLocked) { 37093 label.addClass('locked'); 37094 label.removeClass('unlocked'); 37095 } else { 37096 label.addClass('unlocked'); 37097 label.removeClass('locked'); 37098 } 37099 37100 var data = { 37101 lockstate: isLocked ? 1 : 0 37102 }; 37103 var uid = $toggle.data('uid'); 37104 var url = Storage.getData('app_url') + 'domain/lockDomain/' + uid; 37105 var csrfConfig = Storage.getData('csrf_config'); 37106 var form = $toggle.closest('form'); 37107 data[csrfConfig['token_name_key']] = form.find('[name=csrf_token_name]').val(); 37108 data[csrfConfig['token_key']] = form.find('[name=csrf_token]').val(); 37109 37110 $.post(url, data, function (r) { 37111 r = JSON.parse(r); 37112 $toggle.data('processing', false); 37113 37114 if (r.status == 0) { 37115 $('#lockstate-errors').html(r.msg).removeClass('hidden'); 37116 $('#line-loader-lockstate').addClass('hidden'); 37117 } 37118 if (r.status == 1) { 37119 $('#lockstate-suc').html(r.msg).removeClass('hidden'); 37120 $('#line-loader-lockstate').addClass('hidden'); 37121 37122 // update lock button text and title 37123 var lockButton = $('tr[data-uid="' + uid + '"] .lock.transfer-acc'); 37124 if (isLocked) { 37125 lockButton.removeClass('icon-unlock').addClass('icon-lock'); 37126 lockButton.attr('title', r.msg); 37127 } else { 37128 lockButton.removeClass('icon-lock').addClass('icon-unlock'); 37129 lockButton.attr('title', r.msg); 37130 } 37131 } 37132 }).fail(function() { 37133 $toggle.data('processing', false); 37134 $('#line-loader-lockstate').addClass('hidden'); 37135 }); 37136 }); 37137 } 37138 }); 37139 }) 37140 }); 37141 $('#getthis, .option .add_btn').click(function (e) { 37142 e.preventDefault(); 37143 var inDomain = $('input[name=check-domain]').val(); 37144 if (!stristr(inDomain, '.')) { 37145 inDomain += '.co.il'; 37146 } 37147 if ($(this).hasClass('add_btn')) { 37148 var domainparts = inDomain.split('.'); 37149 var domain = domainparts[0]; 37150 inDomain = domain + $(this).data('tld'); 37151 } 37152 // setCookie('domain', inDomain, 1); 37153 37154 $.get(Storage.getData('app_url') + 'domain/pre-info', {'dname': inDomain}, function (data) { 37155 if(data.success) { 37156 window.location.href = data.page; 37157 } 37158 }); 37159 }); 37160 37161 $(document).on('click', '#invoices,#contacts,#mDomains,#settings', function (e) { 37162 if($(this).attr('id') == 'mDomains' && $(this).hasClass('active')){ 37163 return true; 37164 } 37165 e.preventDefault(); 37166 $('#invoices,#contacts,#mDomains,#settings').removeClass('active'); 37167 $(this).addClass('active'); 37168 var id = $(this).attr('id'); 37169 var domains = $('#domain-cont'); 37170 var contacts = $('#contacts-cont'); 37171 var invoices = $('#invoices-cont'); 37172 var settings = $('#account-settings-cont'); 37173 if (id == 'mDomains') { 37174 domains.removeClass('hidden'); 37175 contacts.addClass('hidden'); 37176 invoices.addClass('hidden'); 37177 settings.addClass('hidden'); 37178 } 37179 if (id == 'contacts') { 37180 contacts.removeClass('hidden'); 37181 domains.addClass('hidden'); 37182 invoices.addClass('hidden'); 37183 settings.addClass('hidden'); 37184 } 37185 if (id == 'invoices') { 37186 invoices.removeClass('hidden'); 37187 domains.addClass('hidden'); 37188 contacts.addClass('hidden'); 37189 settings.addClass('hidden'); 37190 } 37191 if (id == 'settings') { 37192 settings.removeClass('hidden'); 37193 domains.addClass('hidden'); 37194 invoices.addClass('hidden'); 37195 contacts.addClass('hidden'); 37196 } 37197 }); 37198 $(document).on('click', '.update-contact', function (e) { 37199 e.preventDefault(); 37200 var uid = $(this).parent().parent().data('uid'); 37201 $.get(Storage.getData('app_url') + 'contacts/update/' + uid, function (r) { 37202 $.fancybox.open({ 37203 content: r, 37204 padding: 0, 37205 type: 'iframe', 37206 afterShow: function () { 37207 $('#saveContact').click(function (e) { 37208 e.preventDefault(); 37209 var form = $(this).closest('form'); 37210 var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; 37211 var emailEl = form.find('#contactEmail'); 37212 var priPhoneEl = form.find('#contactLanding'); 37213 var streetEl = form.find('#contactStreet'); 37214 var cityEl = form.find('#contactCity'); 37215 var countryEl = form.find('#contactCountry'); 37216 var zipEl = form.find('#contactZip'); 37217 var email = emailEl.val(); 37218 var street = streetEl.val(); 37219 var city = cityEl.val(); 37220 var country = countryEl.val(); 37221 var zip = zipEl.val(); 37222 var phone1 = form.find('#tel1').val(); 37223 var phone2 = form.find('#tel2').val(validatePerf(form.find('#tel2').val())).val(); 37224 var phone3 = form.find('#tel3').val(); 37225 var fax1 = form.find('#fax1').val(); 37226 var fax2 = form.find('#fax2').val(validatePerf(form.find('#fax2').val())).val(); 37227 var fax3 = form.find('#fax3').val(); 37228 priPhoneEl.val(phone3 + ' ' + phone2 + ' ' + phone1); 37229 form.find('#contactFax').val(fax3 + ' ' + fax2 + ' ' + fax1); 37230 var priPhone = priPhoneEl.val(); 37231 var errors = ''; 37232 var ct = true; 37233 $('#contactEdit input').each(function () { 37234 if (!ctype_print($(this).val())) { 37235 ct = false;
37236 } 37237 ; 37238 }); 37239 if (!ct) { 37240 errors += $.translate('English Only') + '\n'; 37241 } 37242 if (!re.test(email) || email === '') { 37243 emailEl.parent().addClass('has-error'); 37244 errors += $.translate('Email is invalid') + '\n'; 37245 } 37246 else { 37247 emailEl.parent().removeClass('has-error'); 37248 } 37249 if (priPhone === '' || priPhone.length < 13 || !/[0-9\s]+/.test(priPhone)) { 37250 priPhoneEl.parent().addClass('has-error'); 37251 errors += $.translate('Primary phone is required') + '\n'; 37252 } 37253 else { 37254 priPhoneEl.parent().removeClass('has-error'); 37255 } 37256 if (street === '' || street.length < 2 || !/[0-9]/.test(street)) { 37257 streetEl.parent().addClass('has-error'); 37258 errors += $.translate('Street is required') + '\n'; 37259 } 37260 else { 37261 streetEl.parent().removeClass('has-error'); 37262 } 37263 if (city === '' || city.length < 2 || /[0-9]/.test(city)) { 37264 cityEl.parent().addClass('has-error'); 37265 errors += $.translate('City is required') + '\n'; 37266 } 37267 else { 37268 cityEl.parent().removeClass('has-error'); 37269 } 37270 if (zip === '' || zip.length !== 7) { 37271 zipEl.parent().addClass('has-error'); 37272 errors += $.translate('Zip is required') + '\n'; 37273 } else if (window.isInvalidZipCode(zip)) { 37274 zipEl.parent().addClass('has-error'); 37275 errors += $.translate('Zip is invalid') + '\n'; 37276 } else { 37277 zipEl.parent().removeClass('has-error'); 37278 } 37279 if (country === '') { 37280 countryEl.parent().addClass('has-error'); 37281 errors += $.translate('Country is required') + '\n'; 37282 } 37283 else { 37284 countryEl.parent().removeClass('has-error'); 37285 } 37286 if (errors !== '') { 37287 $('#contact-modal-error').html(nl2br(errors, true)).removeClass('hidden'); 37288 } else { 37289 $('#contact-modal-error').addClass('hidden'); 37290 $.post($('#contactEdit').attr('action') + '/' + uid, $('#contactEdit').serialize(), function (r) { 37291 r = JSON.parse(r); 37292 if (r.status == 1) { 37293 $('#contactsflash').html(r.msg).removeClass('hidden'); 37294 $('#contact-modal-error').addClass('hidden'); 37295 $.fancybox.close(); 37296 } 37297 if (r.status == 0) { 37298 $('#contact-modal-error').html(nl2br(r.msg, true)).removeClass('hidden'); 37299 } 37300 }) 37301 } 37302 37303 }) 37304 } 37305 }); 37306 }); 37307 }); 37308 $(document).on('click', '.delete-contact', function (e) { 37309 e.preventDefault(); 37310 var con = confirm($.translate('Are you sure?')); 37311 if (con) { 37312 var uid = $(this).parent().parent().data('uid'); 37313 $.get(Storage.getData('app_url') + 'contacts/remove/' + uid, function (r) { 37314 r = JSON.parse(r); 37315 if (r.status == 0) { 37316 window.location = Storage.getData('app_url') + 'user/login'; 37317 } 37318 if (r.status == 1) { 37319 $.get(Storage.getData('app_url') + '/contacts/list', function (data) { 37320 $('#contacts-cont').html(data); 37321 }) 37322 } 37323 if (r.status == 2) { 37324 alert(r.msg); 37325 } 37326 }); 37327 } else { 37328 return; 37329 } 37330 }); 37331 $(document).on('click', '#addContact', function (e) { 37332 e.preventDefault(); 37333 $.get(Storage.getData('app_url') + 'contacts/add', function (r) { 37334 $.fancybox.open({ 37335 content: r, 37336 padding: 0, 37337 type: 'iframe', 37338 afterShow: function () { 37339 $('#saveContact').click(function (e) { 37340 e.preventDefault(); 37341 var form = $(this).closest('form'); 37342 var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; 37343 var emailEl = form.find('#contactEmail'); 37344 var priPhoneEl = form.find('#contactLanding'); 37345 var streetEl = form.find('#contactStreet'); 37346 var cityEl = form.find('#contactCity'); 37347 var countryEl = form.find('#contactCountry'); 37348 var zipEl = form.find('#contactZip'); 37349 var fullNameEl = form.find('#contactFullName'); 37350 var fullName = fullNameEl.val(); 37351 var email = emailEl.val(); 37352 var street = streetEl.val(); 37353 var city = cityEl.val(); 37354 var country = countryEl.val(); 37355 var zip = zipEl.val(); 37356 var phone1 = form.find('#tel1').val(); 37357 var phone2 = form.find('#tel2').val(validatePerf(form.find('#tel2').val())).val(); 37358 var phone3 = form.find('#tel3').val(); 37359 var fax1 = form.find('#fax1').val(); 37360 var fax2 = form.find('#fax2').val(validatePerf(form.find('#fax2').val())).val(); 37361 var fax3 = form.find('#fax3').val(); 37362 priPhoneEl.val(phone3 + ' ' + phone2 + ' ' + phone1); 37363 form.find('#contactFax').val(fax3 + ' ' + fax2 + ' ' + fax1); 37364 var priPhone = priPhoneEl.val(); 37365 var errors = ''; 37366 var ct = true; 37367 form.find('input').each(function () { 37368 if (!ctype_print($(this).val())) { 37369 ct = false;
37370 } 37371 ; 37372 }); 37373 if (!ct) { 37374 errors += $.translate('English Only') + '\n'; 37375 } 37376 if (fullName === '' || fullName.length < 5 || fullName.split(' ').length < 2) { 37377 fullNameEl.parent().addClass('has-error'); 37378 errors += $.translate('full name is required') + '\n'; 37379 } 37380 else { 37381 fullNameEl.parent().removeClass('has-error'); 37382 } 37383 if (!re.test(email) || email === '') { 37384 emailEl.parent().addClass('has-error'); 37385 errors += $.translate('Email is invalid') + '\n'; 37386 } 37387 else { 37388 emailEl.parent().removeClass('has-error'); 37389 } 37390 if (priPhone === '' || priPhone.length < 13 || !/[0-9\s]+/.test(priPhone)) { 37391 priPhoneEl.parent().addClass('has-error'); 37392 errors += $.translate('Primary phone is required') + '\n'; 37393 } 37394 else { 37395 priPhoneEl.parent().removeClass('has-error'); 37396 } 37397 if (street === '' || street.length < 2 || !/[0-9]/.test(street)) { 37398 streetEl.parent().addClass('has-error'); 37399 errors += $.translate('Street is required') + '\n'; 37400 } 37401 else { 37402 streetEl.parent().removeClass('has-error'); 37403 } 37404 if (city === '' || city.length < 2 || /[0-9]/.test(city)) { 37405 cityEl.parent().addClass('has-error'); 37406 errors += $.translate('City is required') + '\n'; 37407 } 37408 else { 37409 cityEl.parent().removeClass('has-error'); 37410 } 37411 if (zip === '' || zip.length !== 7) { 37412 zipEl.parent().addClass('has-error'); 37413 errors += $.translate('Zip is required') + '\n'; 37414 } else if (window.isInvalidZipCode(zip)) { 37415 zipEl.parent().addClass('has-error'); 37416 errors += $.translate('Zip is invalid') + '\n'; 37417 } else { 37418 zipEl.parent().removeClass('has-error'); 37419 } 37420 if (country === '') { 37421 countryEl.parent().addClass('has-error'); 37422 errors += $.translate('Country is required') + '\n'; 37423 } 37424 else { 37425 countryEl.parent().removeClass('has-error'); 37426 } 37427 if (errors !== '') { 37428 form.find('#contact-modal-error').html(nl2br(errors, true)).removeClass('hidden'); 37429 } else { 37430 form.find('#contact-modal-error').addClass('hidden'); 37431 $.post(form.attr('action'), form.serialize(), function (r) { 37432 r = JSON.parse(r); 37433 if (r.status == 1) { 37434 //alert(r.msg); 37435 $('#contactsflash').html(nl2br(r.msg, true)).removeClass('hidden'); 37436 form.find('#contact-modal-error').addClass('hidden'); 37437 $.fancybox.close(); 37438 } 37439 if (r.status == 0) { 37440 form.find('#contact-modal-error').html(nl2br(r.msg, true)).removeClass('hidden'); 37441 } 37442 }) 37443 } 37444 37445 }) 37446 } 37447 }); 37448 }); 37449 }); 37450 $(document).on('submit', '#user-auth-login form', function (e) { 37451 $('#user-auth-login-submit').button('loading'); 37452 e.preventDefault(); 37453 $('#upgrade-ntc').addClass('hidden'); 37454 $('#login-errors').addClass('hidden'); 37455 37456 $.post($(this).getFormSubmitPath(), $(this).serialize(), function (data) { 37457 console.log(data.status); 37458 if (data.status == 0) { 37459 $('#user-auth-login-submit').button('reset'); 37460 $('#login-errors').removeClass('hidden').html(data.msg); 37461 } 37462 if (data.status == 1) { 37463 window.location = data.page; 37464 $.localStorage.set('domains_bulk', []); 37465 e.stopPropagation(); 37466 return false;
37467 } 37468 if (data.status == 2) { 37469 $('#user-auth-login-submit').button('reset'); 37470 $('#upgrade-ntc').removeClass('hidden'); 37471 } 37472 if (data.status == 3) { 37473 $('#user-auth-login-submit').button('reset'); 37474 $('#user-auth-login-email').addClass('disabled'); 37475 $('#user-auth-login-password').addClass('disabled'); 37476 $('#user-auth-login-code').prop('disabled', false); 37477 37478 $('#form-user-auth-block').addClass('hidden'); 37479 $('#form-user-auth-tfa-block').removeClass('hidden'); 37480 } 37481 }); 37482 }); 37483 37484 // email verify 37485 $(document).on('click', '#form-user-auth-email-verify-resend', function (e) { 37486 e.preventDefault(); 37487 37488 $.post(Storage.getData('app_url') + 'user/email/verify/resend', {}, function (response) { 37489 if (response.status == 0) { 37490 $('#email-verify-errors').removeClass('hidden').html(response.msg); 37491 } 37492 if (response.status == 1) { 37493 if(undefined != response.message && undefined != response.message.text && undefined != response.message.title) { 37494 $.showSuccess(response.message.title, response.message.text); 37495 } 37496 37497 return false; 37498 } 37499 }); 37500 }); 37501 37502 $(document).on('submit', '#user-email-verify-form', function (e) { 37503 $('#user-email-verify-submit').button('loading'); 37504 $('#email-verify-errors').addClass('hidden'); 37505 e.preventDefault(); 37506 37507 $.post($(this).getFormSubmitPath(), $(this).serialize(), function (data) { 37508 if (data.status == 0) { 37509 $('#user-email-verify-submit').button('reset'); 37510 $('#email-verify-errors').removeClass('hidden').html(data.msg); 37511 } 37512 if (data.status == 1) { 37513 window.location = Storage.getData('app_url') + 'user/account'; 37514 } 37515 }); 37516 }); 37517 37518 // redirect from user/account page to search domain page 37519 $(document).on('submit', '#whois.account-page', function(e) { 37520 e.preventDefault(); 37521 37522 var inDomain = $('input[name=check-domain]').val(); 37523 37524 if('' == inDomain) { 37525 return false; 37526 } 37527 var normalizedDomain = inDomain.trim() 37528 .toLowerCase() 37529 .replace(/^https?:\/\//i, '') // Remove http:// or https:// 37530 .replace(/^www\./i, '') // Remove www. prefix
37531 .replace(/[^\u0590-\u05FF\w\.\-]/g, ''); // Keep only letters (including Hebrew), numbers, dots, hyphens 37532 37533 // Additional validation: ensure it's not empty after normalization 37534 if('' == normalizedDomain) { 37535 return false; 37536 } 37537 $(this).find('button').button('loading'); 37538 37539 window.location.href = "/?check-domain=" + encodeURIComponent(normalizedDomain) + 37540 "&csrf_token_name=whois&csrf_token=" + 37541 $(this).find('input[name=csrf_token]').val(); 37542 }); 37543 37544 $(document).on('submit', '#whois:not(.account-page)', whois); 37545 function whois(e) { 37546 e.preventDefault(); 37547 $('#check-domain').button('loading'); 37548 var inDomain = $('input[name=check-domain]').val(); 37549 37550 // Clean domain: remove protocol, www, paths, ports 37551 inDomain = inDomain.trim(); 37552 inDomain = inDomain.replace(/^[a-z]+:\/\//i, ''); // Remove protocol 37553 inDomain = inDomain.replace(/^www\./i, ''); // Remove www 37554 inDomain = inDomain.split('/')[0]; // Remove path 37555 inDomain = inDomain.split('?')[0]; // Remove query string 37556 inDomain = inDomain.split('#')[0]; // Remove hash 37557 inDomain = inDomain.replace(/:\d+$/, ''); // Remove port 37558 inDomain = inDomain.toLowerCase(); 37559 37560 window.location.href = "/?check-domain=" + inDomain + "&csrf_token_name=whois&csrf_token=" + $(this).find('input[name=csrf_token]').val(); 37561 37562 return false; 37563 } 37564 37565 $(document).on('submit', '#user-auth-password-reset-form', function (e) { 37566 e.preventDefault(); 37567 $('#user-auth-password-reset-submit').button('loading'); 37568 $('#forgot-errors').addClass('hidden'); 37569 $('#forgot-success').addClass('hidden'); 37570 $.post($(this).attr('action'), $(this).serialize(), function (data) { 37571 data = JSON.parse(data); 37572 if (data.status === 0) { 37573 $('#forgot-errors').removeClass('hidden').html(data.msg); 37574 $('#user-auth-password-reset-submit').button('reset'); 37575 } 37576 if (data.status === 1) { 37577 // todo@alexbuturlakin: Will move "css({'font-size': '15px'})" to less in next commit "enom price and refactoring" 37578 $('#forgot-success').removeClass('hidden').css({'font-size': '15px'}).html(data.msg); 37579 $('#user-auth-password-reset-submit').button('reset'); 37580 } 37581 }); 37582 }); 37583 37584 37585 $(document).on('click', '.option .whoisData', function (e) { 37586 var data = { 37587 domain: cur_domain + $(this).data('tld') 37588 }; 37589 var csrfConfig = Storage.getData('csrf_config'); 37590 var parent = $(this).closest('.actions'); 37591 37592 data[csrfConfig['token_name_key']] = parent.find('[name=csrf_token_name]').val(); 37593 data[csrfConfig['token_key']] = parent.find('[name=csrf_token]').val(); 37594 37595 $.post(Storage.getData('app_url') + 'whois/info', data, function (data) { 37596 e.preventDefault(); 37597 data = data.replace(/&/g, '&') 37598 .replace(/>/g, '>') 37599 .replace(/</g, '<') 37600 .replace(/\n/g, '<br>'); 37601 $.fancybox({ 37602 content: ' <div class="modal-header"><h3>whois</h3></div><div class="whois_wrap"">' + data + '</div>', 37603 padding: 0, 37604 type: 'iframe', 37605 width: 600 37606 }); 37607 }); 37608 }); 37609 37610 37611 $(document).on('click', 'a#newSearch', function (e) { 37612 e.preventDefault(); 37613 $('#alerts_row').addClass('hidden'); 37614 $("#ok").addClass('hidden'); 37615 $("#error").addClass('hidden '); 37616 $('#re-search-domain').removeClass('hidden'); 37617 $('.hpsearatopr').hide(); 37618 $('.option .progressWhois').show(); 37619 $('.option .avilable').hide(); 37620 $('.option .add_btn').hide(); 37621 $('.option .whoisData').hide(); 37622 $('.option .lblTaken').hide(); 37623 37624 }); 37625 37626 $(document).on('submit', '#update-settings form', function (e) { 37627 e.preventDefault(); 37628 var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; 37629 var stringRe = /^[A-Za-z\s][A-Za-z0-9\s]*$/; 37630 var emailEl = $('#registerEmail'); 37631 var passEl = $('#registerPassword'); 37632 var passConfEl = $('#registerPasswordConfirm'); 37633 var fullNameEl = $('#registerFullName'); 37634 var priPhoneEl = $('#registerPrimaryPhone'); 37635 var streetEl = $('#registerAddressStreet'); 37636 var cityEl = $('#registerAddressCity'); 37637 var countryEl = $('#registerAddressCountry'); 37638 var zipEl = $('#registerAddressZip'); 37639 var secondaryPhoneEl = $('#registerSecondaryPhone'); 37640 var email = emailEl.val(); 37641 var pwd = passEl.val(); 37642 var pwdConf = passConfEl.val(); 37643 var fullName = fullNameEl.val(); 37644 var street = streetEl.val(); 37645 var city = cityEl.val(); 37646 var country = countryEl.val(); 37647 var zip = zipEl.val(); 37648 var secondaryPhone = secondaryPhoneEl.val(); 37649 var errors = ''; 37650 var nsvals = []; 37651 var fax1 = $('#fax1').val();
37652 var fax2 = $('#fax2').val(validatePerf($('#fax2').val())).val(); 37653 var fax3 = $('#fax3').val(); 37654 var phone1 = $('#tel1').val(); 37655 var phone2 = $('#tel2').val(validatePerf($('#tel2').val())).val(); 37656 var phone3 = $('#tel3').val(); 37657 priPhoneEl.val(phone3 + ' ' + phone2 + ' ' + phone1); 37658 $('#registerFaxNumber').val(fax3 + ' ' + fax2 + ' ' + fax1); 37659 var priPhone = priPhoneEl.val(); 37660 var ct = true; 37661 $('#update-settings input').each(function () { 37662 if (!ctype_print($(this).val())) { 37663 ct = false; 37664 } 37665 ; 37666 }); 37667 if (!ct) { 37668 errors += $.translate('English Only') + '\n'; 37669 } 37670 if (!re.test(email) || email === '') { 37671 emailEl.parent().addClass('has-error'); 37672 errors += $.translate('Email is invalid') + '\n'; 37673 $('#email_f .UIValidators >span').text('Email is invalid'); 37674 } 37675 else { 37676 emailEl.parent().removeClass('has-error'); 37677 } 37678 if (fullName === '' || fullName.length < 5 || fullName.split(' ').length < 2) { 37679 fullNameEl.parent().addClass('has-error'); 37680 errors += $.translate('full name is required') + '\n'; 37681 $('#fullname_f .UIValidators >span').text($.translate('full name is required')); 37682 37683 } 37684 else { 37685 fullNameEl.parent().removeClass('has-error'); 37686 } 37687 if (priPhone === '' || priPhone.length < 13 || !/[0-9\s]+/.test(priPhone)) { 37688 priPhoneEl.parent().addClass('has-error'); 37689 errors += $.translate('Primary phone is required') + '\n'; 37690 $('#phone1_f .UIValidators >span').text($.translate('Primary phone is required')); 37691 37692 } 37693 else { 37694 priPhoneEl.parent().removeClass('has-error'); 37695 } 37696 if (window.isInvalidOptionalPhone(secondaryPhone)) { 37697 secondaryPhoneEl.parent().addClass('has-error'); 37698 errors += $.translate('Secondary phone is invalid') + '\n'; 37699 } else { 37700 secondaryPhoneEl.parent().removeClass('has-error'); 37701 } 37702 if (street === '' || street.length < 2 || !/[0-9]/.test(street)) { 37703 streetEl.parent().addClass('has-error'); 37704 errors += $.translate('Street is required') + '\n'; 37705 $('#addres_f .UIValidators >span').text($.translate('Street is required with house num')); 37706 37707 } 37708 else { 37709 streetEl.parent().removeClass('has-error'); 37710 } 37711 if (city === '' || city.length < 2 || /[0-9]/.test(city)) { 37712 cityEl.parent().addClass('has-error'); 37713 errors += $.translate('City is required') + '\n'; 37714 $('#city_f .UIValidators >span').text($.translate('City is required')); 37715 37716 } 37717 else { 37718 cityEl.parent().removeClass('has-error'); 37719 } 37720 if (zip === '' || zip.length !== 7) { 37721 zipEl.parent().addClass('has-error'); 37722 errors += $.translate('Zip is required') + '\n'; 37723 $('#zip_f .UIValidators >span').text($.translate('Zip is required')); 37724 } else if (window.isInvalidZipCode(zip)) { 37725 zipEl.parent().addClass('has-error'); 37726 errors += $.translate('Zip is invalid') + '\n'; 37727 $('#zip_f .UIValidators >span').text($.translate('Zip is invalid')); 37728 } else { 37729 zipEl.parent().removeClass('has-error'); 37730 } 37731 if (country === '') { 37732 countryEl.parent().addClass('has-error'); 37733 errors += $.translate('Country is required') + '\n'; 37734 } 37735 else { 37736 countryEl.parent().removeClass('has-error'); 37737 } 37738 37739 if(pwd !== ''){ 37740 if (pwd.length < 8 /*|| !stringRe.test(pwd)*/) { 37741 passEl.parent().addClass('has-error'); 37742 if (false/*!stringRe.test(pwd)*/) { 37743 errors += $.translate('password must contain uppercase lowercase and number characters') + '\n'; 37744 } else { 37745 errors += $.translate('password is required') + '\n'; 37746 $('#pass_f .UIValidators >span').text($.translate('password is required')); 37747 } 37748 } else { 37749 passEl.parent().removeClass('has-error'); 37750 } 37751 37752 if (pwd !== pwdConf) { 37753 passConfEl.parent().addClass('has-error'); 37754 passEl.parent().addClass('has-error'); 37755 errors += $.translate('passwords does not match') + '\n'; 37756 $('#pass_f .UIValidators >span').text($.translate('passwords does not match')); 37757 37758 } else { 37759 passConfEl.parent().removeClass('has-error'); 37760 passEl.parent().removeClass('has-error'); 37761 } 37762 } 37763 if (errors !== '') { 37764 $('#update-settings-errors').html(nl2br(errors, true)).removeClass('hidden'); 37765 window.scrollTo(0, 0); 37766 return false;
37767 } 37768 else { 37769 $('#update-settings-errors').addClass('hidden'); 37770 $('#registerSubmit').button('loading'); 37771 $.post($(this).attr('action'), $(this).serialize(), function (data) { 37772 data = JSON.parse(data); 37773 if (data.status === 0) { 37774 $('#update-settings-errors').removeClass('hidden').html(nl2br(data.msg, true)); 37775 $('#update-settings-success').addClass('hidden'); 37776 window.scrollTo(0, 0); 37777 $('#registerSubmit').button('reset'); 37778 } 37779 if (data.status === 1) { 37780 if (undefined !== data.redirect) { 37781 window.location.href = data.redirect; 37782 } 37783 37784 $('#update-settings-success').removeClass('hidden').html(nl2br(data.msg, true)); 37785 $('#update-settings-errors').addClass('hidden'); 37786 window.scrollTo(0, 0); 37787 $('#registerSubmit').button('reset'); 37788 } 37789 }); 37790 } 37791 }); 37792 37793// +St: 37794 function setValuesForInput() { 37795 /*var in_array = $("input[name*='\\[name\\]']"); 37796 $.each( in_array, function(indx, obj) { 37797 var str = $(obj).val(); 37798 str = str.split('.'); 37799 if( str.length > 4 ) { // serv.protocol.[prior].site.dom => serv.prot.site.dom 37800 str_out = str[0] + '.' + str[1]; 37801 for(var i=3; i< str.length;i++) str_out += '.' + str[i]; 37802 $(obj).val( str_out ); 37803 } 37804 });*/ 37805 } 37806// -St 37807 $(document).on('click', '.manage', function (e) { 37808 e.preventDefault(); 37809 var el = $(this); 37810 if (el.is(':disabled') || el.prop('disabled')) { 37811 return; 37812 } 37813 var uid = el.parent().parent().data('uid'); 37814 var url = Storage.getData('app_url') + 'domain/manageDomain/' + uid; 37815 $.getJSON(url, null, function (r) { 37816 if (r.status == 0) { 37817 // alert(r.msg); 37818 //$('#main-content').html(r.msg); 37819 $.fancybox.open({ 37820 content: '<div class="error-fanc">' + r.msg + '</div>', 37821 padding: 0, 37822 37823 }); 37824 } 37825 if (r.status == 1) { 37826 $.fancybox.open({ 37827 content: r.msg, 37828 padding: 0, 37829 type: 'iframe', 37830 afterShow: function () { 37831 37832 $('#ns-reset-default').click(function() { 37833 37834 var rawNs = $('#default-box-ns').text(); 37835 var defaults; 37836 try { 37837 defaults = eval('(' + rawNs + ')'); 37838 } catch(e) { 37839 console.log("Invalid Default NS"); 37840 return; 37841 } 37842 $('#manage-ns-records tbody tr').each(function(i) { 37843 37844 if (defaults[i]) { 37845 $(this).find('input[name$="[ns]"]').val(defaults[i]); 37846 } else { 37847 $(this).find('input[name$="[ns]"]').val(''); 37848 } 37849 37850 $(this).find('input[name$="[ip]"]').val(''); 37851 $(this).find('input[name$="[ipv6]"]').val(''); 37852 }); 37853 $('#ns-reset-default-after-click').removeClass('hide'); 37854 }); 37855 37856 $('#updatens').submit(function (e) { 37857 e.preventDefault(); 37858 $('#save-ns').button('loading'); 37859 $.post(url, $(this).serialize(), function (r) { 37860 r = JSON.parse(r); 37861 if (r.status == 0) { 37862 $.fancybox.close(); 37863 $('#main-content').html(r.msg); 37864 updateUrl(r.title, r.page); 37865 37866 setValuesForInput(); 37867 } 37868 if (r.status == 1) { 37869 $('#domainflash').html(r.msg).removeClass('hidden'); 37870 $.fancybox.close(); 37871 } 37872 if (r.status == 2) { 37873 $('#ns-errors').html(r.msg).removeClass('hidden'); 37874 $('#save-ns').button('reset'); 37875 } 37876 }) 37877 }); 37878 37879 $('#manage-ns-dnssec-add-button').click(function(e) { 37880 e.preventDefault(); 37881 $(this).addClass('hidden'); 37882 $('#manage-ns-dnssec-create-section').removeClass('hidden'); 37883 $('#manage-ns-dnssec-save-button').removeClass('hidden'); 37884 $('#manage-ns-dnssec-cancel-button').removeClass('hidden'); 37885 }); 37886 37887 $('#manage-ns-dnssec-cancel-button').click(function(e) { 37888 e.preventDefault(); 37889 $(this).addClass('hidden'); 37890 $('#manage-ns-dnssec-create-section').addClass('hidden'); 37891 $('#manage-ns-dnssec-save-button').addClass('hidden'); 37892 $('#manage-ns-dnssec-add-button').removeClass('hidden'); 37893 }); 37894 37895 $('#dnssec-create').submit(function (e) { 37896 e.preventDefault(); 37897 $('#manage-ns-dnssec-save-button').button('loading'); 37898 $('#manage-ns-dnssec-cancel-button').prop('disabled', 'disabled'); 37899 37900 $.post($(this).attr('action'), $(this).serialize()) 37901 .done(function (response) { 37902 $('#manage-ns-dnssec-save-button').button('reset'); 37903 $('#manage-ns-dnssec-cancel-button').prop('disabled', false); 37904 $('#manage-ns-dnssec-errors').html('').addClass('hidden'); 37905 $('#dnssec-create').resetForm(); 37906 37907 let emptyRow = $('#manage-ns-dnssec-records .manage-ns-dnssec-record-empty'); 37908 37909 if (0 !== emptyRow.length) { 37910 emptyRow.remove(); 37911 } 37912 37913 $('#manage-ns-dnssec-cancel-button').click(); 37914 37915 if (0 === $('#manage-ns-dnssec-records > tbody > tr').length) { 37916 $('#manage-ns-dnssec-records > tbody').append(response.tableRow); 37917 } else { 37918 $(response.tableRow).insertBefore('#manage-ns-dnssec-records > tbody > tr:first'); 37919 } 37920 }) 37921 .fail(function(response) { 37922 if (403 === response.status) { 37923 window.location.href = '/user/login'; 37924 } 37925 37926 $('#manage-ns-dnssec-errors').html(response.responseJSON.error).removeClass('hidden'); 37927 $('#manage-ns-dnssec-save-button').button('reset'); 37928 $('#manage-ns-dnssec-cancel-button').prop('disabled', false) 37929 }) 37930 }); 37931 37932 $('#manage-ns-dnssec-records').on('click', '.manage-ns-dnssec-record-delete', function(e) { 37933 e.preventDefault(); 37934 37935 let link = $(this); 37936 37937 $.ajax({ 37938 url: link.attr('href'), 37939 type: 'DELETE', 37940 success: function(response) { 37941 link.parent().parent().remove(); 37942 $('#manage-ns-dnssec-base-errors').html('').addClass('hidden'); 37943 37944 if (0 === response.totalRows) { 37945 $('#manage-ns-dnssec-records > tbody').append(response.emptyRow); 37946 } 37947 }, 37948 error: function(xhr) { 37949 if (403 === xhr.status) { 37950 window.location.href = '/user/login'; 37951 } 37952 37953 $('#manage-ns-dnssec-base-errors').html(xhr.responseJSON.error).removeClass('hidden'); 37954 } 37955 }); 37956 }); 37957 37958 } 37959 }); 37960 } 37961 setValuesForInput(); 37962 }); 37963 }); 37964 37965 $(document).on('click', '.enom-raa-resend', function (e) { 37966 e.preventDefault(); 37967 var el = $(this); 37968 if (el.is(':disabled') || el.data('busy')) { 37969 return; 37970 } 37971 37972 var uid = el.data('uid') || el.closest('tr').data('uid'); 37973 if (!uid) { 37974 return; 37975 } 37976 37977 var url = el.data('url') || (Storage.getData('app_url') + 'domain/enom-raa-resend/' + uid); 37978 37979 el.data('busy', true).prop('disabled', true); 37980 37981 $.ajax({ 37982 url: url, 37983 type: 'POST', 37984 dataType: 'json' 37985 }).done(function (r) { 37986 var msg = (r && r.msg) ? r.msg : ''; 37987 if (r && r.status == 1) { 37988 $.showSuccess(r.title || $.translate('Success'), msg, false, true); 37989 } else { 37990 $.showError(msg || $.translate('Failed to resend verification email. Please contact support.')); 37991 } 37992 }).fail(function () { 37993 $.showError($.translate('Failed to resend verification email. Please contact support.')); 37994 }).always(function () { 37995 el.data('busy', false).prop('disabled', false); 37996 }); 37997 }); 37998 37999 $(document).on('click', '#transfer', function (e) { 38000 e.preventDefault(); 38001 $.get(Storage.getData('app_url') + 'domain/transferDomain', function (r) { 38002 $.fancybox.open({ 38003 content: r, 38004 type: 'iframe', 38005 padding: 0, 38006 afterShow: function () { 38007 $('.show-tooltip').addTooltip(); 38008 38009 $('.panel-default a').click(function () { 38010 $('.collapse').collapse('toggle'); 38011 }) 38012 var btn = $('#transfer-domain'); 38013 $('#transfer-domain').click(function (e) { 38014 var sld = $('#domain-sld').val(); 38015 var tld = $('#domain-tld').val(); 38016 var admin = $('#ownerTransfer').val(); 38017 var tech = $('#techTransfer').val(); 38018 var zone = $('#adminTransfer').val(); 38019 var form = $(this).closest('form'); 38020 38021 btn.button('loading'); 38022 e.preventDefault(); 38023 38024 var csrfConfig = Storage.getData('csrf_config'); 38025 var data = {
38026 sld: sld, 38027 tld: tld, 38028 admin: admin, 38029 adminIsoc: $('option[value="' + admin + '"]').data('isoc-id'), 38030 tech: tech, 38031 techIsoc: $('option[value="' + tech + '"]').data('isoc-id'), 38032 zone: zone, 38033 zoneIsoc: $('option[value="' + zone + '"]').data('isoc-id'), 38034 eppCode: $('#domain-transfer-isoc-epp').val() 38035 }; 38036 38037 38038 data[csrfConfig['token_name_key']] = form.find('[name=csrf_token_name]').val(); 38039 data[csrfConfig['token_key']] = form.find('[name=csrf_token]').val(); 38040 38041 $.post(Storage.getData('app_url') + 'domain/transferDomain', data, function (r) { 38042 r = JSON.parse(r); 38043 if (r.status == 0) { 38044 $('#transfer-modal-error').html(r.msg).removeClass('hidden'); 38045 $('button').button('reset'); 38046 } 38047 if (r.status == 1) { 38048 $.fancybox.close(); 38049 $('#mDomains').click(); 38050 $('#domainflash').html(r.msg).removeClass('hidden'); 38051 } 38052 }); 38053 }); 38054 var transferSubmitting = false; 38055 $('#transfer-enom-domain').click(function (e) { 38056 e.preventDefault(); 38057 if (transferSubmitting) return; 38058 $('#transfer-modal-error').addClass('hidden'); 38059 $('#transfer-enom-domain').button('loading'); 38060 var creditReg = /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|6(?:011|5[0-9]{2})[0-9]{12}|(?:2131|1800|35\d{3})\d{11})$/; 38061 var creditCardEl = $('#creditNumber'); 38062 var creditYrEl = $('#creditExpirationYear'); 38063 var creditMoEl = $('#creditExpirationMonth'); 38064 var creditCardCvvEl = $('#creditCvv'); 38065 var creditIdEl = $('#creditId'); 38066 var date = new Date(); 38067 var creditCard = creditCardEl.val(); 38068 var creditCardYr = creditYrEl.val(); 38069 var creditCardMo = creditMoEl.val(); 38070 var creditCardCvv = creditCardCvvEl.val(); 38071 var creditCardId = creditIdEl.val(); 38072 var approve_termsEl = $('#approve_terms'); 38073 var approve_terms = approve_termsEl.is(":checked"); 38074 var errors = ''; 38075 if ($('[name="enomDomainTransfer"]').val() == '' || $('[name="enomDomainTransfer"]').val().split('.').length < 2) { 38076 errors += $.translate('You must enter domain name') + '\n'; 38077 } 38078 if ($('[name="domainEPPTransfer"]').val() == '' || !enom_ctype_print($('[name="domainEPPTransfer"]').val())) { 38079 errors += $.translate('You must enter valid EPP code') + '\n'; 38080 } 38081 var enomOwnerTransferEl = $('#enomOwnerTransfer'); 38082 if (!enomOwnerTransferEl.val() || enomOwnerTransferEl.val() == '') { 38083 enomOwnerTransferEl.parent().addClass('has-error'); 38084 errors += $.translate('You must select a contact') + '\n'; 38085 } else { 38086 enomOwnerTransferEl.parent().removeClass('has-error'); 38087 } 38088 if (!approve_terms) { 38089 approve_termsEl.parent().addClass('has-error'); 38090 errors += $.translate('Approve Terms is required') + '\n'; 38091 } 38092 else { 38093 approve_termsEl.parent().removeClass('has-error'); 38094 } 38095 if (isNaN(creditCardYr) || parseInt(creditCardYr) < date.getFullYear()) { 38096 creditYrEl.parent().addClass('has-error'); 38097 errors += $.translate('Expiry Year is invali
38097d'); 38098 } 38099 else { 38100 creditYrEl.parent().removeClass('has-error'); 38101 } 38102 if (isNaN(creditCardMo) || creditCardYr == date.getFullYear() && creditCardMo < date.getMonth()) { 38103 creditMoEl.parent().addClass('has-error'); 38104 errors += $.translate('Expiry Month is invalid') + '\n'; 38105 } 38106 else { 38107 creditMoEl.parent().removeClass('has-error'); 38108 } 38109 if (isNaN(creditCardCvv) || creditCardCvv.length < 3 || creditCardCvv.length > 4) { 38110 creditCardCvvEl.parent().addClass('has-error'); 38111 errors += $.translate('cvv is invalid') + '\n'; 38112 } 38113 else { 38114 creditCardCvvEl.parent().removeClass('has-error'); 38115 } 38116 if (isNaN(creditCardId) || creditCardId.length < 9 || creditCardId.length > 9) { 38117 creditIdEl.parent().addClass('has-error'); 38118 errors += $.translate('id is invalid') + '\n'; 38119 } 38120 else { 38121 creditIdEl.parent().removeClass('has-error'); 38122 } 38123 if (isNaN(creditCard) || creditCard.length < 9 || creditCard.length > 17 || !creditReg.test(creditCard) && creditCard.length > 9 || creditCard[0] === 0) { 38124 creditCardEl.parent().addClass('has-error'); 38125 errors += $.translate('card is invalid') + '\n'; 38126 } 38127 else { 38128 creditCardEl.parent().removeClass('has-error'); 38129 } 38130 if (errors != '') { 38131 $('#transfer-modal-error').html(nl2br(errors)).removeClass('hidden'); 38132 $('#transfer-enom-domain').button('reset'); 38133 } else { 38134 transferSubmitting = true; 38135 $.post(Storage.getData('app_url') + 'domain/transferEnom', $('#transferForm').serialize(), function (r) { 38136 r = JSON.parse(r); 38137 if (r.status == 0) { 38138 transferSubmitting = false; 38139 $('#transfer-modal-error').html(nl2br(r.msg)).removeClass('hidden'); 38140 $('#transfer-enom-domain').button('reset'); 38141 } 38142 if (r.status == 1) { 38143 $('#domainflash').html(nl2br(r.msg)).removeClass('hidden'); 38144 $('#transfer-enom-domain').button('reset'); 38145 $.fancybox.close(); 38146 } 38147 }).fail(function () { 38148 transferSubmitting = false; 38149 $('#transfer-enom-domain').button('reset'); 38150 }); 38151 } 38152 }) 38153 } 38154 }); 38155 }); 38156 }); 38157 $(document).on('click', '#isLockCheck', function (e) { 38158 e.preventDefault(); 38159 var domain = ''; 38160 38161 if ($('#collapseEnom').hasClass('in')) { 38162 domain = $('#enomDomainTransfer').val(); 38163 } 38164 38165 if ($('#israeliTranCollapse').hasClass('in') && '' !== $('#domain-sld').val()) { 38166 domain = $('#domain-sld').val() + '.' + $('#domain-tld').val(); 38167 } 38168 38169 if ('' === domain) { 38170 return; 38171 } 38172 38173 var url = $(this).attr('href'); 38174 38175 $('#isLockRes').html('').addClass('hidden'); 38176 if (domain == '') { 38177 $('#transfer-modal-error').html($.translate('please fill domain')).removeClass('hidden'); 38178 //alert(appLocale['please fill domain']); 38179 return false;
38180 } 38181 $('#transfer-modal-error').addClass('hidden'); 38182 $.getJSON(url + domain, function (r) { 38183 if (r.status == 0) { 38184 //alert(r.msg); 38185 $('#transfer-modal-error').html(r.msg).removeClass('hidden'); 38186 } 38187 if (r.status == 1) { 38188 $('#isLockRes').html(r.msg).removeClass('hidden'); 38189 } 38190 }); 38191 }); 38192 38193 /** 38194 $(document).on('click', '.lock', function (e) { 38195 e.preventDefault(); 38196 var el = $(this); 38197 var uid = el.parent().parent().data('uid'); 38198 var url = Storage.getData('app_url') + 'domain/lockDomain/' + uid; 38199 $.getJSON(url, null, function (r) { 38200 if (r.status == 0) { 38201 $('#main-content').html(r.msg); 38202 } 38203 if (r.status == 1) { 38204 $.fancybox.open({ 38205 content: r.msg, 38206 padding: 0, 38207 type: 'iframe', 38208 afterShow: function () { 38209 var btn = $('#save-lock'); 38210 $('#updatelock').submit(function (e) { 38211 e.preventDefault(); 38212 btn.button('loading'); 38213 38214 var data = { 38215 lockstate: $('input[name="lockstate"]:checked').val() 38216 }; 38217 38218 var csrfConfig = Storage.getData('csrf_config'); 38219 38220 data[csrfConfig['token_name_key']] = $(this).find('[name=csrf_token_name]').val(); 38221 data[csrfConfig['token_key']] = $(this).find('[name=csrf_token]').val(); 38222 38223 $.post(url, data, function (r) { 38224 r = JSON.parse(r); 38225 if (r.status == 0) { 38226 $('#main-content').html(r.msg); 38227 $.fancybox.close(); 38228 } 38229 if (r.status == 1) { 38230 alert(r.msg); 38231 $.fancybox.close(); 38232 } 38233 }); 38234 }); 38235 } 38236 }); 38237 } 38238 }); 38239 }); 38240 */ 38241 38242 38243 38244 $(document).on('click', '.renew', function (e) { 38245 e.preventDefault(); 38246 var el = $(this); 38247 var uid = el.parent().parent().data('uid'); 38248 var url = Storage.getData('app_url') + 'domain/renewDomain/' + uid; 38249 $.getJSON(url, null, function (r) { 38250 if (r.status == 0) { 38251 $('#main-content').html(r.msg); 38252 } 38253 if (r.status == 1) { 38254 $.fancybox.open({ 38255 content: r.msg, 38256 padding: 0, 38257 type: 'iframe', 38258 afterShow: function () { 38259 $('.show-tooltip').addTooltip(); 38260 }, 38261 beforeClose: function () { 38262 $('#domain-renew-confirm-pending').modal('hide'); 38263 } 38264 }); 38265 } 38266 }); 38267 }); 38268 38269 $('#main-content.page-domain-renew #renew-domain .cvvhelp').hover(function () { 38270 $(this).find('img').show(); 38271 }, function () { 38272 $(this).find('img').hide(); 38273 }); 38274 38275 var renewSubmitting = false; 38276 $(document).on('click', '#renew-domain #renew', function(e) { 38277 if (renewSubmitting) return; 38278 $(this).button('loading'); 38279 }); 38280 38281 $(document).on('click', '#domain-renew-confirm-confirm', function() { 38282 $('#domain-renew-confirm-pending').modal('hide'); 38283 $('#domain-renew-pending-confirmed').val(1); 38284 $('#renew').trigger('click'); 38285 }); 38286 38287 $(document).on('click', '#domain-renew-confirm-cancel', function() { 38288 $('#domain-renew-confirm-pending').modal('hide'); 38289 }); 38290 38291 $(document).on('submit', '#renew-domain', function (e) { 38292 var btn = $('#renew'); 38293 e.preventDefault(); 38294 38295 // d0ger easy 38296 var creditReg = /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|6(?:011|5[0-9]{2})[0-9]{12}|(?:2131|1800|35\d{3})\d{11})$/; 38297 var creditCardEl = $('#creditNumber'); 38298 var creditYrEl = $('#creditExpirationYear'); 38299 var creditMoEl = $('#creditExpirationMonth');
38300 var creditCardCvvEl = $('#creditCvv'); 38301 var creditIdEl = $('#creditId'); 38302 var domainPeriodEl = $('#domainPeriod'); 38303 var date = new Date(); 38304 var creditCard = creditCardEl.val(); 38305 var creditCardYr = creditYrEl.val(); 38306 var creditCardMo = creditMoEl.val(); 38307 var creditCardCvv = creditCardCvvEl.val(); 38308 var creditCardId = creditIdEl.val(); 38309 var domainPeriod = parseInt($('[name=domainPeriod]:checked').val()); 38310 var approve_termsEl = $('#approve_terms'); 38311 var approve_terms = approve_termsEl.is(":checked"); 38312 var errors = ''; 38313 if(approve_terms != undefined) { 38314 if (!approve_terms) { 38315 approve_termsEl.parent().addClass('has-error'); 38316 errors += $.translate('Approve Terms is required') + '\n'; 38317 //$('#zip_f .UIValidators >span').text(appLocale['Approve Terms is required']); 38318 } 38319 else { 38320 approve_termsEl.parent().removeClass('has-error'); 38321 } 38322 } 38323 38324 if (isNaN(creditCardYr) || parseInt(creditCardYr) < date.getFullYear()) { 38325 creditYrEl.parent().addClass('has-error'); 38326 errors += $.translate('Expiry Year is invalid'); 38327 } 38328 else { 38329 creditYrEl.parent().removeClass('has-error'); 38330 } 38331 if (isNaN(creditCardMo) || creditCardYr == date.getFullYear() && creditCardMo < date.getMonth()) { 38332 creditMoEl.parent().addClass('has-error'); 38333 errors += $.translate('Expiry Month is invalid') + '\n'; 38334 } 38335 else { 38336 creditMoEl.parent().removeClass('has-error'); 38337 } 38338 if (isNaN(creditCardCvv) || creditCardCvv.length < 3 || creditCardCvv.length > 4) { 38339 creditCardCvvEl.parent().addClass('has-error'); 38340 errors += $.translate('cvv is invalid') + '\n'; 38341 } 38342 else { 38343 creditCardCvvEl.parent().removeClass('has-error'); 38344 } 38345 if (isNaN(creditCardId) || creditCardId.length < 9 || creditCardId.length > 9) { 38346 creditIdEl.parent().addClass('has-error'); 38347 errors += $.translate('id is invalid') + '\n'; 38348 } 38349 else { 38350 creditIdEl.parent().removeClass('has-error'); 38351 } 38352 if (isNaN(creditCard) || creditCard.length < 9 || creditCard.length > 17 || !creditReg.test(creditCard) && creditCard.length > 9 || creditCard[0] === 0) { 38353 creditCardEl.parent().addClass('has-error'); 38354 errors += $.translate('card is invalid') + '\n'; 38355 } 38356 else { 38357 creditCardEl.parent().removeClass('has-error'); 38358 } 38359 if (domainPeriod < 1 && domainPeriod > 5) { 38360 domainPeriodEl.parent().addClass('has-error'); 38361 errors += $.translate('Domain Period is invalid') + '\n'; 38362 } 38363 else { 38364 domainPeriodEl.parent().removeClass('has-error'); 38365 } 38366 if (errors !== '') { 38367 $('#renew-errors').html(nl2br(errors, true)).removeClass('hidden'); 38368 btn.button('reset'); 38369 return false; 38370 } else { 38371 $('#renew-errors').addClass('hidden'); 38372 } 38373 renewSubmitting = true; 38374 var uid = $('#renew-domain').data('uid'); 38375 var url = Storage.getData('app_url') + 'domain/renewDomain/' + uid; 38376 var postData = $(this).serialize(); 38377 38378 postData['destination'] = '/user/account'; 38379 38380 $.ajax({ 38381 url: url, 38382 data: postData, 38383 type: 'post', 38384 error: function(XMLHttpRequest, textStatus, errorThrown){ 38385 renewSubmitting = false; 38386 btn.button('reset'); 38387 window.location.href = '/user/login'; 38388 }, 38389 success: function (r) { 38390 if (r.status == 0) { 38391 if(undefined != r.premiumPrice) { 38392 // show warning 38393 $('#renew-domain-is-premium').removeClass('hidden').html(r.msg); 38394 38395 // update form 38396 $('#domain-purchase-is-premium').val(1); 38397 38398 // update price 38399 var priceEl = $('#renew-domain').find('span.UIInfoTitle'); 38400 38401 for (var year in r.premiumPrice) { 38402 priceEl.attr('data-price-{0}'.format(year), r.premiumPrice[year]); 38403 } 38404 38405 var period = parseInt($('#renew-domain input[name=domainPeriod]:checked').val()); 38406 var price = 0; 38407 38408 // update total price 38409 for (var i = 1; i < period + 1; i++) { 38410 var yearPrice = priceEl.attr('data-price-{0}'.format(i)); 38411 38412 if (undefined !== yearPrice) { 38413 price += parseFloat(yearPrice); 38414 } 38415 } 38416 38417 priceEl.find('span').html(Number(price).toFixed(2)); 38418 38419 var checked = $('#renew-domain input[name=domainPeriod]:checked'); 38420 $('#renew-domain input[name=domainPeriod]:first').trigger('click'); 38421 38422 if (checked.length > 0) { 38423 checked.trigger('click'); 38424 } 38425 38426 $('#couponCode').val(''); 38427 $('#cpnDis').addClass('hidden'); 38428 } else if ( 38429 undefined !== r.format 38430 && undefined !== r.type 38431 && 'popin' === r.format 38432 && 'pendingRenew' === r.type 38433 ) { 38434 if (0 !== $('#domain-renew-confirm-pending').length) { 38435 $('#domain-renew-confirm-pending').modal('show'); 38436 } else { 38437 $(r.msg).modal('show'); 38438 } 38439 } else { 38440 if(typeof undefined === typeof r.destination) { 38441 $('#renew-errors').html(nl2br(r.msg, true)).removeClass('hidden'); 38442 } else { 38443 window.location.href = r.destination; 38444 } 38445 } 38446 38447 renewSubmitting = false;
38448 $('#renew').button('reset'); 38449 } 38450 38451 if (r.status == 1) { 38452 $('#domainflash').html(nl2br(r.msg, true)).removeClass('hidden'); 38453 $.fancybox.close(); 38454 38455 $.fancybox.open({ 38456 content: r.msg, 38457 padding: 0, 38458 type: 'iframe', 38459 afterShow: function () { 38460 var btn = $('#good_renew'); 38461 btn.click(function(){ 38462 $.fancybox.close(); 38463 38464 if(typeof undefined === typeof r.destination) { 38465 window.location.href = window.location.href; 38466 } else { 38467 window.location.href = r.destination; 38468 } 38469 38470 }); 38471 }, 38472 afterClose: function () { 38473 if(typeof undefined === typeof r.destination) { 38474 window.location.href = window.location.href; 38475 } else { 38476 window.location.href = r.destination; 38477 } 38478 } 38479 }); 38480 } 38481 } 38482 }); 38483 }); 38484 38485 /*main menu*/ 38486 $('.menu>ul>li').mouseenter(function () { 38487 $('.menu>ul>li').find('.sub-menu').stop().fadeOut(); 38488 38489 var el = $(this); 38490 38491 el.addClass('active').find('.sub-menu').fadeIn(); 38492 38493 // setTimeout(function() { 38494 // 38495 // }, 300); 38496 }); 38497 38498 $('.menu>ul>li').mouseleave(function () { 38499 var el = $(this); 38500 $('.menu>ul>li').find('.sub-menu').stop().hide(); 38501 38502 el.removeClass('active').find('.sub-menu').fadeOut(); 38503 }); 38504 38505 // Mobile Menu Click* 38506 $(document).on('click','#mobileMenu > li > a',function(){ 38507 $('.sub-menu').fadeOut(); 38508 if($(this).parent().hasClass('active')){ 38509 $(this).parent().removeClass('active'); 38510 }else{ 38511 $(this).parent().addClass('active'); 38512 $(this).parent().find('.sub-menu').fadeIn(); 38513 } 38514 38515 }) 38516 38517 38518 $(".fancybox-video").click(function () { 38519 $.fancybox({ 38520 'padding': 0, 38521 'autoScale': false, 38522 'transitionIn': 'none', 38523 'transitionOut': 'none', 38524 'title': this.title, 38525 'width': 640, 38526 'height': 385, 38527 'href': this.href.replace(new RegExp("watch\\?v=", "i"), 'v/'), 38528 'type': 'swf', 38529 'swf': { 38530 'wmode': 'transparent', 38531 'allowfullscreen': 'true' 38532 } 38533 }); 38534 38535 return false; 38536 }); 38537 38538 $(document).on('change', '#renew-domain input[name=domainPeriod]', function () { 38539 var title = $('#renew-domain').find('span.UIInfoTitle'), 38540 // price = parseFloat(title.data('price')), 38541 // secondPrice = parseFloat(title.data('second-price')), 38542 price = 0, 38543 period = parseInt($(this).val()), 38544 creDetails = $('#creditDetails'); 38545 38546 38547 $('#creditExpirationYear').find('option').eq(0).prop('selected', true); 38548 $('#creditExpirationMonth').find('option').eq(0).prop('selected', true); 38549 $('#creditCvv').val(''); 38550 $('#creditId').val(''); 38551 $('#creditNumber').val(''); 38552 $('#cpn-error').addClass('hidden'); 38553 $('#cpnDis').addClass('hidden'); 38554 creDetails.find('input[type=text]').parent().show(); 38555 creDetails.find('select').parent().show(); 38556 $('#checkCoupon').prop('disabled', false); 38557 38558 // update total price 38559 for (var i = 1; i < period + 1; i++) { 38560 var yearPrice = title.attr('data-price-{0}'.format(i)); 38561 38562 if (undefined !== yearPrice) { 38563 price += parseFloat(yearPrice); 38564 } 38565 } 38566 38567 title.find('span').html(Number(price).toFixed(2)); 38568 }); 38569 38570 $(document).on('keyup', '#enomDomainTransfer', function () { 38571 $('#enomPricing').hide() 38572 }); 38573 38574 $(document).on('click', '#enomCalculatePrice', function (e) { 38575 e.preventDefault(); 38576 $('#transfer-modal-error').addClass('hidden'); 38577 $('#enomPricing').hide(); 38578 $('#enomCalculatePrice').button('loading'); 38579 38580 var csrfConfig = Storage.getData('csrf_config'); 38581 var form = $(this).closest('form'); 38582 var data = { 38583 enomDomainTransfer: $('#enomDomainTransfer').val() 38584 }; 38585 38586 38587 data[csrfConfig['token_name_key']] = form.find('[name=csrf_token_name]').val(); 38588 data[csrfConfig['token_key']] = form.find('[name=csrf_token]').val(); 38589 38590 $.post(Storage.getData('app_url') + 'domain/enomcheck', data, function (r) { 38591 r = JSON.parse(r); 38592 if (r.status == 0) { 38593 $('#transfer-modal-error').html(nl2br(r.msg, true)).removeClass('hidden'); 38594 $('#enomCalculatePrice').button('reset'); 38595 } 38596 if (r.status == 1) { 38597 $('#domainBasePricing .amount').html(r.msg); 38598 $('#enomPricing').show(); 38599 $('#enomCalculatePrice').button('reset'); 38600 $('.show-tooltip').addTooltip(); 38601 } 38602 }) 38603 }); 38604 38605 $(document).on('click', '#enomPricing #checkCoupon', function (e) { 38606 e.preventDefault(); 38607 var cpn = $('#couponCode').val(); 38608 $('#cpn-error').addClass('hidden'); 38609 //$('#cpnDis').addClass('hidden'); 38610 $(this).button('loading'); 38611 $('#creditDetails input[type=text]').parent().show(); 38612 $('#creditDetails select').parent().show(); 38613 $('#creditNumber').val('').trigger('change').trigger('keyup.jccv'); 38614 $('#creditExpirationYear option').eq(0).prop('selected', true); 38615 $('#creditExpirationMonth option').eq(0).prop('selected', true);
38616 $('#creditCvv').val(''); 38617 $('#creditId').val(''); 38618 $.get(Storage.getData('app_url') + 'checkCpn/' + cpn, '', function (r) { 38619 r = parseFloat(r); 38620 if (r <= 0) { 38621 $('#cpn-error').removeClass('hidden'); 38622 $('#cpnDis').addClass('hidden'); 38623 } else { 38624 $('#cpn-error').addClass('hidden'); 38625 var price = $('#domainBasePricing span').html(); 38626 var dis = price - r; 38627 if (dis <= 0) { 38628 dis = 0; 38629 $('#creditDetails input[type=text]').parent().hide(); 38630 $('#creditDetails select').parent().hide(); 38631 $('#creditNumber').val('378282246310005'); 38632 $('#creditExpirationYear').val(new Date().getFullYear() + 5); 38633 $('#creditExpirationMonth').val(12); 38634 $('#creditCvv').val(123); 38635 $('#creditId').val(123456789); 38636 } 38637 $('.amount').html(price); 38638 $('.sum').html(Number(dis).toFixed(2)) 38639 $('#cpnDis').removeClass('hidden'); 38640 } 38641 $('#checkCoupon').button('reset'); 38642 }); 38643 $('#checkCoupon').button('reset'); 38644 }); 38645 $(document).on('click', '#search', function (e) { 38646 e.preventDefault(); 38647 var q = $.getQueryParameters(); 38648 var sq = $('#sq').val(); 38649 var baseUrl = document.location.href.replace(window.location.search, '?'); 38650 q.q = sq; 38651 if (sq == '') { 38652 delete q.q; 38653 } 38654 document.location.replace(baseUrl + $.param(q)); 38655 }); 38656 38657 // this code was inlined in main.php file 38658 // cc card validation callback 38659 if($('#creditNumber.validate').length) { 38660 $('#creditNumber.validate').validateCreditCard(function (result) { 38661 var input = $(this); 38662 var type = null == result.card_type ? 'type-none' : 'type-' + result.card_type.name; 38663 var cvv = input.closest('form').find('#creditCvv.validate'); 38664 38665 // set classes 38666 input.removeClassPrefix('type-'); 38667 input.addClass(type); 38668 result.valid ? input.addClass('valid') : input.removeClass('valid'); 38669 38670 // set cvv length 38671 if(cvv.length > 0) { 38672 var maxLen = null != result.card_type && 'amex' == result.card_type.name ? 4 : 3; 38673 cvv.attr('maxlength', maxLen); 38674 } 38675 }); 38676 } 38677 38678 $(document).on('click', '#admin-domain-sent-owner-verify-email', function (e) { 38679 e.preventDefault(); 38680 38681 var el = $(this); 38682 38683 $.ajax({ 38684 url: el.attr('href'), 38685 type: 'POST', 38686 data: { 38687 'email': $('#ownerEmail').val() 38688 }, 38689 success: function (response) { 38690 if (0 == response.status) { 38691 $('#admin-domain-sent-owner-verify-email-errors').html(nl2br(response.msg, true)).removeClass('hidden'); 38692 } 38693 38694 if (1 == response.status) { 38695 38696 console.log('OPA'); 38697 console.log('OPA'); 38698 console.log(el.attr('data-destination')); 38699 console.log(el.data('destination')); 38700 38701 window.location.href = el.attr('data-destination'); 38702 } 38703 }, 38704 error: function (xhr) { 38705 if (403 === xhr.status) { 38706 window.location.href = '/user/login'; 38707 } 38708 38709 $('#admin-domain-sent-owner-verify-email-errors').html(xhr.responseJSON.error).removeClass('hidden'); 38710 } 38711 }); 38712 }); 38713 38714 const $dropdown_support = $("#supportMenu-dropDown"); 38715 const $icon_support = $('#supportMenu i'); 38716 $('#supportMenu').on('click', function () { 38717 if ($dropdown_support.is(':visible')) { 38718 $dropdown_support.slideUp(150); 38719 $icon_support.removeClass('fa-chevron-up').addClass('fa-chevron-down'); 38720 }else{ 38721 $dropdown_support.slideDown(150); 38722 $icon_support.removeClass('fa-chevron-down').addClass('fa-chevron-up'); 38723 }
38724 $("#manageMenu-dropDown").slideUp(150); 38725 $('#manageMenu i').removeClass('fa-chevron-up').addClass('fa-chevron-down'); 38726 38727 }); 38728 38729 const $dropdown_manage = $("#manageMenu-dropDown"); 38730 const $icon_manage = $('#manageMenu i'); 38731 $('#manageMenu').on('click', function () { 38732 if ($dropdown_manage.is(':visible')) { 38733 $dropdown_manage.slideUp(150); 38734 $icon_manage.removeClass('fa-chevron-up').addClass('fa-chevron-down'); 38735 }else{ 38736 $dropdown_manage.slideDown(150); 38737 $icon_manage.removeClass('fa-chevron-down').addClass('fa-chevron-up'); 38738 } 38739 $("#supportMenu-dropDown").slideUp(150); 38740 $('#supportMenu i').removeClass('fa-chevron-up').addClass('fa-chevron-down'); 38741 }); 38742 38743 $(document).on('click', function (e) { 38744 // ×× ×××××¦× ×× ××××ª× ×ת×× #supportMenu ×× #supportMenu-dropDown 38745 if (!$(e.target).closest('#supportMenu, #supportMenu-dropDown').length) { 38746 $("#supportMenu-dropDown").slideUp(150); 38747 $('#supportMenu i').removeClass('fa-chevron-up').addClass('fa-chevron-down'); 38748 } 38749 38750 // ×× ×××××¦× ×× ××××ª× ×ת×× #manageMenu ×× #manageMenu-dropDown 38751 if (!$(e.target).closest('#manageMenu, #manageMenu-dropDown').length) { 38752 $("#manageMenu-dropDown").slideUp(150); 38753 $('#manageMenu i').removeClass('fa-chevron-up').addClass('fa-chevron-down'); 38754 } 38755 }); 38756 38757 // tooltips 38758 $('.show-tooltip').addTooltip(); 38759 38760 function isValidIPv4(ip) { 38761 return /^((25[0-5]|2[0-4][0-9]|1\d{2}|[1-9]?\d)\.){3}(25[0-5]|2[0-4][0-9]|1\d{2}|[1-9]?\d)$/.test(ip); 38762 } 38763 function isValidIPv6(ip) { 38764 return /^(([0-9a-fA-F]{1,4}):){7}([0-9a-fA-F]{1,4})$/.test(ip); 38765 } 38766 function isValidSubdomain(sub, allowUnderscore = false) { 38767 if (!sub) return true; // ר××§ ×× ×ª×§×£ ×× ××פצ××× ×× 38768 if (sub === '' || sub === '*' || sub === '@') return true; // allow just * or just @ 38769 const labels = sub.split('.'); 38770 38771 return labels.every(label => { 38772 if (!label || label.length > 63) return false; 38773 if (label.startsWith('-') || label.endsWith('-')) return false; 38774 38775 const pattern = allowUnderscore 38776 ? /^[\p{L}\p{N}_-]+$/u // ×ת×ר ×× _ 38777 : /^[\p{L}\p{N}-]+$/u; // ×× ×ת×ר _ 38778 38779 return pattern.test(label); 38780 }); 38781 } 38782 38783 38784 function isValidFullDomain(domain, allowUnderscore = false) { 38785 if (!domain) return false; 38786 38787 domain = domain.trim(); 38788 domain = domain.replace(/\.$/, ''); 38789 38790 const labels = domain.split('.'); 38791 38792 // ×ר××©× ××©× ×××××× ××× (×פ××ת 2 ת××××ת: ס××+TLD) 38793 if (labels.length < 2) return false; 38794 38795 // ×פשר ×× ×××××§ ש×××¨× ×××× < 255 ת×××× ×× ×¨×צ×× 38796 38797 return labels.every(label => { 38798 if (!label || label.length > 63) return false; 38799 if (label.startsWith('-') || label.endsWith('-')) return false; 38800 38801 const pattern = allowUnderscore 38802 ? /^[\p{L}\p{N}_-]+$/u 38803 : /^[\p{L}\p{N}-]+$/u; 38804 38805 return pattern.test(label); 38806 }); 38807 } 38808 38809 function isValidURL(url) { 38810 try { 38811 const parsed = new URL(url); 38812 38813 // ××××§× ×©×פר××××§×× ×××§× (http/https ×××× ××××××) 38814 if (!['http:', 'https:'].includes(parsed.protocol)) { 38815 return false; 38816 } 38817 38818 // ××× ×©×Ö¾hostname ×××× ×פ××ת ×××××× ××× (××× ×¨×§ "http://") 38819 if (!parsed.hostname || parsed.hostname.length < 1) { 38820 return false; 38821 } 38822 38823 return true; 38824 } catch (e) { 38825 return false; 38826 } 38827 } 38828 38829 function sanitizeSearchValue(value) { 38830 if (!value) { 38831 return ''; 38832 } 38833 38834 return String(value) 38835 .replace(/[\u200E\u200F\u202A-\u202E\u2066-\u2069\u200B-\u200D\uFEFF\u00AD]/g, '') 38836 .replace(/[\u0000-\u001F\u007F]/g, '') 38837 .replace(/\u00A0/g, ' ') 38838 .trim(); 38839 } 38840 38841 function cleanQueryParamInUrl(paramName, input) { 38842 if (!window.URL || !window.URLSearchParams) { 38843 return; 38844 } 38845 38846 var currentUrl = new URL(window.location.href); 38847 var currentValue = currentUrl.searchParams.get(paramName); 38848 38849 if (currentValue === null) { 38850 return; 38851 } 38852 38853 var cleanValue = sanitizeSearchValue(currentValue); 38854 38855 if (cleanValue !== currentValue) { 38856 if (cleanValue) { 38857 currentUrl.searchParams.set(paramName, cleanValue); 38858 } else { 38859 currentUrl.searchParams.delete(paramName); 38860 } 38861 38862 window.history.replaceState({}, '', currentUrl.toString()); 38863 } 38864 38865 if (input) { 38866 input.value = cleanValue; 38867 } 38868 } 38869 38870 function bindSearchSanitizer(form, options) { 38871 if (!form) { 38872 return; 38873 } 38874 38875 options = options || {}; 38876 38877 var queryParamName = options.queryParamName || 'q'; 38878 var inputSelector = options.inputSelector || 'input[name="' + queryParamName + '"]'; 38879 var input = form.querySelector(inputSelector); 38880 38881 cleanQueryParamInUrl(queryParamName, input); 38882 38883 if (!input) { 38884 return; 38885 } 38886 38887 form.addEventListener('submit', function () { 38888 input.value = sanitizeSearchValue(input.value); 38889 }); 38890 } 38891 38892 // Reusable API for other pages/forms. 38893 window.SearchSanitizer = window.SearchSanitizer || {}; 38894 window.SearchSanitizer.sanitize = sanitizeSearchValue; 38895 window.SearchSanitizer.bindForm = bindSearchSanitizer; 38896 window.SearchSanitizer.cleanUrlParam = cleanQueryParamInUrl; 38897 38898 (function initSearchSanitizers() { 38899 // Current admin customers search form. 38900 bindSearchSanitizer(document.getElementById('filter_table_s')); 38901 bindSearchSanitizer(document.getElementById('filter_table_s'), { 38902 queryParamName: 'u', 38903 inputSelector: 'input[name="u"]' 38904 }); 38905 38906 // Future forms can opt-in by adding class + data attributes. 38907 $('.js-search-sanitize-form').each(function () { 38908 var form = this; 38909 bindSearchSanitizer(form, { 38910 queryParamName: form.getAttribute('data-query-param') || 'q', 38911 inputSelector: form.getAttribute('data-query-input') || undefined 38912 }); 38913 }); 38914 })(); 38915 38916 // Cookie name is promo_popup_dismissed_<id> 38917 (function promoPopupInit() { 38918 var wrap = document.getElementById('promo-popup-wrap'); 38919 if (!wrap) return; 38920 var cookieName = wrap.getAttribute('data-cookie-name'); 38921 var cookieDays = parseInt(wrap.getAttribute('data-cookie-days'), 10) || 7; 38922 38923 function getCookie(name) { 38924 var m = document.cookie.match(new RegExp('(?:^|; )' + name.replace(/([.*+?^${}()|[\]\\])/g, '\\$1') + '=([^;]*)')); 38925 return m ? decodeURIComponent(m[1]) : null; 38926 } 38927 function setCookie(name, value, days) { 38928 var d = new Date(); 38929 d.setTime(d.getTime() + days * 24 * 60 * 60 * 1000); 38930 document.cookie = name + '=' + encodeURIComponent(value) + ';path=/;expires=' + d.toUTCString() + ';SameSite=Lax'; 38931 } 38932 38933 if (getCookie(cookieName)) { 38934 if (wrap.parentNode) wrap.parentNode.removeChild(wrap); 38935 return; 38936 } 38937 38938 wrap.style.display = ''; 38939 document.body.classList.add('promo-popup-open'); 38940 38941 var closeBtn = wrap.querySelector('.promo-popup-close');
38942 var overlay = wrap.querySelector('.promo-popup-overlay'); 38943 38944 function closePopup() { 38945 setCookie(cookieName, '1', cookieDays); 38946 wrap.style.display = 'none'; 38947 document.body.classList.remove('promo-popup-open'); 38948 } 38949 38950 if (closeBtn) closeBtn.addEventListener('click', closePopup); 38951 if (overlay) overlay.addEventListener('click', closePopup); 38952 })(); 38953 38954}); 38955 38956/** 38957 * This file is part of the "box" project. 38958 * 38959 * (c) Alex Buturlakin [email protected] 38960 */ 38961 38962;(function($) { 38963 $(document).ready(function() { 38964 38965 // user log 38966 var userSearchButton = $('#form-admin-log-search').find('button'), 38967 userSearchSelect = $('#admin-log-user-search'), 38968 filterTypeSelect = $('#admin-log-type'), 38969 filterStatusSelect = $('#admin-log-status'), 38970 filterClearButton = $('#form-admin-log-filter-clear'), 38971 filterButton = $('#form-admin-log-filter').find('button'); 38972 38973 filterTypeSelect.select2({ 38974 placeholder: 'Select Type', 38975 width: '100%' 38976 }); 38977 38978 filterStatusSelect.select2({ 38979 placeholder: 'Select Status', 38980 width: '100%' 38981 }); 38982 38983 filterButton.click(function() { 38984 38985 var t = filterTypeSelect.val(), 38986 s = filterStatusSelect.val(), 38987 u = window.location.href; 38988 38989 if(t && '' != t) { 38990 u = $.updateUrlParam(u, 'type', t); 38991 } 38992 38993 if(s && '' != s) { 38994 u = $.updateUrlParam(u, 's', s); 38995 } 38996 38997 window.location.href = u; 38998 38999 return false; 39000 }); 39001 39002 filterClearButton.click(function() { 39003 var u = window.location.href; 39004 39005 u = $.removeUrlParam(u, 's'); 39006 u = $.removeUrlParam(u, 'type'); 39007 39008 window.location.href = u; 39009 39010 return false; 39011 }); 39012 39013 $('.debug-log-view').click(function () { 39014 var el = $(this); 39015 39016 el.addClass('view'); 39017 }); 39018 39019 $('.debug-log-view-single').click(function() { 39020 $(this).addClass('view'); 39021 }); 39022 39023 // open full log data in modal on click (user-log "Data" column) 39024 $(document).on('click', '.js-log-data', function (e) { 39025 var $target = $(this); 39026 var text = $target.text(); 39027 39028 var $backdrop = $('<div class="log-data-modal-backdrop"></div>'); 39029 var $modal = $('<pre class="log-data-modal"></pre>').text(text); 39030 39031 $backdrop.on('click', function () { 39032 $modal.remove(); 39033 $backdrop.remove(); 39034 }); 39035 39036 $('body').append($backdrop).append($modal); 39037 }); 39038 39039 userSearchSelect.select2({ 39040 width: '100%', 39041 // dir: "rtl", 39042 containerCssClass: 'admin-control-search', 39043 39044 ajax: { 39045 delay: 250, 39046 url: '/admin/user-log/search', 39047 placeholder: 'This is my placeholder', 39048 allowClear: true, 39049 data: function(params) { 39050 let term = params.term; 39051 // Convert non-ASCII domains to punycode 39052 if (term && /[^\x00-\x7F]/.test(term)) { 39053 try { 39054 term = new URL('http://' + term).hostname; 39055 } catch(e) {} 39056 } 39057 return {q: term}; 39058 }, 39059 processResults: function (data, params) { 39060 // parse the results into the format expected by Select2 39061 // since we are using custom formatting functions we do not need to 39062 // alter the remote JSON data, except to indicate that infinite 39063 // scrolling can be used 39064 params.page = params.page || 1; 39065 39066 var formattedData = []; 39067 39068 $.each(data, function(subject, elements) { 39069 if(Object.keys(elements).length > 0) { 39070 var children = []; 39071 var type = subject; 39072 39073 if('users' == subject) { 39074 type = 'u'; 39075 } 39076 39077 if('contacts' == subject) { 39078 type = 'c'; 39079 } 39080 39081 if('domains' == subject) { 39082 type = 'd'; 39083 } 39084 39085 $.each(elements, function(id, name) { 39086 children.push({id: id, text: name, group: subject, type: type}); 39087 }); 39088 39089 formattedData.push({id: subject, text: $.ucfirst(subject), children: children}); 39090 } 39091 }); 39092 39093 return { 39094 results: formattedData 39095 // pagination: { 39096 // more: (params.page * 30) < data.total_count 39097 // } 39098 }; 39099 }, 39100 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work 39101 minimumInputLength: 3 39102 } 39103 }).on('select2:select', function(e) { 39104 userSearchButton.prop('disabled', false); 39105 }); 39106 39107 userSearchButton.click(function() { 39108 var data = userSearchSelect.select2('data'); 39109
39110 if(0 == data.length) { 39111 $(this.prop('disabled', true)); 39112 39113 return false; 39114 } 39115 39116 var selected = data[0]; 39117 39118 // redirect 39119 window.location.href = Storage.getData('app_url') + 'admin/user-log?' + selected.type + '=' + selected.id; 39120 return false; 39121 }); 39122 39123 39124 $(document).on('click', '.admin-op-domain-update-status', function (e) { 39125 e.preventDefault(); 39126 var status = $(this).attr('data-status'); 39127 var con = confirm('Are you sure to change domain status to ' + status + '?'); 39128 39129 if (con) { 39130 $.ajax({ 39131 url: $(this).attr('href'), 39132 type: 'POST', 39133 data: { 39134 'status': status, 39135 }, 39136 success: function () { 39137 alert('Well done! Status was updated successfully.'); 39138 $('#admin-domain-op-errors').html('').addClass('hidden'); 39139 }, 39140 error: function (xhr) { 39141 if (403 === xhr.status) { 39142 window.location.href = '/user/login'; 39143 } 39144 39145 $('#admin-domain-op-errors').html(xhr.responseJSON.msg).removeClass('hidden'); 39146 } 39147 }); 39148 } 39149 }); 39150 39151 $(document).on('click', '.admin-op-domain-delete', function (e) { 39152 e.preventDefault(); 39153 var status = $(this).attr('data-status'); 39154 var con = confirm('Are you sure to delete selected domain?'); 39155 39156 if (con) { 39157 $.ajax({ 39158 url: $(this).attr('href'), 39159 type: 'POST', 39160 data: { 39161 'status': status, 39162 }, 39163 success: function () { 39164 alert('Well done! Domain was deleted successfully.'); 39165 $('#admin-domain-op-errors').html('').addClass('hidden'); 39166 window.location.reload(); 39167 }, 39168 error: function (xhr) { 39169 if (403 === xhr.status) { 39170 window.location.href = '/user/login'; 39171 } 39172 39173 $('#admin-domain-op-errors').html(xhr.responseJSON.msg).removeClass('hidden'); 39174 } 39175 }); 39176 } 39177 }); 39178 39179 39180 // section for verify-view.php 39181 var admin_dverify_form = $("#admin-dverify-form"); 39182 admin_dverify_form.find(":input[type=text]").prop("disabled", true); 39183 admin_dverify_form.find(":input[type=radio]").prop("disabled", true); 39184 admin_dverify_form.find(":input[type=submit]").prop("disabled", true); 39185 39186 var pr_input = admin_dverify_form.find(":input[name='name']"); 39187 var org_input = admin_dverify_form.find(":input[name='organization_name']"); 39188 var orgid_input = admin_dverify_form.find(":input[name='organization_number']"); 39189 var admin_dverify_form_org = admin_dverify_form.attr("org"); 39190 39191 var admin_dverify_edit_btn = $("#admin-dverify-edit-button"); 39192 39193 // disable or enable fields by owner type related to current owner type 39194 $(admin_dverify_edit_btn).click(function(event){ 39195 event.preventDefault(); 39196 admin_dverify_form.find(":input").prop("disabled", false); 39197 admin_dverify_edit_btn.prop("disabled", true); 39198 if(admin_dverify_form_org){ 39199 org_input.prop("disabled", false); 39200 orgid_input.prop("disabled", false); 39201 pr_input.prop("disabled", true); 39202 //pr_input.val(null); 39203 }else{ 39204 org_input.prop("disabled", true); 39205 orgid_input.prop("disabled", true); 39206 pr_input.prop("disabled", false); 39207 org_input.val(null); 39208 orgid_input.val(null); 39209 } 39210 }); 39211 39212 //disable form on click outside 39213 $("#admin-verify-edit-table").click(function(event){ 39214 if (!$(event.target).closest("#admin-dverify-form").length) { 39215 admin_dverify_form.find(":input").prop("disabled", true); 39216 admin_dverify_edit_btn.prop("disabled", false); 39217 } 39218 }); 39219 39220 // disable or enable fields by owner type of radio button 39221 admin_dverify_form.on("change", "input[name='owner-type']", function () { 39222 39223 if($(this).val() == "private"){ 39224 if(confirm("Are you sure you want to change the holder to a private entity?")){ 39225 org_input.prop("disabled", true); 39226 orgid_input.prop("disabled", true); 39227 pr_input.prop("disabled", false); 39228 org_input.val(null); 39229 orgid_input.val(null); 39230 }else{ 39231 $("#owner-org").prop("checked", true); 39232 } 39233 39234 }else{ 39235 if(confirm("Are you sure you want to change the holder to a organization entity?")){ 39236 org_input.prop("disabled", false); 39237 orgid_input.prop("disabled", false); 39238 org_input.prop("required", true); 39239 orgid_input.prop("required", true); 39240 pr_input.prop("disabled", true); 39241 }else{ 39242 $("#owner-pr").prop("checked", true); 39243 } 39244 } 39245 }); 39246 39247 // fill org input to owener name 39248 org_input.on("input", function() { 39249 let value = $(this).val(); 39250 pr_input.val(value); 39251 }); 39252 39253 39254 // reject verify 39255 $("#admin-domain-reject-verify").click(function(event){ 39256 event.preventDefault(); 39257 $("#admin-domain-reject-verify-reason").removeClass("hidden"); 39258 var reason = $("#admin-domain-reject-verify-reason").val(); 39259 if(!reason || reason.trim() == ""){ 39260 alert("Please enter a reason for rejection"); 39261 return; 39262 } 39263 39264 var target = $(this).data("url-target"); 39265 $(this).prop("disabled", true); 39266 $.ajax({ 39267 url: target, 39268 type: 'POST', 39269 data: { 39270 'reason': reason 39271 }, 39272 success: function(response){ 39273 window.location.href = response.redirect; 39274 }, 39275 error: function(xhr){ 39276 $('#admin-domain-reject-verify-reason').replaceWith('<div class="alert alert-danger">' + xhr.responseJSON.msg + '</div>'); 39277 $(this).prop("disabled", false); 39278 } 39279 }); 39280 }); 39281 39282 // approve verify 39283 $("#admin-domain-approve-verify").click(function(event){ 39284 event.preventDefault(); 39285 var target = $(this).data("url-target"); 39286 $(this).prop("disabled", true); 39287 $.ajax({ 39288 url: target, 39289 type: 'POST', 39290 success: function(response){ 39291 window.location.href = response.redirect; 39292 }, 39293 error: function(xhr){ 39294 $('#admin-domain-approve-verify').replaceWith('<div class="alert alert-danger">' + xhr.responseJSON.msg + '</div>'); 39295 $(this).prop("disabled", false); 39296 } 39297 }); 39298 }); 39299 }); 39300})(jQuery); 39301//# sourceMappingURL=bundle.js.map
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.