vendor: 6,409 bytes, lines 1-189
1function parse_str(str, array) { 2 // discuss at: http://phpjs.org/functions/parse_str/ 3 // original by: Cagri Ekin 4 // improved by: Michael White (http://getsprink.com) 5 // improved by: Jack 6 // improved by: Brett Zamir (http://brett-zamir.me) 7 // bugfixed by: Onno Marsman 8 // bugfixed by: Brett Zamir (http://brett-zamir.me) 9 // bugfixed by: stag019 10 // bugfixed by: Brett Zamir (http://brett-zamir.me) 11 // bugfixed by: MIO_KODUKI (http://mio-koduki.blogspot.com/) 12 // reimplemented by: stag019 13 // input by: Dreamer 14 // input by: Zaide (http://zaidesthings.com/) 15 // input by: David Pesta (http://davidpesta.com/) 16 // input by: jeicquest 17 // note: When no argument is specified, will put variables in global scope. 18 // note: When a particular argument has been passed, and the returned value is different parse_str of PHP. For example, a=b=c&d====c 19 // test: skip 20 // example 1: var arr = {}; 21 // example 1: parse_str('first=foo&second=bar', arr); 22 // example 1: $result = arr 23 // returns 1: { first: 'foo', second: 'bar' } 24 // example 2: var arr = {}; 25 // example 2: parse_str('str_a=Jack+and+Jill+didn%27t+see+the+well.', arr); 26 // example 2: $result = arr 27 // returns 2: { str_a: "Jack and Jill didn't see the well." } 28 // example 3: var abc = {3:'a'}; 29 // example 3: parse_str('abc[a][b]["c"]=def&abc[q]=t+5'); 30 // returns 3: {"3":"a","a":{"b":{"c":"def"}},"q":"t 5"} 31 32 var strArr = String(str) 33 .replace(/^&/, '') 34 .replace(/&$/, '') 35 .split('&'), 36 sal = strArr.length, 37 i, j, ct, p, lastObj, obj, lastIter, undef, chr, tmp, key, value, 38 postLeftBracketPos, keys, keysLen, 39 fixStr = function(str) { 40 return decodeURIComponent(str.replace(/\+/g, '%20')); 41 }; 42 43 if (!array) { 44 array = this.window; 45 } 46 47 for (i = 0; i < sal; i++) { 48 tmp = strArr[i].split('='); 49 key = fixStr(tmp[0]); 50 value = (tmp.length < 2) ? '' : fixStr(tmp[1]); 51 52 while (key.charAt(0) === ' ') { 53 key = key.slice(1); 54 } 55 if (key.indexOf('\x00') > -1) { 56 key = key.slice(0, key.indexOf('\x00')); 57 } 58 if (key && key.charAt(0) !== '[') { 59 keys = []; 60 postLeftBracketPos = 0; 61 for (j = 0; j < key.length; j++) { 62 if (key.charAt(j) === '[' && !postLeftBracketPos) { 63 postLeftBracketPos = j + 1; 64 } else if (key.charAt(j) === ']') { 65 if (postLeftBracketPos) { 66 if (!keys.length) { 67 keys.push(key.slice(0, postLeftBracketPos - 1)); 68 } 69 keys.push(key.substr(postLeftBracketPos, j - postLeftBracketPos)); 70 postLeftBracketPos = 0; 71 if (key.charAt(j + 1) !== '[') { 72 break; 73 } 74 } 75 } 76 } 77 if (!keys.length) { 78 keys = [key]; 79 } 80 for (j = 0; j < keys[0].length; j++) { 81 chr = keys[0].charAt(j); 82 if (chr === ' ' || chr === '.' || chr === '[') { 83 keys[0] = keys[0].substr(0, j) + '_' + keys[0].substr(j + 1); 84 } 85 if (chr === '[') { 86 break; 87 } 88 } 89 90 obj = array; 91 for (j = 0, keysLen = keys.length; j < keysLen; j++) { 92 key = keys[j].replace(/^['"]/, '') 93 .replace(/['"]$/, ''); 94 lastIter = j !== keys.length - 1; 95 lastObj = obj; 96 if ((key !== '' && key !== ' ') || j === 0) { 97 if (obj[key] === undef) { 98 obj[key] = {}; 99 } 100 obj = obj[key]; 101 } else { // To insert new dimension 102 ct = -1; 103 for (p in obj) { 104 if (obj.hasOwnProperty(p)) { 105 if (+p > ct && p.match(/^\d+$/g)) { 106 ct = +p; 107 } 108 } 109 } 110 key = ct + 1; 111 } 112 } 113 lastObj[key] = value; 114 } 115 } 116} 117 118function http_build_query(formdata, numeric_prefix, arg_separator) { 119 // discuss at: http://phpjs.org/functions/http_build_query/ 120 // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) 121 // improved by: Legaev Andrey 122 // improved by: Michael White (http://getsprink.com) 123 // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) 124 // improved by: Brett Zamir (http://brett-zamir.me) 125 // revised by: stag019 126 // input by: Dreamer 127 // bugfixed by: Brett Zamir (http://brett-zamir.me) 128 // bugfixed by: MIO_KODUKI (http://mio-koduki.blogspot.com/) 129 // note: If the value is null, key and value are skipped in the http_build_query of PHP while in phpjs they are not. 130 // depends on: urlencode 131 // example 1: http_build_query({foo: 'bar', php: 'hypertext processor', baz: 'boom', cow: 'milk'}, '', '&'); 132 // returns 1: 'foo=bar&php=hypertext+processor&baz=boom&cow=milk' 133 // example 2: http_build_query({'php': 'hypertext processor', 0: 'foo', 1: 'bar', 2: 'baz', 3: 'boom', 'cow': 'milk'}, 'myvar_'); 134 // returns 2: 'myvar_0=foo&myvar_1=bar&myvar_2=baz&myvar_3=boom&php=hypertext+processor&cow=milk' 135 136 var value, key, tmp = [], 137 that = this; 138 139 var _http_build_query_helper = function(key, val, arg_separator) { 140 var k, tmp = []; 141 if (val === true) { 142 val = '1'; 143 } else if (val === false) { 144 val = '0'; 145 } 146 if (val != null) { 147 if (typeof val === 'object') { 148 for (k in val) { 149 if (val[k] != null) { 150 tmp.push(_http_build_query_helper(key + '[' + k + ']', val[k], arg_separator)); 151 } 152 } 153 return tmp.join(arg_separator); 154 } else if (typeof val !== 'function') { 155 return that.urlencode(key) + '=' + that.urlencode(val); 156 } else { 157 throw new Error('There was an error processing for http_build_query().'); 158 } 159 } else { 160 return ''; 161 } 162 }; 163 164 if (!arg_separator) { 165 arg_separator = '&'; 166 } 167 for (key in formdata) { 168 value = formdata[key]; 169 if (numeric_prefix && !isNaN(key)) { 170 key = String(numeric_prefix) + key; 171 } 172 var query = _http_build_query_helper(key, value, arg_separator); 173 if (query !== '') { 174 tmp.push(query); 175 } 176 } 177 178 return tmp.join(arg_separator); 179} 180/* 181 http://www.JSON.org/json2.js 182 2008-07-15 183 184 Public Domain. 185 186 NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. 187 188 See http://www.JSON.org/js.html 189
190 This file creates a global JSON object containing two methods: stringify 191 and parse. 192 193 JSON.stringify(value, replacer, space) 194 value any JavaScript value, usually an object or array. 195 196 replacer an optional parameter that determines how object 197 values are stringified for objects. It can be a 198 function or an array. 199 200 space an optional parameter that specifies the indentation 201 of nested structures. If it is omitted, the text will 202 be packed without extra whitespace. If it is a number, 203 it will specify the number of spaces to indent at each 204 level. If it is a string (such as '\t' or ' '), 205 it contains the characters used to indent at each level. 206 207 This method produces a JSON text from a JavaScript value. 208 209 When an object value is found, if the object contains a toJSON 210 method, its toJSON method will be called and the result will be 211 stringified. A toJSON method does not serialize: it returns the 212 value represented by the name/value pair that should be serialized, 213 or undefined if nothing should be serialized. The toJSON method 214 will be passed the key associated with the value, and this will be 215 bound to the object holding the key. 216 217 For example, this would serialize Dates as ISO strings. 218 219 Date.prototype.toJSON = function (key) { 220 function f(n) { 221 // Format integers to have at least two digits. 222 return n < 10 ? '0' + n : n; 223 } 224 225 return this.getUTCFullYear() + '-' + 226 f(this.getUTCMonth() + 1) + '-' + 227 f(this.getUTCDate()) + 'T' + 228 f(this.getUTCHours()) + ':' + 229 f(this.getUTCMinutes()) + ':' + 230 f(this.getUTCSeconds()) + 'Z'; 231 }; 232 233 You can provide an optional replacer method. It will be passed the 234 key and value of each member, with this bound to the containing 235 object. The value that is returned from your method will be 236 serialized. If your method returns undefined, then the member will 237 be excluded from the serialization. 238 239 If the replacer parameter is an array, then it will be used to 240 select the members to be serialized. It filters the results such 241 that only members with keys listed in the replacer array are 242 stringified. 243 244 Values that do not have JSON representations, such as undefined or 245 functions, will not be serialized. Such values in objects will be 246 dropped; in arrays they will be replaced with null. You can use 247 a replacer function to replace those with JSON values. 248 JSON.stringify(undefined) returns undefined. 249 250 The optional space parameter produces a stringification of the 251 value that is filled with line breaks and indentation to make it 252 easier to read. 253 254 If the space parameter is a non-empty string, then that string will 255 be used for indentation. If the space parameter is a number, then 256 the indentation will be that many spaces. 257 258 Example: 259 260 text = JSON.stringify(['e', {pluribus: 'unum'}]); 261 // text is '["e",{"pluribus":"unum"}]' 262 263 264 text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); 265 // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' 266 267 text = JSON.stringify([new Date()], function (key, value) { 268 return this[key] instanceof Date ? 269 'Date(' + this[key] + ')' : value; 270 }); 271 // text is '["Date(---current time---)"]' 272 273 274 JSON.parse(text, reviver) 275 This method parses a JSON text to produce an object or array. 276 It can throw a SyntaxError exception. 277 278 The optional reviver parameter is a function that can filter and 279 transform the results. It receives each of the keys and values, 280 and its return value is used instead of the original value. 281 If it returns what it received, then the structure is not modified. 282 If it returns undefined then the member is deleted. 283 284 Example: 285 286 // Parse the text. Values that look like ISO date strings will 287 // be converted to Date objects. 288 289 myData = JSON.parse(text, function (key, value) { 290 var a; 291 if (typeof value === 'string') { 292 a = 293/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); 294 if (a) { 295 return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], 296 +a[5], +a[6])); 297 } 298 } 299 return value; 300 }); 301 302 myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { 303 var d; 304 if (typeof value === 'string' && 305 value.slice(0, 5) === 'Date(' && 306 value.slice(-1) === ')') { 307 d = new Date(value.slice(5, -1)); 308 if (d) { 309 return d; 310 } 311 } 312 return value; 313 }); 314 315 316 This is a reference implementation. You are free to copy, modify, or 317 redistribute. 318 319 This code should be minified before deployment. 320 See http://javascript.crockford.com/jsmin.html 321 322 USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO 323 NOT CONTROL. 324*/ 325 326/*jslint evil: true */ 327 328/*global JSON */ 329 330/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", call,
331 charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, getUTCMinutes, 332 getUTCMonth, getUTCSeconds, hasOwnProperty, join, lastIndex, length, 333 parse, propertyIsEnumerable, prototype, push, replace, slice, stringify, 334 test, toJSON, toString 335*/ 336 337if (!this.JSON) { 338 339// Create a JSON object only if one does not already exist. We create the 340// object in a closure to avoid creating global variables. 341 342 JSON = function () { 343 344 function f(n) { 345 // Format integers to have at least two digits. 346 return n < 10 ? '0' + n : n; 347 } 348 349 Date.prototype.toJSON = function (key) { 350 351 return this.getUTCFullYear() + '-' + 352 f(this.getUTCMonth() + 1) + '-' + 353 f(this.getUTCDate()) + 'T' + 354 f(this.getUTCHours()) + ':' + 355 f(this.getUTCMinutes()) + ':' + 356 f(this.getUTCSeconds()) + 'Z'; 357 }; 358 359 String.prototype.toJSON = 360 Number.prototype.toJSON = 361 Boolean.prototype.toJSON = function (key) { 362 return this.valueOf(); 363 }; 364 365 var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, 366 escapeable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, 367 gap, 368 indent, 369 meta = { // table of character substitutions 370 '\b': '\\b', 371 '\t': '\\t', 372 '\n': '\\n', 373 '\f': '\\f', 374 '\r': '\\r', 375 '"' : '\\"', 376 '\\': '\\\\' 377 }, 378 rep; 379 380 381 function quote(string) { 382 383// If the string contains no control characters, no quote characters, and no 384// backslash characters, then we can safely slap some quotes around it. 385// Otherwise we must also replace the offending characters with safe escape 386// sequences. 387 388 escapeable.lastIndex = 0; 389 return escapeable.test(string) ? 390 '"' + string.replace(escapeable, function (a) { 391 var c = meta[a]; 392 if (typeof c === 'string') { 393 return c; 394 } 395 return '\\u' + ('0000' + 396 (+(a.charCodeAt(0))).toString(16)).slice(-4); 397 }) + '"' : 398 '"' + string + '"'; 399 } 400 401 402 function str(key, holder) { 403 404// Produce a string from holder[key]. 405 406 var i, // The loop counter. 407 k, // The member key. 408 v, // The member value. 409 length, 410 mind = gap, 411 partial, 412 value = holder[key]; 413 414// If the value has a toJSON method, call it to obtain a replacement value. 415 416 if (value && typeof value === 'object' && 417 typeof value.toJSON === 'function') { 418 value = value.toJSON(key); 419 } 420 421// If we were called with a replacer function, then call the replacer to 422// obtain a replacement value. 423 424 if (typeof rep === 'function') { 425 value = rep.call(holder, key, value); 426 } 427 428// What happens next depends on the value's type. 429 430 switch (typeof value) { 431 case 'string': 432 return quote(value); 433 434 case 'number': 435 436// JSON numbers must be finite. Encode non-finite numbers as null. 437 438 return isFinite(value) ? String(value) : 'null'; 439 440 case 'boolean': 441 case 'null': 442 443// If the value is a boolean or null, convert it to a string. Note: 444// typeof null does not produce 'null'. The case is included here in 445// the remote chance that this gets fixed someday. 446 447 return String(value); 448 449// If the type is 'object', we might be dealing with an object or an array or 450// null. 451 452 case 'object': 453 454// Due to a specification blunder in ECMAScript, typeof null is 'object', 455// so watch out for that case. 456 457 if (!value) { 458 return 'null';
vendor: 5,486 bytes, lines 459-610
459 } 460 461// Make an array to hold the partial results of stringifying this object value. 462 463 gap += indent; 464 partial = []; 465 466// If the object has a dontEnum length property, we'll treat it as an array. 467 468 if (typeof value.length === 'number' && 469 !(value.propertyIsEnumerable('length'))) { 470 471// The object is an array. Stringify every element. Use null as a placeholder 472// for non-JSON values. 473 474 length = value.length; 475 for (i = 0; i < length; i += 1) { 476 partial[i] = str(i, value) || 'null'; 477 } 478 479// Join all of the elements together, separated with commas, and wrap them in 480// brackets. 481 482 v = partial.length === 0 ? '[]' : 483 gap ? '[\n' + gap + 484 partial.join(',\n' + gap) + '\n' + 485 mind + ']' : 486 '[' + partial.join(',') + ']'; 487 gap = mind; 488 return v; 489 } 490 491// If the replacer is an array, use it to select the members to be stringified. 492 493 if (rep && typeof rep === 'object') { 494 length = rep.length; 495 for (i = 0; i < length; i += 1) { 496 k = rep[i]; 497 if (typeof k === 'string') { 498 v = str(k, value); 499 if (v) { 500 partial.push(quote(k) + (gap ? ': ' : ':') + v); 501 } 502 } 503 } 504 } else { 505 506// Otherwise, iterate through all of the keys in the object. 507 508 for (k in value) { 509 if (Object.hasOwnProperty.call(value, k)) { 510 v = str(k, value); 511 if (v) { 512 partial.push(quote(k) + (gap ? ': ' : ':') + v); 513 } 514 } 515 } 516 } 517 518// Join all of the member texts together, separated with commas, 519// and wrap them in braces. 520 521 v = partial.length === 0 ? '{}' : 522 gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + 523 mind + '}' : '{' + partial.join(',') + '}'; 524 gap = mind; 525 return v; 526 } 527 } 528 529// Return the JSON object containing the stringify and parse methods. 530 531 return { 532 stringify: function (value, replacer, space) { 533 534// The stringify method takes a value and an optional replacer, and an optional 535// space parameter, and returns a JSON text. The replacer can be a function 536// that can replace values, or an array of strings that will select the keys. 537// A default replacer method can be provided. Use of the space parameter can 538// produce text that is more easily readable. 539 540 var i; 541 gap = ''; 542 indent = ''; 543 544// If the space parameter is a number, make an indent string containing that 545// many spaces. 546 547 if (typeof space === 'number') { 548 for (i = 0; i < space; i += 1) { 549 indent += ' '; 550 } 551 552// If the space parameter is a string, it will be used as the indent string. 553 554 } else if (typeof space === 'string') { 555 indent = space; 556 } 557 558// If there is a replacer, it must be a function or an array. 559// Otherwise, throw an error. 560 561 rep = replacer; 562 if (replacer && typeof replacer !== 'function' && 563 (typeof replacer !== 'object' || 564 typeof replacer.length !== 'number')) { 565 throw new Error('JSON.stringify'); 566 } 567 568// Make a fake root object containing our value under the key of ''. 569// Return the result of stringifying the value. 570 571 return str('', {'': value}); 572 }, 573 574 575 parse: function (text, reviver) { 576 577// The parse method takes a text and an optional reviver function, and returns 578// a JavaScript value if the text is a valid JSON text. 579 580 var j; 581 582 function walk(holder, key) { 583 584// The walk method is used to recursively walk the resulting structure so 585// that modifications can be made. 586 587 var k, v, value = holder[key]; 588 if (value && typeof value === 'object') { 589 for (k in value) { 590 if (Object.hasOwnProperty.call(value, k)) { 591 v = walk(value, k); 592 if (v !== undefined) { 593 value[k] = v; 594 } else { 595 delete value[k]; 596 } 597 } 598 } 599 } 600 return reviver.call(holder, key, value); 601 } 602 603 604// Parsing happens in four stages. In the first stage, we replace certain 605// Unicode characters with escape sequences. JavaScript handles many characters 606// incorrectly, either silently deleting them, or treating them as line endings. 607 608 cx.lastIndex = 0; 609 if (cx.test(text)) { 610 text = text.replace(cx, function (a) {
611 return '\\u' + ('0000' + 612 (+(a.charCodeAt(0))).toString(16)).slice(-4); 613 }); 614 } 615 616// In the second stage, we run the text against regular expressions that look 617// for non-JSON patterns. We are especially concerned with '()' and 'new' 618// because they can cause invocation, and '=' because it can cause mutation. 619// But just to be safe, we want to reject all unexpected forms. 620 621// We split the second stage into 4 regexp operations in order to work around 622// crippling inefficiencies in IE's and Safari's regexp engines. First we 623// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we 624// replace all simple value tokens with ']' characters. Third, we delete all 625// open brackets that follow a colon or comma or that begin the text. Finally, 626// we look to see that the remaining characters are only whitespace or ']' or 627// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. 628 629 if (/^[\],:{}\s]*$/. 630test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). 631replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). 632replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { 633 634// In the third stage we use the eval function to compile the text into a 635// JavaScript structure. The '{' operator is subject to a syntactic ambiguity 636// in JavaScript: it can begin a block or an object literal. We wrap the text 637// in parens to eliminate the ambiguity. 638 639 j = eval('(' + text + ')'); 640 641// In the optional fourth stage, we recursively walk the new structure, passing 642// each name/value pair to a reviver function for possible transformation. 643 644 return typeof reviver === 'function' ? 645 walk({'': j}, '') : j; 646 } 647 648// If the text is not JSON parseable, then a SyntaxError is thrown. 649 650 throw new SyntaxError('JSON.parse'); 651 } 652 }; 653 }(); 654} 655 656/*! 657 * jQuery JavaScript Library v1.7.1 658 * http://jquery.com/ 659 * 660 * Copyright 2011, John Resig 661 * Dual licensed under the MIT or GPL Version 2 licenses. 662 * http://jquery.org/license 663 * 664 * Includes Sizzle.js 665 * http://sizzlejs.com/ 666 * Copyright 2011, The Dojo Foundation 667 * Released under the MIT, BSD, and GPL Licenses. 668 * 669 * Date: Mon Nov 21 21:11:03 2011 -0500 670 */ 671(function( window, undefined ) { 672 673// Use the correct document accordingly with window argument (sandbox) 674var document = window.document, 675 navigator = window.navigator, 676 location = window.location; 677var jQuery = (function() { 678 679// Define a local copy of jQuery 680var jQuery = function( selector, context ) { 681 // The jQuery object is actually just the init constructor 'enhanced' 682 return new jQuery.fn.init( selector, context, rootjQuery ); 683 }, 684 685 // Map over jQuery in case of overwrite 686 _jQuery = window.jQuery, 687 688 // Map over the $ in case of overwrite 689 _$ = window.$, 690 691 // A central reference to the root jQuery(document) 692 rootjQuery, 693 694 // A simple way to check for HTML strings or ID strings 695 // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) 696 quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, 697 698 // Check if a string has a non-whitespace character in it 699 rnotwhite = /\S/, 700 701 // Used for trimming whitespace 702 trimLeft = /^\s+/, 703 trimRight = /\s+$/, 704 705 // Match a standalone tag 706 rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, 707 708 // JSON RegExp 709 rvalidchars = /^[\],:{}\s]*$/, 710 rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, 711 rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, 712 rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, 713 714 // Useragent RegExp 715 rwebkit = /(webkit)[ \/]([\w.]+)/, 716 ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, 717 rmsie = /(msie) ([\w.]+)/, 718 rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, 719 720 // Matches dashed string for camelizing 721 rdashAlpha = /-([a-z]|[0-9])/ig, 722 rmsPrefix = /^-ms-/, 723 724 // Used by jQuery.camelCase as callback to replace() 725 fcamelCase = function( all, letter ) { 726 return ( letter + "" ).toUpperCase(); 727 }, 728 729 // Keep a UserAgent string for use with jQuery.browser 730 userAgent = navigator.userAgent, 731 732 // For matching the engine and version of the browser 733 browserMatch, 734 735 // The deferred used on DOM ready 736 readyList, 737 738 // The ready event handler 739 DOMContentLoaded, 740 741 // Save a reference to some core methods 742 toString = Object.prototype.toString, 743 hasOwn = Object.prototype.hasOwnProperty, 744 push = Array.prototype.push, 745 slice = Array.prototype.slice, 746 trim = String.prototype.trim, 747 indexOf = Array.prototype.indexOf, 748 749 // [[Class]] -> type pairs 750 class2type = {}; 751 752jQuery.fn = jQuery.prototype = { 753 constructor: jQuery, 754 init: function( selector, context, rootjQuery ) { 755 var match, elem, ret, doc; 756 757 // Handle $(""), $(null), or $(undefined) 758 if ( !selector ) { 759 return this; 760 } 761 762 // Handle $(DOMElement) 763 if ( selector.nodeType ) { 764 this.context = this[0] = selector; 765 this.length = 1; 766 return this; 767 } 768 769 // The body element only exists once, optimize finding it 770 if ( selector === "body" && !context && document.body ) { 771 this.context = document; 772 this[0] = document.body; 773 this.selector = selector; 774 this.length = 1; 775 return this; 776 } 777 778 // Handle HTML strings 779 if ( typeof selector === "string" ) { 780 // Are we dealing with HTML string or an ID? 781 if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { 782 // Assume that strings that start and end with <> are HTML and skip the regex check 783 match = [ null, selector, null ]; 784 785 } else { 786 match = quickExpr.exec( selector ); 787 } 788 789 // Verify a match, and that no context was specified for #id 790 if ( match && (match[1] || !context) ) { 791 792 // HANDLE: $(html) -> $(array) 793 if ( match[1] ) { 794 context = context instanceof jQuery ? context[0] : context; 795 doc = ( context ? context.ownerDocument || context : document ); 796
vendor: 4,597 bytes, lines 797-984
797 // If a single string is passed in and it's a single tag 798 // just do a createElement and skip the rest 799 ret = rsingleTag.exec( selector ); 800 801 if ( ret ) { 802 if ( jQuery.isPlainObject( context ) ) { 803 selector = [ document.createElement( ret[1] ) ]; 804 jQuery.fn.attr.call( selector, context, true ); 805 806 } else { 807 selector = [ doc.createElement( ret[1] ) ]; 808 } 809 810 } else { 811 ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); 812 selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes; 813 } 814 815 return jQuery.merge( this, selector ); 816 817 // HANDLE: $("#id") 818 } else { 819 elem = document.getElementById( match[2] ); 820 821 // Check parentNode to catch when Blackberry 4.6 returns 822 // nodes that are no longer in the document #6963 823 if ( elem && elem.parentNode ) { 824 // Handle the case where IE and Opera return items 825 // by name instead of ID 826 if ( elem.id !== match[2] ) { 827 return rootjQuery.find( selector ); 828 } 829 830 // Otherwise, we inject the element directly into the jQuery object 831 this.length = 1; 832 this[0] = elem; 833 } 834 835 this.context = document; 836 this.selector = selector; 837 return this; 838 } 839 840 // HANDLE: $(expr, $(...)) 841 } else if ( !context || context.jquery ) { 842 return ( context || rootjQuery ).find( selector ); 843 844 // HANDLE: $(expr, context) 845 // (which is just equivalent to: $(context).find(expr) 846 } else { 847 return this.constructor( context ).find( selector ); 848 } 849 850 // HANDLE: $(function) 851 // Shortcut for document ready 852 } else if ( jQuery.isFunction( selector ) ) { 853 return rootjQuery.ready( selector ); 854 } 855 856 if ( selector.selector !== undefined ) { 857 this.selector = selector.selector; 858 this.context = selector.context; 859 } 860 861 return jQuery.makeArray( selector, this ); 862 }, 863 864 // Start with an empty selector 865 selector: "", 866 867 // The current version of jQuery being used 868 jquery: "1.7.1", 869 870 // The default length of a jQuery object is 0 871 length: 0, 872 873 // The number of elements contained in the matched element set 874 size: function() { 875 return this.length; 876 }, 877 878 toArray: function() { 879 return slice.call( this, 0 ); 880 }, 881 882 // Get the Nth element in the matched element set OR 883 // Get the whole matched element set as a clean array 884 get: function( num ) { 885 return num == null ? 886 887 // Return a 'clean' array 888 this.toArray() : 889 890 // Return just the object 891 ( num < 0 ? this[ this.length + num ] : this[ num ] ); 892 }, 893 894 // Take an array of elements and push it onto the stack 895 // (returning the new matched element set) 896 pushStack: function( elems, name, selector ) { 897 // Build a new jQuery matched element set 898 var ret = this.constructor(); 899 900 if ( jQuery.isArray( elems ) ) { 901 push.apply( ret, elems ); 902 903 } else { 904 jQuery.merge( ret, elems ); 905 } 906 907 // Add the old object onto the stack (as a reference) 908 ret.prevObject = this; 909 910 ret.context = this.context; 911 912 if ( name === "find" ) { 913 ret.selector = this.selector + ( this.selector ? " " : "" ) + selector; 914 } else if ( name ) { 915 ret.selector = this.selector + "." + name + "(" + selector + ")"; 916 } 917 918 // Return the newly-formed element set 919 return ret; 920 }, 921 922 // Execute a callback for every element in the matched set. 923 // (You can seed the arguments with an array of args, but this is 924 // only used internally.) 925 each: function( callback, args ) { 926 return jQuery.each( this, callback, args ); 927 }, 928 929 ready: function( fn ) { 930 // Attach the listeners 931 jQuery.bindReady(); 932 933 // Add the callback 934 readyList.add( fn ); 935 936 return this; 937 }, 938 939 eq: function( i ) { 940 i = +i; 941 return i === -1 ? 942 this.slice( i ) : 943 this.slice( i, i + 1 ); 944 }, 945 946 first: function() { 947 return this.eq( 0 ); 948 }, 949 950 last: function() { 951 return this.eq( -1 ); 952 }, 953 954 slice: function() { 955 return this.pushStack( slice.apply( this, arguments ), 956 "slice", slice.call(arguments).join(",") ); 957 }, 958 959 map: function( callback ) { 960 return this.pushStack( jQuery.map(this, function( elem, i ) { 961 return callback.call( elem, i, elem ); 962 })); 963 }, 964 965 end: function() { 966 return this.prevObject || this.constructor(null); 967 }, 968 969 // For internal use only. 970 // Behaves like an Array's method, not like a jQuery method. 971 push: push, 972 sort: [].sort, 973 splice: [].splice 974}; 975 976// Give the init function the jQuery prototype for later instantiation 977jQuery.fn.init.prototype = jQuery.fn; 978 979jQuery.extend = jQuery.fn.extend = function() { 980 var options, name, src, copy, copyIsArray, clone, 981 target = arguments[0] || {}, 982 i = 1, 983 length = arguments.length, 984 deep = false;
985 986 // Handle a deep copy situation 987 if ( typeof target === "boolean" ) { 988 deep = target; 989 target = arguments[1] || {}; 990 // skip the boolean and the target 991 i = 2; 992 } 993 994 // Handle case when target is a string or something (possible in deep copy) 995 if ( typeof target !== "object" && !jQuery.isFunction(target) ) { 996 target = {}; 997 } 998 999 // extend jQuery itself if only one argument is passed 1000 if ( length === i ) { 1001 target = this; 1002 --i; 1003 } 1004 1005 for ( ; i < length; i++ ) { 1006 // Only deal with non-null/undefined values 1007 if ( (options = arguments[ i ]) != null ) { 1008 // Extend the base object 1009 for ( name in options ) { 1010 src = target[ name ]; 1011 copy = options[ name ]; 1012 1013 // Prevent never-ending loop 1014 if ( target === copy ) { 1015 continue; 1016 } 1017 1018 // Recurse if we're merging plain objects or arrays 1019 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { 1020 if ( copyIsArray ) { 1021 copyIsArray = false; 1022 clone = src && jQuery.isArray(src) ? src : []; 1023 1024 } else { 1025 clone = src && jQuery.isPlainObject(src) ? src : {}; 1026 } 1027 1028 // Never move original objects, clone them 1029 target[ name ] = jQuery.extend( deep, clone, copy ); 1030 1031 // Don't bring in undefined values 1032 } else if ( copy !== undefined ) { 1033 target[ name ] = copy; 1034 } 1035 } 1036 } 1037 } 1038 1039 // Return the modified object 1040 return target; 1041}; 1042 1043jQuery.extend({ 1044 noConflict: function( deep ) { 1045 if ( window.$ === jQuery ) { 1046 window.$ = _$; 1047 } 1048 1049 if ( deep && window.jQuery === jQuery ) { 1050 window.jQuery = _jQuery; 1051 } 1052 1053 return jQuery; 1054 }, 1055 1056 // Is the DOM ready to be used? Set to true once it occurs. 1057 isReady: false, 1058 1059 // A counter to track how many items to wait for before 1060 // the ready event fires. See #6781 1061 readyWait: 1, 1062 1063 // Hold (or release) the ready event 1064 holdReady: function( hold ) { 1065 if ( hold ) { 1066 jQuery.readyWait++; 1067 } else { 1068 jQuery.ready( true ); 1069 } 1070 }, 1071 1072 // Handle when the DOM is ready 1073 ready: function( wait ) { 1074 // Either a released hold or an DOMready/load event and not yet ready 1075 if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { 1076 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). 1077 if ( !document.body ) { 1078 return setTimeout( jQuery.ready, 1 ); 1079 } 1080 1081 // Remember that the DOM is ready 1082 jQuery.isReady = true; 1083 1084 // If a normal DOM Ready event fired, decrement, and wait if need be 1085 if ( wait !== true && --jQuery.readyWait > 0 ) { 1086 return; 1087 } 1088 1089 // If there are functions bound, to execute 1090 readyList.fireWith( document, [ jQuery ] ); 1091 1092 // Trigger any bound ready events 1093 if ( jQuery.fn.trigger ) { 1094 jQuery( document ).trigger( "ready" ).off( "ready" ); 1095 } 1096 } 1097 }, 1098 1099 bindReady: function() { 1100 if ( readyList ) { 1101 return; 1102 } 1103 1104 readyList = jQuery.Callbacks( "once memory" ); 1105 1106 // Catch cases where $(document).ready() is called after the 1107 // browser event has already occurred. 1108 if ( document.readyState === "complete" ) { 1109 // Handle it asynchronously to allow scripts the opportunity to delay ready 1110 return setTimeout( jQuery.ready, 1 ); 1111 } 1112 1113 // Mozilla, Opera and webkit nightlies currently support this event 1114 if ( document.addEventListener ) { 1115 // Use the handy event callback 1116 document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); 1117 1118 // A fallback to window.onload, that will always work 1119 window.addEventListener( "load", jQuery.ready, false ); 1120 1121 // If IE event model is used 1122 } else if ( document.attachEvent ) { 1123 // ensure firing before onload, 1124 // maybe late but safe also for iframes 1125 document.attachEvent( "onreadystatechange", DOMContentLoaded ); 1126 1127 // A fallback to window.onload, that will always work 1128 window.attachEvent( "onload", jQuery.ready ); 1129 1130 // If IE and not a frame 1131 // continually check to see if the document is ready 1132 var toplevel = false; 1133 1134 try { 1135 toplevel = window.frameElement == null; 1136 } catch(e) {} 1137 1138 if ( document.documentElement.doScroll && toplevel ) { 1139 doScrollCheck(); 1140 } 1141 } 1142 }, 1143 1144 // See test/unit/core.js for details concerning isFunction. 1145 // Since version 1.3, DOM methods and functions like alert 1146 // aren't supported. They return false on IE (#2968). 1147 isFunction: function( obj ) { 1148 return jQuery.type(obj) === "function"; 1149 }, 1150 1151 isArray: Array.isArray || function( obj ) { 1152 return jQuery.type(obj) === "array"; 1153 }, 1154 1155 // A crude way of determining if an object is a window 1156 isWindow: function( obj ) { 1157 return obj && typeof obj === "object" && "setInterval" in obj; 1158 }, 1159 1160 isNumeric: function( obj ) { 1161 return !isNaN( parseFloat(obj) ) && isFinite( obj ); 1162 }, 1163 1164 type: function( obj ) { 1165 return obj == null ? 1166 String( obj ) : 1167 class2type[ toString.call(obj) ] || "object"; 1168 }, 1169 1170 isPlainObject: function( obj ) { 1171 // Must be an Object. 1172 // Because of IE, we also have to check the presence of the constructor property. 1173 // Make sure that DOM nodes and window objects don't pass through, as well 1174 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { 1175 return false;
vendor: 2,673 bytes, lines 1176-1277
1176 } 1177 1178 try { 1179 // Not own constructor property must be Object 1180 if ( obj.constructor && 1181 !hasOwn.call(obj, "constructor") && 1182 !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { 1183 return false; 1184 } 1185 } catch ( e ) { 1186 // IE8,9 Will throw exceptions on certain host objects #9897 1187 return false; 1188 } 1189 1190 // Own properties are enumerated firstly, so to speed up, 1191 // if last one is own, then all properties are own. 1192 1193 var key; 1194 for ( key in obj ) {} 1195 1196 return key === undefined || hasOwn.call( obj, key ); 1197 }, 1198 1199 isEmptyObject: function( obj ) { 1200 for ( var name in obj ) { 1201 return false; 1202 } 1203 return true; 1204 }, 1205 1206 error: function( msg ) { 1207 throw new Error( msg ); 1208 }, 1209 1210 parseJSON: function( data ) { 1211 if ( typeof data !== "string" || !data ) { 1212 return null; 1213 } 1214 1215 // Make sure leading/trailing whitespace is removed (IE can't handle it) 1216 data = jQuery.trim( data ); 1217 1218 // Attempt to parse using the native JSON parser first 1219 if ( window.JSON && window.JSON.parse ) { 1220 return window.JSON.parse( data ); 1221 } 1222 1223 // Make sure the incoming data is actual JSON 1224 // Logic borrowed from http://json.org/json2.js 1225 if ( rvalidchars.test( data.replace( rvalidescape, "@" ) 1226 .replace( rvalidtokens, "]" ) 1227 .replace( rvalidbraces, "")) ) { 1228 1229 return ( new Function( "return " + data ) )(); 1230 1231 } 1232 jQuery.error( "Invalid JSON: " + data ); 1233 }, 1234 1235 // Cross-browser xml parsing 1236 parseXML: function( data ) { 1237 var xml, tmp; 1238 try { 1239 if ( window.DOMParser ) { // Standard 1240 tmp = new DOMParser(); 1241 xml = tmp.parseFromString( data , "text/xml" ); 1242 } else { // IE 1243 xml = new ActiveXObject( "Microsoft.XMLDOM" ); 1244 xml.async = "false"; 1245 xml.loadXML( data ); 1246 } 1247 } catch( e ) { 1248 xml = undefined; 1249 } 1250 if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { 1251 jQuery.error( "Invalid XML: " + data ); 1252 } 1253 return xml; 1254 }, 1255 1256 noop: function() {}, 1257 1258 // Evaluates a script in a global context 1259 // Workarounds based on findings by Jim Driscoll 1260 // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context 1261 globalEval: function( data ) { 1262 if ( data && rnotwhite.test( data ) ) { 1263 // We use execScript on Internet Explorer 1264 // We use an anonymous function so that context is window 1265 // rather than jQuery in Firefox 1266 ( window.execScript || function( data ) { 1267 window[ "eval" ].call( window, data ); 1268 } )( data ); 1269 } 1270 }, 1271 1272 // Convert dashed to camelCase; used by the css and data modules 1273 // Microsoft forgot to hump their vendor prefix (#9572) 1274 camelCase: function( string ) { 1275 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); 1276 }, 1277
1278 nodeName: function( elem, name ) { 1279 return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); 1280 }, 1281 1282 // args is for internal usage only 1283 each: function( object, callback, args ) { 1284 var name, i = 0, 1285 length = object.length, 1286 isObj = length === undefined || jQuery.isFunction( object ); 1287 1288 if ( args ) { 1289 if ( isObj ) { 1290 for ( name in object ) { 1291 if ( callback.apply( object[ name ], args ) === false ) { 1292 break; 1293 } 1294 } 1295 } else { 1296 for ( ; i < length; ) { 1297 if ( callback.apply( object[ i++ ], args ) === false ) { 1298 break; 1299 } 1300 } 1301 } 1302 1303 // A special, fast, case for the most common use of each 1304 } else { 1305 if ( isObj ) { 1306 for ( name in object ) { 1307 if ( callback.call( object[ name ], name, object[ name ] ) === false ) { 1308 break; 1309 } 1310 } 1311 } else { 1312 for ( ; i < length; ) { 1313 if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { 1314 break; 1315 } 1316 } 1317 } 1318 } 1319 1320 return object; 1321 }, 1322 1323 // Use native String.trim function wherever possible 1324 trim: trim ? 1325 function( text ) { 1326 return text == null ? 1327 "" : 1328 trim.call( text ); 1329 } : 1330 1331 // Otherwise use our own trimming functionality 1332 function( text ) { 1333 return text == null ? 1334 "" : 1335 text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); 1336 }, 1337 1338 // results is for internal usage only 1339 makeArray: function( array, results ) { 1340 var ret = results || []; 1341 1342 if ( array != null ) { 1343 // The window, strings (and functions) also have 'length' 1344 // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 1345 var type = jQuery.type( array ); 1346 1347 if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { 1348 push.call( ret, array ); 1349 } else { 1350 jQuery.merge( ret, array ); 1351 } 1352 } 1353 1354 return ret; 1355 }, 1356 1357 inArray: function( elem, array, i ) { 1358 var len; 1359 1360 if ( array ) { 1361 if ( indexOf ) { 1362 return indexOf.call( array, elem, i ); 1363 } 1364 1365 len = array.length; 1366 i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; 1367 1368 for ( ; i < len; i++ ) { 1369 // Skip accessing in sparse arrays 1370 if ( i in array && array[ i ] === elem ) { 1371 return i; 1372 } 1373 } 1374 } 1375 1376 return -1; 1377 }, 1378 1379 merge: function( first, second ) { 1380 var i = first.length, 1381 j = 0; 1382 1383 if ( typeof second.length === "number" ) { 1384 for ( var l = second.length; j < l; j++ ) { 1385 first[ i++ ] = second[ j ]; 1386 } 1387 1388 } else { 1389 while ( second[j] !== undefined ) { 1390 first[ i++ ] = second[ j++ ]; 1391 } 1392 } 1393 1394 first.length = i; 1395 1396 return first; 1397 }, 1398 1399 grep: function( elems, callback, inv ) { 1400 var ret = [], retVal; 1401 inv = !!inv; 1402 1403 // Go through the array, only saving the items 1404 // that pass the validator function 1405 for ( var i = 0, length = elems.length; i < length; i++ ) { 1406 retVal = !!callback( elems[ i ], i ); 1407 if ( inv !== retVal ) { 1408 ret.push( elems[ i ] ); 1409 } 1410 } 1411 1412 return ret; 1413 }, 1414 1415 // arg is for internal usage only 1416 map: function( elems, callback, arg ) { 1417 var value, key, ret = [], 1418 i = 0, 1419 length = elems.length, 1420 // jquery objects are treated as arrays 1421 isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; 1422 1423 // Go through the array, translating each of the items to their 1424 if ( isArray ) { 1425 for ( ; i < length; i++ ) { 1426 value = callback( elems[ i ], i, arg ); 1427 1428 if ( value != null ) { 1429 ret[ ret.length ] = value; 1430 } 1431 } 1432 1433 // Go through every key on the object, 1434 } else { 1435 for ( key in elems ) { 1436 value = callback( elems[ key ], key, arg ); 1437 1438 if ( value != null ) { 1439 ret[ ret.length ] = value; 1440 } 1441 } 1442 } 1443 1444 // Flatten any nested arrays 1445 return ret.concat.apply( [], ret ); 1446 }, 1447 1448 // A global GUID counter for objects 1449 guid: 1, 1450 1451 // Bind a function to a context, optionally partially applying any 1452 // arguments. 1453 proxy: function( fn, context ) { 1454 if ( typeof context === "string" ) { 1455 var tmp = fn[ context ]; 1456 context = fn; 1457 fn = tmp; 1458 } 1459 1460 // Quick check to determine if target is callable, in the spec 1461 // this throws a TypeError, but we will just return undefined. 1462 if ( !jQuery.isFunction( fn ) ) { 1463 return undefined; 1464 } 1465 1466 // Simulated bind 1467 var args = slice.call( arguments, 2 ), 1468 proxy = function() { 1469 return fn.apply( context, args.concat( slice.call( arguments ) ) ); 1470 }; 1471 1472 // Set the guid of unique handler to the same of original handler, so it can be removed 1473 proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; 1474 1475 return proxy; 1476 }, 1477 1478 // Mutifunctional method to get and set values to a collection 1479 // The value/s can optionally be executed if it's a function 1480 access: function( elems, key, value, exec, fn, pass ) { 1481 var length = elems.length; 1482 1483 // Setting many attributes 1484 if ( typeof key === "object" ) { 1485 for ( var k in key ) { 1486 jQuery.access( elems, k, key[k], exec, fn, value ); 1487 } 1488 return elems; 1489 } 1490 1491 // Setting one attribute 1492 if ( value !== undefined ) { 1493 // Optionally, function values get executed if exec is true 1494 exec = !pass && exec && jQuery.isFunction(value); 1495 1496 for ( var i = 0; i < length; i++ ) { 1497 fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); 1498 } 1499 1500 return elems; 1501 } 1502 1503 // Getting an attribute 1504 return length ? fn( elems[0], key ) : undefined; 1505 }, 1506 1507 now: function() { 1508 return ( new Date() ).getTime(); 1509 }, 1510 1511 // Use of jQuery.browser is frowned upon. 1512 // More details: http://docs.jquery.com/Utilities/jQuery.browser 1513 uaMatch: function( ua ) { 1514 ua = ua.toLowerCase(); 1515 1516 var match = rwebkit.exec( ua ) || 1517 ropera.exec( ua ) || 1518 rmsie.exec( ua ) || 1519 ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || 1520 []; 1521 1522 return { browser: match[1] || "", version: match[2] || "0" }; 1523 }, 1524 1525 sub: function() { 1526 function jQuerySub( selector, context ) { 1527 return new jQuerySub.fn.init( selector, context ); 1528 } 1529 jQuery.extend( true, jQuerySub, this ); 1530 jQuerySub.superclass = this; 1531 jQuerySub.fn = jQuerySub.prototype = this(); 1532 jQuerySub.fn.constructor = jQuerySub; 1533 jQuerySub.sub = this.sub; 1534 jQuerySub.fn.init = function init( selector, context ) { 1535 if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { 1536 context = jQuerySub( context ); 1537 } 1538 1539 return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); 1540 }; 1541 jQuerySub.fn.init.prototype = jQuerySub.fn; 1542 var rootjQuerySub = jQuerySub(document); 1543 return jQuerySub; 1544 }, 1545 1546 browser: {} 1547}); 1548 1549// Populate the class2type map 1550jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { 1551 class2type[ "[object " + name + "]" ] = name.toLowerCase(); 1552}); 1553 1554browserMatch = jQuery.uaMatch( userAgent ); 1555if ( browserMatch.browser ) { 1556 jQuery.browser[ browserMatch.browser ] = true; 1557 jQuery.browser.version = browserMatch.version; 1558} 1559 1560// Deprecated, use jQuery.browser.webkit instead 1561if ( jQuery.browser.webkit ) { 1562 jQuery.browser.safari = true; 1563} 1564
1565// IE doesn't match non-breaking spaces with \s 1566if ( rnotwhite.test( "\xA0" ) ) { 1567 trimLeft = /^[\s\xA0]+/; 1568 trimRight = /[\s\xA0]+$/; 1569} 1570 1571// All jQuery objects should point back to these 1572rootjQuery = jQuery(document); 1573 1574// Cleanup functions for the document ready method 1575if ( document.addEventListener ) { 1576 DOMContentLoaded = function() { 1577 document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); 1578 jQuery.ready(); 1579 }; 1580 1581} else if ( document.attachEvent ) { 1582 DOMContentLoaded = function() { 1583 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). 1584 if ( document.readyState === "complete" ) { 1585 document.detachEvent( "onreadystatechange", DOMContentLoaded ); 1586 jQuery.ready(); 1587 } 1588 }; 1589} 1590 1591// The DOM ready check for Internet Explorer 1592function doScrollCheck() { 1593 if ( jQuery.isReady ) { 1594 return; 1595 } 1596 1597 try { 1598 // If IE is used, use the trick by Diego Perini 1599 // http://javascript.nwbox.com/IEContentLoaded/ 1600 document.documentElement.doScroll("left"); 1601 } catch(e) { 1602 setTimeout( doScrollCheck, 1 ); 1603 return; 1604 } 1605 1606 // and execute any waiting functions 1607 jQuery.ready(); 1608} 1609 1610return jQuery; 1611 1612})(); 1613 1614 1615// String to Object flags format cache 1616var flagsCache = {}; 1617 1618// Convert String-formatted flags into Object-formatted ones and store in cache 1619function createFlags( flags ) { 1620 var object = flagsCache[ flags ] = {}, 1621 i, length; 1622 flags = flags.split( /\s+/ ); 1623 for ( i = 0, length = flags.length; i < length; i++ ) { 1624 object[ flags[i] ] = true; 1625 } 1626 return object; 1627} 1628 1629/* 1630 * Create a callback list using the following parameters: 1631 * 1632 * flags: an optional list of space-separated flags that will change how 1633 * the callback list behaves 1634 * 1635 * By default a callback list will act like an event callback list and can be 1636 * "fired" multiple times. 1637 * 1638 * Possible flags: 1639 * 1640 * once: will ensure the callback list can only be fired once (like a Deferred) 1641 * 1642 * memory: will keep track of previous values and will call any callback added 1643 * after the list has been fired right away with the latest "memorized" 1644 * values (like a Deferred) 1645 * 1646 * unique: will ensure a callback can only be added once (no duplicate in the list) 1647 * 1648 * stopOnFalse: interrupt callings when a callback returns false 1649 * 1650 */ 1651jQuery.Callbacks = function( flags ) { 1652 1653 // Convert flags from String-formatted to Object-formatted 1654 // (we check in cache first) 1655 flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {}; 1656 1657 var // Actual callback list 1658 list = [], 1659 // Stack of fire calls for repeatable lists 1660 stack = [], 1661 // Last fire value (for non-forgettable lists) 1662 memory, 1663 // Flag to know if list is currently firing 1664 firing, 1665 // First callback to fire (used internally by add and fireWith) 1666 firingStart, 1667 // End of the loop when firing 1668 firingLength, 1669 // Index of currently firing callback (modified by remove if needed) 1670 firingIndex, 1671 // Add one or several callbacks to the list 1672 add = function( args ) { 1673 var i, 1674 length, 1675 elem, 1676 type, 1677 actual; 1678 for ( i = 0, length = args.length; i < length; i++ ) { 1679 elem = args[ i ]; 1680 type = jQuery.type( elem ); 1681 if ( type === "array" ) { 1682 // Inspect recursively 1683 add( elem ); 1684 } else if ( type === "function" ) { 1685 // Add if not in unique mode and callback is not in 1686 if ( !flags.unique || !self.has( elem ) ) { 1687 list.push( elem ); 1688 } 1689 } 1690 } 1691 }, 1692 // Fire callbacks 1693 fire = function( context, args ) { 1694 args = args || []; 1695 memory = !flags.memory || [ context, args ]; 1696 firing = true; 1697 firingIndex = firingStart || 0; 1698 firingStart = 0; 1699 firingLength = list.length; 1700 for ( ; list && firingIndex < firingLength; firingIndex++ ) { 1701 if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) { 1702 memory = true; // Mark as halted 1703 break; 1704 } 1705 } 1706 firing = false; 1707 if ( list ) { 1708 if ( !flags.once ) { 1709 if ( stack && stack.length ) { 1710 memory = stack.shift(); 1711 self.fireWith( memory[ 0 ], memory[ 1 ] ); 1712 } 1713 } else if ( memory === true ) { 1714 self.disable(); 1715 } else { 1716 list = []; 1717 } 1718 } 1719 }, 1720 // Actual Callbacks object 1721 self = { 1722 // Add a callback or a collection of callbacks to the list 1723 add: function() { 1724 if ( list ) { 1725 var length = list.length; 1726 add( arguments ); 1727 // Do we need to add the callbacks to the 1728 // current firing batch? 1729 if ( firing ) { 1730 firingLength = list.length; 1731 // With memory, if we're not firing then 1732 // we should call right away, unless previous 1733 // firing was halted (stopOnFalse) 1734 } else if ( memory && memory !== true ) { 1735 firingStart = length; 1736 fire( memory[ 0 ], memory[ 1 ] ); 1737 } 1738 } 1739 return this; 1740 }, 1741 // Remove a callback from the list 1742 remove: function() { 1743 if ( list ) { 1744 var args = arguments, 1745 argIndex = 0, 1746 argLength = args.length; 1747 for ( ; argIndex < argLength ; argIndex++ ) { 1748 for ( var i = 0; i < list.length; i++ ) { 1749 if ( args[ argIndex ] === list[ i ] ) { 1750 // Handle firingIndex and firingLength 1751 if ( firing ) { 1752 if ( i <= firingLength ) { 1753 firingLength--; 1754 if ( i <= firingIndex ) { 1755 firingIndex--; 1756 } 1757 } 1758 } 1759 // Remove the element 1760 list.splice( i--, 1 ); 1761 // If we have some unicity property then 1762 // we only need to do this once 1763 if ( flags.unique ) { 1764 break; 1765 } 1766 } 1767 } 1768 } 1769 } 1770 return this; 1771 }, 1772 // Control if a given callback is in the list 1773 has: function( fn ) { 1774 if ( list ) { 1775 var i = 0, 1776 length = list.length; 1777 for ( ; i < length; i++ ) { 1778 if ( fn === list[ i ] ) { 1779 return true; 1780 } 1781 } 1782 } 1783 return false;
1784 }, 1785 // Remove all callbacks from the list 1786 empty: function() { 1787 list = []; 1788 return this; 1789 }, 1790 // Have the list do nothing anymore 1791 disable: function() { 1792 list = stack = memory = undefined; 1793 return this; 1794 }, 1795 // Is it disabled? 1796 disabled: function() { 1797 return !list; 1798 }, 1799 // Lock the list in its current state 1800 lock: function() { 1801 stack = undefined; 1802 if ( !memory || memory === true ) { 1803 self.disable(); 1804 } 1805 return this; 1806 }, 1807 // Is it locked? 1808 locked: function() { 1809 return !stack; 1810 }, 1811 // Call all callbacks with the given context and arguments 1812 fireWith: function( context, args ) { 1813 if ( stack ) { 1814 if ( firing ) { 1815 if ( !flags.once ) { 1816 stack.push( [ context, args ] ); 1817 } 1818 } else if ( !( flags.once && memory ) ) { 1819 fire( context, args ); 1820 } 1821 } 1822 return this; 1823 }, 1824 // Call all the callbacks with the given arguments 1825 fire: function() { 1826 self.fireWith( this, arguments ); 1827 return this; 1828 }, 1829 // To know if the callbacks have already been called at least once 1830 fired: function() { 1831 return !!memory; 1832 } 1833 }; 1834 1835 return self; 1836}; 1837 1838 1839 1840 1841var // Static reference to slice 1842 sliceDeferred = [].slice; 1843 1844jQuery.extend({ 1845 1846 Deferred: function( func ) { 1847 var doneList = jQuery.Callbacks( "once memory" ), 1848 failList = jQuery.Callbacks( "once memory" ), 1849 progressList = jQuery.Callbacks( "memory" ), 1850 state = "pending", 1851 lists = { 1852 resolve: doneList, 1853 reject: failList, 1854 notify: progressList 1855 }, 1856 promise = { 1857 done: doneList.add, 1858 fail: failList.add, 1859 progress: progressList.add, 1860 1861 state: function() { 1862 return state; 1863 }, 1864 1865 // Deprecated 1866 isResolved: doneList.fired, 1867 isRejected: failList.fired, 1868 1869 then: function( doneCallbacks, failCallbacks, progressCallbacks ) { 1870 deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks ); 1871 return this; 1872 }, 1873 always: function() { 1874 deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments ); 1875 return this; 1876 }, 1877 pipe: function( fnDone, fnFail, fnProgress ) { 1878 return jQuery.Deferred(function( newDefer ) { 1879 jQuery.each( { 1880 done: [ fnDone, "resolve" ], 1881 fail: [ fnFail, "reject" ], 1882 progress: [ fnProgress, "notify" ] 1883 }, function( handler, data ) { 1884 var fn = data[ 0 ], 1885 action = data[ 1 ], 1886 returned; 1887 if ( jQuery.isFunction( fn ) ) { 1888 deferred[ handler ](function() { 1889 returned = fn.apply( this, arguments ); 1890 if ( returned && jQuery.isFunction( returned.promise ) ) { 1891 returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify ); 1892 } else { 1893 newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); 1894 } 1895 }); 1896 } else { 1897 deferred[ handler ]( newDefer[ action ] ); 1898 } 1899 }); 1900 }).promise(); 1901 }, 1902 // Get a promise for this deferred 1903 // If obj is provided, the promise aspect is added to the object 1904 promise: function( obj ) { 1905 if ( obj == null ) { 1906 obj = promise; 1907 } else { 1908 for ( var key in promise ) { 1909 obj[ key ] = promise[ key ]; 1910 } 1911 } 1912 return obj; 1913 } 1914 }, 1915 deferred = promise.promise({}), 1916 key; 1917 1918 for ( key in lists ) { 1919 deferred[ key ] = lists[ key ].fire; 1920 deferred[ key + "With" ] = lists[ key ].fireWith; 1921 } 1922 1923 // Handle state 1924 deferred.done( function() { 1925 state = "resolved"; 1926 }, failList.disable, progressList.lock ).fail( function() { 1927 state = "rejected"; 1928 }, doneList.disable, progressList.lock ); 1929 1930 // Call given func if any 1931 if ( func ) { 1932 func.call( deferred, deferred ); 1933 } 1934 1935 // All done! 1936 return deferred; 1937 }, 1938 1939 // Deferred helper 1940 when: function( firstParam ) { 1941 var args = sliceDeferred.call( arguments, 0 ), 1942 i = 0, 1943 length = args.length, 1944 pValues = new Array( length ), 1945 count = length, 1946 pCount = length, 1947 deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? 1948 firstParam : 1949 jQuery.Deferred(), 1950 promise = deferred.promise(); 1951 function resolveFunc( i ) { 1952 return function( value ) { 1953 args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; 1954 if ( !( --count ) ) { 1955 deferred.resolveWith( deferred, args ); 1956 } 1957 }; 1958 } 1959 function progressFunc( i ) { 1960 return function( value ) { 1961 pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; 1962 deferred.notifyWith( promise, pValues ); 1963 }; 1964 } 1965 if ( length > 1 ) { 1966 for ( ; i < length; i++ ) { 1967 if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) { 1968 args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) ); 1969 } else { 1970 --count; 1971 } 1972 } 1973 if ( !count ) { 1974 deferred.resolveWith( deferred, args ); 1975 } 1976 } else if ( deferred !== firstParam ) { 1977 deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); 1978 } 1979 return promise; 1980 } 1981}); 1982 1983 1984 1985 1986jQuery.support = (function() { 1987 1988 var support, 1989 all, 1990 a, 1991 select, 1992 opt, 1993 input, 1994 marginDiv, 1995 fragment, 1996 tds, 1997 events, 1998 eventName, 1999 i, 2000 isSupported, 2001 div = document.createElement( "div" ), 2002 documentElement = document.documentElement; 2003 2004 // Preliminary tests 2005 div.setAttribute("className", "t"); 2006 div.innerHTML = " <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a>
2006<input type='checkbox'/>"; 2007 2008 all = div.getElementsByTagName( "*" ); 2009 a = div.getElementsByTagName( "a" )[ 0 ]; 2010 2011 // Can't get basic test support 2012 if ( !all || !all.length || !a ) { 2013 return {}; 2014 } 2015 2016 // First batch of supports tests 2017 select = document.createElement( "select" ); 2018 opt = select.appendChild( document.createElement("option") ); 2019 input = div.getElementsByTagName( "input" )[ 0 ]; 2020 2021 support = { 2022 // IE strips leading whitespace when .innerHTML is used 2023 leadingWhitespace: ( div.firstChild.nodeType === 3 ), 2024 2025 // Make sure that tbody elements aren't automatically inserted 2026 // IE will insert them into empty tables 2027 tbody: !div.getElementsByTagName("tbody").length, 2028 2029 // Make sure that link elements get serialized correctly by innerHTML 2030 // This requires a wrapper element in IE 2031 htmlSerialize: !!div.getElementsByTagName("link").length, 2032 2033 // Get the style information from getAttribute 2034 // (IE uses .cssText instead) 2035 style: /top/.test( a.getAttribute("style") ), 2036 2037 // Make sure that URLs aren't manipulated 2038 // (IE normalizes it by default) 2039 hrefNormalized: ( a.getAttribute("href") === "/a" ), 2040 2041 // Make sure that element opacity exists 2042 // (IE uses filter instead) 2043 // Use a regex to work around a WebKit issue. See #5145 2044 opacity: /^0.55/.test( a.style.opacity ), 2045 2046 // Verify style float existence 2047 // (IE uses styleFloat instead of cssFloat) 2048 cssFloat: !!a.style.cssFloat, 2049 2050 // Make sure that if no value is specified for a checkbox 2051 // that it defaults to "on". 2052 // (WebKit defaults to "" instead) 2053 checkOn: ( input.value === "on" ), 2054 2055 // Make sure that a selected-by-default option has a working selected property. 2056 // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) 2057 optSelected: opt.selected, 2058 2059 // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) 2060 getSetAttribute: div.className !== "t", 2061 2062 // Tests for enctype support on a form(#6743) 2063 enctype: !!document.createElement("form").enctype, 2064 2065 // Makes sure cloning an html5 element does not cause problems 2066 // Where outerHTML is undefined, this still works 2067 html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>", 2068 2069 // Will be defined later 2070 submitBubbles: true, 2071 changeBubbles: true, 2072 focusinBubbles: false, 2073 deleteExpando: true, 2074 noCloneEvent: true, 2075 inlineBlockNeedsLayout: false, 2076 shrinkWrapBlocks: false, 2077 reliableMarginRight: true 2078 }; 2079 2080 // Make sure checked status is properly cloned 2081 input.checked = true; 2082 support.noCloneChecked = input.cloneNode( true ).checked; 2083 2084 // Make sure that the options inside disabled selects aren't marked as disabled 2085 // (WebKit marks them as disabled) 2086 select.disabled = true; 2087 support.optDisabled = !opt.disabled; 2088 2089 // Test to see if it's possible to delete an expando from an element 2090 // Fails in Internet Explorer 2091 try { 2092 delete div.test; 2093 } catch( e ) { 2094 support.deleteExpando = false; 2095 } 2096 2097 if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { 2098 div.attachEvent( "onclick", function() { 2099 // Cloning a node shouldn't copy over any 2100 // bound event handlers (IE does this) 2101 support.noCloneEvent = false; 2102 }); 2103 div.cloneNode( true ).fireEvent( "onclick" ); 2104 } 2105 2106 // Check if a radio maintains its value 2107 // after being appended to the DOM 2108 input = document.createElement("input"); 2109 input.value = "t"; 2110 input.setAttribute("type", "radio"); 2111 support.radioValue = input.value === "t"; 2112 2113 input.setAttribute("checked", "checked"); 2114 div.appendChild( input ); 2115 fragment = document.createDocumentFragment(); 2116 fragment.appendChild( div.lastChild ); 2117 2118 // WebKit doesn't clone checked state correctly in fragments 2119 support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; 2120 2121 // Check if a disconnected checkbox will retain its checked 2122 // value of true after appended to the DOM (IE6/7) 2123 support.appendChecked = input.checked; 2124 2125 fragment.removeChild( input ); 2126 fragment.appendChild( div ); 2127 2128 div.innerHTML = ""; 2129 2130 // Check if div with explicit width and no margin-right incorrectly 2131 // gets computed margin-right based on width of container. For more 2132 // info see bug #3333 2133 // Fails in WebKit before Feb 2011 nightlies 2134 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right 2135 if ( window.getComputedStyle ) { 2136 marginDiv = document.createElement( "div" ); 2137 marginDiv.style.width = "0"; 2138 marginDiv.style.marginRight = "0"; 2139 div.style.width = "2px"; 2140 div.appendChild( marginDiv ); 2141 support.reliableMarginRight = 2142 ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; 2143 } 2144 2145 // Technique from Juriy Zaytsev 2146 // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/ 2147 // We only care about the case where non-standard event systems 2148 // are used, namely in IE. Short-circuiting here helps us to 2149 // avoid an eval call (in setAttribute) which can cause CSP 2150 // to go haywire. See: https://developer.mozilla.org/en/Security/CSP 2151 if ( div.attachEvent ) { 2152 for( i in { 2153 submit: 1, 2154 change: 1, 2155 focusin: 1 2156 }) { 2157 eventName = "on" + i; 2158 isSupported = ( eventName in div ); 2159 if ( !isSupported ) { 2160 div.setAttribute( eventName, "return;" ); 2161 isSupported = ( typeof div[ eventName ] === "function" ); 2162 } 2163 support[ i + "Bubbles" ] = isSupported; 2164 } 2165 } 2166 2167 fragment.removeChild( div ); 2168 2169 // Null elements to avoid leaks in IE 2170 fragment = select = opt = marginDiv = div = input = null; 2171 2172 // Run tests that need a body at doc ready 2173 jQuery(function() { 2174 var container, outer, inner, table, td, offsetSupport, 2175 conMarginTop, ptlm, vb, style, html, 2176 body = document.getElementsByTagName("body")[0]; 2177 2178 if ( !body ) { 2179 // Return for frameset docs that don't have a body 2180 return; 2181 } 2182 2183 conMarginTop = 1; 2184 ptlm = "position:absolute;top:0;left:0;width:1px;height:1px;margin:0;"; 2185 vb = "visibility:hidden;border:0;"; 2186 style = "style='" + ptlm + "border:5px solid #000;padding:0;'"; 2187 html = "<div " + style + "><div></div></div>" + 2188 "<table " + style + " cellpadding='0' cellspacing='0'>" + 2189 "<tr><td></td></tr></table>"; 2190 2191 container = document.createElement("div"); 2192 container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px"; 2193 body.insertBefore( container, body.firstChild ); 2194 2195 // Construct the test element 2196 div = document.createElement("div"); 2197 container.appendChild( div ); 2198 2199 // Check if table cells still have offsetWidth/Height when they are set 2200 // to display:none and there are still other visible table cells in a 2201 // table row; if so, offsetWidth/Height are not reliable for use when 2202 // determining if an element has been hidden directly using 2203 // display:none (it is still safe to use offsets if a parent element is 2204 // hidden; don safety goggles and see bug #4512 for more information). 2205 // (only IE 8 fails this test) 2206 div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>"; 2207 tds = div.getElementsByTagName( "td" ); 2208 isSupported = ( tds[ 0 ].offsetHeight === 0 ); 2209 2210 tds[ 0 ].style.display = ""; 2211 tds[ 1 ].style.display = "none"; 2212 2213 // Check if empty table cells still have offsetWidth/Height 2214 // (IE <= 8 fail this test) 2215 support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); 2216 2217 // Figure out if the W3C box model works as expected 2218 div.innerHTML = ""; 2219 div.style.width = div.style.paddingLeft = "1px"; 2220 jQuery.boxModel = support.boxModel = div.offsetWidth === 2; 2221 2222 if ( typeof div.style.zoom !== "undefined" ) { 2223 // Check if natively block-level elements act like inline-block 2224 // elements when setting their display to 'inline' and giving 2225 // them layout 2226 // (IE < 8 does this) 2227 div.style.display = "inline"; 2228 div.style.zoom = 1; 2229 support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); 2230 2231 // Check if elements with layout shrink-wrap their children 2232 // (IE 6 does this) 2233 div.style.display = ""; 2234 div.innerHTML = "<div style='width:4px;'></div>"; 2235 support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); 2236 } 2237 2238 div.style.cssText = ptlm + vb; 2239 div.innerHTML = html; 2240 2241 outer = div.firstChild; 2242 inner = outer.firstChild; 2243 td = outer.nextSibling.firstChild.firstChild; 2244 2245 offsetSupport = { 2246 doesNotAddBorder: ( inner.offsetTop !== 5 ), 2247 doesAddBorderForTableAndCells: ( td.offsetTop === 5 ) 2248 }; 2249 2250 inner.style.position = "fixed"; 2251 inner.style.top = "20px"; 2252 2253 // safari subtracts parent border width here which is 5px 2254 offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 ); 2255 inner.style.position = inner.style.top = ""; 2256 2257 outer.style.overflow = "hidden"; 2258 outer.style.position = "relative"; 2259 2260 offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 ); 2261 offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop ); 2262 2263 body.removeChild( container ); 2264 div = container = null; 2265 2266 jQuery.extend( support, offsetSupport ); 2267 }); 2268 2269 return support; 2270})(); 2271 2272 2273 2274 2275var rbrace = /^(?:\{.*\}|\[.*\])$/, 2276 rmultiDash = /([A-Z])/g; 2277 2278jQuery.extend({ 2279 cache: {}, 2280 2281 // Please use with caution 2282 uuid: 0, 2283 2284 // Unique for each copy of jQuery on the page 2285 // Non-digits removed to match rinlinejQuery 2286 expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), 2287 2288 // The following elements throw uncatchable exceptions if you 2289 // attempt to add expando properties to them. 2290 noData: { 2291 "embed": true, 2292 // Ban all objects except for Flash (which handle expandos) 2293 "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", 2294 "applet": true 2295 }, 2296 2297 hasData: function( elem ) { 2298 elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; 2299 return !!elem && !isEmptyDataObject( elem ); 2300 }, 2301 2302 data: function( elem, name, data, pvt /* Internal Use Only */ ) { 2303 if ( !jQuery.acceptData( elem ) ) { 2304 return; 2305 } 2306 2307 var privateCache, thisCache, ret, 2308 internalKey = jQuery.expando, 2309 getByName = typeof name === "string", 2310 2311 // We have to handle DOM nodes and JS objects differently because IE6-7 2312 // can't GC object references properly across the DOM-JS boundary 2313 isNode = elem.nodeType, 2314 2315 // Only DOM nodes need the global jQuery cache; JS object data is 2316 // attached directly to the object so GC can occur automatically 2317 cache = isNode ? jQuery.cache : elem, 2318 2319 // Only defining an ID for JS objects if its cache already exists allows 2320 // the code to shortcut on the same path as a DOM node with no cache 2321 id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey, 2322 isEvents = name === "events"; 2323 2324 // Avoid doing any more work than we need to when trying to get data on an 2325 // object that has no data at all 2326 if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) { 2327 return; 2328 } 2329 2330 if ( !id ) { 2331 // Only DOM nodes need a new unique ID for each element since their data 2332 // ends up in the global cache 2333 if ( isNode ) { 2334 elem[ internalKey ] = id = ++jQuery.uuid; 2335 } else { 2336 id = internalKey; 2337 } 2338 } 2339 2340 if ( !cache[ id ] ) { 2341 cache[ id ] = {}; 2342 2343 // Avoids exposing jQuery metadata on plain JS objects when the object 2344 // is serialized using JSON.stringify 2345 if ( !isNode ) { 2346 cache[ id ].toJSON = jQuery.noop; 2347 } 2348 } 2349
2350 // An object can be passed to jQuery.data instead of a key/value pair; this gets 2351 // shallow copied over onto the existing cache 2352 if ( typeof name === "object" || typeof name === "function" ) { 2353 if ( pvt ) { 2354 cache[ id ] = jQuery.extend( cache[ id ], name ); 2355 } else { 2356 cache[ id ].data = jQuery.extend( cache[ id ].data, name ); 2357 } 2358 } 2359 2360 privateCache = thisCache = cache[ id ]; 2361 2362 // jQuery data() is stored in a separate object inside the object's internal data 2363 // cache in order to avoid key collisions between internal data and user-defined 2364 // data. 2365 if ( !pvt ) { 2366 if ( !thisCache.data ) { 2367 thisCache.data = {}; 2368 } 2369 2370 thisCache = thisCache.data; 2371 } 2372 2373 if ( data !== undefined ) { 2374 thisCache[ jQuery.camelCase( name ) ] = data; 2375 } 2376 2377 // Users should not attempt to inspect the internal events object using jQuery.data, 2378 // it is undocumented and subject to change. But does anyone listen? No. 2379 if ( isEvents && !thisCache[ name ] ) { 2380 return privateCache.events; 2381 } 2382 2383 // Check for both converted-to-camel and non-converted data property names 2384 // If a data property was specified 2385 if ( getByName ) { 2386 2387 // First Try to find as-is property data 2388 ret = thisCache[ name ]; 2389 2390 // Test for null|undefined property data 2391 if ( ret == null ) { 2392 2393 // Try to find the camelCased property 2394 ret = thisCache[ jQuery.camelCase( name ) ]; 2395 } 2396 } else { 2397 ret = thisCache; 2398 } 2399 2400 return ret; 2401 }, 2402 2403 removeData: function( elem, name, pvt /* Internal Use Only */ ) { 2404 if ( !jQuery.acceptData( elem ) ) { 2405 return; 2406 } 2407 2408 var thisCache, i, l, 2409 2410 // Reference to internal data cache key 2411 internalKey = jQuery.expando, 2412 2413 isNode = elem.nodeType, 2414 2415 // See jQuery.data for more information 2416 cache = isNode ? jQuery.cache : elem, 2417 2418 // See jQuery.data for more information 2419 id = isNode ? elem[ internalKey ] : internalKey; 2420 2421 // If there is already no cache entry for this object, there is no 2422 // purpose in continuing 2423 if ( !cache[ id ] ) { 2424 return; 2425 } 2426 2427 if ( name ) { 2428 2429 thisCache = pvt ? cache[ id ] : cache[ id ].data; 2430 2431 if ( thisCache ) { 2432 2433 // Support array or space separated string names for data keys 2434 if ( !jQuery.isArray( name ) ) { 2435 2436 // try the string as a key before any manipulation 2437 if ( name in thisCache ) { 2438 name = [ name ]; 2439 } else { 2440 2441 // split the camel cased version by spaces unless a key with the spaces exists 2442 name = jQuery.camelCase( name ); 2443 if ( name in thisCache ) { 2444 name = [ name ]; 2445 } else { 2446 name = name.split( " " ); 2447 } 2448 } 2449 } 2450 2451 for ( i = 0, l = name.length; i < l; i++ ) { 2452 delete thisCache[ name[i] ]; 2453 } 2454 2455 // If there is no data left in the cache, we want to continue 2456 // and let the cache object itself get destroyed 2457 if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { 2458 return; 2459 } 2460 } 2461 } 2462 2463 // See jQuery.data for more information 2464 if ( !pvt ) { 2465 delete cache[ id ].data; 2466 2467 // Don't destroy the parent cache unless the internal data object 2468 // had been the only thing left in it 2469 if ( !isEmptyDataObject(cache[ id ]) ) { 2470 return; 2471 } 2472 } 2473 2474 // Browsers that fail expando deletion also refuse to delete expandos on 2475 // the window, but it will allow it on all other JS objects; other browsers 2476 // don't care 2477 // Ensure that `cache` is not a window object #10080 2478 if ( jQuery.support.deleteExpando || !cache.setInterval ) { 2479 delete cache[ id ]; 2480 } else { 2481 cache[ id ] = null; 2482 } 2483 2484 // We destroyed the cache and need to eliminate the expando on the node to avoid 2485 // false lookups in the cache for entries that no longer exist 2486 if ( isNode ) { 2487 // IE does not allow us to delete expando properties from nodes, 2488 // nor does it have a removeAttribute function on Document nodes; 2489 // we must handle all of these cases 2490 if ( jQuery.support.deleteExpando ) { 2491 delete elem[ internalKey ]; 2492 } else if ( elem.removeAttribute ) { 2493 elem.removeAttribute( internalKey ); 2494 } else { 2495 elem[ internalKey ] = null; 2496 } 2497 } 2498 }, 2499 2500 // For internal use only. 2501 _data: function( elem, name, data ) { 2502 return jQuery.data( elem, name, data, true ); 2503 }, 2504 2505 // A method for determining if a DOM node can handle the data expando 2506 acceptData: function( elem ) { 2507 if ( elem.nodeName ) { 2508 var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; 2509 2510 if ( match ) { 2511 return !(match === true || elem.getAttribute("classid") !== match); 2512 } 2513 } 2514 2515 return true; 2516 } 2517}); 2518 2519jQuery.fn.extend({ 2520 data: function( key, value ) { 2521 var parts, attr, name, 2522 data = null; 2523 2524 if ( typeof key === "undefined" ) { 2525 if ( this.length ) { 2526 data = jQuery.data( this[0] ); 2527 2528 if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) { 2529 attr = this[0].attributes; 2530 for ( var i = 0, l = attr.length; i < l; i++ ) { 2531 name = attr[i].name; 2532
2533 if ( name.indexOf( "data-" ) === 0 ) { 2534 name = jQuery.camelCase( name.substring(5) ); 2535 2536 dataAttr( this[0], name, data[ name ] ); 2537 } 2538 } 2539 jQuery._data( this[0], "parsedAttrs", true ); 2540 } 2541 } 2542 2543 return data; 2544 2545 } else if ( typeof key === "object" ) { 2546 return this.each(function() { 2547 jQuery.data( this, key ); 2548 }); 2549 } 2550 2551 parts = key.split("."); 2552 parts[1] = parts[1] ? "." + parts[1] : ""; 2553 2554 if ( value === undefined ) { 2555 data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); 2556 2557 // Try to fetch any internally stored data first 2558 if ( data === undefined && this.length ) { 2559 data = jQuery.data( this[0], key ); 2560 data = dataAttr( this[0], key, data ); 2561 } 2562 2563 return data === undefined && parts[1] ? 2564 this.data( parts[0] ) : 2565 data; 2566 2567 } else { 2568 return this.each(function() { 2569 var self = jQuery( this ), 2570 args = [ parts[0], value ]; 2571 2572 self.triggerHandler( "setData" + parts[1] + "!", args ); 2573 jQuery.data( this, key, value ); 2574 self.triggerHandler( "changeData" + parts[1] + "!", args ); 2575 }); 2576 } 2577 }, 2578 2579 removeData: function( key ) { 2580 return this.each(function() { 2581 jQuery.removeData( this, key ); 2582 }); 2583 } 2584}); 2585 2586function dataAttr( elem, key, data ) { 2587 // If nothing was found internally, try to fetch any 2588 // data from the HTML5 data-* attribute 2589 if ( data === undefined && elem.nodeType === 1 ) { 2590 2591 var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); 2592 2593 data = elem.getAttribute( name ); 2594 2595 if ( typeof data === "string" ) { 2596 try { 2597 data = data === "true" ? true : 2598 data === "false" ? false : 2599 data === "null" ? null : 2600 jQuery.isNumeric( data ) ? parseFloat( data ) : 2601 rbrace.test( data ) ? jQuery.parseJSON( data ) : 2602 data; 2603 } catch( e ) {} 2604 2605 // Make sure we set the data so it isn't changed later 2606 jQuery.data( elem, key, data ); 2607 2608 } else { 2609 data = undefined; 2610 } 2611 } 2612 2613 return data; 2614} 2615 2616// checks a cache object for emptiness 2617function isEmptyDataObject( obj ) { 2618 for ( var name in obj ) { 2619 2620 // if the public data object is empty, the private is still empty 2621 if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { 2622 continue; 2623 } 2624 if ( name !== "toJSON" ) { 2625 return false; 2626 } 2627 } 2628 2629 return true; 2630} 2631 2632 2633 2634 2635function handleQueueMarkDefer( elem, type, src ) { 2636 var deferDataKey = type + "defer", 2637 queueDataKey = type + "queue", 2638 markDataKey = type + "mark", 2639 defer = jQuery._data( elem, deferDataKey ); 2640 if ( defer && 2641 ( src === "queue" || !jQuery._data(elem, queueDataKey) ) && 2642 ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) { 2643 // Give room for hard-coded callbacks to fire first 2644 // and eventually mark/queue something else on the element 2645 setTimeout( function() { 2646 if ( !jQuery._data( elem, queueDataKey ) && 2647 !jQuery._data( elem, markDataKey ) ) { 2648 jQuery.removeData( elem, deferDataKey, true ); 2649 defer.fire(); 2650 } 2651 }, 0 ); 2652 } 2653} 2654 2655jQuery.extend({ 2656 2657 _mark: function( elem, type ) { 2658 if ( elem ) { 2659 type = ( type || "fx" ) + "mark"; 2660 jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 ); 2661 } 2662 }, 2663 2664 _unmark: function( force, elem, type ) { 2665 if ( force !== true ) { 2666 type = elem; 2667 elem = force; 2668 force = false; 2669 } 2670 if ( elem ) { 2671 type = type || "fx"; 2672 var key = type + "mark", 2673 count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 ); 2674 if ( count ) { 2675 jQuery._data( elem, key, count ); 2676 } else { 2677 jQuery.removeData( elem, key, true ); 2678 handleQueueMarkDefer( elem, type, "mark" ); 2679 } 2680 } 2681 }, 2682 2683 queue: function( elem, type, data ) { 2684 var q; 2685 if ( elem ) { 2686 type = ( type || "fx" ) + "queue"; 2687 q = jQuery._data( elem, type ); 2688 2689 // Speed up dequeue by getting out quickly if this is just a lookup 2690 if ( data ) { 2691 if ( !q || jQuery.isArray(data) ) { 2692 q = jQuery._data( elem, type, jQuery.makeArray(data) ); 2693 } else { 2694 q.push( data ); 2695 } 2696 } 2697 return q || []; 2698 } 2699 }, 2700 2701 dequeue: function( elem, type ) { 2702 type = type || "fx"; 2703 2704 var queue = jQuery.queue( elem, type ), 2705 fn = queue.shift(), 2706 hooks = {}; 2707 2708 // If the fx queue is dequeued, always remove the progress sentinel 2709 if ( fn === "inprogress" ) { 2710 fn = queue.shift(); 2711 } 2712 2713 if ( fn ) { 2714 // Add a progress sentinel to prevent the fx queue from being 2715 // automatically dequeued 2716 if ( type === "fx" ) { 2717 queue.unshift( "inprogress" ); 2718 } 2719 2720 jQuery._data( elem, type + ".run", hooks ); 2721 fn.call( elem, function() { 2722 jQuery.dequeue( elem, type ); 2723 }, hooks ); 2724 } 2725 2726 if ( !queue.length ) { 2727 jQuery.removeData( elem, type + "queue " + type + ".run", true ); 2728 handleQueueMarkDefer( elem, type, "queue" ); 2729 } 2730 } 2731}); 2732 2733jQuery.fn.extend({ 2734 queue: function( type, data ) { 2735 if ( typeof type !== "string" ) { 2736 data = type; 2737 type = "fx"; 2738 } 2739 2740 if ( data === undefined ) { 2741 return jQuery.queue( this[0], type ); 2742 } 2743 return this.each(function() { 2744 var queue = jQuery.queue( this, type, data ); 2745 2746 if ( type === "fx" && queue[0] !== "inprogress" ) { 2747 jQuery.dequeue( this, type ); 2748 } 2749 }); 2750 }, 2751 dequeue: function( type ) { 2752 return this.each(function() { 2753 jQuery.dequeue( this, type ); 2754 }); 2755 }, 2756 // Based off of the plugin by Clint Helfers, with permission. 2757 // http://blindsignals.com/index.php/2009/07/jquery-delay/ 2758 delay: function( time, type ) { 2759 time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; 2760 type = type || "fx"; 2761 2762 return this.queue( type, function( next, hooks ) { 2763 var timeout = setTimeout( next, time ); 2764 hooks.stop = function() { 2765 clearTimeout( timeout ); 2766 }; 2767 }); 2768 }, 2769 clearQueue: function( type ) { 2770 return this.queue( type || "fx", [] ); 2771 }, 2772 // Get a promise resolved when queues of a certain type 2773 // are emptied (fx is the type by default) 2774 promise: function( type, object ) { 2775 if ( typeof type !== "string" ) { 2776 object = type; 2777 type = undefined; 2778 } 2779 type = type || "fx"; 2780 var defer = jQuery.Deferred(), 2781 elements = this, 2782 i = elements.length, 2783 count = 1, 2784 deferDataKey = type + "defer", 2785 queueDataKey = type + "queue", 2786 markDataKey = type + "mark", 2787 tmp; 2788 function resolve() { 2789 if ( !( --count ) ) { 2790 defer.resolveWith( elements, [ elements ] ); 2791 } 2792 } 2793 while( i-- ) { 2794 if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || 2795 ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || 2796 jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && 2797 jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) { 2798 count++; 2799 tmp.add( resolve ); 2800 } 2801 } 2802 resolve(); 2803 return defer.promise(); 2804 } 2805}); 2806 2807 2808 2809 2810var rclass = /[\n\t\r]/g, 2811 rspace = /\s+/, 2812 rreturn = /\r/g, 2813 rtype = /^(?:button|input)$/i, 2814 rfocusable = /^(?:button|input|object|select|textarea)$/i, 2815 rclickable = /^a(?:rea)?$/i, 2816 rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, 2817 getSetAttribute = jQuery.support.getSetAttribute, 2818 nodeHook, boolHook, fixSpecified; 2819 2820jQuery.fn.extend({ 2821 attr: function( name, value ) { 2822 return jQuery.access( this, name, value, true, jQuery.attr ); 2823 }, 2824 2825 removeAttr: function( name ) { 2826 return this.each(function() { 2827 jQuery.removeAttr( this, name ); 2828 }); 2829 }, 2830 2831 prop: function( name, value ) { 2832 return jQuery.access( this, name, value, true, jQuery.prop ); 2833 }, 2834 2835 removeProp: function( name ) { 2836 name = jQuery.propFix[ name ] || name; 2837 return this.each(function() { 2838 // try/catch handles cases where IE balks (such as removing a property on window) 2839 try { 2840 this[ name ] = undefined; 2841 delete this[ name ]; 2842 } catch( e ) {} 2843 }); 2844 }, 2845 2846 addClass: function( value ) { 2847 var classNames, i, l, elem, 2848 setClass, c, cl; 2849 2850 if ( jQuery.isFunction( value ) ) { 2851 return this.each(function( j ) { 2852 jQuery( this ).addClass( value.call(this, j, this.className) ); 2853 }); 2854 } 2855 2856 if ( value && typeof value === "string" ) { 2857 classNames = value.split( rspace ); 2858 2859 for ( i = 0, l = this.length; i < l; i++ ) { 2860 elem = this[ i ]; 2861 2862 if ( elem.nodeType === 1 ) { 2863 if ( !elem.className && classNames.length === 1 ) { 2864 elem.className = value; 2865 2866 } else { 2867 setClass = " " + elem.className + " "; 2868 2869 for ( c = 0, cl = classNames.length; c < cl; c++ ) { 2870 if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { 2871 setClass += classNames[ c ] + " "; 2872 } 2873 } 2874 elem.className = jQuery.trim( setClass ); 2875 } 2876 } 2877 } 2878 } 2879 2880 return this; 2881 }, 2882 2883 removeClass: function( value ) { 2884 var classNames, i, l, elem, className, c, cl; 2885 2886 if ( jQuery.isFunction( value ) ) { 2887 return this.each(function( j ) { 2888 jQuery( this ).removeClass( value.call(this, j, this.className) ); 2889 }); 2890 } 2891 2892 if ( (value && typeof value === "string") || value === undefined ) { 2893 classNames = ( value || "" ).split( rspace ); 2894 2895 for ( i = 0, l = this.length; i < l; i++ ) { 2896 elem = this[ i ]; 2897 2898 if ( elem.nodeType === 1 && elem.className ) { 2899 if ( value ) { 2900 className = (" " + elem.className + " ").replace( rclass, " " ); 2901 for ( c = 0, cl = classNames.length; c < cl; c++ ) { 2902 className = className.replace(" " + classNames[ c ] + " ", " "); 2903 } 2904 elem.className = jQuery.trim( className ); 2905 2906 } else { 2907 elem.className = ""; 2908 } 2909 } 2910 } 2911 } 2912 2913 return this; 2914 }, 2915 2916 toggleClass: function( value, stateVal ) { 2917 var type = typeof value, 2918 isBool = typeof stateVal === "boolean"; 2919 2920 if ( jQuery.isFunction( value ) ) { 2921 return this.each(function( i ) { 2922 jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); 2923 }); 2924 } 2925 2926 return this.each(function() { 2927 if ( type === "string" ) { 2928 // toggle individual class names 2929 var className, 2930 i = 0, 2931 self = jQuery( this ), 2932 state = stateVal, 2933 classNames = value.split( rspace ); 2934 2935 while ( (className = classNames[ i++ ]) ) { 2936 // check each className given, space seperated list 2937 state = isBool ? state : !self.hasClass( className ); 2938 self[ state ? "addClass" : "removeClass" ]( className ); 2939 } 2940 2941 } else if ( type === "undefined" || type === "boolean" ) { 2942 if ( this.className ) { 2943 // store className if set 2944 jQuery._data( this, "__className__", this.className ); 2945 } 2946 2947 // toggle whole className 2948 this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; 2949 } 2950 }); 2951 }, 2952 2953 hasClass: function( selector ) { 2954 var className = " " + selector + " ", 2955 i = 0, 2956 l = this.length; 2957 for ( ; i < l; i++ ) { 2958 if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { 2959 return true; 2960 } 2961 } 2962 2963 return false;
2964 }, 2965 2966 val: function( value ) { 2967 var hooks, ret, isFunction, 2968 elem = this[0]; 2969 2970 if ( !arguments.length ) { 2971 if ( elem ) { 2972 hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; 2973 2974 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { 2975 return ret; 2976 } 2977 2978 ret = elem.value; 2979 2980 return typeof ret === "string" ? 2981 // handle most common string cases 2982 ret.replace(rreturn, "") : 2983 // handle cases where value is null/undef or number 2984 ret == null ? "" : ret; 2985 } 2986 2987 return; 2988 } 2989 2990 isFunction = jQuery.isFunction( value ); 2991 2992 return this.each(function( i ) { 2993 var self = jQuery(this), val; 2994 2995 if ( this.nodeType !== 1 ) { 2996 return; 2997 } 2998 2999 if ( isFunction ) { 3000 val = value.call( this, i, self.val() ); 3001 } else { 3002 val = value; 3003 } 3004 3005 // Treat null/undefined as ""; convert numbers to string 3006 if ( val == null ) { 3007 val = ""; 3008 } else if ( typeof val === "number" ) { 3009 val += ""; 3010 } else if ( jQuery.isArray( val ) ) { 3011 val = jQuery.map(val, function ( value ) { 3012 return value == null ? "" : value + ""; 3013 }); 3014 } 3015 3016 hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; 3017 3018 // If set returns undefined, fall back to normal setting 3019 if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { 3020 this.value = val; 3021 } 3022 }); 3023 } 3024}); 3025 3026jQuery.extend({ 3027 valHooks: { 3028 option: { 3029 get: function( elem ) { 3030 // attributes.value is undefined in Blackberry 4.7 but 3031 // uses .value. See #6932 3032 var val = elem.attributes.value; 3033 return !val || val.specified ? elem.value : elem.text; 3034 } 3035 }, 3036 select: { 3037 get: function( elem ) { 3038 var value, i, max, option, 3039 index = elem.selectedIndex, 3040 values = [], 3041 options = elem.options, 3042 one = elem.type === "select-one"; 3043 3044 // Nothing was selected 3045 if ( index < 0 ) { 3046 return null; 3047 } 3048 3049 // Loop through all the selected options 3050 i = one ? index : 0; 3051 max = one ? index + 1 : options.length; 3052 for ( ; i < max; i++ ) { 3053 option = options[ i ]; 3054 3055 // Don't return options that are disabled or in a disabled optgroup 3056 if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && 3057 (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { 3058 3059 // Get the specific value for the option 3060 value = jQuery( option ).val(); 3061 3062 // We don't need an array for one selects 3063 if ( one ) { 3064 return value; 3065 } 3066 3067 // Multi-Selects return an array 3068 values.push( value ); 3069 } 3070 } 3071 3072 // Fixes Bug #2551 -- select.val() broken in IE after form.reset() 3073 if ( one && !values.length && options.length ) { 3074 return jQuery( options[ index ] ).val(); 3075 } 3076 3077 return values; 3078 }, 3079 3080 set: function( elem, value ) { 3081 var values = jQuery.makeArray( value ); 3082 3083 jQuery(elem).find("option").each(function() { 3084 this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; 3085 }); 3086 3087 if ( !values.length ) { 3088 elem.selectedIndex = -1; 3089 } 3090 return values; 3091 } 3092 } 3093 }, 3094 3095 attrFn: { 3096 val: true, 3097 css: true, 3098 html: true, 3099 text: true, 3100 data: true, 3101 width: true, 3102 height: true, 3103 offset: true 3104 }, 3105 3106 attr: function( elem, name, value, pass ) { 3107 var ret, hooks, notxml, 3108 nType = elem.nodeType; 3109 3110 // don't get/set attributes on text, comment and attribute nodes 3111 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { 3112 return; 3113 } 3114 3115 if ( pass && name in jQuery.attrFn ) { 3116 return jQuery( elem )[ name ]( value ); 3117 } 3118 3119 // Fallback to prop when attributes are not supported 3120 if ( typeof elem.getAttribute === "undefined" ) { 3121 return jQuery.prop( elem, name, value ); 3122 } 3123 3124 notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); 3125 3126 // All attributes are lowercase 3127 // Grab necessary hook if one is defined 3128 if ( notxml ) { 3129 name = name.toLowerCase(); 3130 hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); 3131 } 3132 3133 if ( value !== undefined ) { 3134 3135 if ( value === null ) { 3136 jQuery.removeAttr( elem, name ); 3137 return; 3138 3139 } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { 3140 return ret; 3141 3142 } else { 3143 elem.setAttribute( name, "" + value ); 3144 return value; 3145 } 3146 3147 } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { 3148 return ret; 3149 3150 } else { 3151 3152 ret = elem.getAttribute( name ); 3153 3154 // Non-existent attributes return null, we normalize to undefined 3155 return ret === null ? 3156 undefined : 3157 ret; 3158 } 3159 }, 3160 3161 removeAttr: function( elem, value ) { 3162 var propName, attrNames, name, l, 3163 i = 0; 3164 3165 if ( value && elem.nodeType === 1 ) { 3166 attrNames = value.toLowerCase().split( rspace ); 3167 l = attrNames.length; 3168 3169 for ( ; i < l; i++ ) { 3170 name = attrNames[ i ]; 3171
vendor: 5,612 bytes, lines 3172-3364
3172 if ( name ) { 3173 propName = jQuery.propFix[ name ] || name; 3174 3175 // See #9699 for explanation of this approach (setting first, then removal) 3176 jQuery.attr( elem, name, "" ); 3177 elem.removeAttribute( getSetAttribute ? name : propName ); 3178 3179 // Set corresponding property to false for boolean attributes 3180 if ( rboolean.test( name ) && propName in elem ) { 3181 elem[ propName ] = false; 3182 } 3183 } 3184 } 3185 } 3186 }, 3187 3188 attrHooks: { 3189 type: { 3190 set: function( elem, value ) { 3191 // We can't allow the type property to be changed (since it causes problems in IE) 3192 if ( rtype.test( elem.nodeName ) && elem.parentNode ) { 3193 jQuery.error( "type property can't be changed" ); 3194 } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { 3195 // Setting the type on a radio button after the value resets the value in IE6-9 3196 // Reset value to it's default in case type is set after value 3197 // This is for element creation 3198 var val = elem.value; 3199 elem.setAttribute( "type", value ); 3200 if ( val ) { 3201 elem.value = val; 3202 } 3203 return value; 3204 } 3205 } 3206 }, 3207 // Use the value property for back compat 3208 // Use the nodeHook for button elements in IE6/7 (#1954) 3209 value: { 3210 get: function( elem, name ) { 3211 if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { 3212 return nodeHook.get( elem, name ); 3213 } 3214 return name in elem ? 3215 elem.value : 3216 null; 3217 }, 3218 set: function( elem, value, name ) { 3219 if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { 3220 return nodeHook.set( elem, value, name ); 3221 } 3222 // Does not return so that setAttribute is also used 3223 elem.value = value; 3224 } 3225 } 3226 }, 3227 3228 propFix: { 3229 tabindex: "tabIndex", 3230 readonly: "readOnly", 3231 "for": "htmlFor", 3232 "class": "className", 3233 maxlength: "maxLength", 3234 cellspacing: "cellSpacing", 3235 cellpadding: "cellPadding", 3236 rowspan: "rowSpan", 3237 colspan: "colSpan", 3238 usemap: "useMap", 3239 frameborder: "frameBorder", 3240 contenteditable: "contentEditable" 3241 }, 3242 3243 prop: function( elem, name, value ) { 3244 var ret, hooks, notxml, 3245 nType = elem.nodeType; 3246 3247 // don't get/set properties on text, comment and attribute nodes 3248 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { 3249 return; 3250 } 3251 3252 notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); 3253 3254 if ( notxml ) { 3255 // Fix name and attach hooks 3256 name = jQuery.propFix[ name ] || name; 3257 hooks = jQuery.propHooks[ name ]; 3258 } 3259 3260 if ( value !== undefined ) { 3261 if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { 3262 return ret; 3263 3264 } else { 3265 return ( elem[ name ] = value ); 3266 } 3267 3268 } else { 3269 if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { 3270 return ret; 3271 3272 } else { 3273 return elem[ name ]; 3274 } 3275 } 3276 }, 3277 3278 propHooks: { 3279 tabIndex: { 3280 get: function( elem ) { 3281 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set 3282 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ 3283 var attributeNode = elem.getAttributeNode("tabindex"); 3284 3285 return attributeNode && attributeNode.specified ? 3286 parseInt( attributeNode.value, 10 ) : 3287 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? 3288 0 : 3289 undefined; 3290 } 3291 } 3292 } 3293}); 3294 3295// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional) 3296jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex; 3297 3298// Hook for boolean attributes 3299boolHook = { 3300 get: function( elem, name ) { 3301 // Align boolean attributes with corresponding properties 3302 // Fall back to attribute presence where some booleans are not supported 3303 var attrNode, 3304 property = jQuery.prop( elem, name ); 3305 return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ? 3306 name.toLowerCase() : 3307 undefined; 3308 }, 3309 set: function( elem, value, name ) { 3310 var propName; 3311 if ( value === false ) { 3312 // Remove boolean attributes when set to false 3313 jQuery.removeAttr( elem, name ); 3314 } else { 3315 // value is true since we know at this point it's type boolean and not false 3316 // Set boolean attributes to the same name and set the DOM property 3317 propName = jQuery.propFix[ name ] || name; 3318 if ( propName in elem ) { 3319 // Only set the IDL specifically if it already exists on the element 3320 elem[ propName ] = true; 3321 } 3322 3323 elem.setAttribute( name, name.toLowerCase() ); 3324 } 3325 return name; 3326 } 3327}; 3328 3329// IE6/7 do not support getting/setting some attributes with get/setAttribute 3330if ( !getSetAttribute ) { 3331 3332 fixSpecified = { 3333 name: true, 3334 id: true 3335 }; 3336 3337 // Use this for any attribute in IE6/7 3338 // This fixes almost every IE6/7 issue 3339 nodeHook = jQuery.valHooks.button = { 3340 get: function( elem, name ) { 3341 var ret; 3342 ret = elem.getAttributeNode( name ); 3343 return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ? 3344 ret.nodeValue : 3345 undefined; 3346 }, 3347 set: function( elem, value, name ) { 3348 // Set the existing or create a new attribute node 3349 var ret = elem.getAttributeNode( name ); 3350 if ( !ret ) { 3351 ret = document.createAttribute( name ); 3352 elem.setAttributeNode( ret ); 3353 } 3354 return ( ret.nodeValue = value + "" ); 3355 } 3356 }; 3357 3358 // Apply the nodeHook to tabindex 3359 jQuery.attrHooks.tabindex.set = nodeHook.set; 3360 3361 // Set width and height to auto instead of 0 on empty string( Bug #8150 ) 3362 // This is for removals 3363 jQuery.each([ "width", "height" ], function( i, name ) { 3364 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
3365 set: function( elem, value ) { 3366 if ( value === "" ) { 3367 elem.setAttribute( name, "auto" ); 3368 return value; 3369 } 3370 } 3371 }); 3372 }); 3373 3374 // Set contenteditable to false on removals(#10429) 3375 // Setting to empty string throws an error as an invalid value 3376 jQuery.attrHooks.contenteditable = { 3377 get: nodeHook.get, 3378 set: function( elem, value, name ) { 3379 if ( value === "" ) { 3380 value = "false"; 3381 } 3382 nodeHook.set( elem, value, name ); 3383 } 3384 }; 3385} 3386 3387 3388// Some attributes require a special call on IE 3389if ( !jQuery.support.hrefNormalized ) { 3390 jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { 3391 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { 3392 get: function( elem ) { 3393 var ret = elem.getAttribute( name, 2 ); 3394 return ret === null ? undefined : ret; 3395 } 3396 }); 3397 }); 3398} 3399 3400if ( !jQuery.support.style ) { 3401 jQuery.attrHooks.style = { 3402 get: function( elem ) { 3403 // Return undefined in the case of empty string 3404 // Normalize to lowercase since IE uppercases css property names 3405 return elem.style.cssText.toLowerCase() || undefined; 3406 }, 3407 set: function( elem, value ) { 3408 return ( elem.style.cssText = "" + value ); 3409 } 3410 }; 3411} 3412 3413// Safari mis-reports the default selected property of an option 3414// Accessing the parent's selectedIndex property fixes it 3415if ( !jQuery.support.optSelected ) { 3416 jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { 3417 get: function( elem ) { 3418 var parent = elem.parentNode; 3419 3420 if ( parent ) { 3421 parent.selectedIndex; 3422 3423 // Make sure that it also works with optgroups, see #5701 3424 if ( parent.parentNode ) { 3425 parent.parentNode.selectedIndex; 3426 } 3427 } 3428 return null; 3429 } 3430 }); 3431} 3432 3433// IE6/7 call enctype encoding 3434if ( !jQuery.support.enctype ) { 3435 jQuery.propFix.enctype = "encoding"; 3436} 3437 3438// Radios and checkboxes getter/setter 3439if ( !jQuery.support.checkOn ) { 3440 jQuery.each([ "radio", "checkbox" ], function() { 3441 jQuery.valHooks[ this ] = { 3442 get: function( elem ) { 3443 // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified 3444 return elem.getAttribute("value") === null ? "on" : elem.value; 3445 } 3446 }; 3447 }); 3448} 3449jQuery.each([ "radio", "checkbox" ], function() { 3450 jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { 3451 set: function( elem, value ) { 3452 if ( jQuery.isArray( value ) ) { 3453 return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); 3454 } 3455 } 3456 }); 3457}); 3458 3459 3460 3461 3462var rformElems = /^(?:textarea|input|select)$/i, 3463 rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/, 3464 rhoverHack = /\bhover(\.\S+)?\b/, 3465 rkeyEvent = /^key/, 3466 rmouseEvent = /^(?:mouse|contextmenu)|click/, 3467 rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, 3468 rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/, 3469 quickParse = function( selector ) { 3470 var quick = rquickIs.exec( selector ); 3471 if ( quick ) { 3472 // 0 1 2 3 3473 // [ _, tag, id, class ] 3474 quick[1] = ( quick[1] || "" ).toLowerCase(); 3475 quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" ); 3476 } 3477 return quick; 3478 }, 3479 quickIs = function( elem, m ) { 3480 var attrs = elem.attributes || {}; 3481 return ( 3482 (!m[1] || elem.nodeName.toLowerCase() === m[1]) && 3483 (!m[2] || (attrs.id || {}).value === m[2]) && 3484 (!m[3] || m[3].test( (attrs[ "class" ] || {}).value )) 3485 ); 3486 }, 3487 hoverHack = function( events ) { 3488 return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" ); 3489 }; 3490 3491/* 3492 * Helper functions for managing events -- not part of the public interface. 3493 * Props to Dean Edwards' addEvent library for many of the ideas. 3494 */ 3495jQuery.event = { 3496 3497 add: function( elem, types, handler, data, selector ) { 3498 3499 var elemData, eventHandle, events, 3500 t, tns, type, namespaces, handleObj, 3501 handleObjIn, quick, handlers, special; 3502 3503 // Don't attach events to noData or text/comment nodes (allow plain objects tho) 3504 if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) { 3505 return; 3506 } 3507 3508 // Caller can pass in an object of custom data in lieu of the handler 3509 if ( handler.handler ) { 3510 handleObjIn = handler; 3511 handler = handleObjIn.handler; 3512 } 3513 3514 // Make sure that the handler has a unique ID, used to find/remove it later 3515 if ( !handler.guid ) { 3516 handler.guid = jQuery.guid++; 3517 } 3518 3519 // Init the element's event structure and main handler, if this is the first 3520 events = elemData.events; 3521 if ( !events ) { 3522 elemData.events = events = {}; 3523 } 3524 eventHandle = elemData.handle; 3525 if ( !eventHandle ) { 3526 elemData.handle = eventHandle = function( e ) { 3527 // Discard the second event of a jQuery.event.trigger() and 3528 // when an event is called after a page has unloaded 3529 return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? 3530 jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : 3531 undefined; 3532 }; 3533 // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events 3534 eventHandle.elem = elem; 3535 } 3536 3537 // Handle multiple events separated by a space 3538 // jQuery(...).bind("mouseover mouseout", fn); 3539 types = jQuery.trim( hoverHack(types) ).split( " " ); 3540 for ( t = 0; t < types.length; t++ ) { 3541 3542 tns = rtypenamespace.exec( types[t] ) || []; 3543 type = tns[1];
vendor: 4,277 bytes, lines 3544-3678
3544 namespaces = ( tns[2] || "" ).split( "." ).sort(); 3545 3546 // If event changes its type, use the special event handlers for the changed type 3547 special = jQuery.event.special[ type ] || {}; 3548 3549 // If selector defined, determine special event api type, otherwise given type 3550 type = ( selector ? special.delegateType : special.bindType ) || type; 3551 3552 // Update special based on newly reset type 3553 special = jQuery.event.special[ type ] || {}; 3554 3555 // handleObj is passed to all event handlers 3556 handleObj = jQuery.extend({ 3557 type: type, 3558 origType: tns[1], 3559 data: data, 3560 handler: handler, 3561 guid: handler.guid, 3562 selector: selector, 3563 quick: quickParse( selector ), 3564 namespace: namespaces.join(".") 3565 }, handleObjIn ); 3566 3567 // Init the event handler queue if we're the first 3568 handlers = events[ type ]; 3569 if ( !handlers ) { 3570 handlers = events[ type ] = []; 3571 handlers.delegateCount = 0; 3572 3573 // Only use addEventListener/attachEvent if the special events handler returns false 3574 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { 3575 // Bind the global event handler to the element 3576 if ( elem.addEventListener ) { 3577 elem.addEventListener( type, eventHandle, false ); 3578 3579 } else if ( elem.attachEvent ) { 3580 elem.attachEvent( "on" + type, eventHandle ); 3581 } 3582 } 3583 } 3584 3585 if ( special.add ) { 3586 special.add.call( elem, handleObj ); 3587 3588 if ( !handleObj.handler.guid ) { 3589 handleObj.handler.guid = handler.guid; 3590 } 3591 } 3592 3593 // Add to the element's handler list, delegates in front 3594 if ( selector ) { 3595 handlers.splice( handlers.delegateCount++, 0, handleObj ); 3596 } else { 3597 handlers.push( handleObj ); 3598 } 3599 3600 // Keep track of which events have ever been used, for event optimization 3601 jQuery.event.global[ type ] = true; 3602 } 3603 3604 // Nullify elem to prevent memory leaks in IE 3605 elem = null; 3606 }, 3607 3608 global: {}, 3609 3610 // Detach an event or set of events from an element 3611 remove: function( elem, types, handler, selector, mappedTypes ) { 3612 3613 var elemData = jQuery.hasData( elem ) && jQuery._data( elem ), 3614 t, tns, type, origType, namespaces, origCount, 3615 j, events, special, handle, eventType, handleObj; 3616 3617 if ( !elemData || !(events = elemData.events) ) { 3618 return; 3619 } 3620 3621 // Once for each type.namespace in types; type may be omitted 3622 types = jQuery.trim( hoverHack( types || "" ) ).split(" "); 3623 for ( t = 0; t < types.length; t++ ) { 3624 tns = rtypenamespace.exec( types[t] ) || []; 3625 type = origType = tns[1]; 3626 namespaces = tns[2]; 3627 3628 // Unbind all events (on this namespace, if provided) for the element 3629 if ( !type ) { 3630 for ( type in events ) { 3631 jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); 3632 } 3633 continue; 3634 } 3635 3636 special = jQuery.event.special[ type ] || {}; 3637 type = ( selector? special.delegateType : special.bindType ) || type; 3638 eventType = events[ type ] || []; 3639 origCount = eventType.length; 3640 namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null; 3641 3642 // Remove matching events 3643 for ( j = 0; j < eventType.length; j++ ) { 3644 handleObj = eventType[ j ]; 3645 3646 if ( ( mappedTypes || origType === handleObj.origType ) && 3647 ( !handler || handler.guid === handleObj.guid ) && 3648 ( !namespaces || namespaces.test( handleObj.namespace ) ) && 3649 ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { 3650 eventType.splice( j--, 1 ); 3651 3652 if ( handleObj.selector ) { 3653 eventType.delegateCount--; 3654 } 3655 if ( special.remove ) { 3656 special.remove.call( elem, handleObj ); 3657 } 3658 } 3659 } 3660 3661 // Remove generic event handler if we removed something and no more handlers exist 3662 // (avoids potential for endless recursion during removal of special event handlers) 3663 if ( eventType.length === 0 && origCount !== eventType.length ) { 3664 if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { 3665 jQuery.removeEvent( elem, type, elemData.handle ); 3666 } 3667 3668 delete events[ type ]; 3669 } 3670 } 3671 3672 // Remove the expando if it's no longer used 3673 if ( jQuery.isEmptyObject( events ) ) { 3674 handle = elemData.handle; 3675 if ( handle ) { 3676 handle.elem = null; 3677 } 3678
3679 // removeData also checks for emptiness and clears the expando if empty 3680 // so use it instead of delete 3681 jQuery.removeData( elem, [ "events", "handle" ], true ); 3682 } 3683 }, 3684 3685 // Events that are safe to short-circuit if no handlers are attached. 3686 // Native DOM events should not be added, they may have inline handlers. 3687 customEvent: { 3688 "getData": true, 3689 "setData": true, 3690 "changeData": true 3691 }, 3692 3693 trigger: function( event, data, elem, onlyHandlers ) { 3694 // Don't do events on text and comment nodes 3695 if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) { 3696 return; 3697 } 3698 3699 // Event object or event type 3700 var type = event.type || event, 3701 namespaces = [], 3702 cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType; 3703 3704 // focus/blur morphs to focusin/out; ensure we're not firing them right now 3705 if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { 3706 return; 3707 } 3708 3709 if ( type.indexOf( "!" ) >= 0 ) { 3710 // Exclusive events trigger only for the exact event (no namespaces) 3711 type = type.slice(0, -1); 3712 exclusive = true; 3713 } 3714 3715 if ( type.indexOf( "." ) >= 0 ) { 3716 // Namespaced trigger; create a regexp to match event type in handle() 3717 namespaces = type.split("."); 3718 type = namespaces.shift(); 3719 namespaces.sort(); 3720 } 3721 3722 if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { 3723 // No jQuery handlers for this event type, and it can't have inline handlers 3724 return; 3725 } 3726 3727 // Caller can pass in an Event, Object, or just an event type string 3728 event = typeof event === "object" ? 3729 // jQuery.Event object 3730 event[ jQuery.expando ] ? event : 3731 // Object literal 3732 new jQuery.Event( type, event ) : 3733 // Just the event type (string) 3734 new jQuery.Event( type ); 3735 3736 event.type = type; 3737 event.isTrigger = true; 3738 event.exclusive = exclusive; 3739 event.namespace = namespaces.join( "." ); 3740 event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null; 3741 ontype = type.indexOf( ":" ) < 0 ? "on" + type : ""; 3742 3743 // Handle a global trigger 3744 if ( !elem ) { 3745 3746 // TODO: Stop taunting the data cache; remove global events and always attach to document 3747 cache = jQuery.cache; 3748 for ( i in cache ) { 3749 if ( cache[ i ].events && cache[ i ].events[ type ] ) { 3750 jQuery.event.trigger( event, data, cache[ i ].handle.elem, true ); 3751 } 3752 } 3753 return; 3754 } 3755 3756 // Clean up the event in case it is being reused 3757 event.result = undefined; 3758 if ( !event.target ) { 3759 event.target = elem; 3760 } 3761 3762 // Clone any incoming data and prepend the event, creating the handler arg list 3763 data = data != null ? jQuery.makeArray( data ) : []; 3764 data.unshift( event ); 3765 3766 // Allow special events to draw outside the lines 3767 special = jQuery.event.special[ type ] || {}; 3768 if ( special.trigger && special.trigger.apply( elem, data ) === false ) { 3769 return; 3770 } 3771 3772 // Determine event propagation path in advance, per W3C events spec (#9951) 3773 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) 3774 eventPath = [[ elem, special.bindType || type ]]; 3775 if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { 3776 3777 bubbleType = special.delegateType || type; 3778 cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode; 3779 old = null; 3780 for ( ; cur; cur = cur.parentNode ) { 3781 eventPath.push([ cur, bubbleType ]); 3782 old = cur; 3783 } 3784 3785 // Only add window if we got to document (e.g., not plain obj or detached DOM) 3786 if ( old && old === elem.ownerDocument ) { 3787 eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]); 3788 } 3789 } 3790 3791 // Fire handlers on the event path 3792 for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) { 3793 3794 cur = eventPath[i][0]; 3795 event.type = eventPath[i][1]; 3796 3797 handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); 3798 if ( handle ) { 3799 handle.apply( cur, data ); 3800 } 3801 // Note that this is a bare JS function and not a jQuery handler 3802 handle = ontype && cur[ ontype ]; 3803 if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) { 3804 event.preventDefault(); 3805 } 3806 } 3807 event.type = type; 3808 3809 // If nobody prevented the default action, do it now 3810 if ( !onlyHandlers && !event.isDefaultPrevented() ) { 3811 3812 if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && 3813 !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { 3814 3815 // Call a native DOM method on the target with the same name name as the event. 3816 // Can't use an .isFunction() check here because IE6/7 fails that test. 3817 // Don't do default actions on window, that's where global variables be (#6170) 3818 // IE<9 dies on focus/blur to hidden element (#1486) 3819 if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) { 3820 3821 // Don't re-trigger an onFOO event when we call its FOO() method 3822 old = elem[ ontype ]; 3823 3824 if ( old ) { 3825 elem[ ontype ] = null; 3826 } 3827 3828 // Prevent re-triggering of the same event, since we already bubbled it above 3829 jQuery.event.triggered = type; 3830 elem[ type ](); 3831 jQuery.event.triggered = undefined; 3832 3833 if ( old ) { 3834 elem[ ontype ] = old; 3835 } 3836 } 3837 } 3838 } 3839 3840 return event.result; 3841 }, 3842 3843 dispatch: function( event ) { 3844 3845 // Make a writable jQuery.Event from the native event object 3846 event = jQuery.event.fix( event || window.event ); 3847 3848 var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []), 3849 delegateCount = handlers.delegateCount, 3850 args = [].slice.call( arguments, 0 ), 3851 run_all = !event.exclusive && !event.namespace, 3852 handlerQueue = [], 3853 i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related; 3854 3855 // Use the fix-ed jQuery.Event rather than the (read-only) native event 3856 args[0] = event; 3857 event.delegateTarget = this; 3858 3859 // Determine handlers that should run if there are delegated events 3860 // Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861) 3861 if ( delegateCount && !event.target.disabled && !(event.button && event.type === "click") ) { 3862 3863 // Pregenerate a single jQuery object for reuse with .is() 3864 jqcur = jQuery(this); 3865 jqcur.context = this.ownerDocument || this; 3866 3867 for ( cur = event.target; cur != this; cur = cur.parentNode || this ) { 3868 selMatch = {}; 3869 matches = []; 3870 jqcur[0] = cur; 3871 for ( i = 0; i < delegateCount; i++ ) { 3872 handleObj = handlers[ i ]; 3873 sel = handleObj.selector; 3874 3875 if ( selMatch[ sel ] === undefined ) { 3876 selMatch[ sel ] = ( 3877 handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel ) 3878 ); 3879 } 3880 if ( selMatch[ sel ] ) { 3881 matches.push( handleObj ); 3882 } 3883 } 3884 if ( matches.length ) { 3885 handlerQueue.push({ elem: cur, matches: matches }); 3886 } 3887 } 3888 } 3889 3890 // Add the remaining (directly-bound) handlers 3891 if ( handlers.length > delegateCount ) { 3892 handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) }); 3893 } 3894 3895 // Run delegates first; they may want to stop propagation beneath us 3896 for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) { 3897 matched = handlerQueue[ i ]; 3898 event.currentTarget = matched.elem; 3899 3900 for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) { 3901 handleObj = matched.matches[ j ]; 3902 3903 // Triggered event must either 1) be non-exclusive and have no namespace, or 3904 // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). 3905 if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) { 3906 3907 event.data = handleObj.data; 3908 event.handleObj = handleObj; 3909 3910 ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) 3911 .apply( matched.elem, args ); 3912 3913 if ( ret !== undefined ) { 3914 event.result = ret; 3915 if ( ret === false ) { 3916 event.preventDefault(); 3917 event.stopPropagation(); 3918 } 3919 } 3920 } 3921 } 3922 } 3923 3924 return event.result; 3925 }, 3926 3927 // Includes some event props shared by KeyEvent and MouseEvent 3928 // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 *** 3929 props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), 3930 3931 fixHooks: {}, 3932 3933 keyHooks: {
vendor: 15,758 bytes, lines 3934-4495
3934 props: "char charCode key keyCode".split(" "), 3935 filter: function( event, original ) { 3936 3937 // Add which for key events 3938 if ( event.which == null ) { 3939 event.which = original.charCode != null ? original.charCode : original.keyCode; 3940 } 3941 3942 return event; 3943 } 3944 }, 3945 3946 mouseHooks: { 3947 props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), 3948 filter: function( event, original ) { 3949 var eventDoc, doc, body, 3950 button = original.button, 3951 fromElement = original.fromElement; 3952 3953 // Calculate pageX/Y if missing and clientX/Y available 3954 if ( event.pageX == null && original.clientX != null ) { 3955 eventDoc = event.target.ownerDocument || document; 3956 doc = eventDoc.documentElement; 3957 body = eventDoc.body; 3958 3959 event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); 3960 event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); 3961 } 3962 3963 // Add relatedTarget, if necessary 3964 if ( !event.relatedTarget && fromElement ) { 3965 event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; 3966 } 3967 3968 // Add which for click: 1 === left; 2 === middle; 3 === right 3969 // Note: button is not normalized, so don't use it 3970 if ( !event.which && button !== undefined ) { 3971 event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); 3972 } 3973 3974 return event; 3975 } 3976 }, 3977 3978 fix: function( event ) { 3979 if ( event[ jQuery.expando ] ) { 3980 return event; 3981 } 3982 3983 // Create a writable copy of the event object and normalize some properties 3984 var i, prop, 3985 originalEvent = event, 3986 fixHook = jQuery.event.fixHooks[ event.type ] || {}, 3987 copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; 3988 3989 event = jQuery.Event( originalEvent ); 3990 3991 for ( i = copy.length; i; ) { 3992 prop = copy[ --i ]; 3993 event[ prop ] = originalEvent[ prop ]; 3994 } 3995 3996 // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2) 3997 if ( !event.target ) { 3998 event.target = originalEvent.srcElement || document; 3999 } 4000 4001 // Target should not be a text node (#504, Safari) 4002 if ( event.target.nodeType === 3 ) { 4003 event.target = event.target.parentNode; 4004 } 4005 4006 // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8) 4007 if ( event.metaKey === undefined ) { 4008 event.metaKey = event.ctrlKey; 4009 } 4010 4011 return fixHook.filter? fixHook.filter( event, originalEvent ) : event; 4012 }, 4013 4014 special: { 4015 ready: { 4016 // Make sure the ready event is setup 4017 setup: jQuery.bindReady 4018 }, 4019 4020 load: { 4021 // Prevent triggered image.load events from bubbling to window.load 4022 noBubble: true 4023 }, 4024 4025 focus: { 4026 delegateType: "focusin" 4027 }, 4028 blur: { 4029 delegateType: "focusout" 4030 }, 4031 4032 beforeunload: { 4033 setup: function( data, namespaces, eventHandle ) { 4034 // We only want to do this special case on windows 4035 if ( jQuery.isWindow( this ) ) { 4036 this.onbeforeunload = eventHandle; 4037 } 4038 }, 4039 4040 teardown: function( namespaces, eventHandle ) { 4041 if ( this.onbeforeunload === eventHandle ) { 4042 this.onbeforeunload = null; 4043 } 4044 } 4045 } 4046 }, 4047 4048 simulate: function( type, elem, event, bubble ) { 4049 // Piggyback on a donor event to simulate a different one. 4050 // Fake originalEvent to avoid donor's stopPropagation, but if the 4051 // simulated event prevents default then we do the same on the donor. 4052 var e = jQuery.extend( 4053 new jQuery.Event(), 4054 event, 4055 { type: type, 4056 isSimulated: true, 4057 originalEvent: {} 4058 } 4059 ); 4060 if ( bubble ) { 4061 jQuery.event.trigger( e, null, elem ); 4062 } else { 4063 jQuery.event.dispatch.call( elem, e ); 4064 } 4065 if ( e.isDefaultPrevented() ) { 4066 event.preventDefault(); 4067 } 4068 } 4069}; 4070 4071// Some plugins are using, but it's undocumented/deprecated and will be removed. 4072// The 1.7 special event interface should provide all the hooks needed now. 4073jQuery.event.handle = jQuery.event.dispatch; 4074 4075jQuery.removeEvent = document.removeEventListener ? 4076 function( elem, type, handle ) { 4077 if ( elem.removeEventListener ) { 4078 elem.removeEventListener( type, handle, false ); 4079 } 4080 } : 4081 function( elem, type, handle ) { 4082 if ( elem.detachEvent ) { 4083 elem.detachEvent( "on" + type, handle ); 4084 } 4085 }; 4086 4087jQuery.Event = function( src, props ) { 4088 // Allow instantiation without the 'new' keyword 4089 if ( !(this instanceof jQuery.Event) ) { 4090 return new jQuery.Event( src, props ); 4091 } 4092 4093 // Event object 4094 if ( src && src.type ) { 4095 this.originalEvent = src; 4096 this.type = src.type; 4097 4098 // Events bubbling up the document may have been marked as prevented 4099 // by a handler lower down the tree; reflect the correct value. 4100 this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || 4101 src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; 4102 4103 // Event type 4104 } else { 4105 this.type = src; 4106 } 4107 4108 // Put explicitly provided properties onto the event object 4109 if ( props ) { 4110 jQuery.extend( this, props ); 4111 } 4112 4113 // Create a timestamp if incoming event doesn't have one 4114 this.timeStamp = src && src.timeStamp || jQuery.now(); 4115 4116 // Mark it as fixed 4117 this[ jQuery.expando ] = true; 4118}; 4119 4120function returnFalse() { 4121 return false; 4122} 4123function returnTrue() { 4124 return true; 4125} 4126 4127// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding 4128// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html 4129jQuery.Event.prototype = { 4130 preventDefault: function() { 4131 this.isDefaultPrevented = returnTrue; 4132 4133 var e = this.originalEvent; 4134 if ( !e ) { 4135 return; 4136 } 4137 4138 // if preventDefault exists run it on the original event 4139 if ( e.preventDefault ) { 4140 e.preventDefault(); 4141 4142 // otherwise set the returnValue property of the original event to false (IE) 4143 } else { 4144 e.returnValue = false; 4145 } 4146 }, 4147 stopPropagation: function() { 4148 this.isPropagationStopped = returnTrue; 4149 4150 var e = this.originalEvent; 4151 if ( !e ) { 4152 return; 4153 } 4154 // if stopPropagation exists run it on the original event 4155 if ( e.stopPropagation ) { 4156 e.stopPropagation(); 4157 } 4158 // otherwise set the cancelBubble property of the original event to true (IE) 4159 e.cancelBubble = true; 4160 }, 4161 stopImmediatePropagation: function() { 4162 this.isImmediatePropagationStopped = returnTrue; 4163 this.stopPropagation(); 4164 }, 4165 isDefaultPrevented: returnFalse, 4166 isPropagationStopped: returnFalse, 4167 isImmediatePropagationStopped: returnFalse 4168}; 4169 4170// Create mouseenter/leave events using mouseover/out and event-time checks 4171jQuery.each({ 4172 mouseenter: "mouseover", 4173 mouseleave: "mouseout" 4174}, function( orig, fix ) { 4175 jQuery.event.special[ orig ] = { 4176 delegateType: fix, 4177 bindType: fix, 4178 4179 handle: function( event ) { 4180 var target = this, 4181 related = event.relatedTarget, 4182 handleObj = event.handleObj, 4183 selector = handleObj.selector, 4184 ret; 4185 4186 // For mousenter/leave call the handler if related is outside the target. 4187 // NB: No relatedTarget if the mouse left/entered the browser window 4188 if ( !related || (related !== target && !jQuery.contains( target, related )) ) { 4189 event.type = handleObj.origType; 4190 ret = handleObj.handler.apply( this, arguments ); 4191 event.type = fix; 4192 } 4193 return ret; 4194 } 4195 }; 4196}); 4197 4198// IE submit delegation 4199if ( !jQuery.support.submitBubbles ) { 4200 4201 jQuery.event.special.submit = { 4202 setup: function() { 4203 // Only need this for delegated form submit events 4204 if ( jQuery.nodeName( this, "form" ) ) { 4205 return false; 4206 } 4207 4208 // Lazy-add a submit handler when a descendant form may potentially be submitted 4209 jQuery.event.add( this, "click._submit keypress._submit", function( e ) { 4210 // Node name check avoids a VML-related crash in IE (#9807) 4211 var elem = e.target, 4212 form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; 4213 if ( form && !form._submit_attached ) { 4214 jQuery.event.add( form, "submit._submit", function( event ) { 4215 // If form was submitted by the user, bubble the event up the tree 4216 if ( this.parentNode && !event.isTrigger ) { 4217 jQuery.event.simulate( "submit", this.parentNode, event, true ); 4218 } 4219 }); 4220 form._submit_attached = true; 4221 } 4222 }); 4223 // return undefined since we don't need an event listener 4224 }, 4225 4226 teardown: function() { 4227 // Only need this for delegated form submit events 4228 if ( jQuery.nodeName( this, "form" ) ) { 4229 return false; 4230 } 4231 4232 // Remove delegated handlers; cleanData eventually reaps submit handlers attached above 4233 jQuery.event.remove( this, "._submit" ); 4234 } 4235 }; 4236} 4237 4238// IE change delegation and checkbox/radio fix 4239if ( !jQuery.support.changeBubbles ) { 4240 4241 jQuery.event.special.change = { 4242 4243 setup: function() { 4244 4245 if ( rformElems.test( this.nodeName ) ) { 4246 // IE doesn't fire change on a check/radio until blur; trigger it on click 4247 // after a propertychange. Eat the blur-change in special.change.handle. 4248 // This still fires onchange a second time for check/radio after blur. 4249 if ( this.type === "checkbox" || this.type === "radio" ) { 4250 jQuery.event.add( this, "propertychange._change", function( event ) { 4251 if ( event.originalEvent.propertyName === "checked" ) { 4252 this._just_changed = true; 4253 } 4254 }); 4255 jQuery.event.add( this, "click._change", function( event ) { 4256 if ( this._just_changed && !event.isTrigger ) { 4257 this._just_changed = false; 4258 jQuery.event.simulate( "change", this, event, true ); 4259 } 4260 }); 4261 } 4262 return false; 4263 } 4264 // Delegated event; lazy-add a change handler on descendant inputs 4265 jQuery.event.add( this, "beforeactivate._change", function( e ) { 4266 var elem = e.target; 4267 4268 if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) { 4269 jQuery.event.add( elem, "change._change", function( event ) { 4270 if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { 4271 jQuery.event.simulate( "change", this.parentNode, event, true ); 4272 } 4273 }); 4274 elem._change_attached = true; 4275 } 4276 }); 4277 }, 4278 4279 handle: function( event ) { 4280 var elem = event.target; 4281 4282 // Swallow native change events from checkbox/radio, we already triggered them above 4283 if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { 4284 return event.handleObj.handler.apply( this, arguments ); 4285 } 4286 }, 4287 4288 teardown: function() { 4289 jQuery.event.remove( this, "._change" ); 4290 4291 return rformElems.test( this.nodeName ); 4292 } 4293 }; 4294} 4295 4296// Create "bubbling" focus and blur events 4297if ( !jQuery.support.focusinBubbles ) { 4298 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { 4299 4300 // Attach a single capturing handler while someone wants focusin/focusout 4301 var attaches = 0, 4302 handler = function( event ) { 4303 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); 4304 }; 4305 4306 jQuery.event.special[ fix ] = { 4307 setup: function() { 4308 if ( attaches++ === 0 ) { 4309 document.addEventListener( orig, handler, true ); 4310 } 4311 }, 4312 teardown: function() { 4313 if ( --attaches === 0 ) { 4314 document.removeEventListener( orig, handler, true ); 4315 } 4316 } 4317 }; 4318 }); 4319} 4320 4321jQuery.fn.extend({ 4322 4323 on: function( types, selector, data, fn, /*INTERNAL*/ one ) { 4324 var origFn, type; 4325 4326 // Types can be a map of types/handlers 4327 if ( typeof types === "object" ) { 4328 // ( types-Object, selector, data ) 4329 if ( typeof selector !== "string" ) { 4330 // ( types-Object, data ) 4331 data = selector; 4332 selector = undefined; 4333 } 4334 for ( type in types ) { 4335 this.on( type, selector, data, types[ type ], one ); 4336 } 4337 return this; 4338 } 4339 4340 if ( data == null && fn == null ) { 4341 // ( types, fn ) 4342 fn = selector; 4343 data = selector = undefined; 4344 } else if ( fn == null ) { 4345 if ( typeof selector === "string" ) { 4346 // ( types, selector, fn ) 4347 fn = data; 4348 data = undefined; 4349 } else { 4350 // ( types, data, fn ) 4351 fn = data; 4352 data = selector; 4353 selector = undefined; 4354 } 4355 } 4356 if ( fn === false ) { 4357 fn = returnFalse; 4358 } else if ( !fn ) { 4359 return this; 4360 } 4361 4362 if ( one === 1 ) { 4363 origFn = fn; 4364 fn = function( event ) { 4365 // Can use an empty set, since event contains the info 4366 jQuery().off( event ); 4367 return origFn.apply( this, arguments ); 4368 }; 4369 // Use same guid so caller can remove using origFn 4370 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); 4371 } 4372 return this.each( function() { 4373 jQuery.event.add( this, types, fn, data, selector ); 4374 }); 4375 }, 4376 one: function( types, selector, data, fn ) { 4377 return this.on.call( this, types, selector, data, fn, 1 ); 4378 }, 4379 off: function( types, selector, fn ) { 4380 if ( types && types.preventDefault && types.handleObj ) { 4381 // ( event ) dispatched jQuery.Event 4382 var handleObj = types.handleObj; 4383 jQuery( types.delegateTarget ).off( 4384 handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type, 4385 handleObj.selector, 4386 handleObj.handler 4387 ); 4388 return this; 4389 } 4390 if ( typeof types === "object" ) { 4391 // ( types-object [, selector] ) 4392 for ( var type in types ) { 4393 this.off( type, selector, types[ type ] ); 4394 } 4395 return this; 4396 } 4397 if ( selector === false || typeof selector === "function" ) { 4398 // ( types [, fn] ) 4399 fn = selector; 4400 selector = undefined; 4401 } 4402 if ( fn === false ) { 4403 fn = returnFalse; 4404 } 4405 return this.each(function() { 4406 jQuery.event.remove( this, types, fn, selector ); 4407 }); 4408 }, 4409 4410 bind: function( types, data, fn ) { 4411 return this.on( types, null, data, fn ); 4412 }, 4413 unbind: function( types, fn ) { 4414 return this.off( types, null, fn ); 4415 }, 4416 4417 live: function( types, data, fn ) { 4418 jQuery( this.context ).on( types, this.selector, data, fn ); 4419 return this; 4420 }, 4421 die: function( types, fn ) { 4422 jQuery( this.context ).off( types, this.selector || "**", fn ); 4423 return this; 4424 }, 4425 4426 delegate: function( selector, types, data, fn ) { 4427 return this.on( types, selector, data, fn ); 4428 }, 4429 undelegate: function( selector, types, fn ) { 4430 // ( namespace ) or ( selector, types [, fn] ) 4431 return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn ); 4432 }, 4433 4434 trigger: function( type, data ) { 4435 return this.each(function() { 4436 jQuery.event.trigger( type, data, this ); 4437 }); 4438 }, 4439 triggerHandler: function( type, data ) { 4440 if ( this[0] ) { 4441 return jQuery.event.trigger( type, data, this[0], true ); 4442 } 4443 }, 4444 4445 toggle: function( fn ) { 4446 // Save reference to arguments for access in closure 4447 var args = arguments, 4448 guid = fn.guid || jQuery.guid++, 4449 i = 0, 4450 toggler = function( event ) { 4451 // Figure out which function to execute 4452 var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; 4453 jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); 4454 4455 // Make sure that clicks stop 4456 event.preventDefault(); 4457 4458 // and execute the function 4459 return args[ lastToggle ].apply( this, arguments ) || false; 4460 }; 4461 4462 // link all the functions, so any of them can unbind this click handler 4463 toggler.guid = guid; 4464 while ( i < args.length ) { 4465 args[ i++ ].guid = guid; 4466 } 4467 4468 return this.click( toggler ); 4469 }, 4470 4471 hover: function( fnOver, fnOut ) { 4472 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); 4473 } 4474}); 4475 4476jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + 4477 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + 4478 "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { 4479 4480 // Handle event binding 4481 jQuery.fn[ name ] = function( data, fn ) { 4482 if ( fn == null ) { 4483 fn = data; 4484 data = null; 4485 } 4486 4487 return arguments.length > 0 ? 4488 this.on( name, null, data, fn ) : 4489 this.trigger( name ); 4490 }; 4491 4492 if ( jQuery.attrFn ) { 4493 jQuery.attrFn[ name ] = true; 4494 } 4495
4496 if ( rkeyEvent.test( name ) ) { 4497 jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks; 4498 } 4499 4500 if ( rmouseEvent.test( name ) ) { 4501 jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; 4502 } 4503}); 4504 4505 4506 4507/*! 4508 * Sizzle CSS Selector Engine 4509 * Copyright 2011, The Dojo Foundation 4510 * Released under the MIT, BSD, and GPL Licenses. 4511 * More information: http://sizzlejs.com/ 4512 */ 4513(function(){ 4514 4515var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, 4516 expando = "sizcache" + (Math.random() + '').replace('.', ''), 4517 done = 0, 4518 toString = Object.prototype.toString, 4519 hasDuplicate = false, 4520 baseHasDuplicate = true, 4521 rBackslash = /\\/g, 4522 rReturn = /\r\n/g, 4523 rNonWord = /\W/; 4524 4525// Here we check if the JavaScript engine is using some sort of 4526// optimization where it does not always call our comparision 4527// function. If that is the case, discard the hasDuplicate value. 4528// Thus far that includes Google Chrome. 4529[0, 0].sort(function() { 4530 baseHasDuplicate = false; 4531 return 0; 4532}); 4533 4534var Sizzle = function( selector, context, results, seed ) { 4535 results = results || []; 4536 context = context || document; 4537 4538 var origContext = context; 4539 4540 if ( context.nodeType !== 1 && context.nodeType !== 9 ) { 4541 return []; 4542 } 4543 4544 if ( !selector || typeof selector !== "string" ) { 4545 return results; 4546 } 4547 4548 var m, set, checkSet, extra, ret, cur, pop, i, 4549 prune = true, 4550 contextXML = Sizzle.isXML( context ), 4551 parts = [], 4552 soFar = selector; 4553 4554 // Reset the position of the chunker regexp (start from head) 4555 do { 4556 chunker.exec( "" ); 4557 m = chunker.exec( soFar ); 4558 4559 if ( m ) { 4560 soFar = m[3]; 4561 4562 parts.push( m[1] ); 4563 4564 if ( m[2] ) { 4565 extra = m[3]; 4566 break; 4567 } 4568 } 4569 } while ( m ); 4570 4571 if ( parts.length > 1 && origPOS.exec( selector ) ) { 4572 4573 if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { 4574 set = posProcess( parts[0] + parts[1], context, seed ); 4575 4576 } else { 4577 set = Expr.relative[ parts[0] ] ? 4578 [ context ] : 4579 Sizzle( parts.shift(), context ); 4580 4581 while ( parts.length ) { 4582 selector = parts.shift(); 4583 4584 if ( Expr.relative[ selector ] ) { 4585 selector += parts.shift(); 4586 } 4587 4588 set = posProcess( selector, set, seed ); 4589 } 4590 } 4591 4592 } else { 4593 // Take a shortcut and set the context if the root selector is an ID 4594 // (but not if it'll be faster if the inner selector is an ID) 4595 if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && 4596 Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { 4597 4598 ret = Sizzle.find( parts.shift(), context, contextXML ); 4599 context = ret.expr ? 4600 Sizzle.filter( ret.expr, ret.set )[0] : 4601 ret.set[0]; 4602 } 4603 4604 if ( context ) { 4605 ret = seed ? 4606 { expr: parts.pop(), set: makeArray(seed) } : 4607 Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); 4608 4609 set = ret.expr ? 4610 Sizzle.filter( ret.expr, ret.set ) : 4611 ret.set; 4612 4613 if ( parts.length > 0 ) { 4614 checkSet = makeArray( set ); 4615 4616 } else { 4617 prune = false;
4618 } 4619 4620 while ( parts.length ) { 4621 cur = parts.pop(); 4622 pop = cur; 4623 4624 if ( !Expr.relative[ cur ] ) { 4625 cur = ""; 4626 } else { 4627 pop = parts.pop(); 4628 } 4629 4630 if ( pop == null ) { 4631 pop = context; 4632 } 4633 4634 Expr.relative[ cur ]( checkSet, pop, contextXML ); 4635 } 4636 4637 } else { 4638 checkSet = parts = []; 4639 } 4640 } 4641 4642 if ( !checkSet ) { 4643 checkSet = set; 4644 } 4645 4646 if ( !checkSet ) { 4647 Sizzle.error( cur || selector ); 4648 } 4649 4650 if ( toString.call(checkSet) === "[object Array]" ) { 4651 if ( !prune ) { 4652 results.push.apply( results, checkSet ); 4653 4654 } else if ( context && context.nodeType === 1 ) { 4655 for ( i = 0; checkSet[i] != null; i++ ) { 4656 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { 4657 results.push( set[i] ); 4658 } 4659 } 4660 4661 } else { 4662 for ( i = 0; checkSet[i] != null; i++ ) { 4663 if ( checkSet[i] && checkSet[i].nodeType === 1 ) { 4664 results.push( set[i] ); 4665 } 4666 } 4667 } 4668 4669 } else { 4670 makeArray( checkSet, results ); 4671 } 4672 4673 if ( extra ) { 4674 Sizzle( extra, origContext, results, seed ); 4675 Sizzle.uniqueSort( results ); 4676 } 4677 4678 return results; 4679}; 4680 4681Sizzle.uniqueSort = function( results ) { 4682 if ( sortOrder ) { 4683 hasDuplicate = baseHasDuplicate; 4684 results.sort( sortOrder ); 4685 4686 if ( hasDuplicate ) { 4687 for ( var i = 1; i < results.length; i++ ) { 4688 if ( results[i] === results[ i - 1 ] ) { 4689 results.splice( i--, 1 ); 4690 } 4691 } 4692 } 4693 } 4694 4695 return results; 4696}; 4697 4698Sizzle.matches = function( expr, set ) { 4699 return Sizzle( expr, null, null, set ); 4700}; 4701 4702Sizzle.matchesSelector = function( node, expr ) { 4703 return Sizzle( expr, null, null, [node] ).length > 0; 4704}; 4705 4706Sizzle.find = function( expr, context, isXML ) { 4707 var set, i, len, match, type, left; 4708 4709 if ( !expr ) { 4710 return []; 4711 } 4712 4713 for ( i = 0, len = Expr.order.length; i < len; i++ ) { 4714 type = Expr.order[i]; 4715 4716 if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { 4717 left = match[1]; 4718 match.splice( 1, 1 ); 4719 4720 if ( left.substr( left.length - 1 ) !== "\\" ) { 4721 match[1] = (match[1] || "").replace( rBackslash, "" ); 4722 set = Expr.find[ type ]( match, context, isXML ); 4723 4724 if ( set != null ) { 4725 expr = expr.replace( Expr.match[ type ], "" ); 4726 break; 4727 } 4728 } 4729 } 4730 } 4731 4732 if ( !set ) { 4733 set = typeof context.getElementsByTagName !== "undefined" ? 4734 context.getElementsByTagName( "*" ) : 4735 []; 4736 } 4737 4738 return { set: set, expr: expr }; 4739}; 4740 4741Sizzle.filter = function( expr, set, inplace, not ) { 4742 var match, anyFound, 4743 type, found, item, filter, left, 4744 i, pass, 4745 old = expr, 4746 result = [], 4747 curLoop = set, 4748 isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); 4749 4750 while ( expr && set.length ) { 4751 for ( type in Expr.filter ) { 4752 if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { 4753 filter = Expr.filter[ type ]; 4754 left = match[1]; 4755 4756 anyFound = false; 4757 4758 match.splice(1,1); 4759 4760 if ( left.substr( left.length - 1 ) === "\\" ) { 4761 continue; 4762 } 4763 4764 if ( curLoop === result ) { 4765 result = []; 4766 } 4767 4768 if ( Expr.preFilter[ type ] ) { 4769 match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); 4770 4771 if ( !match ) { 4772 anyFound = found = true; 4773 4774 } else if ( match === true ) { 4775 continue; 4776 } 4777 } 4778 4779 if ( match ) { 4780 for ( i = 0; (item = curLoop[i]) != null; i++ ) { 4781 if ( item ) { 4782 found = filter( item, match, i, curLoop ); 4783 pass = not ^ found; 4784 4785 if ( inplace && found != null ) { 4786 if ( pass ) { 4787 anyFound = true; 4788 4789 } else { 4790 curLoop[i] = false; 4791 } 4792 4793 } else if ( pass ) { 4794 result.push( item ); 4795 anyFound = true; 4796 } 4797 } 4798 } 4799 } 4800 4801 if ( found !== undefined ) { 4802 if ( !inplace ) { 4803 curLoop = result; 4804 } 4805 4806 expr = expr.replace( Expr.match[ type ], "" ); 4807 4808 if ( !anyFound ) { 4809 return []; 4810 } 4811 4812 break; 4813 } 4814 } 4815 } 4816 4817 // Improper expression 4818 if ( expr === old ) { 4819 if ( anyFound == null ) { 4820 Sizzle.error( expr ); 4821 4822 } else { 4823 break; 4824 } 4825 } 4826 4827 old = expr; 4828 } 4829 4830 return curLoop; 4831}; 4832 4833Sizzle.error = function( msg ) { 4834 throw new Error( "Syntax error, unrecognized expression: " + msg ); 4835}; 4836 4837/** 4838 * Utility function for retreiving the text value of an array of DOM nodes 4839 * @param {Array|Element} elem 4840 */ 4841var getText = Sizzle.getText = function( elem ) { 4842 var i, node, 4843 nodeType = elem.nodeType, 4844 ret = ""; 4845 4846 if ( nodeType ) { 4847 if ( nodeType === 1 || nodeType === 9 ) { 4848 // Use textContent || innerText for elements 4849 if ( typeof elem.textContent === 'string' ) { 4850 return elem.textContent; 4851 } else if ( typeof elem.innerText === 'string' ) { 4852 // Replace IE's carriage returns 4853 return elem.innerText.replace( rReturn, '' ); 4854 } else { 4855 // Traverse it's children 4856 for ( elem = elem.firstChild; elem; elem = elem.nextSibling) { 4857 ret += getText( elem ); 4858 } 4859 } 4860 } else if ( nodeType === 3 || nodeType === 4 ) { 4861 return elem.nodeValue; 4862 } 4863 } else { 4864 4865 // If no nodeType, this is expected to be an array 4866 for ( i = 0; (node = elem[i]); i++ ) {
4867 // Do not traverse comment nodes 4868 if ( node.nodeType !== 8 ) { 4869 ret += getText( node ); 4870 } 4871 } 4872 } 4873 return ret; 4874}; 4875 4876var Expr = Sizzle.selectors = { 4877 order: [ "ID", "NAME", "TAG" ], 4878 4879 match: { 4880 ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, 4881 CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, 4882 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, 4883 ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, 4884 TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, 4885 CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, 4886 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, 4887 PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ 4888 }, 4889 4890 leftMatch: {}, 4891 4892 attrMap: { 4893 "class": "className", 4894 "for": "htmlFor" 4895 }, 4896 4897 attrHandle: { 4898 href: function( elem ) { 4899 return elem.getAttribute( "href" ); 4900 }, 4901 type: function( elem ) { 4902 return elem.getAttribute( "type" ); 4903 } 4904 }, 4905 4906 relative: { 4907 "+": function(checkSet, part){ 4908 var isPartStr = typeof part === "string", 4909 isTag = isPartStr && !rNonWord.test( part ), 4910 isPartStrNotTag = isPartStr && !isTag; 4911 4912 if ( isTag ) { 4913 part = part.toLowerCase(); 4914 } 4915 4916 for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { 4917 if ( (elem = checkSet[i]) ) { 4918 while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} 4919 4920 checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? 4921 elem || false : 4922 elem === part; 4923 } 4924 } 4925 4926 if ( isPartStrNotTag ) { 4927 Sizzle.filter( part, checkSet, true ); 4928 } 4929 }, 4930 4931 ">": function( checkSet, part ) { 4932 var elem, 4933 isPartStr = typeof part === "string", 4934 i = 0, 4935 l = checkSet.length; 4936 4937 if ( isPartStr && !rNonWord.test( part ) ) { 4938 part = part.toLowerCase(); 4939 4940 for ( ; i < l; i++ ) { 4941 elem = checkSet[i]; 4942 4943 if ( elem ) { 4944 var parent = elem.parentNode; 4945 checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; 4946 } 4947 } 4948 4949 } else { 4950 for ( ; i < l; i++ ) { 4951 elem = checkSet[i]; 4952 4953 if ( elem ) { 4954 checkSet[i] = isPartStr ? 4955 elem.parentNode : 4956 elem.parentNode === part; 4957 } 4958 } 4959 4960 if ( isPartStr ) { 4961 Sizzle.filter( part, checkSet, true ); 4962 } 4963 } 4964 }, 4965 4966 "": function(checkSet, part, isXML){ 4967 var nodeCheck, 4968 doneName = done++, 4969 checkFn = dirCheck; 4970 4971 if ( typeof part === "string" && !rNonWord.test( part ) ) { 4972 part = part.toLowerCase(); 4973 nodeCheck = part; 4974 checkFn = dirNodeCheck; 4975 } 4976 4977 checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); 4978 }, 4979 4980 "~": function( checkSet, part, isXML ) { 4981 var nodeCheck, 4982 doneName = done++, 4983 checkFn = dirCheck; 4984 4985 if ( typeof part === "string" && !rNonWord.test( part ) ) { 4986 part = part.toLowerCase(); 4987 nodeCheck = part; 4988 checkFn = dirNodeCheck; 4989 } 4990 4991 checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); 4992 } 4993 }, 4994 4995 find: { 4996 ID: function( match, context, isXML ) { 4997 if ( typeof context.getElementById !== "undefined" && !isXML ) { 4998 var m = context.getElementById(match[1]); 4999 // Check parentNode to catch when Blackberry 4.6 returns 5000 // nodes that are no longer in the document #6963 5001 return m && m.parentNode ? [m] : []; 5002 } 5003 }, 5004 5005 NAME: function( match, context ) { 5006 if ( typeof context.getElementsByName !== "undefined" ) { 5007 var ret = [], 5008 results = context.getElementsByName( match[1] ); 5009 5010 for ( var i = 0, l = results.length; i < l; i++ ) { 5011 if ( results[i].getAttribute("name") === match[1] ) { 5012 ret.push( results[i] ); 5013 } 5014 } 5015 5016 return ret.length === 0 ? null : ret; 5017 } 5018 }, 5019 5020 TAG: function( match, context ) { 5021 if ( typeof context.getElementsByTagName !== "undefined" ) { 5022 return context.getElementsByTagName( match[1] ); 5023 } 5024 } 5025 }, 5026 preFilter: { 5027 CLASS: function( match, curLoop, inplace, result, not, isXML ) { 5028 match = " " + match[1].replace( rBackslash, "" ) + " "; 5029 5030 if ( isXML ) { 5031 return match; 5032 } 5033 5034 for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { 5035 if ( elem ) { 5036 if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { 5037 if ( !inplace ) { 5038 result.push( elem ); 5039 } 5040 5041 } else if ( inplace ) { 5042 curLoop[i] = false;
5043 } 5044 } 5045 } 5046 5047 return false; 5048 }, 5049 5050 ID: function( match ) { 5051 return match[1].replace( rBackslash, "" ); 5052 }, 5053 5054 TAG: function( match, curLoop ) { 5055 return match[1].replace( rBackslash, "" ).toLowerCase(); 5056 }, 5057 5058 CHILD: function( match ) { 5059 if ( match[1] === "nth" ) { 5060 if ( !match[2] ) { 5061 Sizzle.error( match[0] ); 5062 } 5063 5064 match[2] = match[2].replace(/^\+|\s*/g, ''); 5065 5066 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' 5067 var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( 5068 match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || 5069 !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); 5070 5071 // calculate the numbers (first)n+(last) including if they are negative 5072 match[2] = (test[1] + (test[2] || 1)) - 0; 5073 match[3] = test[3] - 0; 5074 } 5075 else if ( match[2] ) { 5076 Sizzle.error( match[0] ); 5077 } 5078 5079 // TODO: Move to normal caching system 5080 match[0] = done++; 5081 5082 return match; 5083 }, 5084 5085 ATTR: function( match, curLoop, inplace, result, not, isXML ) { 5086 var name = match[1] = match[1].replace( rBackslash, "" ); 5087 5088 if ( !isXML && Expr.attrMap[name] ) { 5089 match[1] = Expr.attrMap[name]; 5090 } 5091 5092 // Handle if an un-quoted value was used 5093 match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); 5094 5095 if ( match[2] === "~=" ) { 5096 match[4] = " " + match[4] + " "; 5097 } 5098 5099 return match; 5100 }, 5101 5102 PSEUDO: function( match, curLoop, inplace, result, not ) { 5103 if ( match[1] === "not" ) { 5104 // If we're dealing with a complex expression, or a simple one 5105 if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { 5106 match[3] = Sizzle(match[3], null, null, curLoop); 5107 5108 } else { 5109 var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); 5110 5111 if ( !inplace ) { 5112 result.push.apply( result, ret ); 5113 } 5114 5115 return false; 5116 } 5117 5118 } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { 5119 return true; 5120 } 5121 5122 return match; 5123 }, 5124 5125 POS: function( match ) { 5126 match.unshift( true ); 5127 5128 return match; 5129 } 5130 }, 5131 5132 filters: { 5133 enabled: function( elem ) { 5134 return elem.disabled === false && elem.type !== "hidden"; 5135 }, 5136 5137 disabled: function( elem ) { 5138 return elem.disabled === true; 5139 }, 5140 5141 checked: function( elem ) { 5142 return elem.checked === true; 5143 }, 5144 5145 selected: function( elem ) { 5146 // Accessing this property makes selected-by-default 5147 // options in Safari work properly 5148 if ( elem.parentNode ) { 5149 elem.parentNode.selectedIndex; 5150 } 5151 5152 return elem.selected === true; 5153 }, 5154 5155 parent: function( elem ) { 5156 return !!elem.firstChild; 5157 }, 5158 5159 empty: function( elem ) { 5160 return !elem.firstChild; 5161 }, 5162 5163 has: function( elem, i, match ) { 5164 return !!Sizzle( match[3], elem ).length; 5165 }, 5166 5167 header: function( elem ) { 5168 return (/h\d/i).test( elem.nodeName ); 5169 }, 5170 5171 text: function( elem ) { 5172 var attr = elem.getAttribute( "type" ), type = elem.type; 5173 // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) 5174 // use getAttribute instead to test this case 5175 return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); 5176 }, 5177 5178 radio: function( elem ) { 5179 return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; 5180 }, 5181 5182 checkbox: function( elem ) { 5183 return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; 5184 }, 5185 5186 file: function( elem ) { 5187 return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; 5188 }, 5189 5190 password: function( elem ) { 5191 return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; 5192 }, 5193 5194 submit: function( elem ) { 5195 var name = elem.nodeName.toLowerCase(); 5196 return (name === "input" || name === "button") && "submit" === elem.type; 5197 }, 5198 5199 image: function( elem ) { 5200 return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; 5201 }, 5202 5203 reset: function( elem ) { 5204 var name = elem.nodeName.toLowerCase(); 5205 return (name === "input" || name === "button") && "reset" === elem.type; 5206 }, 5207 5208 button: function( elem ) { 5209 var name = elem.nodeName.toLowerCase(); 5210 return name === "input" && "button" === elem.type || name === "button"; 5211 }, 5212 5213 input: function( elem ) { 5214 return (/input|select|textarea|button/i).test( elem.nodeName ); 5215 }, 5216 5217 focus: function( elem ) { 5218 return elem === elem.ownerDocument.activeElement; 5219 } 5220 }, 5221 setFilters: { 5222 first: function( elem, i ) { 5223 return i === 0; 5224 }, 5225 5226 last: function( elem, i, match, array ) { 5227 return i === array.length - 1; 5228 }, 5229 5230 even: function( elem, i ) { 5231 return i % 2 === 0; 5232 }, 5233 5234 odd: function( elem, i ) { 5235 return i % 2 === 1; 5236 }, 5237 5238 lt: function( elem, i, match ) { 5239 return i < match[3] - 0; 5240 }, 5241 5242 gt: function( elem, i, match ) { 5243 return i > match[3] - 0; 5244 }, 5245 5246 nth: function( elem, i, match ) { 5247 return match[3] - 0 === i; 5248 }, 5249 5250 eq: function( elem, i, match ) { 5251 return match[3] - 0 === i; 5252 } 5253 }, 5254 filter: { 5255 PSEUDO: function( elem, match, i, array ) { 5256 var name = match[1], 5257 filter = Expr.filters[ name ]; 5258 5259 if ( filter ) { 5260 return filter( elem, i, match, array ); 5261 5262 } else if ( name === "contains" ) { 5263 return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; 5264 5265 } else if ( name === "not" ) { 5266 var not = match[3]; 5267 5268 for ( var j = 0, l = not.length; j < l; j++ ) { 5269 if ( not[j] === elem ) { 5270 return false;
5271 } 5272 } 5273 5274 return true; 5275 5276 } else { 5277 Sizzle.error( name ); 5278 } 5279 }, 5280 5281 CHILD: function( elem, match ) { 5282 var first, last, 5283 doneName, parent, cache, 5284 count, diff, 5285 type = match[1], 5286 node = elem; 5287 5288 switch ( type ) { 5289 case "only": 5290 case "first": 5291 while ( (node = node.previousSibling) ) { 5292 if ( node.nodeType === 1 ) { 5293 return false; 5294 } 5295 } 5296 5297 if ( type === "first" ) { 5298 return true; 5299 } 5300 5301 node = elem; 5302 5303 case "last": 5304 while ( (node = node.nextSibling) ) { 5305 if ( node.nodeType === 1 ) { 5306 return false; 5307 } 5308 } 5309 5310 return true; 5311 5312 case "nth": 5313 first = match[2]; 5314 last = match[3]; 5315 5316 if ( first === 1 && last === 0 ) { 5317 return true; 5318 } 5319 5320 doneName = match[0]; 5321 parent = elem.parentNode; 5322 5323 if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) { 5324 count = 0; 5325 5326 for ( node = parent.firstChild; node; node = node.nextSibling ) { 5327 if ( node.nodeType === 1 ) { 5328 node.nodeIndex = ++count; 5329 } 5330 } 5331 5332 parent[ expando ] = doneName; 5333 } 5334 5335 diff = elem.nodeIndex - last; 5336 5337 if ( first === 0 ) { 5338 return diff === 0; 5339 5340 } else { 5341 return ( diff % first === 0 && diff / first >= 0 ); 5342 } 5343 } 5344 }, 5345 5346 ID: function( elem, match ) { 5347 return elem.nodeType === 1 && elem.getAttribute("id") === match; 5348 }, 5349 5350 TAG: function( elem, match ) { 5351 return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match; 5352 }, 5353 5354 CLASS: function( elem, match ) { 5355 return (" " + (elem.className || elem.getAttribute("class")) + " ") 5356 .indexOf( match ) > -1; 5357 }, 5358 5359 ATTR: function( elem, match ) { 5360 var name = match[1], 5361 result = Sizzle.attr ? 5362 Sizzle.attr( elem, name ) : 5363 Expr.attrHandle[ name ] ? 5364 Expr.attrHandle[ name ]( elem ) : 5365 elem[ name ] != null ? 5366 elem[ name ] : 5367 elem.getAttribute( name ), 5368 value = result + "", 5369 type = match[2], 5370 check = match[4]; 5371 5372 return result == null ? 5373 type === "!=" : 5374 !type && Sizzle.attr ? 5375 result != null : 5376 type === "=" ? 5377 value === check : 5378 type === "*=" ? 5379 value.indexOf(check) >= 0 : 5380 type === "~=" ? 5381 (" " + value + " ").indexOf(check) >= 0 : 5382 !check ? 5383 value && result !== false : 5384 type === "!=" ? 5385 value !== check : 5386 type === "^=" ? 5387 value.indexOf(check) === 0 : 5388 type === "$=" ? 5389 value.substr(value.length - check.length) === check : 5390 type === "|=" ? 5391 value === check || value.substr(0, check.length + 1) === check + "-" : 5392 false; 5393 }, 5394 5395 POS: function( elem, match, i, array ) { 5396 var name = match[2], 5397 filter = Expr.setFilters[ name ]; 5398 5399 if ( filter ) { 5400 return filter( elem, i, match, array ); 5401 } 5402 } 5403 } 5404}; 5405 5406var origPOS = Expr.match.POS, 5407 fescape = function(all, num){ 5408 return "\\" + (num - 0 + 1); 5409 }; 5410 5411for ( var type in Expr.match ) { 5412 Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); 5413 Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); 5414} 5415 5416var makeArray = function( array, results ) { 5417 array = Array.prototype.slice.call( array, 0 ); 5418 5419 if ( results ) { 5420 results.push.apply( results, array ); 5421 return results; 5422 } 5423 5424 return array; 5425}; 5426 5427// Perform a simple check to determine if the browser is capable of 5428// converting a NodeList to an array using builtin methods. 5429// Also verifies that the returned array holds DOM nodes 5430// (which is not the case in the Blackberry browser) 5431try { 5432 Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; 5433 5434// Provide a fallback method if it does not work 5435} catch( e ) { 5436 makeArray = function( array, results ) { 5437 var i = 0, 5438 ret = results || []; 5439 5440 if ( toString.call(array) === "[object Array]" ) { 5441 Array.prototype.push.apply( ret, array ); 5442 5443 } else { 5444 if ( typeof array.length === "number" ) { 5445 for ( var l = array.length; i < l; i++ ) { 5446 ret.push( array[i] ); 5447 } 5448 5449 } else { 5450 for ( ; array[i]; i++ ) {
5451 ret.push( array[i] ); 5452 } 5453 } 5454 } 5455 5456 return ret; 5457 }; 5458} 5459 5460var sortOrder, siblingCheck; 5461 5462if ( document.documentElement.compareDocumentPosition ) { 5463 sortOrder = function( a, b ) { 5464 if ( a === b ) { 5465 hasDuplicate = true; 5466 return 0; 5467 } 5468 5469 if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { 5470 return a.compareDocumentPosition ? -1 : 1; 5471 } 5472 5473 return a.compareDocumentPosition(b) & 4 ? -1 : 1; 5474 }; 5475 5476} else { 5477 sortOrder = function( a, b ) { 5478 // The nodes are identical, we can exit early 5479 if ( a === b ) { 5480 hasDuplicate = true; 5481 return 0; 5482 5483 // Fallback to using sourceIndex (in IE) if it's available on both nodes 5484 } else if ( a.sourceIndex && b.sourceIndex ) { 5485 return a.sourceIndex - b.sourceIndex; 5486 } 5487 5488 var al, bl, 5489 ap = [], 5490 bp = [], 5491 aup = a.parentNode, 5492 bup = b.parentNode, 5493 cur = aup; 5494 5495 // If the nodes are siblings (or identical) we can do a quick check 5496 if ( aup === bup ) { 5497 return siblingCheck( a, b ); 5498 5499 // If no parents were found then the nodes are disconnected 5500 } else if ( !aup ) { 5501 return -1; 5502 5503 } else if ( !bup ) { 5504 return 1; 5505 } 5506 5507 // Otherwise they're somewhere else in the tree so we need 5508 // to build up a full list of the parentNodes for comparison 5509 while ( cur ) { 5510 ap.unshift( cur ); 5511 cur = cur.parentNode; 5512 } 5513 5514 cur = bup; 5515 5516 while ( cur ) { 5517 bp.unshift( cur ); 5518 cur = cur.parentNode; 5519 } 5520 5521 al = ap.length; 5522 bl = bp.length; 5523 5524 // Start walking down the tree looking for a discrepancy 5525 for ( var i = 0; i < al && i < bl; i++ ) { 5526 if ( ap[i] !== bp[i] ) { 5527 return siblingCheck( ap[i], bp[i] ); 5528 } 5529 } 5530 5531 // We ended someplace up the tree so do a sibling check 5532 return i === al ? 5533 siblingCheck( a, bp[i], -1 ) : 5534 siblingCheck( ap[i], b, 1 ); 5535 }; 5536 5537 siblingCheck = function( a, b, ret ) { 5538 if ( a === b ) { 5539 return ret; 5540 } 5541 5542 var cur = a.nextSibling; 5543 5544 while ( cur ) { 5545 if ( cur === b ) { 5546 return -1; 5547 } 5548 5549 cur = cur.nextSibling; 5550 } 5551 5552 return 1; 5553 }; 5554} 5555 5556// Check to see if the browser returns elements by name when 5557// querying by getElementById (and provide a workaround) 5558(function(){ 5559 // We're going to inject a fake input element with a specified name 5560 var form = document.createElement("div"), 5561 id = "script" + (new Date()).getTime(), 5562 root = document.documentElement; 5563 5564 form.innerHTML = "<a name='" + id + "'/>"; 5565 5566 // Inject it into the root element, check its status, and remove it quickly 5567 root.insertBefore( form, root.firstChild ); 5568 5569 // The workaround has to do additional checks after a getElementById 5570 // Which slows things down for other browsers (hence the branching) 5571 if ( document.getElementById( id ) ) { 5572 Expr.find.ID = function( match, context, isXML ) { 5573 if ( typeof context.getElementById !== "undefined" && !isXML ) { 5574 var m = context.getElementById(match[1]); 5575 5576 return m ? 5577 m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? 5578 [m] : 5579 undefined : 5580 []; 5581 } 5582 }; 5583 5584 Expr.filter.ID = function( elem, match ) { 5585 var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); 5586 5587 return elem.nodeType === 1 && node && node.nodeValue === match; 5588 }; 5589 } 5590 5591 root.removeChild( form ); 5592 5593 // release memory in IE 5594 root = form = null; 5595})(); 5596 5597(function(){ 5598 // Check to see if the browser returns only elements 5599 // when doing getElementsByTagName("*") 5600 5601 // Create a fake element 5602 var div = document.createElement("div"); 5603 div.appendChild( document.createComment("") ); 5604 5605 // Make sure no comments are found 5606 if ( div.getElementsByTagName("*").length > 0 ) { 5607 Expr.find.TAG = function( match, context ) { 5608 var results = context.getElementsByTagName( match[1] ); 5609 5610 // Filter out possible comments 5611 if ( match[1] === "*" ) { 5612 var tmp = []; 5613 5614 for ( var i = 0; results[i]; i++ ) { 5615 if ( results[i].nodeType === 1 ) { 5616 tmp.push( results[i] ); 5617 } 5618 } 5619 5620 results = tmp; 5621 } 5622 5623 return results; 5624 }; 5625 } 5626 5627 // Check to see if an attribute returns normalized href attributes 5628 div.innerHTML = "<a href='#'></a>"; 5629 5630 if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && 5631 div.firstChild.getAttribute("href") !== "#" ) { 5632 5633 Expr.attrHandle.href = function( elem ) { 5634 return elem.getAttribute( "href", 2 ); 5635 }; 5636 } 5637 5638 // release memory in IE 5639 div = null; 5640})(); 5641 5642if ( document.querySelectorAll ) { 5643 (function(){
5644 var oldSizzle = Sizzle, 5645 div = document.createElement("div"), 5646 id = "__sizzle__"; 5647 5648 div.innerHTML = "<p class='TEST'></p>"; 5649 5650 // Safari can't handle uppercase or unicode characters when 5651 // in quirks mode. 5652 if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { 5653 return; 5654 } 5655 5656 Sizzle = function( query, context, extra, seed ) { 5657 context = context || document; 5658 5659 // Only use querySelectorAll on non-XML documents 5660 // (ID selectors don't work in non-HTML documents) 5661 if ( !seed && !Sizzle.isXML(context) ) { 5662 // See if we find a selector to speed up 5663 var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); 5664 5665 if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { 5666 // Speed-up: Sizzle("TAG") 5667 if ( match[1] ) { 5668 return makeArray( context.getElementsByTagName( query ), extra ); 5669 5670 // Speed-up: Sizzle(".CLASS") 5671 } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { 5672 return makeArray( context.getElementsByClassName( match[2] ), extra ); 5673 } 5674 } 5675 5676 if ( context.nodeType === 9 ) { 5677 // Speed-up: Sizzle("body") 5678 // The body element only exists once, optimize finding it 5679 if ( query === "body" && context.body ) { 5680 return makeArray( [ context.body ], extra ); 5681 5682 // Speed-up: Sizzle("#ID") 5683 } else if ( match && match[3] ) { 5684 var elem = context.getElementById( match[3] ); 5685 5686 // Check parentNode to catch when Blackberry 4.6 returns 5687 // nodes that are no longer in the document #6963 5688 if ( elem && elem.parentNode ) { 5689 // Handle the case where IE and Opera return items 5690 // by name instead of ID 5691 if ( elem.id === match[3] ) { 5692 return makeArray( [ elem ], extra ); 5693 } 5694 5695 } else { 5696 return makeArray( [], extra ); 5697 } 5698 } 5699 5700 try { 5701 return makeArray( context.querySelectorAll(query), extra ); 5702 } catch(qsaError) {} 5703 5704 // qSA works strangely on Element-rooted queries 5705 // We can work around this by specifying an extra ID on the root 5706 // and working up from there (Thanks to Andrew Dupont for the technique) 5707 // IE 8 doesn't work on object elements 5708 } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { 5709 var oldContext = context, 5710 old = context.getAttribute( "id" ), 5711 nid = old || id, 5712 hasParent = context.parentNode, 5713 relativeHierarchySelector = /^\s*[+~]/.test( query ); 5714 5715 if ( !old ) { 5716 context.setAttribute( "id", nid ); 5717 } else { 5718 nid = nid.replace( /'/g, "\\$&" ); 5719 } 5720 if ( relativeHierarchySelector && hasParent ) { 5721 context = context.parentNode; 5722 } 5723 5724 try { 5725 if ( !relativeHierarchySelector || hasParent ) { 5726 return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); 5727 } 5728 5729 } catch(pseudoError) { 5730 } finally { 5731 if ( !old ) { 5732 oldContext.removeAttribute( "id" ); 5733 } 5734 } 5735 } 5736 } 5737 5738 return oldSizzle(query, context, extra, seed); 5739 }; 5740 5741 for ( var prop in oldSizzle ) { 5742 Sizzle[ prop ] = oldSizzle[ prop ]; 5743 } 5744 5745 // release memory in IE 5746 div = null; 5747 })(); 5748} 5749 5750(function(){ 5751 var html = document.documentElement, 5752 matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; 5753 5754 if ( matches ) { 5755 // Check to see if it's possible to do matchesSelector 5756 // on a disconnected node (IE 9 fails this) 5757 var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), 5758 pseudoWorks = false; 5759 5760 try { 5761 // This should fail with an exception 5762 // Gecko does not error, returns false instead
5763 matches.call( document.documentElement, "[test!='']:sizzle" ); 5764 5765 } catch( pseudoError ) { 5766 pseudoWorks = true; 5767 } 5768 5769 Sizzle.matchesSelector = function( node, expr ) { 5770 // Make sure that attribute selectors are quoted 5771 expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); 5772 5773 if ( !Sizzle.isXML( node ) ) { 5774 try { 5775 if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { 5776 var ret = matches.call( node, expr ); 5777 5778 // IE 9's matchesSelector returns false on disconnected nodes 5779 if ( ret || !disconnectedMatch || 5780 // As well, disconnected nodes are said to be in a document 5781 // fragment in IE 9, so check for that 5782 node.document && node.document.nodeType !== 11 ) { 5783 return ret; 5784 } 5785 } 5786 } catch(e) {} 5787 } 5788 5789 return Sizzle(expr, null, null, [node]).length > 0; 5790 }; 5791 } 5792})(); 5793 5794(function(){ 5795 var div = document.createElement("div"); 5796 5797 div.innerHTML = "<div class='test e'></div><div class='test'></div>"; 5798 5799 // Opera can't find a second classname (in 9.6) 5800 // Also, make sure that getElementsByClassName actually exists 5801 if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { 5802 return; 5803 } 5804 5805 // Safari caches class attributes, doesn't catch changes (in 3.2) 5806 div.lastChild.className = "e"; 5807 5808 if ( div.getElementsByClassName("e").length === 1 ) { 5809 return; 5810 } 5811 5812 Expr.order.splice(1, 0, "CLASS"); 5813 Expr.find.CLASS = function( match, context, isXML ) { 5814 if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { 5815 return context.getElementsByClassName(match[1]); 5816 } 5817 }; 5818 5819 // release memory in IE 5820 div = null; 5821})(); 5822 5823function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { 5824 for ( var i = 0, l = checkSet.length; i < l; i++ ) { 5825 var elem = checkSet[i]; 5826 5827 if ( elem ) { 5828 var match = false; 5829 5830 elem = elem[dir]; 5831 5832 while ( elem ) { 5833 if ( elem[ expando ] === doneName ) { 5834 match = checkSet[elem.sizset]; 5835 break; 5836 } 5837 5838 if ( elem.nodeType === 1 && !isXML ){ 5839 elem[ expando ] = doneName; 5840 elem.sizset = i; 5841 } 5842 5843 if ( elem.nodeName.toLowerCase() === cur ) { 5844 match = elem; 5845 break; 5846 } 5847 5848 elem = elem[dir]; 5849 } 5850 5851 checkSet[i] = match; 5852 } 5853 } 5854} 5855 5856function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { 5857 for ( var i = 0, l = checkSet.length; i < l; i++ ) { 5858 var elem = checkSet[i]; 5859 5860 if ( elem ) { 5861 var match = false; 5862 5863 elem = elem[dir]; 5864 5865 while ( elem ) { 5866 if ( elem[ expando ] === doneName ) { 5867 match = checkSet[elem.sizset]; 5868 break; 5869 } 5870 5871 if ( elem.nodeType === 1 ) { 5872 if ( !isXML ) { 5873 elem[ expando ] = doneName; 5874 elem.sizset = i; 5875 } 5876 5877 if ( typeof cur !== "string" ) { 5878 if ( elem === cur ) { 5879 match = true; 5880 break; 5881 } 5882 5883 } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { 5884 match = elem; 5885 break; 5886 } 5887 } 5888 5889 elem = elem[dir]; 5890 } 5891 5892 checkSet[i] = match; 5893 } 5894 } 5895} 5896 5897if ( document.documentElement.contains ) { 5898 Sizzle.contains = function( a, b ) { 5899 return a !== b && (a.contains ? a.contains(b) : true); 5900 }; 5901 5902} else if ( document.documentElement.compareDocumentPosition ) { 5903 Sizzle.contains = function( a, b ) { 5904 return !!(a.compareDocumentPosition(b) & 16); 5905 }; 5906 5907} else { 5908 Sizzle.contains = function() { 5909 return false; 5910 }; 5911} 5912 5913Sizzle.isXML = function( elem ) { 5914 // documentElement is verified for cases where it doesn't yet exist 5915 // (such as loading iframes in IE - #4833) 5916 var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; 5917 5918 return documentElement ? documentElement.nodeName !== "HTML" : false; 5919}; 5920 5921var posProcess = function( selector, context, seed ) { 5922 var match, 5923 tmpSet = [], 5924 later = "", 5925 root = context.nodeType ? [context] : context; 5926 5927 // Position selectors must be done after the filter 5928 // And so must :not(positional) so we move all PSEUDOs to the end 5929 while ( (match = Expr.match.PSEUDO.exec( selector )) ) { 5930 later += match[0]; 5931 selector = selector.replace( Expr.match.PSEUDO, "" ); 5932 } 5933 5934 selector = Expr.relative[selector] ? selector + "*" : selector; 5935 5936 for ( var i = 0, l = root.length; i < l; i++ ) { 5937 Sizzle( selector, root[i], tmpSet, seed ); 5938 } 5939 5940 return Sizzle.filter( later, tmpSet ); 5941}; 5942 5943// EXPOSE 5944// Override sizzle attribute retrieval 5945Sizzle.attr = jQuery.attr; 5946Sizzle.selectors.attrMap = {}; 5947jQuery.find = Sizzle; 5948jQuery.expr = Sizzle.selectors; 5949jQuery.expr[":"] = jQuery.expr.filters; 5950jQuery.unique = Sizzle.uniqueSort; 5951jQuery.text = Sizzle.getText; 5952jQuery.isXMLDoc = Sizzle.isXML; 5953jQuery.contains = Sizzle.contains; 5954 5955 5956})(); 5957 5958 5959var runtil = /Until$/, 5960 rparentsprev = /^(?:parents|prevUntil|prevAll)/, 5961 // Note: This RegExp should be improved, or likely pulled from Sizzle 5962 rmultiselector = /,/, 5963 isSimple = /^.[^:#\[\.,]*$/, 5964 slice = Array.prototype.slice, 5965 POS = jQuery.expr.match.POS, 5966 // methods guaranteed to produce a unique set when starting from a unique set 5967 guaranteedUnique = { 5968 children: true, 5969 contents: true, 5970 next: true, 5971 prev: true 5972 }; 5973 5974jQuery.fn.extend({ 5975 find: function( selector ) { 5976 var self = this, 5977 i, l; 5978 5979 if ( typeof selector !== "string" ) {
5980 return jQuery( selector ).filter(function() { 5981 for ( i = 0, l = self.length; i < l; i++ ) { 5982 if ( jQuery.contains( self[ i ], this ) ) { 5983 return true; 5984 } 5985 } 5986 }); 5987 } 5988 5989 var ret = this.pushStack( "", "find", selector ), 5990 length, n, r; 5991 5992 for ( i = 0, l = this.length; i < l; i++ ) { 5993 length = ret.length; 5994 jQuery.find( selector, this[i], ret ); 5995 5996 if ( i > 0 ) { 5997 // Make sure that the results are unique 5998 for ( n = length; n < ret.length; n++ ) { 5999 for ( r = 0; r < length; r++ ) { 6000 if ( ret[r] === ret[n] ) { 6001 ret.splice(n--, 1); 6002 break; 6003 } 6004 } 6005 } 6006 } 6007 } 6008 6009 return ret; 6010 }, 6011 6012 has: function( target ) { 6013 var targets = jQuery( target ); 6014 return this.filter(function() { 6015 for ( var i = 0, l = targets.length; i < l; i++ ) { 6016 if ( jQuery.contains( this, targets[i] ) ) { 6017 return true; 6018 } 6019 } 6020 }); 6021 }, 6022 6023 not: function( selector ) { 6024 return this.pushStack( winnow(this, selector, false), "not", selector); 6025 }, 6026 6027 filter: function( selector ) { 6028 return this.pushStack( winnow(this, selector, true), "filter", selector ); 6029 }, 6030 6031 is: function( selector ) { 6032 return !!selector && ( 6033 typeof selector === "string" ? 6034 // If this is a positional selector, check membership in the returned set 6035 // so $("p:first").is("p:last") won't return true for a doc with two "p". 6036 POS.test( selector ) ? 6037 jQuery( selector, this.context ).index( this[0] ) >= 0 : 6038 jQuery.filter( selector, this ).length > 0 : 6039 this.filter( selector ).length > 0 ); 6040 }, 6041 6042 closest: function( selectors, context ) { 6043 var ret = [], i, l, cur = this[0]; 6044 6045 // Array (deprecated as of jQuery 1.7) 6046 if ( jQuery.isArray( selectors ) ) { 6047 var level = 1; 6048 6049 while ( cur && cur.ownerDocument && cur !== context ) { 6050 for ( i = 0; i < selectors.length; i++ ) { 6051 6052 if ( jQuery( cur ).is( selectors[ i ] ) ) { 6053 ret.push({ selector: selectors[ i ], elem: cur, level: level }); 6054 } 6055 } 6056 6057 cur = cur.parentNode; 6058 level++; 6059 } 6060 6061 return ret; 6062 } 6063 6064 // String 6065 var pos = POS.test( selectors ) || typeof selectors !== "string" ? 6066 jQuery( selectors, context || this.context ) : 6067 0; 6068 6069 for ( i = 0, l = this.length; i < l; i++ ) { 6070 cur = this[i]; 6071 6072 while ( cur ) { 6073 if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { 6074 ret.push( cur ); 6075 break; 6076 6077 } else { 6078 cur = cur.parentNode; 6079 if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { 6080 break; 6081 } 6082 } 6083 } 6084 } 6085 6086 ret = ret.length > 1 ? jQuery.unique( ret ) : ret; 6087 6088 return this.pushStack( ret, "closest", selectors ); 6089 }, 6090 6091 // Determine the position of an element within 6092 // the matched set of elements 6093 index: function( elem ) { 6094 6095 // No argument, return index in parent 6096 if ( !elem ) { 6097 return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; 6098 } 6099 6100 // index in selector 6101 if ( typeof elem === "string" ) { 6102 return jQuery.inArray( this[0], jQuery( elem ) ); 6103 } 6104 6105 // Locate the position of the desired element 6106 return jQuery.inArray( 6107 // If it receives a jQuery object, the first element is used 6108 elem.jquery ? elem[0] : elem, this ); 6109 }, 6110 6111 add: function( selector, context ) { 6112 var set = typeof selector === "string" ? 6113 jQuery( selector, context ) : 6114 jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), 6115 all = jQuery.merge( this.get(), set ); 6116 6117 return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? 6118 all : 6119 jQuery.unique( all ) ); 6120 }, 6121 6122 andSelf: function() { 6123 return this.add( this.prevObject ); 6124 } 6125}); 6126 6127// A painfully simple check to see if an element is disconnected 6128// from a document (should be improved, where feasible). 6129function isDisconnected( node ) { 6130 return !node || !node.parentNode || node.parentNode.nodeType === 11; 6131} 6132 6133jQuery.each({ 6134 parent: function( elem ) { 6135 var parent = elem.parentNode; 6136 return parent && parent.nodeType !== 11 ? parent : null; 6137 }, 6138 parents: function( elem ) { 6139 return jQuery.dir( elem, "parentNode" ); 6140 }, 6141 parentsUntil: function( elem, i, until ) { 6142 return jQuery.dir( elem, "parentNode", until ); 6143 }, 6144 next: function( elem ) { 6145 return jQuery.nth( elem, 2, "nextSibling" ); 6146 }, 6147 prev: function( elem ) { 6148 return jQuery.nth( elem, 2, "previousSibling" ); 6149 }, 6150 nextAll: function( elem ) { 6151 return jQuery.dir( elem, "nextSibling" ); 6152 }, 6153 prevAll: function( elem ) { 6154 return jQuery.dir( elem, "previousSibling" ); 6155 }, 6156 nextUntil: function( elem, i, until ) { 6157 return jQuery.dir( elem, "nextSibling", until ); 6158 }, 6159 prevUntil: function( elem, i, until ) { 6160 return jQuery.dir( elem, "previousSibling", until ); 6161 }, 6162 siblings: function( elem ) { 6163 return jQuery.sibling( elem.parentNode.firstChild, elem ); 6164 }, 6165 children: function( elem ) { 6166 return jQuery.sibling( elem.firstChild ); 6167 }, 6168 contents: function( elem ) { 6169 return jQuery.nodeName( elem, "iframe" ) ? 6170 elem.contentDocument || elem.contentWindow.document : 6171 jQuery.makeArray( elem.childNodes ); 6172 } 6173}, function( name, fn ) { 6174 jQuery.fn[ name ] = function( until, selector ) { 6175 var ret = jQuery.map( this, fn, until ); 6176 6177 if ( !runtil.test( name ) ) { 6178 selector = until; 6179 } 6180 6181 if ( selector && typeof selector === "string" ) { 6182 ret = jQuery.filter( selector, ret ); 6183 } 6184 6185 ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; 6186 6187 if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { 6188 ret = ret.reverse(); 6189 } 6190 6191 return this.pushStack( ret, name, slice.call( arguments ).join(",") ); 6192 }; 6193}); 6194 6195jQuery.extend({ 6196 filter: function( expr, elems, not ) { 6197 if ( not ) { 6198 expr = ":not(" + expr + ")"; 6199 } 6200 6201 return elems.length === 1 ? 6202 jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : 6203 jQuery.find.matches(expr, elems); 6204 }, 6205 6206 dir: function( elem, dir, until ) { 6207 var matched = [], 6208 cur = elem[ dir ]; 6209 6210 while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { 6211 if ( cur.nodeType === 1 ) { 6212 matched.push( cur ); 6213 } 6214 cur = cur[dir]; 6215 } 6216 return matched; 6217 }, 6218 6219 nth: function( cur, result, dir, elem ) { 6220 result = result || 1; 6221 var num = 0; 6222 6223 for ( ; cur; cur = cur[dir] ) { 6224 if ( cur.nodeType === 1 && ++num === result ) { 6225 break; 6226 } 6227 } 6228 6229 return cur; 6230 }, 6231 6232 sibling: function( n, elem ) { 6233 var r = []; 6234 6235 for ( ; n; n = n.nextSibling ) { 6236 if ( n.nodeType === 1 && n !== elem ) { 6237 r.push( n ); 6238 } 6239 } 6240 6241 return r; 6242 } 6243}); 6244 6245// Implement the identical functionality for filter and not 6246function winnow( elements, qualifier, keep ) { 6247 6248 // Can't pass null or undefined to indexOf in Firefox 4 6249 // Set to 0 to skip string check 6250 qualifier = qualifier || 0; 6251 6252 if ( jQuery.isFunction( qualifier ) ) { 6253 return jQuery.grep(elements, function( elem, i ) { 6254 var retVal = !!qualifier.call( elem, i, elem ); 6255 return retVal === keep; 6256 }); 6257 6258 } else if ( qualifier.nodeType ) { 6259 return jQuery.grep(elements, function( elem, i ) { 6260 return ( elem === qualifier ) === keep; 6261 }); 6262 6263 } else if ( typeof qualifier === "string" ) { 6264 var filtered = jQuery.grep(elements, function( elem ) { 6265 return elem.nodeType === 1; 6266 }); 6267 6268 if ( isSimple.test( qualifier ) ) { 6269 return jQuery.filter(qualifier, filtered, !keep); 6270 } else { 6271 qualifier = jQuery.filter( qualifier, filtered ); 6272 } 6273 } 6274 6275 return jQuery.grep(elements, function( elem, i ) { 6276 return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; 6277 }); 6278} 6279 6280 6281 6282 6283function createSafeFragment( document ) { 6284 var list = nodeNames.split( "|" ),
vendor: 3,540 bytes, lines 6285-6422
6285 safeFrag = document.createDocumentFragment(); 6286 6287 if ( safeFrag.createElement ) { 6288 while ( list.length ) { 6289 safeFrag.createElement( 6290 list.pop() 6291 ); 6292 } 6293 } 6294 return safeFrag; 6295} 6296 6297var nodeNames = "abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|" + 6298 "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", 6299 rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, 6300 rleadingWhitespace = /^\s+/, 6301 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, 6302 rtagName = /<([\w:]+)/, 6303 rtbody = /<tbody/i, 6304 rhtml = /<|&#?\w+;/, 6305 rnoInnerhtml = /<(?:script|style)/i, 6306 rnocache = /<(?:script|object|embed|option|style)/i, 6307 rnoshimcache = new RegExp("<(?:" + nodeNames + ")", "i"), 6308 // checked="checked" or checked 6309 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, 6310 rscriptType = /\/(java|ecma)script/i, 6311 rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)/, 6312 wrapMap = { 6313 option: [ 1, "<select multiple='multiple'>", "</select>" ], 6314 legend: [ 1, "<fieldset>", "</fieldset>" ], 6315 thead: [ 1, "<table>", "</table>" ], 6316 tr: [ 2, "<table><tbody>", "</tbody></table>" ], 6317 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], 6318 col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ], 6319 area: [ 1, "<map>", "</map>" ], 6320 _default: [ 0, "", "" ] 6321 }, 6322 safeFragment = createSafeFragment( document ); 6323 6324wrapMap.optgroup = wrapMap.option; 6325wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; 6326wrapMap.th = wrapMap.td; 6327 6328// IE can't serialize <link> and <script> tags normally 6329if ( !jQuery.support.htmlSerialize ) { 6330 wrapMap._default = [ 1, "div<div>", "</div>" ]; 6331} 6332 6333jQuery.fn.extend({ 6334 text: function( text ) { 6335 if ( jQuery.isFunction(text) ) { 6336 return this.each(function(i) { 6337 var self = jQuery( this ); 6338 6339 self.text( text.call(this, i, self.text()) ); 6340 }); 6341 } 6342 6343 if ( typeof text !== "object" && text !== undefined ) { 6344 return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) ); 6345 } 6346 6347 return jQuery.text( this ); 6348 }, 6349 6350 wrapAll: function( html ) { 6351 if ( jQuery.isFunction( html ) ) { 6352 return this.each(function(i) { 6353 jQuery(this).wrapAll( html.call(this, i) ); 6354 }); 6355 } 6356 6357 if ( this[0] ) { 6358 // The elements to wrap the target around 6359 var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); 6360 6361 if ( this[0].parentNode ) { 6362 wrap.insertBefore( this[0] ); 6363 } 6364 6365 wrap.map(function() { 6366 var elem = this; 6367 6368 while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { 6369 elem = elem.firstChild; 6370 } 6371 6372 return elem; 6373 }).append( this ); 6374 } 6375 6376 return this; 6377 }, 6378 6379 wrapInner: function( html ) { 6380 if ( jQuery.isFunction( html ) ) { 6381 return this.each(function(i) { 6382 jQuery(this).wrapInner( html.call(this, i) ); 6383 }); 6384 } 6385 6386 return this.each(function() { 6387 var self = jQuery( this ), 6388 contents = self.contents(); 6389 6390 if ( contents.length ) { 6391 contents.wrapAll( html ); 6392 6393 } else { 6394 self.append( html ); 6395 } 6396 }); 6397 }, 6398 6399 wrap: function( html ) { 6400 var isFunction = jQuery.isFunction( html ); 6401 6402 return this.each(function(i) { 6403 jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); 6404 }); 6405 }, 6406 6407 unwrap: function() { 6408 return this.parent().each(function() { 6409 if ( !jQuery.nodeName( this, "body" ) ) { 6410 jQuery( this ).replaceWith( this.childNodes ); 6411 } 6412 }).end(); 6413 }, 6414 6415 append: function() { 6416 return this.domManip(arguments, true, function( elem ) { 6417 if ( this.nodeType === 1 ) { 6418 this.appendChild( elem ); 6419 } 6420 }); 6421 }, 6422
6423 prepend: function() { 6424 return this.domManip(arguments, true, function( elem ) { 6425 if ( this.nodeType === 1 ) { 6426 this.insertBefore( elem, this.firstChild ); 6427 } 6428 }); 6429 }, 6430 6431 before: function() { 6432 if ( this[0] && this[0].parentNode ) { 6433 return this.domManip(arguments, false, function( elem ) { 6434 this.parentNode.insertBefore( elem, this ); 6435 }); 6436 } else if ( arguments.length ) { 6437 var set = jQuery.clean( arguments ); 6438 set.push.apply( set, this.toArray() ); 6439 return this.pushStack( set, "before", arguments ); 6440 } 6441 }, 6442 6443 after: function() { 6444 if ( this[0] && this[0].parentNode ) { 6445 return this.domManip(arguments, false, function( elem ) { 6446 this.parentNode.insertBefore( elem, this.nextSibling ); 6447 }); 6448 } else if ( arguments.length ) { 6449 var set = this.pushStack( this, "after", arguments ); 6450 set.push.apply( set, jQuery.clean(arguments) ); 6451 return set; 6452 } 6453 }, 6454 6455 // keepData is for internal use only--do not document 6456 remove: function( selector, keepData ) { 6457 for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { 6458 if ( !selector || jQuery.filter( selector, [ elem ] ).length ) { 6459 if ( !keepData && elem.nodeType === 1 ) { 6460 jQuery.cleanData( elem.getElementsByTagName("*") ); 6461 jQuery.cleanData( [ elem ] ); 6462 } 6463 6464 if ( elem.parentNode ) { 6465 elem.parentNode.removeChild( elem ); 6466 } 6467 } 6468 } 6469 6470 return this; 6471 }, 6472 6473 empty: function() { 6474 for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { 6475 // Remove element nodes and prevent memory leaks 6476 if ( elem.nodeType === 1 ) { 6477 jQuery.cleanData( elem.getElementsByTagName("*") ); 6478 } 6479 6480 // Remove any remaining nodes 6481 while ( elem.firstChild ) { 6482 elem.removeChild( elem.firstChild ); 6483 } 6484 } 6485 6486 return this; 6487 }, 6488 6489 clone: function( dataAndEvents, deepDataAndEvents ) { 6490 dataAndEvents = dataAndEvents == null ? false : dataAndEvents; 6491 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; 6492 6493 return this.map( function () { 6494 return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); 6495 }); 6496 }, 6497 6498 html: function( value ) { 6499 if ( value === undefined ) { 6500 return this[0] && this[0].nodeType === 1 ? 6501 this[0].innerHTML.replace(rinlinejQuery, "") : 6502 null; 6503 6504 // See if we can take a shortcut and just use innerHTML 6505 } else if ( typeof value === "string" && !rnoInnerhtml.test( value ) && 6506 (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) && 6507 !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) { 6508 6509 value = value.replace(rxhtmlTag, "<$1></$2>"); 6510 6511 try { 6512 for ( var i = 0, l = this.length; i < l; i++ ) { 6513 // Remove element nodes and prevent memory leaks 6514 if ( this[i].nodeType === 1 ) { 6515 jQuery.cleanData( this[i].getElementsByTagName("*") ); 6516 this[i].innerHTML = value; 6517 } 6518 } 6519 6520 // If using innerHTML throws an exception, use the fallback method 6521 } catch(e) { 6522 this.empty().append( value ); 6523 } 6524 6525 } else if ( jQuery.isFunction( value ) ) { 6526 this.each(function(i){ 6527 var self = jQuery( this ); 6528 6529 self.html( value.call(this, i, self.html()) ); 6530 }); 6531 6532 } else { 6533 this.empty().append( value ); 6534 } 6535 6536 return this; 6537 }, 6538 6539 replaceWith: function( value ) { 6540 if ( this[0] && this[0].parentNode ) { 6541 // Make sure that the elements are removed from the DOM before they are inserted 6542 // this can help fix replacing a parent with child elements 6543 if ( jQuery.isFunction( value ) ) { 6544 return this.each(function(i) { 6545 var self = jQuery(this), old = self.html(); 6546 self.replaceWith( value.call( this, i, old ) ); 6547 }); 6548 } 6549 6550 if ( typeof value !== "string" ) { 6551 value = jQuery( value ).detach(); 6552 } 6553 6554 return this.each(function() { 6555 var next = this.nextSibling, 6556 parent = this.parentNode; 6557 6558 jQuery( this ).remove(); 6559 6560 if ( next ) { 6561 jQuery(next).before( value ); 6562 } else { 6563 jQuery(parent).append( value ); 6564 } 6565 }); 6566 } else { 6567 return this.length ? 6568 this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) : 6569 this; 6570 } 6571 }, 6572 6573 detach: function( selector ) { 6574 return this.remove( selector, true ); 6575 }, 6576 6577 domManip: function( args, table, callback ) { 6578 var results, first, fragment, parent, 6579 value = args[0], 6580 scripts = []; 6581 6582 // We can't cloneNode fragments that contain checked, in WebKit 6583 if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) { 6584 return this.each(function() { 6585 jQuery(this).domManip( args, table, callback, true ); 6586 }); 6587 } 6588 6589 if ( jQuery.isFunction(value) ) { 6590 return this.each(function(i) { 6591 var self = jQuery(this); 6592 args[0] = value.call(this, i, table ? self.html() : undefined); 6593 self.domManip( args, table, callback ); 6594 }); 6595 } 6596 6597 if ( this[0] ) { 6598 parent = value && value.parentNode; 6599 6600 // If we're in a fragment, just use that instead of building a new one 6601 if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) { 6602 results = { fragment: parent }; 6603 6604 } else { 6605 results = jQuery.buildFragment( args, this, scripts ); 6606 } 6607 6608 fragment = results.fragment; 6609 6610 if ( fragment.childNodes.length === 1 ) { 6611 first = fragment = fragment.firstChild; 6612 } else { 6613 first = fragment.firstChild; 6614 } 6615 6616 if ( first ) { 6617 table = table && jQuery.nodeName( first, "tr" ); 6618 6619 for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) { 6620 callback.call( 6621 table ? 6622 root(this[i], first) : 6623 this[i], 6624 // Make sure that we do not leak memory by inadvertently discarding 6625 // the original fragment (which might have attached data) instead of 6626 // using it; in addition, use the original fragment object for the last 6627 // item instead of first because it can end up being emptied incorrectly 6628 // in certain situations (Bug #8070). 6629 // Fragments from the fragment cache must always be cloned and never used 6630 // in place. 6631 results.cacheable || ( l > 1 && i < lastIndex ) ? 6632 jQuery.clone( fragment, true, true ) : 6633 fragment 6634 ); 6635 } 6636 } 6637 6638 if ( scripts.length ) { 6639 jQuery.each( scripts, evalScript ); 6640 } 6641 } 6642 6643 return this; 6644 } 6645}); 6646 6647function root( elem, cur ) { 6648 return jQuery.nodeName(elem, "table") ? 6649 (elem.getElementsByTagName("tbody")[0] || 6650 elem.appendChild(elem.ownerDocument.createElement("tbody"))) : 6651 elem; 6652} 6653 6654function cloneCopyEvent( src, dest ) { 6655
6656 if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { 6657 return; 6658 } 6659 6660 var type, i, l, 6661 oldData = jQuery._data( src ), 6662 curData = jQuery._data( dest, oldData ), 6663 events = oldData.events; 6664 6665 if ( events ) { 6666 delete curData.handle; 6667 curData.events = {}; 6668 6669 for ( type in events ) { 6670 for ( i = 0, l = events[ type ].length; i < l; i++ ) { 6671 jQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? "." : "" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data ); 6672 } 6673 } 6674 } 6675 6676 // make the cloned public data object a copy from the original 6677 if ( curData.data ) { 6678 curData.data = jQuery.extend( {}, curData.data ); 6679 } 6680} 6681 6682function cloneFixAttributes( src, dest ) { 6683 var nodeName; 6684 6685 // We do not need to do anything for non-Elements 6686 if ( dest.nodeType !== 1 ) { 6687 return; 6688 } 6689 6690 // clearAttributes removes the attributes, which we don't want, 6691 // but also removes the attachEvent events, which we *do* want 6692 if ( dest.clearAttributes ) { 6693 dest.clearAttributes(); 6694 } 6695 6696 // mergeAttributes, in contrast, only merges back on the 6697 // original attributes, not the events 6698 if ( dest.mergeAttributes ) { 6699 dest.mergeAttributes( src ); 6700 } 6701 6702 nodeName = dest.nodeName.toLowerCase(); 6703 6704 // IE6-8 fail to clone children inside object elements that use 6705 // the proprietary classid attribute value (rather than the type 6706 // attribute) to identify the type of content to display 6707 if ( nodeName === "object" ) { 6708 dest.outerHTML = src.outerHTML; 6709 6710 } else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) { 6711 // IE6-8 fails to persist the checked state of a cloned checkbox 6712 // or radio button. Worse, IE6-7 fail to give the cloned element 6713 // a checked appearance if the defaultChecked value isn't also set 6714 if ( src.checked ) { 6715 dest.defaultChecked = dest.checked = src.checked; 6716 } 6717 6718 // IE6-7 get confused and end up setting the value of a cloned 6719 // checkbox/radio button to an empty string instead of "on" 6720 if ( dest.value !== src.value ) { 6721 dest.value = src.value; 6722 } 6723 6724 // IE6-8 fails to return the selected option to the default selected 6725 // state when cloning options 6726 } else if ( nodeName === "option" ) { 6727 dest.selected = src.defaultSelected; 6728 6729 // IE6-8 fails to set the defaultValue to the correct value when 6730 // cloning other types of input fields 6731 } else if ( nodeName === "input" || nodeName === "textarea" ) { 6732 dest.defaultValue = src.defaultValue; 6733 } 6734 6735 // Event data gets referenced instead of copied if the expando 6736 // gets copied too 6737 dest.removeAttribute( jQuery.expando ); 6738} 6739 6740jQuery.buildFragment = function( args, nodes, scripts ) { 6741 var fragment, cacheable, cacheresults, doc, 6742 first = args[ 0 ]; 6743 6744 // nodes may contain either an explicit document object, 6745 // a jQuery collection or context object. 6746 // If nodes[0] contains a valid object to assign to doc 6747 if ( nodes && nodes[0] ) { 6748 doc = nodes[0].ownerDocument || nodes[0]; 6749 } 6750 6751 // Ensure that an attr object doesn't incorrectly stand in as a document object 6752 // Chrome and Firefox seem to allow this to occur and will throw exception 6753 // Fixes #8950 6754 if ( !doc.createDocumentFragment ) { 6755 doc = document; 6756 } 6757 6758 // Only cache "small" (1/2 KB) HTML strings that are associated with the main document 6759 // Cloning options loses the selected state, so don't cache them 6760 // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment 6761 // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache 6762 // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501 6763 if ( args.length === 1 && typeof first === "string" && first.length < 512 && doc === document && 6764 first.charAt(0) === "<" && !rnocache.test( first ) && 6765 (jQuery.support.checkClone || !rchecked.test( first )) && 6766 (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) { 6767 6768 cacheable = true; 6769 6770 cacheresults = jQuery.fragments[ first ]; 6771 if ( cacheresults && cacheresults !== 1 ) { 6772 fragment = cacheresults; 6773 } 6774 } 6775 6776 if ( !fragment ) { 6777 fragment = doc.createDocumentFragment(); 6778 jQuery.clean( args, doc, fragment, scripts ); 6779 } 6780 6781 if ( cacheable ) {
6782 jQuery.fragments[ first ] = cacheresults ? fragment : 1; 6783 } 6784 6785 return { fragment: fragment, cacheable: cacheable }; 6786}; 6787 6788jQuery.fragments = {}; 6789 6790jQuery.each({ 6791 appendTo: "append", 6792 prependTo: "prepend", 6793 insertBefore: "before", 6794 insertAfter: "after", 6795 replaceAll: "replaceWith" 6796}, function( name, original ) { 6797 jQuery.fn[ name ] = function( selector ) { 6798 var ret = [], 6799 insert = jQuery( selector ), 6800 parent = this.length === 1 && this[0].parentNode; 6801 6802 if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { 6803 insert[ original ]( this[0] ); 6804 return this; 6805 6806 } else { 6807 for ( var i = 0, l = insert.length; i < l; i++ ) { 6808 var elems = ( i > 0 ? this.clone(true) : this ).get(); 6809 jQuery( insert[i] )[ original ]( elems ); 6810 ret = ret.concat( elems ); 6811 } 6812 6813 return this.pushStack( ret, name, insert.selector ); 6814 } 6815 }; 6816}); 6817 6818function getAll( elem ) { 6819 if ( typeof elem.getElementsByTagName !== "undefined" ) { 6820 return elem.getElementsByTagName( "*" ); 6821 6822 } else if ( typeof elem.querySelectorAll !== "undefined" ) { 6823 return elem.querySelectorAll( "*" ); 6824 6825 } else { 6826 return []; 6827 } 6828} 6829 6830// Used in clean, fixes the defaultChecked property 6831function fixDefaultChecked( elem ) { 6832 if ( elem.type === "checkbox" || elem.type === "radio" ) { 6833 elem.defaultChecked = elem.checked; 6834 } 6835} 6836// Finds all inputs and passes them to fixDefaultChecked 6837function findInputs( elem ) { 6838 var nodeName = ( elem.nodeName || "" ).toLowerCase(); 6839 if ( nodeName === "input" ) { 6840 fixDefaultChecked( elem ); 6841 // Skip scripts, get other children 6842 } else if ( nodeName !== "script" && typeof elem.getElementsByTagName !== "undefined" ) { 6843 jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked ); 6844 } 6845} 6846 6847// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js 6848function shimCloneNode( elem ) { 6849 var div = document.createElement( "div" ); 6850 safeFragment.appendChild( div ); 6851 6852 div.innerHTML = elem.outerHTML; 6853 return div.firstChild; 6854} 6855 6856jQuery.extend({ 6857 clone: function( elem, dataAndEvents, deepDataAndEvents ) { 6858 var srcElements, 6859 destElements, 6860 i, 6861 // IE<=8 does not properly clone detached, unknown element nodes 6862 clone = jQuery.support.html5Clone || !rnoshimcache.test( "<" + elem.nodeName ) ? 6863 elem.cloneNode( true ) : 6864 shimCloneNode( elem ); 6865 6866 if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && 6867 (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { 6868 // IE copies events bound via attachEvent when using cloneNode. 6869 // Calling detachEvent on the clone will also remove the events 6870 // from the original. In order to get around this, we use some 6871 // proprietary methods to clear the events. Thanks to MooTools 6872 // guys for this hotness. 6873 6874 cloneFixAttributes( elem, clone ); 6875 6876 // Using Sizzle here is crazy slow, so we use getElementsByTagName instead 6877 srcElements = getAll( elem ); 6878 destElements = getAll( clone ); 6879 6880 // Weird iteration because IE will replace the length property 6881 // with an element if you are cloning the body and one of the 6882 // elements on the page has a name or id of "length" 6883 for ( i = 0; srcElements[i]; ++i ) { 6884 // Ensure that the destination node is not null; Fixes #9587 6885 if ( destElements[i] ) { 6886 cloneFixAttributes( srcElements[i], destElements[i] ); 6887 } 6888 } 6889 } 6890 6891 // Copy the events from the original to the clone 6892 if ( dataAndEvents ) { 6893 cloneCopyEvent( elem, clone ); 6894 6895 if ( deepDataAndEvents ) { 6896 srcElements = getAll( elem ); 6897 destElements = getAll( clone ); 6898 6899 for ( i = 0; srcElements[i]; ++i ) { 6900 cloneCopyEvent( srcElements[i], destElements[i] ); 6901 } 6902 } 6903 } 6904 6905 srcElements = destElements = null; 6906 6907 // Return the cloned set 6908 return clone; 6909 }, 6910 6911 clean: function( elems, context, fragment, scripts ) { 6912 var checkScriptType; 6913 6914 context = context || document; 6915 6916 // !context.createElement fails in IE with an error but returns typeof 'object' 6917 if ( typeof context.createElement === "undefined" ) { 6918 context = context.ownerDocument || context[0] && context[0].ownerDocument || document; 6919 } 6920 6921 var ret = [], j; 6922 6923 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { 6924 if ( typeof elem === "number" ) { 6925 elem += ""; 6926 } 6927 6928 if ( !elem ) { 6929 continue; 6930 } 6931 6932 // Convert html string into DOM nodes 6933 if ( typeof elem === "string" ) { 6934 if ( !rhtml.test( elem ) ) { 6935 elem = context.createTextNode( elem ); 6936 } else { 6937 // Fix "XHTML"-style tags in all browsers 6938 elem = elem.replace(rxhtmlTag, "<$1></$2>"); 6939 6940 // Trim whitespace, otherwise indexOf won't work as expected 6941 var tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(), 6942 wrap = wrapMap[ tag ] || wrapMap._default, 6943 depth = wrap[0], 6944 div = context.createElement("div"); 6945 6946 // Append wrapper element to unknown element safe doc fragment 6947 if ( context === document ) { 6948 // Use the fragment we've already created for this document 6949 safeFragment.appendChild( div ); 6950 } else { 6951 // Use a fragment created with the owner document 6952 createSafeFragment( context ).appendChild( div ); 6953 } 6954 6955 // Go to html and back, then peel off extra wrappers 6956 div.innerHTML = wrap[1] + elem + wrap[2]; 6957 6958 // Move to the right depth 6959 while ( depth-- ) {
6960 div = div.lastChild; 6961 } 6962 6963 // Remove IE's autoinserted <tbody> from table fragments 6964 if ( !jQuery.support.tbody ) { 6965 6966 // String was a <table>, *may* have spurious <tbody> 6967 var hasBody = rtbody.test(elem), 6968 tbody = tag === "table" && !hasBody ? 6969 div.firstChild && div.firstChild.childNodes : 6970 6971 // String was a bare <thead> or <tfoot> 6972 wrap[1] === "<table>" && !hasBody ? 6973 div.childNodes : 6974 []; 6975 6976 for ( j = tbody.length - 1; j >= 0 ; --j ) { 6977 if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) { 6978 tbody[ j ].parentNode.removeChild( tbody[ j ] ); 6979 } 6980 } 6981 } 6982 6983 // IE completely kills leading whitespace when innerHTML is used 6984 if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { 6985 div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild ); 6986 } 6987 6988 elem = div.childNodes; 6989 } 6990 } 6991 6992 // Resets defaultChecked for any radios and checkboxes 6993 // about to be appended to the DOM in IE 6/7 (#8060) 6994 var len; 6995 if ( !jQuery.support.appendChecked ) { 6996 if ( elem[0] && typeof (len = elem.length) === "number" ) { 6997 for ( j = 0; j < len; j++ ) { 6998 findInputs( elem[j] ); 6999 } 7000 } else { 7001 findInputs( elem ); 7002 } 7003 } 7004 7005 if ( elem.nodeType ) { 7006 ret.push( elem ); 7007 } else { 7008 ret = jQuery.merge( ret, elem ); 7009 } 7010 } 7011 7012 if ( fragment ) { 7013 checkScriptType = function( elem ) { 7014 return !elem.type || rscriptType.test( elem.type ); 7015 }; 7016 for ( i = 0; ret[i]; i++ ) { 7017 if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) { 7018 scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] ); 7019 7020 } else { 7021 if ( ret[i].nodeType === 1 ) { 7022 var jsTags = jQuery.grep( ret[i].getElementsByTagName( "script" ), checkScriptType ); 7023 7024 ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) ); 7025 } 7026 fragment.appendChild( ret[i] ); 7027 } 7028 } 7029 } 7030 7031 return ret; 7032 }, 7033 7034 cleanData: function( elems ) { 7035 var data, id, 7036 cache = jQuery.cache, 7037 special = jQuery.event.special, 7038 deleteExpando = jQuery.support.deleteExpando; 7039 7040 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { 7041 if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { 7042 continue; 7043 } 7044 7045 id = elem[ jQuery.expando ]; 7046 7047 if ( id ) { 7048 data = cache[ id ]; 7049 7050 if ( data && data.events ) { 7051 for ( var type in data.events ) { 7052 if ( special[ type ] ) { 7053 jQuery.event.remove( elem, type ); 7054 7055 // This is a shortcut to avoid jQuery.event.remove's overhead 7056 } else { 7057 jQuery.removeEvent( elem, type, data.handle ); 7058 } 7059 } 7060 7061 // Null the DOM reference to avoid IE6/7/8 leak (#7054) 7062 if ( data.handle ) { 7063 data.handle.elem = null; 7064 } 7065 } 7066 7067 if ( deleteExpando ) { 7068 delete elem[ jQuery.expando ]; 7069 7070 } else if ( elem.removeAttribute ) { 7071 elem.removeAttribute( jQuery.expando ); 7072 } 7073 7074 delete cache[ id ]; 7075 } 7076 } 7077 } 7078}); 7079 7080function evalScript( i, elem ) { 7081 if ( elem.src ) { 7082 jQuery.ajax({ 7083 url: elem.src, 7084 async: false, 7085 dataType: "script" 7086 }); 7087 } else { 7088 jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "/*$0*/" ) ); 7089 } 7090 7091 if ( elem.parentNode ) { 7092 elem.parentNode.removeChild( elem ); 7093 } 7094} 7095 7096 7097 7098 7099var ralpha = /alpha\([^)]*\)/i, 7100 ropacity = /opacity=([^)]*)/, 7101 // fixed for IE9, see #8346 7102 rupper = /([A-Z]|^ms)/g, 7103 rnumpx = /^-?\d+(?:px)?$/i, 7104 rnum = /^-?\d/, 7105 rrelNum = /^([\-+])=([\-+.\de]+)/, 7106 7107 cssShow = { position: "absolute", visibility: "hidden", display: "block" }, 7108 cssWidth = [ "Left", "Right" ], 7109 cssHeight = [ "Top", "Bottom" ], 7110 curCSS, 7111 7112 getComputedStyle, 7113 currentStyle; 7114 7115jQuery.fn.css = function( name, value ) { 7116 // Setting 'undefined' is a no-op 7117 if ( arguments.length === 2 && value === undefined ) { 7118 return this; 7119 } 7120 7121 return jQuery.access( this, name, value, true, function( elem, name, value ) { 7122 return value !== undefined ? 7123 jQuery.style( elem, name, value ) : 7124 jQuery.css( elem, name ); 7125 }); 7126}; 7127 7128jQuery.extend({ 7129 // Add in style property hooks for overriding the default 7130 // behavior of getting and setting a style property 7131 cssHooks: { 7132 opacity: { 7133 get: function( elem, computed ) { 7134 if ( computed ) { 7135 // We should always get a number back from opacity 7136 var ret = curCSS( elem, "opacity", "opacity" ); 7137 return ret === "" ? "1" : ret; 7138 7139 } else { 7140 return elem.style.opacity; 7141 } 7142 } 7143 } 7144 }, 7145 7146 // Exclude the following css properties to add px 7147 cssNumber: { 7148 "fillOpacity": true, 7149 "fontWeight": true, 7150 "lineHeight": true, 7151 "opacity": true, 7152 "orphans": true, 7153 "widows": true, 7154 "zIndex": true, 7155 "zoom": true 7156 }, 7157 7158 // Add in properties whose names you wish to fix before 7159 // setting or getting the value 7160 cssProps: { 7161 // normalize float css property 7162 "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" 7163 }, 7164 7165 // Get and set the style property on a DOM Node 7166 style: function( elem, name, value, extra ) { 7167 // Don't set styles on text and comment nodes 7168 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { 7169 return; 7170 } 7171 7172 // Make sure that we're working with the right name 7173 var ret, type, origName = jQuery.camelCase( name ), 7174 style = elem.style, hooks = jQuery.cssHooks[ origName ]; 7175 7176 name = jQuery.cssProps[ origName ] || origName; 7177 7178 // Check if we're setting a value 7179 if ( value !== undefined ) { 7180 type = typeof value; 7181 7182 // convert relative number strings (+= or -=) to relative numbers. #7345 7183 if ( type === "string" && (ret = rrelNum.exec( value )) ) { 7184 value = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) ); 7185 // Fixes bug #9237 7186 type = "number"; 7187 } 7188 7189 // Make sure that NaN and null values aren't set. See: #7116 7190 if ( value == null || type === "number" && isNaN( value ) ) { 7191 return; 7192 } 7193 7194 // If a number was passed in, add 'px' to the (except for certain CSS properties) 7195 if ( type === "number" && !jQuery.cssNumber[ origName ] ) { 7196 value += "px"; 7197 } 7198 7199 // If a hook was provided, use that value, otherwise just set the specified value 7200 if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
7201 // Wrapped to prevent IE from throwing errors when 'invalid' values are provided 7202 // Fixes bug #5509 7203 try { 7204 style[ name ] = value; 7205 } catch(e) {} 7206 } 7207 7208 } else { 7209 // If a hook was provided get the non-computed value from there 7210 if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { 7211 return ret; 7212 } 7213 7214 // Otherwise just get the value from the style object 7215 return style[ name ]; 7216 } 7217 }, 7218 7219 css: function( elem, name, extra ) { 7220 var ret, hooks; 7221 7222 // Make sure that we're working with the right name 7223 name = jQuery.camelCase( name ); 7224 hooks = jQuery.cssHooks[ name ]; 7225 name = jQuery.cssProps[ name ] || name; 7226 7227 // cssFloat needs a special treatment 7228 if ( name === "cssFloat" ) { 7229 name = "float"; 7230 } 7231 7232 // If a hook was provided get the computed value from there 7233 if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) { 7234 return ret; 7235 7236 // Otherwise, if a way to get the computed value exists, use that 7237 } else if ( curCSS ) { 7238 return curCSS( elem, name ); 7239 } 7240 }, 7241 7242 // A method for quickly swapping in/out CSS properties to get correct calculations 7243 swap: function( elem, options, callback ) { 7244 var old = {}; 7245 7246 // Remember the old values, and insert the new ones 7247 for ( var name in options ) { 7248 old[ name ] = elem.style[ name ]; 7249 elem.style[ name ] = options[ name ]; 7250 } 7251 7252 callback.call( elem ); 7253 7254 // Revert the old values 7255 for ( name in options ) { 7256 elem.style[ name ] = old[ name ]; 7257 } 7258 } 7259}); 7260 7261// DEPRECATED, Use jQuery.css() instead 7262jQuery.curCSS = jQuery.css; 7263 7264jQuery.each(["height", "width"], function( i, name ) { 7265 jQuery.cssHooks[ name ] = { 7266 get: function( elem, computed, extra ) { 7267 var val; 7268 7269 if ( computed ) { 7270 if ( elem.offsetWidth !== 0 ) { 7271 return getWH( elem, name, extra ); 7272 } else { 7273 jQuery.swap( elem, cssShow, function() { 7274 val = getWH( elem, name, extra ); 7275 }); 7276 } 7277 7278 return val; 7279 } 7280 }, 7281 7282 set: function( elem, value ) { 7283 if ( rnumpx.test( value ) ) { 7284 // ignore negative width and height values #1599 7285 value = parseFloat( value ); 7286 7287 if ( value >= 0 ) { 7288 return value + "px"; 7289 } 7290 7291 } else { 7292 return value; 7293 } 7294 } 7295 }; 7296}); 7297 7298if ( !jQuery.support.opacity ) { 7299 jQuery.cssHooks.opacity = { 7300 get: function( elem, computed ) { 7301 // IE uses filters for opacity 7302 return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ? 7303 ( parseFloat( RegExp.$1 ) / 100 ) + "" : 7304 computed ? "1" : ""; 7305 }, 7306 7307 set: function( elem, value ) { 7308 var style = elem.style, 7309 currentStyle = elem.currentStyle, 7310 opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "", 7311 filter = currentStyle && currentStyle.filter || style.filter || ""; 7312 7313 // IE has trouble with opacity if it does not have layout 7314 // Force it by setting the zoom level 7315 style.zoom = 1; 7316 7317 // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652 7318 if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" ) { 7319 7320 // Setting style.filter to null, "" & " " still leave "filter:" in the cssText 7321 // if "filter:" is present at all, clearType is disabled, we want to avoid this 7322 // style.removeAttribute is IE Only, but so apparently is this code path... 7323 style.removeAttribute( "filter" ); 7324 7325 // if there there is no filter style applied in a css rule, we are done 7326 if ( currentStyle && !currentStyle.filter ) { 7327 return; 7328 } 7329 } 7330 7331 // otherwise, set new filter values 7332 style.filter = ralpha.test( filter ) ? 7333 filter.replace( ralpha, opacity ) : 7334 filter + " " + opacity; 7335 } 7336 }; 7337} 7338 7339jQuery(function() { 7340 // This hook cannot be added until DOM ready because the support test 7341 // for it is not run until after DOM ready 7342 if ( !jQuery.support.reliableMarginRight ) { 7343 jQuery.cssHooks.marginRight = { 7344 get: function( elem, computed ) { 7345 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right 7346 // Work around by temporarily setting element display to inline-block 7347 var ret; 7348 jQuery.swap( elem, { "display": "inline-block" }, function() { 7349 if ( computed ) { 7350 ret = curCSS( elem, "margin-right", "marginRight" ); 7351 } else { 7352 ret = elem.style.marginRight; 7353 } 7354 }); 7355 return ret; 7356 } 7357 }; 7358 } 7359}); 7360 7361if ( document.defaultView && document.defaultView.getComputedStyle ) { 7362 getComputedStyle = function( elem, name ) { 7363 var ret, defaultView, computedStyle; 7364 7365 name = name.replace( rupper, "-$1" ).toLowerCase(); 7366 7367 if ( (defaultView = elem.ownerDocument.defaultView) && 7368 (computedStyle = defaultView.getComputedStyle( elem, null )) ) { 7369 ret = computedStyle.getPropertyValue( name ); 7370 if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) { 7371 ret = jQuery.style( elem, name ); 7372 } 7373 } 7374 7375 return ret; 7376 }; 7377} 7378 7379if ( document.documentElement.currentStyle ) { 7380 currentStyle = function( elem, name ) { 7381 var left, rsLeft, uncomputed, 7382 ret = elem.currentStyle && elem.currentStyle[ name ], 7383 style = elem.style; 7384 7385 // Avoid setting ret to empty string here 7386 // so we don't default to auto 7387 if ( ret === null && style && (uncomputed = style[ name ]) ) { 7388 ret = uncomputed; 7389 } 7390 7391 // From the awesome hack by Dean Edwards 7392 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 7393 7394 // If we're not dealing with a regular pixel number 7395 // but a number that has a weird ending, we need to convert it to pixels 7396 if ( !rnumpx.test( ret ) && rnum.test( ret ) ) { 7397 7398 // Remember the original values 7399 left = style.left; 7400 rsLeft = elem.runtimeStyle && elem.runtimeStyle.left; 7401 7402 // Put in the new values to get a computed value out 7403 if ( rsLeft ) { 7404 elem.runtimeStyle.left = elem.currentStyle.left; 7405 } 7406 style.left = name === "fontSize" ? "1em" : ( ret || 0 ); 7407 ret = style.pixelLeft + "px"; 7408 7409 // Revert the changed values 7410 style.left = left; 7411 if ( rsLeft ) { 7412 elem.runtimeStyle.left = rsLeft; 7413 } 7414 } 7415 7416 return ret === "" ? "auto" : ret; 7417 }; 7418} 7419 7420curCSS = getComputedStyle || currentStyle; 7421 7422function getWH( elem, name, extra ) { 7423 7424 // Start with offset property 7425 var val = name === "width" ? elem.offsetWidth : elem.offsetHeight, 7426 which = name === "width" ? cssWidth : cssHeight, 7427 i = 0, 7428 len = which.length; 7429 7430 if ( val > 0 ) { 7431 if ( extra !== "border" ) { 7432 for ( ; i < len; i++ ) { 7433 if ( !extra ) { 7434 val -= parseFloat( jQuery.css( elem, "padding" + which[ i ] ) ) || 0; 7435 } 7436 if ( extra === "margin" ) { 7437 val += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0; 7438 } else { 7439 val -= parseFloat( jQuery.css( elem, "border" + which[ i ] + "Width" ) ) || 0; 7440 } 7441 } 7442 } 7443 7444 return val + "px"; 7445 } 7446 7447 // Fall back to computed then uncomputed css if necessary 7448 val = curCSS( elem, name, name ); 7449 if ( val < 0 || val == null ) { 7450 val = elem.style[ name ] || 0; 7451 } 7452 // Normalize "", auto, and prepare for extra 7453 val = parseFloat( val ) || 0; 7454 7455 // Add padding, border, margin 7456 if ( extra ) { 7457 for ( ; i < len; i++ ) { 7458 val += parseFloat( jQuery.css( elem, "padding" + which[ i ] ) ) || 0; 7459 if ( extra !== "padding" ) { 7460 val += parseFloat( jQuery.css( elem, "border" + which[ i ] + "Width" ) ) || 0; 7461 } 7462 if ( extra === "margin" ) { 7463 val += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0; 7464 } 7465 } 7466 } 7467 7468 return val + "px"; 7469} 7470 7471if ( jQuery.expr && jQuery.expr.filters ) { 7472 jQuery.expr.filters.hidden = function( elem ) { 7473 var width = elem.offsetWidth, 7474 height = elem.offsetHeight; 7475 7476 return ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "dis
7476play" )) === "none"); 7477 }; 7478 7479 jQuery.expr.filters.visible = function( elem ) { 7480 return !jQuery.expr.filters.hidden( elem ); 7481 }; 7482} 7483 7484 7485 7486 7487var r20 = /%20/g, 7488 rbracket = /\[\]$/, 7489 rCRLF = /\r?\n/g, 7490 rhash = /#.*$/, 7491 rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL 7492 rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i, 7493 // #7653, #8125, #8152: local protocol detection 7494 rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/, 7495 rnoContent = /^(?:GET|HEAD)$/, 7496 rprotocol = /^\/\//, 7497 rquery = /\?/, 7498 rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, 7499 rselectTextarea = /^(?:select|textarea)/i, 7500 rspacesAjax = /\s+/, 7501 rts = /([?&])_=[^&]*/, 7502 rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/, 7503 7504 // Keep a copy of the old load method 7505 _load = jQuery.fn.load, 7506 7507 /* Prefilters 7508 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) 7509 * 2) These are called: 7510 * - BEFORE asking for a transport 7511 * - AFTER param serialization (s.data is a string if s.processData is true) 7512 * 3) key is the dataType 7513 * 4) the catchall symbol "*" can be used 7514 * 5) execution will start with transport dataType and THEN continue down to "*" if needed 7515 */ 7516 prefilters = {}, 7517 7518 /* Transports bindings 7519 * 1) key is the dataType 7520 * 2) the catchall symbol "*" can be used 7521 * 3) selection will start with transport dataType and THEN go to "*" if needed 7522 */ 7523 transports = {}, 7524 7525 // Document location 7526 ajaxLocation, 7527 7528 // Document location segments 7529 ajaxLocParts, 7530 7531 // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression 7532 allTypes = ["*/"] + ["*"]; 7533 7534// #8138, IE may throw an exception when accessing 7535// a field from window.location if document.domain has been set 7536try { 7537 ajaxLocation = location.href; 7538} catch( e ) { 7539 // Use the href attribute of an A element 7540 // since IE will modify it given document.location 7541 ajaxLocation = document.createElement( "a" ); 7542 ajaxLocation.href = ""; 7543 ajaxLocation = ajaxLocation.href; 7544} 7545 7546// Segment location into parts 7547ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || []; 7548 7549// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport 7550function addToPrefiltersOrTransports( structure ) { 7551 7552 // dataTypeExpression is optional and defaults to "*" 7553 return function( dataTypeExpression, func ) { 7554 7555 if ( typeof dataTypeExpression !== "string" ) { 7556 func = dataTypeExpression; 7557 dataTypeExpression = "*"; 7558 } 7559 7560 if ( jQuery.isFunction( func ) ) { 7561 var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ), 7562 i = 0, 7563 length = dataTypes.length, 7564 dataType, 7565 list, 7566 placeBefore; 7567 7568 // For each dataType in the dataTypeExpression 7569 for ( ; i < length; i++ ) { 7570 dataType = dataTypes[ i ]; 7571 // We control if we're asked to add before 7572 // any existing element 7573 placeBefore = /^\+/.test( dataType ); 7574 if ( placeBefore ) { 7575 dataType = dataType.substr( 1 ) || "*"; 7576 } 7577 list = structure[ dataType ] = structure[ dataType ] || []; 7578 // then we add to the structure accordingly 7579 list[ placeBefore ? "unshift" : "push" ]( func ); 7580 } 7581 } 7582 }; 7583} 7584 7585// Base inspection function for prefilters and transports 7586function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR, 7587 dataType /* internal */, inspected /* internal */ ) { 7588 7589 dataType = dataType || options.dataTypes[ 0 ]; 7590 inspected = inspected || {}; 7591 7592 inspected[ dataType ] = true; 7593 7594 var list = structure[ dataType ], 7595 i = 0, 7596 length = list ? list.length : 0, 7597 executeOnly = ( structure === prefilters ), 7598 selection; 7599 7600 for ( ; i < length && ( executeOnly || !selection ); i++ ) { 7601 selection = list[ i ]( options, originalOptions, jqXHR ); 7602 // If we got redirected to another dataType 7603 // we try there if executing only and not done already 7604 if ( typeof selection === "string" ) { 7605 if ( !executeOnly || inspected[ selection ] ) { 7606 selection = undefined; 7607 } else { 7608 options.dataTypes.unshift( selection ); 7609 selection = inspectPrefiltersOrTransports( 7610 structure, options, originalOptions, jqXHR, selection, inspected ); 7611 } 7612 } 7613 } 7614 // If we're only executing or nothing was selected 7615 // we try the catchall dataType if not done already 7616 if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) { 7617 selection = inspectPrefiltersOrTransports( 7618 structure, options, originalOptions, jqXHR, "*", inspected ); 7619 } 7620 // unnecessary when only executing (prefilters) 7621 // but it'll be ignored by the caller in that case 7622 return selection; 7623} 7624 7625// A special extend for ajax options 7626// that takes "flat" options (not to be deep extended) 7627// Fixes #9887 7628function ajaxExtend( target, src ) { 7629 var key, deep, 7630 flatOptions = jQuery.ajaxSettings.flatOptions || {}; 7631 for ( key in src ) { 7632 if ( src[ key ] !== undefined ) { 7633 ( flatOptions[ key ] ? target : ( deep || ( deep = {}
vendor: 12,773 bytes, lines 7633-8130
7633 ) ) )[ key ] = src[ key ]; 7634 } 7635 } 7636 if ( deep ) { 7637 jQuery.extend( true, target, deep ); 7638 } 7639} 7640 7641jQuery.fn.extend({ 7642 load: function( url, params, callback ) { 7643 if ( typeof url !== "string" && _load ) { 7644 return _load.apply( this, arguments ); 7645 7646 // Don't do a request if no elements are being requested 7647 } else if ( !this.length ) { 7648 return this; 7649 } 7650 7651 var off = url.indexOf( " " ); 7652 if ( off >= 0 ) { 7653 var selector = url.slice( off, url.length ); 7654 url = url.slice( 0, off ); 7655 } 7656 7657 // Default to a GET request 7658 var type = "GET"; 7659 7660 // If the second parameter was provided 7661 if ( params ) { 7662 // If it's a function 7663 if ( jQuery.isFunction( params ) ) { 7664 // We assume that it's the callback 7665 callback = params; 7666 params = undefined; 7667 7668 // Otherwise, build a param string 7669 } else if ( typeof params === "object" ) { 7670 params = jQuery.param( params, jQuery.ajaxSettings.traditional ); 7671 type = "POST"; 7672 } 7673 } 7674 7675 var self = this; 7676 7677 // Request the remote document 7678 jQuery.ajax({ 7679 url: url, 7680 type: type, 7681 dataType: "html", 7682 data: params, 7683 // Complete callback (responseText is used internally) 7684 complete: function( jqXHR, status, responseText ) { 7685 // Store the response as specified by the jqXHR object 7686 responseText = jqXHR.responseText; 7687 // If successful, inject the HTML into all the matched elements 7688 if ( jqXHR.isResolved() ) { 7689 // #4825: Get the actual response in case 7690 // a dataFilter is present in ajaxSettings 7691 jqXHR.done(function( r ) { 7692 responseText = r; 7693 }); 7694 // See if a selector was specified 7695 self.html( selector ? 7696 // Create a dummy div to hold the results 7697 jQuery("<div>") 7698 // inject the contents of the document in, removing the scripts 7699 // to avoid any 'Permission Denied' errors in IE 7700 .append(responseText.replace(rscript, "")) 7701 7702 // Locate the specified elements 7703 .find(selector) : 7704 7705 // If not, just inject the full result 7706 responseText ); 7707 } 7708 7709 if ( callback ) { 7710 self.each( callback, [ responseText, status, jqXHR ] ); 7711 } 7712 } 7713 }); 7714 7715 return this; 7716 }, 7717 7718 serialize: function() { 7719 return jQuery.param( this.serializeArray() ); 7720 }, 7721 7722 serializeArray: function() { 7723 return this.map(function(){ 7724 return this.elements ? jQuery.makeArray( this.elements ) : this; 7725 }) 7726 .filter(function(){ 7727 return this.name && !this.disabled && 7728 ( this.checked || rselectTextarea.test( this.nodeName ) || 7729 rinput.test( this.type ) ); 7730 }) 7731 .map(function( i, elem ){ 7732 var val = jQuery( this ).val(); 7733 7734 return val == null ? 7735 null : 7736 jQuery.isArray( val ) ? 7737 jQuery.map( val, function( val, i ){ 7738 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; 7739 }) : 7740 { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; 7741 }).get(); 7742 } 7743}); 7744 7745// Attach a bunch of functions for handling common AJAX events 7746jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){ 7747 jQuery.fn[ o ] = function( f ){ 7748 return this.on( o, f ); 7749 }; 7750}); 7751 7752jQuery.each( [ "get", "post" ], function( i, method ) { 7753 jQuery[ method ] = function( url, data, callback, type ) { 7754 // shift arguments if data argument was omitted 7755 if ( jQuery.isFunction( data ) ) { 7756 type = type || callback; 7757 callback = data; 7758 data = undefined; 7759 } 7760 7761 return jQuery.ajax({ 7762 type: method, 7763 url: url, 7764 data: data, 7765 success: callback, 7766 dataType: type 7767 }); 7768 }; 7769}); 7770 7771jQuery.extend({ 7772 7773 getScript: function( url, callback ) { 7774 return jQuery.get( url, undefined, callback, "script" ); 7775 }, 7776 7777 getJSON: function( url, data, callback ) { 7778 return jQuery.get( url, data, callback, "json" ); 7779 }, 7780 7781 // Creates a full fledged settings object into target 7782 // with both ajaxSettings and settings fields. 7783 // If target is omitted, writes into ajaxSettings. 7784 ajaxSetup: function( target, settings ) { 7785 if ( settings ) { 7786 // Building a settings object 7787 ajaxExtend( target, jQuery.ajaxSettings ); 7788 } else { 7789 // Extending ajaxSettings 7790 settings = target; 7791 target = jQuery.ajaxSettings; 7792 } 7793 ajaxExtend( target, settings ); 7794 return target; 7795 }, 7796 7797 ajaxSettings: { 7798 url: ajaxLocation, 7799 isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ), 7800 global: true, 7801 type: "GET", 7802 contentType: "application/x-www-form-urlencoded", 7803 processData: true, 7804 async: true, 7805 /* 7806 timeout: 0, 7807 data: null, 7808 dataType: null, 7809 username: null, 7810 password: null, 7811 cache: null, 7812 traditional: false, 7813 headers: {}, 7814 */ 7815 7816 accepts: { 7817 xml: "application/xml, text/xml", 7818 html: "text/html", 7819 text: "text/plain", 7820 json: "application/json, text/javascript", 7821 "*": allTypes 7822 }, 7823 7824 contents: { 7825 xml: /xml/, 7826 html: /html/, 7827 json: /json/ 7828 }, 7829 7830 responseFields: { 7831 xml: "responseXML", 7832 text: "responseText" 7833 }, 7834 7835 // List of data converters 7836 // 1) key format is "source_type destination_type" (a single space in-between) 7837 // 2) the catchall symbol "*" can be used for source_type 7838 converters: { 7839 7840 // Convert anything to text 7841 "* text": window.String, 7842 7843 // Text to html (true = no transformation) 7844 "text html": true, 7845 7846 // Evaluate text as a json expression 7847 "text json": jQuery.parseJSON, 7848 7849 // Parse text as xml 7850 "text xml": jQuery.parseXML 7851 }, 7852 7853 // For options that shouldn't be deep extended: 7854 // you can add your own custom options here if 7855 // and when you create one that shouldn't be 7856 // deep extended (see ajaxExtend) 7857 flatOptions: { 7858 context: true, 7859 url: true 7860 } 7861 }, 7862 7863 ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), 7864 ajaxTransport: addToPrefiltersOrTransports( transports ), 7865 7866 // Main method 7867 ajax: function( url, options ) { 7868 7869 // If url is an object, simulate pre-1.5 signature 7870 if ( typeof url === "object" ) { 7871 options = url; 7872 url = undefined; 7873 } 7874 7875 // Force options to be an object 7876 options = options || {}; 7877 7878 var // Create the final options object 7879 s = jQuery.ajaxSetup( {}, options ), 7880 // Callbacks context 7881 callbackContext = s.context || s, 7882 // Context for global events 7883 // It's the callbackContext if one was provided in the options 7884 // and if it's a DOM node or a jQuery collection 7885 globalEventContext = callbackContext !== s && 7886 ( callbackContext.nodeType || callbackContext instanceof jQuery ) ? 7887 jQuery( callbackContext ) : jQuery.event, 7888 // Deferreds 7889 deferred = jQuery.Deferred(), 7890 completeDeferred = jQuery.Callbacks( "once memory" ), 7891 // Status-dependent callbacks 7892 statusCode = s.statusCode || {}, 7893 // ifModified key 7894 ifModifiedKey, 7895 // Headers (they are sent all at once) 7896 requestHeaders = {}, 7897 requestHeadersNames = {}, 7898 // Response headers 7899 responseHeadersString, 7900 responseHeaders, 7901 // transport 7902 transport, 7903 // timeout handle 7904 timeoutTimer, 7905 // Cross-domain detection vars 7906 parts, 7907 // The jqXHR state 7908 state = 0, 7909 // To know if global events are to be dispatched 7910 fireGlobals, 7911 // Loop variable 7912 i, 7913 // Fake xhr 7914 jqXHR = { 7915 7916 readyState: 0, 7917 7918 // Caches the header 7919 setRequestHeader: function( name, value ) { 7920 if ( !state ) { 7921 var lname = name.toLowerCase(); 7922 name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; 7923 requestHeaders[ name ] = value; 7924 } 7925 return this; 7926 }, 7927 7928 // Raw string 7929 getAllResponseHeaders: function() { 7930 return state === 2 ? responseHeadersString : null; 7931 }, 7932 7933 // Builds headers hashtable if needed 7934 getResponseHeader: function( key ) { 7935 var match; 7936 if ( state === 2 ) { 7937 if ( !responseHeaders ) { 7938 responseHeaders = {}; 7939 while( ( match = rheaders.exec( responseHeadersString ) ) ) { 7940 responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; 7941 } 7942 } 7943 match = responseHeaders[ key.toLowerCase() ]; 7944 } 7945 return match === undefined ? null : match; 7946 }, 7947 7948 // Overrides response content-type header 7949 overrideMimeType: function( type ) { 7950 if ( !state ) { 7951 s.mimeType = type; 7952 } 7953 return this; 7954 }, 7955 7956 // Cancel the request 7957 abort: function( statusText ) { 7958 statusText = statusText || "abort"; 7959 if ( transport ) { 7960 transport.abort( statusText ); 7961 } 7962 done( 0, statusText ); 7963 return this; 7964 } 7965 }; 7966 7967 // Callback for when everything is done 7968 // It is defined here because jslint complains if it is declared 7969 // at the end of the function (which would be more logical and readable) 7970 function done( status, nativeStatusText, responses, headers ) { 7971 7972 // Called once 7973 if ( state === 2 ) { 7974 return; 7975 } 7976 7977 // State is "done" now 7978 state = 2; 7979 7980 // Clear timeout if it exists 7981 if ( timeoutTimer ) { 7982 clearTimeout( timeoutTimer ); 7983 } 7984 7985 // Dereference transport for early garbage collection 7986 // (no matter how long the jqXHR object will be used) 7987 transport = undefined; 7988 7989 // Cache response headers 7990 responseHeadersString = headers || ""; 7991 7992 // Set readyState 7993 jqXHR.readyState = status > 0 ? 4 : 0; 7994 7995 var isSuccess, 7996 success, 7997 error, 7998 statusText = nativeStatusText, 7999 response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined, 8000 lastModified, 8001 etag; 8002 8003 // If successful, handle type chaining 8004 if ( status >= 200 && status < 300 || status === 304 ) { 8005 8006 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. 8007 if ( s.ifModified ) { 8008 8009 if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) { 8010 jQuery.lastModified[ ifModifiedKey ] = lastModified; 8011 } 8012 if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) { 8013 jQuery.etag[ ifModifiedKey ] = etag; 8014 } 8015 } 8016 8017 // If not modified 8018 if ( status === 304 ) { 8019 8020 statusText = "notmodified"; 8021 isSuccess = true; 8022 8023 // If we have data 8024 } else { 8025 8026 try { 8027 success = ajaxConvert( s, response ); 8028 statusText = "success"; 8029 isSuccess = true; 8030 } catch(e) { 8031 // We have a parsererror 8032 statusText = "parsererror"; 8033 error = e; 8034 } 8035 } 8036 } else { 8037 // We extract error from statusText 8038 // then normalize statusText and status for non-aborts 8039 error = statusText; 8040 if ( !statusText || status ) { 8041 statusText = "error"; 8042 if ( status < 0 ) { 8043 status = 0; 8044 } 8045 } 8046 } 8047 8048 // Set data for the fake xhr object 8049 jqXHR.status = status; 8050 jqXHR.statusText = "" + ( nativeStatusText || statusText ); 8051 8052 // Success/Error 8053 if ( isSuccess ) { 8054 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); 8055 } else { 8056 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); 8057 } 8058 8059 // Status-dependent callbacks 8060 jqXHR.statusCode( statusCode ); 8061 statusCode = undefined; 8062 8063 if ( fireGlobals ) { 8064 globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ), 8065 [ jqXHR, s, isSuccess ? success : error ] ); 8066 } 8067 8068 // Complete 8069 completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); 8070 8071 if ( fireGlobals ) { 8072 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); 8073 // Handle the global AJAX counter 8074 if ( !( --jQuery.active ) ) { 8075 jQuery.event.trigger( "ajaxStop" ); 8076 } 8077 } 8078 } 8079 8080 // Attach deferreds 8081 deferred.promise( jqXHR ); 8082 jqXHR.success = jqXHR.done; 8083 jqXHR.error = jqXHR.fail; 8084 jqXHR.complete = completeDeferred.add; 8085 8086 // Status-dependent callbacks 8087 jqXHR.statusCode = function( map ) { 8088 if ( map ) { 8089 var tmp; 8090 if ( state < 2 ) { 8091 for ( tmp in map ) { 8092 statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ]; 8093 } 8094 } else { 8095 tmp = map[ jqXHR.status ]; 8096 jqXHR.then( tmp, tmp ); 8097 } 8098 } 8099 return this; 8100 }; 8101 8102 // Remove hash character (#7531: and string promotion) 8103 // Add protocol if not provided (#5866: IE7 issue with protocol-less urls) 8104 // We also use the url parameter if available 8105 s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); 8106 8107 // Extract dataTypes list 8108 s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax ); 8109 8110 // Determine if a cross-domain request is in order 8111 if ( s.crossDomain == null ) { 8112 parts = rurl.exec( s.url.toLowerCase() ); 8113 s.crossDomain = !!( parts && 8114 ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] || 8115 ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) != 8116 ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) ) 8117 ); 8118 } 8119 8120 // Convert data if not already a string 8121 if ( s.data && s.processData && typeof s.data !== "string" ) { 8122 s.data = jQuery.param( s.data, s.traditional ); 8123 } 8124 8125 // Apply prefilters 8126 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); 8127 8128 // If request was aborted inside a prefiler, stop there 8129 if ( state === 2 ) { 8130 return false;
8131 } 8132 8133 // We can fire global events as of now if asked to 8134 fireGlobals = s.global; 8135 8136 // Uppercase the type 8137 s.type = s.type.toUpperCase(); 8138 8139 // Determine if request has content 8140 s.hasContent = !rnoContent.test( s.type ); 8141 8142 // Watch for a new set of requests 8143 if ( fireGlobals && jQuery.active++ === 0 ) { 8144 jQuery.event.trigger( "ajaxStart" ); 8145 } 8146 8147 // More options handling for requests with no content 8148 if ( !s.hasContent ) { 8149 8150 // If data is available, append data to url 8151 if ( s.data ) { 8152 s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data; 8153 // #9682: remove data so that it's not used in an eventual retry 8154 delete s.data; 8155 } 8156 8157 // Get ifModifiedKey before adding the anti-cache parameter 8158 ifModifiedKey = s.url; 8159 8160 // Add anti-cache in url if needed 8161 if ( s.cache === false ) { 8162 8163 var ts = jQuery.now(), 8164 // try replacing _= if it is there 8165 ret = s.url.replace( rts, "$1_=" + ts ); 8166 8167 // if nothing was replaced, add timestamp to the end 8168 s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" ); 8169 } 8170 } 8171 8172 // Set the correct header, if data is being sent 8173 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { 8174 jqXHR.setRequestHeader( "Content-Type", s.contentType ); 8175 } 8176 8177 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. 8178 if ( s.ifModified ) { 8179 ifModifiedKey = ifModifiedKey || s.url; 8180 if ( jQuery.lastModified[ ifModifiedKey ] ) { 8181 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] ); 8182 } 8183 if ( jQuery.etag[ ifModifiedKey ] ) { 8184 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] ); 8185 } 8186 } 8187 8188 // Set the Accepts header for the server, depending on the dataType 8189 jqXHR.setRequestHeader( 8190 "Accept", 8191 s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? 8192 s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : 8193 s.accepts[ "*" ] 8194 ); 8195 8196 // Check for headers option 8197 for ( i in s.headers ) { 8198 jqXHR.setRequestHeader( i, s.headers[ i ] ); 8199 } 8200 8201 // Allow custom headers/mimetypes and early abort 8202 if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { 8203 // Abort if not done already 8204 jqXHR.abort(); 8205 return false; 8206 8207 } 8208 8209 // Install callbacks on deferreds 8210 for ( i in { success: 1, error: 1, complete: 1 } ) { 8211 jqXHR[ i ]( s[ i ] ); 8212 } 8213 8214 // Get transport 8215 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); 8216 8217 // If no transport, we auto-abort 8218 if ( !transport ) { 8219 done( -1, "No Transport" ); 8220 } else { 8221 jqXHR.readyState = 1; 8222 // Send global event 8223 if ( fireGlobals ) { 8224 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); 8225 } 8226 // Timeout 8227 if ( s.async && s.timeout > 0 ) { 8228 timeoutTimer = setTimeout( function(){ 8229 jqXHR.abort( "timeout" ); 8230 }, s.timeout ); 8231 } 8232 8233 try { 8234 state = 1; 8235 transport.send( requestHeaders, done ); 8236 } catch (e) { 8237 // Propagate exception as error if not done 8238 if ( state < 2 ) { 8239 done( -1, e ); 8240 // Simply rethrow otherwise 8241 } else { 8242 throw e; 8243 } 8244 } 8245 } 8246 8247 return jqXHR; 8248 }, 8249 8250 // Serialize an array of form elements or a set of 8251 // key/values into a query string 8252 param: function( a, traditional ) { 8253 var s = [], 8254 add = function( key, value ) { 8255 // If value is a function, invoke it and return its value 8256 value = jQuery.isFunction( value ) ? value() : value; 8257 s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value ); 8258 }; 8259 8260 // Set traditional to true for jQuery <= 1.3.2 behavior. 8261 if ( traditional === undefined ) { 8262 traditional = jQuery.ajaxSettings.traditional; 8263 } 8264 8265 // If an array was passed in, assume that it is an array of form elements. 8266 if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { 8267 // Serialize the form elements 8268 jQuery.each( a, function() { 8269 add( this.name, this.value ); 8270 }); 8271 8272 } else { 8273 // If traditional, encode the "old" way (the way 1.3.2 or older 8274 // did it), otherwise encode params recursively. 8275 for ( var prefix in a ) { 8276 buildParams( prefix, a[ prefix ], traditional, add ); 8277 } 8278 } 8279 8280 // Return the resulting serialization 8281 return s.join( "&" ).replace( r20, "+" ); 8282 } 8283}); 8284 8285function buildParams( prefix, obj, traditional, add ) { 8286 if ( jQuery.isArray( obj ) ) { 8287 // Serialize array item. 8288 jQuery.each( obj, function( i, v ) { 8289 if ( traditional || rbracket.test( prefix ) ) { 8290 // Treat each array item as a scalar. 8291 add( prefix, v ); 8292 8293 } else { 8294 // If array item is non-scalar (array or object), encode its 8295 // numeric index to resolve deserialization ambiguity issues. 8296 // Note that rack (as of 1.0.0) can't currently deserialize 8297 // nested arrays properly, and attempting to do so may cause 8298 // a server error. Possible fixes are to modify rack's 8299 // deserialization algorithm or to provide an option or flag 8300 // to force array serialization to be shallow. 8301 buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add ); 8302 } 8303 }); 8304 8305 } else if ( !traditional && obj != null && typeof obj === "object" ) { 8306 // Serialize object item. 8307 for ( var name in obj ) { 8308 buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); 8309 } 8310 8311 } else { 8312 // Serialize scalar item. 8313 add( prefix, obj ); 8314 } 8315} 8316 8317// This is still on the jQuery object... for now 8318// Want to move this to jQuery.ajax some day 8319jQuery.extend({ 8320 8321 // Counter for holding the number of active queries 8322 active: 0, 8323 8324 // Last-Modified header cache for next request 8325 lastModified: {}, 8326 etag: {} 8327 8328}
8328); 8329 8330/* Handles responses to an ajax request: 8331 * - sets all responseXXX fields accordingly 8332 * - finds the right dataType (mediates between content-type and expected dataType) 8333 * - returns the corresponding response 8334 */ 8335function ajaxHandleResponses( s, jqXHR, responses ) { 8336 8337 var contents = s.contents, 8338 dataTypes = s.dataTypes, 8339 responseFields = s.responseFields, 8340 ct, 8341 type, 8342 finalDataType, 8343 firstDataType; 8344 8345 // Fill responseXXX fields 8346 for ( type in responseFields ) { 8347 if ( type in responses ) { 8348 jqXHR[ responseFields[type] ] = responses[ type ]; 8349 } 8350 } 8351 8352 // Remove auto dataType and get content-type in the process 8353 while( dataTypes[ 0 ] === "*" ) { 8354 dataTypes.shift(); 8355 if ( ct === undefined ) { 8356 ct = s.mimeType || jqXHR.getResponseHeader( "content-type" ); 8357 } 8358 } 8359 8360 // Check if we're dealing with a known content-type 8361 if ( ct ) { 8362 for ( type in contents ) { 8363 if ( contents[ type ] && contents[ type ].test( ct ) ) { 8364 dataTypes.unshift( type ); 8365 break; 8366 } 8367 } 8368 } 8369 8370 // Check to see if we have a response for the expected dataType 8371 if ( dataTypes[ 0 ] in responses ) { 8372 finalDataType = dataTypes[ 0 ]; 8373 } else { 8374 // Try convertible dataTypes 8375 for ( type in responses ) { 8376 if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) { 8377 finalDataType = type; 8378 break; 8379 } 8380 if ( !firstDataType ) { 8381 firstDataType = type; 8382 } 8383 } 8384 // Or just use first one 8385 finalDataType = finalDataType || firstDataType; 8386 } 8387 8388 // If we found a dataType 8389 // We add the dataType to the list if needed 8390 // and return the corresponding response 8391 if ( finalDataType ) { 8392 if ( finalDataType !== dataTypes[ 0 ] ) { 8393 dataTypes.unshift( finalDataType ); 8394 } 8395 return responses[ finalDataType ]; 8396 } 8397} 8398 8399// Chain conversions given the request and the original response 8400function ajaxConvert( s, response ) { 8401 8402 // Apply the dataFilter if provided 8403 if ( s.dataFilter ) { 8404 response = s.dataFilter( response, s.dataType ); 8405 } 8406 8407 var dataTypes = s.dataTypes, 8408 converters = {}, 8409 i, 8410 key, 8411 length = dataTypes.length, 8412 tmp, 8413 // Current and previous dataTypes 8414 current = dataTypes[ 0 ], 8415 prev, 8416 // Conversion expression 8417 conversion, 8418 // Conversion function 8419 conv, 8420 // Conversion functions (transitive conversion) 8421 conv1, 8422 conv2; 8423 8424 // For each dataType in the chain 8425 for ( i = 1; i < length; i++ ) { 8426 8427 // Create converters map 8428 // with lowercased keys 8429 if ( i === 1 ) { 8430 for ( key in s.converters ) { 8431 if ( typeof key === "string" ) { 8432 converters[ key.toLowerCase() ] = s.converters[ key ]; 8433 } 8434 } 8435 } 8436 8437 // Get the dataTypes 8438 prev = current; 8439 current = dataTypes[ i ]; 8440 8441 // If current is auto dataType, update it to prev 8442 if ( current === "*" ) { 8443 current = prev; 8444 // If no auto and dataTypes are actually different 8445 } else if ( prev !== "*" && prev !== current ) { 8446 8447 // Get the converter 8448 conversion = prev + " " + current; 8449 conv = converters[ conversion ] || converters[ "* " + current ]; 8450 8451 // If there is no direct converter, search transitively 8452 if ( !conv ) { 8453 conv2 = undefined; 8454 for ( conv1 in converters ) { 8455 tmp = conv1.split( " " ); 8456 if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) { 8457 conv2 = converters[ tmp[1] + " " + current ]; 8458 if ( conv2 ) { 8459 conv1 = converters[ conv1 ]; 8460 if ( conv1 === true ) { 8461 conv = conv2; 8462 } else if ( conv2 === true ) { 8463 conv = conv1; 8464 } 8465 break; 8466 } 8467 } 8468 } 8469 } 8470 // If we found no converter, dispatch an error 8471 if ( !( conv || conv2 ) ) { 8472 jQuery.error( "No conversion from " + conversion.replace(" "," to ") ); 8473 } 8474 // If found converter is not an equivalence 8475 if ( conv !== true ) { 8476 // Convert with 1 or 2 converters accordingly 8477 response = conv ? conv( response ) : conv2( conv1(response) ); 8478 } 8479 } 8480 } 8481 return response; 8482} 8483 8484 8485 8486 8487var jsc = jQuery.now(), 8488 jsre = /(\=)\?(&|$)|\?\?/i; 8489 8490// Default jsonp settings 8491jQuery.ajaxSetup({ 8492 jsonp: "callback", 8493 jsonpCallback: function() { 8494 return jQuery.expando + "_" + ( jsc++ ); 8495 } 8496}); 8497 8498// Detect, normalize options and install callbacks for jsonp requests 8499jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { 8500 8501 var inspectData = s.contentType === "application/x-www-form-urlencoded" && 8502 ( typeof s.data === "string" ); 8503 8504 if ( s.dataTypes[ 0 ] === "jsonp" || 8505 s.jsonp !== false && ( jsre.test( s.url ) || 8506 inspectData && jsre.test( s.data ) ) ) { 8507 8508 var responseContainer, 8509 jsonpCallback = s.jsonpCallback = 8510 jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback, 8511 previous = window[ jsonpCallback ], 8512 url = s.url, 8513 data = s.data, 8514 replace = "$1" + jsonpCallback + "$2"; 8515 8516 if ( s.jsonp !== false ) { 8517 url = url.replace( jsre, replace ); 8518 if ( s.url === url ) { 8519 if ( inspectData ) { 8520 data = data.replace( jsre, replace ); 8521 } 8522 if ( s.data === data ) { 8523 // Add callback manually 8524 url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback; 8525 } 8526 } 8527 } 8528 8529 s.url = url; 8530 s.data = data; 8531 8532 // Install callback 8533 window[ jsonpCallback ] = function( response ) { 8534 responseContainer = [ response ]; 8535 }; 8536 8537 // Clean-up function 8538 jqXHR.always(function() { 8539 // Set callback back to previous value 8540 window[ jsonpCallback ] = previous; 8541 // Call if it was a function and we have a response 8542 if ( responseContainer && jQuery.isFunction( previous ) ) { 8543 window[ jsonpCallback ]( responseContainer[ 0 ] ); 8544 } 8545 }); 8546 8547 // Use data converter to retrieve json after script execution 8548 s.converters["script json"] = function() { 8549 if ( !responseContainer ) { 8550 jQuery.error( jsonpCallback + " was not called" ); 8551 } 8552 return responseContainer[ 0 ]; 8553 }; 8554 8555 // force json dataType 8556 s.dataTypes[ 0 ] = "json"; 8557 8558 // Delegate to script 8559 return "script"; 8560 } 8561}); 8562 8563 8564 8565 8566// Install script dataType 8567jQuery.ajaxSetup({ 8568 accepts: { 8569 script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" 8570 }, 8571 contents: { 8572 script: /javascript|ecmascript/ 8573 }, 8574 converters: { 8575 "text script": function( text ) { 8576 jQuery.globalEval( text ); 8577 return text; 8578 } 8579 } 8580}); 8581 8582// Handle cache's special case and global 8583jQuery.ajaxPrefilter( "script", function( s ) { 8584 if ( s.cache === undefined ) { 8585 s.cache = false;
vendor: 3,904 bytes, lines 8586-8741
8586 } 8587 if ( s.crossDomain ) { 8588 s.type = "GET"; 8589 s.global = false; 8590 } 8591}); 8592 8593// Bind script tag hack transport 8594jQuery.ajaxTransport( "script", function(s) { 8595 8596 // This transport only deals with cross domain requests 8597 if ( s.crossDomain ) { 8598 8599 var script, 8600 head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement; 8601 8602 return { 8603 8604 send: function( _, callback ) { 8605 8606 script = document.createElement( "script" ); 8607 8608 script.async = "async"; 8609 8610 if ( s.scriptCharset ) { 8611 script.charset = s.scriptCharset; 8612 } 8613 8614 script.src = s.url; 8615 8616 // Attach handlers for all browsers 8617 script.onload = script.onreadystatechange = function( _, isAbort ) { 8618 8619 if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) { 8620 8621 // Handle memory leak in IE 8622 script.onload = script.onreadystatechange = null; 8623 8624 // Remove the script 8625 if ( head && script.parentNode ) { 8626 head.removeChild( script ); 8627 } 8628 8629 // Dereference the script 8630 script = undefined; 8631 8632 // Callback if not abort 8633 if ( !isAbort ) { 8634 callback( 200, "success" ); 8635 } 8636 } 8637 }; 8638 // Use insertBefore instead of appendChild to circumvent an IE6 bug. 8639 // This arises when a base node is used (#2709 and #4378). 8640 head.insertBefore( script, head.firstChild ); 8641 }, 8642 8643 abort: function() { 8644 if ( script ) { 8645 script.onload( 0, 1 ); 8646 } 8647 } 8648 }; 8649 } 8650}); 8651 8652 8653 8654 8655var // #5280: Internet Explorer will keep connections alive if we don't abort on unload 8656 xhrOnUnloadAbort = window.ActiveXObject ? function() { 8657 // Abort all pending requests 8658 for ( var key in xhrCallbacks ) { 8659 xhrCallbacks[ key ]( 0, 1 ); 8660 } 8661 } : false, 8662 xhrId = 0, 8663 xhrCallbacks; 8664 8665// Functions to create xhrs 8666function createStandardXHR() { 8667 try { 8668 return new window.XMLHttpRequest(); 8669 } catch( e ) {} 8670} 8671 8672function createActiveXHR() { 8673 try { 8674 return new window.ActiveXObject( "Microsoft.XMLHTTP" ); 8675 } catch( e ) {} 8676} 8677 8678// Create the request object 8679// (This is still attached to ajaxSettings for backward compatibility) 8680jQuery.ajaxSettings.xhr = window.ActiveXObject ? 8681 /* Microsoft failed to properly 8682 * implement the XMLHttpRequest in IE7 (can't request local files), 8683 * so we use the ActiveXObject when it is available 8684 * Additionally XMLHttpRequest can be disabled in IE7/IE8 so 8685 * we need a fallback. 8686 */ 8687 function() { 8688 return !this.isLocal && createStandardXHR() || createActiveXHR(); 8689 } : 8690 // For all other browsers, use the standard XMLHttpRequest object 8691 createStandardXHR; 8692 8693// Determine support properties 8694(function( xhr ) { 8695 jQuery.extend( jQuery.support, { 8696 ajax: !!xhr, 8697 cors: !!xhr && ( "withCredentials" in xhr ) 8698 }); 8699})( jQuery.ajaxSettings.xhr() ); 8700 8701// Create transport if the browser can provide an xhr 8702if ( jQuery.support.ajax ) { 8703 8704 jQuery.ajaxTransport(function( s ) { 8705 // Cross domain only allowed if supported through XMLHttpRequest 8706 if ( !s.crossDomain || jQuery.support.cors ) { 8707 8708 var callback; 8709 8710 return { 8711 send: function( headers, complete ) { 8712 8713 // Get a new xhr 8714 var xhr = s.xhr(), 8715 handle, 8716 i; 8717 8718 // Open the socket 8719 // Passing null username, generates a login popup on Opera (#2865) 8720 if ( s.username ) { 8721 xhr.open( s.type, s.url, s.async, s.username, s.password ); 8722 } else { 8723 xhr.open( s.type, s.url, s.async ); 8724 } 8725 8726 // Apply custom fields if provided 8727 if ( s.xhrFields ) { 8728 for ( i in s.xhrFields ) { 8729 xhr[ i ] = s.xhrFields[ i ]; 8730 } 8731 } 8732 8733 // Override mime type if needed 8734 if ( s.mimeType && xhr.overrideMimeType ) { 8735 xhr.overrideMimeType( s.mimeType ); 8736 } 8737 8738 // X-Requested-With header 8739 // For cross-domain requests, seeing as conditions for a preflight are 8740 // akin to a jigsaw puzzle, we simply never set it to be sure. 8741 // (it can always be set on a per-request basis or even using ajaxSetup)
8742 // For same-domain requests, won't change header if already provided. 8743 if ( !s.crossDomain && !headers["X-Requested-With"] ) { 8744 headers[ "X-Requested-With" ] = "XMLHttpRequest"; 8745 } 8746 8747 // Need an extra try/catch for cross domain requests in Firefox 3 8748 try { 8749 for ( i in headers ) { 8750 xhr.setRequestHeader( i, headers[ i ] ); 8751 } 8752 } catch( _ ) {} 8753 8754 // Do send the request 8755 // This may raise an exception which is actually 8756 // handled in jQuery.ajax (so no try/catch here) 8757 xhr.send( ( s.hasContent && s.data ) || null ); 8758 8759 // Listener 8760 callback = function( _, isAbort ) { 8761 8762 var status, 8763 statusText, 8764 responseHeaders, 8765 responses, 8766 xml; 8767 8768 // Firefox throws exceptions when accessing properties 8769 // of an xhr when a network error occured 8770 // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE) 8771 try { 8772 8773 // Was never called and is aborted or complete 8774 if ( callback && ( isAbort || xhr.readyState === 4 ) ) { 8775 8776 // Only called once 8777 callback = undefined; 8778 8779 // Do not keep as active anymore 8780 if ( handle ) { 8781 xhr.onreadystatechange = jQuery.noop; 8782 if ( xhrOnUnloadAbort ) { 8783 delete xhrCallbacks[ handle ]; 8784 } 8785 } 8786 8787 // If it's an abort 8788 if ( isAbort ) { 8789 // Abort it manually if needed 8790 if ( xhr.readyState !== 4 ) { 8791 xhr.abort(); 8792 } 8793 } else { 8794 status = xhr.status; 8795 responseHeaders = xhr.getAllResponseHeaders(); 8796 responses = {}; 8797 xml = xhr.responseXML; 8798 8799 // Construct response list 8800 if ( xml && xml.documentElement /* #4958 */ ) { 8801 responses.xml = xml; 8802 } 8803 responses.text = xhr.responseText; 8804 8805 // Firefox throws an exception when accessing 8806 // statusText for faulty cross-domain requests 8807 try { 8808 statusText = xhr.statusText; 8809 } catch( e ) { 8810 // We normalize with Webkit giving an empty statusText 8811 statusText = ""; 8812 } 8813 8814 // Filter status for non standard behaviors 8815 8816 // If the request is local and we have data: assume a success 8817 // (success with no data won't get notified, that's the best we 8818 // can do given current implementations) 8819 if ( !status && s.isLocal && !s.crossDomain ) { 8820 status = responses.text ? 200 : 404; 8821 // IE - #1450: sometimes returns 1223 when it should be 204 8822 } else if ( status === 1223 ) { 8823 status = 204; 8824 } 8825 } 8826 } 8827 } catch( firefoxAccessException ) { 8828 if ( !isAbort ) { 8829 complete( -1, firefoxAccessException ); 8830 } 8831 } 8832 8833 // Call complete if needed 8834 if ( responses ) { 8835 complete( status, statusText, responses, responseHeaders ); 8836 } 8837 }; 8838 8839 // if we're in sync mode or it's in cache 8840 // and has been retrieved directly (IE6 & IE7) 8841 // we need to manually fire the callback 8842 if ( !s.async || xhr.readyState === 4 ) { 8843 callback(); 8844 } else { 8845 handle = ++xhrId; 8846 if ( xhrOnUnloadAbort ) { 8847 // Create the active xhrs callbacks list if needed 8848 // and attach the unload handler 8849 if ( !xhrCallbacks ) { 8850 xhrCallbacks = {}; 8851 jQuery( window ).unload( xhrOnUnloadAbort ); 8852 } 8853 // Add to list of active xhrs callbacks 8854 xhrCallbacks[ handle ] = callback; 8855 } 8856 xhr.onreadystatechange = callback; 8857 } 8858 }, 8859 8860 abort: function() { 8861 if ( callback ) { 8862 callback(0,1); 8863 } 8864 } 8865 }; 8866 } 8867 }); 8868} 8869 8870 8871 8872 8873var elemdisplay = {}, 8874 iframe, iframeDoc, 8875 rfxtypes = /^(?:toggle|show|hide)$/, 8876 rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i, 8877 timerId, 8878 fxAttrs = [ 8879 // height animations 8880 [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ], 8881 // width animations 8882 [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ], 8883 // opacity animations 8884 [ "opacity" ] 8885 ], 8886 fxNow; 8887 8888jQuery.fn.extend({ 8889 show: function( speed, easing, callback ) { 8890 var elem, display; 8891 8892 if ( speed || speed === 0 ) { 8893 return this.animate( genFx("show", 3), speed, easing, callback ); 8894 8895 } else { 8896 for ( var i = 0, j = this.length; i < j; i++ ) { 8897 elem = this[ i ]; 8898 8899 if ( elem.style ) { 8900 display = elem.style.display; 8901 8902 // Reset the inline display of this element to learn if it is 8903 // being hidden by cascaded rules or not 8904 if ( !jQuery._data(elem, "olddisplay") && display === "none" ) { 8905 display = elem.style.display = ""; 8906 } 8907 8908 // Set elements which have been overridden with display: none 8909 // in a stylesheet to whatever the default browser style is 8910 // for such an element
8911 if ( display === "" && jQuery.css(elem, "display") === "none" ) { 8912 jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) ); 8913 } 8914 } 8915 } 8916 8917 // Set the display of most of the elements in a second loop 8918 // to avoid the constant reflow 8919 for ( i = 0; i < j; i++ ) { 8920 elem = this[ i ]; 8921 8922 if ( elem.style ) { 8923 display = elem.style.display; 8924 8925 if ( display === "" || display === "none" ) { 8926 elem.style.display = jQuery._data( elem, "olddisplay" ) || ""; 8927 } 8928 } 8929 } 8930 8931 return this; 8932 } 8933 }, 8934 8935 hide: function( speed, easing, callback ) { 8936 if ( speed || speed === 0 ) { 8937 return this.animate( genFx("hide", 3), speed, easing, callback); 8938 8939 } else { 8940 var elem, display, 8941 i = 0, 8942 j = this.length; 8943 8944 for ( ; i < j; i++ ) { 8945 elem = this[i]; 8946 if ( elem.style ) { 8947 display = jQuery.css( elem, "display" ); 8948 8949 if ( display !== "none" && !jQuery._data( elem, "olddisplay" ) ) { 8950 jQuery._data( elem, "olddisplay", display ); 8951 } 8952 } 8953 } 8954 8955 // Set the display of the elements in a second loop 8956 // to avoid the constant reflow 8957 for ( i = 0; i < j; i++ ) { 8958 if ( this[i].style ) { 8959 this[i].style.display = "none"; 8960 } 8961 } 8962 8963 return this; 8964 } 8965 }, 8966 8967 // Save the old toggle function 8968 _toggle: jQuery.fn.toggle, 8969 8970 toggle: function( fn, fn2, callback ) { 8971 var bool = typeof fn === "boolean"; 8972 8973 if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) { 8974 this._toggle.apply( this, arguments ); 8975 8976 } else if ( fn == null || bool ) { 8977 this.each(function() { 8978 var state = bool ? fn : jQuery(this).is(":hidden"); 8979 jQuery(this)[ state ? "show" : "hide" ](); 8980 }); 8981 8982 } else { 8983 this.animate(genFx("toggle", 3), fn, fn2, callback); 8984 } 8985 8986 return this; 8987 }, 8988 8989 fadeTo: function( speed, to, easing, callback ) { 8990 return this.filter(":hidden").css("opacity", 0).show().end() 8991 .animate({opacity: to}, speed, easing, callback); 8992 }, 8993 8994 animate: function( prop, speed, easing, callback ) { 8995 var optall = jQuery.speed( speed, easing, callback ); 8996 8997 if ( jQuery.isEmptyObject( prop ) ) { 8998 return this.each( optall.complete, [ false ] ); 8999 } 9000 9001 // Do not change referenced properties as per-property easing will be lost 9002 prop = jQuery.extend( {}, prop ); 9003 9004 function doAnimation() { 9005 // XXX 'this' does not always have a nodeName when running the 9006 // test suite 9007 9008 if ( optall.queue === false ) { 9009 jQuery._mark( this ); 9010 } 9011 9012 var opt = jQuery.extend( {}, optall ), 9013 isElement = this.nodeType === 1, 9014 hidden = isElement && jQuery(this).is(":hidden"), 9015 name, val, p, e, 9016 parts, start, end, unit, 9017 method; 9018 9019 // will store per property easing and be used to determine when an animation is complete 9020 opt.animatedProperties = {}; 9021 9022 for ( p in prop ) { 9023 9024 // property name normalization 9025 name = jQuery.camelCase( p ); 9026 if ( p !== name ) { 9027 prop[ name ] = prop[ p ]; 9028 delete prop[ p ]; 9029 } 9030 9031 val = prop[ name ]; 9032 9033 // easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default) 9034 if ( jQuery.isArray( val ) ) { 9035 opt.animatedProperties[ name ] = val[ 1 ]; 9036 val = prop[ name ] = val[ 0 ]; 9037 } else { 9038 opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing'; 9039 } 9040 9041 if ( val === "hide" && hidden || val === "show" && !hidden ) { 9042 return opt.complete.call( this ); 9043 } 9044 9045 if ( isElement && ( name === "height" || name === "width" ) ) { 9046 // Make sure that nothing sneaks out 9047 // Record all 3 overflow attributes because IE does not 9048 // change the overflow attribute when overflowX and 9049 // overflowY are set to the same value 9050 opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ]; 9051 9052 // Set display property to inline-block for height/width 9053 // animations on inline elements that are having width/height animated 9054 if ( jQuery.css( this, "display" ) === "inline" && 9055 jQuery.css( this, "float" ) === "none" ) { 9056 9057 // inline-level elements accept inline-block; 9058 // block-level elements need to be inline with layout 9059 if ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === "inline" ) { 9060 this.style.display = "inline-block"; 9061 9062 } else { 9063 this.style.zoom = 1; 9064 } 9065 } 9066 } 9067 } 9068 9069 if ( opt.overflow != null ) { 9070 this.style.overflow = "hidden"; 9071 } 9072 9073 for ( p in prop ) { 9074 e = new jQuery.fx( this, opt, p ); 9075 val = prop[ p ]; 9076 9077 if ( rfxtypes.test( val ) ) { 9078 9079 // Tracks whether to show or hide based on private 9080 // data attached to the element 9081 method = jQuery._data( this, "toggle" + p ) || ( val === "toggle" ? hidden ? "show" : "hide" : 0 ); 9082 if ( method ) { 9083 jQuery._data( this, "toggle" + p, method === "show" ? "hide" : "show" ); 9084 e[ method ](); 9085 } else { 9086 e[ val ](); 9087 } 9088 9089 } else { 9090 parts = rfxnum.exec( val ); 9091 start = e.cur(); 9092 9093 if ( parts ) { 9094 end = parseFloat( parts[2] ); 9095 unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" ); 9096 9097 // We need to compute starting value 9098 if ( unit !== "px" ) {
9099 jQuery.style( this, p, (end || 1) + unit); 9100 start = ( (end || 1) / e.cur() ) * start; 9101 jQuery.style( this, p, start + unit); 9102 } 9103 9104 // If a +=/-= token was provided, we're doing a relative animation 9105 if ( parts[1] ) { 9106 end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start; 9107 } 9108 9109 e.custom( start, end, unit ); 9110 9111 } else { 9112 e.custom( start, val, "" ); 9113 } 9114 } 9115 } 9116 9117 // For JS strict compliance 9118 return true; 9119 } 9120 9121 return optall.queue === false ? 9122 this.each( doAnimation ) : 9123 this.queue( optall.queue, doAnimation ); 9124 }, 9125 9126 stop: function( type, clearQueue, gotoEnd ) { 9127 if ( typeof type !== "string" ) { 9128 gotoEnd = clearQueue; 9129 clearQueue = type; 9130 type = undefined; 9131 } 9132 if ( clearQueue && type !== false ) { 9133 this.queue( type || "fx", [] ); 9134 } 9135 9136 return this.each(function() { 9137 var index, 9138 hadTimers = false, 9139 timers = jQuery.timers, 9140 data = jQuery._data( this ); 9141 9142 // clear marker counters if we know they won't be 9143 if ( !gotoEnd ) { 9144 jQuery._unmark( true, this ); 9145 } 9146 9147 function stopQueue( elem, data, index ) { 9148 var hooks = data[ index ]; 9149 jQuery.removeData( elem, index, true ); 9150 hooks.stop( gotoEnd ); 9151 } 9152 9153 if ( type == null ) { 9154 for ( index in data ) { 9155 if ( data[ index ] && data[ index ].stop && index.indexOf(".run") === index.length - 4 ) { 9156 stopQueue( this, data, index ); 9157 } 9158 } 9159 } else if ( data[ index = type + ".run" ] && data[ index ].stop ){ 9160 stopQueue( this, data, index ); 9161 } 9162 9163 for ( index = timers.length; index--; ) { 9164 if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) { 9165 if ( gotoEnd ) { 9166 9167 // force the next step to be the last 9168 timers[ index ]( true ); 9169 } else { 9170 timers[ index ].saveState(); 9171 } 9172 hadTimers = true; 9173 timers.splice( index, 1 ); 9174 } 9175 } 9176 9177 // start the next in the queue if the last step wasn't forced 9178 // timers currently will call their complete callbacks, which will dequeue 9179 // but only if they were gotoEnd 9180 if ( !( gotoEnd && hadTimers ) ) { 9181 jQuery.dequeue( this, type ); 9182 } 9183 }); 9184 } 9185 9186}); 9187 9188// Animations created synchronously will run synchronously 9189function createFxNow() { 9190 setTimeout( clearFxNow, 0 ); 9191 return ( fxNow = jQuery.now() ); 9192} 9193 9194function clearFxNow() { 9195 fxNow = undefined; 9196} 9197 9198// Generate parameters to create a standard animation 9199function genFx( type, num ) { 9200 var obj = {}; 9201 9202 jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() { 9203 obj[ this ] = type; 9204 }); 9205 9206 return obj; 9207} 9208 9209// Generate shortcuts for custom animations 9210jQuery.each({ 9211 slideDown: genFx( "show", 1 ), 9212 slideUp: genFx( "hide", 1 ), 9213 slideToggle: genFx( "toggle", 1 ), 9214 fadeIn: { opacity: "show" }, 9215 fadeOut: { opacity: "hide" }, 9216 fadeToggle: { opacity: "toggle" } 9217}, function( name, props ) { 9218 jQuery.fn[ name ] = function( speed, easing, callback ) { 9219 return this.animate( props, speed, easing, callback ); 9220 }; 9221}); 9222 9223jQuery.extend({ 9224 speed: function( speed, easing, fn ) { 9225 var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { 9226 complete: fn || !fn && easing || 9227 jQuery.isFunction( speed ) && speed, 9228 duration: speed, 9229 easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing 9230 }; 9231 9232 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : 9233 opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default; 9234 9235 // normalize opt.queue - true/undefined/null -> "fx" 9236 if ( opt.queue == null || opt.queue === true ) { 9237 opt.queue = "fx"; 9238 } 9239 9240 // Queueing 9241 opt.old = opt.complete; 9242 9243 opt.complete = function( noUnmark ) { 9244 if ( jQuery.isFunction( opt.old ) ) { 9245 opt.old.call( this ); 9246 } 9247 9248 if ( opt.queue ) { 9249 jQuery.dequeue( this, opt.queue ); 9250 } else if ( noUnmark !== false ) { 9251 jQuery._unmark( this ); 9252 } 9253 }; 9254 9255 return opt; 9256 }, 9257 9258 easing: { 9259 linear: function( p, n, firstNum, diff ) { 9260 return firstNum + diff * p; 9261 }, 9262 swing: function( p, n, firstNum, diff ) { 9263 return ( ( -Math.cos( p*Math.PI ) / 2 ) + 0.5 ) * diff + firstNum; 9264 } 9265 }, 9266 9267 timers: [], 9268 9269 fx: function( elem, options, prop ) { 9270 this.options = options; 9271 this.elem = elem; 9272 this.prop = prop; 9273 9274 options.orig = options.orig || {}; 9275 } 9276 9277}); 9278 9279jQuery.fx.prototype = { 9280 // Simple function for setting a style value 9281 update: function() { 9282 if ( this.options.step ) { 9283 this.options.step.call( this.elem, this.now, this ); 9284 } 9285 9286 ( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this ); 9287 }, 9288 9289 // Get the current size 9290 cur: function() { 9291 if ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) { 9292 return this.elem[ this.prop ]; 9293 } 9294 9295 var parsed, 9296 r = jQuery.css( this.elem, this.prop ); 9297 // Empty strings, null, undefined and "auto" are converted to 0, 9298 // complex values such as "rotate(1rad)" are returned as is, 9299 // simple values such as "10px" are parsed to Float. 9300 return isNaN( parsed = parseFloat( r ) ) ? !r || r === "auto" ? 0 : r : parsed; 9301 }, 9302 9303 // Start an animation from one number to another 9304 custom: function( from, to, unit ) { 9305 var self = this, 9306 fx = jQuery.fx; 9307 9308 this.startTime = fxNow || createFxNow(); 9309 this.end = to; 9310 this.now = this.start = from; 9311 this.pos = this.state = 0; 9312 this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" ); 9313 9314 function t( gotoEnd ) { 9315 return self.step( gotoEnd ); 9316 } 9317 9318 t.queue = this.options.queue; 9319 t.elem = this.elem;
9320 t.saveState = function() { 9321 if ( self.options.hide && jQuery._data( self.elem, "fxshow" + self.prop ) === undefined ) { 9322 jQuery._data( self.elem, "fxshow" + self.prop, self.start ); 9323 } 9324 }; 9325 9326 if ( t() && jQuery.timers.push(t) && !timerId ) { 9327 timerId = setInterval( fx.tick, fx.interval ); 9328 } 9329 }, 9330 9331 // Simple 'show' function 9332 show: function() { 9333 var dataShow = jQuery._data( this.elem, "fxshow" + this.prop ); 9334 9335 // Remember where we started, so that we can go back to it later 9336 this.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop ); 9337 this.options.show = true; 9338 9339 // Begin the animation 9340 // Make sure that we start at a small width/height to avoid any flash of content 9341 if ( dataShow !== undefined ) { 9342 // This show is picking up where a previous hide or show left off 9343 this.custom( this.cur(), dataShow ); 9344 } else { 9345 this.custom( this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur() ); 9346 } 9347 9348 // Start by showing the element 9349 jQuery( this.elem ).show(); 9350 }, 9351 9352 // Simple 'hide' function 9353 hide: function() { 9354 // Remember where we started, so that we can go back to it later 9355 this.options.orig[ this.prop ] = jQuery._data( this.elem, "fxshow" + this.prop ) || jQuery.style( this.elem, this.prop ); 9356 this.options.hide = true; 9357 9358 // Begin the animation 9359 this.custom( this.cur(), 0 ); 9360 }, 9361 9362 // Each step of an animation 9363 step: function( gotoEnd ) { 9364 var p, n, complete, 9365 t = fxNow || createFxNow(), 9366 done = true, 9367 elem = this.elem, 9368 options = this.options; 9369 9370 if ( gotoEnd || t >= options.duration + this.startTime ) { 9371 this.now = this.end; 9372 this.pos = this.state = 1; 9373 this.update(); 9374 9375 options.animatedProperties[ this.prop ] = true; 9376 9377 for ( p in options.animatedProperties ) { 9378 if ( options.animatedProperties[ p ] !== true ) { 9379 done = false; 9380 } 9381 } 9382 9383 if ( done ) { 9384 // Reset the overflow 9385 if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) { 9386 9387 jQuery.each( [ "", "X", "Y" ], function( index, value ) { 9388 elem.style[ "overflow" + value ] = options.overflow[ index ]; 9389 }); 9390 } 9391 9392 // Hide the element if the "hide" operation was done 9393 if ( options.hide ) { 9394 jQuery( elem ).hide(); 9395 } 9396 9397 // Reset the properties, if the item has been hidden or shown 9398 if ( options.hide || options.show ) { 9399 for ( p in options.animatedProperties ) { 9400 jQuery.style( elem, p, options.orig[ p ] ); 9401 jQuery.removeData( elem, "fxshow" + p, true ); 9402 // Toggle data is no longer needed 9403 jQuery.removeData( elem, "toggle" + p, true ); 9404 } 9405 } 9406 9407 // Execute the complete function 9408 // in the event that the complete function throws an exception 9409 // we must ensure it won't be called twice. #5684 9410 9411 complete = options.complete; 9412 if ( complete ) { 9413 9414 options.complete = false; 9415 complete.call( elem ); 9416 } 9417 } 9418 9419 return false; 9420 9421 } else { 9422 // classical easing cannot be used with an Infinity duration 9423 if ( options.duration == Infinity ) { 9424 this.now = t; 9425 } else { 9426 n = t - this.startTime; 9427 this.state = n / options.duration; 9428 9429 // Perform the easing function, defaults to swing 9430 this.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration ); 9431 this.now = this.start + ( (this.end - this.start) * this.pos ); 9432 } 9433 // Perform the next step of the animation 9434 this.update(); 9435 } 9436 9437 return true; 9438 } 9439}; 9440 9441jQuery.extend( jQuery.fx, { 9442 tick: function() { 9443 var timer, 9444 timers = jQuery.timers, 9445 i = 0; 9446 9447 for ( ; i < timers.length; i++ ) { 9448 timer = timers[ i ]; 9449 // Checks the timer has not already been removed 9450 if ( !timer() && timers[ i ] === timer ) { 9451 timers.splice( i--, 1 ); 9452 } 9453 } 9454 9455 if ( !timers.length ) { 9456 jQuery.fx.stop(); 9457 } 9458 }, 9459 9460 interval: 13, 9461 9462 stop: function() { 9463 clearInterval( timerId ); 9464 timerId = null; 9465 }, 9466 9467 speeds: { 9468 slow: 600, 9469 fast: 200, 9470 // Default speed 9471 _default: 400 9472 }, 9473 9474 step: { 9475 opacity: function( fx ) { 9476 jQuery.style( fx.elem, "opacity", fx.now ); 9477 }, 9478 9479 _default: function( fx ) { 9480 if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) { 9481 fx.elem.style[ fx.prop ] = fx.now + fx.unit; 9482 } else { 9483 fx.elem[ fx.prop ] = fx.now; 9484 } 9485 } 9486 } 9487}); 9488 9489// Adds width/height step functions 9490// Do not set anything below 0 9491jQuery.each([ "width", "height" ], function( i, prop ) { 9492 jQuery.fx.step[ prop ] = function( fx ) { 9493 jQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit ); 9494 }; 9495}); 9496 9497if ( jQuery.expr && jQuery.expr.filters ) { 9498 jQuery.expr.filters.animated = function( elem ) { 9499 return jQuery.grep(jQuery.timers, function( fn ) { 9500 return elem === fn.elem; 9501 }).length; 9502 }; 9503} 9504 9505// Try to restore the default display value of an element 9506function defaultDisplay( nodeName ) { 9507 9508 if ( !elemdisplay[ nodeName ] ) { 9509 9510 var body = document.body, 9511 elem = jQuery( "<" + nodeName + ">" ).appendTo( body ), 9512 display = elem.css( "display" ); 9513 elem.remove(); 9514 9515 // If the simple way fails, 9516 // get element's real default display by attaching it to a temp iframe 9517 if ( display === "none" || display === "" ) { 9518 // No iframe to use yet, so create it 9519 if ( !iframe ) { 9520 iframe = document.createElement( "iframe" ); 9521 iframe.frameBorder = iframe.width = iframe.height = 0; 9522 } 9523 9524 body.appendChild( iframe ); 9525 9526 // Create a cacheable copy of the iframe document on first call. 9527 // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML 9528 // document to it; WebKit & Firefox won't allow reusing the iframe document. 9529 if ( !iframeDoc || !iframe.createElement ) { 9530 iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document; 9531 iframeDoc.write( ( document.compatMode === "CSS1Compat" ? "<!doctype html>" : "" ) + "<html><body>" ); 9532 iframeDoc.close(); 9533 } 9534 9535 elem = iframeDoc.createElement( nodeName ); 9536 9537 iframeDoc.body.appendChild( elem ); 9538
9539 display = jQuery.css( elem, "display" ); 9540 body.removeChild( iframe ); 9541 } 9542 9543 // Store the correct default display 9544 elemdisplay[ nodeName ] = display; 9545 } 9546 9547 return elemdisplay[ nodeName ]; 9548} 9549 9550 9551 9552 9553var rtable = /^t(?:able|d|h)$/i, 9554 rroot = /^(?:body|html)$/i; 9555 9556if ( "getBoundingClientRect" in document.documentElement ) { 9557 jQuery.fn.offset = function( options ) { 9558 var elem = this[0], box; 9559 9560 if ( options ) { 9561 return this.each(function( i ) { 9562 jQuery.offset.setOffset( this, options, i ); 9563 }); 9564 } 9565 9566 if ( !elem || !elem.ownerDocument ) { 9567 return null; 9568 } 9569 9570 if ( elem === elem.ownerDocument.body ) { 9571 return jQuery.offset.bodyOffset( elem ); 9572 } 9573 9574 try { 9575 box = elem.getBoundingClientRect(); 9576 } catch(e) {} 9577 9578 var doc = elem.ownerDocument, 9579 docElem = doc.documentElement; 9580 9581 // Make sure we're not dealing with a disconnected DOM node 9582 if ( !box || !jQuery.contains( docElem, elem ) ) { 9583 return box ? { top: box.top, left: box.left } : { top: 0, left: 0 }; 9584 } 9585 9586 var body = doc.body, 9587 win = getWindow(doc), 9588 clientTop = docElem.clientTop || body.clientTop || 0, 9589 clientLeft = docElem.clientLeft || body.clientLeft || 0, 9590 scrollTop = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop, 9591 scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft, 9592 top = box.top + scrollTop - clientTop, 9593 left = box.left + scrollLeft - clientLeft; 9594 9595 return { top: top, left: left }; 9596 }; 9597 9598} else { 9599 jQuery.fn.offset = function( options ) { 9600 var elem = this[0]; 9601 9602 if ( options ) { 9603 return this.each(function( i ) { 9604 jQuery.offset.setOffset( this, options, i ); 9605 }); 9606 } 9607 9608 if ( !elem || !elem.ownerDocument ) { 9609 return null; 9610 } 9611 9612 if ( elem === elem.ownerDocument.body ) { 9613 return jQuery.offset.bodyOffset( elem ); 9614 } 9615 9616 var computedStyle, 9617 offsetParent = elem.offsetParent, 9618 prevOffsetParent = elem, 9619 doc = elem.ownerDocument, 9620 docElem = doc.documentElement, 9621 body = doc.body, 9622 defaultView = doc.defaultView, 9623 prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle, 9624 top = elem.offsetTop, 9625 left = elem.offsetLeft; 9626 9627 while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) { 9628 if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) { 9629 break; 9630 } 9631 9632 computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle; 9633 top -= elem.scrollTop; 9634 left -= elem.scrollLeft; 9635 9636 if ( elem === offsetParent ) { 9637 top += elem.offsetTop; 9638 left += elem.offsetLeft; 9639 9640 if ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) { 9641 top += parseFloat( computedStyle.borderTopWidth ) || 0; 9642 left += parseFloat( computedStyle.borderLeftWidth ) || 0; 9643 } 9644 9645 prevOffsetParent = offsetParent; 9646 offsetParent = elem.offsetParent; 9647 } 9648 9649 if ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) { 9650 top += parseFloat( computedStyle.borderTopWidth ) || 0; 9651 left += parseFloat( computedStyle.borderLeftWidth ) || 0; 9652 } 9653 9654 prevComputedStyle = computedStyle; 9655 } 9656 9657 if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) { 9658 top += body.offsetTop; 9659 left += body.offsetLeft; 9660 } 9661 9662 if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) { 9663 top += Math.max( docElem.scrollTop, body.scrollTop ); 9664 left += Math.max( docElem.scrollLeft, body.scrollLeft ); 9665 } 9666 9667 return { top: top, left: left }; 9668 }; 9669} 9670 9671jQuery.offset = { 9672 9673 bodyOffset: function( body ) { 9674 var top = body.offsetTop, 9675 left = body.offsetLeft; 9676 9677 if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) { 9678 top += parseFloat( jQuery.css(body, "marginTop") ) || 0; 9679 left += parseFloat( jQuery.css(body, "marginLeft") ) || 0; 9680 } 9681 9682 return { top: top, left: left }; 9683 }, 9684 9685 setOffset: function( elem, options, i ) { 9686 var position = jQuery.css( elem, "position" ); 9687 9688 // set position first, in-case top/left are set even on static elem 9689 if ( position === "static" ) { 9690 elem.style.position = "relative"; 9691 } 9692 9693 var curElem = jQuery( elem ), 9694 curOffset = curElem.offset(), 9695 curCSSTop = jQuery.css( elem, "top" ), 9696 curCSSLeft = jQuery.css( elem, "left" ), 9697 calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1, 9698 props = {}, curPosition = {}, curTop, curLeft; 9699 9700 // need to be able to calculate position if either top or left is auto and position is either absolute or fixed 9701 if ( calculatePosition ) { 9702 curPosition = curElem.position(); 9703 curTop = curPosition.top; 9704 curLeft = curPosition.left; 9705 } else { 9706 curTop = parseFloat( curCSSTop ) || 0; 9707 curLeft = parseFloat( curCSSLeft ) || 0; 9708 } 9709 9710 if ( jQuery.isFunction( options ) ) { 9711 options = options.call( elem, i, curOffset ); 9712 } 9713 9714 if ( options.top != null ) { 9715 props.top = ( options.top - curOffset.top ) + curTop; 9716 } 9717 if ( options.left != null ) { 9718 props.left = ( options.left - curOffset.left ) + curLeft; 9719 } 9720 9721 if ( "using" in options ) { 9722 options.using.call( elem, props ); 9723 } else { 9724 curElem.css( props ); 9725 } 9726 } 9727}; 9728 9729 9730jQuery.fn.extend({ 9731 9732 position: function() { 9733 if ( !this[0] ) { 9734 return null; 9735 } 9736 9737 var elem = this[0], 9738 9739 // Get *real* offsetParent 9740 offsetParent = this.offsetParent(), 9741 9742 // Get correct offsets 9743 offset = this.offset(), 9744 parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset(); 9745 9746 // Subtract element margins 9747 // note: when an element has margin: auto the offsetLeft and marginLeft 9748 // are the same in Safari causing offset.left to incorrectly be 0 9749 offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0; 9750 offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0; 9751 9752 // Add offsetParent borders 9753 parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0; 9754 parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0; 9755 9756 // Subtract the two offsets 9757 return { 9758 top: offset.top - parentOffset.top, 9759 left: offset.left - parentOffset.left 9760 }; 9761 }, 9762 9763 offsetParent: function() { 9764 return this.map(function() { 9765 var offsetParent = this.offsetParent || document.body;
9766 while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) { 9767 offsetParent = offsetParent.offsetParent; 9768 } 9769 return offsetParent; 9770 }); 9771 } 9772}); 9773 9774 9775// Create scrollLeft and scrollTop methods 9776jQuery.each( ["Left", "Top"], function( i, name ) { 9777 var method = "scroll" + name; 9778 9779 jQuery.fn[ method ] = function( val ) { 9780 var elem, win; 9781 9782 if ( val === undefined ) { 9783 elem = this[ 0 ]; 9784 9785 if ( !elem ) { 9786 return null; 9787 } 9788 9789 win = getWindow( elem ); 9790 9791 // Return the scroll offset 9792 return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] : 9793 jQuery.support.boxModel && win.document.documentElement[ method ] || 9794 win.document.body[ method ] : 9795 elem[ method ]; 9796 } 9797 9798 // Set the scroll offset 9799 return this.each(function() { 9800 win = getWindow( this ); 9801 9802 if ( win ) { 9803 win.scrollTo( 9804 !i ? val : jQuery( win ).scrollLeft(), 9805 i ? val : jQuery( win ).scrollTop() 9806 ); 9807 9808 } else { 9809 this[ method ] = val; 9810 } 9811 }); 9812 }; 9813}); 9814 9815function getWindow( elem ) { 9816 return jQuery.isWindow( elem ) ? 9817 elem : 9818 elem.nodeType === 9 ? 9819 elem.defaultView || elem.parentWindow : 9820 false; 9821} 9822 9823 9824 9825 9826// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods 9827jQuery.each([ "Height", "Width" ], function( i, name ) { 9828 9829 var type = name.toLowerCase(); 9830 9831 // innerHeight and innerWidth 9832 jQuery.fn[ "inner" + name ] = function() { 9833 var elem = this[0]; 9834 return elem ? 9835 elem.style ? 9836 parseFloat( jQuery.css( elem, type, "padding" ) ) : 9837 this[ type ]() : 9838 null; 9839 }; 9840 9841 // outerHeight and outerWidth 9842 jQuery.fn[ "outer" + name ] = function( margin ) { 9843 var elem = this[0]; 9844 return elem ? 9845 elem.style ? 9846 parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) : 9847 this[ type ]() : 9848 null; 9849 }; 9850 9851 jQuery.fn[ type ] = function( size ) { 9852 // Get window width or height 9853 var elem = this[0]; 9854 if ( !elem ) { 9855 return size == null ? null : this; 9856 } 9857 9858 if ( jQuery.isFunction( size ) ) { 9859 return this.each(function( i ) { 9860 var self = jQuery( this ); 9861 self[ type ]( size.call( this, i, self[ type ]() ) ); 9862 }); 9863 } 9864 9865 if ( jQuery.isWindow( elem ) ) { 9866 // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode 9867 // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat 9868 var docElemProp = elem.document.documentElement[ "client" + name ], 9869 body = elem.document.body; 9870 return elem.document.compatMode === "CSS1Compat" && docElemProp || 9871 body && body[ "client" + name ] || docElemProp; 9872 9873 // Get document width or height 9874 } else if ( elem.nodeType === 9 ) { 9875 // Either scroll[Width/Height] or offset[Width/Height], whichever is greater 9876 return Math.max( 9877 elem.documentElement["client" + name], 9878 elem.body["scroll" + name], elem.documentElement["scroll" + name], 9879 elem.body["offset" + name], elem.documentElement["offset" + name] 9880 ); 9881 9882 // Get or set width or height on the element 9883 } else if ( size === undefined ) { 9884 var orig = jQuery.css( elem, type ), 9885 ret = parseFloat( orig ); 9886 9887 return jQuery.isNumeric( ret ) ? ret : orig; 9888 9889 // Set the width or height on the element (default to pixels if value is unitless) 9890 } else { 9891 return this.css( type, typeof size === "string" ? size : size + "px" ); 9892 } 9893 }; 9894 9895}); 9896 9897 9898 9899 9900// Expose jQuery to the global object 9901window.jQuery = window.$ = jQuery; 9902 9903// Expose jQuery as an AMD module, but only for AMD loaders that 9904// understand the issues with loading multiple versions of jQuery 9905// in a page that all might call define(). The loader will indicate 9906// they have special allowances for multiple jQuery versions by 9907// specifying define.amd.jQuery = true. Register as a named module, 9908// since jQuery can be concatenated with other files that may use define, 9909// but not use a proper concatenation script that understands anonymous 9910// AMD modules. A named AMD is safest and most robust way to register. 9911// Lowercase jquery is used because AMD module names are derived from 9912// file names, and jQuery is normally delivered in a lowercase file name. 9913// Do this after creating the global so that if an AMD module wants to call
vendor: 5,421 bytes, lines 9914-10010
9914// noConflict to hide this version of jQuery, it will work. 9915if ( typeof define === "function" && define.amd && define.amd.jQuery ) { 9916 define( "jquery", [], function () { return jQuery; } ); 9917} 9918 9919 9920 9921})( window ); 9922 9923/*! Copyright (c) 2013 Brandon Aaron (http://brandon.aaron.sh) 9924 * Licensed under the MIT License (LICENSE.txt). 9925 * 9926 * Version: 3.1.12 9927 * 9928 * Requires: jQuery 1.2.2+ 9929 */ 9930!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})}); 9931/** //** ----= mwImageReader =--------------------------------------------------------------------------------------\**//** \ 9932* 9933* Fast loads image from File object and runs callback on it. 9934* 9935* @param object(File) $file - File object to use as source. 9936* @param function $callback - Callback to execute. 9937* 9938\**//** ---------------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 9939function mwImageReader ($file, $callback) { 9940 9941 // Using native DOM, so need to fallback if jQuery happen 9942 if ( $file instanceof jQuery ) 9943 $file = $file.get(0); 9944 9945 // If file is DOM input - using first file 9946 if ( $file instanceof HTMLInputElement ) 9947 $file = $file.files[0]; 9948 9949 // Nothng to do if no files selected 9950 if ( !$file ) 9951 return; 9952 9953 // Nothing to do for non image file 9954 if ( !$file.type.match(/image.*/) ) 9955 return; 9956 9957 // Reading file 9958 var $reader = new FileReader(); 9959 $reader.onload = function ($e) { 9960 9961 // Issuing callback 9962 if ( typeof($callback) == 'function' ) 9963 $callback($reader.result); 9964 9965 }; //FUNC reader.onload 9966 9967 $reader.readAsDataURL($file); 9968 9969} //FUNC mwImageReader 9970 9971/** //** ----= mwImagePreview =--------------------------------------------------------------------------------------\**//** \ 9972* 9973* Fast loads image from File object (usually obtained from file input) into <img> element using HTML5 filesAPI. 9974* 9975* @param jQuery $image - Image to update. 9976* @param object(File) $file - File object to use as source. 9977* 9978\**//** ---------------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 9979function mwImagePreview ($image, $file, $callback) { 9980 9981 // Using native DOM, so need to fallback if jQuery happen 9982 if ( $image instanceof jQuery ) 9983 $image = $image.get(0); 9984 9985 // Reading image from file input and applying to image 9986 mwImageReader($file, function ($src) { 9987 9988 // Saving old event handler, replacing with own and then returning it back 9989 var $oe = $image.onload; 9990 9991 // Triggering callback after image was actually drawn 9992 // Setting this before 9993 $image.onload = function () { 9994 9995 // Resetting onload we just added 9996 $image.onload = $oe; 9997 9998 // Issuing callback 9999 if ( typeof($callback) == 'function' ) 10000 $callback($src); 10001 10002 }; //FUNC image.onLoad 10003 10004 // Now after event is setup, we can actually apply loaded image 10005 $image.src = $src; 10006 10007 }); //mwImageReader.callback 10008 10009} //FUNC mwImagePreview 10010
10011/** //** ----= mwBackgroundPreview =------------------------------------------------------------------------------\**//** \ 10012* 10013* Fast loads image from File object (usually obtained from file input) into background of element using HTML5 filesAPI. 10014* 10015* @param jQuery $image - Image to update. 10016* @param object(File) $file - File object to use as source. 10017* 10018\**//** ---------------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 10019function mwBackgroundPreview ($image, $file, $callback) { 10020 10021 // Reading image from file input and applying to image 10022 mwImageReader($file, function ($src) { 10023 10024 // Now after event is setup, we can actually apply loaded image 10025 $image.css('background-image', "url('"+$src+"')"); 10026 10027 // Issuing callback 10028 if ( typeof($callback) == 'function' ) 10029 $callback($src); 10030 10031 }); //mwImageReader.callback 10032 10033} //FUNC mwBackgroundPreview 10034 10035/** //** ----= mwOnImageChange =--------------------------------------------------------------------------------------\**//** \ 10036* 10037* Binds onChange event to given file input, and updates specified <img> element using HTML5 files API once input changes. 10038* 10039* @param jQuery $image - Image to update. 10040* @param jQuery $imageInput - File input to bing. 10041* 10042\**//** ---------------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 10043function mwOnImageChange ($image, $imageInput) { 10044 10045 // Need to check if files API is really available before do fancy tricks 10046 if ( !isFilesAPI() ) return; 10047 10048 $imageInput 10049 .off('change.mwOnImageChange') 10050 .on('change.mwOnImageChange', function () { 10051 10052 // Safety check 10053 if ( !this.files.length ) 10054 return; 10055 10056 // Using first given file (single image update essencially) 10057 mwImagePreview($image, this.files[0]); 10058 10059 }) //onChange 10060 ; //jQuery imageInput 10061 10062} //FUNC mwOnImageChange 10063 10064/** //** ----= mwLoadImage =--------------------------------------------------------------------------------------\**//** \ 10065* 10066* Adds preloader to specified <img> element. Uses expected dimensions to draw proper loading box. 10067* Uses native DOM tree methods, to be less depended on onLoad event (no need to wait other libs to load). 10068* Detects element proportinal changes (in case of dynamic image widths of responsive images). 10069* 10070* @param DOMElement $image - Image to load. 10071* @param int $width, $height - Expected image dimensions. 10072* 10073\**//** ---------------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 10074function mwLoadImage ($image, $width, $height) { 10075 10076 if ( !$image ) 10077 return; 10078 10079 // Using native DOM, so need to fallback if jQuery happen 10080 if ( $image instanceof jQuery || $image.jquery ) 10081 $image = $image.get(0); 10082 10083 // Not doing anyting if image is loaded already (cache?) 10084 if ( $image.naturalWidth || $image.naturalHeight ) 10085 return; 10086 10087 // Have to have some defaults, 10088 $width = $width || $image.scrollWidth; 10089 $height = $height || 30; 10090 10091 // Calculating ratio for scticking sizes. Will calculate on place from width, for full responsive behavior 10092 var $ratio = $width / $height; 10093 10094 // Saving original image styles, to restore after it's loaded 10095 var $css = { 10096 'width' : $image.style.width, 10097 'height' : $image.style.height, 10098 } //$css 10099 10100 // Also temprary removing alt text, so saving it too 10101 var $alt = $image.getAttribute('alt'); 10102 $image.setAttribute('alt', ''); 10103 10104 // Setting loading state 10105 $image.className += ' loading'; 10106 10107 // Setting image size strictly while it loads (to make sure loader look correctly) 10108 // Calculating through ratio, to make sure % widths/heights are handled correctly on responsive 10109 // ToDo: Test source dimensions, might be clientWidth better to use as source 10110 $image.style.width = $width + 'px'; 10111 $image.style.height = Math.round($width / $ratio) + 'px'; 10112 10113 // When image loaded - need to revert changes and remove loading state 10114 $image.onload = function () { 10115 10116 // Removing class 10117 $image.className = $image.className.replace('loading', ''); 10118 10119 // Setting height/width back 10120 $image.style.width = $css.width; 10121 $image.style.height = $css.height; 10122 10123 // Restoring alt 10124 $image.setAttribute('alt', $alt); 10125 10126 // Unsetting onload 10127 $image.onload = false;
10128 } //FUNC $image.onLoad 10129 10130} //FUNC mwLoadImage 10131 10132/** //** ----= mwInitMedia =--------------------------------------------------------------------------------------\**//** \ 10133* 10134* Initiates common morweb audion/video players on page. 10135* 10136* @param jQuery [$context] - Context to search within. 10137* 10138\**//** ---------------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 10139function mwInitMedia ($context) { 10140 10141 // ToDo: Implement conditional media resources initiating 10142 var $el = jQuery('audio, video', $context); 10143 10144 if ( !$el.length ) 10145 return; 10146 10147 // Initiating common audio/video 10148 $el.mediaelementplayer({ 10149 enableAutosize : false, 10150 alwaysShowControls : false, 10151 iconSprite : '/cms3/res/mediaelement/mejs-controls.svg', 10152 enableKeyboard : false, 10153 // controls : false, 10154 // useDefaultControls : false, 10155 10156 /*/ // For user with CDN 10157 pluginPath : '/cms/res/mediaelement/', 10158 shimScriptAccess : 'always', 10159 /**/ 10160 success : function( $mediaElement, $originalNode, $instance ) { 10161 10162 // Storing instance as element data for easy access later 10163 jQuery($originalNode).data('mediaelement', $instance); 10164 10165 // Workaround to retain controls attribute on video 10166 // Somehow mediaelement looses it, and fails to init 10167 // Required only on video 10168 // ToDo: invesitgate conditions 10169 // Discovered in 4.2.5 10170 // In 2025 we don't need to control controls again. Browsers evolve. 10171 /*/ 10172 jQuery($originalNode).attr({ 10173 'controls' : 'controls' 10174 }); 10175 10176 setTimeout( function () { 10177 // jQuery($originalNode).removeAttr('controls'); 10178 }, 10); 10179 10180 /*/ 10181 // jQuery($originalNode).removeAttr('controls'); 10182 /**/ 10183 }, //FUNC success 10184 10185 }); //mediaelementplayer.options 10186 10187 // ToDo: Implement widget based initiations 10188 10189} //FUNC mwInitMedia 10190 10191/*! 10192 * MediaElement.js 10193 * http://www.mediaelementjs.com/ 10194 * 10195 * Wrapper that mimics native HTML5 MediaElement (audio and video) 10196 * using a variety of technologies (pure JavaScript, iframe) 10197 * 10198 * Copyright 2010-2017, John Dyer (http://j.hn/) 10199 * License: MIT 10200 * 10201 */(function(){function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}return e})()({1:[function(_dereq_,module,exports){ 10202 10203},{}],2:[function(_dereq_,module,exports){ 10204(function (global){ 10205var topLevel = typeof global !== 'undefined' ? global : 10206 typeof window !== 'undefined' ? window : {} 10207var minDoc = _dereq_(1); 10208 10209var doccy; 10210 10211if (typeof document !== 'undefined') { 10212 doccy = document; 10213} else { 10214 doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4']; 10215 10216 if (!doccy) { 10217 doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc; 10218 } 10219} 10220 10221module.exports = doccy; 10222 10223}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 10224},{"1":1}],3:[function(_dereq_,module,exports){ 10225(function (global){ 10226var win; 10227 10228if (typeof window !== "undefined") { 10229 win = window; 10230} else if (typeof global !== "undefined") { 10231 win = global; 10232} else if (typeof self !== "undefined"){ 10233 win = self; 10234} else { 10235 win = {}; 10236} 10237 10238module.exports = win; 10239 10240}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 10241},{}],4:[function(_dereq_,module,exports){ 10242(function (root) { 10243 10244 // Store setTimeout reference so promise-polyfill will be unaffected by 10245 // other code modifying setTimeout (like sinon.useFakeTimers()) 10246 var setTimeoutFunc = setTimeout; 10247 10248 function noop() {} 10249 10250 // Polyfill for Function.prototype.bind 10251 function bind(fn, thisArg) { 10252 return function () { 10253 fn.apply(thisArg, arguments); 10254 }; 10255 } 10256 10257 function Promise(fn) { 10258 if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new'); 10259 if (typeof fn !== 'function') throw new TypeError('not a function'); 10260 this._state = 0; 10261 this._handled = false;
vendor: 25,855 bytes, lines 10262-10877
10262 this._value = undefined; 10263 this._deferreds = []; 10264 10265 doResolve(fn, this); 10266 } 10267 10268 function handle(self, deferred) { 10269 while (self._state === 3) { 10270 self = self._value; 10271 } 10272 if (self._state === 0) { 10273 self._deferreds.push(deferred); 10274 return; 10275 } 10276 self._handled = true; 10277 Promise._immediateFn(function () { 10278 var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected; 10279 if (cb === null) { 10280 (self._state === 1 ? resolve : reject)(deferred.promise, self._value); 10281 return; 10282 } 10283 var ret; 10284 try { 10285 ret = cb(self._value); 10286 } catch (e) { 10287 reject(deferred.promise, e); 10288 return; 10289 } 10290 resolve(deferred.promise, ret); 10291 }); 10292 } 10293 10294 function resolve(self, newValue) { 10295 try { 10296 // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure 10297 if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.'); 10298 if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) { 10299 var then = newValue.then; 10300 if (newValue instanceof Promise) { 10301 self._state = 3; 10302 self._value = newValue; 10303 finale(self); 10304 return; 10305 } else if (typeof then === 'function') { 10306 doResolve(bind(then, newValue), self); 10307 return; 10308 } 10309 } 10310 self._state = 1; 10311 self._value = newValue; 10312 finale(self); 10313 } catch (e) { 10314 reject(self, e); 10315 } 10316 } 10317 10318 function reject(self, newValue) { 10319 self._state = 2; 10320 self._value = newValue; 10321 finale(self); 10322 } 10323 10324 function finale(self) { 10325 if (self._state === 2 && self._deferreds.length === 0) { 10326 Promise._immediateFn(function() { 10327 if (!self._handled) { 10328 Promise._unhandledRejectionFn(self._value); 10329 } 10330 }); 10331 } 10332 10333 for (var i = 0, len = self._deferreds.length; i < len; i++) { 10334 handle(self, self._deferreds[i]); 10335 } 10336 self._deferreds = null; 10337 } 10338 10339 function Handler(onFulfilled, onRejected, promise) { 10340 this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null; 10341 this.onRejected = typeof onRejected === 'function' ? onRejected : null; 10342 this.promise = promise; 10343 } 10344 10345 /** 10346 * Take a potentially misbehaving resolver function and make sure 10347 * onFulfilled and onRejected are only called once. 10348 * 10349 * Makes no guarantees about asynchrony. 10350 */ 10351 function doResolve(fn, self) { 10352 var done = false; 10353 try { 10354 fn(function (value) { 10355 if (done) return; 10356 done = true; 10357 resolve(self, value); 10358 }, function (reason) { 10359 if (done) return; 10360 done = true; 10361 reject(self, reason); 10362 }); 10363 } catch (ex) { 10364 if (done) return; 10365 done = true; 10366 reject(self, ex); 10367 } 10368 } 10369 10370 Promise.prototype['catch'] = function (onRejected) { 10371 return this.then(null, onRejected); 10372 }; 10373 10374 Promise.prototype.then = function (onFulfilled, onRejected) { 10375 var prom = new (this.constructor)(noop); 10376 10377 handle(this, new Handler(onFulfilled, onRejected, prom)); 10378 return prom; 10379 }; 10380 10381 Promise.all = function (arr) { 10382 var args = Array.prototype.slice.call(arr); 10383 10384 return new Promise(function (resolve, reject) { 10385 if (args.length === 0) return resolve([]); 10386 var remaining = args.length; 10387 10388 function res(i, val) { 10389 try { 10390 if (val && (typeof val === 'object' || typeof val === 'function')) { 10391 var then = val.then; 10392 if (typeof then === 'function') { 10393 then.call(val, function (val) { 10394 res(i, val); 10395 }, reject); 10396 return; 10397 } 10398 } 10399 args[i] = val; 10400 if (--remaining === 0) { 10401 resolve(args); 10402 } 10403 } catch (ex) { 10404 reject(ex); 10405 } 10406 } 10407 10408 for (var i = 0; i < args.length; i++) { 10409 res(i, args[i]); 10410 } 10411 }); 10412 }; 10413 10414 Promise.resolve = function (value) { 10415 if (value && typeof value === 'object' && value.constructor === Promise) { 10416 return value; 10417 } 10418 10419 return new Promise(function (resolve) { 10420 resolve(value); 10421 }); 10422 }; 10423 10424 Promise.reject = function (value) { 10425 return new Promise(function (resolve, reject) { 10426 reject(value); 10427 }); 10428 }; 10429 10430 Promise.race = function (values) { 10431 return new Promise(function (resolve, reject) { 10432 for (var i = 0, len = values.length; i < len; i++) { 10433 values[i].then(resolve, reject); 10434 } 10435 }); 10436 }; 10437 10438 // Use polyfill for setImmediate for performance gains 10439 Promise._immediateFn = (typeof setImmediate === 'function' && function (fn) { setImmediate(fn); }) || 10440 function (fn) { 10441 setTimeoutFunc(fn, 0); 10442 }; 10443 10444 Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) { 10445 if (typeof console !== 'undefined' && console) { 10446 console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console 10447 } 10448 }; 10449 10450 /** 10451 * Set the immediate function to execute callbacks 10452 * @param fn {function} Function to execute 10453 * @deprecated 10454 */ 10455 Promise._setImmediateFn = function _setImmediateFn(fn) { 10456 Promise._immediateFn = fn; 10457 }; 10458 10459 /** 10460 * Change the function to execute on unhandled rejection 10461 * @param {function} fn Function to execute on unhandled rejection 10462 * @deprecated 10463 */ 10464 Promise._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) { 10465 Promise._unhandledRejectionFn = fn; 10466 }; 10467 10468 if (typeof module !== 'undefined' && module.exports) { 10469 module.exports = Promise; 10470 } else if (!root.Promise) { 10471 root.Promise = Promise; 10472 } 10473 10474})(this); 10475 10476},{}],5:[function(_dereq_,module,exports){ 10477!function(root, factory) { 10478 "function" == typeof define && define.amd ? // AMD. Register as an anonymous module unless amdModuleId is set 10479 define([], function() { 10480 return root.svg4everybody = factory(); 10481 }) : "object" == typeof module && module.exports ? // Node. Does not work with strict CommonJS, but 10482 // only CommonJS-like environments that support module.exports, 10483 // like Node. 10484 module.exports = factory() : root.svg4everybody = factory(); 10485}(this, function() { 10486 /*! svg4everybody v2.1.9 | github.com/jonathantneal/svg4everybody */ 10487 function embed(parent, svg, target) { 10488 // if the target exists 10489 if (target) { 10490 // create a document fragment to hold the contents of the target 10491 var fragment = document.createDocumentFragment(), viewBox = !svg.hasAttribute("viewBox") && target.getAttribute("viewBox"); 10492 // conditionally set the viewBox on the svg 10493 viewBox && svg.setAttribute("viewBox", viewBox); 10494 // copy the contents of the clone into the fragment 10495 for (// clone the target 10496 var clone = target.cloneNode(!0); clone.childNodes.length; ) { 10497 fragment.appendChild(clone.firstChild); 10498 } 10499 // append the fragment into the svg 10500 parent.appendChild(fragment); 10501 } 10502 } 10503 function loadreadystatechange(xhr) { 10504 // listen to changes in the request 10505 xhr.onreadystatechange = function() { 10506 // if the request is ready 10507 if (4 === xhr.readyState) { 10508 // get the cached html document 10509 var cachedDocument = xhr._cachedDocument; 10510 // ensure the cached html document based on the xhr response 10511 cachedDocument || (cachedDocument = xhr._cachedDocument = document.implementation.createHTMLDocument(""), 10512 cachedDocument.body.innerHTML = xhr.responseText, xhr._cachedTarget = {}), // clear the xhr embeds list and embed each item 10513 xhr._embeds.splice(0).map(function(item) { 10514 // get the cached target 10515 var target = xhr._cachedTarget[item.id]; 10516 // ensure the cached target 10517 target || (target = xhr._cachedTarget[item.id] = cachedDocument.getElementById(item.id)), 10518 // embed the target into the svg 10519 embed(item.parent, item.svg, target); 10520 }); 10521 } 10522 }, // test the ready state change immediately 10523 xhr.onreadystatechange(); 10524 } 10525 function svg4everybody(rawopts) { 10526 function oninterval() { 10527 // while the index exists in the live <use> collection 10528 for (// get the cached <use> index 10529 var index = 0; index < uses.length; ) { 10530 // get the current <use> 10531 var use = uses[index], parent = use.parentNode, svg = getSVGAncestor(parent), src = use.getAttribute("xlink:href") || use.getAttribute("href"); 10532 if (!src && opts.attributeName && (src = use.getAttribute(opts.attributeName)), 10533 svg && src) { 10534 if (polyfill) { 10535 if (!opts.validate || opts.validate(src, svg, use)) { 10536 // remove the <use> element 10537 parent.removeChild(use); 10538 // parse the src and get the url and id 10539 var srcSplit = src.split("#"), url = srcSplit.shift(), id = srcSplit.join("#"); 10540 // if the link is external 10541 if (url.length) { 10542 // get the cached xhr request 10543 var xhr = requests[url]; 10544 // ensure the xhr request exists 10545 xhr || (xhr = requests[url] = new XMLHttpRequest(), xhr.open("GET", url), xhr.send(), 10546 xhr._embeds = []), // add the svg and id as an item to the xhr embeds list 10547 xhr._embeds.push({ 10548 parent: parent, 10549 svg: svg, 10550 id: id 10551 }), // prepare the xhr ready state change event 10552 loadreadystatechange(xhr); 10553 } else { 10554 // embed the local id into the svg 10555 embed(parent, svg, document.getElementById(id)); 10556 } 10557 } else { 10558 // increase the index when the previous value was not "valid" 10559 ++index, ++numberOfSvgUseElementsToBypass; 10560 } 10561 } 10562 } else { 10563 // increase the index when the previous value was not "valid" 10564 ++index; 10565 } 10566 } 10567 // continue the interval 10568 (!uses.length || uses.length - numberOfSvgUseElementsToBypass > 0) && requestAnimationFrame(oninterval, 67); 10569 } 10570 var polyfill, opts = Object(rawopts), newerIEUA = /\bTrident\/[567]\b|\bMSIE (?:9|10)\.0\b/, webkitUA = /\bAppleWebKit\/(\d+)\b/, olderEdgeUA = /\bEdge\/12\.(\d+)\b/, edgeUA = /\bEdge\/.(\d+)\b/, inIframe = window.top !== window.self; 10571 polyfill = "polyfill" in opts ? opts.polyfill : newerIEUA.test(navigator.userAgent) || (navigator.userAgent.match(olderEdgeUA) || [])[1] < 10547 || (navigator.userAgent.match(webkitUA) || [])[1] < 537 || edgeUA.test(navigator.userAgent) && inIframe; 10572 // create xhr requests object 10573 var requests = {}, requestAnimationFrame = window.requestAnimationFrame || setTimeout, uses = document.getElementsByTagName("use"), numberOfSvgUseElementsToBypass = 0; 10574 // conditionally start the interval if the polyfill is active 10575 polyfill && oninterval(); 10576 } 10577 function getSVGAncestor(node) { 10578 for (var svg = node; "svg" !== svg.nodeName.toLowerCase() && (svg = svg.parentNode); ) {} 10579 return svg; 10580 } 10581 return svg4everybody; 10582}); 10583},{}],6:[function(_dereq_,module,exports){ 10584'use strict'; 10585 10586Object.defineProperty(exports, "__esModule", { 10587 value: true 10588}); 10589 10590var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 10591 10592var _mejs = _dereq_(8); 10593 10594var _mejs2 = _interopRequireDefault(_mejs); 10595 10596var _en = _dereq_(16); 10597 10598var _general = _dereq_(26); 10599 10600function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 10601 10602var i18n = { lang: 'en', en: _en.EN }; 10603 10604i18n.language = function () { 10605 for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { 10606 args[_key] = arguments[_key]; 10607 } 10608 10609 if (args !== null && args !== undefined && args.length) { 10610 10611 if (typeof args[0] !== 'string') { 10612 throw new TypeError('Language code must be a string value'); 10613 } 10614 10615 if (!/^[a-z]{2,3}((\-|_)[a-z]{2})?$/i.test(args[0])) { 10616 throw new TypeError('Language code must have format 2-3 letters and. optionally, hyphen, underscore followed by 2 more letters'); 10617 } 10618 10619 i18n.lang = args[0]; 10620 10621 if (i18n[args[0]] === undefined) { 10622 args[1] = args[1] !== null && args[1] !== undefined && _typeof(args[1]) === 'object' ? args[1] : {}; 10623 i18n[args[0]] = !(0, _general.isObjectEmpty)(args[1]) ? args[1] : _en.EN; 10624 } else if (args[1] !== null && args[1] !== undefined && _typeof(args[1]) === 'object') { 10625 i18n[args[0]] = args[1]; 10626 } 10627 } 10628 10629 return i18n.lang; 10630}; 10631 10632i18n.t = function (message) { 10633 var pluralParam = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; 10634 10635 10636 if (typeof message === 'string' && message.length) { 10637 10638 var str = void 0, 10639 pluralForm = void 0; 10640 10641 var language = i18n.language(); 10642 10643 var _plural = function _plural(input, number, form) { 10644 10645 if ((typeof input === 'undefined' ? 'undefined' : _typeof(input)) !== 'object' || typeof number !== 'number' || typeof form !== 'number') { 10646 return input; 10647 } 10648 10649 var _pluralForms = function () { 10650 return [function () { 10651 return arguments.length <= 1 ? undefined : arguments[1]; 10652 }, function () { 10653 return (arguments.length <= 0 ? undefined : arguments[0]) === 1 ? arguments.length <= 1 ? undefined : arguments[1] : arguments.length <= 2 ? undefined : arguments[2]; 10654 }, function () { 10655 return (arguments.length <= 0 ? undefined : arguments[0]) === 0 || (arguments.length <= 0 ? undefined : arguments[0]) === 1 ? arguments.length <= 1 ? undefined : arguments[1] : arguments.length <= 2 ? undefined : arguments[2]; 10656 }, function () { 10657 if ((arguments.length <= 0 ? undefined : arguments[0]) % 10 === 1 && (arguments.length <= 0 ? undefined : arguments[0]) % 100 !== 11) { 10658 return arguments.length <= 1 ? undefined : arguments[1]; 10659 } else if ((arguments.length <= 0 ? undefined : arguments[0]) !== 0) { 10660 return arguments.length <= 2 ? undefined : arguments[2]; 10661 } else { 10662 return arguments.length <= 3 ? undefined : arguments[3]; 10663 } 10664 }, function () { 10665 if ((arguments.length <= 0 ? undefined : arguments[0]) === 1 || (arguments.length <= 0 ? undefined : arguments[0]) === 11) { 10666 return arguments.length <= 1 ? undefined : arguments[1]; 10667 } else if ((arguments.length <= 0 ? undefined : arguments[0]) === 2 || (arguments.length <= 0 ? undefined : arguments[0]) === 12) { 10668 return arguments.length <= 2 ? undefined : arguments[2]; 10669 } else if ((arguments.length <= 0 ? undefined : arguments[0]) > 2 && (arguments.length <= 0 ? undefined : arguments[0]) < 20) { 10670 return arguments.length <= 3 ? undefined : arguments[3]; 10671 } else { 10672 return arguments.length <= 4 ? undefined : arguments[4]; 10673 } 10674 }, function () { 10675 if ((arguments.length <= 0 ? undefined : arguments[0]) === 1) { 10676 return arguments.length <= 1 ? undefined : arguments[1]; 10677 } else if ((arguments.length <= 0 ? undefined : arguments[0]) === 0 || (arguments.length <= 0 ? undefined : arguments[0]) % 100 > 0 && (arguments.length <= 0 ? undefined : arguments[0]) % 100 < 20) { 10678 return arguments.length <= 2 ? undefined : arguments[2]; 10679 } else { 10680 return arguments.length <= 3 ? undefined : arguments[3]; 10681 } 10682 }, function () { 10683 if ((arguments.length <= 0 ? undefined : arguments[0]) % 10 === 1 && (arguments.length <= 0 ? undefined : arguments[0]) % 100 !== 11) { 10684 return arguments.length <= 1 ? undefined : arguments[1]; 10685 } else if ((arguments.length <= 0 ? undefined : arguments[0]) % 10 >= 2 && ((arguments.length <= 0 ? undefined : arguments[0]) % 100 < 10 || (arguments.length <= 0 ? undefined : arguments[0]) % 100 >= 20)) { 10686 return arguments.length <= 2 ? undefined : arguments[2]; 10687 } else { 10688 return [3]; 10689 } 10690 }, function () { 10691 if ((arguments.length <= 0 ? undefined : arguments[0]) % 10 === 1 && (arguments.length <= 0 ? undefined : arguments[0]) % 100 !== 11) { 10692 return arguments.length <= 1 ? undefined : arguments[1]; 10693 } else if ((arguments.length <= 0 ? undefined : arguments[0]) % 10 >= 2 && (arguments.length <= 0 ? undefined : arguments[0]) % 10 <= 4 && ((arguments.length <= 0 ? undefined : arguments[0]) % 100 < 10 || (arguments.length <= 0 ? undefined : arguments[0]) % 100 >= 20)) { 10694 return arguments.length <= 2 ? undefined : arguments[2]; 10695 } else { 10696 return arguments.length <= 3 ? undefined : arguments[3]; 10697 } 10698 }, function () { 10699 if ((arguments.length <= 0 ? undefined : arguments[0]) === 1) { 10700 return arguments.length <= 1 ? undefined : arguments[1]; 10701 } else if ((arguments.length <= 0 ? undefined : arguments[0]) >= 2 && (arguments.length <= 0 ? undefined : arguments[0]) <= 4) { 10702 return arguments.length <= 2 ? undefined : arguments[2]; 10703 } else { 10704 return arguments.length <= 3 ? undefined : arguments[3]; 10705 } 10706 }, function () { 10707 if ((arguments.length <= 0 ? undefined : arguments[0]) === 1) { 10708 return arguments.length <= 1 ? undefined : arguments[1]; 10709 } else if ((arguments.length <= 0 ? undefined : arguments[0]) % 10 >= 2 && (arguments.length <= 0 ? undefined : arguments[0]) % 10 <= 4 && ((arguments.length <= 0 ? undefined : arguments[0]) % 100 < 10 || (arguments.length <= 0 ? undefined : arguments[0]) % 100 >= 20)) { 10710 return arguments.length <= 2 ? undefined : arguments[2]; 10711 } else { 10712 return arguments.length <= 3 ? undefined : arguments[3]; 10713 } 10714 }, function () { 10715 if ((arguments.length <= 0 ? undefined : arguments[0]) % 100 === 1) { 10716 return arguments.length <= 2 ? undefined : arguments[2]; 10717 } else if ((arguments.length <= 0 ? undefined : arguments[0]) % 100 === 2) { 10718 return arguments.length <= 3 ? undefined : arguments[3]; 10719 } else if ((arguments.length <= 0 ? undefined : arguments[0]) % 100 === 3 || (arguments.length <= 0 ? undefined : arguments[0]) % 100 === 4) { 10720 return arguments.length <= 4 ? undefined : arguments[4]; 10721 } else { 10722 return arguments.length <= 1 ? undefined : arguments[1]; 10723 } 10724 }, function () { 10725 if ((arguments.length <= 0 ? undefined : arguments[0]) === 1) { 10726 return arguments.length <= 1 ? undefined : arguments[1]; 10727 } else if ((arguments.length <= 0 ? undefined : arguments[0]) === 2) { 10728 return arguments.length <= 2 ? undefined : arguments[2]; 10729 } else if ((arguments.length <= 0 ? undefined : arguments[0]) > 2 && (arguments.length <= 0 ? undefined : arguments[0]) < 7) { 10730 return arguments.length <= 3 ? undefined : arguments[3]; 10731 } else if ((arguments.length <= 0 ? undefined : arguments[0]) > 6 && (arguments.length <= 0 ? undefined : arguments[0]) < 11) { 10732 return arguments.length <= 4 ? undefined : arguments[4]; 10733 } else { 10734 return arguments.length <= 5 ? undefined : arguments[5]; 10735 } 10736 }, function () { 10737 if ((arguments.length <= 0 ? undefined : arguments[0]) === 0) { 10738 return arguments.length <= 1 ? undefined : arguments[1]; 10739 } else if ((arguments.length <= 0 ? undefined : arguments[0]) === 1) { 10740 return arguments.length <= 2 ? undefined : arguments[2]; 10741 } else if ((arguments.length <= 0 ? undefined : arguments[0]) === 2) { 10742 return arguments.length <= 3 ? undefined : arguments[3]; 10743 } else if ((arguments.length <= 0 ? undefined : arguments[0]) % 100 >= 3 && (arguments.length <= 0 ? undefined : arguments[0]) % 100 <= 10) { 10744 return arguments.length <= 4 ? undefined : arguments[4]; 10745 } else if ((arguments.length <= 0 ? undefined : arguments[0]) % 100 >= 11) { 10746 return arguments.length <= 5 ? undefined : arguments[5]; 10747 } else { 10748 return arguments.length <= 6 ? undefined : arguments[6]; 10749 } 10750 }, function () { 10751 if ((arguments.length <= 0 ? undefined : arguments[0]) === 1) { 10752 return arguments.length <= 1 ? undefined : arguments[1]; 10753 } else if ((arguments.length <= 0 ? undefined : arguments[0]) === 0 || (arguments.length <= 0 ? undefined : arguments[0]) % 100 > 1 && (arguments.length <= 0 ? undefined : arguments[0]) % 100 < 11) { 10754 return arguments.length <= 2 ? undefined : arguments[2]; 10755 } else if ((arguments.length <= 0 ? undefined : arguments[0]) % 100 > 10 && (arguments.length <= 0 ? undefined : arguments[0]) % 100 < 20) { 10756 return arguments.length <= 3 ? undefined : arguments[3]; 10757 } else { 10758 return arguments.length <= 4 ? undefined : arguments[4]; 10759 } 10760 }, function () { 10761 if ((arguments.length <= 0 ? undefined : arguments[0]) % 10 === 1) { 10762 return arguments.length <= 1 ? undefined : arguments[1]; 10763 } else if ((arguments.length <= 0 ? undefined : arguments[0]) % 10 === 2) { 10764 return arguments.length <= 2 ? undefined : arguments[2]; 10765 } else { 10766 return arguments.length <= 3 ? undefined : arguments[3]; 10767 } 10768 }, function () { 10769 return (arguments.length <= 0 ? undefined : arguments[0]) !== 11 && (arguments.length <= 0 ? undefined : arguments[0]) % 10 === 1 ? arguments.length <= 1 ? undefined : arguments[1] : arguments.length <= 2 ? undefined : arguments[2]; 10770 }, function () { 10771 if ((arguments.length <= 0 ? undefined : arguments[0]) === 1) { 10772 return arguments.length <= 1 ? undefined : arguments[1]; 10773 } else if ((arguments.length <= 0 ? undefined : arguments[0]) % 10 >= 2 && (arguments.length <= 0 ? undefined : arguments[0]) % 10 <= 4 && ((arguments.length <= 0 ? undefined : arguments[0]) % 100 < 10 || (arguments.length <= 0 ? undefined : arguments[0]) % 100 >= 20)) { 10774 return arguments.length <= 2 ? undefined : arguments[2]; 10775 } else { 10776 return arguments.length <= 3 ? undefined : arguments[3]; 10777 } 10778 }, function () { 10779 if ((arguments.length <= 0 ? undefined : arguments[0]) === 1) { 10780 return arguments.length <= 1 ? undefined : arguments[1]; 10781 } else if ((arguments.length <= 0 ? undefined : arguments[0]) === 2) { 10782 return arguments.length <= 2 ? undefined : arguments[2]; 10783 } else if ((arguments.length <= 0 ? undefined : arguments[0]) !== 8 && (arguments.length <= 0 ? undefined : arguments[0]) !== 11) { 10784 return arguments.length <= 3 ? undefined : arguments[3]; 10785 } else { 10786 return arguments.length <= 4 ? undefined : arguments[4]; 10787 } 10788 }, function () { 10789 return (arguments.length <= 0 ? undefined : arguments[0]) === 0 ? arguments.length <= 1 ? undefined : arguments[1] : arguments.length <= 2 ? undefined : arguments[2]; 10790 }, function () { 10791 if ((arguments.length <= 0 ? undefined : arguments[0]) === 1) { 10792 return arguments.length <= 1 ? undefined : arguments[1]; 10793 } else if ((arguments.length <= 0 ? undefined : arguments[0]) === 2) { 10794 return arguments.length <= 2 ? undefined : arguments[2]; 10795 } else if ((arguments.length <= 0 ? undefined : arguments[0]) === 3) { 10796 return arguments.length <= 3 ? undefined : arguments[3]; 10797 } else { 10798 return arguments.length <= 4 ? undefined : arguments[4]; 10799 } 10800 }, function () { 10801 if ((arguments.length <= 0 ? undefined : arguments[0]) === 0) { 10802 return arguments.length <= 1 ? undefined : arguments[1]; 10803 } else if ((arguments.length <= 0 ? undefined : arguments[0]) === 1) { 10804 return arguments.length <= 2 ? undefined : arguments[2]; 10805 } else { 10806 return arguments.length <= 3 ? undefined : arguments[3]; 10807 } 10808 }]; 10809 }(); 10810 10811 return _pluralForms[form].apply(null, [number].concat(input)); 10812 }; 10813 10814 if (i18n[language] !== undefined) { 10815 str = i18n[language][message]; 10816 if (pluralParam !== null && typeof pluralParam === 'number') { 10817 pluralForm = i18n[language]['mejs.plural-form']; 10818 str = _plural.apply(null, [str, pluralParam, pluralForm]); 10819 } 10820 } 10821 10822 if (!str && i18n.en) { 10823 str = i18n.en[message]; 10824 if (pluralParam !== null && typeof pluralParam === 'number') { 10825 pluralForm = i18n.en['mejs.plural-form']; 10826 str = _plural.apply(null, [str, pluralParam, pluralForm]); 10827 } 10828 } 10829 10830 str = str || message; 10831 10832 if (pluralParam !== null && typeof pluralParam === 'number') { 10833 str = str.replace('%1', pluralParam); 10834 } 10835 10836 return (0, _general.escapeHTML)(str); 10837 } 10838 10839 return message; 10840}; 10841 10842_mejs2.default.i18n = i18n; 10843 10844if (typeof mejsL10n !== 'undefined') { 10845 _mejs2.default.i18n.language(mejsL10n.language, mejsL10n.strings); 10846} 10847 10848exports.default = i18n; 10849 10850},{"16":16,"26":26,"8":8}],7:[function(_dereq_,module,exports){ 10851'use strict'; 10852 10853Object.defineProperty(exports, "__esModule", { 10854 value: true 10855}); 10856 10857var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 10858 10859var _window = _dereq_(3); 10860 10861var _window2 = _interopRequireDefault(_window); 10862 10863var _document = _dereq_(2); 10864 10865var _document2 = _interopRequireDefault(_document); 10866 10867var _mejs = _dereq_(8); 10868 10869var _mejs2 = _interopRequireDefault(_mejs); 10870 10871var _general = _dereq_(26); 10872 10873var _media2 = _dereq_(28); 10874 10875var _renderer = _dereq_(9); 10876 10877var _constants = _dereq_(24
vendor: 13,265 bytes, lines 10877-11294
10877); 10878 10879function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 10880 10881function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 10882 10883var MediaElement = function MediaElement(idOrNode, options, sources) { 10884 var _this = this; 10885 10886 _classCallCheck(this, MediaElement); 10887 10888 var t = this; 10889 10890 sources = Array.isArray(sources) ? sources : null; 10891 10892 t.defaults = { 10893 renderers: [], 10894 10895 fakeNodeName: 'div', 10896 10897 iconSprite: 'mejs-controls.svg' 10898 }; 10899 10900 options = Object.assign(t.defaults, options); 10901 10902 t.mediaElement = _document2.default.createElement(options.fakeNodeName); 10903 10904 var id = idOrNode, 10905 error = false; 10906 10907 if (typeof idOrNode === 'string') { 10908 t.mediaElement.originalNode = _document2.default.getElementById(idOrNode); 10909 } else { 10910 t.mediaElement.originalNode = idOrNode; 10911 id = idOrNode.id; 10912 } 10913 10914 if (t.mediaElement.originalNode === undefined || t.mediaElement.originalNode === null) { 10915 return null; 10916 } 10917 10918 t.mediaElement.options = options; 10919 id = id || 'mejs_' + Math.random().toString().slice(2); 10920 10921 t.mediaElement.originalNode.setAttribute('id', id + '_from_mejs'); 10922 10923 var tagName = t.mediaElement.originalNode.tagName.toLowerCase(); 10924 if (['video', 'audio'].indexOf(tagName) > -1 && !t.mediaElement.originalNode.getAttribute('preload')) { 10925 t.mediaElement.originalNode.setAttribute('preload', 'none'); 10926 } 10927 10928 t.mediaElement.originalNode.setAttribute('tabindex', -1); 10929 10930 t.mediaElement.originalNode.parentNode.insertBefore(t.mediaElement, t.mediaElement.originalNode); 10931 10932 t.mediaElement.appendChild(t.mediaElement.originalNode); 10933 10934 var processURL = function processURL(url, type) { 10935 if (_window2.default.location.protocol === 'https:' && url.indexOf('http:') === 0 && _constants.IS_IOS && _mejs2.default.html5media.mediaTypes.indexOf(type) > -1) { 10936 var xhr = new XMLHttpRequest(); 10937 xhr.onreadystatechange = function () { 10938 if (this.readyState === 4 && this.status === 200) { 10939 var _url = _window2.default.URL || _window2.default.webkitURL, 10940 blobUrl = _url.createObjectURL(this.response); 10941 t.mediaElement.originalNode.setAttribute('src', blobUrl); 10942 return blobUrl; 10943 } 10944 return url; 10945 }; 10946 xhr.open('GET', url); 10947 xhr.responseType = 'blob'; 10948 xhr.send(); 10949 } 10950 10951 return url; 10952 }; 10953 10954 var mediaFiles = void 0; 10955 if (sources !== null) { 10956 mediaFiles = sources; 10957 } else if (t.mediaElement.originalNode !== null) { 10958 10959 mediaFiles = []; 10960 switch (t.mediaElement.originalNode.nodeName.toLowerCase()) { 10961 case 'iframe': 10962 mediaFiles.push({ 10963 type: '', 10964 src: t.mediaElement.originalNode.getAttribute('src') 10965 }); 10966 break; 10967 case 'audio': 10968 case 'video': 10969 var _sources = t.mediaElement.originalNode.children.length, 10970 nodeSource = t.mediaElement.originalNode.getAttribute('src'); 10971 10972 if (nodeSource) { 10973 var node = t.mediaElement.originalNode, 10974 type = (0, _media2.formatType)(nodeSource, node.getAttribute('type')); 10975 mediaFiles.push({ 10976 type: type, 10977 src: processURL(nodeSource, type) 10978 }); 10979 } 10980 10981 for (var i = 0; i < _sources; i++) { 10982 var n = t.mediaElement.originalNode.children[i]; 10983 if (n.tagName.toLowerCase() === 'source') { 10984 var src = n.getAttribute('src'), 10985 _type = (0, _media2.formatType)(src, n.getAttribute('type')); 10986 mediaFiles.push({ type: _type, src: processURL(src, _type) }); 10987 } 10988 } 10989 break; 10990 } 10991 } 10992 10993 t.mediaElement.id = id; 10994 t.mediaElement.renderers = {}; 10995 t.mediaElement.events = {}; 10996 t.mediaElement.promises = []; 10997 t.mediaElement.renderer = null; 10998 t.mediaElement.rendererName = null; 10999 11000 t.mediaElement.changeRenderer = function (rendererName, mediaFiles) { 11001 var t = _this, 11002 media = Object.keys(mediaFiles[0]).length > 2 ? mediaFiles[0] : mediaFiles[0].src; 11003 11004 if (t.mediaElement.renderer !== undefined && t.mediaElement.renderer !== null && t.mediaElement.renderer.name === rendererName) { 11005 t.mediaElement.renderer.pause(); 11006 t.mediaElement.renderer.show(); 11007 t.mediaElement.renderer.setSrc(media); 11008 return true; 11009 } 11010 11011 if (t.mediaElement.renderer !== undefined && t.mediaElement.renderer !== null) { 11012 t.mediaElement.renderer.pause(); 11013 t.mediaElement.renderer.hide(); 11014 } 11015 11016 var newRenderer = t.mediaElement.renderers[rendererName], 11017 newRendererType = null; 11018 11019 if (newRenderer !== undefined && newRenderer !== null) { 11020 newRenderer.show(); 11021 newRenderer.setSrc(media); 11022 t.mediaElement.renderer = newRenderer; 11023 t.mediaElement.rendererName = rendererName; 11024 return true; 11025 } 11026 11027 var rendererArray = t.mediaElement.options.renderers.length ? t.mediaElement.options.renderers : _renderer.renderer.order; 11028 11029 for (var _i = 0, total = rendererArray.length; _i < total; _i++) { 11030 var index = rendererArray[_i]; 11031 11032 if (index === rendererName) { 11033 var rendererList = _renderer.renderer.renderers; 11034 newRendererType = rendererList[index]; 11035 11036 var renderOptions = Object.assign(newRendererType.options, t.mediaElement.options); 11037 newRenderer = newRendererType.create(t.mediaElement, renderOptions, mediaFiles); 11038 newRenderer.name = rendererName; 11039 11040 t.mediaElement.renderers[newRendererType.name] = newRenderer; 11041 t.mediaElement.renderer = newRenderer; 11042 t.mediaElement.rendererName = rendererName; 11043 newRenderer.show(); 11044 return true; 11045 } 11046 } 11047 11048 return false; 11049 }; 11050 11051 t.mediaElement.setSize = function (width, height) { 11052 if (t.mediaElement.renderer !== undefined && t.mediaElement.renderer !== null) { 11053 t.mediaElement.renderer.setSize(width, height); 11054 } 11055 }; 11056 11057 t.mediaElement.generateError = function (message, urlList) { 11058 message = message || ''; 11059 urlList = Array.isArray(urlList) ? urlList : []; 11060 var event = (0, _general.createEvent)('error', t.mediaElement); 11061 event.message = message; 11062 event.urls = urlList; 11063 t.mediaElement.dispatchEvent(event); 11064 error = true; 11065 }; 11066 11067 var props = _mejs2.default.html5media.properties, 11068 methods = _mejs2.default.html5media.methods, 11069 addProperty = function addProperty(obj, name, onGet, onSet) { 11070 var oldValue = obj[name]; 11071 var getFn = function getFn() { 11072 return onGet.apply(obj, [oldValue]); 11073 }, 11074 setFn = function setFn(newValue) { 11075 oldValue = onSet.apply(obj, [newValue]); 11076 return oldValue; 11077 }; 11078 11079 Object.defineProperty(obj, name, { 11080 get: getFn, 11081 set: setFn 11082 }); 11083 }, 11084 assignGettersSetters = function assignGettersSetters(propName) { 11085 if (propName !== 'src') { 11086 var capName = '' + propName.substring(0, 1).toUpperCase() + propName.substring(1), 11087 getFn = function getFn() { 11088 return t.mediaElement.renderer !== undefined && t.mediaElement.renderer !== null && typeof t.mediaElement.renderer['get' + capName] === 'function' ? t.mediaElement.renderer['get' + capName]() : null; 11089 }, 11090 setFn = function setFn(value) { 11091 if (t.mediaElement.renderer !== undefined && t.mediaElement.renderer !== null && typeof t.mediaElement.renderer['set' + capName] === 'function') { 11092 t.mediaElement.renderer['set' + capName](value); 11093 } 11094 }; 11095 11096 addProperty(t.mediaElement, propName, getFn, setFn); 11097 t.mediaElement['get' + capName] = getFn; 11098 t.mediaElement['set' + capName] = setFn; 11099 } 11100 }, 11101 getSrc = function getSrc() { 11102 return t.mediaElement.renderer !== undefined && t.mediaElement.renderer !== null ? t.mediaElement.renderer.getSrc() : null; 11103 }, 11104 setSrc = function setSrc(value) { 11105 var mediaFiles = []; 11106 if (typeof value === 'string') { 11107 mediaFiles.push({ 11108 src: value, 11109 type: value ? (0, _media2.getTypeFromFile)(value) : '' 11110 }); 11111 } else if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && value.src !== undefined) { 11112 var _src = (0, _media2.absolutizeUrl)(value.src), 11113 _type2 = value.type, 11114 media = Object.assign(value, { 11115 src: _src, 11116 type: (_type2 === '' || _type2 === null || _type2 === undefined) && _src ? (0, _media2.getTypeFromFile)(_src) : _type2 11117 }); 11118 mediaFiles.push(media); 11119 } else if (Array.isArray(value)) { 11120 for (var _i2 = 0, total = value.length; _i2 < total; _i2++) { 11121 11122 var _src2 = (0, _media2.absolutizeUrl)(value[_i2].src), 11123 _type3 = value[_i2].type, 11124 _media = Object.assign(value[_i2], { 11125 src: _src2, 11126 type: (_type3 === '' || _type3 === null || _type3 === undefined) && _src2 ? (0, _media2.getTypeFromFile)(_src2) : _type3 11127 }); 11128 mediaFiles.push(_media); 11129 } 11130 } 11131 11132 var renderInfo = _renderer.renderer.select(mediaFiles, t.mediaElement.options.renderers.length ? t.mediaElement.options.renderers : []), 11133 event = void 0; 11134 11135 if (!t.mediaElement.paused && !(t.mediaElement.src == null || t.mediaElement.src === '')) { 11136 t.mediaElement.pause(); 11137 event = (0, _general.createEvent)('pause', t.mediaElement); 11138 t.mediaElement.dispatchEvent(event); 11139 } 11140 t.mediaElement.originalNode.src = mediaFiles[0].src || ''; 11141 11142 if (renderInfo === null && mediaFiles[0].src) { 11143 t.mediaElement.generateError('No renderer found', mediaFiles); 11144 return; 11145 } 11146 11147 var shouldChangeRenderer = !(mediaFiles[0].src == null || mediaFiles[0].src === ''); 11148 return shouldChangeRenderer ? t.mediaElement.changeRenderer(renderInfo.rendererName, mediaFiles) : null; 11149 }, 11150 triggerAction = function triggerAction(methodName, args) { 11151 try { 11152 if (methodName === 'play' && (t.mediaElement.rendererName === 'native_dash' || t.mediaElement.rendererName === 'native_hls' || t.mediaElement.rendererName === 'vimeo_iframe')) { 11153 var response = t.mediaElement.renderer[methodName](args); 11154 if (response && typeof response.then === 'function') { 11155 response.catch(function () { 11156 if (t.mediaElement.paused) { 11157 setTimeout(function () { 11158 var tmpResponse = t.mediaElement.renderer.play(); 11159 if (tmpResponse !== undefined) { 11160 tmpResponse.catch(function () { 11161 if (!t.mediaElement.renderer.paused) { 11162 t.mediaElement.renderer.pause(); 11163 } 11164 }); 11165 } 11166 }, 150); 11167 } 11168 }); 11169 } 11170 return response; 11171 } else { 11172 return t.mediaElement.renderer[methodName](args); 11173 } 11174 } catch (e) { 11175 t.mediaElement.generateError(e, mediaFiles); 11176 throw e; 11177 } 11178 }, 11179 assignMethods = function assignMethods(methodName) { 11180 t.mediaElement[methodName] = function () { 11181 for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { 11182 args[_key] = arguments[_key]; 11183 } 11184 11185 if (t.mediaElement.renderer !== undefined && t.mediaElement.renderer !== null && typeof t.mediaElement.renderer[methodName] === 'function') { 11186 if (t.mediaElement.promises.length) { 11187 return Promise.all(t.mediaElement.promises).then(function () { 11188 return triggerAction(methodName, args); 11189 }).catch(function (e) { 11190 t.mediaElement.generateError(e, mediaFiles); 11191 return Promise.reject(e); 11192 }); 11193 } else { 11194 return triggerAction(methodName, args); 11195 } 11196 } 11197 return null; 11198 }; 11199 }; 11200 11201 addProperty(t.mediaElement, 'src', getSrc, setSrc); 11202 11203 t.mediaElement.getSrc = getSrc; 11204 t.mediaElement.setSrc = setSrc; 11205 for (var _i3 = 0, total = props.length; _i3 < total; _i3++) { 11206 assignGettersSetters(props[_i3]); 11207 } 11208 11209 for (var _i4 = 0, _total = methods.length; _i4 < _total; _i4++) { 11210 assignMethods(methods[_i4]); 11211 } 11212 11213 t.mediaElement.addEventListener = function (eventName, callback) { 11214 t.mediaElement.events[eventName] = t.mediaElement.events[eventName] || []; 11215 11216 t.mediaElement.events[eventName].push(callback); 11217 }; 11218 t.mediaElement.removeEventListener = function (eventName, callback) { 11219 if (!eventName) { 11220 t.mediaElement.events = {}; 11221 return true; 11222 } 11223 11224 var callbacks = t.mediaElement.events[eventName]; 11225 11226 if (!callbacks) { 11227 return true; 11228 } 11229 11230 if (!callback) { 11231 t.mediaElement.events[eventName] = []; 11232 return true; 11233 } 11234 11235 for (var _i5 = 0; _i5 < callbacks.length; _i5++) { 11236 if (callbacks[_i5] === callback) { 11237 t.mediaElement.events[eventName].splice(_i5, 1); 11238 return true; 11239 } 11240 } 11241 return false; 11242 }; 11243 11244 t.mediaElement.dispatchEvent = function (event) { 11245 var callbacks = t.mediaElement.events[event.type]; 11246 if (callbacks) { 11247 for (var _i6 = 0; _i6 < callbacks.length; _i6++) { 11248 callbacks[_i6].apply(null, [event]); 11249 } 11250 } 11251 }; 11252 11253 t.mediaElement.destroy = function () { 11254 var mediaElement = t.mediaElement.originalNode.cloneNode(true); 11255 var wrapper = t.mediaElement.parentElement; 11256 mediaElement.removeAttribute('id'); 11257 mediaElement.remove(); 11258 t.mediaElement.remove(); 11259 wrapper.appendChild(mediaElement); 11260 }; 11261 11262 if (mediaFiles.length) { 11263 t.mediaElement.src = mediaFiles; 11264 } 11265 11266 if (t.mediaElement.promises.length) { 11267 Promise.all(t.mediaElement.promises).then(function () { 11268 if (t.mediaElement.options.success) { 11269 t.mediaElement.options.success(t.mediaElement, t.mediaElement.originalNode); 11270 } 11271 }).catch(function () { 11272 if (error && t.mediaElement.options.error) { 11273 t.mediaElement.options.error(t.mediaElement, t.mediaElement.originalNode); 11274 } 11275 }); 11276 } else { 11277 if (t.mediaElement.options.success) { 11278 t.mediaElement.options.success(t.mediaElement, t.mediaElement.originalNode); 11279 } 11280 11281 if (error && t.mediaElement.options.error) { 11282 t.mediaElement.options.error(t.mediaElement, t.mediaElement.originalNode); 11283 } 11284 } 11285 11286 return t.mediaElement; 11287}; 11288 11289_window2.default.MediaElement = MediaElement; 11290_mejs2.default.MediaElement = MediaElement; 11291 11292exports.default = MediaElement; 11293 11294},{"
vendor: 15,028 bytes, lines 11294-11748
112942":2,"24":24,"26":26,"28":28,"3":3,"8":8,"9":9}],8:[function(_dereq_,module,exports){ 11295'use strict'; 11296 11297Object.defineProperty(exports, "__esModule", { 11298 value: true 11299}); 11300 11301var _window = _dereq_(3); 11302 11303var _window2 = _interopRequireDefault(_window); 11304 11305function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 11306 11307var mejs = {}; 11308 11309mejs.version = '7.0.7'; 11310 11311mejs.html5media = { 11312 properties: ['volume', 'src', 'currentTime', 'muted', 'duration', 'paused', 'ended', 'buffered', 'error', 'networkState', 'readyState', 'seeking', 'seekable', 'currentSrc', 'preload', 'bufferedBytes', 'bufferedTime', 'initialTime', 'startOffsetTime', 'defaultPlaybackRate', 'playbackRate', 'played', 'autoplay', 'loop', 'controls'], 11313 readOnlyProperties: ['duration', 'paused', 'ended', 'buffered', 'error', 'networkState', 'readyState', 'seeking', 'seekable'], 11314 11315 methods: ['load', 'play', 'pause', 'canPlayType'], 11316 11317 events: ['loadstart', 'durationchange', 'loadedmetadata', 'loadeddata', 'progress', 'canplay', 'canplaythrough', 'suspend', 'abort', 'error', 'emptied', 'stalled', 'play', 'playing', 'pause', 'waiting', 'seeking', 'seeked', 'timeupdate', 'ended', 'ratechange', 'volumechange'], 11318 11319 mediaTypes: ['audio/mp3', 'audio/ogg', 'audio/oga', 'audio/wav', 'audio/x-wav', 'audio/wave', 'audio/x-pn-wav', 'audio/mpeg', 'audio/mp4', 'video/mp4', 'video/webm', 'video/ogg', 'video/ogv'] 11320}; 11321 11322_window2.default.mejs = mejs; 11323 11324exports.default = mejs; 11325 11326},{"3":3}],9:[function(_dereq_,module,exports){ 11327'use strict'; 11328 11329Object.defineProperty(exports, "__esModule", { 11330 value: true 11331}); 11332exports.renderer = undefined; 11333 11334var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 11335 11336var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 11337 11338var _mejs = _dereq_(8); 11339 11340var _mejs2 = _interopRequireDefault(_mejs); 11341 11342function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 11343 11344function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 11345 11346var Renderer = function () { 11347 function Renderer() { 11348 _classCallCheck(this, Renderer); 11349 11350 this.renderers = {}; 11351 this.order = []; 11352 } 11353 11354 _createClass(Renderer, [{ 11355 key: 'add', 11356 value: function add(renderer) { 11357 if (renderer.name === undefined) { 11358 throw new TypeError('renderer must contain at least `name` property'); 11359 } 11360 11361 this.renderers[renderer.name] = renderer; 11362 this.order.push(renderer.name); 11363 } 11364 }, { 11365 key: 'select', 11366 value: function select(mediaFiles) { 11367 var renderers = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; 11368 11369 var renderersLength = renderers.length; 11370 11371 renderers = renderers.length ? renderers : this.order; 11372 11373 if (!renderersLength) { 11374 var rendererIndicator = [/^(html5|native)/i, /iframe$/i], 11375 rendererRanking = function rendererRanking(renderer) { 11376 for (var i = 0, total = rendererIndicator.length; i < total; i++) { 11377 if (rendererIndicator[i].test(renderer)) { 11378 return i; 11379 } 11380 } 11381 return rendererIndicator.length; 11382 }; 11383 11384 renderers.sort(function (a, b) { 11385 return rendererRanking(a) - rendererRanking(b); 11386 }); 11387 } 11388 11389 for (var i = 0, total = renderers.length; i < total; i++) { 11390 var key = renderers[i], 11391 _renderer = this.renderers[key]; 11392 11393 if (_renderer !== null && _renderer !== undefined) { 11394 for (var j = 0, jl = mediaFiles.length; j < jl; j++) { 11395 11396 if (typeof _renderer.canPlayType === 'function' && typeof mediaFiles[j].type === 'string' && _renderer.canPlayType(mediaFiles[j].type)) { 11397 return { 11398 rendererName: _renderer.name, 11399 src: mediaFiles[j].src 11400 }; 11401 } 11402 } 11403 } 11404 } 11405 11406 return null; 11407 } 11408 }, { 11409 key: 'order', 11410 set: function set(order) { 11411 if (!Array.isArray(order)) { 11412 throw new TypeError('order must be an array of strings.'); 11413 } 11414 11415 this._order = order; 11416 }, 11417 get: function get() { 11418 return this._order; 11419 } 11420 }, { 11421 key: 'renderers', 11422 set: function set(renderers) { 11423 if (renderers !== null && (typeof renderers === 'undefined' ? 'undefined' : _typeof(renderers)) !== 'object') { 11424 throw new TypeError('renderers must be an array of objects.'); 11425 } 11426 11427 this._renderers = renderers; 11428 }, 11429 get: function get() { 11430 return this._renderers; 11431 } 11432 }]); 11433 11434 return Renderer; 11435}(); 11436 11437var renderer = exports.renderer = new Renderer(); 11438 11439_mejs2.default.Renderers = renderer; 11440 11441},{"8":8}],10:[function(_dereq_,module,exports){ 11442'use strict'; 11443 11444var _window = _dereq_(3); 11445 11446var _window2 = _interopRequireDefault(_window); 11447 11448var _document = _dereq_(2); 11449 11450var _document2 = _interopRequireDefault(_document); 11451 11452var _i18n = _dereq_(6); 11453 11454var _i18n2 = _interopRequireDefault(_i18n); 11455 11456var _player = _dereq_(17); 11457 11458var _player2 = _interopRequireDefault(_player); 11459 11460var _constants = _dereq_(24); 11461 11462var Features = _interopRequireWildcard(_constants); 11463 11464var _general = _dereq_(26); 11465 11466var _dom = _dereq_(25); 11467 11468var _media = _dereq_(28); 11469 11470var _generate = _dereq_(27); 11471 11472function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } 11473 11474function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 11475 11476Object.assign(_player.config, { 11477 usePluginFullScreen: true, 11478 11479 fullscreenText: null, 11480 11481 useFakeFullscreen: false 11482}); 11483 11484Object.assign(_player2.default.prototype, { 11485 isFullScreen: false, 11486 11487 isNativeFullScreen: false, 11488 11489 isInIframe: false, 11490 11491 isPluginClickThroughCreated: false, 11492 11493 fullscreenMode: '', 11494 11495 containerSizeTimeout: null, 11496 11497 buildfullscreen: function buildfullscreen(player) { 11498 if (!player.isVideo) { 11499 return; 11500 } 11501 11502 player.isInIframe = _window2.default.location !== _window2.default.parent.location; 11503 11504 player.detectFullscreenMode(); 11505 11506 var t = this, 11507 fullscreenTitle = (0, _general.isString)(t.options.fullscreenText) ? t.options.fullscreenText : _i18n2.default.t('mejs.fullscreen'), 11508 fullscreenBtn = _document2.default.createElement('div'); 11509 fullscreenBtn.className = t.options.classPrefix + 'button ' + t.options.classPrefix + 'fullscreen-button'; 11510 fullscreenBtn.innerHTML = (0, _generate.generateControlButton)(t.id, fullscreenTitle, fullscreenTitle, '' + t.media.options.iconSprite, ['icon-fullscreen', 'icon-unfullscreen'], '' + t.options.classPrefix); 11511 t.addControlElement(fullscreenBtn, 'fullscreen'); 11512 11513 fullscreenBtn.addEventListener('click', function () { 11514 var isFullScreen = Features.HAS_TRUE_NATIVE_FULLSCREEN && Features.IS_FULLSCREEN || player.isFullScreen; 11515 11516 if (isFullScreen) { 11517 player.exitFullScreen(); 11518 } else { 11519 player.enterFullScreen(); 11520 } 11521 }); 11522 11523 player.fullscreenBtn = fullscreenBtn; 11524 11525 t.options.keyActions.push({ 11526 keys: [70], 11527 action: function action(player, media, key, event) { 11528 if (!event.ctrlKey) { 11529 if (typeof player.enterFullScreen !== 'undefined') { 11530 if (player.isFullScreen) { 11531 player.exitFullScreen(); 11532 } else { 11533 player.enterFullScreen(); 11534 } 11535 } 11536 } 11537 } 11538 }); 11539 11540 t.exitFullscreenCallback = function (e) { 11541 var key = e.which || e.keyCode || 0; 11542 if (t.options.enableKeyboard && key === 27 && (Features.HAS_TRUE_NATIVE_FULLSCREEN && Features.IS_FULLSCREEN || t.isFullScreen)) { 11543 player.exitFullScreen(); 11544 } 11545 }; 11546 11547 t.globalBind('keydown', t.exitFullscreenCallback); 11548 11549 t.normalHeight = 0; 11550 t.normalWidth = 0; 11551 11552 if (Features.HAS_TRUE_NATIVE_FULLSCREEN) { 11553 var fullscreenChanged = function fullscreenChanged() { 11554 if (player.isFullScreen) { 11555 if (Features.isFullScreen()) { 11556 player.isNativeFullScreen = true; 11557 11558 player.setControlsSize(); 11559 } else { 11560 player.isNativeFullScreen = false; 11561 11562 player.exitFullScreen(); 11563 } 11564 } 11565 }; 11566 11567 player.globalBind(Features.FULLSCREEN_EVENT_NAME, fullscreenChanged); 11568 } 11569 }, 11570 cleanfullscreen: function cleanfullscreen(player) { 11571 player.exitFullScreen(); 11572 player.globalUnbind('keydown', player.exitFullscreenCallback); 11573 }, 11574 detectFullscreenMode: function detectFullscreenMode() { 11575 var t = this, 11576 isNative = t.media.rendererName !== null && /(native|html5)/i.test(t.media.rendererName); 11577 11578 var mode = ''; 11579 11580 if (Features.HAS_TRUE_NATIVE_FULLSCREEN && isNative) { 11581 mode = 'native-native'; 11582 } else if (Features.HAS_TRUE_NATIVE_FULLSCREEN && !isNative) { 11583 mode = 'plugin-native'; 11584 } else if (t.usePluginFullScreen && Features.SUPPORT_POINTER_EVENTS) { 11585 mode = 'plugin-click'; 11586 } 11587 11588 t.fullscreenMode = mode; 11589 return mode; 11590 }, 11591 enterFullScreen: function enterFullScreen() { 11592 var t = this, 11593 isNative = t.media.rendererName !== null && /(html5|native)/i.test(t.media.rendererName), 11594 containerStyles = getComputedStyle(t.getElement(t.container)); 11595 11596 if (!t.isVideo) { 11597 return; 11598 } 11599 11600 if (t.options.useFakeFullscreen === false && (Features.IS_IOS || Features.IS_SAFARI) && Features.HAS_IOS_FULLSCREEN && typeof t.media.originalNode.webkitEnterFullscreen === 'function' && t.media.originalNode.canPlayType((0, _media.getTypeFromFile)(t.media.getSrc()))) { 11601 t.media.originalNode.webkitEnterFullscreen(); 11602 return; 11603 } 11604 11605 (0, _dom.addClass)(_document2.default.documentElement, t.options.classPrefix + 'fullscreen'); 11606 (0, _dom.addClass)(t.getElement(t.container), t.options.classPrefix + 'container-fullscreen'); 11607 11608 t.normalHeight = parseFloat(containerStyles.height); 11609 t.normalWidth = parseFloat(containerStyles.width); 11610 11611 if (t.fullscreenMode === 'native-native' || t.fullscreenMode === 'plugin-native') { 11612 Features.requestFullScreen(t.getElement(t.container)); 11613 11614 if (t.isInIframe) { 11615 setTimeout(function checkFullscreen() { 11616 11617 if (t.isNativeFullScreen) { 11618 var percentErrorMargin = 0.002, 11619 windowWidth = _window2.default.innerWidth || _document2.default.documentElement.clientWidth || _document2.default.body.clientWidth, 11620 screenWidth = screen.width, 11621 absDiff = Math.abs(screenWidth - windowWidth), 11622 marginError = screenWidth * percentErrorMargin; 11623 11624 if (absDiff > marginError) { 11625 t.exitFullScreen(); 11626 } else { 11627 setTimeout(checkFullscreen, 500); 11628 } 11629 } 11630 }, 1000); 11631 } 11632 } 11633 11634 t.getElement(t.container).style.width = '100%'; 11635 t.getElement(t.container).style.height = '100%'; 11636 11637 t.containerSizeTimeout = setTimeout(function () { 11638 t.getElement(t.container).style.width = '100%'; 11639 t.getElement(t.container).style.height = '100%'; 11640 t.setControlsSize(); 11641 }, 500); 11642 11643 if (isNative) { 11644 t.node.style.width = '100%'; 11645 t.node.style.height = '100%'; 11646 } else { 11647 var elements = t.getElement(t.container).querySelectorAll('embed, object, video'), 11648 _total = elements.length; 11649 for (var i = 0; i < _total; i++) { 11650 elements[i].style.width = '100%'; 11651 elements[i].style.height = '100%'; 11652 } 11653 } 11654 11655 if (t.options.setDimensions && typeof t.media.setSize === 'function') { 11656 t.media.setSize(screen.width, screen.height); 11657 } 11658 11659 var layers = t.getElement(t.layers).children, 11660 total = layers.length; 11661 for (var _i = 0; _i < total; _i++) { 11662 layers[_i].style.width = '100%'; 11663 layers[_i].style.height = '100%'; 11664 } 11665 11666 if (t.fullscreenBtn) { 11667 (0, _dom.removeClass)(t.fullscreenBtn, t.options.classPrefix + 'fullscreen'); 11668 (0, _dom.addClass)(t.fullscreenBtn, t.options.classPrefix + 'unfullscreen'); 11669 } 11670 11671 t.setControlsSize(); 11672 t.isFullScreen = true; 11673 11674 var zoomFactor = Math.min(screen.width / t.width, screen.height / t.height), 11675 captionText = t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'captions-text'); 11676 if (captionText) { 11677 captionText.style.fontSize = zoomFactor * 100 + '%'; 11678 captionText.style.lineHeight = 'normal'; 11679 t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'captions-position').style.bottom = (screen.height - t.normalHeight) / 2 - t.getElement(t.controls).offsetHeight / 2 + zoomFactor + 15 + 'px'; 11680 } 11681 var event = (0, _general.createEvent)('enteredfullscreen', t.getElement(t.container)); 11682 t.getElement(t.container).dispatchEvent(event); 11683 }, 11684 exitFullScreen: function exitFullScreen() { 11685 var t = this, 11686 isNative = t.media.rendererName !== null && /(native|html5)/i.test(t.media.rendererName); 11687 11688 if (!t.isVideo) { 11689 return; 11690 } 11691 11692 clearTimeout(t.containerSizeTimeout); 11693 11694 if (Features.HAS_TRUE_NATIVE_FULLSCREEN && (Features.IS_FULLSCREEN || t.isFullScreen)) { 11695 Features.cancelFullScreen(); 11696 } 11697 11698 (0, _dom.removeClass)(_document2.default.documentElement, t.options.classPrefix + 'fullscreen'); 11699 (0, _dom.removeClass)(t.getElement(t.container), t.options.classPrefix + 'container-fullscreen'); 11700 11701 if (t.options.setDimensions) { 11702 t.getElement(t.container).style.width = t.normalWidth + 'px'; 11703 t.getElement(t.container).style.height = t.normalHeight + 'px'; 11704 11705 if (isNative) { 11706 t.node.style.width = t.normalWidth + 'px'; 11707 t.node.style.height = t.normalHeight + 'px'; 11708 } else { 11709 var elements = t.getElement(t.container).querySelectorAll('embed, object, video'), 11710 _total2 = elements.length; 11711 for (var i = 0; i < _total2; i++) { 11712 elements[i].style.width = t.normalWidth + 'px'; 11713 elements[i].style.height = t.normalHeight + 'px'; 11714 } 11715 } 11716 11717 if (typeof t.media.setSize === 'function') { 11718 t.media.setSize(t.normalWidth, t.normalHeight); 11719 } 11720 11721 var layers = t.getElement(t.layers).children, 11722 total = layers.length; 11723 for (var _i2 = 0; _i2 < total; _i2++) { 11724 layers[_i2].style.width = t.normalWidth + 'px'; 11725 layers[_i2].style.height = t.normalHeight + 'px'; 11726 } 11727 } 11728 11729 if (t.fullscreenBtn) { 11730 (0, _dom.removeClass)(t.fullscreenBtn, t.options.classPrefix + 'unfullscreen'); 11731 (0, _dom.addClass)(t.fullscreenBtn, t.options.classPrefix + 'fullscreen'); 11732 } 11733 11734 t.setControlsSize(); 11735 t.isFullScreen = false; 11736 11737 var captionText = t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'captions-text'); 11738 if (captionText) { 11739 captionText.style.fontSize = ''; 11740 captionText.style.lineHeight = ''; 11741 t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'captions-position').style.bottom = ''; 11742 } 11743 var event = (0, _general.createEvent)('exitedfullscreen', t.getElement(t.container)); 11744 t.getElement(t.container).dispatchEvent(event); 11745 } 11746}); 11747 11748},{"17":17,"2":2,"24":24,"25":25,"26":26,"27":27,"28":28,"3":3
vendor: 91,660 bytes, lines 11748-14468
11748,"6":6}],11:[function(_dereq_,module,exports){ 11749'use strict'; 11750 11751var _document = _dereq_(2); 11752 11753var _document2 = _interopRequireDefault(_document); 11754 11755var _player = _dereq_(17); 11756 11757var _player2 = _interopRequireDefault(_player); 11758 11759var _i18n = _dereq_(6); 11760 11761var _i18n2 = _interopRequireDefault(_i18n); 11762 11763var _general = _dereq_(26); 11764 11765var _dom = _dereq_(25); 11766 11767var _generate = _dereq_(27); 11768 11769function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 11770 11771Object.assign(_player.config, { 11772 playText: null, 11773 11774 pauseText: null 11775}); 11776 11777Object.assign(_player2.default.prototype, { 11778 buildplaypause: function buildplaypause(player, controls, layers, media) { 11779 var t = this, 11780 op = t.options, 11781 playTitle = (0, _general.isString)(op.playText) ? op.playText : _i18n2.default.t('mejs.play'), 11782 pauseTitle = (0, _general.isString)(op.pauseText) ? op.pauseText : _i18n2.default.t('mejs.pause'), 11783 play = _document2.default.createElement('div'); 11784 11785 play.className = t.options.classPrefix + 'button ' + t.options.classPrefix + 'playpause-button ' + t.options.classPrefix + 'play'; 11786 play.innerHTML = (0, _generate.generateControlButton)(t.id, pauseTitle, playTitle, '' + t.media.options.iconSprite, ['icon-play', 'icon-pause', 'icon-replay'], '' + t.options.classPrefix); 11787 play.addEventListener('click', function () { 11788 if (t.paused) { 11789 t.play(); 11790 } else { 11791 t.pause(); 11792 } 11793 }); 11794 11795 var playBtn = play.querySelector('button'); 11796 t.addControlElement(play, 'playpause'); 11797 11798 function togglePlayPause(which) { 11799 (0, _dom.removeClass)(play, t.options.classPrefix + 'play'); 11800 (0, _dom.removeClass)(play, t.options.classPrefix + 'replay'); 11801 (0, _dom.removeClass)(play, t.options.classPrefix + 'pause'); 11802 11803 if ('play' === which) { 11804 (0, _dom.addClass)(play, t.options.classPrefix + 'pause'); 11805 playBtn.setAttribute('title', pauseTitle); 11806 playBtn.setAttribute('aria-label', pauseTitle); 11807 } else if ('pse' === which) { 11808 (0, _dom.addClass)(play, t.options.classPrefix + 'play'); 11809 playBtn.setAttribute('title', playTitle); 11810 playBtn.setAttribute('aria-label', playTitle); 11811 } else { 11812 (0, _dom.addClass)(play, t.options.classPrefix + 'replay'); 11813 playBtn.setAttribute('title', playTitle); 11814 playBtn.setAttribute('aria-label', playTitle); 11815 } 11816 } 11817 11818 togglePlayPause('pse'); 11819 11820 media.addEventListener('loadedmetadata', function () { 11821 togglePlayPause('pse'); 11822 }); 11823 media.addEventListener('play', function () { 11824 togglePlayPause('play'); 11825 }); 11826 media.addEventListener('playing', function () { 11827 togglePlayPause('play'); 11828 }); 11829 media.addEventListener('pause', function () { 11830 togglePlayPause('pse'); 11831 }); 11832 media.addEventListener('ended', function () { 11833 if (!player.options.loop) { 11834 setTimeout(function () { 11835 togglePlayPause('replay'); 11836 }, 0); 11837 } 11838 }); 11839 } 11840}); 11841 11842},{"17":17,"2":2,"25":25,"26":26,"27":27,"6":6}],12:[function(_dereq_,module,exports){ 11843'use strict'; 11844 11845var _document = _dereq_(2); 11846 11847var _document2 = _interopRequireDefault(_document); 11848 11849var _player = _dereq_(17); 11850 11851var _player2 = _interopRequireDefault(_player); 11852 11853var _i18n = _dereq_(6); 11854 11855var _i18n2 = _interopRequireDefault(_i18n); 11856 11857var _constants = _dereq_(24); 11858 11859var _time = _dereq_(30); 11860 11861var _dom = _dereq_(25); 11862 11863function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 11864 11865Object.assign(_player.config, { 11866 enableProgressTooltip: true, 11867 11868 useSmoothHover: true, 11869 11870 forceLive: false 11871}); 11872 11873Object.assign(_player2.default.prototype, { 11874 buildprogress: function buildprogress(player, controls, layers, media) { 11875 11876 var lastKeyPressTime = 0, 11877 mouseIsDown = false, 11878 startedPaused = false; 11879 11880 var t = this, 11881 autoRewindInitial = player.options.autoRewind, 11882 tooltip = player.options.enableProgressTooltip ? '<span class="' + t.options.classPrefix + 'time-float">' + ('<span class="' + t.options.classPrefix + 'time-float-current">00:00</span>') + ('<span class="' + t.options.classPrefix + 'time-float-corner"></span>') + '</span>' : '', 11883 rail = _document2.default.createElement('div'); 11884 11885 rail.className = t.options.classPrefix + 'time-rail'; 11886 rail.innerHTML = '<span class="' + t.options.classPrefix + 'time-total ' + t.options.classPrefix + 'time-slider">' + ('<span class="' + t.options.classPrefix + 'time-buffering"></span>') + ('<span class="' + t.options.classPrefix + 'time-loaded"></span>') + ('<span class="' + t.options.classPrefix + 'time-current"></span>') + ('<span class="' + t.options.classPrefix + 'time-hovered no-hover"></span>') + ('<span class="' + t.options.classPrefix + 'time-handle"><span class="' + t.options.classPrefix + 'time-handle-content"></span></span>') + ('' + tooltip) + '</span>'; 11887 11888 t.addControlElement(rail, 'progress'); 11889 11890 t.options.keyActions.push({ 11891 keys: [37, 227], 11892 action: function action(player) { 11893 if (!isNaN(player.duration) && player.duration > 0) { 11894 if (player.isVideo) { 11895 player.showControls(); 11896 player.startControlsTimer(); 11897 } 11898 11899 var timeSlider = player.getElement(player.container).querySelector('.' + t.options.classPrefix + 'time-total'); 11900 if (timeSlider) { 11901 timeSlider.focus(); 11902 } 11903 11904 var newTime = Math.max(player.currentTime - player.options.defaultSeekBackwardInterval(player), 0); 11905 11906 if (!player.paused) { 11907 player.pause(); 11908 } 11909 11910 setTimeout(function () { 11911 player.setCurrentTime(newTime, true); 11912 }, 0); 11913 11914 setTimeout(function () { 11915 player.play(); 11916 }, 0); 11917 } 11918 } 11919 }, { 11920 keys: [39, 228], 11921 action: function action(player) { 11922 11923 if (!isNaN(player.duration) && player.duration > 0) { 11924 if (player.isVideo) { 11925 player.showControls(); 11926 player.startControlsTimer(); 11927 } 11928 11929 var timeSlider = player.getElement(player.container).querySelector('.' + t.options.classPrefix + 'time-total'); 11930 if (timeSlider) { 11931 timeSlider.focus(); 11932 } 11933 11934 var newTime = Math.min(player.currentTime + player.options.defaultSeekForwardInterval(player), player.duration); 11935 11936 if (!player.paused) { 11937 player.pause(); 11938 } 11939 11940 setTimeout(function () { 11941 player.setCurrentTime(newTime, true); 11942 }, 0); 11943 11944 setTimeout(function () { 11945 player.play(); 11946 }, 0); 11947 } 11948 } 11949 }); 11950 11951 t.rail = controls.querySelector('.' + t.options.classPrefix + 'time-rail'); 11952 t.total = controls.querySelector('.' + t.options.classPrefix + 'time-total'); 11953 t.loaded = controls.querySelector('.' + t.options.classPrefix + 'time-loaded'); 11954 t.current = controls.querySelector('.' + t.options.classPrefix + 'time-current'); 11955 t.handle = controls.querySelector('.' + t.options.classPrefix + 'time-handle'); 11956 t.timefloat = controls.querySelector('.' + t.options.classPrefix + 'time-float'); 11957 t.timefloatcurrent = controls.querySelector('.' + t.options.classPrefix + 'time-float-current'); 11958 t.slider = controls.querySelector('.' + t.options.classPrefix + 'time-slider'); 11959 t.hovered = controls.querySelector('.' + t.options.classPrefix + 'time-hovered'); 11960 t.buffer = controls.querySelector('.' + t.options.classPrefix + 'time-buffering'); 11961 t.newTime = 0; 11962 t.forcedHandlePause = false; 11963 t.setTransformStyle = function (element, value) { 11964 element.style.transform = value; 11965 element.style.webkitTransform = value; 11966 element.style.MozTransform = value; 11967 element.style.msTransform = value; 11968 element.style.OTransform = value; 11969 }; 11970 11971 t.buffer.style.display = 'none'; 11972 11973 var handleMouseMove = function handleMouseMove(e) { 11974 var totalStyles = getComputedStyle(t.total), 11975 offsetStyles = (0, _dom.offset)(t.total), 11976 width = t.total.offsetWidth, 11977 transform = function () { 11978 if (totalStyles.webkitTransform !== undefined) { 11979 return 'webkitTransform'; 11980 } else if (totalStyles.mozTransform !== undefined) { 11981 return 'mozTransform '; 11982 } else if (totalStyles.oTransform !== undefined) { 11983 return 'oTransform'; 11984 } else if (totalStyles.msTransform !== undefined) { 11985 return 'msTransform'; 11986 } else { 11987 return 'transform'; 11988 } 11989 }(), 11990 cssMatrix = function () { 11991 if ('WebKitCSSMatrix' in window) { 11992 return 'WebKitCSSMatrix'; 11993 } else if ('MSCSSMatrix' in window) { 11994 return 'MSCSSMatrix'; 11995 } else if ('CSSMatrix' in window) { 11996 return 'CSSMatrix'; 11997 } 11998 }(); 11999 12000 var percentage = 0, 12001 leftPos = 0, 12002 pos = 0, 12003 x = void 0; 12004 12005 if (e.originalEvent && e.originalEvent.changedTouches) { 12006 x = e.originalEvent.changedTouches[0].pageX; 12007 } else if (e.changedTouches) { 12008 x = e.changedTouches[0].pageX; 12009 } else { 12010 x = e.pageX; 12011 } 12012 12013 if (t.getDuration()) { 12014 if (x < offsetStyles.left) { 12015 x = offsetStyles.left; 12016 } else if (x > width + offsetStyles.left) { 12017 x = width + offsetStyles.left; 12018 } 12019 12020 pos = x - offsetStyles.left; 12021 percentage = pos / width; 12022 t.newTime = percentage * t.getDuration(); 12023 12024 if (mouseIsDown && t.getCurrentTime() !== null && t.newTime.toFixed(4) !== t.getCurrentTime().toFixed(4)) { 12025 t.setCurrentRailHandle(t.newTime); 12026 t.updateCurrent(t.newTime); 12027 } 12028 12029 if (!_constants.IS_IOS && !_constants.IS_ANDROID) { 12030 if (pos < 0) { 12031 pos = 0; 12032 } 12033 if (t.options.useSmoothHover && cssMatrix !== null && typeof window[cssMatrix] !== 'undefined') { 12034 var matrix = new window[cssMatrix](getComputedStyle(t.handle)[transform]), 12035 handleLocation = matrix.m41, 12036 hoverScaleX = pos / parseFloat(getComputedStyle(t.total).width) - handleLocation / parseFloat(getComputedStyle(t.total).width); 12037 12038 t.hovered.style.left = handleLocation + 'px'; 12039 t.setTransformStyle(t.hovered, 'scaleX(' + hoverScaleX + ')'); 12040 t.hovered.setAttribute('pos', pos); 12041 12042 if (hoverScaleX >= 0) { 12043 (0, _dom.removeClass)(t.hovered, 'negative'); 12044 } else { 12045 (0, _dom.addClass)(t.hovered, 'negative'); 12046 } 12047 } 12048 12049 if (t.timefloat) { 12050 var half = t.timefloat.offsetWidth / 2, 12051 offsetContainer = mejs.Utils.offset(t.getElement(t.container)), 12052 tooltipStyles = getComputedStyle(t.timefloat); 12053 12054 if (x - offsetContainer.left < t.timefloat.offsetWidth) { 12055 leftPos = half; 12056 } else if (x - offsetContainer.left >= t.getElement(t.container).offsetWidth - half) { 12057 leftPos = t.total.offsetWidth - half; 12058 } else { 12059 leftPos = pos; 12060 } 12061 12062 if ((0, _dom.hasClass)(t.getElement(t.container), t.options.classPrefix + 'long-video')) { 12063 leftPos += parseFloat(tooltipStyles.marginLeft) / 2 + t.timefloat.offsetWidth / 2; 12064 } 12065 12066 t.timefloat.style.left = leftPos + 'px'; 12067 t.timefloatcurrent.innerHTML = (0, _time.secondsToTimeCode)(t.newTime, player.options.alwaysShowHours, player.options.showTimecodeFrameCount, player.options.framesPerSecond, player.options.secondsDecimalLength, player.options.timeFormat); 12068 t.timefloat.style.display = 'block'; 12069 } 12070 } 12071 } else if (!_constants.IS_IOS && !_constants.IS_ANDROID && t.timefloat) { 12072 leftPos = t.timefloat.offsetWidth + width >= t.getElement(t.container).offsetWidth ? t.timefloat.offsetWidth / 2 : 0; 12073 t.timefloat.style.left = leftPos + 'px'; 12074 t.timefloat.style.left = leftPos + 'px'; 12075 t.timefloat.style.display = 'block'; 12076 } 12077 }, 12078 updateSlider = function updateSlider() { 12079 var seconds = t.getCurrentTime(), 12080 timeSliderText = _i18n2.default.t('mejs.time-slider'), 12081 time = (0, _time.secondsToTimeCode)(seconds, player.options.alwaysShowHours, player.options.showTimecodeFrameCount, player.options.framesPerSecond, player.options.secondsDecimalLength, player.options.timeFormat), 12082 duration = t.getDuration(); 12083 12084 t.slider.setAttribute('role', 'slider'); 12085 t.slider.tabIndex = 0; 12086 12087 if (media.paused) { 12088 t.slider.setAttribute('aria-label', timeSliderText); 12089 t.slider.setAttribute('aria-valuemin', 0); 12090 t.slider.setAttribute('aria-valuemax', isNaN(duration) ? 0 : duration); 12091 t.slider.setAttribute('aria-valuenow', seconds); 12092 t.slider.setAttribute('aria-valuetext', time); 12093 } else { 12094 t.slider.removeAttribute('aria-label'); 12095 t.slider.removeAttribute('aria-valuemin'); 12096 t.slider.removeAttribute('aria-valuemax'); 12097 t.slider.removeAttribute('aria-valuenow'); 12098 t.slider.removeAttribute('aria-valuetext'); 12099 } 12100 }, 12101 restartPlayer = function restartPlayer() { 12102 if (new Date() - lastKeyPressTime >= 1000) { 12103 t.play(); 12104 } 12105 }, 12106 handleMouseup = function handleMouseup() { 12107 if (mouseIsDown && t.getCurrentTime() !== null && t.newTime.toFixed(4) !== t.getCurrentTime().toFixed(4)) { 12108 t.setCurrentTime(t.newTime, true); 12109 t.setCurrentRailHandle(t.newTime); 12110 t.updateCurrent(t.newTime); 12111 } 12112 if (t.forcedHandlePause) { 12113 t.slider.focus(); 12114 t.play(); 12115 } 12116 t.forcedHandlePause = false; 12117 }; 12118 12119 t.slider.addEventListener('focus', function () { 12120 player.options.autoRewind = false; 12121 }); 12122 t.slider.addEventListener('blur', function () { 12123 player.options.autoRewind = autoRewindInitial; 12124 }); 12125 t.slider.addEventListener('keydown', function (e) { 12126 if (new Date() - lastKeyPressTime >= 1000) { 12127 startedPaused = t.paused; 12128 } 12129 12130 if (t.options.enableKeyboard && t.options.keyActions.length) { 12131 12132 var keyCode = e.which || e.keyCode || 0, 12133 duration = t.getDuration(), 12134 seekForward = player.options.defaultSeekForwardInterval(media), 12135 seekBackward = player.options.defaultSeekBackwardInterval(media); 12136 12137 var seekTime = t.getCurrentTime(); 12138 var volume = t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'volume-slider'); 12139 12140 if (keyCode === 38 || keyCode === 40) { 12141 if (volume) { 12142 volume.style.display = 'block'; 12143 } 12144 if (t.isVideo) { 12145 t.showControls(); 12146 t.startControlsTimer(); 12147 } 12148 12149 var newVolume = keyCode === 38 ? Math.min(t.volume + 0.1, 1) : Math.max(t.volume - 0.1, 0), 12150 mutePlayer = newVolume <= 0; 12151 t.setVolume(newVolume); 12152 t.setMuted(mutePlayer); 12153 return; 12154 } else { 12155 if (volume) { 12156 volume.style.display = 'none'; 12157 } 12158 } 12159 12160 switch (keyCode) { 12161 case 37: 12162 if (t.getDuration() !== Infinity) { 12163 seekTime -= seekBackward; 12164 } 12165 break; 12166 case 39: 12167 if (t.getDuration() !== Infinity) { 12168 seekTime += seekForward; 12169 } 12170 break; 12171 case 36: 12172 seekTime = 0; 12173 break; 12174 case 35: 12175 seekTime = duration; 12176 break; 12177 case 13: 12178 if (t.paused) { 12179 t.play(); 12180 } else { 12181 t.pause(); 12182 } 12183 return; 12184 default: 12185 return; 12186 } 12187 12188 seekTime = seekTime < 0 || isNaN(seekTime) ? 0 : seekTime >= duration ? duration : Math.floor(seekTime); 12189 lastKeyPressTime = new Date(); 12190 if (!startedPaused) { 12191 player.pause(); 12192 } 12193 12194 setTimeout(function () { 12195 t.setCurrentTime(seekTime, true); 12196 }, 0); 12197 12198 if (seekTime < t.getDuration() && !startedPaused) { 12199 setTimeout(restartPlayer, 1100); 12200 } 12201 12202 player.showControls(); 12203 12204 e.preventDefault(); 12205 e.stopPropagation(); 12206 } 12207 }); 12208 12209 var events = ['mousedown', 'touchstart']; 12210 12211 t.slider.addEventListener('dragstart', function () { 12212 return false; 12213 }); 12214 12215 for (var i = 0, total = events.length; i < total; i++) { 12216 t.slider.addEventListener(events[i], function (e) { 12217 t.forcedHandlePause = false; 12218 if (t.getDuration() !== Infinity) { 12219 if (e.which === 1 || e.which === 0) { 12220 if (!t.paused) { 12221 t.pause(); 12222 t.forcedHandlePause = true; 12223 } 12224 12225 mouseIsDown = true; 12226 handleMouseMove(e); 12227 var endEvents = ['mouseup', 'touchend']; 12228 12229 for (var j = 0, totalEvents = endEvents.length; j < totalEvents; j++) { 12230 t.getElement(t.container).addEventListener(endEvents[j], function (event) { 12231 var target = event.target; 12232 if (target === t.slider || target.closest('.' + t.options.classPrefix + 'time-slider')) { 12233 handleMouseMove(event); 12234 } 12235 }); 12236 } 12237 t.globalBind('mouseup.dur touchend.dur', function () { 12238 handleMouseup(); 12239 mouseIsDown = false; 12240 if (t.timefloat) { 12241 t.timefloat.style.display = 'none'; 12242 } 12243 }); 12244 } 12245 } 12246 }, _constants.SUPPORT_PASSIVE_EVENT && events[i] === 'touchstart' ? { passive: true } : false); 12247 } 12248 t.slider.addEventListener('mouseenter', function (e) { 12249 if (e.target === t.slider && t.getDuration() !== Infinity) { 12250 t.getElement(t.container).addEventListener('mousemove', function (event) { 12251 var target = event.target; 12252 if (target === t.slider || target.closest('.' + t.options.classPrefix + 'time-slider')) { 12253 handleMouseMove(event); 12254 } 12255 }); 12256 if (t.timefloat && !_constants.IS_IOS && !_constants.IS_ANDROID) { 12257 t.timefloat.style.display = 'block'; 12258 } 12259 if (t.hovered && !_constants.IS_IOS && !_constants.IS_ANDROID && t.options.useSmoothHover) { 12260 (0, _dom.removeClass)(t.hovered, 'no-hover'); 12261 } 12262 } 12263 }); 12264 t.slider.addEventListener('mouseleave', function () { 12265 if (t.getDuration() !== Infinity) { 12266 if (!mouseIsDown) { 12267 if (t.timefloat) { 12268 t.timefloat.style.display = 'none'; 12269 } 12270 if (t.hovered && t.options.useSmoothHover) { 12271 (0, _dom.addClass)(t.hovered, 'no-hover'); 12272 } 12273 } 12274 } 12275 }); 12276 12277 t.broadcastCallback = function (e) { 12278 var broadcast = controls.querySelector('.' + t.options.classPrefix + 'broadcast'); 12279 if (!t.options.forceLive && t.getDuration() !== Infinity) { 12280 if (broadcast) { 12281 t.slider.style.display = ''; 12282 broadcast.remove(); 12283 } 12284 12285 player.setProgressRail(e); 12286 if (!t.forcedHandlePause) { 12287 player.setCurrentRail(e); 12288 } 12289 updateSlider(); 12290 } else if (!broadcast && t.options.forceLive) { 12291 var label = _document2.default.createElement('span'); 12292 label.className = t.options.classPrefix + 'broadcast'; 12293 label.innerText = _i18n2.default.t('mejs.live-broadcast'); 12294 t.slider.style.display = 'none'; 12295 t.rail.appendChild(label); 12296 } 12297 }; 12298 12299 media.addEventListener('progress', t.broadcastCallback); 12300 media.addEventListener('timeupdate', t.broadcastCallback); 12301 media.addEventListener('play', function () { 12302 t.buffer.style.display = 'none'; 12303 }); 12304 media.addEventListener('playing', function () { 12305 t.buffer.style.display = 'none'; 12306 }); 12307 media.addEventListener('seeking', function () { 12308 t.buffer.style.display = ''; 12309 }); 12310 media.addEventListener('seeked', function () { 12311 t.buffer.style.display = 'none'; 12312 }); 12313 media.addEventListener('pause', function () { 12314 t.buffer.style.display = 'none'; 12315 }); 12316 media.addEventListener('waiting', function () { 12317 t.buffer.style.display = ''; 12318 }); 12319 media.addEventListener('loadeddata', function () { 12320 t.buffer.style.display = ''; 12321 }); 12322 media.addEventListener('canplay', function () { 12323 t.buffer.style.display = 'none'; 12324 }); 12325 media.addEventListener('error', function () { 12326 t.buffer.style.display = 'none'; 12327 }); 12328 12329 t.getElement(t.container).addEventListener('controlsresize', function (e) { 12330 if (t.getDuration() !== Infinity) { 12331 player.setProgressRail(e); 12332 if (!t.forcedHandlePause) { 12333 player.setCurrentRail(e); 12334 } 12335 } 12336 }); 12337 }, 12338 cleanprogress: function cleanprogress(player, controls, layers, media) { 12339 media.removeEventListener('progress', player.broadcastCallback); 12340 media.removeEventListener('timeupdate', player.broadcastCallback); 12341 if (player.rail) { 12342 player.rail.remove(); 12343 } 12344 }, 12345 setProgressRail: function setProgressRail(e) { 12346 var t = this, 12347 target = e !== undefined ? e.detail.target || e.target : t.media; 12348 12349 var percent = null; 12350 12351 if (target && target.buffered && target.buffered.length > 0 && target.buffered.end && t.getDuration()) { 12352 percent = target.buffered.end(target.buffered.length - 1) / t.getDuration(); 12353 } else if (target && target.bytesTotal !== undefined && target.bytesTotal > 0 && target.bufferedBytes !== undefined) { 12354 percent = target.bufferedBytes / target.bytesTotal; 12355 } else if (e && e.lengthComputable && e.total !== 0) { 12356 percent = e.loaded / e.total; 12357 } 12358 12359 if (percent !== null) { 12360 percent = Math.min(1, Math.max(0, percent)); 12361 12362 if (t.loaded) { 12363 t.setTransformStyle(t.loaded, 'scaleX(' + percent + ')'); 12364 } 12365 } 12366 }, 12367 setCurrentRailHandle: function setCurrentRailHandle(fakeTime) { 12368 var t = this; 12369 t.setCurrentRailMain(t, fakeTime); 12370 }, 12371 setCurrentRail: function setCurrentRail() { 12372 var t = this; 12373 t.setCurrentRailMain(t); 12374 }, 12375 setCurrentRailMain: function setCurrentRailMain(t, fakeTime) { 12376 if (t.getCurrentTime() !== undefined && t.getDuration()) { 12377 var nTime = typeof fakeTime === 'undefined' ? t.getCurrentTime() : fakeTime; 12378 12379 if (t.total && t.handle) { 12380 var tW = parseFloat(getComputedStyle(t.total).width); 12381 12382 var newWidth = Math.round(tW * nTime / t.getDuration()), 12383 handlePos = newWidth - Math.round(t.handle.offsetWidth / 2); 12384 12385 handlePos = handlePos < 0 ? 0 : handlePos; 12386 t.setTransformStyle(t.current, 'scaleX(' + newWidth / tW + ')'); 12387 t.setTransformStyle(t.handle, 'translateX(' + handlePos + 'px)'); 12388 12389 if (t.options.useSmoothHover && !(0, _dom.hasClass)(t.hovered, 'no-hover')) { 12390 var pos = parseInt(t.hovered.getAttribute('pos'), 10); 12391 pos = isNaN(pos) ? 0 : pos; 12392 12393 var hoverScaleX = pos / tW - handlePos / tW; 12394 12395 t.hovered.style.left = handlePos + 'px'; 12396 t.setTransformStyle(t.hovered, 'scaleX(' + hoverScaleX + ')'); 12397 12398 if (hoverScaleX >= 0) { 12399 (0, _dom.removeClass)(t.hovered, 'negative'); 12400 } else { 12401 (0, _dom.addClass)(t.hovered, 'negative'); 12402 } 12403 } 12404 } 12405 } 12406 } 12407}); 12408 12409},{"17":17,"2":2,"24":24,"25":25,"30":30,"6":6}],13:[function(_dereq_,module,exports){ 12410'use strict'; 12411 12412var _document = _dereq_(2); 12413 12414var _document2 = _interopRequireDefault(_document); 12415 12416var _player = _dereq_(17); 12417 12418var _player2 = _interopRequireDefault(_player); 12419 12420var _i18n = _dereq_(6); 12421 12422var _i18n2 = _interopRequireDefault(_i18n); 12423 12424var _time = _dereq_(30); 12425 12426var _dom = _dereq_(25); 12427 12428function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 12429 12430Object.assign(_player.config, { 12431 duration: 0, 12432 12433 timeAndDurationSeparator: '<span> | </span>' 12434}); 12435 12436Object.assign(_player2.default.prototype, { 12437 buildcurrent: function buildcurrent(player, controls, layers, media) { 12438 var t = this, 12439 time = _document2.default.createElement('div'); 12440 12441 time.className = t.options.classPrefix + 'time'; 12442 time.setAttribute('role', 'timer'); 12443 time.setAttribute('aria-live', 'off'); 12444 time.innerHTML = '<span class="mejs__offscreen">' + _i18n2.default.t('mejs.current') + '</span><span class="' + t.options.classPrefix + 'currenttime">' + (0, _time.secondsToTimeCode)(0, player.options.alwaysShowHours, player.options.showTimecodeFrameCount, player.options.framesPerSecond, player.options.secondsDecimalLength, player.options.timeFormat) + '</span>'; 12445 12446 t.addControlElement(time, 'current'); 12447 player.updateCurrent(); 12448 t.updateTimeCallback = function () { 12449 if (t.controlsAreVisible) { 12450 player.updateCurrent(); 12451 } 12452 }; 12453 media.addEventListener('timeupdate', t.updateTimeCallback); 12454 }, 12455 cleancurrent: function cleancurrent(player, controls, layers, media) { 12456 media.removeEventListener('timeupdate', player.updateTimeCallback); 12457 }, 12458 buildduration: function buildduration(player, controls, layers, media) { 12459 var t = this, 12460 currTime = controls.lastChild.querySelector('.' + t.options.classPrefix + 'currenttime'); 12461 12462 if (currTime) { 12463 controls.querySelector('.' + t.options.classPrefix + 'time').innerHTML += t.options.timeAndDurationSeparator + '<span class="mejs__offscreen">' + _i18n2.default.t('mejs.duration') + '</span><span class="' + t.options.classPrefix + 'duration">' + ((0, _time.secondsToTimeCode)(t.options.duration, t.options.alwaysShowHours, t.options.showTimecodeFrameCount, t.options.framesPerSecond, t.options.secondsDecimalLength, t.options.timeFormat) + '</span>'); 12464 } else { 12465 if (controls.querySelector('.' + t.options.classPrefix + 'currenttime')) { 12466 (0, _dom.addClass)(controls.querySelector('.' + t.options.classPrefix + 'currenttime').parentNode, t.options.classPrefix + 'currenttime-container'); 12467 } 12468 12469 var duration = _document2.default.createElement('div'); 12470 duration.className = t.options.classPrefix + 'time ' + t.options.classPrefix + 'duration-container'; 12471 duration.innerHTML = '<span class="mejs__offscreen">' + _i18n2.default.t('mejs.duration') + '</span><span class="' + t.options.classPrefix + 'duration">' + ((0, _time.secondsToTimeCode)(t.options.duration, t.options.alwaysShowHours, t.options.showTimecodeFrameCount, t.options.framesPerSecond, t.options.secondsDecimalLength, t.options.timeFormat) + '</span>'); 12472 12473 t.addControlElement(duration, 'duration'); 12474 } 12475 12476 t.updateDurationCallback = function () { 12477 if (t.controlsAreVisible) { 12478 player.updateDuration(); 12479 } 12480 }; 12481 12482 media.addEventListener('timeupdate', t.updateDurationCallback); 12483 }, 12484 cleanduration: function cleanduration(player, controls, layers, media) { 12485 media.removeEventListener('timeupdate', player.updateDurationCallback); 12486 }, 12487 updateCurrent: function updateCurrent() { 12488 var t = this; 12489 12490 var currentTime = t.getCurrentTime(); 12491 12492 if (isNaN(currentTime)) { 12493 currentTime = 0; 12494 } 12495 12496 var timecode = (0, _time.secondsToTimeCode)(currentTime, t.options.alwaysShowHours, t.options.showTimecodeFrameCount, t.options.framesPerSecond, t.options.secondsDecimalLength, t.options.timeFormat); 12497 12498 if (timecode.length > 5) { 12499 (0, _dom.addClass)(t.getElement(t.container), t.options.classPrefix + 'long-video'); 12500 } else { 12501 (0, _dom.removeClass)(t.getElement(t.container), t.options.classPrefix + 'long-video'); 12502 } 12503 12504 if (t.getElement(t.controls).querySelector('.' + t.options.classPrefix + 'currenttime')) { 12505 t.getElement(t.controls).querySelector('.' + t.options.classPrefix + 'currenttime').innerText = timecode; 12506 } 12507 }, 12508 updateDuration: function updateDuration() { 12509 var t = this; 12510 12511 var duration = t.getDuration(); 12512 12513 if (t.media !== undefined && (isNaN(duration) || duration === Infinity || duration < 0)) { 12514 t.media.duration = t.options.duration = duration = 0; 12515 } 12516 12517 if (t.options.duration > 0) { 12518 duration = t.options.duration; 12519 } 12520 12521 var timecode = (0, _time.secondsToTimeCode)(duration, t.options.alwaysShowHours, t.options.showTimecodeFrameCount, t.options.framesPerSecond, t.options.secondsDecimalLength, t.options.timeFormat); 12522 12523 if (timecode.length > 5) { 12524 (0, _dom.addClass)(t.getElement(t.container), t.options.classPrefix + 'long-video'); 12525 } else { 12526 (0, _dom.removeClass)(t.getElement(t.container), t.options.classPrefix + 'long-video'); 12527 } 12528 12529 if (t.getElement(t.controls).querySelector('.' + t.options.classPrefix + 'duration') && duration > 0) { 12530 t.getElement(t.controls).querySelector('.' + t.options.classPrefix + 'duration').innerHTML = timecode; 12531 } 12532 } 12533}); 12534 12535},{"17":17,"2":2,"25":25,"30":30,"6":6}],14:[function(_dereq_,module,exports){ 12536'use strict'; 12537 12538var _document = _dereq_(2); 12539 12540var _document2 = _interopRequireDefault(_document); 12541 12542var _mejs = _dereq_(8); 12543 12544var _mejs2 = _interopRequireDefault(_mejs); 12545 12546var _i18n = _dereq_(6); 12547 12548var _i18n2 = _interopRequireDefault(_i18n); 12549 12550var _player = _dereq_(17); 12551 12552var _player2 = _interopRequireDefault(_player); 12553 12554var _general = _dereq_(26); 12555 12556var _dom = _dereq_(25); 12557 12558var _generate = _dereq_(27); 12559 12560function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 12561 12562Object.assign(_player.config, { 12563 autoplayCaptionLanguage: null, 12564 12565 defaultTrackLine: -3, 12566 12567 tracksText: null, 12568 12569 chaptersText: null, 12570 12571 chaptersLanguage: null, 12572 12573 hideCaptionsButtonWhenEmpty: true, 12574 12575 toggleCaptionsButtonWhenOnlyOne: false 12576}); 12577 12578Object.assign(_player2.default.prototype, { 12579 hasChapters: false, 12580 12581 buildtracks: function buildtracks(player, controls) { 12582 this.initTracks(player); 12583 12584 if (!player.tracks.length && (!player.trackFiles || !(player.trackFiles.length === 0))) { 12585 return; 12586 } 12587 12588 var t = this, 12589 tracksTitle = (0, _general.isString)(t.options.tracksText) ? t.options.tracksText : _i18n2.default.t('mejs.captions-subtitles'), 12590 chaptersTitle = (0, _general.isString)(t.options.chaptersText) ? t.options.chaptersText : _i18n2.default.t('mejs.captions-chapters'); 12591 12592 t.hideAllTracks(); 12593 12594 t.clearTrackHtml(player); 12595 12596 player.captionsButton = _document2.default.createElement('div'); 12597 player.captionsButton.className = t.options.classPrefix + 'button ' + t.options.classPrefix + 'captions-button'; 12598 player.captionsButton.innerHTML = (0, _generate.generateControlButton)(t.id, tracksTitle, tracksTitle, '' + t.media.options.iconSprite, ['icon-captions'], '' + t.options.classPrefix) + ('<div class="' + t.options.classPrefix + 'captions-selector ' + t.options.classPrefix + 'offscreen">') + ('<ul class="' + t.options.classPrefix + 'captions-selector-list">') + ('<li class="' + t.options.classPrefix + 'captions-selector-list-item">') + ('<input type="radio" class="' + t.options.classPrefix + 'captions-selector-input" ') + ('name="' + player.id + '_captions" id="' + player.id + '_captions_none" ') + 'value="none" checked disabled>' + ('<label class="' + t.options.classPrefix + 'captions-selector-label ') + (t.options.classPrefix + 'captions-selected" ') + ('for="' + player.id + '_captions_none">' + _i18n2.default.t('mejs.none') + '</label>') + '</li>' + '</ul>' + '</div>'; 12599 12600 t.addControlElement(player.captionsButton, 'tracks'); 12601 12602 player.captionsButton.querySelector('.' + t.options.classPrefix + 'captions-selector-input').disabled = false; 12603 12604 player.chaptersButton = _document2.default.createElement('div'); 12605 player.chaptersButton.className = t.options.classPrefix + 'button ' + t.options.classPrefix + 'chapters-button'; 12606 player.chaptersButton.innerHTML = (0, _generate.generateControlButton)(t.id, chaptersTitle, chaptersTitle, '' + t.media.options.iconSprite, ['icon-chapters'], '' + t.options.classPrefix) + ('<div class="' + t.options.classPrefix + 'chapters-selector ' + t.options.classPrefix + 'offscreen">') + ('<ul class="' + t.options.classPrefix + 'chapters-selector-list"></ul>') + '</div>'; 12607 12608 var subtitles = t.getSubtitles(); 12609 var chapters = t.getChapters(); 12610 12611 if (chapters.length > 0 && !controls.querySelector('.' + t.options.classPrefix + 'chapter-selector')) { 12612 player.captionsButton.parentNode.insertBefore(player.chaptersButton, player.captionsButton); 12613 } 12614 12615 for (var i = 0; i < subtitles.length; i++) { 12616 player.addTrackButton(subtitles[i]); 12617 if (subtitles[i].isLoaded) { 12618 t.enableTrackButton(subtitles[i]); 12619 } 12620 } 12621 12622 player.trackToLoad = -1; 12623 player.selectedTrack = null; 12624 player.isLoadingTrack = false; 12625 12626 var inEvents = ['mouseenter', 'focusin'], 12627 outEvents = ['mouseleave', 'focusout']; 12628 12629 if (t.options.toggleCaptionsButtonWhenOnlyOne && subtitles.length === 1) { 12630 player.captionsButton.classList.add(t.options.classPrefix + 'captions-button-toggle'); 12631 player.captionsButton.addEventListener('click', function () { 12632 var trackId = 'none'; 12633 if (player.selectedTrack === null) { 12634 trackId = player.getSubtitles()[0].trackId; 12635 } 12636 player.setTrack(trackId); 12637 }); 12638 } else { 12639 var labels = player.captionsButton.querySelectorAll('.' + t.options.classPrefix + 'captions-selector-label'), 12640 captions = player.captionsButton.querySelectorAll('input[type=radio]'); 12641 12642 for (var _i = 0; _i < inEvents.length; _i++) { 12643 player.captionsButton.addEventListener(inEvents[_i], function () { 12644 (0, _dom.removeClass)(this.querySelector('.' + t.options.classPrefix + 'captions-selector'), t.options.classPrefix + 'offscreen'); 12645 }); 12646 } 12647 12648 for (var _i2 = 0; _i2 < outEvents.length; _i2++) { 12649 player.captionsButton.addEventListener(outEvents[_i2], function () { 12650 var _this = this; 12651 12652 setTimeout(function () { 12653 (0, _dom.addClass)(_this.querySelector('.' + t.options.classPrefix + 'captions-selector'), t.options.classPrefix + 'offscreen'); 12654 }, 0); 12655 }); 12656 } 12657 12658 for (var _i3 = 0; _i3 < captions.length; _i3++) { 12659 captions[_i3].addEventListener('click', function (e) { 12660 if (!e.target.disabled) { 12661 player.setTrack(this.value); 12662 } 12663 }); 12664 } 12665 12666 for (var _i4 = 0; _i4 < labels.length; _i4++) { 12667 labels[_i4].addEventListener('click', function (e) { 12668 var radio = (0, _dom.siblings)(this, function (el) { 12669 return el.tagName === 'INPUT'; 12670 })[0], 12671 event = (0, _general.createEvent)('click', radio); 12672 radio.dispatchEvent(event); 12673 e.preventDefault(); 12674 }); 12675 } 12676 12677 player.captionsButton.addEventListener('keydown', function (e) { 12678 e.stopPropagation(); 12679 }); 12680 } 12681 12682 for (var _i5 = 0; _i5 < inEvents.length; _i5++) { 12683 player.chaptersButton.addEventListener(inEvents[_i5], function () { 12684 if (this.querySelector('.' + t.options.classPrefix + 'chapters-selector-list').children.length) { 12685 (0, _dom.removeClass)(this.querySelector('.' + t.options.classPrefix + 'chapters-selector'), t.options.classPrefix + 'offscreen'); 12686 } 12687 }); 12688 } 12689 12690 for (var _i6 = 0; _i6 < outEvents.length; _i6++) { 12691 player.chaptersButton.addEventListener(outEvents[_i6], function () { 12692 var _this2 = this; 12693 12694 setTimeout(function () { 12695 (0, _dom.addClass)(_this2.querySelector('.' + t.options.classPrefix + 'chapters-selector'), t.options.classPrefix + 'offscreen'); 12696 }, 0); 12697 }); 12698 } 12699 12700 player.chaptersButton.addEventListener('keydown', function (e) { 12701 e.stopPropagation(); 12702 }); 12703 12704 t.checkAllCaptionsLoadedOrError(); 12705 t.checkAllChaptersLoadedOrError(); 12706 }, 12707 clearTrackHtml: function clearTrackHtml(player) { 12708 if (player) { 12709 if (player.captionsButton) { 12710 player.captionsButton.remove(); 12711 } 12712 if (player.chaptersButton) { 12713 player.chaptersButton.remove(); 12714 } 12715 } 12716 }, 12717 initTracks: function initTracks(player) { 12718 var t = this, 12719 trackFiles = t.trackFiles === null ? t.node.querySelectorAll('track') : t.trackFiles; 12720 12721 t.tracks = []; 12722 12723 if (trackFiles) { 12724 player.trackFiles = trackFiles; 12725 for (var i = 0; i < trackFiles.length; i++) { 12726 var track = trackFiles[i], 12727 srclang = track.getAttribute('srclang').toLowerCase() || '', 12728 trackId = track.getAttribute('id') || t.id + '_track_' + i + '_' + track.getAttribute('kind') + '_' + srclang; 12729 track.setAttribute('id', trackId); 12730 12731 var trackData = { 12732 trackId: trackId, 12733 srclang: srclang, 12734 src: track.getAttribute('src'), 12735 kind: track.getAttribute('kind'), 12736 label: track.getAttribute('label') || '', 12737 entries: [], 12738 isDefault: track.hasAttribute('default'), 12739 isError: false, 12740 isLoaded: false 12741 }; 12742 t.tracks.push(trackData); 12743 12744 if (track.getAttribute('kind') === 'captions' || track.getAttribute('kind') === 'subtitles') { 12745 switch (track.readyState) { 12746 case 2: 12747 t.handleCaptionsLoaded(track); 12748 break; 12749 case 3: 12750 t.handleCaptionsError(track); 12751 break; 12752 default: 12753 track.addEventListener('load', function (event) { 12754 t.handleCaptionsLoaded(event.target); 12755 }); 12756 track.addEventListener('error', function (event) { 12757 t.handleCaptionsError(event.target); 12758 }); 12759 break; 12760 } 12761 } else if (track.getAttribute('kind') === 'chapters') { 12762 switch (track.readyState) { 12763 case 2: 12764 t.handleChaptersLoaded(track); 12765 break; 12766 case 3: 12767 t.handleChaptersError(track); 12768 break; 12769 default: 12770 track.addEventListener('load', function (event) { 12771 t.handleChaptersLoaded(event.target); 12772 }); 12773 track.addEventListener('error', function (event) { 12774 t.handleChaptersError(event.target); 12775 }); 12776 break; 12777 } 12778 } 12779 } 12780 } 12781 }, 12782 handleCaptionsLoaded: function handleCaptionsLoaded(target) { 12783 var textTracks = this.node.textTracks, 12784 playerTrack = this.getTrackById(target.getAttribute('id')); 12785 12786 if (Number.isInteger(this.options.defaultTrackLine)) { 12787 for (var i = 0; i < textTracks.length; i++) { 12788 if (target.getAttribute('srclang') === textTracks[i].language && target.getAttribute('kind') === textTracks[i].kind) { 12789 var cues = textTracks[i].cues; 12790 for (var c = 0; c < cues.length; c++) { 12791 if (cues[c].line === 'auto' || cues[c].line === undefined || cues[c].line === null) { 12792 cues[c].line = this.options.defaultTrackLine; 12793 } 12794 } 12795 break; 12796 } 12797 } 12798 } 12799 12800 playerTrack.isLoaded = true; 12801 this.enableTrackButton(playerTrack); 12802 this.checkAllCaptionsLoadedOrError(); 12803 }, 12804 handleCaptionsError: function handleCaptionsError(target) { 12805 var playerTrack = this.getTrackById(target.getAttribute('id')); 12806 12807 playerTrack.isError = true; 12808 this.removeTrackButton(playerTrack); 12809 this.checkAllCaptionsLoadedOrError(); 12810 }, 12811 handleChaptersLoaded: function handleChaptersLoaded(target) { 12812 var playerTrack = this.getTrackById(target.getAttribute('id')); 12813 12814 this.hasChapters = true; 12815 playerTrack.isLoaded = true; 12816 this.checkAllChaptersLoadedOrError(); 12817 }, 12818 handleChaptersError: function handleChaptersError(target) { 12819 var playerTrack = this.getTrackById(target.getAttribute('id')); 12820 playerTrack.isError = true; 12821 this.checkAllChaptersLoadedOrError(); 12822 }, 12823 checkAllCaptionsLoadedOrError: function checkAllCaptionsLoadedOrError() { 12824 var subtitles = this.getSubtitles(); 12825 if (subtitles.length === subtitles.filter(function (_ref) { 12826 var isLoaded = _ref.isLoaded, 12827 isError = _ref.isError; 12828 return isLoaded || isError; 12829 }).length) { 12830 this.removeCaptionsIfEmpty(); 12831 this.checkForAutoPlay(); 12832 } 12833 }, 12834 checkAllChaptersLoadedOrError: function checkAllChaptersLoadedOrError() { 12835 var _this3 = this; 12836 12837 var chapters = this.getChapters(), 12838 readyChapters = chapters.filter(function (_ref2) { 12839 var isLoaded = _ref2.isLoaded; 12840 return isLoaded; 12841 }); 12842 if (chapters.length === chapters.filter(function (_ref3) { 12843 var isLoaded = _ref3.isLoaded, 12844 isError = _ref3.isError; 12845 return isLoaded || isError; 12846 }).length) { 12847 if (readyChapters.length === 0) { 12848 this.chaptersButton.remove(); 12849 } else { 12850 var langChapter = readyChapters.find(function (_ref4) { 12851 var srclang = _ref4.srclang; 12852 return srclang === _this3.options.chaptersLanguage; 12853 }); 12854 12855 langChapter = langChapter || readyChapters.find(function (_ref5) { 12856 var srclang = _ref5.srclang; 12857 return srclang === _i18n2.default.lang; 12858 }); 12859 12860 if (readyChapters.length === 1 || !langChapter) { 12861 this.drawChapters(readyChapters[0].trackId); 12862 } else { 12863 this.drawChapters(langChapter.trackId); 12864 } 12865 } 12866 } 12867 }, 12868 setTrack: function setTrack(trackId) { 12869 var t = this, 12870 radios = t.captionsButton.querySelectorAll('input[type="radio"]'), 12871 captions = t.captionsButton.querySelectorAll('.' + t.options.classPrefix + 'captions-selected'), 12872 track = t.captionsButton.querySelector('input[value="' + trackId + '"]'); 12873 12874 for (var i = 0; i < radios.length; i++) { 12875 radios[i].checked = false; 12876 } 12877 12878 for (var _i7 = 0; _i7 < captions.length; _i7++) { 12879 (0, _dom.removeClass)(captions[_i7], t.options.classPrefix + 'captions-selected'); 12880 } 12881 12882 track.checked = true; 12883 var labels = (0, _dom.siblings)(track, function (el) { 12884 return (0, _dom.hasClass)(el, t.options.classPrefix + 'captions-selector-label'); 12885 }); 12886 for (var _i8 = 0; _i8 < labels.length; _i8++) { 12887 (0, _dom.addClass)(labels[_i8], t.options.classPrefix + 'captions-selected'); 12888 } 12889 12890 if (trackId === 'none') { 12891 t.selectedTrack = null; 12892 (0, _dom.removeClass)(t.captionsButton, t.options.classPrefix + 'captions-enabled'); 12893 t.deactivateVideoTracks(); 12894 } else { 12895 var _track = t.getTrackById(trackId); 12896 if (_track) { 12897 if (t.selectedTrack === null) { 12898 (0, _dom.addClass)(t.captionsButton, t.options.classPrefix + 'captions-enabled'); 12899 } 12900 t.selectedTrack = _track; 12901 t.activateVideoTrack(t.selectedTrack.srclang); 12902 } 12903 } 12904 12905 var event = (0, _general.createEvent)('captionschange', t.media); 12906 event.detail.caption = t.selectedTrack; 12907 t.media.dispatchEvent(event); 12908 }, 12909 hideAllTracks: function hideAllTracks() { 12910 if (this.node.textTracks) { 12911 for (var i = 0; i < this.node.textTracks.length; i++) { 12912 this.node.textTracks[i].mode = 'hidden'; 12913 } 12914 } 12915 }, 12916 deactivateVideoTracks: function deactivateVideoTracks() { 12917 if (this.node.textTracks) { 12918 for (var i = 0; i < this.node.textTracks.length; i++) { 12919 var track = this.node.textTracks[i]; 12920 if (track.kind === 'subtitles' || track.kind === 'captions') { 12921 track.mode = 'hidden'; 12922 } 12923 } 12924 } 12925 if (this.options.toggleCaptionsButtonWhenOnlyOne && this.getSubtitles().length === 1) { 12926 this.captionsButton.classList.remove(this.options.classPrefix + 'captions-button-toggle-on'); 12927 } 12928 }, 12929 activateVideoTrack: function activateVideoTrack(srclang) { 12930 for (var i = 0; i < this.node.textTracks.length; i++) { 12931 var track = this.node.textTracks[i]; 12932 12933 if (track.kind === 'subtitles' || track.kind === 'captions') { 12934 if (track.language === srclang) { 12935 track.mode = 'showing'; 12936 if (this.options.toggleCaptionsButtonWhenOnlyOne && this.getSubtitles().length === 1) { 12937 this.captionsButton.classList.add(this.options.classPrefix + 'captions-button-toggle-on'); 12938 } 12939 } else { 12940 track.mode = 'hidden'; 12941 } 12942 } 12943 } 12944 }, 12945 checkForAutoPlay: function checkForAutoPlay() { 12946 var _this4 = this; 12947 12948 var readySubtitles = this.getSubtitles().filter(function (_ref6) { 12949 var isError = _ref6.isError; 12950 return !isError; 12951 }), 12952 autoplayTrack = readySubtitles.find(function (_ref7) { 12953 var srclang = _ref7.srclang; 12954 return _this4.options.autoplayCaptionLanguage === srclang; 12955 }) || readySubtitles.find(function (_ref8) { 12956 var isDefault = _ref8.isDefault; 12957 return isDefault; 12958 }); 12959 12960 if (autoplayTrack) { 12961 if (this.options.toggleCaptionsButtonWhenOnlyOne && readySubtitles.length === 1 && this.captionsButton) { 12962 this.captionsButton.dispatchEvent((0, _general.createEvent)('click', this.captionsButton)); 12963 } else { 12964 var target = _document2.default.getElementById(autoplayTrack.trackId + '-btn'); 12965 if (target) { 12966 target.checked = true; 12967 target.dispatchEvent((0, _general.createEvent)('click', target)); 12968 } 12969 } 12970 } 12971 }, 12972 enableTrackButton: function enableTrackButton(track) { 12973 var t = this, 12974 lang = track.srclang, 12975 target = _document2.default.getElementById(track.trackId + '-btn'); 12976 if (!target) { 12977 return; 12978 } 12979 12980 var label = track.label; 12981 12982 if (label === '') { 12983 label = _i18n2.default.t(_mejs2.default.language.codes[lang]) || lang; 12984 } 12985 target.disabled = false; 12986 var targetSiblings = (0, _dom.siblings)(target, function (el) { 12987 return (0, _dom.hasClass)(el, t.options.classPrefix + 'captions-selector-label'); 12988 }); 12989 for (var i = 0; i < targetSiblings.length; i++) { 12990 targetSiblings[i].innerHTML = label; 12991 } 12992 }, 12993 removeTrackButton: function removeTrackButton(track) { 12994 var element = _document2.default.getElementById(track.trackId + '-btn'); 12995 if (element) { 12996 var button = element.closest('li'); 12997 if (button) { 12998 button.remove(); 12999 } 13000 } 13001 }, 13002 addTrackButton: function addTrackButton(track) { 13003 var t = this, 13004 label = track.label || _i18n2.default.t(_mejs2.default.language.codes[track.srclang]) || track.srclang; 13005 13006 t.captionsButton.querySelector('ul').innerHTML += '<li class="' + t.options.classPrefix + 'captions-selector-list-item">' + ('<input type="radio" class="' + t.options.classPrefix + 'captions-selector-input" ') + ('name="' + t.id + '_captions" id="' + track.trackId + '-btn" value="' + track.trackId + '" disabled>') + ('<label class="' + t.options.classPrefix + 'captions-selector-label"') + ('for="' + track.trackId + '">' + label + ' (loading)</label>') + '</li>'; 13007 }, 13008 removeCaptionsIfEmpty: function removeCaptionsIfEmpty() { 13009 if (this.captionsButton && this.options.hideCaptionsButtonWhenEmpty) { 13010 var subtitleCount = this.getSubtitles().filter(function (_ref9) { 13011 var isError = _ref9.isError; 13012 return !isError; 13013 }).length; 13014 this.captionsButton.style.display = subtitleCount > 0 ? '' : 'none'; 13015 this.setControlsSize(); 13016 } 13017 }, 13018 drawChapters: function drawChapters(chapterTrackId) { 13019 var t = this, 13020 chapter = this.node.textTracks.getTrackById(chapterTrackId), 13021 numberOfChapters = chapter.cues.length; 13022 13023 if (!numberOfChapters) { 13024 return; 13025 } 13026 13027 t.chaptersButton.querySelector('ul').innerHTML = ''; 13028 13029 for (var i = 0; i < numberOfChapters; i++) { 13030 t.chaptersButton.querySelector('ul').innerHTML += '<li class="' + t.options.classPrefix + 'chapters-selector-list-item" ' + 'role="menuitemcheckbox" aria-live="polite" aria-disabled="false" aria-checked="false">' + ('<input type="radio" class="' + t.options.classPrefix + 'captions-selector-input" ') + ('name="' + t.id + '_chapters" id="' + t.id + '_chapters_' + i + '" value="' + chapter.cues[i].startTime + '" disabled>') + ('<label class="' + t.options.classPrefix + 'chapters-selector-label"') + ('for="' + t.id + '_chapters_' + i + '">' + chapter.cues[i].text + '</label>') + '</li>'; 13031 } 13032 13033 var radios = t.chaptersButton.querySelectorAll('input[type="radio"]'), 13034 labels = t.chaptersButton.querySelectorAll('.' + t.options.classPrefix + 'chapters-selector-label'); 13035 13036 for (var _i9 = 0; _i9 < radios.length; _i9++) { 13037 radios[_i9].disabled = false; 13038 radios[_i9].checked = false; 13039 radios[_i9].addEventListener('click', function (e) { 13040 var self = this, 13041 listItems = t.chaptersButton.querySelectorAll('li'), 13042 label = (0, _dom.siblings)(self, function (el) { 13043 return (0, _dom.hasClass)(el, t.options.classPrefix + 'chapters-selector-label'); 13044 })[0]; 13045 13046 self.checked = true; 13047 self.parentNode.setAttribute('aria-checked', true); 13048 (0, _dom.addClass)(label, t.options.classPrefix + 'chapters-selected'); 13049 (0, _dom.removeClass)(t.chaptersButton.querySelector('.' + t.options.classPrefix + 'chapters-selected'), t.options.classPrefix + 'chapters-selected'); 13050 13051 for (var _i10 = 0; _i10 < listItems.length; _i10++) { 13052 listItems[_i10].setAttribute('aria-checked', false); 13053 } 13054 13055 var keyboard = e.keyCode || e.which; 13056 if (typeof keyboard === 'undefined') { 13057 setTimeout(function () { 13058 t.getElement(t.container).focus(); 13059 }, 500); 13060 } 13061 13062 t.media.setCurrentTime(parseFloat(self.value)); 13063 if (t.media.paused) { 13064 t.media.play(); 13065 } 13066 }); 13067 } 13068 13069 for (var _i11 = 0; _i11 < labels.length; _i11++) { 13070 labels[_i11].addEventListener('click', function (e) { 13071 var radio = (0, _dom.siblings)(this, function (el) { 13072 return el.tagName === 'INPUT'; 13073 })[0], 13074 event = (0, _general.createEvent)('click', radio); 13075 radio.dispatchEvent(event); 13076 e.preventDefault(); 13077 }); 13078 } 13079 }, 13080 getTrackById: function getTrackById(trackId) { 13081 return this.tracks.find(function (track) { 13082 return track.trackId === trackId; 13083 }); 13084 }, 13085 getChapters: function getChapters() { 13086 return this.tracks.filter(function (_ref10) { 13087 var kind = _ref10.kind; 13088 return kind === 'chapters'; 13089 }); 13090 }, 13091 getSubtitles: function getSubtitles() { 13092 return this.tracks.filter(function (_ref11) { 13093 var kind = _ref11.kind; 13094 return kind === 'subtitles' || kind === 'captions'; 13095 }); 13096 }, 13097 searchTrackPosition: function searchTrackPosition(tracks, currentTime) { 13098 var lo = 0, 13099 hi = tracks.length - 1, 13100 mid = void 0, 13101 start = void 0, 13102 stop = void 0; 13103 13104 while (lo <= hi) { 13105 mid = lo + hi >> 1; 13106 start = tracks[mid].start; 13107 stop = tracks[mid].stop; 13108 13109 if (currentTime >= start && currentTime < stop) { 13110 return mid; 13111 } else if (start < currentTime) { 13112 lo = mid + 1; 13113 } else if (start > currentTime) { 13114 hi = mid - 1; 13115 } 13116 } 13117 13118 return -1; 13119 } 13120}); 13121 13122_mejs2.default.language = { 13123 codes: { 13124 af: 'mejs.afrikaans', 13125 sq: 'mejs.albanian', 13126 ar: 'mejs.arabic', 13127 be: 'mejs.belarusian', 13128 bg: 'mejs.bulgarian', 13129 ca: 'mejs.catalan', 13130 zh: 'mejs.chinese', 13131 'zh-cn': 'mejs.chinese-simplified', 13132 'zh-tw': 'mejs.chines-traditional', 13133 hr: 'mejs.croatian', 13134 cs: 'mejs.czech', 13135 da: 'mejs.danish', 13136 nl: 'mejs.dutch', 13137 en: 'mejs.english', 13138 et: 'mejs.estonian', 13139 fl: 'mejs.filipino', 13140 fi: 'mejs.finnish', 13141 fr: 'mejs.french', 13142 gl: 'mejs.galician', 13143 de: 'mejs.german', 13144 el: 'mejs.greek', 13145 ht: 'mejs.haitian-creole', 13146 iw: 'mejs.hebrew', 13147 hi: 'mejs.hindi', 13148 hu: 'mejs.hungarian', 13149 is: 'mejs.icelandic', 13150 id: 'mejs.indonesian', 13151 ga: 'mejs.irish', 13152 it: 'mejs.italian', 13153 ja: 'mejs.japanese', 13154 ko: 'mejs.korean', 13155 lv: 'mejs.latvian', 13156 lt: 'mejs.lithuanian', 13157 mk: 'mejs.macedonian', 13158 ms: 'mejs.malay', 13159 mt: 'mejs.maltese', 13160 no: 'mejs.norwegian', 13161 fa: 'mejs.persian', 13162 pl: 'mejs.polish', 13163 pt: 'mejs.portuguese', 13164 ro: 'mejs.romanian', 13165 ru: 'mejs.russian', 13166 sr: 'mejs.serbian', 13167 sk: 'mejs.slovak', 13168 sl: 'mejs.slovenian', 13169 es: 'mejs.spanish', 13170 sw: 'mejs.swahili', 13171 sv: 'mejs.swedish', 13172 tl: 'mejs.tagalog', 13173 th: 'mejs.thai', 13174 tr: 'mejs.turkish', 13175 uk: 'mejs.ukrainian', 13176 vi: 'mejs.vietnamese', 13177 cy: 'mejs.welsh', 13178 yi: 'mejs.yiddish' 13179 } 13180}; 13181 13182},{"17":17,"2":2,"25":25,"26":26,"27":27,"6":6,"8":8}],15:[function(_dereq_,module,exports){ 13183'use strict'; 13184 13185var _document = _dereq_(2); 13186 13187var _document2 = _interopRequireDefault(_document); 13188 13189var _player = _dereq_(17); 13190 13191var _player2 = _interopRequireDefault(_player); 13192 13193var _i18n = _dereq_(6); 13194 13195var _i18n2 = _interopRequireDefault(_i18n); 13196 13197var _constants = _dereq_(24); 13198 13199var _general = _dereq_(26); 13200 13201var _dom = _dereq_(25); 13202 13203var _generate = _dereq_(27); 13204 13205function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 13206 13207Object.assign(_player.config, { 13208 muteText: null, 13209 13210 unmuteText: null, 13211 13212 allyVolumeControlText: null, 13213 13214 hideVolumeOnTouchDevices: true, 13215 13216 audioVolume: 'horizontal', 13217 13218 videoVolume: 'vertical', 13219 13220 startVolume: 0.8 13221}); 13222 13223Object.assign(_player2.default.prototype, { 13224 buildvolume: function buildvolume(player, controls, layers, media) { 13225 if ((_constants.IS_ANDROID || _constants.IS_IOS) && this.options.hideVolumeOnTouchDevices) { 13226 return; 13227 } 13228 13229 var t = this, 13230 mode = t.isVideo ? t.options.videoVolume : t.options.audioVolume, 13231 muteText = (0, _general.isString)(t.options.muteText) ? t.options.muteText : _i18n2.default.t('mejs.mute'), 13232 unmuteText = (0, _general.isString)(t.options.unmuteText) ? t.options.unmuteText : _i18n2.default.t('mejs.unmute'), 13233 volumeControlText = (0, _general.isString)(t.options.allyVolumeControlText) ? t.options.allyVolumeControlText : _i18n2.default.t('mejs.volume-help-text'), 13234 mute = _document2.default.createElement('div'); 13235 13236 mute.className = t.options.classPrefix + 'button ' + t.options.classPrefix + 'volume-button ' + t.options.classPrefix + 'mute'; 13237 mute.innerHTML = mode === 'horizontal' ? (0, _generate.generateControlButton)(t.id, muteText, muteText, '' + t.media.options.iconSprite, ['icon-mute', 'icon-unmute'], '' + t.options.classPrefix, '', t.options.classPrefix + 'horizontal-volume-slider') : (0, _generate.generateControlButton)(t.id, muteText, muteText, '' + t.media.options.iconSprite, ['icon-mute', 'icon-unmute'], '' + t.options.classPrefix, '', t.options.classPrefix + 'volume-slider') + ('<a class="' + t.options.classPrefix + 'volume-slider" ') + ('aria-label="' + _i18n2.default.t('mejs.volume-slider') + '" aria-valuemin="0" aria-valuemax="100" role="slider" ') + 'aria-orientation="vertical">' + ('<span class="' + t.options.classPrefix + 'offscreen" id="' + t.options.classPrefix + 'volume-slider">' + volumeControlText + '</span>') + ('<div class="' + t.options.classPrefix + 'volume-total">') + ('<div class="' + t.options.classPrefix + 'volume-current"></div>') + ('<div class="' + t.options.classPrefix + 'volume-handle"></div>') + '</div>' + '</a>'; 13238 13239 t.addControlElement(mute, 'volume'); 13240 13241 t.options.keyActions.push({ 13242 keys: [38], 13243 action: function action(player) { 13244 var volumeSlider = player.getElement(player.container).querySelector('.' + t.options.classPrefix + 'volume-slider'); 13245 if (volumeSlider && volumeSlider.matches(':focus')) { 13246 volumeSlider.style.display = 'block'; 13247 } 13248 if (player.isVideo) { 13249 player.showControls(); 13250 player.startControlsTimer(); 13251 } 13252 13253 var newVolume = Math.min(player.volume + 0.1, 1); 13254 player.setVolume(newVolume); 13255 if (newVolume > 0) { 13256 player.setMuted(false); 13257 } 13258 } 13259 }, { 13260 keys: [40], 13261 action: function action(player) { 13262 var volumeSlider = player.getElement(player.container).querySelector('.' + t.options.classPrefix + 'volume-slider'); 13263 if (volumeSlider) { 13264 volumeSlider.style.display = 'block'; 13265 } 13266 13267 if (player.isVideo) { 13268 player.showControls(); 13269 player.startControlsTimer(); 13270 } 13271 13272 var newVolume = Math.max(player.volume - 0.1, 0); 13273 player.setVolume(newVolume); 13274 13275 if (newVolume <= 0.1) { 13276 player.setMuted(true); 13277 } 13278 } 13279 }, { 13280 keys: [77], 13281 action: function action(player) { 13282 var volumeSlider = player.getElement(player.container).querySelector('.' + t.options.classPrefix + 'volume-slider'); 13283 if (volumeSlider) { 13284 volumeSlider.style.display = 'block'; 13285 } 13286 13287 if (player.isVideo) { 13288 player.showControls(); 13289 player.startControlsTimer(); 13290 } 13291 if (player.media.muted) { 13292 player.setMuted(false); 13293 } else { 13294 player.setMuted(true); 13295 } 13296 } 13297 }); 13298 13299 if (mode === 'horizontal') { 13300 var anchor = _document2.default.createElement('a'); 13301 anchor.className = t.options.classPrefix + 'horizontal-volume-slider'; 13302 anchor.setAttribute('aria-label', _i18n2.default.t('mejs.volume-slider')); 13303 anchor.setAttribute('aria-valuemin', 0); 13304 anchor.setAttribute('aria-valuemax', 100); 13305 anchor.setAttribute('aria-valuenow', 100); 13306 anchor.setAttribute('role', 'slider'); 13307 anchor.innerHTML += '<span class="' + t.options.classPrefix + 'offscreen" id="' + t.options.classPrefix + 'horizontal-volume-slider">' + volumeControlText + '</span>' + ('<div class="' + t.options.classPrefix + 'horizontal-volume-total">') + ('<div class="' + t.options.classPrefix + 'horizontal-volume-current"></div>') + ('<div class="' + t.options.classPrefix + 'horizontal-volume-handle"></div>') + '</div>'; 13308 mute.parentNode.insertBefore(anchor, mute.nextSibling); 13309 } 13310 13311 var mouseIsDown = false, 13312 mouseIsOver = false, 13313 modified = false, 13314 updateVolumeSlider = function updateVolumeSlider() { 13315 var volume = Math.floor(media.volume * 100); 13316 volumeSlider.setAttribute('aria-valuenow', volume); 13317 volumeSlider.setAttribute('aria-valuetext', volume + '%'); 13318 }; 13319 13320 var volumeSlider = mode === 'vertical' ? t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'volume-slider') : t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'horizontal-volume-slider'), 13321 volumeTotal = mode === 'vertical' ? t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'volume-total') : t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'horizontal-volume-total'), 13322 volumeCurrent = mode === 'vertical' ? t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'volume-current') : t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'horizontal-volume-current'), 13323 volumeHandle = mode === 'vertical' ? t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'volume-handle') : t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'horizontal-volume-handle'), 13324 positionVolumeHandle = function positionVolumeHandle(volume) { 13325 13326 if (volume === null || isNaN(volume) || volume === undefined) { 13327 return; 13328 } 13329 13330 volume = Math.max(0, volume); 13331 volume = Math.min(volume, 1); 13332 13333 if (volume === 0) { 13334 (0, _dom.removeClass)(mute, t.options.classPrefix + 'mute'); 13335 (0, _dom.addClass)(mute, t.options.classPrefix + 'unmute'); 13336 var button = mute.firstElementChild; 13337 button.setAttribute('title', unmuteText); 13338 button.setAttribute('aria-label', unmuteText); 13339 } else { 13340 (0, _dom.removeClass)(mute, t.options.classPrefix + 'unmute'); 13341 (0, _dom.addClass)(mute, t.options.classPrefix + 'mute'); 13342 var _button = mute.firstElementChild; 13343 _button.setAttribute('title', muteText); 13344 _button.setAttribute('aria-label', muteText); 13345 } 13346 13347 var volumePercentage = volume * 100 + '%', 13348 volumeStyles = getComputedStyle(volumeHandle); 13349 13350 if (mode === 'vertical') { 13351 volumeCurrent.style.bottom = 0; 13352 volumeCurrent.style.height = volumePercentage; 13353 volumeHandle.style.bottom = volumePercentage; 13354 volumeHandle.style.marginBottom = -parseFloat(volumeStyles.height) / 2 + 'px'; 13355 } else { 13356 volumeCurrent.style.left = 0; 13357 volumeCurrent.style.width = volumePercentage; 13358 volumeHandle.style.left = volumePercentage; 13359 volumeHandle.style.marginLeft = -parseFloat(volumeStyles.width) / 2 + 'px'; 13360 } 13361 }, 13362 handleVolumeMove = function handleVolumeMove(e) { 13363 var totalOffset = (0, _dom.offset)(volumeTotal), 13364 volumeStyles = getComputedStyle(volumeTotal); 13365 13366 modified = true; 13367 13368 var volume = null; 13369 13370 if (mode === 'vertical') { 13371 var railHeight = parseFloat(volumeStyles.height), 13372 newY = e.pageY - totalOffset.top; 13373 13374 volume = (railHeight - newY) / railHeight; 13375 13376 if (totalOffset.top === 0 || totalOffset.left === 0) { 13377 return; 13378 } 13379 } else { 13380 var railWidth = parseFloat(volumeStyles.width), 13381 newX = e.pageX - totalOffset.left; 13382 13383 volume = newX / railWidth; 13384 } 13385 13386 volume = Math.max(0, volume); 13387 volume = Math.min(volume, 1); 13388 13389 positionVolumeHandle(volume); 13390 13391 t.setMuted(volume === 0); 13392 t.setVolume(volume); 13393 13394 e.preventDefault(); 13395 e.stopPropagation(); 13396 }, 13397 toggleMute = function toggleMute() { 13398 if (t.muted) { 13399 positionVolumeHandle(0); 13400 (0, _dom.removeClass)(mute, t.options.classPrefix + 'mute'); 13401 (0, _dom.addClass)(mute, t.options.classPrefix + 'unmute'); 13402 } else { 13403 13404 positionVolumeHandle(media.volume); 13405 (0, _dom.removeClass)(mute, t.options.classPrefix + 'unmute'); 13406 (0, _dom.addClass)(mute, t.options.classPrefix + 'mute'); 13407 } 13408 }; 13409 13410 player.getElement(player.container).addEventListener('keydown', function (e) { 13411 var hasFocus = !!e.target.closest('.' + t.options.classPrefix + 'container'); 13412 if (!hasFocus && mode === 'vertical') { 13413 volumeSlider.style.display = 'none'; 13414 } 13415 }); 13416 13417 mute.addEventListener('mouseenter', function (e) { 13418 if (e.target === mute) { 13419 volumeSlider.style.display = 'block'; 13420 mouseIsOver = true; 13421 e.preventDefault(); 13422 e.stopPropagation(); 13423 } 13424 }); 13425 mute.addEventListener('focusin', function () { 13426 volumeSlider.style.display = 'block'; 13427 mouseIsOver = true; 13428 }); 13429 13430 mute.addEventListener('focusout', function (e) { 13431 if ((!e.relatedTarget || e.relatedTarget && !e.relatedTarget.matches('.' + t.options.classPrefix + 'volume-slider')) && mode === 'vertical') { 13432 volumeSlider.style.display = 'none'; 13433 } 13434 }); 13435 mute.addEventListener('mouseleave', function () { 13436 mouseIsOver = false; 13437 if (!mouseIsDown && mode === 'vertical') { 13438 volumeSlider.style.display = 'none'; 13439 } 13440 }); 13441 mute.addEventListener('focusout', function () { 13442 mouseIsOver = false; 13443 }); 13444 mute.addEventListener('keydown', function (e) { 13445 if (t.options.enableKeyboard && t.options.keyActions.length) { 13446 var keyCode = e.which || e.keyCode || 0, 13447 volume = media.volume; 13448 13449 switch (keyCode) { 13450 case 38: 13451 volume = Math.min(volume + 0.1, 1); 13452 break; 13453 case 40: 13454 volume = Math.max(0, volume - 0.1); 13455 break; 13456 default: 13457 return true; 13458 } 13459 13460 mouseIsDown = false; 13461 positionVolumeHandle(volume); 13462 media.setVolume(volume); 13463 13464 e.preventDefault(); 13465 e.stopPropagation(); 13466 } 13467 }); 13468 mute.querySelector('button').addEventListener('click', function () { 13469 media.setMuted(!media.muted); 13470 var event = (0, _general.createEvent)('volumechange', media); 13471 media.dispatchEvent(event); 13472 }); 13473 13474 volumeSlider.addEventListener('dragstart', function () { 13475 return false; 13476 }); 13477 13478 volumeSlider.addEventListener('mouseover', function () { 13479 mouseIsOver = true; 13480 }); 13481 volumeSlider.addEventListener('focusin', function () { 13482 volumeSlider.style.display = 'block'; 13483 mouseIsOver = true; 13484 }); 13485 volumeSlider.addEventListener('focusout', function () { 13486 mouseIsOver = false; 13487 if (!mouseIsDown && mode === 'vertical') { 13488 volumeSlider.style.display = 'none'; 13489 } 13490 }); 13491 volumeSlider.addEventListener('mousedown', function (e) { 13492 handleVolumeMove(e); 13493 t.globalBind('mousemove.vol', function (event) { 13494 var target = event.target; 13495 13496 var targetHasClosest = typeof target.closest == 'function'; 13497 var targetSliderElement = target.closest(mode === 'vertical' ? '.' + t.options.classPrefix + 'volume-slider' : '.' + t.options.classPrefix + 'horizontal-volume-slider'); 13498 if (mouseIsDown && (target === volumeSlider || targetHasClosest && targetSliderElement)) { 13499 handleVolumeMove(event); 13500 } 13501 }); 13502 t.globalBind('mouseup.vol', function () { 13503 mouseIsDown = false; 13504 if (!mouseIsOver && mode === 'vertical') { 13505 volumeSlider.style.display = 'none'; 13506 } 13507 }); 13508 mouseIsDown = true; 13509 e.preventDefault(); 13510 e.stopPropagation(); 13511 }); 13512 13513 media.addEventListener('volumechange', function (e) { 13514 if (!mouseIsDown) { 13515 toggleMute(); 13516 } 13517 updateVolumeSlider(e); 13518 }); 13519 13520 var rendered = false; 13521 media.addEventListener('rendererready', function () { 13522 if (!modified) { 13523 setTimeout(function () { 13524 rendered = true; 13525 if (player.options.startVolume === 0 || media.originalNode.muted) { 13526 media.setMuted(true); 13527 } 13528 media.setVolume(player.options.startVolume); 13529 t.setControlsSize(); 13530 }, 250); 13531 } 13532 }); 13533 13534 media.addEventListener('loadedmetadata', function () { 13535 setTimeout(function () { 13536 if (!modified && !rendered) { 13537 if (player.options.startVolume === 0 || media.originalNode.muted) { 13538 media.setMuted(true); 13539 } 13540 if (player.options.startVolume === 0) { 13541 player.options.startVolume = 0; 13542 } 13543 media.setVolume(player.options.startVolume); 13544 t.setControlsSize(); 13545 } 13546 rendered = false; 13547 }, 250); 13548 }); 13549 13550 if (player.options.startVolume === 0 || media.originalNode.muted) { 13551 media.setMuted(true); 13552 if (player.options.startVolume === 0) { 13553 player.options.startVolume = 0; 13554 } 13555 toggleMute(); 13556 } 13557 13558 t.getElement(t.container).addEventListener('controlsresize', function () { 13559 toggleMute(); 13560 }); 13561 } 13562}); 13563 13564},{"17":17,"2":2,"24":24,"25":25,"26":26,"27":27,"6":6}],16:[function(_dereq_,module,exports){ 13565'use strict'; 13566 13567Object.defineProperty(exports, "__esModule", { 13568 value: true 13569}); 13570var EN = exports.EN = { 13571 'mejs.plural-form': 1, 13572 13573 'mejs.download-file': 'Download File', 13574 13575 'mejs.fullscreen': 'Fullscreen', 13576 13577 'mejs.play': 'Play', 13578 'mejs.pause': 'Pause', 13579 13580 'mejs.time-slider': 'Time Slider', 13581 'mejs.time-help-text': 'Use Left/Right Arrow keys to advance one second, Up/Down arrows to advance ten seconds.', 13582 'mejs.live-broadcast': 'Live Broadcast', 13583 13584 'mejs.current': 'Current time', 13585 'mejs.duration': 'Total duration', 13586 13587 'mejs.volume-help-text': 'Use Up/Down Arrow keys to increase or decrease volume.', 13588 'mejs.unmute': 'Unmute', 13589 'mejs.mute': 'Mute', 13590 'mejs.volume-slider': 'Volume Slider', 13591 13592 'mejs.video-player': 'Video Player', 13593 'mejs.audio-player': 'Audio Player', 13594 13595 'mejs.captions-subtitles': 'Captions/Subtitles', 13596 'mejs.captions-chapters': 'Chapters', 13597 'mejs.none': 'None', 13598 'mejs.afrikaans': 'Afrikaans', 13599 'mejs.albanian': 'Albanian', 13600 'mejs.arabic': 'Arabic', 13601 'mejs.belarusian': 'Belarusian', 13602 'mejs.bulgarian': 'Bulgarian', 13603 'mejs.catalan': 'Catalan', 13604 'mejs.chinese': 'Chinese', 13605 'mejs.chinese-simplified': 'Chinese (Simplified)', 13606 'mejs.chinese-traditional': 'Chinese (Traditional)', 13607 'mejs.croatian': 'Croatian', 13608 'mejs.czech': 'Czech', 13609 'mejs.danish': 'Danish', 13610 'mejs.dutch': 'Dutch', 13611 'mejs.english': 'English', 13612 'mejs.estonian': 'Estonian', 13613 'mejs.filipino': 'Filipino', 13614 'mejs.finnish': 'Finnish', 13615 'mejs.french': 'French', 13616 'mejs.galician': 'Galician', 13617 'mejs.german': 'German', 13618 'mejs.greek': 'Greek', 13619 'mejs.haitian-creole': 'Haitian Creole', 13620 'mejs.hebrew': 'Hebrew', 13621 'mejs.hindi': 'Hindi', 13622 'mejs.hungarian': 'Hungarian', 13623 'mejs.icelandic': 'Icelandic', 13624 'mejs.indonesian': 'Indonesian', 13625 'mejs.irish': 'Irish', 13626 'mejs.italian': 'Italian', 13627 'mejs.japanese': 'Japanese', 13628 'mejs.korean': 'Korean', 13629 'mejs.latvian': 'Latvian', 13630 'mejs.lithuanian': 'Lithuanian', 13631 'mejs.macedonian': 'Macedonian', 13632 'mejs.malay': 'Malay', 13633 'mejs.maltese': 'Maltese', 13634 'mejs.norwegian': 'Norwegian', 13635 'mejs.persian': 'Persian', 13636 'mejs.polish': 'Polish', 13637 'mejs.portuguese': 'Portuguese', 13638 'mejs.romanian': 'Romanian', 13639 'mejs.russian': 'Russian', 13640 'mejs.serbian': 'Serbian', 13641 'mejs.slovak': 'Slovak', 13642 'mejs.slovenian': 'Slovenian', 13643 'mejs.spanish': 'Spanish', 13644 'mejs.swahili': 'Swahili', 13645 'mejs.swedish': 'Swedish', 13646 'mejs.tagalog': 'Tagalog', 13647 'mejs.thai': 'Thai', 13648 'mejs.turkish': 'Turkish', 13649 'mejs.ukrainian': 'Ukrainian', 13650 'mejs.vietnamese': 'Vietnamese', 13651 'mejs.welsh': 'Welsh', 13652 'mejs.yiddish': 'Yiddish' 13653}; 13654 13655},{}],17:[function(_dereq_,module,exports){ 13656'use strict'; 13657 13658Object.defineProperty(exports, "__esModule", { 13659 value: true 13660}); 13661exports.config = undefined; 13662 13663var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 13664 13665var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 13666 13667var _window = _dereq_(3); 13668 13669var _window2 = _interopRequireDefault(_window); 13670 13671var _document = _dereq_(2); 13672 13673var _document2 = _interopRequireDefault(_document); 13674 13675var _mejs = _dereq_(8); 13676 13677var _mejs2 = _interopRequireDefault(_mejs); 13678 13679var _mediaelement = _dereq_(7); 13680 13681var _mediaelement2 = _interopRequireDefault(_mediaelement); 13682 13683var _default = _dereq_(18); 13684 13685var _default2 = _interopRequireDefault(_default); 13686 13687var _i18n = _dereq_(6); 13688 13689var _i18n2 = _interopRequireDefault(_i18n); 13690 13691var _constants = _dereq_(24); 13692 13693var _general = _dereq_(26); 13694 13695var _time = _dereq_(30); 13696 13697var _media = _dereq_(28); 13698 13699var _dom = _dereq_(25); 13700 13701var dom = _interopRequireWildcard(_dom); 13702 13703var _generate = _dereq_(27); 13704 13705function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } 13706 13707function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 13708 13709function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 13710 13711_mejs2.default.mepIndex = 0; 13712 13713_mejs2.default.players = {}; 13714 13715var config = exports.config = { 13716 poster: '', 13717 13718 showPosterWhenEnded: false, 13719 13720 showPosterWhenPaused: false, 13721 13722 defaultVideoWidth: 480, 13723 13724 defaultVideoHeight: 270, 13725 13726 videoWidth: -1, 13727 13728 videoHeight: -1, 13729 13730 defaultAudioWidth: 400, 13731 13732 defaultAudioHeight: 40, 13733 13734 defaultSeekBackwardInterval: function defaultSeekBackwardInterval(media) { 13735 return media.getDuration() * 0.05; 13736 }, 13737 13738 defaultSeekForwardInterval: function defaultSeekForwardInterval(media) { 13739 return media.getDuration() * 0.05; 13740 }, 13741 13742 setDimensions: true, 13743 13744 audioWidth: -1, 13745 13746 audioHeight: -1, 13747 13748 loop: false, 13749 13750 autoRewind: true, 13751 13752 enableAutosize: true, 13753 13754 timeFormat: '', 13755 13756 alwaysShowHours: false, 13757 13758 showTimecodeFrameCount: false, 13759 13760 framesPerSecond: 25, 13761 13762 alwaysShowControls: false, 13763 13764 hideVideoControlsOnLoad: false, 13765 13766 hideVideoControlsOnPause: false, 13767 13768 clickToPlayPause: true, 13769 13770 controlsTimeoutDefault: 1500, 13771 13772 controlsTimeoutMouseEnter: 2500, 13773 13774 controlsTimeoutMouseLeave: 1000, 13775 13776 iPadUseNativeControls: false, 13777 13778 iPhoneUseNativeControls: false, 13779 13780 AndroidUseNativeControls: false, 13781 13782 features: ['playpause', 'current', 'progress', 'duration', 'tracks', 'volume', 'fullscreen'], 13783 13784 useDefaultControls: false, 13785 13786 isVideo: true, 13787 13788 stretching: 'auto', 13789 13790 classPrefix: 'mejs__', 13791 13792 enableKeyboard: true, 13793 13794 pauseOtherPlayers: true, 13795 13796 secondsDecimalLength: 0, 13797 13798 customError: null, 13799 13800 keyActions: [], 13801 13802 hideScreenReaderTitle: false 13803}; 13804 13805_mejs2.default.MepDefaults = config; 13806 13807var MediaElementPlayer = function () { 13808 function MediaElementPlayer(node, o) { 13809 _classCallCheck(this, MediaElementPlayer); 13810 13811 var t = this, 13812 element = typeof node === 'string' ? _document2.default.getElementById(node) : node; 13813 13814 if (!(t instanceof MediaElementPlayer)) { 13815 return new MediaElementPlayer(element, o); 13816 } 13817 13818 t.node = t.media = element; 13819 13820 if (!t.node) { 13821 return; 13822 } 13823 13824 if (t.media.player) { 13825 return t.media.player; 13826 } 13827 13828 t.hasFocus = false; 13829 13830 t.controlsAreVisible = true; 13831 13832 t.controlsEnabled = true; 13833 13834 t.controlsTimer = null; 13835 13836 t.currentMediaTime = 0; 13837 13838 t.proxy = null; 13839 13840 if (o === undefined) { 13841 var options = t.node.getAttribute('data-mejsoptions'); 13842 o = options ? JSON.parse(options) : {}; 13843 } 13844 13845 t.options = Object.assign({}, config, o); 13846 13847 if (t.options.loop && !t.media.getAttribute('loop')) { 13848 t.media.loop = true; 13849 t.node.loop = true; 13850 } else if (t.media.loop) { 13851 t.options.loop = true; 13852 } 13853 13854 if (!t.options.timeFormat) { 13855 t.options.timeFormat = 'mm:ss'; 13856 if (t.options.alwaysShowHours) { 13857 t.options.timeFormat = 'hh:mm:ss'; 13858 } 13859 if (t.options.showTimecodeFrameCount) { 13860 t.options.timeFormat += ':ff'; 13861 } 13862 } 13863 13864 (0, _time.calculateTimeFormat)(0, t.options, t.options.framesPerSecond || 25); 13865 13866 t.id = 'mep_' + _mejs2.default.mepIndex++; 13867 13868 _mejs2.default.players[t.id] = t; 13869 13870 t.init(); 13871 13872 return t; 13873 } 13874 13875 _createClass(MediaElementPlayer, [{ 13876 key: 'getElement', 13877 value: function getElement(element) { 13878 return element; 13879 } 13880 }, { 13881 key: 'init', 13882 value: function init() { 13883 var t = this, 13884 playerOptions = Object.assign({}, t.options, { 13885 success: function success(media, domNode) { 13886 t._meReady(media, domNode); 13887 }, 13888 error: function error(e) { 13889 t._handleError(e); 13890 } 13891 }), 13892 tagName = t.node.tagName.toLowerCase(); 13893 13894 t.isDynamic = tagName !== 'audio' && tagName !== 'video' && tagName !== 'iframe'; 13895 t.isVideo = t.isDynamic ? t.options.isVideo : tagName !== 'audio' && t.options.isVideo; 13896 t.mediaFiles = null; 13897 t.trackFiles = null; 13898 13899 t.media.addEventListener('rendererready', this.updateNode.bind(this)); 13900 13901 if (_constants.IS_IPAD && t.options.iPadUseNativeControls || _constants.IS_IPHONE && t.options.iPhoneUseNativeControls) { 13902 t.node.setAttribute('controls', true); 13903 13904 if (_constants.IS_IPAD && t.node.getAttribute('autoplay')) { 13905 t.play(); 13906 } 13907 } else if ((t.isVideo || !t.isVideo && (t.options.features.length || t.options.useDefaultControls)) && !(_constants.IS_ANDROID && t.options.AndroidUseNativeControls)) { 13908 t.node.removeAttribute('controls'); 13909 var videoPlayerTitle = t.isVideo ? _i18n2.default.t('mejs.video-player') : _i18n2.default.t('mejs.audio-player'); 13910 13911 if (!t.options.hideScreenReaderTitle) { 13912 var offscreen = _document2.default.createElement('span'); 13913 offscreen.className = t.options.classPrefix + 'offscreen'; 13914 offscreen.innerText = videoPlayerTitle; 13915 t.media.parentNode.insertBefore(offscreen, t.media); 13916 } 13917 13918 t.container = _document2.default.createElement('div'); 13919 t.getElement(t.container).id = t.id; 13920 t.getElement(t.container).className = t.options.classPrefix + 'container ' + t.options.classPrefix + 'container-keyboard-inactive ' + t.media.className; 13921 t.getElement(t.container).tabIndex = 0; 13922 t.getElement(t.container).setAttribute('role', 'application'); 13923 t.getElement(t.container).setAttribute('aria-label', videoPlayerTitle); 13924 t.getElement(t.container).innerHTML = '<div class="' + t.options.classPrefix + 'inner">' + ('<div class="' + t.options.classPrefix + 'mediaelement"></div>') + ('<div class="' + t.options.classPrefix + 'layers"></div>') + ('<div class="' + t.options.classPrefix + 'controls"></div>') + '</div>'; 13925 13926 t.getElement(t.container).addEventListener('focus', function (e) { 13927 if (!t.controlsAreVisible && !t.hasFocus && t.controlsEnabled) { 13928 t.showControls(true); 13929 13930 var btnSelector = (0, _general.isNodeAfter)(e.relatedTarget, t.getElement(t.container)) ? '.' + t.options.classPrefix + 'controls .' + t.options.classPrefix + 'button:last-child > button' : '.' + t.options.classPrefix + 'playpause-button > button', 13931 button = t.getElement(t.container).querySelector(btnSelector); 13932 13933 button.focus(); 13934 } 13935 }); 13936 t.node.parentNode.insertBefore(t.getElement(t.container), t.node); 13937 13938 if (!t.options.features.length && !t.options.useDefaultControls) { 13939 t.getElement(t.container).style.background = 'transparent'; 13940 t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'controls').style.display = 'none'; 13941 } 13942 13943 if (t.isVideo && t.options.stretching === 'fill' && !dom.hasClass(t.getElement(t.container).parentNode, t.options.classPrefix + 'fill-container')) { 13944 t.outerContainer = t.media.parentNode; 13945 13946 var wrapper = _document2.default.createElement('div'); 13947 wrapper.className = t.options.classPrefix + 'fill-container'; 13948 t.getElement(t.container).parentNode.insertBefore(wrapper, t.getElement(t.container)); 13949 wrapper.appendChild(t.getElement(t.container)); 13950 } 13951 13952 if (_constants.IS_ANDROID) { 13953 dom.addClass(t.getElement(t.container), t.options.classPrefix + 'android'); 13954 } 13955 if (_constants.IS_IOS) { 13956 dom.addClass(t.getElement(t.container), t.options.classPrefix + 'ios'); 13957 } 13958 if (_constants.IS_IPAD) { 13959 dom.addClass(t.getElement(t.container), t.options.classPrefix + 'ipad'); 13960 } 13961 if (_constants.IS_IPHONE) { 13962 dom.addClass(t.getElement(t.container), t.options.classPrefix + 'iphone'); 13963 } 13964 dom.addClass(t.getElement(t.container), t.isVideo ? t.options.classPrefix + 'video' : t.options.classPrefix + 'audio'); 13965 13966 t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'mediaelement').appendChild(t.node); 13967 13968 t.media.player = t; 13969 13970 t.controls = t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'controls'); 13971 t.layers = t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'layers'); 13972 13973 var tagType = t.isVideo ? 'video' : 'audio', 13974 capsTagName = tagType.substring(0, 1).toUpperCase() + tagType.substring(1); 13975 13976 if (t.options[tagType + 'Width'] > 0 || t.options[tagType + 'Width'].toString().indexOf('%') > -1) { 13977 t.width = t.options[tagType + 'Width']; 13978 } else if (t.node.style.width !== '' && t.node.style.width !== null) { 13979 t.width = t.node.style.width; 13980 } else if (t.node.getAttribute('width')) { 13981 t.width = t.node.getAttribute('width'); 13982 } else { 13983 t.width = t.options['default' + capsTagName + 'Width']; 13984 } 13985 13986 if (t.options[tagType + 'Height'] > 0 || t.options[tagType + 'Height'].toString().indexOf('%') > -1) { 13987 t.height = t.options[tagType + 'Height']; 13988 } else if (t.node.style.height !== '' && t.node.style.height !== null) { 13989 t.height = t.node.style.height; 13990 } else if (t.node.getAttribute('height')) { 13991 t.height = t.node.getAttribute('height'); 13992 } else { 13993 t.height = t.options['default' + capsTagName + 'Height']; 13994 } 13995 t.initialAspectRatio = t.height >= t.width ? t.width / t.height : t.height / t.width; 13996 13997 t.setPlayerSize(t.width, t.height); 13998 } else if (!t.isVideo && !t.options.features.length && !t.options.useDefaultControls) { 13999 t.node.style.display = 'none'; 14000 } 14001 14002 playerOptions.pluginWidth = t.width; 14003 playerOptions.pluginHeight = t.height; 14004 14005 _mejs2.default.MepDefaults = playerOptions; 14006 14007 new _mediaelement2.default(t.media, playerOptions, t.mediaFiles); 14008 14009 if (t.getElement(t.container) !== undefined && t.options.features.length && t.controlsAreVisible && !t.options.hideVideoControlsOnLoad) { 14010 var event = (0, _general.createEvent)('controlsshown', t.getElement(t.container)); 14011 t.getElement(t.container).dispatchEvent(event); 14012 } 14013 } 14014 }, { 14015 key: 'updateNode', 14016 value: function updateNode(event) { 14017 var node = void 0, 14018 iframeId = void 0; 14019 var mediaElement = event.detail.target.hasOwnProperty('mediaElement') ? event.detail.target.mediaElement : event.detail.target; 14020 var originalNode = mediaElement.originalNode; 14021 14022 if (event.detail.isIframe) { 14023 iframeId = mediaElement.renderer.id; 14024 node = mediaElement.querySelector('#' + iframeId); 14025 node.style.position = 'absolute'; 14026 14027 if (originalNode.style.maxWidth) { 14028 node.style.maxWidth = originalNode.style.maxWidth; 14029 } 14030 } else { 14031 node = event.detail.target; 14032 } 14033 this.domNode = node; 14034 this.node = node; 14035 } 14036 }, { 14037 key: 'showControls', 14038 value: function showControls(doAnimation) { 14039 var t = this; 14040 14041 doAnimation = doAnimation === undefined || doAnimation; 14042 14043 if (t.controlsAreVisible || !t.isVideo) { 14044 return; 14045 } 14046 14047 if (doAnimation) { 14048 (function () { 14049 dom.fadeIn(t.getElement(t.controls), 200, function () { 14050 dom.removeClass(t.getElement(t.controls), t.options.classPrefix + 'offscreen'); 14051 var event = (0, _general.createEvent)('controlsshown', t.getElement(t.container)); 14052 t.getElement(t.container).dispatchEvent(event); 14053 }); 14054 14055 var controls = t.getElement(t.container).querySelectorAll('.' + t.options.classPrefix + 'control'); 14056 14057 var _loop = function _loop(i, total) { 14058 dom.fadeIn(controls[i], 200, function () { 14059 dom.removeClass(controls[i], t.options.classPrefix + 'offscreen'); 14060 }); 14061 }; 14062 14063 for (var i = 0, total = controls.length; i < total; i++) { 14064 _loop(i, total); 14065 } 14066 })(); 14067 } else { 14068 dom.removeClass(t.getElement(t.controls), t.options.classPrefix + 'offscreen'); 14069 t.getElement(t.controls).style.display = ''; 14070 t.getElement(t.controls).style.opacity = 1; 14071 14072 var controls = t.getElement(t.container).querySelectorAll('.' + t.options.classPrefix + 'control'); 14073 for (var i = 0, total = controls.length; i < total; i++) { 14074 dom.removeClass(controls[i], t.options.classPrefix + 'offscreen'); 14075 controls[i].style.display = ''; 14076 } 14077 14078 var event = (0, _general.createEvent)('controlsshown', t.getElement(t.container)); 14079 t.getElement(t.container).dispatchEvent(event); 14080 } 14081 14082 t.controlsAreVisible = true; 14083 t.setControlsSize(); 14084 } 14085 }, { 14086 key: 'hideControls', 14087 value: function hideControls(doAnimation, forceHide) { 14088 var t = this; 14089 14090 doAnimation = doAnimation === undefined || doAnimation; 14091 14092 if (forceHide !== true && (!t.controlsAreVisible || t.options.alwaysShowControls || t.paused && t.readyState === 4 && (!t.options.hideVideoControlsOnLoad && t.currentTime <= 0 || !t.options.hideVideoControlsOnPause && t.currentTime > 0) || t.isVideo && !t.options.hideVideoControlsOnLoad && !t.readyState || t.ended)) { 14093 return; 14094 } 14095 14096 if (doAnimation) { 14097 (function () { 14098 dom.fadeOut(t.getElement(t.controls), 200, function () { 14099 dom.addClass(t.getElement(t.controls), t.options.classPrefix + 'offscreen'); 14100 t.getElement(t.controls).style.display = ''; 14101 var event = (0, _general.createEvent)('controlshidden', t.getElement(t.container)); 14102 t.getElement(t.container).dispatchEvent(event); 14103 }); 14104 14105 var controls = t.getElement(t.container).querySelectorAll('.' + t.options.classPrefix + 'control'); 14106 14107 var _loop2 = function _loop2(i, total) { 14108 dom.fadeOut(controls[i], 200, function () { 14109 dom.addClass(controls[i], t.options.classPrefix + 'offscreen'); 14110 controls[i].style.display = ''; 14111 }); 14112 }; 14113 14114 for (var i = 0, total = controls.length; i < total; i++) { 14115 _loop2(i, total); 14116 } 14117 })(); 14118 } else { 14119 dom.addClass(t.getElement(t.controls), t.options.classPrefix + 'offscreen'); 14120 t.getElement(t.controls).style.display = ''; 14121 t.getElement(t.controls).style.opacity = 0; 14122 14123 var controls = t.getElement(t.container).querySelectorAll('.' + t.options.classPrefix + 'control'); 14124 for (var i = 0, total = controls.length; i < total; i++) { 14125 dom.addClass(controls[i], t.options.classPrefix + 'offscreen'); 14126 controls[i].style.display = ''; 14127 } 14128 14129 var event = (0, _general.createEvent)('controlshidden', t.getElement(t.container)); 14130 t.getElement(t.container).dispatchEvent(event); 14131 } 14132 14133 t.controlsAreVisible = false; 14134 } 14135 }, { 14136 key: 'startControlsTimer', 14137 value: function startControlsTimer(timeout) { 14138 var t = this; 14139 14140 timeout = typeof timeout !== 'undefined' ? timeout : t.options.controlsTimeoutDefault; 14141 14142 t.killControlsTimer('start'); 14143 14144 t.controlsTimer = setTimeout(function () { 14145 t.hideControls(); 14146 t.killControlsTimer('hide'); 14147 }, timeout); 14148 } 14149 }, { 14150 key: 'killControlsTimer', 14151 value: function killControlsTimer() { 14152 var t = this; 14153 14154 if (t.controlsTimer !== null) { 14155 clearTimeout(t.controlsTimer); 14156 delete t.controlsTimer; 14157 t.controlsTimer = null; 14158 } 14159 } 14160 }, { 14161 key: 'disableControls', 14162 value: function disableControls() { 14163 var t = this; 14164 14165 t.killControlsTimer(); 14166 t.controlsEnabled = false; 14167 t.hideControls(false, true); 14168 } 14169 }, { 14170 key: 'enableControls', 14171 value: function enableControls() { 14172 var t = this; 14173 14174 t.controlsEnabled = true; 14175 t.showControls(false); 14176 } 14177 }, { 14178 key: '_setDefaultPlayer', 14179 value: function _setDefaultPlayer() { 14180 var t = this; 14181 if (t.proxy) { 14182 t.proxy.pause(); 14183 } 14184 t.proxy = new _default2.default(t); 14185 t.media.addEventListener('loadedmetadata', function () { 14186 if (t.getCurrentTime() > 0 && t.currentMediaTime > 0) { 14187 t.setCurrentTime(t.currentMediaTime); 14188 if (!_constants.IS_IOS && !_constants.IS_ANDROID) { 14189 t.play(); 14190 } 14191 } 14192 }); 14193 } 14194 }, { 14195 key: '_meReady', 14196 value: function _meReady(media, domNode) { 14197 var t = this, 14198 autoplayAttr = domNode.getAttribute('autoplay'), 14199 autoplay = !(autoplayAttr === undefined || autoplayAttr === null || autoplayAttr === 'false'), 14200 isNative = media.rendererName !== null && /(native|html5)/i.test(media.rendererName); 14201 14202 if (t.getElement(t.controls)) { 14203 t.enableControls(); 14204 } 14205 14206 if (t.getElement(t.container) && t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'overlay-play')) { 14207 t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'overlay-play').style.display = ''; 14208 } 14209 14210 if (t.created) { 14211 return; 14212 } 14213 14214 t.created = true; 14215 t.media = media; 14216 t.domNode = domNode; 14217 14218 if (!(_constants.IS_ANDROID && t.options.AndroidUseNativeControls) && !(_constants.IS_IPAD && t.options.iPadUseNativeControls) && !(_constants.IS_IPHONE && t.options.iPhoneUseNativeControls)) { 14219 if (!t.isVideo && !t.options.features.length && !t.options.useDefaultControls) { 14220 if (autoplay && isNative) { 14221 t.play(); 14222 } 14223 14224 if (t.options.success) { 14225 14226 if (typeof t.options.success === 'string') { 14227 _window2.default[t.options.success](t.media, t.domNode, t); 14228 } else { 14229 t.options.success(t.media, t.domNode, t); 14230 } 14231 } 14232 14233 return; 14234 } 14235 14236 t.featurePosition = {}; 14237 14238 t._setDefaultPlayer(); 14239 14240 t.buildposter(t, t.getElement(t.controls), t.getElement(t.layers), t.media); 14241 t.buildkeyboard(t, t.getElement(t.controls), t.getElement(t.layers), t.media); 14242 t.buildoverlays(t, t.getElement(t.controls), t.getElement(t.layers), t.media); 14243 14244 if (t.options.useDefaultControls) { 14245 var defaultControls = ['playpause', 'current', 'progress', 'duration', 'tracks', 'volume', 'fullscreen']; 14246 t.options.features = defaultControls.concat(t.options.features.filter(function (item) { 14247 return defaultControls.indexOf(item) === -1; 14248 })); 14249 } 14250 14251 t.buildfeatures(t, t.getElement(t.controls), t.getElement(t.layers), t.media); 14252 14253 var event = (0, _general.createEvent)('controlsready', t.getElement(t.container)); 14254 t.getElement(t.container).dispatchEvent(event); 14255 14256 t.setPlayerSize(t.width, t.height); 14257 t.setControlsSize(); 14258 14259 if (t.isVideo) { 14260 t.clickToPlayPauseCallback = function () { 14261 if (t.options.clickToPlayPause) { 14262 var button = t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'overlay-button'), 14263 pressed = button.getAttribute('aria-pressed'); 14264 14265 if (t.paused && pressed) { 14266 t.pause(); 14267 } else if (t.paused) { 14268 t.play(); 14269 } else { 14270 t.pause(); 14271 } 14272 14273 button.setAttribute('aria-pressed', !pressed); 14274 t.getElement(t.container).focus(); 14275 } 14276 }; 14277 14278 t.createIframeLayer(); 14279 14280 t.media.addEventListener('click', t.clickToPlayPauseCallback); 14281 14282 if ((_constants.IS_ANDROID || _constants.IS_IOS) && !t.options.alwaysShowControls) { 14283 t.node.addEventListener('touchstart', function () { 14284 if (t.controlsAreVisible) { 14285 t.hideControls(false); 14286 } else { 14287 if (t.controlsEnabled) { 14288 t.showControls(false); 14289 } 14290 } 14291 }, _constants.SUPPORT_PASSIVE_EVENT ? { passive: true } : false); 14292 } else { 14293 t.getElement(t.container).addEventListener('mouseenter', function () { 14294 if (t.controlsEnabled) { 14295 if (!t.options.alwaysShowControls) { 14296 t.killControlsTimer('enter'); 14297 t.showControls(); 14298 t.startControlsTimer(t.options.controlsTimeoutMouseEnter); 14299 } 14300 } 14301 }); 14302 t.getElement(t.container).addEventListener('mousemove', function () { 14303 if (t.controlsEnabled) { 14304 if (!t.controlsAreVisible) { 14305 t.showControls(); 14306 } 14307 if (!t.options.alwaysShowControls) { 14308 t.startControlsTimer(t.options.controlsTimeoutMouseEnter); 14309 } 14310 } 14311 }); 14312 t.getElement(t.container).addEventListener('mouseleave', function () { 14313 if (t.controlsEnabled) { 14314 if (!t.paused && !t.options.alwaysShowControls) { 14315 t.startControlsTimer(t.options.controlsTimeoutMouseLeave); 14316 } 14317 } 14318 }); 14319 } 14320 14321 if (t.options.hideVideoControlsOnLoad) { 14322 t.hideControls(false); 14323 } 14324 14325 if (t.options.enableAutosize) { 14326 t.media.addEventListener('loadedmetadata', function (e) { 14327 var target = e !== undefined ? e.detail.target || e.target : t.media; 14328 if (t.options.videoHeight <= 0 && !t.domNode.getAttribute('height') && !t.domNode.style.height && target !== null && !isNaN(target.videoHeight)) { 14329 t.setPlayerSize(target.videoWidth, target.videoHeight); 14330 t.setControlsSize(); 14331 t.media.setSize(target.videoWidth, target.videoHeight); 14332 } 14333 }); 14334 } 14335 } 14336 14337 t.media.addEventListener('play', function () { 14338 t.hasFocus = true; 14339 14340 for (var playerIndex in _mejs2.default.players) { 14341 if (_mejs2.default.players.hasOwnProperty(playerIndex)) { 14342 var p = _mejs2.default.players[playerIndex]; 14343 14344 if (p.id !== t.id && t.options.pauseOtherPlayers && !p.paused && !p.ended && p.options.ignorePauseOtherPlayersOption !== true) { 14345 p.pause(); 14346 p.hasFocus = false; 14347 } 14348 } 14349 } 14350 14351 if (!(_constants.IS_ANDROID || _constants.IS_IOS) && !t.options.alwaysShowControls && t.isVideo) { 14352 t.hideControls(); 14353 } 14354 }); 14355 14356 t.media.addEventListener('ended', function () { 14357 if (t.options.autoRewind) { 14358 try { 14359 t.setCurrentTime(0); 14360 14361 setTimeout(function () { 14362 var loadingElement = t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'overlay-loading'); 14363 if (loadingElement && loadingElement.parentNode) { 14364 loadingElement.parentNode.style.display = 'none'; 14365 } 14366 }, 20); 14367 } catch (exp) { 14368 14369 } 14370 } 14371 14372 t.pause(); 14373 14374 if (t.setProgressRail) { 14375 t.setProgressRail(); 14376 } 14377 if (t.setCurrentRail) { 14378 t.setCurrentRail(); 14379 } 14380 14381 if (t.options.loop) { 14382 t.play(); 14383 } else if (!t.options.alwaysShowControls && t.controlsEnabled) { 14384 t.showControls(); 14385 } 14386 }); 14387 14388 t.media.addEventListener('loadedmetadata', function () { 14389 14390 (0, _time.calculateTimeFormat)(t.getDuration(), t.options, t.options.framesPerSecond || 25); 14391 14392 if (t.updateDuration) { 14393 t.updateDuration(); 14394 } 14395 if (t.updateCurrent) { 14396 t.updateCurrent(); 14397 } 14398 14399 if (!t.isFullScreen) { 14400 t.setPlayerSize(t.width, t.height); 14401 t.setControlsSize(); 14402 } 14403 }); 14404 14405 var duration = null; 14406 t.media.addEventListener('timeupdate', function () { 14407 if (!isNaN(t.getDuration()) && duration !== t.getDuration()) { 14408 duration = t.getDuration(); 14409 (0, _time.calculateTimeFormat)(duration, t.options, t.options.framesPerSecond || 25); 14410 14411 if (t.updateDuration) { 14412 t.updateDuration(); 14413 } 14414 if (t.updateCurrent) { 14415 t.updateCurrent(); 14416 } 14417 14418 t.setControlsSize(); 14419 } 14420 }); 14421 14422 if (t.options.enableKeyboard) { 14423 t.getElement(t.container).addEventListener('keydown', function (e) { 14424 var keyCode = e.keyCode || e.which || 0; 14425 14426 if (e.target === t.container && keyCode === 13) { 14427 if (t.paused) { 14428 t.play(); 14429 } else { 14430 t.pause(); 14431 } 14432 } 14433 }); 14434 } 14435 14436 t.getElement(t.container).addEventListener('click', function (e) { 14437 dom.addClass(e.currentTarget, t.options.classPrefix + 'container-keyboard-inactive'); 14438 }); 14439 14440 t.getElement(t.container).addEventListener('focusin', function (e) { 14441 dom.removeClass(e.currentTarget, t.options.classPrefix + 'container-keyboard-inactive'); 14442 if (t.isVideo && !_constants.IS_ANDROID && !_constants.IS_IOS && t.controlsEnabled && !t.options.alwaysShowControls) { 14443 t.killControlsTimer('enter'); 14444 t.showControls(); 14445 t.startControlsTimer(t.options.controlsTimeoutMouseEnter); 14446 } 14447 }); 14448 14449 t.getElement(t.container).addEventListener('focusout', function (e) { 14450 setTimeout(function () { 14451 if (e.relatedTarget) { 14452 if (t.keyboardAction && !e.relatedTarget.closest('.' + t.options.classPrefix + 'container')) { 14453 t.keyboardAction = false; 14454 if (t.isVideo && !t.options.alwaysShowControls && !t.paused) { 14455 t.startControlsTimer(t.options.controlsTimeoutMouseLeave); 14456 } 14457 } 14458 } 14459 }, 0); 14460 }); 14461 14462 setTimeout(function () { 14463 t.setPlayerSize(t.width, t.height); 14464 t.setControlsSize(); 14465 }, 0); 14466 14467 t.globalResizeCallback = function () { 14468 if (
vendor: 11,265 bytes, lines 14468-14823
14468!(t.isFullScreen || _constants.HAS_TRUE_NATIVE_FULLSCREEN && _document2.default.webkitIsFullScreen)) { 14469 t.setPlayerSize(t.width, t.height); 14470 } 14471 14472 t.setControlsSize(); 14473 }; 14474 14475 t.globalBind('resize', t.globalResizeCallback); 14476 } 14477 14478 if (autoplay && isNative) { 14479 t.play(); 14480 } 14481 14482 if (t.options.success) { 14483 if (typeof t.options.success === 'string') { 14484 _window2.default[t.options.success](t.media, t.domNode, t); 14485 } else { 14486 t.options.success(t.media, t.domNode, t); 14487 } 14488 } 14489 } 14490 }, { 14491 key: '_handleError', 14492 value: function _handleError(e, media, node) { 14493 var t = this, 14494 play = t.getElement(t.layers).querySelector('.' + t.options.classPrefix + 'overlay-play'); 14495 14496 if (play) { 14497 play.style.display = 'none'; 14498 } 14499 14500 if (t.options.error) { 14501 t.options.error(e, media, node); 14502 } 14503 14504 if (t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'cannotplay')) { 14505 t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'cannotplay').remove(); 14506 } 14507 14508 var errorContainer = _document2.default.createElement('div'); 14509 errorContainer.className = t.options.classPrefix + 'cannotplay'; 14510 errorContainer.style.width = '100%'; 14511 errorContainer.style.height = '100%'; 14512 14513 var errorContent = typeof t.options.customError === 'function' ? t.options.customError(t.media, t.media.originalNode) : t.options.customError, 14514 imgError = ''; 14515 14516 if (!errorContent) { 14517 var poster = t.media.originalNode.getAttribute('poster'); 14518 if (poster) { 14519 imgError = '<img src="' + poster + '" alt="' + _mejs2.default.i18n.t('mejs.download-file') + '">'; 14520 } 14521 14522 if (e.message) { 14523 errorContent = '<p>' + e.message + '</p>'; 14524 } 14525 14526 if (e.urls) { 14527 for (var i = 0, total = e.urls.length; i < total; i++) { 14528 var url = e.urls[i]; 14529 errorContent += '<a href="' + url.src + '" data-type="' + url.type + '"><span>' + _mejs2.default.i18n.t('mejs.download-file') + ': ' + url.src + '</span></a>'; 14530 } 14531 } 14532 } 14533 14534 if (errorContent && t.getElement(t.layers).querySelector('.' + t.options.classPrefix + 'overlay-error')) { 14535 errorContainer.innerHTML = errorContent; 14536 t.getElement(t.layers).querySelector('.' + t.options.classPrefix + 'overlay-error').innerHTML = '' + imgError + errorContainer.outerHTML; 14537 t.getElement(t.layers).querySelector('.' + t.options.classPrefix + 'overlay-error').parentNode.style.display = 'block'; 14538 } 14539 14540 if (t.controlsEnabled) { 14541 t.disableControls(); 14542 } 14543 } 14544 }, { 14545 key: 'setPlayerSize', 14546 value: function setPlayerSize(width, height) { 14547 var t = this; 14548 14549 if (!t.options.setDimensions) { 14550 return false; 14551 } 14552 14553 if (typeof width !== 'undefined') { 14554 t.width = width; 14555 } 14556 14557 if (typeof height !== 'undefined') { 14558 t.height = height; 14559 } 14560 14561 switch (t.options.stretching) { 14562 case 'fill': 14563 if (t.isVideo) { 14564 t.setFillMode(); 14565 } else { 14566 t.setDimensions(t.width, t.height); 14567 } 14568 break; 14569 case 'responsive': 14570 t.setResponsiveMode(); 14571 break; 14572 case 'none': 14573 t.setDimensions(t.width, t.height); 14574 break; 14575 14576 default: 14577 if (t.hasFluidMode() === true) { 14578 t.setResponsiveMode(); 14579 } else { 14580 t.setDimensions(t.width, t.height); 14581 } 14582 break; 14583 } 14584 } 14585 }, { 14586 key: 'hasFluidMode', 14587 value: function hasFluidMode() { 14588 var t = this; 14589 14590 return t.height.toString().indexOf('%') !== -1 || t.node && t.node.style.maxWidth && t.node.style.maxWidth !== 'none' && t.node.style.maxWidth !== t.width || t.node && t.node.currentStyle && t.node.currentStyle.maxWidth === '100%'; 14591 } 14592 }, { 14593 key: 'setResponsiveMode', 14594 value: function setResponsiveMode() { 14595 var t = this, 14596 parent = function () { 14597 var parentEl = void 0, 14598 el = t.getElement(t.container); 14599 14600 while (el) { 14601 try { 14602 if (_constants.IS_FIREFOX && el.tagName.toLowerCase() === 'html' && _window2.default.self !== _window2.default.top && _window2.default.frameElement !== null) { 14603 return _window2.default.frameElement; 14604 } else { 14605 parentEl = el.parentElement; 14606 } 14607 } catch (e) { 14608 parentEl = el.parentElement; 14609 } 14610 14611 if (parentEl && dom.visible(parentEl)) { 14612 return parentEl; 14613 } 14614 el = parentEl; 14615 } 14616 return null; 14617 }(), 14618 parentStyles = parent ? getComputedStyle(parent, null) : getComputedStyle(_document2.default.body, null), 14619 nativeWidth = function () { 14620 if (t.isVideo) { 14621 if (t.node.videoWidth && t.node.videoWidth > 0) { 14622 return t.node.videoWidth; 14623 } else if (t.node.getAttribute('width')) { 14624 return t.node.getAttribute('width'); 14625 } else { 14626 return t.options.defaultVideoWidth; 14627 } 14628 } else { 14629 return t.options.defaultAudioWidth; 14630 } 14631 }(), 14632 nativeHeight = function () { 14633 if (t.isVideo) { 14634 if (t.node.videoHeight && t.node.videoHeight > 0) { 14635 return t.node.videoHeight; 14636 } else if (t.node.getAttribute('height')) { 14637 return t.node.getAttribute('height'); 14638 } else { 14639 return t.options.defaultVideoHeight; 14640 } 14641 } else { 14642 return t.options.defaultAudioHeight; 14643 } 14644 }(), 14645 aspectRatio = function () { 14646 if (!t.options.enableAutosize) { 14647 return t.initialAspectRatio; 14648 } 14649 var ratio = 1; 14650 if (!t.isVideo) { 14651 return ratio; 14652 } 14653 14654 if (t.node.videoWidth && t.node.videoWidth > 0 && t.node.videoHeight && t.node.videoHeight > 0) { 14655 ratio = t.height >= t.width ? t.node.videoWidth / t.node.videoHeight : t.node.videoHeight / t.node.videoWidth; 14656 } else { 14657 ratio = t.initialAspectRatio; 14658 } 14659 14660 if (isNaN(ratio) || ratio < 0.01 || ratio > 100) { 14661 ratio = 1; 14662 } 14663 return ratio; 14664 }(), 14665 parentHeight = parseFloat(parentStyles.height); 14666 14667 var newHeight = void 0, 14668 parentWidth = parseFloat(parentStyles.width); 14669 14670 if (t.isVideo) { 14671 if (t.height === '100%' && t.width === '100%') { 14672 newHeight = parentHeight; 14673 } else if (t.height === '100%') { 14674 newHeight = parseFloat(parentWidth * nativeHeight / nativeWidth, 10); 14675 } else { 14676 newHeight = t.height >= t.width ? parseFloat(parentWidth / aspectRatio, 10) : parseFloat(parentWidth * aspectRatio, 10); 14677 } 14678 } else { 14679 newHeight = nativeHeight; 14680 } 14681 14682 if (newHeight <= t.container.querySelector('.' + t.options.classPrefix + 'inner').offsetHeight) { 14683 newHeight = t.container.querySelector('.' + t.options.classPrefix + 'inner').offsetHeight; 14684 } 14685 14686 if (isNaN(newHeight)) { 14687 newHeight = parentHeight; 14688 } 14689 14690 if (t.getElement(t.container).parentNode.length > 0 && t.getElement(t.container).parentNode.tagName.toLowerCase() === 'body') { 14691 parentWidth = _window2.default.innerWidth || _document2.default.documentElement.clientWidth || _document2.default.body.clientWidth; 14692 newHeight = _window2.default.innerHeight || _document2.default.documentElement.clientHeight || _document2.default.body.clientHeight; 14693 } 14694 14695 if (newHeight && parentWidth) { 14696 t.getElement(t.container).style.width = parentWidth + 'px'; 14697 t.getElement(t.container).style.height = newHeight + 'px'; 14698 14699 t.node.style.width = '100%'; 14700 t.node.style.height = '100%'; 14701 14702 if (t.isVideo && t.media.setSize) { 14703 t.media.setSize(parentWidth, newHeight); 14704 } 14705 14706 if (newHeight <= t.container.querySelector('.' + t.options.classPrefix + 'inner').offsetHeight) { 14707 t.node.style.width = 'auto'; 14708 t.node.style.height = 'auto'; 14709 } 14710 14711 var layerChildren = t.getElement(t.layers).children; 14712 for (var i = 0, total = layerChildren.length; i < total; i++) { 14713 layerChildren[i].style.width = '100%'; 14714 layerChildren[i].style.height = '100%'; 14715 } 14716 } 14717 } 14718 }, { 14719 key: 'setFillMode', 14720 value: function setFillMode() { 14721 var t = this; 14722 var isIframe = _window2.default.self !== _window2.default.top && _window2.default.frameElement !== null; 14723 var parent = function () { 14724 var parentEl = void 0, 14725 el = t.getElement(t.container); 14726 14727 while (el) { 14728 try { 14729 if (_constants.IS_FIREFOX && el.tagName.toLowerCase() === 'html' && _window2.default.self !== _window2.default.top && _window2.default.frameElement !== null) { 14730 return _window2.default.frameElement; 14731 } else { 14732 parentEl = el.parentElement; 14733 } 14734 } catch (e) { 14735 parentEl = el.parentElement; 14736 } 14737 14738 if (parentEl && dom.visible(parentEl)) { 14739 return parentEl; 14740 } 14741 el = parentEl; 14742 } 14743 14744 return null; 14745 }(); 14746 var parentStyles = parent ? getComputedStyle(parent, null) : getComputedStyle(_document2.default.body, null); 14747 14748 if (t.node.style.height !== 'none' && t.node.style.height !== t.height) { 14749 t.node.style.height = 'auto'; 14750 } 14751 if (t.node.style.maxWidth !== 'none' && t.node.style.maxWidth !== t.width) { 14752 t.node.style.maxWidth = 'none'; 14753 } 14754 14755 if (t.node.style.maxHeight !== 'none' && t.node.style.maxHeight !== t.height) { 14756 t.node.style.maxHeight = 'none'; 14757 } 14758 14759 if (t.node.currentStyle) { 14760 if (t.node.currentStyle.height === '100%') { 14761 t.node.currentStyle.height = 'auto'; 14762 } 14763 if (t.node.currentStyle.maxWidth === '100%') { 14764 t.node.currentStyle.maxWidth = 'none'; 14765 } 14766 if (t.node.currentStyle.maxHeight === '100%') { 14767 t.node.currentStyle.maxHeight = 'none'; 14768 } 14769 } 14770 14771 if (!isIframe && !parseFloat(parentStyles.width)) { 14772 parent.style.width = t.media.offsetWidth + 'px'; 14773 } 14774 14775 if (!isIframe && !parseFloat(parentStyles.height)) { 14776 parent.style.height = t.media.offsetHeight + 'px'; 14777 } 14778 14779 parentStyles = getComputedStyle(parent); 14780 14781 var parentWidth = parseFloat(parentStyles.width), 14782 parentHeight = parseFloat(parentStyles.height); 14783 t.setDimensions('100%', '100%'); 14784 14785 var poster = t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'poster>img'); 14786 if (poster) { 14787 poster.style.display = ''; 14788 } 14789 14790 var targetElement = t.getElement(t.container).querySelectorAll('object, embed, iframe, video'), 14791 initHeight = parseFloat(t.height, 10), 14792 initWidth = parseFloat(t.width, 10), 14793 scaleX1 = parentWidth, 14794 scaleY1 = initHeight * parentWidth / initWidth, 14795 scaleX2 = initWidth * parentHeight / initHeight, 14796 scaleY2 = parentHeight, 14797 bScaleOnWidth = scaleX2 > parentWidth === false, 14798 finalWidth = bScaleOnWidth ? Math.floor(scaleX1) : Math.floor(scaleX2), 14799 finalHeight = bScaleOnWidth ? Math.floor(scaleY1) : Math.floor(scaleY2), 14800 width = bScaleOnWidth ? parentWidth + 'px' : finalWidth + 'px', 14801 height = bScaleOnWidth ? finalHeight + 'px' : parentHeight + 'px'; 14802 14803 for (var i = 0, total = targetElement.length; i < total; i++) { 14804 targetElement[i].style.height = height; 14805 targetElement[i].style.width = width; 14806 if (t.media.setSize) { 14807 t.media.setSize(width, height); 14808 } 14809 14810 targetElement[i].style.marginLeft = Math.floor((parentWidth - finalWidth) / 2) + 'px'; 14811 targetElement[i].style.marginTop = 0; 14812 } 14813 } 14814 }, { 14815 key: 'setDimensions', 14816 value: function setDimensions(width, height) { 14817 var t = this; 14818 14819 width = (0, _general.isString)(width) && width.indexOf('%') > -1 ? width : parseFloat(width) + 'px'; 14820 height = (0, _general.isString)(height) && height.indexOf('%') > -1 ? height : parseFloat(height) + 'px'; 14821 14822 t.getElement(t.container).style.width = width; 14823 t.getElement(t.container).style.height = height;
vendor: 51,091 bytes, lines 14823-16701
14823 14824 14825 var layers = t.getElement(t.layers).children; 14826 for (var i = 0, total = layers.length; i < total; i++) { 14827 layers[i].style.width = width; 14828 layers[i].style.height = height; 14829 } 14830 } 14831 }, { 14832 key: 'setControlsSize', 14833 value: function setControlsSize() { 14834 var t = this; 14835 14836 if (!dom.visible(t.getElement(t.container))) { 14837 return; 14838 } 14839 14840 if (!(t.rail && dom.visible(t.rail))) { 14841 var children = t.getElement(t.controls).children; 14842 var minWidth = 0; 14843 14844 for (var i = 0, total = children.length; i < total; i++) { 14845 minWidth += children[i].offsetWidth; 14846 } 14847 14848 t.getElement(t.container).style.minWidth = minWidth + 'px'; 14849 } 14850 } 14851 }, { 14852 key: 'addControlElement', 14853 value: function addControlElement(element, key) { 14854 var t = this; 14855 14856 if (t.featurePosition[key] !== undefined) { 14857 var child = t.getElement(t.controls).children[t.featurePosition[key] - 1]; 14858 child.parentNode.insertBefore(element, child.nextSibling); 14859 } else { 14860 t.getElement(t.controls).appendChild(element); 14861 var children = t.getElement(t.controls).children; 14862 for (var i = 0, total = children.length; i < total; i++) { 14863 if (element === children[i]) { 14864 t.featurePosition[key] = i; 14865 break; 14866 } 14867 } 14868 } 14869 } 14870 }, { 14871 key: 'createIframeLayer', 14872 value: function createIframeLayer() { 14873 var t = this; 14874 14875 if (t.isVideo && t.media.rendererName !== null && t.media.rendererName.indexOf('iframe') > -1 && !_document2.default.getElementById(t.media.id + '-iframe-overlay')) { 14876 14877 var layer = _document2.default.createElement('div'), 14878 target = _document2.default.getElementById(t.media.id + '_' + t.media.rendererName); 14879 14880 layer.id = t.media.id + '-iframe-overlay'; 14881 layer.className = t.options.classPrefix + 'iframe-overlay'; 14882 layer.addEventListener('click', function (e) { 14883 if (t.options.clickToPlayPause) { 14884 if (t.paused) { 14885 t.play(); 14886 } else { 14887 t.pause(); 14888 } 14889 14890 e.preventDefault(); 14891 e.stopPropagation(); 14892 } 14893 }); 14894 14895 target.parentNode.insertBefore(layer, target); 14896 } 14897 } 14898 }, { 14899 key: 'resetSize', 14900 value: function resetSize() { 14901 var t = this; 14902 14903 setTimeout(function () { 14904 t.setPlayerSize(t.width, t.height); 14905 t.setControlsSize(); 14906 }, 50); 14907 } 14908 }, { 14909 key: 'setPoster', 14910 value: function setPoster(url) { 14911 var t = this; 14912 14913 if (t.getElement(t.container)) { 14914 var posterDiv = t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'poster'); 14915 14916 if (!posterDiv) { 14917 posterDiv = _document2.default.createElement('div'); 14918 posterDiv.className = t.options.classPrefix + 'poster ' + t.options.classPrefix + 'layer'; 14919 t.getElement(t.layers).appendChild(posterDiv); 14920 } 14921 14922 var posterImg = posterDiv.querySelector('img'); 14923 14924 if (!posterImg && url) { 14925 posterImg = _document2.default.createElement('img'); 14926 posterImg.alt = ''; 14927 posterImg.className = t.options.classPrefix + 'poster-img'; 14928 posterImg.width = '100%'; 14929 posterImg.height = '100%'; 14930 posterDiv.style.display = ''; 14931 posterDiv.appendChild(posterImg); 14932 } 14933 14934 if (url) { 14935 posterImg.setAttribute('src', url); 14936 posterDiv.style.backgroundImage = 'url("' + url + '")'; 14937 posterDiv.style.display = ''; 14938 } else if (posterImg) { 14939 posterDiv.style.backgroundImage = 'none'; 14940 posterDiv.style.display = 'none'; 14941 posterImg.remove(); 14942 } else { 14943 posterDiv.style.display = 'none'; 14944 } 14945 } else if (_constants.IS_IPAD && t.options.iPadUseNativeControls || _constants.IS_IPHONE && t.options.iPhoneUseNativeControls || _constants.IS_ANDROID && t.options.AndroidUseNativeControls) { 14946 t.media.originalNode.poster = url; 14947 } 14948 } 14949 }, { 14950 key: 'changeSkin', 14951 value: function changeSkin(className) { 14952 var t = this; 14953 14954 t.getElement(t.container).className = t.options.classPrefix + 'container ' + className; 14955 t.setPlayerSize(t.width, t.height); 14956 t.setControlsSize(); 14957 } 14958 }, { 14959 key: 'globalBind', 14960 value: function globalBind(events, callback) { 14961 var t = this, 14962 doc = t.node ? t.node.ownerDocument : _document2.default; 14963 14964 events = (0, _general.splitEvents)(events, t.id); 14965 if (events.d) { 14966 var eventList = events.d.split(' '); 14967 for (var i = 0, total = eventList.length; i < total; i++) { 14968 eventList[i].split('.').reduce(function (part, e) { 14969 doc.addEventListener(e, callback, false); 14970 return e; 14971 }, ''); 14972 } 14973 } 14974 if (events.w) { 14975 var _eventList = events.w.split(' '); 14976 for (var _i = 0, _total = _eventList.length; _i < _total; _i++) { 14977 _eventList[_i].split('.').reduce(function (part, e) { 14978 _window2.default.addEventListener(e, callback, false); 14979 return e; 14980 }, ''); 14981 } 14982 } 14983 } 14984 }, { 14985 key: 'globalUnbind', 14986 value: function globalUnbind(events, callback) { 14987 var t = this, 14988 doc = t.node ? t.node.ownerDocument : _document2.default; 14989 14990 events = (0, _general.splitEvents)(events, t.id); 14991 if (events.d) { 14992 var eventList = events.d.split(' '); 14993 for (var i = 0, total = eventList.length; i < total; i++) { 14994 eventList[i].split('.').reduce(function (part, e) { 14995 doc.removeEventListener(e, callback, false); 14996 return e; 14997 }, ''); 14998 } 14999 } 15000 if (events.w) { 15001 var _eventList2 = events.w.split(' '); 15002 for (var _i2 = 0, _total2 = _eventList2.length; _i2 < _total2; _i2++) { 15003 _eventList2[_i2].split('.').reduce(function (part, e) { 15004 _window2.default.removeEventListener(e, callback, false); 15005 return e; 15006 }, ''); 15007 } 15008 } 15009 } 15010 }, { 15011 key: 'buildfeatures', 15012 value: function buildfeatures(player, controls, layers, media) { 15013 var t = this; 15014 15015 for (var i = 0, total = t.options.features.length; i < total; i++) { 15016 var feature = t.options.features[i]; 15017 if (t['build' + feature]) { 15018 try { 15019 t['build' + feature](player, controls, layers, media); 15020 } catch (e) { 15021 console.error('error building ' + feature, e); 15022 } 15023 } 15024 } 15025 } 15026 }, { 15027 key: 'buildposter', 15028 value: function buildposter(player, controls, layers, media) { 15029 var t = this, 15030 poster = _document2.default.createElement('div'); 15031 15032 poster.className = t.options.classPrefix + 'poster ' + t.options.classPrefix + 'layer'; 15033 layers.appendChild(poster); 15034 15035 var posterUrl = media.originalNode.getAttribute('poster'); 15036 15037 if (player.options.poster !== '') { 15038 if (posterUrl && _constants.IS_IOS) { 15039 media.originalNode.removeAttribute('poster'); 15040 } 15041 posterUrl = player.options.poster; 15042 } 15043 15044 if (posterUrl) { 15045 t.setPoster(posterUrl); 15046 } else if (t.media.renderer !== null && typeof t.media.renderer.getPosterUrl === 'function') { 15047 t.setPoster(t.media.renderer.getPosterUrl()); 15048 } else { 15049 poster.style.display = 'none'; 15050 } 15051 15052 media.addEventListener('play', function () { 15053 poster.style.display = 'none'; 15054 }); 15055 15056 media.addEventListener('playing', function () { 15057 poster.style.display = 'none'; 15058 }); 15059 15060 if (player.options.showPosterWhenEnded && player.options.autoRewind) { 15061 media.addEventListener('ended', function () { 15062 poster.style.display = ''; 15063 }); 15064 } 15065 15066 media.addEventListener('error', function () { 15067 poster.style.display = 'none'; 15068 }); 15069 15070 if (player.options.showPosterWhenPaused) { 15071 media.addEventListener('pause', function () { 15072 if (!player.ended) { 15073 poster.style.display = ''; 15074 } 15075 }); 15076 } 15077 } 15078 }, { 15079 key: 'buildoverlays', 15080 value: function buildoverlays(player, controls, layers, media) { 15081 if (!player.isVideo) { 15082 return; 15083 } 15084 15085 var t = this, 15086 loading = _document2.default.createElement('div'), 15087 error = _document2.default.createElement('div'), 15088 bigPlay = _document2.default.createElement('div'); 15089 15090 loading.style.display = 'none'; 15091 loading.className = t.options.classPrefix + 'overlay ' + t.options.classPrefix + 'layer'; 15092 loading.innerHTML = '<div class="' + t.options.classPrefix + 'overlay-loading">' + ('<div class="' + t.options.classPrefix + 'overlay-loading-bg-img">\n\t\t\t\t\t<svg xmlns="http://www.w3.org/2000/svg">\n\t\t\t\t\t\t<use xlink:href="' + t.media.options.iconSprite + '#icon-loading-spinner"></use>\n\t\t\t\t\t</svg>\n\t\t\t\t</div>') + '</div>'; 15093 layers.appendChild(loading); 15094 15095 error.style.display = 'none'; 15096 error.className = t.options.classPrefix + 'overlay ' + t.options.classPrefix + 'layer'; 15097 error.innerHTML = '<div class="' + t.options.classPrefix + 'overlay-error"></div>'; 15098 layers.appendChild(error); 15099 15100 bigPlay.className = t.options.classPrefix + 'overlay ' + t.options.classPrefix + 'layer ' + t.options.classPrefix + 'overlay-play'; 15101 bigPlay.innerHTML = (0, _generate.generateControlButton)(t.id, _i18n2.default.t('mejs.play'), _i18n2.default.t('mejs.play'), '' + t.media.options.iconSprite, ['icon-overlay-play'], '' + t.options.classPrefix, t.options.classPrefix + 'overlay-button', '', false); 15102 15103 bigPlay.addEventListener('click', function () { 15104 if (t.options.clickToPlayPause) { 15105 15106 var button = t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'overlay-button'), 15107 pressed = button.getAttribute('aria-pressed'); 15108 15109 if (t.paused) { 15110 t.play(); 15111 } else { 15112 t.pause(); 15113 } 15114 15115 button.setAttribute('aria-pressed', !!pressed); 15116 t.getElement(t.container).focus(); 15117 } 15118 }); 15119 15120 layers.appendChild(bigPlay); 15121 15122 if (t.media.rendererName !== null && (/(youtube|facebook)/i.test(t.media.rendererName) && !(t.media.originalNode.getAttribute('poster') || player.options.poster || typeof t.media.renderer.getPosterUrl === 'function' && t.media.renderer.getPosterUrl()) || _constants.IS_STOCK_ANDROID || t.media.originalNode.getAttribute('autoplay'))) { 15123 bigPlay.style.display = 'none'; 15124 } 15125 15126 var hasError = false; 15127 15128 media.addEventListener('play', function () { 15129 bigPlay.style.display = 'none'; 15130 loading.style.display = 'none'; 15131 error.style.display = 'none'; 15132 hasError = false; 15133 }); 15134 media.addEventListener('playing', function () { 15135 bigPlay.style.display = 'none'; 15136 loading.style.display = 'none'; 15137 error.style.display = 'none'; 15138 hasError = false; 15139 }); 15140 media.addEventListener('seeking', function () { 15141 bigPlay.style.display = 'none'; 15142 loading.style.display = ''; 15143 hasError = false; 15144 }); 15145 media.addEventListener('seeked', function () { 15146 bigPlay.style.display = t.paused && !_constants.IS_STOCK_ANDROID ? '' : 'none'; 15147 loading.style.display = 'none'; 15148 hasError = false; 15149 }); 15150 media.addEventListener('pause', function () { 15151 loading.style.display = 'none'; 15152 if (!_constants.IS_STOCK_ANDROID && !hasError) { 15153 bigPlay.style.display = ''; 15154 } 15155 hasError = false; 15156 }); 15157 media.addEventListener('waiting', function () { 15158 loading.style.display = ''; 15159 hasError = false; 15160 }); 15161 15162 media.addEventListener('loadeddata', function () { 15163 loading.style.display = ''; 15164 15165 if (_constants.IS_ANDROID) { 15166 media.canplayTimeout = setTimeout(function () { 15167 if (_document2.default.createEvent) { 15168 var evt = _document2.default.createEvent('HTMLEvents'); 15169 evt.initEvent('canplay', true, true); 15170 return media.dispatchEvent(evt); 15171 } 15172 }, 300); 15173 } 15174 hasError = false; 15175 }); 15176 media.addEventListener('canplay', function () { 15177 loading.style.display = 'none'; 15178 15179 clearTimeout(media.canplayTimeout); 15180 hasError = false; 15181 }); 15182 15183 media.addEventListener('error', function (e) { 15184 t._handleError(e, t.media, t.node); 15185 loading.style.display = 'none'; 15186 bigPlay.style.display = 'none'; 15187 hasError = true; 15188 }); 15189 15190 media.addEventListener('loadedmetadata', function () { 15191 if (!t.controlsEnabled) { 15192 t.enableControls(); 15193 } 15194 }); 15195 15196 media.addEventListener('keydown', function (e) { 15197 t.onkeydown(player, media, e); 15198 hasError = false; 15199 }); 15200 } 15201 }, { 15202 key: 'buildkeyboard', 15203 value: function buildkeyboard(player, controls, layers, media) { 15204 var t = this; 15205 15206 t.getElement(t.container).addEventListener('keydown', function () { 15207 t.keyboardAction = true; 15208 }); 15209 15210 t.globalKeydownCallback = function (event) { 15211 if (!_document2.default.activeElement) { 15212 return true; 15213 } 15214 15215 var container = _document2.default.activeElement.closest('.' + t.options.classPrefix + 'container'), 15216 target = t.media.closest('.' + t.options.classPrefix + 'container'); 15217 t.hasFocus = !!(container && target && container.id === target.id); 15218 return t.onkeydown(player, media, event); 15219 }; 15220 15221 t.globalClickCallback = function (event) { 15222 t.hasFocus = !!event.target.closest('.' + t.options.classPrefix + 'container'); 15223 }; 15224 15225 t.globalBind('keydown', t.globalKeydownCallback); 15226 15227 t.globalBind('click', t.globalClickCallback); 15228 } 15229 }, { 15230 key: 'onkeydown', 15231 value: function onkeydown(player, media, e) { 15232 if (player.hasFocus && player.options.enableKeyboard) { 15233 for (var i = 0, total = player.options.keyActions.length; i < total; i++) { 15234 var keyAction = player.options.keyActions[i]; 15235 15236 for (var j = 0, jl = keyAction.keys.length; j < jl; j++) { 15237 if (e.keyCode === keyAction.keys[j]) { 15238 keyAction.action(player, media, e.keyCode, e); 15239 e.preventDefault(); 15240 e.stopPropagation(); 15241 return; 15242 } 15243 } 15244 } 15245 } 15246 15247 return true; 15248 } 15249 }, { 15250 key: 'play', 15251 value: function play() { 15252 return this.proxy.play(); 15253 } 15254 }, { 15255 key: 'pause', 15256 value: function pause() { 15257 return this.proxy.pause(); 15258 } 15259 }, { 15260 key: 'load', 15261 value: function load() { 15262 return this.proxy.load(); 15263 } 15264 }, { 15265 key: 'setCurrentTime', 15266 value: function setCurrentTime(time) { 15267 var userInteraction = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; 15268 15269 this.seekUserInteraction = userInteraction; 15270 this.proxy.setCurrentTime(time); 15271 } 15272 }, { 15273 key: 'getCurrentTime', 15274 value: function getCurrentTime() { 15275 return this.proxy.currentTime; 15276 } 15277 }, { 15278 key: 'getDuration', 15279 value: function getDuration() { 15280 return this.proxy.duration; 15281 } 15282 }, { 15283 key: 'setVolume', 15284 value: function setVolume(volume) { 15285 this.proxy.volume = volume; 15286 } 15287 }, { 15288 key: 'getVolume', 15289 value: function getVolume() { 15290 return this.proxy.getVolume(); 15291 } 15292 }, { 15293 key: 'setMuted', 15294 value: function setMuted(value) { 15295 this.proxy.setMuted(value); 15296 } 15297 }, { 15298 key: 'setSrc', 15299 value: function setSrc(src) { 15300 if (!this.controlsEnabled) { 15301 this.enableControls(); 15302 } 15303 this.proxy.setSrc(src); 15304 } 15305 }, { 15306 key: 'getSrc', 15307 value: function getSrc() { 15308 return this.proxy.getSrc(); 15309 } 15310 }, { 15311 key: 'canPlayType', 15312 value: function canPlayType(type) { 15313 return this.proxy.canPlayType(type); 15314 } 15315 }, { 15316 key: 'remove', 15317 value: function remove() { 15318 var t = this, 15319 rendererName = t.media.rendererName, 15320 src = t.media.originalNode.src; 15321 15322 for (var featureIndex in t.options.features) { 15323 var feature = t.options.features[featureIndex]; 15324 if (t['clean' + feature]) { 15325 try { 15326 t['clean' + feature](t, t.getElement(t.layers), t.getElement(t.controls), t.media); 15327 } catch (e) { 15328 console.error('error cleaning ' + feature, e); 15329 } 15330 } 15331 } 15332 15333 var nativeWidth = t.node.getAttribute('width'), 15334 nativeHeight = t.node.getAttribute('height'); 15335 15336 if (nativeWidth) { 15337 if (nativeWidth.indexOf('%') === -1) { 15338 nativeWidth = nativeWidth + 'px'; 15339 } 15340 } else { 15341 nativeWidth = 'auto'; 15342 } 15343 15344 if (nativeHeight) { 15345 if (nativeHeight.indexOf('%') === -1) { 15346 nativeHeight = nativeHeight + 'px'; 15347 } 15348 } else { 15349 nativeHeight = 'auto'; 15350 } 15351 15352 t.node.style.width = nativeWidth; 15353 t.node.style.height = nativeHeight; 15354 15355 t.setPlayerSize(0, 0); 15356 15357 if (!t.isDynamic) { 15358 (function () { 15359 t.node.setAttribute('controls', true); 15360 t.node.setAttribute('id', t.node.getAttribute('id').replace('_' + rendererName, '').replace('_from_mejs', '')); 15361 var poster = t.getElement(t.container).querySelector('.' + t.options.classPrefix + 'poster>img'); 15362 if (poster) { 15363 t.node.setAttribute('poster', poster.src); 15364 } 15365 15366 delete t.node.autoplay; 15367 15368 t.node.setAttribute('src', ''); 15369 if (t.media.canPlayType((0, _media.getTypeFromFile)(src)) !== '') { 15370 t.node.setAttribute('src', src); 15371 } 15372 15373 if (rendererName && rendererName.indexOf('iframe') > -1) { 15374 var layer = _document2.default.getElementById(t.media.id + '-iframe-overlay'); 15375 layer.remove(); 15376 } 15377 15378 var node = t.node.cloneNode(); 15379 node.style.display = ''; 15380 t.getElement(t.container).parentNode.insertBefore(node, t.getElement(t.container)); 15381 t.node.remove(); 15382 15383 if (t.mediaFiles) { 15384 for (var i = 0, total = t.mediaFiles.length; i < total; i++) { 15385 var source = _document2.default.createElement('source'); 15386 source.setAttribute('src', t.mediaFiles[i].src); 15387 source.setAttribute('type', t.mediaFiles[i].type); 15388 node.appendChild(source); 15389 } 15390 } 15391 if (t.trackFiles) { 15392 var _loop3 = function _loop3(_i3, _total3) { 15393 var track = t.trackFiles[_i3]; 15394 var newTrack = _document2.default.createElement('track'); 15395 newTrack.kind = track.kind; 15396 newTrack.label = track.label; 15397 newTrack.srclang = track.srclang; 15398 newTrack.src = track.src; 15399 15400 node.appendChild(newTrack); 15401 newTrack.addEventListener('load', function () { 15402 this.mode = 'showing'; 15403 node.textTracks[_i3].mode = 'showing'; 15404 }); 15405 }; 15406 15407 for (var _i3 = 0, _total3 = t.trackFiles.length; _i3 < _total3; _i3++) { 15408 _loop3(_i3, _total3); 15409 } 15410 } 15411 15412 delete t.node; 15413 delete t.mediaFiles; 15414 delete t.trackFiles; 15415 })(); 15416 } else { 15417 t.getElement(t.container).parentNode.insertBefore(t.node, t.getElement(t.container)); 15418 } 15419 15420 if (t.media.renderer && typeof t.media.renderer.destroy === 'function') { 15421 t.media.renderer.destroy(); 15422 } 15423 15424 if (_typeof(t.getElement(t.container)) === 'object') { 15425 var offscreen = t.getElement(t.container).parentNode.querySelector('.' + t.options.classPrefix + 'offscreen'); 15426 if (offscreen) { 15427 offscreen.remove(); 15428 } 15429 t.getElement(t.container).remove(); 15430 } 15431 t.globalUnbind('resize', t.globalResizeCallback); 15432 t.globalUnbind('keydown', t.globalKeydownCallback); 15433 t.globalUnbind('click', t.globalClickCallback); 15434 15435 delete t.media.player; 15436 } 15437 }, { 15438 key: 'paused', 15439 get: function get() { 15440 return this.proxy.paused; 15441 } 15442 }, { 15443 key: 'muted', 15444 get: function get() { 15445 return this.proxy.muted; 15446 }, 15447 set: function set(muted) { 15448 this.setMuted(muted); 15449 } 15450 }, { 15451 key: 'ended', 15452 get: function get() { 15453 return this.proxy.ended; 15454 } 15455 }, { 15456 key: 'readyState', 15457 get: function get() { 15458 return this.proxy.readyState; 15459 } 15460 }, { 15461 key: 'currentTime', 15462 set: function set(time) { 15463 this.setCurrentTime(time); 15464 }, 15465 get: function get() { 15466 return this.getCurrentTime(); 15467 } 15468 }, { 15469 key: 'duration', 15470 get: function get() { 15471 return this.getDuration(); 15472 } 15473 }, { 15474 key: 'volume', 15475 set: function set(volume) { 15476 this.setVolume(volume); 15477 }, 15478 get: function get() { 15479 return this.getVolume(); 15480 } 15481 }, { 15482 key: 'src', 15483 set: function set(src) { 15484 this.setSrc(src); 15485 }, 15486 get: function get() { 15487 return this.getSrc(); 15488 } 15489 }]); 15490 15491 return MediaElementPlayer; 15492}(); 15493 15494_window2.default.MediaElementPlayer = MediaElementPlayer; 15495_mejs2.default.MediaElementPlayer = MediaElementPlayer; 15496 15497exports.default = MediaElementPlayer; 15498 15499},{"18":18,"2":2,"24":24,"25":25,"26":26,"27":27,"28":28,"3":3,"30":30,"6":6,"7":7,"8":8}],18:[function(_dereq_,module,exports){ 15500'use strict'; 15501 15502Object.defineProperty(exports, "__esModule", { 15503 value: true 15504}); 15505 15506var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 15507 15508var _window = _dereq_(3); 15509 15510var _window2 = _interopRequireDefault(_window); 15511 15512function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 15513 15514function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 15515 15516var DefaultPlayer = function () { 15517 function DefaultPlayer(player) { 15518 _classCallCheck(this, DefaultPlayer); 15519 15520 this.media = player.media; 15521 this.isVideo = player.isVideo; 15522 this.classPrefix = player.options.classPrefix; 15523 this.createIframeLayer = function () { 15524 return player.createIframeLayer(); 15525 }; 15526 this.setPoster = function (url) { 15527 return player.setPoster(url); 15528 }; 15529 return this; 15530 } 15531 15532 _createClass(DefaultPlayer, [{ 15533 key: 'play', 15534 value: function play() { 15535 return this.media.play(); 15536 } 15537 }, { 15538 key: 'pause', 15539 value: function pause() { 15540 return this.media.pause(); 15541 } 15542 }, { 15543 key: 'load', 15544 value: function load() { 15545 var t = this; 15546 15547 if (!t.isLoaded) { 15548 t.media.load(); 15549 } 15550 15551 t.isLoaded = true; 15552 } 15553 }, { 15554 key: 'setCurrentTime', 15555 value: function setCurrentTime(time) { 15556 this.media.setCurrentTime(time); 15557 } 15558 }, { 15559 key: 'getCurrentTime', 15560 value: function getCurrentTime() { 15561 return this.media.currentTime; 15562 } 15563 }, { 15564 key: 'getDuration', 15565 value: function getDuration() { 15566 var duration = this.media.getDuration(); 15567 if (duration === Infinity && this.media.seekable && this.media.seekable.length) { 15568 duration = this.media.seekable.end(0); 15569 } 15570 return duration; 15571 } 15572 }, { 15573 key: 'setVolume', 15574 value: function setVolume(volume) { 15575 this.media.setVolume(volume); 15576 } 15577 }, { 15578 key: 'getVolume', 15579 value: function getVolume() { 15580 return this.media.getVolume(); 15581 } 15582 }, { 15583 key: 'setMuted', 15584 value: function setMuted(value) { 15585 this.media.setMuted(value); 15586 } 15587 }, { 15588 key: 'setSrc', 15589 value: function setSrc(src) { 15590 var t = this, 15591 layer = document.getElementById(t.media.id + '-iframe-overlay'); 15592 15593 if (layer) { 15594 layer.remove(); 15595 } 15596 15597 t.media.setSrc(src); 15598 t.createIframeLayer(); 15599 if (t.media.renderer !== null && typeof t.media.renderer.getPosterUrl === 'function') { 15600 t.setPoster(t.media.renderer.getPosterUrl()); 15601 } 15602 } 15603 }, { 15604 key: 'getSrc', 15605 value: function getSrc() { 15606 return this.media.getSrc(); 15607 } 15608 }, { 15609 key: 'canPlayType', 15610 value: function canPlayType(type) { 15611 return this.media.canPlayType(type); 15612 } 15613 }, { 15614 key: 'paused', 15615 get: function get() { 15616 return this.media.paused; 15617 } 15618 }, { 15619 key: 'muted', 15620 set: function set(muted) { 15621 this.setMuted(muted); 15622 }, 15623 get: function get() { 15624 return this.media.muted; 15625 } 15626 }, { 15627 key: 'ended', 15628 get: function get() { 15629 return this.media.ended; 15630 } 15631 }, { 15632 key: 'readyState', 15633 get: function get() { 15634 return this.media.readyState; 15635 } 15636 }, { 15637 key: 'currentTime', 15638 set: function set(time) { 15639 this.setCurrentTime(time); 15640 }, 15641 get: function get() { 15642 return this.getCurrentTime(); 15643 } 15644 }, { 15645 key: 'duration', 15646 get: function get() { 15647 return this.getDuration(); 15648 } 15649 }, { 15650 key: 'remainingTime', 15651 get: function get() { 15652 return this.getDuration() - this.currentTime(); 15653 } 15654 }, { 15655 key: 'volume', 15656 set: function set(volume) { 15657 this.setVolume(volume); 15658 }, 15659 get: function get() { 15660 return this.getVolume(); 15661 } 15662 }, { 15663 key: 'src', 15664 set: function set(src) { 15665 this.setSrc(src); 15666 }, 15667 get: function get() { 15668 return this.getSrc(); 15669 } 15670 }]); 15671 15672 return DefaultPlayer; 15673}(); 15674 15675exports.default = DefaultPlayer; 15676 15677 15678_window2.default.DefaultPlayer = DefaultPlayer; 15679 15680},{"3":3}],19:[function(_dereq_,module,exports){ 15681'use strict'; 15682 15683var _window = _dereq_(3); 15684 15685var _window2 = _interopRequireDefault(_window); 15686 15687var _mejs = _dereq_(8); 15688 15689var _mejs2 = _interopRequireDefault(_mejs); 15690 15691var _player = _dereq_(17); 15692 15693var _player2 = _interopRequireDefault(_player); 15694 15695function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 15696 15697if (typeof jQuery !== 'undefined') { 15698 _mejs2.default.$ = jQuery; 15699} else if (typeof Zepto !== 'undefined') { 15700 _mejs2.default.$ = Zepto; 15701} else if (typeof ender !== 'undefined') { 15702 _mejs2.default.$ = ender; 15703} 15704 15705(function ($) { 15706 if (typeof $ !== 'undefined') { 15707 $.fn.mediaelementplayer = function (options) { 15708 if (options === false) { 15709 this.each(function () { 15710 var player = $(this).data('mediaelementplayer'); 15711 if (player) { 15712 player.remove(); 15713 } 15714 $(this).removeData('mediaelementplayer'); 15715 }); 15716 } else { 15717 this.each(function () { 15718 $(this).data('mediaelementplayer', new _player2.default(this, options)); 15719 }); 15720 } 15721 return this; 15722 }; 15723 15724 $(document).ready(function () { 15725 $('.' + _mejs2.default.MepDefaults.classPrefix + 'player').mediaelementplayer(); 15726 }); 15727 } 15728})(_mejs2.default.$); 15729 15730},{"17":17,"3":3,"8":8}],20:[function(_dereq_,module,exports){ 15731'use strict'; 15732 15733var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 15734 15735var _window = _dereq_(3); 15736 15737var _window2 = _interopRequireDefault(_window); 15738 15739var _mejs = _dereq_(8); 15740 15741var _mejs2 = _interopRequireDefault(_mejs); 15742 15743var _renderer = _dereq_(9); 15744 15745var _general = _dereq_(26); 15746 15747var _media = _dereq_(28); 15748 15749var _constants = _dereq_(24); 15750 15751var _dom = _dereq_(25); 15752 15753function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 15754 15755var NativeDash = { 15756 15757 promise: null, 15758 15759 load: function load(settings) { 15760 if (typeof dashjs !== 'undefined') { 15761 NativeDash.promise = new Promise(function (resolve) { 15762 resolve(); 15763 }).then(function () { 15764 NativeDash._createPlayer(settings); 15765 }); 15766 } else { 15767 settings.options.path = typeof settings.options.path === 'string' ? settings.options.path : 'https://cdn.dashjs.org/latest/dash.all.min.js'; 15768 15769 NativeDash.promise = NativeDash.promise || (0, _dom.loadScript)(settings.options.path); 15770 NativeDash.promise.then(function () { 15771 NativeDash._createPlayer(settings); 15772 }); 15773 } 15774 15775 return NativeDash.promise; 15776 }, 15777 15778 _createPlayer: function _createPlayer(settings) { 15779 var player = dashjs.MediaPlayer().create(); 15780 _window2.default['__ready__' + settings.id](player); 15781 return player; 15782 } 15783}; 15784 15785var DashNativeRenderer = { 15786 name: 'native_dash', 15787 options: { 15788 prefix: 'native_dash', 15789 dash: { 15790 path: 'https://cdn.dashjs.org/latest/dash.all.min.js', 15791 debug: false, 15792 drm: {}, 15793 15794 robustnessLevel: '' 15795 } 15796 }, 15797 15798 canPlayType: function canPlayType(type) { 15799 return _constants.HAS_MSE && ['application/dash+xml'].indexOf(type.toLowerCase()) > -1; 15800 }, 15801 15802 create: function create(mediaElement, options, mediaFiles) { 15803 15804 var originalNode = mediaElement.originalNode, 15805 id = mediaElement.id + '_' + options.prefix, 15806 autoplay = originalNode.autoplay, 15807 children = originalNode.children; 15808 15809 var node = null, 15810 dashPlayer = null; 15811 15812 originalNode.removeAttribute('type'); 15813 for (var i = 0, total = children.length; i < total; i++) { 15814 children[i].removeAttribute('type'); 15815 } 15816 15817 node = originalNode.cloneNode(true); 15818 options = Object.assign(options, mediaElement.options); 15819 15820 var props = _mejs2.default.html5media.properties, 15821 events = _mejs2.default.html5media.events.concat(['click', 'mouseover', 'mouseout']).filter(function (e) { 15822 return e !== 'error'; 15823 }), 15824 attachNativeEvents = function attachNativeEvents(e) { 15825 var event = (0, _general.createEvent)(e.type, mediaElement); 15826 mediaElement.dispatchEvent(event); 15827 }, 15828 assignGettersSetters = function assignGettersSetters(propName) { 15829 var capName = '' + propName.substring(0, 1).toUpperCase() + propName.substring(1); 15830 15831 node['get' + capName] = function () { 15832 return dashPlayer !== null ? node[propName] : null; 15833 }; 15834 15835 node['set' + capName] = function (value) { 15836 if (_mejs2.default.html5media.readOnlyProperties.indexOf(propName) === -1) { 15837 if (propName === 'src') { 15838 var source = (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && value.src ? value.src : value; 15839 node[propName] = source; 15840 if (dashPlayer !== null) { 15841 dashPlayer.reset(); 15842 for (var _i = 0, _total = events.length; _i < _total; _i++) { 15843 node.removeEventListener(events[_i], attachNativeEvents); 15844 } 15845 dashPlayer = NativeDash._createPlayer({ 15846 options: options.dash, 15847 id: id 15848 }); 15849 15850 if (value && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && _typeof(value.drm) === 'object') { 15851 dashPlayer.setProtectionData(value.drm); 15852 if ((0, _general.isString)(options.dash.robustnessLevel) && options.dash.robustnessLevel) { 15853 dashPlayer.getProtectionController().setRobustnessLevel(options.dash.robustnessLevel); 15854 } 15855 } 15856 dashPlayer.attachSource(source); 15857 if (autoplay) { 15858 dashPlayer.play(); 15859 } 15860 } 15861 } else { 15862 node[propName] = value; 15863 } 15864 } 15865 }; 15866 }; 15867 15868 for (var _i2 = 0, _total2 = props.length; _i2 < _total2; _i2++) { 15869 assignGettersSetters(props[_i2]); 15870 } 15871 15872 _window2.default['__ready__' + id] = function (_dashPlayer) { 15873 mediaElement.dashPlayer = dashPlayer = _dashPlayer; 15874 15875 var dashEvents = dashjs.MediaPlayer.events, 15876 assignEvents = function assignEvents(eventName) { 15877 if (eventName === 'loadedmetadata') { 15878 dashPlayer.initialize(); 15879 dashPlayer.attachView(node); 15880 dashPlayer.setAutoPlay(false); 15881 15882 if (_typeof(options.dash.drm) === 'object' && !_mejs2.default.Utils.isObjectEmpty(options.dash.drm)) { 15883 dashPlayer.setProtectionData(options.dash.drm); 15884 if ((0, _general.isString)(options.dash.robustnessLevel) && options.dash.robustnessLevel) { 15885 dashPlayer.getProtectionController().setRobustnessLevel(options.dash.robustnessLevel); 15886 } 15887 } 15888 dashPlayer.attachSource(node.getSrc()); 15889 } 15890 15891 node.addEventListener(eventName, attachNativeEvents); 15892 }; 15893 15894 for (var _i3 = 0, _total3 = events.length; _i3 < _total3; _i3++) { 15895 assignEvents(events[_i3]); 15896 } 15897 15898 var assignMdashEvents = function assignMdashEvents(e) { 15899 if (e.type.toLowerCase() === 'error') { 15900 mediaElement.generateError(e.message, node.src); 15901 console.error(e); 15902 } else { 15903 var _event = (0, _general.createEvent)(e.type, mediaElement); 15904 _event.data = e; 15905 mediaElement.dispatchEvent(_event); 15906 } 15907 }; 15908 15909 for (var eventType in dashEvents) { 15910 if (dashEvents.hasOwnProperty(eventType)) { 15911 dashPlayer.on(dashEvents[eventType], function (e) { 15912 return assignMdashEvents(e); 15913 }); 15914 } 15915 } 15916 }; 15917 15918 if (mediaFiles && mediaFiles.length > 0) { 15919 for (var _i4 = 0, _total4 = mediaFiles.length; _i4 < _total4; _i4++) { 15920 if (_renderer.renderer.renderers[options.prefix].canPlayType(mediaFiles[_i4].type)) { 15921 node.setAttribute('src', mediaFiles[_i4].src); 15922 if (typeof mediaFiles[_i4].drm !== 'undefined') { 15923 options.dash.drm = mediaFiles[_i4].drm; 15924 } 15925 break; 15926 } 15927 } 15928 } 15929 15930 node.setAttribute('id', id); 15931 15932 originalNode.parentNode.insertBefore(node, originalNode); 15933 originalNode.autoplay = false; 15934 originalNode.style.display = 'none'; 15935 15936 node.setSize = function (width, height) { 15937 node.style.width = width + 'px'; 15938 node.style.height = height + 'px'; 15939 return node; 15940 }; 15941 15942 node.hide = function () { 15943 node.pause(); 15944 node.style.display = 'none'; 15945 return node; 15946 }; 15947 15948 node.show = function () { 15949 node.style.display = ''; 15950 return node; 15951 }; 15952 15953 node.destroy = function () { 15954 if (dashPlayer !== null) { 15955 dashPlayer.reset(); 15956 } 15957 }; 15958 15959 var event = (0, _general.createEvent)('rendererready', node, false); 15960 mediaElement.originalNode.dispatchEvent(event); 15961 15962 mediaElement.promises.push(NativeDash.load({ 15963 options: options.dash, 15964 id: id 15965 })); 15966 15967 return node; 15968 } 15969}; 15970 15971_media.typeChecks.push(function (url) { 15972 return ~url.toLowerCase().indexOf('.mpd') ? 'application/dash+xml' : null; 15973}); 15974 15975_renderer.renderer.add(DashNativeRenderer); 15976 15977},{"24":24,"25":25,"26":26,"28":28,"3":3,"8":8,"9":9}],21:[function(_dereq_,module,exports){ 15978'use strict'; 15979 15980var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 15981 15982var _window = _dereq_(3); 15983 15984var _window2 = _interopRequireDefault(_window); 15985 15986var _mejs = _dereq_(8); 15987 15988var _mejs2 = _interopRequireDefault(_mejs); 15989 15990var _renderer = _dereq_(9); 15991 15992var _general = _dereq_(26); 15993 15994var _constants = _dereq_(24); 15995 15996var _media = _dereq_(28); 15997 15998var _dom = _dereq_(25); 15999 16000function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16001 16002var NativeHls = { 16003 16004 promise: null, 16005 16006 load: function load(settings) { 16007 if (typeof Hls !== 'undefined') { 16008 NativeHls.promise = new Promise(function (resolve) { 16009 resolve(); 16010 }).then(function () { 16011 NativeHls._createPlayer(settings); 16012 }); 16013 } else { 16014 settings.options.path = typeof settings.options.path === 'string' ? settings.options.path : 'https://cdn.jsdelivr.net/npm/hls.js@latest'; 16015 16016 NativeHls.promise = NativeHls.promise || (0, _dom.loadScript)(settings.options.path); 16017 NativeHls.promise.then(function () { 16018 NativeHls._createPlayer(settings); 16019 }); 16020 } 16021 16022 return NativeHls.promise; 16023 }, 16024 16025 _createPlayer: function _createPlayer(settings) { 16026 var player = new Hls(settings.options); 16027 _window2.default['__ready__' + settings.id](player); 16028 return player; 16029 } 16030}; 16031 16032var HlsNativeRenderer = { 16033 name: 'native_hls', 16034 options: { 16035 prefix: 'native_hls', 16036 hls: { 16037 path: 'https://cdn.jsdelivr.net/npm/hls.js@latest', 16038 16039 autoStartLoad: false, 16040 debug: false 16041 } 16042 }, 16043 16044 canPlayType: function canPlayType(type) { 16045 return _constants.HAS_MSE && ['application/x-mpegurl', 'application/vnd.apple.mpegurl', 'audio/mpegurl', 'audio/hls', 'video/hls'].indexOf(type.toLowerCase()) > -1; 16046 }, 16047 16048 create: function create(mediaElement, options, mediaFiles) { 16049 16050 var originalNode = mediaElement.originalNode, 16051 id = mediaElement.id + '_' + options.prefix, 16052 preload = originalNode.getAttribute('preload'), 16053 autoplay = originalNode.autoplay; 16054 16055 var hlsPlayer = null, 16056 node = null, 16057 index = 0, 16058 total = mediaFiles.length; 16059 16060 node = originalNode.cloneNode(true); 16061 options = Object.assign(options, mediaElement.options); 16062 options.hls.autoStartLoad = preload && preload !== 'none' || autoplay; 16063 16064 var props = _mejs2.default.html5media.properties, 16065 events = _mejs2.default.html5media.events.concat(['click', 'mouseover', 'mouseout']).filter(function (e) { 16066 return e !== 'error'; 16067 }), 16068 attachNativeEvents = function attachNativeEvents(e) { 16069 var event = (0, _general.createEvent)(e.type, mediaElement); 16070 mediaElement.dispatchEvent(event); 16071 }, 16072 assignGettersSetters = function assignGettersSetters(propName) { 16073 var capName = '' + propName.substring(0, 1).toUpperCase() + propName.substring(1); 16074 16075 node['get' + capName] = function () { 16076 return hlsPlayer !== null ? node[propName] : null; 16077 }; 16078 16079 node['set' + capName] = function (value) { 16080 if (_mejs2.default.html5media.readOnlyProperties.indexOf(propName) === -1) { 16081 if (propName === 'src') { 16082 node[propName] = (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && value.src ? value.src : value; 16083 if (hlsPlayer !== null) { 16084 hlsPlayer.destroy(); 16085 for (var i = 0, _total = events.length; i < _total; i++) { 16086 node.removeEventListener(events[i], attachNativeEvents); 16087 } 16088 hlsPlayer = NativeHls._createPlayer({ 16089 options: options.hls, 16090 id: id 16091 }); 16092 hlsPlayer.loadSource(value); 16093 hlsPlayer.attachMedia(node); 16094 } 16095 } else { 16096 node[propName] = value; 16097 } 16098 } 16099 }; 16100 }; 16101 16102 for (var i = 0, _total2 = props.length; i < _total2; i++) { 16103 assignGettersSetters(props[i]); 16104 } 16105 16106 _window2.default['__ready__' + id] = function (_hlsPlayer) { 16107 mediaElement.hlsPlayer = hlsPlayer = _hlsPlayer; 16108 var hlsEvents = Hls.Events, 16109 assignEvents = function assignEvents(eventName) { 16110 if (eventName === 'loadedmetadata') { 16111 var url = mediaElement.originalNode.src; 16112 hlsPlayer.detachMedia(); 16113 hlsPlayer.loadSource(url); 16114 hlsPlayer.attachMedia(node); 16115 } 16116 16117 node.addEventListener(eventName, attachNativeEvents); 16118 }; 16119 16120 for (var _i = 0, _total3 = events.length; _i < _total3; _i++) { 16121 assignEvents(events[_i]); 16122 } 16123 16124 var recoverDecodingErrorDate = void 0, 16125 recoverSwapAudioCodecDate = void 0; 16126 var assignHlsEvents = function assignHlsEvents(name, data) { 16127 if (name === 'hlsError') { 16128 console.warn(data); 16129 data = data[1]; 16130 16131 if (data.fatal) { 16132 switch (data.type) { 16133 case 'mediaError': 16134 var now = new Date().getTime(); 16135 if (!recoverDecodingErrorDate || now - recoverDecodingErrorDate > 3000) { 16136 recoverDecodingErrorDate = new Date().getTime(); 16137 hlsPlayer.recoverMediaError(); 16138 } else if (!recoverSwapAudioCodecDate || now - recoverSwapAudioCodecDate > 3000) { 16139 recoverSwapAudioCodecDate = new Date().getTime(); 16140 console.warn('Attempting to swap Audio Codec and recover from media error'); 16141 hlsPlayer.swapAudioCodec(); 16142 hlsPlayer.recoverMediaError(); 16143 } else { 16144 var message = 'Cannot recover, last media error recovery failed'; 16145 mediaElement.generateError(message, node.src); 16146 console.error(message); 16147 } 16148 break; 16149 case 'networkError': 16150 if (data.details === 'manifestLoadError') { 16151 if (index < total && mediaFiles[index + 1] !== undefined) { 16152 node.setSrc(mediaFiles[index++].src); 16153 node.load(); 16154 node.play(); 16155 } else { 16156 var _message = 'Network error'; 16157 mediaElement.generateError(_message, mediaFiles); 16158 console.error(_message); 16159 } 16160 } else { 16161 var _message2 = 'Network error'; 16162 mediaElement.generateError(_message2, mediaFiles); 16163 console.error(_message2); 16164 } 16165 break; 16166 default: 16167 hlsPlayer.destroy(); 16168 break; 16169 } 16170 return; 16171 } 16172 } 16173 var event = (0, _general.createEvent)(name, mediaElement); 16174 event.data = data; 16175 mediaElement.dispatchEvent(event); 16176 }; 16177 16178 var _loop = function _loop(eventType) { 16179 if (hlsEvents.hasOwnProperty(eventType)) { 16180 hlsPlayer.on(hlsEvents[eventType], function () { 16181 for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { 16182 args[_key] = arguments[_key]; 16183 } 16184 16185 return assignHlsEvents(hlsEvents[eventType], args); 16186 }); 16187 } 16188 }; 16189 16190 for (var eventType in hlsEvents) { 16191 _loop(eventType); 16192 } 16193 }; 16194 16195 if (total > 0) { 16196 for (; index < total; index++) { 16197 if (_renderer.renderer.renderers[options.prefix].canPlayType(mediaFiles[index].type)) { 16198 node.setAttribute('src', mediaFiles[index].src); 16199 break; 16200 } 16201 } 16202 } 16203 16204 if (preload !== 'auto' && !autoplay) { 16205 node.addEventListener('play', function () { 16206 if (hlsPlayer !== null) { 16207 hlsPlayer.startLoad(); 16208 } 16209 }); 16210 16211 node.addEventListener('pause', function () { 16212 if (hlsPlayer !== null) { 16213 hlsPlayer.stopLoad(); 16214 } 16215 }); 16216 } 16217 16218 node.setAttribute('id', id); 16219 16220 originalNode.parentNode.insertBefore(node, originalNode); 16221 originalNode.autoplay = false; 16222 originalNode.style.display = 'none'; 16223 16224 node.setSize = function (width, height) { 16225 node.style.width = width + 'px'; 16226 node.style.height = height + 'px'; 16227 return node; 16228 }; 16229 16230 node.hide = function () { 16231 node.pause(); 16232 node.style.display = 'none'; 16233 return node; 16234 }; 16235 16236 node.show = function () { 16237 node.style.display = ''; 16238 return node; 16239 }; 16240 16241 node.destroy = function () { 16242 if (hlsPlayer !== null) { 16243 hlsPlayer.stopLoad(); 16244 hlsPlayer.destroy(); 16245 } 16246 }; 16247 16248 var event = (0, _general.createEvent)('rendererready', node, false); 16249 mediaElement.originalNode.dispatchEvent(event); 16250 16251 mediaElement.promises.push(NativeHls.load({ 16252 options: options.hls, 16253 id: id 16254 })); 16255 16256 return node; 16257 } 16258}; 16259 16260_media.typeChecks.push(function (url) { 16261 return ~url.toLowerCase().indexOf('.m3u8') ? 'application/x-mpegURL' : null; 16262}); 16263 16264_renderer.renderer.add(HlsNativeRenderer); 16265 16266},{"24":24,"25":25,"26":26,"28":28,"3":3,"8":8,"9":9}],22:[function(_dereq_,module,exports){ 16267'use strict'; 16268 16269var _window = _dereq_(3); 16270 16271var _window2 = _interopRequireDefault(_window); 16272 16273var _document = _dereq_(2); 16274 16275var _document2 = _interopRequireDefault(_document); 16276 16277var _mejs = _dereq_(8); 16278 16279var _mejs2 = _interopRequireDefault(_mejs); 16280 16281var _renderer = _dereq_(9); 16282 16283var _general = _dereq_(26); 16284 16285var _constants = _dereq_(24); 16286 16287function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16288 16289var HtmlMediaElement = { 16290 name: 'html5', 16291 options: { 16292 prefix: 'html5' 16293 }, 16294 16295 canPlayType: function canPlayType(type) { 16296 16297 var mediaElement = _document2.default.createElement('video'); 16298 16299 if (_constants.IS_ANDROID && /\/mp(3|4)$/i.test(type) || ~['application/x-mpegurl', 'vnd.apple.mpegurl', 'audio/mpegurl', 'audio/hls', 'video/hls'].indexOf(type.toLowerCase()) && _constants.SUPPORTS_NATIVE_HLS) { 16300 return 'yes'; 16301 } else if (mediaElement.canPlayType) { 16302 return mediaElement.canPlayType(type.toLowerCase()).replace(/no/, ''); 16303 } else { 16304 return ''; 16305 } 16306 }, 16307 16308 create: function create(mediaElement, options, mediaFiles) { 16309 16310 var id = mediaElement.id + '_' + options.prefix; 16311 var isActive = false; 16312 16313 var node = null; 16314 16315 if (mediaElement.originalNode === undefined || mediaElement.originalNode === null) { 16316 node = _document2.default.createElement('audio'); 16317 mediaElement.appendChild(node); 16318 } else { 16319 node = mediaElement.originalNode; 16320 } 16321 16322 node.setAttribute('id', id); 16323 16324 var props = _mejs2.default.html5media.properties, 16325 assignGettersSetters = function assignGettersSetters(propName) { 16326 var capName = '' + propName.substring(0, 1).toUpperCase() + propName.substring(1); 16327 16328 node['get' + capName] = function () { 16329 return node[propName]; 16330 }; 16331 16332 node['set' + capName] = function (value) { 16333 if (_mejs2.default.html5media.readOnlyProperties.indexOf(propName) === -1) { 16334 node[propName] = value; 16335 } 16336 }; 16337 }; 16338 16339 for (var i = 0, _total = props.length; i < _total; i++) { 16340 assignGettersSetters(props[i]); 16341 } 16342 16343 var events = _mejs2.default.html5media.events.concat(['click', 'mouseover', 'mouseout']).filter(function (e) { 16344 return e !== 'error'; 16345 }), 16346 assignEvents = function assignEvents(eventName) { 16347 node.addEventListener(eventName, function (e) { 16348 if (isActive) { 16349 var _event = (0, _general.createEvent)(e.type, e.target); 16350 mediaElement.dispatchEvent(_event); 16351 } 16352 }); 16353 }; 16354 16355 for (var _i = 0, _total2 = events.length; _i < _total2; _i++) { 16356 assignEvents(events[_i]); 16357 } 16358 16359 node.setSize = function (width, height) { 16360 node.style.width = width + 'px'; 16361 node.style.height = height + 'px'; 16362 return node; 16363 }; 16364 16365 node.hide = function () { 16366 isActive = false; 16367 node.style.display = 'none'; 16368 16369 return node; 16370 }; 16371 16372 node.show = function () { 16373 isActive = true; 16374 node.style.display = ''; 16375 16376 return node; 16377 }; 16378 16379 var index = 0, 16380 total = mediaFiles.length; 16381 if (total > 0) { 16382 for (; index < total; index++) { 16383 if (_renderer.renderer.renderers[options.prefix].canPlayType(mediaFiles[index].type)) { 16384 node.setAttribute('src', mediaFiles[index].src); 16385 break; 16386 } 16387 } 16388 } 16389 16390 node.addEventListener('error', function (e) { 16391 if (e && e.target && e.target.error && e.target.error.code === 4 && isActive) { 16392 if (index < total && mediaFiles[index + 1] !== undefined) { 16393 node.src = mediaFiles[index++].src; 16394 node.load(); 16395 node.play(); 16396 } else { 16397 mediaElement.generateError('Media error: Format(s) not supported or source(s) not found', mediaFiles); 16398 } 16399 } 16400 }); 16401 16402 var event = (0, _general.createEvent)('rendererready', node, false); 16403 mediaElement.originalNode.dispatchEvent(event); 16404 16405 return node; 16406 } 16407}; 16408 16409_window2.default.HtmlMediaElement = _mejs2.default.HtmlMediaElement = HtmlMediaElement; 16410 16411_renderer.renderer.add(HtmlMediaElement); 16412 16413},{"2":2,"24":24,"26":26,"3":3,"8":8,"9":9}],23:[function(_dereq_,module,exports){ 16414'use strict'; 16415 16416var _window = _dereq_(3); 16417 16418var _window2 = _interopRequireDefault(_window); 16419 16420var _document = _dereq_(2); 16421 16422var _document2 = _interopRequireDefault(_document); 16423 16424var _mejs = _dereq_(8); 16425 16426var _mejs2 = _interopRequireDefault(_mejs); 16427 16428var _renderer = _dereq_(9); 16429 16430var _general = _dereq_(26); 16431 16432var _media = _dereq_(28); 16433 16434var _dom = _dereq_(25); 16435 16436function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16437 16438var YouTubeApi = { 16439 isIframeStarted: false, 16440 16441 isIframeLoaded: false, 16442 16443 iframeQueue: [], 16444 16445 enqueueIframe: function enqueueIframe(settings) { 16446 YouTubeApi.isLoaded = typeof YT !== 'undefined' && YT.loaded; 16447 16448 if (YouTubeApi.isLoaded) { 16449 YouTubeApi.createIframe(settings); 16450 } else { 16451 YouTubeApi.loadIframeApi(); 16452 YouTubeApi.iframeQueue.push(settings); 16453 } 16454 }, 16455 16456 loadIframeApi: function loadIframeApi() { 16457 if (!YouTubeApi.isIframeStarted) { 16458 (0, _dom.loadScript)('https://www.youtube.com/player_api'); 16459 YouTubeApi.isIframeStarted = true; 16460 } 16461 }, 16462 16463 iFrameReady: function iFrameReady() { 16464 16465 YouTubeApi.isLoaded = true; 16466 YouTubeApi.isIframeLoaded = true; 16467 16468 while (YouTubeApi.iframeQueue.length > 0) { 16469 var settings = YouTubeApi.iframeQueue.pop(); 16470 YouTubeApi.createIframe(settings); 16471 } 16472 }, 16473 16474 createIframe: function createIframe(settings) { 16475 return new YT.Player(settings.containerId, settings); 16476 }, 16477 16478 getYouTubeId: function getYouTubeId(url) { 16479 16480 var youTubeId = ''; 16481 16482 if (url.indexOf('?') > 0) { 16483 youTubeId = YouTubeApi.getYouTubeIdFromParam(url); 16484 16485 if (youTubeId === '') { 16486 youTubeId = YouTubeApi.getYouTubeIdFromUrl(url); 16487 } 16488 } else { 16489 youTubeId = YouTubeApi.getYouTubeIdFromUrl(url); 16490 } 16491 16492 var id = youTubeId.substring(youTubeId.lastIndexOf('/') + 1); 16493 youTubeId = id.split('?'); 16494 return youTubeId[0]; 16495 }, 16496 16497 getYouTubeIdFromParam: function getYouTubeIdFromParam(url) { 16498 16499 if (url === undefined || url === null || !url.trim().length) { 16500 return null; 16501 } 16502 16503 var parts = url.split('?'), 16504 parameters = parts[1].split('&'); 16505 16506 var youTubeId = ''; 16507 16508 for (var i = 0, total = parameters.length; i < total; i++) { 16509 var paramParts = parameters[i].split('='); 16510 if (paramParts[0] === 'v') { 16511 youTubeId = paramParts[1]; 16512 break; 16513 } 16514 } 16515 16516 return youTubeId; 16517 }, 16518 16519 getYouTubeIdFromUrl: function getYouTubeIdFromUrl(url) { 16520 16521 if (url === undefined || url === null || !url.trim().length) { 16522 return null; 16523 } 16524 16525 var parts = url.split('?'); 16526 url = parts[0]; 16527 return url.substring(url.lastIndexOf('/') + 1); 16528 }, 16529 16530 getYouTubeNoCookieUrl: function getYouTubeNoCookieUrl(url) { 16531 if (url === undefined || url === null || !url.trim().length || url.indexOf('//www.youtube') === -1) { 16532 return url; 16533 } 16534 16535 var parts = url.split('/'); 16536 parts[2] = parts[2].replace('.com', '-nocookie.com'); 16537 return parts.join('/'); 16538 } 16539}; 16540 16541var YouTubeIframeRenderer = { 16542 name: 'youtube_iframe', 16543 16544 options: { 16545 prefix: 'youtube_iframe', 16546 16547 youtube: { 16548 autoplay: 0, 16549 controls: 0, 16550 disablekb: 1, 16551 end: 0, 16552 loop: 0, 16553 modestbranding: 0, 16554 playsinline: 0, 16555 rel: 0, 16556 showinfo: 0, 16557 start: 0, 16558 iv_load_policy: 3, 16559 16560 nocookie: false, 16561 16562 imageQuality: null 16563 } 16564 }, 16565 16566 canPlayType: function canPlayType(type) { 16567 return ~['video/youtube', 'video/x-youtube'].indexOf(type.toLowerCase()); 16568 }, 16569 16570 create: function create(mediaElement, options, mediaFiles) { 16571 16572 var youtube = {}, 16573 apiStack = [], 16574 readyState = 4; 16575 16576 var youTubeApi = null, 16577 paused = true, 16578 ended = false, 16579 youTubeIframe = null, 16580 volume = 1; 16581 16582 youtube.options = options; 16583 youtube.id = mediaElement.id + '_' + options.prefix; 16584 youtube.mediaElement = mediaElement; 16585 16586 var props = _mejs2.default.html5media.properties, 16587 assignGettersSetters = function assignGettersSetters(propName) { 16588 16589 var capName = '' + propName.substring(0, 1).toUpperCase() + propName.substring(1); 16590 16591 youtube['get' + capName] = function () { 16592 if (youTubeApi !== null) { 16593 var value = null; 16594 16595 switch (propName) { 16596 case 'currentTime': 16597 return youTubeApi.getCurrentTime(); 16598 case 'duration': 16599 return youTubeApi.getDuration(); 16600 case 'volume': 16601 volume = youTubeApi.getVolume() / 100; 16602 return volume; 16603 case 'playbackRate': 16604 return youTubeApi.getPlaybackRate(); 16605 case 'paused': 16606 return paused; 16607 case 'ended': 16608 return ended; 16609 case 'muted': 16610 return youTubeApi.isMuted(); 16611 case 'buffered': 16612 var percentLoaded = youTubeApi.getVideoLoadedFraction(), 16613 duration = youTubeApi.getDuration(); 16614 return { 16615 start: function start() { 16616 return 0; 16617 }, 16618 end: function end() { 16619 return percentLoaded * duration; 16620 }, 16621 length: 1 16622 }; 16623 case 'src': 16624 return youTubeApi.getVideoUrl(); 16625 case 'readyState': 16626 return readyState; 16627 } 16628 16629 return value; 16630 } else { 16631 return null; 16632 } 16633 }; 16634 16635 youtube['set' + capName] = function (value) { 16636 if (youTubeApi !== null) { 16637 switch (propName) { 16638 case 'src': 16639 var url = typeof value === 'string' ? value : value[0].src, 16640 _videoId = YouTubeApi.getYouTubeId(url); 16641 16642 if (mediaElement.originalNode.autoplay) { 16643 youTubeApi.loadVideoById(_videoId); 16644 } else { 16645 youTubeApi.cueVideoById(_videoId); 16646 } 16647 break; 16648 case 'currentTime': 16649 youTubeApi.seekTo(value); 16650 break; 16651 case 'muted': 16652 if (value) { 16653 youTubeApi.mute(); 16654 } else { 16655 youTubeApi.unMute(); 16656 } 16657 setTimeout(function () { 16658 var event = (0, _general.createEvent)('volumechange', youtube); 16659 mediaElement.dispatchEvent(event); 16660 }, 50); 16661 break; 16662 case 'volume': 16663 volume = value; 16664 youTubeApi.setVolume(value * 100); 16665 setTimeout(function () { 16666 var event = (0, _general.createEvent)('volumechange', youtube); 16667 mediaElement.dispatchEvent(event); 16668 }, 50); 16669 break; 16670 case 'playbackRate': 16671 youTubeApi.setPlaybackRate(value); 16672 setTimeout(function () { 16673 var event = (0, _general.createEvent)('ratechange', youtube); 16674 mediaElement.dispatchEvent(event); 16675 }, 50); 16676 break; 16677 case 'readyState': 16678 var event = (0, _general.createEvent)('canplay', youtube); 16679 mediaElement.dispatchEvent(event); 16680 break; 16681 default: 16682 16683 break; 16684 } 16685 } else { 16686 apiStack.push({ type: 'set', propName: propName, value: value }); 16687 } 16688 }; 16689 }; 16690 16691 for (var i = 0, total = props.length; i < total; i++) { 16692 assignGettersSetters(props[i]); 16693 } 16694 16695 var methods = _mejs2.default.html5media.methods, 16696 assignMethods = function assignMethods(methodName) { 16697 youtube[methodName] = function () { 16698 if (youTubeApi !== null) { 16699 switch (methodName) { 16700 case 'play': 16701 paused = false;
vendor: 4,117 bytes, lines 16702-16831
16702 return youTubeApi.playVideo(); 16703 case 'pause': 16704 paused = true; 16705 return youTubeApi.pauseVideo(); 16706 case 'load': 16707 return null; 16708 } 16709 } else { 16710 apiStack.push({ type: 'call', methodName: methodName }); 16711 } 16712 }; 16713 }; 16714 16715 for (var _i = 0, _total = methods.length; _i < _total; _i++) { 16716 assignMethods(methods[_i]); 16717 } 16718 16719 var errorHandler = function errorHandler(error) { 16720 var message = ''; 16721 switch (error.data) { 16722 case 2: 16723 message = 'The request contains an invalid parameter value. Verify that video ID has 11 characters and that contains no invalid characters, such as exclamation points or asterisks.'; 16724 break; 16725 case 5: 16726 message = 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.'; 16727 break; 16728 case 100: 16729 message = 'The video requested was not found. Either video has been removed or has been marked as private.'; 16730 break; 16731 case 101: 16732 case 105: 16733 message = 'The owner of the requested video does not allow it to be played in embedded players.'; 16734 break; 16735 default: 16736 message = 'Unknown error.'; 16737 break; 16738 } 16739 mediaElement.generateError('Code ' + error.data + ': ' + message, mediaFiles); 16740 }; 16741 16742 var youtubeContainer = _document2.default.createElement('div'); 16743 youtubeContainer.id = youtube.id; 16744 16745 if (youtube.options.youtube.nocookie) { 16746 mediaElement.originalNode.src = YouTubeApi.getYouTubeNoCookieUrl(mediaFiles[0].src); 16747 } 16748 16749 mediaElement.originalNode.parentNode.insertBefore(youtubeContainer, mediaElement.originalNode); 16750 mediaElement.originalNode.style.display = 'none'; 16751 16752 var isAudio = mediaElement.originalNode.tagName.toLowerCase() === 'audio', 16753 height = isAudio ? '1' : mediaElement.originalNode.height, 16754 width = isAudio ? '1' : mediaElement.originalNode.width, 16755 videoId = YouTubeApi.getYouTubeId(mediaFiles[0].src), 16756 youtubeSettings = { 16757 id: youtube.id, 16758 containerId: youtubeContainer.id, 16759 videoId: videoId, 16760 height: height, 16761 width: width, 16762 host: youtube.options.youtube && youtube.options.youtube.nocookie ? 'https://www.youtube-nocookie.com' : undefined, 16763 playerVars: Object.assign({ 16764 controls: 0, 16765 rel: 0, 16766 disablekb: 1, 16767 showinfo: 0, 16768 modestbranding: 0, 16769 html5: 1, 16770 iv_load_policy: 3 16771 }, youtube.options.youtube), 16772 origin: _window2.default.location.host, 16773 events: { 16774 onReady: function onReady(e) { 16775 mediaElement.youTubeApi = youTubeApi = e.target; 16776 mediaElement.youTubeState = { 16777 paused: true, 16778 ended: false 16779 }; 16780 16781 if (apiStack.length) { 16782 for (var _i2 = 0, _total2 = apiStack.length; _i2 < _total2; _i2++) { 16783 16784 var stackItem = apiStack[_i2]; 16785 16786 if (stackItem.type === 'set') { 16787 var propName = stackItem.propName, 16788 capName = '' + propName.substring(0, 1).toUpperCase() + propName.substring(1); 16789 16790 youtube['set' + capName](stackItem.value); 16791 } else if (stackItem.type === 'call') { 16792 youtube[stackItem.methodName](); 16793 } 16794 } 16795 } 16796 16797 youTubeIframe = youTubeApi.getIframe(); 16798 16799 if (mediaElement.originalNode.muted) { 16800 youTubeApi.mute(); 16801 } 16802 16803 var events = ['mouseover', 'mouseout'], 16804 assignEvents = function assignEvents(e) { 16805 var newEvent = (0, _general.createEvent)(e.type, youtube); 16806 mediaElement.dispatchEvent(newEvent); 16807 }; 16808 16809 for (var _i3 = 0, _total3 = events.length; _i3 < _total3; _i3++) { 16810 youTubeIframe.addEventListener(events[_i3], assignEvents, false); 16811 } 16812 16813 var initEvents = ['rendererready', 'loadedmetadata', 'loadeddata', 'canplay']; 16814 16815 for (var _i4 = 0, _total4 = initEvents.length; _i4 < _total4; _i4++) { 16816 var event = (0, _general.createEvent)(initEvents[_i4], youtube, true); 16817 mediaElement.dispatchEvent(event); 16818 } 16819 }, 16820 onStateChange: function onStateChange(e) { 16821 var events = []; 16822 16823 switch (e.data) { 16824 case -1: 16825 events = ['loadedmetadata']; 16826 paused = true; 16827 ended = false; 16828 break; 16829 case 0: 16830 events = ['ended']; 16831 paused = false;
vendor: 4,035 bytes, lines 16832-16958
16832 ended = !youtube.options.youtube.loop; 16833 if (!youtube.options.youtube.loop) { 16834 youtube.stopInterval(); 16835 } 16836 break; 16837 case 1: 16838 events = ['play', 'playing']; 16839 paused = false; 16840 ended = false; 16841 youtube.startInterval(); 16842 break; 16843 case 2: 16844 events = ['pause']; 16845 paused = true; 16846 ended = false; 16847 youtube.stopInterval(); 16848 break; 16849 case 3: 16850 events = ['progress']; 16851 ended = false; 16852 break; 16853 case 5: 16854 events = ['loadeddata', 'loadedmetadata', 'canplay']; 16855 paused = true; 16856 ended = false; 16857 break; 16858 } 16859 16860 for (var _i5 = 0, _total5 = events.length; _i5 < _total5; _i5++) { 16861 var event = (0, _general.createEvent)(events[_i5], youtube); 16862 mediaElement.dispatchEvent(event); 16863 } 16864 }, 16865 onError: function onError(e) { 16866 return errorHandler(e); 16867 } 16868 } 16869 }; 16870 16871 if (isAudio || mediaElement.originalNode.hasAttribute('playsinline')) { 16872 youtubeSettings.playerVars.playsinline = 1; 16873 } 16874 16875 if (mediaElement.originalNode.controls) { 16876 youtubeSettings.playerVars.controls = 1; 16877 } 16878 if (mediaElement.originalNode.autoplay) { 16879 youtubeSettings.playerVars.autoplay = 1; 16880 } 16881 if (mediaElement.originalNode.loop) { 16882 youtubeSettings.playerVars.loop = 1; 16883 } 16884 16885 if ((youtubeSettings.playerVars.loop && parseInt(youtubeSettings.playerVars.loop, 10) === 1 || mediaElement.originalNode.src.indexOf('loop=') > -1) && !youtubeSettings.playerVars.playlist && mediaElement.originalNode.src.indexOf('playlist=') === -1) { 16886 youtubeSettings.playerVars.playlist = YouTubeApi.getYouTubeId(mediaElement.originalNode.src); 16887 } 16888 16889 YouTubeApi.enqueueIframe(youtubeSettings); 16890 16891 youtube.onEvent = function (eventName, player, _youTubeState) { 16892 if (_youTubeState !== null && _youTubeState !== undefined) { 16893 mediaElement.youTubeState = _youTubeState; 16894 } 16895 }; 16896 16897 youtube.setSize = function (width, height) { 16898 if (youTubeApi !== null) { 16899 youTubeApi.setSize(width, height); 16900 } 16901 }; 16902 youtube.hide = function () { 16903 youtube.stopInterval(); 16904 youtube.pause(); 16905 if (youTubeIframe) { 16906 youTubeIframe.style.display = 'none'; 16907 } 16908 }; 16909 youtube.show = function () { 16910 if (youTubeIframe) { 16911 youTubeIframe.style.display = ''; 16912 } 16913 }; 16914 youtube.destroy = function () { 16915 youTubeApi.destroy(); 16916 }; 16917 youtube.interval = null; 16918 16919 youtube.startInterval = function () { 16920 youtube.interval = setInterval(function () { 16921 var event = (0, _general.createEvent)('timeupdate', youtube); 16922 mediaElement.dispatchEvent(event); 16923 }, 250); 16924 }; 16925 youtube.stopInterval = function () { 16926 if (youtube.interval) { 16927 clearInterval(youtube.interval); 16928 } 16929 }; 16930 youtube.getPosterUrl = function () { 16931 var quality = options.youtube.imageQuality, 16932 resolutions = ['default', 'hqdefault', 'mqdefault', 'sddefault', 'maxresdefault'], 16933 id = YouTubeApi.getYouTubeId(mediaElement.originalNode.src); 16934 return quality && resolutions.indexOf(quality) > -1 && id ? 'https://img.youtube.com/vi/' + id + '/' + quality + '.jpg' : ''; 16935 }; 16936 16937 return youtube; 16938 } 16939}; 16940 16941_window2.default.onYouTubePlayerAPIReady = function () { 16942 YouTubeApi.iFrameReady(); 16943}; 16944 16945_media.typeChecks.push(function (url) { 16946 return (/\/\/(www\.youtube|youtu\.?be)/i.test(url) ? 'video/x-youtube' : null 16947 ); 16948}); 16949 16950_renderer.renderer.add(YouTubeIframeRenderer); 16951 16952},{"2":2,"25":25,"26":26,"28":28,"3":3,"8":8,"9":9}],24:[function(_dereq_,module,exports){ 16953'use strict'; 16954 16955Object.defineProperty(exports, "__esModule", { 16956 value: true 16957}); 16958exports.cancelFullScreen = exports.requestFullScreen = exports.isFullScreen = exports.FULLSCREEN_EVENT_NAME = exports.HAS_NATIVE_FULLSCREEN_ENABLED = exports.HAS_TRUE_NATIVE_FULLSCREEN = exports.HAS_IOS_FULLSCREEN = exports.HAS_MS_NATIVE_FULLSCREEN = exports.HAS_MOZ_NATIVE_FULLSCREEN = exports.HAS_WEBKIT_NATIVE_FULLSCREEN = exports.HAS_NATIVE_FULLSCREEN = exports.SUPPORTS_NATIVE_HLS = exports.SUPPORT_PASSIVE_EVENT = exports.SUPPORT_POINTER_EVENTS = exports.HAS_MSE = exports.IS_STOCK_ANDROID = exp
vendor: 1,400 bytes, lines 16958-16985
16958orts.IS_SAFARI = exports.IS_FIREFOX = exports.IS_CHROME = exports.IS_EDGE = exports.IS_IE = exports.IS_ANDROID = exports.IS_IOS = exports.IS_IPOD = exports.IS_IPHONE = exports.IS_IPAD = exports.UA = exports.NAV = undefined; 16959 16960var _window = _dereq_(3); 16961 16962var _window2 = _interopRequireDefault(_window); 16963 16964var _document = _dereq_(2); 16965 16966var _document2 = _interopRequireDefault(_document); 16967 16968var _mejs = _dereq_(8); 16969 16970var _mejs2 = _interopRequireDefault(_mejs); 16971 16972function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16973 16974var NAV = exports.NAV = _window2.default.navigator; 16975var UA = exports.UA = NAV.userAgent.toLowerCase(); 16976var IS_IPAD = exports.IS_IPAD = /ipad/i.test(UA) && !_window2.default.MSStream; 16977var IS_IPHONE = exports.IS_IPHONE = /iphone/i.test(UA) && !_window2.default.MSStream; 16978var IS_IPOD = exports.IS_IPOD = /ipod/i.test(UA) && !_window2.default.MSStream; 16979var IS_IOS = exports.IS_IOS = /ipad|iphone|ipod/i.test(UA) && !_window2.default.MSStream; 16980var IS_ANDROID = exports.IS_ANDROID = /android/i.test(UA); 16981var IS_IE = exports.IS_IE = /(trident|microsoft)/i.test(NAV.appName); 16982var IS_EDGE = exports.IS_EDGE = 'msLaunchUri' in NAV && !('documentMode' in _document2.default); 16983var IS_CHROME = exports.IS_CHROME = /chrome/i.test(UA); 16984var IS_FIREFOX = exports.IS_FIREFOX = /firefox/i.test(UA); 16985var IS_SAFARI = exports.IS_SAFARI = /safari/i.test(UA) && !IS_CHROME;
vendor: 32,196 bytes, lines 16986-18082
16986var IS_STOCK_ANDROID = exports.IS_STOCK_ANDROID = /^mozilla\/\d+\.\d+\s\(linux;\su;/i.test(UA); 16987var HAS_MSE = exports.HAS_MSE = 'MediaSource' in _window2.default; 16988var SUPPORT_POINTER_EVENTS = exports.SUPPORT_POINTER_EVENTS = true;var SUPPORT_PASSIVE_EVENT = exports.SUPPORT_PASSIVE_EVENT = function () { 16989 var supportsPassive = false; 16990 try { 16991 var opts = Object.defineProperty({}, 'passive', { 16992 get: function get() { 16993 supportsPassive = true; 16994 } 16995 }); 16996 _window2.default.addEventListener('test', null, opts); 16997 } catch (e) {} 16998 16999 return supportsPassive; 17000}(); 17001 17002var html5Elements = ['source', 'track', 'audio', 'video']; 17003var video = void 0; 17004 17005for (var i = 0, total = html5Elements.length; i < total; i++) { 17006 video = _document2.default.createElement(html5Elements[i]); 17007} 17008 17009var SUPPORTS_NATIVE_HLS = exports.SUPPORTS_NATIVE_HLS = IS_SAFARI || IS_IE && /edge/i.test(UA); 17010 17011var hasiOSFullScreen = video.webkitEnterFullscreen !== undefined; 17012 17013var hasNativeFullscreen = video.requestFullscreen !== undefined; 17014 17015if (hasiOSFullScreen && /mac os x 10_5/i.test(UA)) { 17016 hasNativeFullscreen = false; 17017 hasiOSFullScreen = false; 17018} 17019 17020var hasWebkitNativeFullScreen = video.webkitRequestFullScreen !== undefined; 17021var hasMozNativeFullScreen = video.mozRequestFullScreen !== undefined; 17022var hasMsNativeFullScreen = video.msRequestFullscreen !== undefined; 17023var hasTrueNativeFullScreen = hasWebkitNativeFullScreen || hasMozNativeFullScreen || hasMsNativeFullScreen; 17024var nativeFullScreenEnabled = hasTrueNativeFullScreen; 17025var fullScreenEventName = ''; 17026var isFullScreen = void 0, 17027 requestFullScreen = void 0, 17028 cancelFullScreen = void 0; 17029 17030if (hasMozNativeFullScreen) { 17031 nativeFullScreenEnabled = _document2.default.mozFullScreenEnabled; 17032} else if (hasMsNativeFullScreen) { 17033 nativeFullScreenEnabled = _document2.default.msFullscreenEnabled; 17034} 17035 17036if (IS_CHROME) { 17037 hasiOSFullScreen = false; 17038} 17039 17040if (hasTrueNativeFullScreen) { 17041 if (hasWebkitNativeFullScreen) { 17042 fullScreenEventName = 'webkitfullscreenchange'; 17043 } else if (hasMozNativeFullScreen) { 17044 fullScreenEventName = 'fullscreenchange'; 17045 } else if (hasMsNativeFullScreen) { 17046 fullScreenEventName = 'MSFullscreenChange'; 17047 } 17048 17049 exports.isFullScreen = isFullScreen = function isFullScreen() { 17050 if (hasMozNativeFullScreen) { 17051 return _document2.default.mozFullScreen; 17052 } else if (hasWebkitNativeFullScreen) { 17053 return _document2.default.webkitIsFullScreen; 17054 } else if (hasMsNativeFullScreen) { 17055 return _document2.default.msFullscreenElement !== null; 17056 } 17057 }; 17058 17059 exports.requestFullScreen = requestFullScreen = function requestFullScreen(el) { 17060 if (hasWebkitNativeFullScreen) { 17061 el.webkitRequestFullScreen(); 17062 } else if (hasMozNativeFullScreen) { 17063 el.mozRequestFullScreen(); 17064 } else if (hasMsNativeFullScreen) { 17065 el.msRequestFullscreen(); 17066 } 17067 }; 17068 17069 exports.cancelFullScreen = cancelFullScreen = function cancelFullScreen() { 17070 if (hasWebkitNativeFullScreen) { 17071 _document2.default.webkitCancelFullScreen(); 17072 } else if (hasMozNativeFullScreen) { 17073 _document2.default.mozCancelFullScreen(); 17074 } else if (hasMsNativeFullScreen) { 17075 _document2.default.msExitFullscreen(); 17076 } 17077 }; 17078} 17079 17080var HAS_NATIVE_FULLSCREEN = exports.HAS_NATIVE_FULLSCREEN = hasNativeFullscreen; 17081var HAS_WEBKIT_NATIVE_FULLSCREEN = exports.HAS_WEBKIT_NATIVE_FULLSCREEN = hasWebkitNativeFullScreen; 17082var HAS_MOZ_NATIVE_FULLSCREEN = exports.HAS_MOZ_NATIVE_FULLSCREEN = hasMozNativeFullScreen; 17083var HAS_MS_NATIVE_FULLSCREEN = exports.HAS_MS_NATIVE_FULLSCREEN = hasMsNativeFullScreen; 17084var HAS_IOS_FULLSCREEN = exports.HAS_IOS_FULLSCREEN = hasiOSFullScreen; 17085var HAS_TRUE_NATIVE_FULLSCREEN = exports.HAS_TRUE_NATIVE_FULLSCREEN = hasTrueNativeFullScreen; 17086var HAS_NATIVE_FULLSCREEN_ENABLED = exports.HAS_NATIVE_FULLSCREEN_ENABLED = nativeFullScreenEnabled; 17087var FULLSCREEN_EVENT_NAME = exports.FULLSCREEN_EVENT_NAME = fullScreenEventName; 17088exports.isFullScreen = isFullScreen; 17089exports.requestFullScreen = requestFullScreen; 17090exports.cancelFullScreen = cancelFullScreen; 17091 17092 17093_mejs2.default.Features = _mejs2.default.Features || {}; 17094_mejs2.default.Features.isiPad = IS_IPAD; 17095_mejs2.default.Features.isiPod = IS_IPOD; 17096_mejs2.default.Features.isiPhone = IS_IPHONE; 17097_mejs2.default.Features.isiOS = _mejs2.default.Features.isiPhone || _mejs2.default.Features.isiPad; 17098_mejs2.default.Features.isAndroid = IS_ANDROID; 17099_mejs2.default.Features.isIE = IS_IE; 17100_mejs2.default.Features.isEdge = IS_EDGE; 17101_mejs2.default.Features.isChrome = IS_CHROME; 17102_mejs2.default.Features.isFirefox = IS_FIREFOX; 17103_mejs2.default.Features.isSafari = IS_SAFARI; 17104_mejs2.default.Features.isStockAndroid = IS_STOCK_ANDROID; 17105_mejs2.default.Features.hasMSE = HAS_MSE; 17106_mejs2.default.Features.supportsNativeHLS = SUPPORTS_NATIVE_HLS; 17107_mejs2.default.Features.supportsPointerEvents = SUPPORT_POINTER_EVENTS; 17108_mejs2.default.Features.supportsPassiveEvent = SUPPORT_PASSIVE_EVENT; 17109_mejs2.default.Features.hasiOSFullScreen = HAS_IOS_FULLSCREEN; 17110_mejs2.default.Features.hasNativeFullscreen = HAS_NATIVE_FULLSCREEN; 17111_mejs2.default.Features.hasWebkitNativeFullScreen = HAS_WEBKIT_NATIVE_FULLSCREEN; 17112_mejs2.default.Features.hasMozNativeFullScreen = HAS_MOZ_NATIVE_FULLSCREEN; 17113_mejs2.default.Features.hasMsNativeFullScreen = HAS_MS_NATIVE_FULLSCREEN; 17114_mejs2.default.Features.hasTrueNativeFullScreen = HAS_TRUE_NATIVE_FULLSCREEN; 17115_mejs2.default.Features.nativeFullScreenEnabled = HAS_NATIVE_FULLSCREEN_ENABLED; 17116_mejs2.default.Features.fullScreenEventName = FULLSCREEN_EVENT_NAME; 17117_mejs2.default.Features.isFullScreen = isFullScreen; 17118_mejs2.default.Features.requestFullScreen = requestFullScreen; 17119_mejs2.default.Features.cancelFullScreen = cancelFullScreen; 17120 17121},{"2":2,"3":3,"8":8}],25:[function(_dereq_,module,exports){ 17122'use strict'; 17123 17124Object.defineProperty(exports, "__esModule", { 17125 value: true 17126}); 17127exports.removeClass = exports.addClass = exports.hasClass = undefined; 17128exports.loadScript = loadScript; 17129exports.offset = offset; 17130exports.toggleClass = toggleClass; 17131exports.fadeOut = fadeOut; 17132exports.fadeIn = fadeIn; 17133exports.siblings = siblings; 17134exports.visible = visible; 17135exports.ajax = ajax; 17136 17137var _window = _dereq_(3); 17138 17139var _window2 = _interopRequireDefault(_window); 17140 17141var _document = _dereq_(2); 17142 17143var _document2 = _interopRequireDefault(_document); 17144 17145var _mejs = _dereq_(8); 17146 17147var _mejs2 = _interopRequireDefault(_mejs); 17148 17149function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 17150 17151function loadScript(url) { 17152 return new Promise(function (resolve, reject) { 17153 var script = _document2.default.createElement('script'); 17154 script.src = url; 17155 script.async = true; 17156 script.onload = function () { 17157 script.remove(); 17158 resolve(); 17159 }; 17160 script.onerror = function () { 17161 script.remove(); 17162 reject(); 17163 }; 17164 _document2.default.head.appendChild(script); 17165 }); 17166} 17167 17168function offset(el) { 17169 var rect = el.getBoundingClientRect(), 17170 scrollLeft = _window2.default.pageXOffset || _document2.default.documentElement.scrollLeft, 17171 scrollTop = _window2.default.pageYOffset || _document2.default.documentElement.scrollTop; 17172 return { top: rect.top + scrollTop, left: rect.left + scrollLeft }; 17173} 17174 17175var hasClassMethod = void 0, 17176 addClassMethod = void 0, 17177 removeClassMethod = void 0; 17178 17179if ('classList' in _document2.default.documentElement) { 17180 hasClassMethod = function hasClassMethod(el, className) { 17181 return el.classList !== undefined && el.classList.contains(className); 17182 }; 17183 addClassMethod = function addClassMethod(el, className) { 17184 return el.classList.add(className); 17185 }; 17186 removeClassMethod = function removeClassMethod(el, className) { 17187 return el.classList.remove(className); 17188 }; 17189} else { 17190 hasClassMethod = function hasClassMethod(el, className) { 17191 return new RegExp('\\b' + className + '\\b').test(el.className); 17192 }; 17193 addClassMethod = function addClassMethod(el, className) { 17194 if (!hasClass(el, className)) { 17195 el.className += ' ' + className; 17196 } 17197 }; 17198 removeClassMethod = function removeClassMethod(el, className) { 17199 el.className = el.className.replace(new RegExp('\\b' + className + '\\b', 'g'), ''); 17200 }; 17201} 17202 17203var hasClass = exports.hasClass = hasClassMethod; 17204var addClass = exports.addClass = addClassMethod; 17205var removeClass = exports.removeClass = removeClassMethod; 17206 17207function toggleClass(el, className) { 17208 hasClass(el, className) ? removeClass(el, className) : addClass(el, className); 17209} 17210 17211function fadeOut(el) { 17212 var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 400; 17213 var callback = arguments[2]; 17214 17215 if (!el.style.opacity) { 17216 el.style.opacity = 1; 17217 } 17218 17219 var start = null; 17220 _window2.default.requestAnimationFrame(function animate(timestamp) { 17221 start = start || timestamp; 17222 var progress = timestamp - start; 17223 var opacity = parseFloat(1 - progress / duration, 2); 17224 el.style.opacity = opacity < 0 ? 0 : opacity; 17225 if (progress > duration) { 17226 if (callback && typeof callback === 'function') { 17227 callback(); 17228 } 17229 } else { 17230 _window2.default.requestAnimationFrame(animate); 17231 } 17232 }); 17233} 17234 17235function fadeIn(el) { 17236 var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 400; 17237 var callback = arguments[2]; 17238 17239 if (!el.style.opacity) { 17240 el.style.opacity = 0; 17241 } 17242 17243 var start = null; 17244 _window2.default.requestAnimationFrame(function animate(timestamp) { 17245 start = start || timestamp; 17246 var progress = timestamp - start; 17247 var opacity = parseFloat(progress / duration, 2); 17248 el.style.opacity = opacity > 1 ? 1 : opacity; 17249 if (progress > duration) { 17250 if (callback && typeof callback === 'function') { 17251 callback(); 17252 } 17253 } else { 17254 _window2.default.requestAnimationFrame(animate); 17255 } 17256 }); 17257} 17258 17259function siblings(el, filter) { 17260 var siblings = []; 17261 el = el.parentNode.firstChild; 17262 do { 17263 if (!filter || filter(el)) { 17264 siblings.push(el); 17265 } 17266 } while (el = el.nextSibling); 17267 return siblings; 17268} 17269 17270function visible(elem) { 17271 if (elem.getClientRects !== undefined && elem.getClientRects === 'function') { 17272 return !!(elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length); 17273 } 17274 return !!(elem.offsetWidth || elem.offsetHeight); 17275} 17276 17277function ajax(url, dataType, success, error) { 17278 var xhr = _window2.default.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); 17279 17280 var type = 'application/x-www-form-urlencoded; charset=UTF-8', 17281 completed = false, 17282 accept = '*/'.concat('*'); 17283 17284 switch (dataType) { 17285 case 'text': 17286 type = 'text/plain'; 17287 break; 17288 case 'json': 17289 type = 'application/json, text/javascript'; 17290 break; 17291 case 'html': 17292 type = 'text/html'; 17293 break; 17294 case 'xml': 17295 type = 'application/xml, text/xml'; 17296 break; 17297 } 17298 17299 if (type !== 'application/x-www-form-urlencoded') { 17300 accept = type + ', */*; q=0.01'; 17301 } 17302 17303 if (xhr) { 17304 xhr.open('GET', url, true); 17305 xhr.setRequestHeader('Accept', accept); 17306 xhr.onreadystatechange = function () { 17307 if (completed) { 17308 return; 17309 } 17310 17311 if (xhr.readyState === 4) { 17312 if (xhr.status === 200) { 17313 completed = true; 17314 var data = void 0; 17315 switch (dataType) { 17316 case 'json': 17317 data = JSON.parse(xhr.responseText); 17318 break; 17319 case 'xml': 17320 data = xhr.responseXML; 17321 break; 17322 default: 17323 data = xhr.responseText; 17324 break; 17325 } 17326 success(data); 17327 } else if (typeof error === 'function') { 17328 error(xhr.status); 17329 } 17330 } 17331 }; 17332 17333 xhr.send(); 17334 } 17335} 17336 17337_mejs2.default.Utils = _mejs2.default.Utils || {}; 17338_mejs2.default.Utils.offset = offset; 17339_mejs2.default.Utils.hasClass = hasClass; 17340_mejs2.default.Utils.addClass = addClass; 17341_mejs2.default.Utils.removeClass = removeClass; 17342_mejs2.default.Utils.toggleClass = toggleClass; 17343_mejs2.default.Utils.fadeIn = fadeIn; 17344_mejs2.default.Utils.fadeOut = fadeOut; 17345_mejs2.default.Utils.siblings = siblings; 17346_mejs2.default.Utils.visible = visible; 17347_mejs2.default.Utils.ajax = ajax; 17348_mejs2.default.Utils.loadScript = loadScript; 17349 17350},{"2":2,"3":3,"8":8}],26:[function(_dereq_,module,exports){ 17351'use strict'; 17352 17353Object.defineProperty(exports, "__esModule", { 17354 value: true 17355}); 17356exports.escapeHTML = escapeHTML; 17357exports.debounce = debounce; 17358exports.isObjectEmpty = isObjectEmpty; 17359exports.splitEvents = splitEvents; 17360exports.createEvent = createEvent; 17361exports.isNodeAfter = isNodeAfter; 17362exports.isString = isString; 17363 17364var _mejs = _dereq_(8); 17365 17366var _mejs2 = _interopRequireDefault(_mejs); 17367 17368function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 17369 17370function escapeHTML(input) { 17371 17372 if (typeof input !== 'string') { 17373 throw new Error('Argument passed must be a string'); 17374 } 17375 17376 var map = { 17377 '&': '&', 17378 '<': '<', 17379 '>': '>', 17380 '"': '"' 17381 }; 17382 17383 return input.replace(/[&<>"]/g, function (c) { 17384 return map[c]; 17385 }); 17386} 17387 17388function debounce(func, wait) { 17389 var _this = this, 17390 _arguments = arguments; 17391 17392 var immediate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; 17393 17394 17395 if (typeof func !== 'function') { 17396 throw new Error('First argument must be a function'); 17397 } 17398 17399 if (typeof wait !== 'number') { 17400 throw new Error('Second argument must be a numeric value'); 17401 } 17402 17403 var timeout = void 0; 17404 return function () { 17405 var context = _this, 17406 args = _arguments; 17407 var later = function later() { 17408 timeout = null; 17409 if (!immediate) { 17410 func.apply(context, args); 17411 } 17412 }; 17413 var callNow = immediate && !timeout; 17414 clearTimeout(timeout); 17415 timeout = setTimeout(later, wait); 17416 17417 if (callNow) { 17418 func.apply(context, args); 17419 } 17420 }; 17421} 17422 17423function isObjectEmpty(instance) { 17424 return Object.getOwnPropertyNames(instance).length <= 0; 17425} 17426 17427function splitEvents(events, id) { 17428 var rwindow = /^((after|before)print|(before)?unload|hashchange|message|o(ff|n)line|page(hide|show)|popstate|resize|storage)\b/; 17429 17430 var ret = { d: [], w: [] }; 17431 (events || '').split(' ').forEach(function (v) { 17432 var eventName = '' + v + (id ? '.' + id : ''); 17433 17434 if (eventName.startsWith('.')) { 17435 ret.d.push(eventName); 17436 ret.w.push(eventName); 17437 } else { 17438 ret[rwindow.test(v) ? 'w' : 'd'].push(eventName); 17439 } 17440 }); 17441 17442 ret.d = ret.d.join(' '); 17443 ret.w = ret.w.join(' '); 17444 return ret; 17445} 17446 17447function createEvent(eventName, target, isIframe) { 17448 17449 if (typeof eventName !== 'string') { 17450 throw new Error('Event name must be a string'); 17451 } 17452 17453 var eventFrags = eventName.match(/([a-z]+\.([a-z]+))/i), 17454 detail = { 17455 target: target, 17456 isIframe: isIframe 17457 }; 17458 17459 if (eventFrags !== null) { 17460 eventName = eventFrags[1]; 17461 detail.namespace = eventFrags[2]; 17462 } 17463 17464 return new window.CustomEvent(eventName, { 17465 detail: detail 17466 }); 17467} 17468 17469function isNodeAfter(sourceNode, targetNode) { 17470 17471 return !!(sourceNode && targetNode && sourceNode.compareDocumentPosition(targetNode) & 2); 17472} 17473 17474function isString(value) { 17475 return typeof value === 'string'; 17476} 17477 17478_mejs2.default.Utils = _mejs2.default.Utils || {}; 17479_mejs2.default.Utils.escapeHTML = escapeHTML; 17480_mejs2.default.Utils.debounce = debounce; 17481_mejs2.default.Utils.isObjectEmpty = isObjectEmpty; 17482_mejs2.default.Utils.splitEvents = splitEvents; 17483_mejs2.default.Utils.createEvent = createEvent; 17484_mejs2.default.Utils.isNodeAfter = isNodeAfter; 17485_mejs2.default.Utils.isString = isString; 17486 17487},{"8":8}],27:[function(_dereq_,module,exports){ 17488'use strict'; 17489 17490Object.defineProperty(exports, "__esModule", { 17491 value: true 17492}); 17493exports.generateControlButton = generateControlButton; 17494 17495var _mejs = _dereq_(8); 17496 17497var _mejs2 = _interopRequireDefault(_mejs); 17498 17499function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 17500 17501function generateControlButton(playerId, ariaLabel, title, iconSprite, icons, classPrefix) { 17502 var buttonClass = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null; 17503 var ariaDescribedby = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : ''; 17504 var ariaPressed = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : null; 17505 17506 17507 if (typeof playerId !== 'string') { 17508 throw new Error('`ariaControls` argument must be a string'); 17509 } 17510 if (typeof ariaLabel !== 'string') { 17511 throw new Error('`ariaLabel` argument must be a string'); 17512 } 17513 if (typeof title !== 'string') { 17514 throw new Error('`title` argument must be a string'); 17515 } 17516 if (typeof iconSprite !== 'string') { 17517 throw new Error('`iconSprite` argument must be a string'); 17518 } 17519 if (typeof ariaDescribedby !== 'string') { 17520 throw new Error('`ariaDescribedby` argument must be a string'); 17521 } 17522 if (!Array.isArray(icons)) { 17523 throw new Error('`icons` argument must be an array'); 17524 } 17525 if (typeof classPrefix !== 'string') { 17526 throw new Error('`classPrefix` argument must be a string'); 17527 } 17528 17529 var className = buttonClass ? 'class="' + buttonClass + '" ' : ''; 17530 17531 var ariaDescribedbyAttr = ariaDescribedby !== '' ? 'aria-describedby="' + ariaDescribedby + '" ' : ''; 17532 17533 var ariaPressedAttr = ariaPressed !== null ? 'aria-pressed="' + ariaPressed + '"' : ''; 17534 17535 var iconHtml = icons.map(function (icon) { 17536 return '<svg xmlns="http://www.w3.org/2000/svg" id="' + playerId + '-' + icon + '" class="' + classPrefix + icon + '" aria-hidden="true" focusable="false">\n\t\t\t\t<use xlink:href="' + iconSprite + '#' + icon + '"></use>\n\t\t\t</svg>\n'; 17537 }); 17538 17539 return '<button ' + className + ' type="button" aria-controls="' + playerId + '" title="' + title + '" aria-label="' + ariaLabel + '" ' + ariaDescribedbyAttr + ' ' + ariaPressedAttr + '>\n\t\t\t' + iconHtml.join('') + '\n\t\t</button>'; 17540} 17541 17542_mejs2.default.Utils = _mejs2.default.Utils || {}; 17543_mejs2.default.Utils.generateControlButton = generateControlButton; 17544 17545},{"8":8}],28:[function(_dereq_,module,exports){ 17546'use strict'; 17547 17548Object.defineProperty(exports, "__esModule", { 17549 value: true 17550}); 17551exports.typeChecks = undefined; 17552exports.absolutizeUrl = absolutizeUrl; 17553exports.formatType = formatType; 17554exports.getMimeFromType = getMimeFromType; 17555exports.getTypeFromFile = getTypeFromFile; 17556exports.getExtension = getExtension; 17557exports.normalizeExtension = normalizeExtension; 17558 17559var _mejs = _dereq_(8); 17560 17561var _mejs2 = _interopRequireDefault(_mejs); 17562 17563var _general = _dereq_(26); 17564 17565function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 17566 17567var typeChecks = exports.typeChecks = []; 17568 17569function absolutizeUrl(url) { 17570 17571 if (typeof url !== 'string') { 17572 throw new Error('`url` argument must be a string'); 17573 } 17574 17575 var el = document.createElement('div'); 17576 el.innerHTML = '<a href="' + (0, _general.escapeHTML)(url) + '">x</a>'; 17577 return el.firstChild.href; 17578} 17579 17580function formatType(url) { 17581 var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; 17582 17583 return url && !type ? getTypeFromFile(url) : type; 17584} 17585 17586function getMimeFromType(type) { 17587 17588 if (typeof type !== 'string') { 17589 throw new Error('`type` argument must be a string'); 17590 } 17591 17592 return type && type.indexOf(';') > -1 ? type.substr(0, type.indexOf(';')) : type; 17593} 17594 17595function getTypeFromFile(url) { 17596 17597 if (typeof url !== 'string') { 17598 throw new Error('`url` argument must be a string'); 17599 } 17600 17601 for (var i = 0, total = typeChecks.length; i < total; i++) { 17602 var type = typeChecks[i](url); 17603 17604 if (type) { 17605 return type; 17606 } 17607 } 17608 17609 var ext = getExtension(url), 17610 normalizedExt = normalizeExtension(ext); 17611 17612 var mime = 'video/mp4'; 17613 17614 if (normalizedExt) { 17615 if (~['mp4', 'm4v', 'ogg', 'ogv', 'webm', 'mpeg'].indexOf(normalizedExt)) { 17616 mime = 'video/' + normalizedExt; 17617 } else if ('mov' === normalizedExt) { 17618 mime = 'video/quicktime'; 17619 } else if (~['mp3', 'oga', 'wav', 'mid', 'midi'].indexOf(normalizedExt)) { 17620 mime = 'audio/' + normalizedExt; 17621 } 17622 } 17623 17624 return mime; 17625} 17626 17627function getExtension(url) { 17628 17629 if (typeof url !== 'string') { 17630 throw new Error('`url` argument must be a string'); 17631 } 17632 17633 var baseUrl = url.split('?')[0], 17634 baseName = baseUrl.split('\\').pop().split('/').pop(); 17635 return ~baseName.indexOf('.') ? baseName.substring(baseName.lastIndexOf('.') + 1) : ''; 17636} 17637 17638function normalizeExtension(extension) { 17639 17640 if (typeof extension !== 'string') { 17641 throw new Error('`extension` argument must be a string'); 17642 } 17643 17644 switch (extension) { 17645 case 'mp4': 17646 case 'm4v': 17647 return 'mp4'; 17648 case 'webm': 17649 case 'webma': 17650 case 'webmv': 17651 return 'webm'; 17652 case 'ogg': 17653 case 'oga': 17654 case 'ogv': 17655 return 'ogg'; 17656 default: 17657 return extension; 17658 } 17659} 17660 17661_mejs2.default.Utils = _mejs2.default.Utils || {}; 17662_mejs2.default.Utils.typeChecks = typeChecks; 17663_mejs2.default.Utils.absolutizeUrl = absolutizeUrl; 17664_mejs2.default.Utils.formatType = formatType; 17665_mejs2.default.Utils.getMimeFromType = getMimeFromType; 17666_mejs2.default.Utils.getTypeFromFile = getTypeFromFile; 17667_mejs2.default.Utils.getExtension = getExtension; 17668_mejs2.default.Utils.normalizeExtension = normalizeExtension; 17669 17670},{"26":26,"8":8}],29:[function(_dereq_,module,exports){ 17671'use strict'; 17672 17673var _document = _dereq_(2); 17674 17675var _document2 = _interopRequireDefault(_document); 17676 17677var _promisePolyfill = _dereq_(4); 17678 17679var _promisePolyfill2 = _interopRequireDefault(_promisePolyfill); 17680 17681var _svg4everybody = _dereq_(5); 17682 17683var _svg4everybody2 = _interopRequireDefault(_svg4everybody); 17684 17685function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 17686 17687(function (arr) { 17688 arr.forEach(function (item) { 17689 if (item.hasOwnProperty('remove')) { 17690 return; 17691 } 17692 Object.defineProperty(item, 'remove', { 17693 configurable: true, 17694 enumerable: true, 17695 writable: true, 17696 value: function remove() { 17697 this.parentNode.removeChild(this); 17698 } 17699 }); 17700 }); 17701})([Element.prototype, CharacterData.prototype, DocumentType.prototype]); 17702 17703(function () { 17704 17705 if (typeof window.CustomEvent === 'function') { 17706 return false; 17707 } 17708 17709 function CustomEvent(event, params) { 17710 params = params || { bubbles: false, cancelable: false, detail: undefined }; 17711 var evt = _document2.default.createEvent('CustomEvent'); 17712 evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); 17713 return evt; 17714 } 17715 17716 CustomEvent.prototype = window.Event.prototype; 17717 window.CustomEvent = CustomEvent; 17718})(); 17719 17720if (typeof Object.assign !== 'function') { 17721 Object.assign = function (target) { 17722 17723 if (target === null || target === undefined) { 17724 throw new TypeError('Cannot convert undefined or null to object'); 17725 } 17726 17727 var to = Object(target); 17728 17729 for (var index = 1, total = arguments.length; index < total; index++) { 17730 var nextSource = arguments[index]; 17731 17732 if (nextSource !== null) { 17733 for (var nextKey in nextSource) { 17734 if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { 17735 to[nextKey] = nextSource[nextKey]; 17736 } 17737 } 17738 } 17739 } 17740 return to; 17741 }; 17742} 17743 17744if (!String.prototype.startsWith) { 17745 String.prototype.startsWith = function (searchString, position) { 17746 position = position || 0; 17747 return this.substr(position, searchString.length) === searchString; 17748 }; 17749} 17750 17751if (!Element.prototype.matches) { 17752 Element.prototype.matches = Element.prototype.matchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.webkitMatchesSelector || function (s) { 17753 var matches = (this.document || this.ownerDocument).querySelectorAll(s), 17754 i = matches.length - 1; 17755 while (--i >= 0 && matches.item(i) !== this) {} 17756 return i > -1; 17757 }; 17758} 17759 17760if (window.Element && !Element.prototype.closest) { 17761 Element.prototype.closest = function (s) { 17762 var matches = (this.document || this.ownerDocument).querySelectorAll(s), 17763 i = void 0, 17764 el = this; 17765 do { 17766 i = matches.length; 17767 while (--i >= 0 && matches.item(i) !== el) {} 17768 } while (i < 0 && (el = el.parentElement)); 17769 return el; 17770 }; 17771} 17772 17773(function () { 17774 var lastTime = 0; 17775 var vendors = ['ms', 'moz', 'webkit', 'o']; 17776 for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { 17777 window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']; 17778 window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame']; 17779 } 17780 17781 if (!window.requestAnimationFrame) window.requestAnimationFrame = function (callback) { 17782 var currTime = new Date().getTime(); 17783 var timeToCall = Math.max(0, 16 - (currTime - lastTime)); 17784 var id = window.setTimeout(function () { 17785 callback(currTime + timeToCall); 17786 }, timeToCall); 17787 lastTime = currTime + timeToCall; 17788 return id; 17789 }; 17790 17791 if (!window.cancelAnimationFrame) window.cancelAnimationFrame = function (id) { 17792 clearTimeout(id); 17793 }; 17794})(); 17795 17796if (/firefox/i.test(navigator.userAgent)) { 17797 var getComputedStyle = window.getComputedStyle; 17798 window.getComputedStyle = function (el, pseudoEl) { 17799 var t = getComputedStyle(el, pseudoEl); 17800 return t === null ? { getPropertyValue: function getPropertyValue() {} } : t; 17801 }; 17802} 17803 17804if (!window.Promise) { 17805 window.Promise = _promisePolyfill2.default; 17806} 17807 17808(0, _svg4everybody2.default)(); 17809 17810(function (constructor) { 17811 if (constructor && constructor.prototype && constructor.prototype.children === null) { 17812 Object.defineProperty(constructor.prototype, 'children', { 17813 get: function get() { 17814 var i = 0, 17815 node = void 0, 17816 nodes = this.childNodes, 17817 children = []; 17818 while (node = nodes[i++]) { 17819 if (node.nodeType === 1) { 17820 children.push(node); 17821 } 17822 } 17823 return children; 17824 } 17825 }); 17826 } 17827})(window.Node || window.Element); 17828 17829},{"2":2,"4":4,"5":5}],30:[function(_dereq_,module,exports){ 17830'use strict'; 17831 17832Object.defineProperty(exports, "__esModule", { 17833 value: true 17834}); 17835exports.isDropFrame = isDropFrame; 17836exports.secondsToTimeCode = secondsToTimeCode; 17837exports.timeCodeToSeconds = timeCodeToSeconds; 17838exports.calculateTimeFormat = calculateTimeFormat; 17839exports.convertSMPTEtoSeconds = convertSMPTEtoSeconds; 17840 17841var _mejs = _dereq_(8); 17842 17843var _mejs2 = _interopRequireDefault(_mejs); 17844 17845function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 17846 17847function isDropFrame() { 17848 var fps = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 25; 17849 17850 return !(fps % 1 === 0); 17851} 17852function secondsToTimeCode(time) { 17853 var forceHours = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; 17854 var showFrameCount = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; 17855 var fps = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 25; 17856 var secondsDecimalLength = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0; 17857 var timeFormat = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 'hh:mm:ss'; 17858 17859 17860 time = !time || typeof time !== 'number' || time < 0 ? 0 : time; 17861 17862 var dropFrames = Math.round(fps * 0.066666), 17863 timeBase = Math.round(fps), 17864 framesPer24Hours = Math.round(fps * 3600) * 24, 17865 framesPer10Minutes = Math.round(fps * 600), 17866 frameSep = isDropFrame(fps) ? ';' : ':', 17867 hours = void 0, 17868 minutes = void 0, 17869 seconds = void 0, 17870 frames = void 0, 17871 f = Math.round(time * fps); 17872 17873 if (isDropFrame(fps)) { 17874 17875 if (f < 0) { 17876 f = framesPer24Hours + f; 17877 } 17878 17879 f = f % framesPer24Hours; 17880 17881 var d = Math.floor(f / framesPer10Minutes); 17882 var m = f % framesPer10Minutes; 17883 f = f + dropFrames * 9 * d; 17884 if (m > dropFrames) { 17885 f = f + dropFrames * Math.floor((m - dropFrames) / Math.round(timeBase * 60 - dropFrames)); 17886 } 17887 17888 var timeBaseDivision = Math.floor(f / timeBase); 17889 17890 hours = Math.floor(Math.floor(timeBaseDivision / 60) / 60); 17891 minutes = Math.floor(timeBaseDivision / 60) % 60; 17892 17893 if (showFrameCount) { 17894 seconds = timeBaseDivision % 60; 17895 } else { 17896 seconds = Math.floor(f / timeBase % 60).toFixed(secondsDecimalLength); 17897 } 17898 } else { 17899 hours = Math.floor(time / 3600) % 24; 17900 minutes = Math.floor(time / 60) % 60; 17901 if (showFrameCount) { 17902 seconds = Math.floor(time % 60); 17903 } else { 17904 seconds = Math.floor(time % 60).toFixed(secondsDecimalLength); 17905 } 17906 } 17907 hours = hours <= 0 ? 0 : hours; 17908 minutes = minutes <= 0 ? 0 : minutes; 17909 seconds = seconds <= 0 ? 0 : seconds; 17910 17911 seconds = seconds === 60 ? 0 : seconds; 17912 minutes = minutes === 60 ? 0 : minutes; 17913 17914 var timeFormatFrags = timeFormat.split(':'); 17915 var timeFormatSettings = {}; 17916 for (var i = 0, total = timeFormatFrags.length; i < total; ++i) { 17917 var unique = ''; 17918 for (var j = 0, t = timeFormatFrags[i].length; j < t; j++) { 17919 if (unique.indexOf(timeFormatFrags[i][j]) < 0) { 17920 unique += timeFormatFrags[i][j]; 17921 } 17922 } 17923 if (~['f', 's', 'm', 'h'].indexOf(unique)) { 17924 timeFormatSettings[unique] = timeFormatFrags[i].length; 17925 } 17926 } 17927 17928 var result = forceHours || hours > 0 ? (hours < 10 && timeFormatSettings.h > 1 ? '0' + hours : hours) + ':' : ''; 17929 result += (minutes < 10 && timeFormatSettings.m > 1 ? '0' + minutes : minutes) + ':'; 17930 result += '' + (seconds < 10 && timeFormatSettings.s > 1 ? '0' + seconds : seconds); 17931 17932 if (showFrameCount) { 17933 frames = (f % timeBase).toFixed(0); 17934 frames = frames <= 0 ? 0 : frames; 17935 result += frames < 10 && timeFormatSettings.f ? frameSep + '0' + frames : '' + frameSep + frames; 17936 } 17937 17938 return result; 17939} 17940 17941function timeCodeToSeconds(time) { 17942 var fps = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 25; 17943 17944 17945 if (typeof time !== 'string') { 17946 throw new TypeError('Time must be a string'); 17947 } 17948 17949 if (time.indexOf(';') > 0) { 17950 time = time.replace(';', ':'); 17951 } 17952 17953 if (!/\d{2}(\:\d{2}){0,3}/i.test(time)) { 17954 throw new TypeError('Time code must have the format `00:00:00`'); 17955 } 17956 17957 var parts = time.split(':'); 17958 17959 var output = void 0, 17960 hours = 0, 17961 minutes = 0, 17962 seconds = 0, 17963 frames = 0, 17964 totalMinutes = 0, 17965 dropFrames = Math.round(fps * 0.066666), 17966 timeBase = Math.round(fps), 17967 hFrames = timeBase * 3600, 17968 mFrames = timeBase * 60; 17969 17970 switch (parts.length) { 17971 default: 17972 case 1: 17973 seconds = parseInt(parts[0], 10); 17974 break; 17975 case 2: 17976 minutes = parseInt(parts[0], 10); 17977 seconds = parseInt(parts[1], 10); 17978 break; 17979 case 3: 17980 hours = parseInt(parts[0], 10); 17981 minutes = parseInt(parts[1], 10); 17982 seconds = parseInt(parts[2], 10); 17983 break; 17984 case 4: 17985 hours = parseInt(parts[0], 10); 17986 minutes = parseInt(parts[1], 10); 17987 seconds = parseInt(parts[2], 10); 17988 frames = parseInt(parts[3], 10); 17989 break; 17990 } 17991 17992 if (isDropFrame(fps)) { 17993 totalMinutes = 60 * hours + minutes; 17994 output = hFrames * hours + mFrames * minutes + timeBase * seconds + frames - dropFrames * (totalMinutes - Math.floor(totalMinutes / 10)); 17995 } else { 17996 output = (hFrames * hours + mFrames * minutes + fps * seconds + frames) / fps; 17997 } 17998 17999 return parseFloat(output.toFixed(3)); 18000} 18001 18002function calculateTimeFormat(time, options) { 18003 var fps = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 25; 18004 18005 18006 time = !time || typeof time !== 'number' || time < 0 ? 0 : time; 18007 18008 var hours = Math.floor(time / 3600) % 24, 18009 minutes = Math.floor(time / 60) % 60, 18010 seconds = Math.floor(time % 60), 18011 frames = Math.floor((time % 1 * fps).toFixed(3)), 18012 lis = [[frames, 'f'], [seconds, 's'], [minutes, 'm'], [hours, 'h']]; 18013 18014 var format = options.timeFormat, 18015 firstTwoPlaces = format[1] === format[0], 18016 separatorIndex = firstTwoPlaces ? 2 : 1, 18017 separator = format.length < separatorIndex ? format[separatorIndex] : ':', 18018 firstChar = format[0], 18019 required = false; 18020 18021 for (var i = 0, len = lis.length; i < len; i++) { 18022 if (~format.indexOf(lis[i][1])) { 18023 required = true; 18024 } else if (required) { 18025 var hasNextValue = false; 18026 for (var j = i; j < len; j++) { 18027 if (lis[j][0] > 0) { 18028 hasNextValue = true; 18029 break; 18030 } 18031 } 18032 18033 if (!hasNextValue) { 18034 break; 18035 } 18036 18037 if (!firstTwoPlaces) { 18038 format = firstChar + format; 18039 } 18040 format = lis[i][1] + separator + format; 18041 if (firstTwoPlaces) { 18042 format = lis[i][1] + format; 18043 } 18044 firstChar = lis[i][1]; 18045 } 18046 } 18047 18048 options.timeFormat = format; 18049} 18050 18051function convertSMPTEtoSeconds(SMPTE) { 18052 18053 if (typeof SMPTE !== 'string') { 18054 throw new TypeError('Argument must be a string value'); 18055 } 18056 18057 SMPTE = SMPTE.replace(',', '.'); 18058 18059 var decimalLen = ~SMPTE.indexOf('.') ? SMPTE.split('.')[1].length : 0; 18060 18061 var secs = 0, 18062 multiplier = 1; 18063 18064 SMPTE = SMPTE.split(':').reverse(); 18065 18066 for (var i = 0, total = SMPTE.length; i < total; i++) { 18067 multiplier = 1; 18068 if (i > 0) { 18069 multiplier = Math.pow(60, i); 18070 } 18071 secs += Number(SMPTE[i]) * multiplier; 18072 } 18073 return Number(secs.toFixed(decimalLen)); 18074} 18075 18076_mejs2.default.Utils = _mejs2.default.Utils || {}; 18077_mejs2.default.Utils.secondsToTimeCode = secondsToTimeCode; 18078_mejs2.default.Utils.timeCodeToSeconds = timeCodeToSeconds; 18079_mejs2.default.Utils.calculateTimeFormat = calculateTimeFormat; 18080_mejs2.default.Utils.convertSMPTEtoSeconds = convertSMPTEtoSeconds; 18081 18082},{"8":8}]},{},[29,7,6,16,22,20,21,23,17,19,18,10,11,12,13,14,15]);
vendor: 4,086 bytes, lines 18083-18239
18083 18084/*! 18085 * jQuery UI 1.8.16 18086 * 18087 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 18088 * Dual licensed under the MIT or GPL Version 2 licenses. 18089 * http://jquery.org/license 18090 * 18091 * http://docs.jquery.com/UI 18092 */ 18093(function( $, undefined ) { 18094 18095// prevent duplicate loading 18096// this is only a problem because we proxy existing functions 18097// and we don't want to double proxy them 18098$.ui = $.ui || {}; 18099if ( $.ui.version ) { 18100 return; 18101} 18102 18103$.extend( $.ui, { 18104 version: "1.8.16", 18105 18106 keyCode: { 18107 ALT: 18, 18108 BACKSPACE: 8, 18109 CAPS_LOCK: 20, 18110 COMMA: 188, 18111 COMMAND: 91, 18112 COMMAND_LEFT: 91, // COMMAND 18113 COMMAND_RIGHT: 93, 18114 CONTROL: 17, 18115 DELETE: 46, 18116 DOWN: 40, 18117 END: 35, 18118 ENTER: 13, 18119 ESCAPE: 27, 18120 HOME: 36, 18121 INSERT: 45, 18122 LEFT: 37, 18123 MENU: 93, // COMMAND_RIGHT 18124 NUMPAD_ADD: 107, 18125 NUMPAD_DECIMAL: 110, 18126 NUMPAD_DIVIDE: 111, 18127 NUMPAD_ENTER: 108, 18128 NUMPAD_MULTIPLY: 106, 18129 NUMPAD_SUBTRACT: 109, 18130 PAGE_DOWN: 34, 18131 PAGE_UP: 33, 18132 PERIOD: 190, 18133 RIGHT: 39, 18134 SHIFT: 16, 18135 SPACE: 32, 18136 TAB: 9, 18137 UP: 38, 18138 WINDOWS: 91 // COMMAND 18139 } 18140}); 18141 18142// plugins 18143$.fn.extend({ 18144 propAttr: $.fn.prop || $.fn.attr, 18145 18146 _focus: $.fn.focus, 18147 focus: function( delay, fn ) { 18148 return typeof delay === "number" ? 18149 this.each(function() { 18150 var elem = this; 18151 setTimeout(function() { 18152 $( elem ).focus(); 18153 if ( fn ) { 18154 fn.call( elem ); 18155 } 18156 }, delay ); 18157 }) : 18158 this._focus.apply( this, arguments ); 18159 }, 18160 18161 scrollParent: function() { 18162 var scrollParent; 18163 if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) { 18164 scrollParent = this.parents().filter(function() { 18165 return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); 18166 }).eq(0); 18167 } else { 18168 scrollParent = this.parents().filter(function() { 18169 return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); 18170 }).eq(0); 18171 } 18172 18173 return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent; 18174 }, 18175 18176 zIndex: function( zIndex ) { 18177 if ( zIndex !== undefined ) { 18178 return this.css( "zIndex", zIndex ); 18179 } 18180 18181 if ( this.length ) { 18182 var elem = $( this[ 0 ] ), position, value; 18183 while ( elem.length && elem[ 0 ] !== document ) { 18184 // Ignore z-index if position is set to a value where z-index is ignored by the browser 18185 // This makes behavior of this function consistent across browsers 18186 // WebKit always returns auto if the element is positioned 18187 position = elem.css( "position" ); 18188 if ( position === "absolute" || position === "relative" || position === "fixed" ) { 18189 // IE returns 0 when zIndex is not specified 18190 // other browsers return a string 18191 // we ignore the case of nested elements with an explicit value of 0 18192 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> 18193 value = parseInt( elem.css( "zIndex" ), 10 ); 18194 if ( !isNaN( value ) && value !== 0 ) { 18195 return value; 18196 } 18197 } 18198 elem = elem.parent(); 18199 } 18200 } 18201 18202 return 0; 18203 }, 18204 18205 disableSelection: function() { 18206 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) + 18207 ".ui-disableSelection", function( event ) { 18208 event.preventDefault(); 18209 }); 18210 }, 18211 18212 enableSelection: function() { 18213 return this.unbind( ".ui-disableSelection" ); 18214 } 18215}); 18216 18217$.each( [ "Width", "Height" ], function( i, name ) { 18218 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], 18219 type = name.toLowerCase(), 18220 orig = { 18221 innerWidth: $.fn.innerWidth, 18222 innerHeight: $.fn.innerHeight, 18223 outerWidth: $.fn.outerWidth, 18224 outerHeight: $.fn.outerHeight 18225 }; 18226 18227 function reduce( elem, size, border, margin ) { 18228 $.each( side, function() { 18229 size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0; 18230 if ( border ) { 18231 size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0; 18232 } 18233 if ( margin ) { 18234 size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0; 18235 } 18236 }); 18237 return size; 18238 } 18239
18240 $.fn[ "inner" + name ] = function( size ) { 18241 if ( size === undefined ) { 18242 return orig[ "inner" + name ].call( this ); 18243 } 18244 18245 return this.each(function() { 18246 $( this ).css( type, reduce( this, size ) + "px" ); 18247 }); 18248 }; 18249 18250 $.fn[ "outer" + name] = function( size, margin ) { 18251 if ( typeof size !== "number" ) { 18252 return orig[ "outer" + name ].call( this, size ); 18253 } 18254 18255 return this.each(function() { 18256 $( this).css( type, reduce( this, size, true, margin ) + "px" ); 18257 }); 18258 }; 18259}); 18260 18261// selectors 18262function focusable( element, isTabIndexNotNaN ) { 18263 var nodeName = element.nodeName.toLowerCase(); 18264 if ( "area" === nodeName ) { 18265 var map = element.parentNode, 18266 mapName = map.name, 18267 img; 18268 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { 18269 return false; 18270 } 18271 img = $( "img[usemap=#" + mapName + "]" )[0]; 18272 return !!img && visible( img ); 18273 } 18274 return ( /input|select|textarea|button|object/.test( nodeName ) 18275 ? !element.disabled 18276 : "a" == nodeName 18277 ? element.href || isTabIndexNotNaN 18278 : isTabIndexNotNaN) 18279 // the element and all of its ancestors must be visible 18280 && visible( element ); 18281} 18282 18283function visible( element ) { 18284 return !$( element ).parents().andSelf().filter(function() { 18285 return $.curCSS( this, "visibility" ) === "hidden" || 18286 $.expr.filters.hidden( this ); 18287 }).length; 18288} 18289 18290$.extend( $.expr[ ":" ], { 18291 data: function( elem, i, match ) { 18292 return !!$.data( elem, match[ 3 ] ); 18293 }, 18294 18295 focusable: function( element ) { 18296 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); 18297 }, 18298 18299 tabbable: function( element ) { 18300 var tabIndex = $.attr( element, "tabindex" ), 18301 isTabIndexNaN = isNaN( tabIndex ); 18302 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); 18303 } 18304}); 18305 18306// support 18307$(function() { 18308 var body = document.body, 18309 div = body.appendChild( div = document.createElement( "div" ) ); 18310 18311 $.extend( div.style, { 18312 minHeight: "100px", 18313 height: "auto", 18314 padding: 0, 18315 borderWidth: 0 18316 }); 18317 18318 $.support.minHeight = div.offsetHeight === 100; 18319 $.support.selectstart = "onselectstart" in div; 18320 18321 // set display to none to avoid a layout bug in IE 18322 // http://dev.jquery.com/ticket/4014 18323 body.removeChild( div ).style.display = "none"; 18324}); 18325 18326 18327 18328 18329 18330// deprecated 18331$.extend( $.ui, { 18332 // $.ui.plugin is deprecated. Use the proxy pattern instead. 18333 plugin: { 18334 add: function( module, option, set ) { 18335 var proto = $.ui[ module ].prototype; 18336 for ( var i in set ) { 18337 proto.plugins[ i ] = proto.plugins[ i ] || []; 18338 proto.plugins[ i ].push( [ option, set[ i ] ] ); 18339 } 18340 }, 18341 call: function( instance, name, args ) { 18342 var set = instance.plugins[ name ]; 18343 if ( !set || !instance.element[ 0 ].parentNode ) { 18344 return; 18345 } 18346 18347 for ( var i = 0; i < set.length; i++ ) { 18348 if ( instance.options[ set[ i ][ 0 ] ] ) { 18349 set[ i ][ 1 ].apply( instance.element, args ); 18350 } 18351 } 18352 } 18353 }, 18354 18355 // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains() 18356 contains: function( a, b ) { 18357 return document.compareDocumentPosition ? 18358 a.compareDocumentPosition( b ) & 16 : 18359 a !== b && a.contains( b ); 18360 }, 18361 18362 // only used by resizable 18363 hasScroll: function( el, a ) { 18364 18365 //If overflow is hidden, the element might have extra content, but the user wants to hide it 18366 if ( $( el ).css( "overflow" ) === "hidden") { 18367 return false; 18368 } 18369 18370 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", 18371 has = false; 18372 18373 if ( el[ scroll ] > 0 ) { 18374 return true; 18375 } 18376 18377 // TODO: determine which cases actually cause this to happen 18378 // if the element doesn't have the scroll set, see if it's possible to 18379 // set the scroll 18380 el[ scroll ] = 1; 18381 has = ( el[ scroll ] > 0 ); 18382 el[ scroll ] = 0; 18383 return has; 18384 }, 18385 18386 // these are odd functions, fix the API or move into individual plugins 18387 isOverAxis: function( x, reference, size ) { 18388 //Determines when x coordinate is over "b" element axis 18389 return ( x > reference ) && ( x < ( reference + size ) ); 18390 }, 18391 isOver: function( y, x, top, left, height, width ) { 18392 //Determines when x, y coordinates is over "b" element 18393 return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width ); 18394 } 18395}); 18396 18397})( jQuery ); 18398 18399/*! 18400 * jQuery UI Widget 1.8.16 18401 * 18402 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 18403 * Dual licensed under the MIT or GPL Version 2 licenses. 18404 * http://jquery.org/license 18405 * 18406 * http://docs.jquery.com/UI/Widget 18407 */ 18408(function( $, undefined ) { 18409 18410// jQuery 1.4+ 18411if ( $.cleanData ) { 18412 var _cleanData = $.cleanData; 18413 $.cleanData = function( elems ) { 18414 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { 18415 try { 18416 $( elem ).triggerHandler( "remove" ); 18417 // http://bugs.jquery.com/ticket/8235 18418 } catch( e ) {} 18419 } 18420 _cleanData( elems ); 18421 }; 18422} else { 18423 var _remove = $.fn.remove; 18424 $.fn.remove = function( selector, keepData ) { 18425 return this.each(function() { 18426 if ( !keepData ) { 18427 if ( !selector || $.filter( selector, [ this ] ).length ) { 18428 $( "*", this ).add( [ this ] ).each(function() { 18429 try { 18430 $( this ).triggerHandler( "remove" ); 18431 // http://bugs.jquery.com/ticket/8235 18432 } catch( e ) {} 18433 }); 18434 } 18435 } 18436 return _remove.call( $(this), selector, keepData ); 18437 }); 18438 }; 18439} 18440 18441$.widget = function( name, base, prototype ) { 18442 var namespace = name.split( "." )[ 0 ], 18443 fullName; 18444 name = name.split( "." )[ 1 ]; 18445 fullName = namespace + "-" + name; 18446 18447 if ( !prototype ) { 18448 prototype = base; 18449 base = $.Widget; 18450 } 18451 18452 // create selector for plugin 18453 $.expr[ ":" ][ fullName ] = function( elem ) { 18454 return !!$.data( elem, name ); 18455 }; 18456 18457 $[ namespace ] = $[ namespace ] || {}; 18458 $[ namespace ][ name ] = function( options, element ) { 18459 // allow instantiation without initializing for simple inheritance 18460 if ( arguments.length ) { 18461 this._createWidget( options, element ); 18462 } 18463 }; 18464 18465 var basePrototype = new base(); 18466 // we need to make the options hash a property directly on the new instance 18467 // otherwise we'll modify the options hash on the prototype that we're 18468 // inheriting from 18469// $.each( basePrototype, function( key, val ) { 18470// if ( $.isPlainObject(val) ) { 18471// basePrototype[ key ] = $.extend( {}, val ); 18472// } 18473// }); 18474 basePrototype.options = $.extend( true, {}, basePrototype.options ); 18475 $[ namespace ][ name ].prototype = $.extend( true, basePrototype, { 18476 namespace: namespace, 18477 widgetName: name, 18478 widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name, 18479 widgetBaseClass: fullName 18480 }, prototype ); 18481 18482 $.widget.bridge( name, $[ namespace ][ name ] ); 18483}; 18484 18485$.widget.bridge = function( name, object ) { 18486 $.fn[ name ] = function( options ) { 18487 var isMethodCall = typeof options === "string", 18488 args = Array.prototype.slice.call( arguments, 1 ), 18489 returnValue = this; 18490 18491 // allow multiple hashes to be passed on init 18492 options = !isMethodCall && args.length ? 18493 $.extend.apply( null, [ true, options ].concat(args) ) : 18494 options; 18495 18496 // prevent calls to internal methods 18497 if ( isMethodCall && options.charAt( 0 ) === "_" ) { 18498 return returnValue; 18499 } 18500 18501 if ( isMethodCall ) { 18502 this.each(function() { 18503 var instance = $.data( this, name ),
18504 methodValue = instance && $.isFunction( instance[options] ) ? 18505 instance[ options ].apply( instance, args ) : 18506 instance; 18507 // TODO: add this back in 1.9 and use $.error() (see #5972) 18508// if ( !instance ) { 18509// throw "cannot call methods on " + name + " prior to initialization; " + 18510// "attempted to call method '" + options + "'"; 18511// } 18512// if ( !$.isFunction( instance[options] ) ) { 18513// throw "no such method '" + options + "' for " + name + " widget instance"; 18514// } 18515// var methodValue = instance[ options ].apply( instance, args ); 18516 if ( methodValue !== instance && methodValue !== undefined ) { 18517 returnValue = methodValue; 18518 return false; 18519 } 18520 }); 18521 } else { 18522 this.each(function() { 18523 var instance = $.data( this, name ); 18524 if ( instance ) { 18525 instance.option( options || {} )._init(); 18526 } else { 18527 $.data( this, name, new object( options, this ) ); 18528 } 18529 }); 18530 } 18531 18532 return returnValue; 18533 }; 18534}; 18535 18536$.Widget = function( options, element ) { 18537 // allow instantiation without initializing for simple inheritance 18538 if ( arguments.length ) { 18539 this._createWidget( options, element ); 18540 } 18541}; 18542 18543$.Widget.prototype = { 18544 widgetName: "widget", 18545 widgetEventPrefix: "", 18546 options: { 18547 disabled: false 18548 }, 18549 _createWidget: function( options, element ) { 18550 // $.widget.bridge stores the plugin instance, but we do it anyway 18551 // so that it's stored even before the _create function runs 18552 $.data( element, this.widgetName, this ); 18553 this.element = $( element ); 18554 this.options = $.extend( true, {}, 18555 this.options, 18556 this._getCreateOptions(), 18557 options ); 18558 18559 var self = this; 18560 this.element.bind( "remove." + this.widgetName, function() { 18561 self.destroy(); 18562 }); 18563 18564 this._create(); 18565 this._trigger( "create" ); 18566 this._init(); 18567 }, 18568 _getCreateOptions: function() { 18569 return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ]; 18570 }, 18571 _create: function() {}, 18572 _init: function() {}, 18573 18574 destroy: function() { 18575 this.element 18576 .unbind( "." + this.widgetName ) 18577 .removeData( this.widgetName ); 18578 this.widget() 18579 .unbind( "." + this.widgetName ) 18580 .removeAttr( "aria-disabled" ) 18581 .removeClass( 18582 this.widgetBaseClass + "-disabled " + 18583 "ui-state-disabled" ); 18584 }, 18585 18586 widget: function() { 18587 return this.element; 18588 }, 18589 18590 option: function( key, value ) { 18591 var options = key; 18592 18593 if ( arguments.length === 0 ) { 18594 // don't return a reference to the internal hash 18595 return $.extend( {}, this.options ); 18596 } 18597 18598 if (typeof key === "string" ) { 18599 if ( value === undefined ) { 18600 return this.options[ key ]; 18601 } 18602 options = {}; 18603 options[ key ] = value; 18604 } 18605 18606 this._setOptions( options ); 18607 18608 return this; 18609 }, 18610 _setOptions: function( options ) { 18611 var self = this; 18612 $.each( options, function( key, value ) { 18613 self._setOption( key, value ); 18614 }); 18615 18616 return this; 18617 }, 18618 _setOption: function( key, value ) { 18619 this.options[ key ] = value; 18620 18621 if ( key === "disabled" ) { 18622 this.widget() 18623 [ value ? "addClass" : "removeClass"]( 18624 this.widgetBaseClass + "-disabled" + " " + 18625 "ui-state-disabled" ) 18626 .attr( "aria-disabled", value ); 18627 } 18628 18629 return this; 18630 }, 18631 18632 enable: function() { 18633 return this._setOption( "disabled", false ); 18634 }, 18635 disable: function() { 18636 return this._setOption( "disabled", true ); 18637 }, 18638 18639 _trigger: function( type, event, data ) { 18640 var callback = this.options[ type ]; 18641 18642 event = $.Event( event ); 18643 event.type = ( type === this.widgetEventPrefix ? 18644 type : 18645 this.widgetEventPrefix + type ).toLowerCase(); 18646 data = data || {}; 18647 18648 // copy original event properties over to the new event 18649 // this would happen if we could call $.event.fix instead of $.Event 18650 // but we don't have a way to force an event to be fixed multiple times 18651 if ( event.originalEvent ) { 18652 for ( var i = $.event.props.length, prop; i; ) { 18653 prop = $.event.props[ --i ]; 18654 event[ prop ] = event.originalEvent[ prop ]; 18655 } 18656 } 18657 18658 this.element.trigger( event, data ); 18659 18660 return !( $.isFunction(callback) && 18661 callback.call( this.element[0], event, data ) === false || 18662 event.isDefaultPrevented() ); 18663 } 18664}; 18665 18666})( jQuery ); 18667 18668/*! 18669 * jQuery UI Mouse 1.8.16 18670 * 18671 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 18672 * Dual licensed under the MIT or GPL Version 2 licenses. 18673 * http://jquery.org/license 18674 * 18675 * http://docs.jquery.com/UI/Mouse 18676 * 18677 * Depends: 18678 * jquery.ui.widget.js 18679 */ 18680(function( $, undefined ) { 18681 18682var mouseHandled = false;
18683$( document ).mouseup( function( e ) { 18684 mouseHandled = false; 18685}); 18686 18687$.widget("ui.mouse", { 18688 options: { 18689 cancel: ':input,option', 18690 distance: 1, 18691 delay: 0 18692 }, 18693 _mouseInit: function() { 18694 var self = this; 18695 18696 this.element 18697 .bind('mousedown.'+this.widgetName, function(event) { 18698 return self._mouseDown(event); 18699 }) 18700 .bind('click.'+this.widgetName, function(event) { 18701 if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) { 18702 $.removeData(event.target, self.widgetName + '.preventClickEvent'); 18703 event.stopImmediatePropagation(); 18704 return false; 18705 } 18706 }); 18707 18708 this.started = false; 18709 }, 18710 18711 // TODO: make sure destroying one instance of mouse doesn't mess with 18712 // other instances of mouse 18713 _mouseDestroy: function() { 18714 this.element.unbind('.'+this.widgetName); 18715 }, 18716 18717 _mouseDown: function(event) { 18718 // don't let more than one widget handle mouseStart 18719 if( mouseHandled ) { return }; 18720 18721 // we may have missed mouseup (out of window) 18722 (this._mouseStarted && this._mouseUp(event)); 18723 18724 this._mouseDownEvent = event; 18725 18726 var self = this, 18727 btnIsLeft = (event.which == 1), 18728 // event.target.nodeName works around a bug in IE 8 with 18729 // disabled inputs (#7620) 18730 elIsCancel = (typeof this.options.cancel == "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); 18731 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { 18732 return true; 18733 } 18734 18735 this.mouseDelayMet = !this.options.delay; 18736 if (!this.mouseDelayMet) { 18737 this._mouseDelayTimer = setTimeout(function() { 18738 self.mouseDelayMet = true; 18739 }, this.options.delay); 18740 } 18741 18742 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { 18743 this._mouseStarted = (this._mouseStart(event) !== false); 18744 if (!this._mouseStarted) { 18745 event.preventDefault(); 18746 return true; 18747 } 18748 } 18749 18750 // Click event may never have fired (Gecko & Opera) 18751 if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) { 18752 $.removeData(event.target, this.widgetName + '.preventClickEvent'); 18753 } 18754 18755 // these delegates are required to keep context 18756 this._mouseMoveDelegate = function(event) {
18757 return self._mouseMove(event); 18758 }; 18759 this._mouseUpDelegate = function(event) { 18760 return self._mouseUp(event); 18761 }; 18762 $(document) 18763 .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate) 18764 .bind('mouseup.'+this.widgetName, this._mouseUpDelegate); 18765 18766 event.preventDefault(); 18767 18768 mouseHandled = true; 18769 return true; 18770 }, 18771 18772 _mouseMove: function(event) { 18773 // IE mouseup check - mouseup happened when mouse was out of window 18774 if ($.browser.msie && !(document.documentMode >= 9) && !event.button) { 18775 return this._mouseUp(event); 18776 } 18777 18778 if (this._mouseStarted) { 18779 this._mouseDrag(event); 18780 return event.preventDefault(); 18781 } 18782 18783 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { 18784 this._mouseStarted = 18785 (this._mouseStart(this._mouseDownEvent, event) !== false); 18786 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); 18787 } 18788 18789 return !this._mouseStarted; 18790 }, 18791 18792 _mouseUp: function(event) { 18793 $(document) 18794 .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate) 18795 .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate); 18796 18797 if (this._mouseStarted) { 18798 this._mouseStarted = false; 18799 18800 if (event.target == this._mouseDownEvent.target) { 18801 $.data(event.target, this.widgetName + '.preventClickEvent', true); 18802 } 18803 18804 this._mouseStop(event); 18805 } 18806 18807 return false; 18808 }, 18809 18810 _mouseDistanceMet: function(event) { 18811 return (Math.max( 18812 Math.abs(this._mouseDownEvent.pageX - event.pageX), 18813 Math.abs(this._mouseDownEvent.pageY - event.pageY) 18814 ) >= this.options.distance 18815 ); 18816 }, 18817 18818 _mouseDelayMet: function(event) { 18819 return this.mouseDelayMet; 18820 }, 18821 18822 // These are placeholder methods, to be overriden by extending plugin 18823 _mouseStart: function(event) {}, 18824 _mouseDrag: function(event) {}, 18825 _mouseStop: function(event) {}, 18826 _mouseCapture: function(event) { return true; } 18827}); 18828 18829})(jQuery); 18830 18831/* 18832 * jQuery UI Position 1.8.16 18833 * 18834 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 18835 * Dual licensed under the MIT or GPL Version 2 licenses. 18836 * http://jquery.org/license 18837 * 18838 * http://docs.jquery.com/UI/Position 18839 */ 18840(function( $, undefined ) { 18841 18842$.ui = $.ui || {}; 18843 18844var horizontalPositions = /left|center|right/, 18845 verticalPositions = /top|center|bottom/, 18846 center = "center", 18847 _position = $.fn.position, 18848 _offset = $.fn.offset; 18849 18850$.fn.position = function( options ) { 18851 if ( !options || !options.of ) { 18852 return _position.apply( this, arguments ); 18853 } 18854 18855 // make a copy, we don't want to modify arguments 18856 options = $.extend( {}, options ); 18857 18858 var target = $( options.of ), 18859 targetElem = target[0], 18860 collision = ( options.collision || "flip" ).split( " " ), 18861 offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ], 18862 targetWidth, 18863 targetHeight, 18864 basePosition; 18865 18866 if ( targetElem.nodeType === 9 ) { 18867 targetWidth = target.width(); 18868 targetHeight = target.height(); 18869 basePosition = { top: 0, left: 0 }; 18870 // TODO: use $.isWindow() in 1.9 18871 } else if ( targetElem.setTimeout ) { 18872 targetWidth = target.width(); 18873 targetHeight = target.height(); 18874 basePosition = { top: target.scrollTop(), left: target.scrollLeft() }; 18875 } else if ( targetElem.preventDefault ) { 18876 // force left top to allow flipping 18877 options.at = "left top"; 18878 targetWidth = targetHeight = 0; 18879 basePosition = { top: options.of.pageY, left: options.of.pageX }; 18880 } else { 18881 targetWidth = target.outerWidth(); 18882 targetHeight = target.outerHeight(); 18883 basePosition = target.offset(); 18884 } 18885 18886 // force my and at to have valid horizontal and veritcal positions 18887 // if a value is missing or invalid, it will be converted to center 18888 $.each( [ "my", "at" ], function() { 18889 var pos = ( options[this] || "" ).split( " " ); 18890 if ( pos.length === 1) { 18891 pos = horizontalPositions.test( pos[0] ) ? 18892 pos.concat( [center] ) : 18893 verticalPositions.test( pos[0] ) ? 18894 [ center ].concat( pos ) : 18895 [ center, center ]; 18896 } 18897 pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center; 18898 pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center; 18899 options[ this ] = pos; 18900 }); 18901 18902 // normalize collision option 18903 if ( collision.length === 1 ) { 18904 collision[ 1 ] = collision[ 0 ]; 18905 } 18906 18907 // normalize offset option 18908 offset[ 0 ] = parseInt( offset[0], 10 ) || 0; 18909 if ( offset.length === 1 ) { 18910 offset[ 1 ] = offset[ 0 ]; 18911 } 18912 offset[ 1 ] = parseInt( offset[1], 10 ) || 0; 18913 18914 if ( options.at[0] === "right" ) { 18915 basePosition.left += targetWidth; 18916 } else if ( options.at[0] === center ) { 18917 basePosition.left += targetWidth / 2; 18918 } 18919 18920 if ( options.at[1] === "bottom" ) { 18921 basePosition.top += targetHeight; 18922 } else if ( options.at[1] === center ) { 18923 basePosition.top += targetHeight / 2; 18924 } 18925 18926 basePosition.left += offset[ 0 ]; 18927 basePosition.top += offset[ 1 ]; 18928 18929 return this.each(function() { 18930 var elem = $( this ), 18931 elemWidth = elem.outerWidth(), 18932 elemHeight = elem.outerHeight(), 18933 marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0, 18934 marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0, 18935 collisionWidth = elemWidth + marginLeft + 18936 ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ),
18937 collisionHeight = elemHeight + marginTop + 18938 ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ), 18939 position = $.extend( {}, basePosition ), 18940 collisionPosition; 18941 18942 if ( options.my[0] === "right" ) { 18943 position.left -= elemWidth; 18944 } else if ( options.my[0] === center ) { 18945 position.left -= elemWidth / 2; 18946 } 18947 18948 if ( options.my[1] === "bottom" ) { 18949 position.top -= elemHeight; 18950 } else if ( options.my[1] === center ) { 18951 position.top -= elemHeight / 2; 18952 } 18953 18954 // prevent fractions (see #5280) 18955 position.left = Math.round( position.left ); 18956 position.top = Math.round( position.top ); 18957 18958 collisionPosition = { 18959 left: position.left - marginLeft, 18960 top: position.top - marginTop 18961 }; 18962 18963 $.each( [ "left", "top" ], function( i, dir ) { 18964 if ( $.ui.position[ collision[i] ] ) { 18965 $.ui.position[ collision[i] ][ dir ]( position, { 18966 targetWidth: targetWidth, 18967 targetHeight: targetHeight, 18968 elemWidth: elemWidth, 18969 elemHeight: elemHeight, 18970 collisionPosition: collisionPosition, 18971 collisionWidth: collisionWidth, 18972 collisionHeight: collisionHeight, 18973 offset: offset, 18974 my: options.my, 18975 at: options.at 18976 }); 18977 } 18978 }); 18979 18980 if ( $.fn.bgiframe ) { 18981 elem.bgiframe(); 18982 } 18983 elem.offset( $.extend( position, { using: options.using } ) ); 18984 }); 18985}; 18986 18987$.ui.position = { 18988 fit: { 18989 left: function( position, data ) { 18990 var win = $( window ), 18991 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(); 18992 position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left ); 18993 }, 18994 top: function( position, data ) { 18995 var win = $( window ), 18996 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(); 18997 position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top ); 18998 } 18999 }, 19000 19001 flip: { 19002 left: function( position, data ) { 19003 if ( data.at[0] === center ) { 19004 return; 19005 } 19006 var win = $( window ), 19007 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(), 19008 myOffset = data.my[ 0 ] === "left" ? 19009 -data.elemWidth : 19010 data.my[ 0 ] === "right" ? 19011 data.elemWidth : 19012 0, 19013 atOffset = data.at[ 0 ] === "left" ? 19014 data.targetWidth : 19015 -data.targetWidth, 19016 offset = -2 * data.offset[ 0 ]; 19017 position.left += data.collisionPosition.left < 0 ? 19018 myOffset + atOffset + offset : 19019 over > 0 ? 19020 myOffset + atOffset + offset : 19021 0; 19022 }, 19023 top: function( position, data ) { 19024 if ( data.at[1] === center ) { 19025 return; 19026 } 19027 var win = $( window ), 19028 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(), 19029 myOffset = data.my[ 1 ] === "top" ? 19030 -data.elemHeight : 19031 data.my[ 1 ] === "bottom" ? 19032 data.elemHeight : 19033 0, 19034 atOffset = data.at[ 1 ] === "top" ? 19035 data.targetHeight : 19036 -data.targetHeight, 19037 offset = -2 * data.offset[ 1 ]; 19038 position.top += data.collisionPosition.top < 0 ? 19039 myOffset + atOffset + offset : 19040 over > 0 ? 19041 myOffset + atOffset + offset : 19042 0; 19043 } 19044 } 19045}; 19046 19047// offset setter from jQuery 1.4 19048if ( !$.offset.setOffset ) { 19049 $.offset.setOffset = function( elem, options ) { 19050 // set position first, in-case top/left are set even on static elem 19051 if ( /static/.test( $.curCSS( elem, "position" ) ) ) { 19052 elem.style.position = "relative"; 19053 } 19054 var curElem = $( elem ), 19055 curOffset = curElem.offset(), 19056 curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0, 19057 curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0, 19058 props = { 19059 top: (options.top - curOffset.top) + curTop, 19060 left: (options.left - curOffset.left) + curLeft 19061 }; 19062 19063 if ( 'using' in options ) { 19064 options.using.call( elem, props ); 19065 } else { 19066 curElem.css( props ); 19067 } 19068 }; 19069 19070 $.fn.offset = function( options ) { 19071 var elem = this[ 0 ]; 19072 if ( !elem || !elem.ownerDocument ) { return null; } 19073 if ( options ) { 19074 return this.each(function() { 19075 $.offset.setOffset( this, options ); 19076 }); 19077 } 19078 return _offset.call( this ); 19079 }; 19080} 19081 19082}( jQuery )); 19083 19084/* 19085 * jQuery UI Draggable 1.8.16 19086 * 19087 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 19088 * Dual licensed under the MIT or GPL Version 2 licenses. 19089 * http://jquery.org/license 19090 * 19091 * http://docs.jquery.com/UI/Draggables 19092 * 19093 * Depends: 19094 * jquery.ui.core.js 19095 * jquery.ui.mouse.js 19096 * jquery.ui.widget.js 19097 */ 19098(function( $, undefined ) { 19099 19100$.widget("ui.draggable", $.ui.mouse, { 19101 widgetEventPrefix: "drag", 19102 options: { 19103 addClasses: true, 19104 appendTo: "parent", 19105 axis: false, 19106 connectToSortable: false, 19107 containment: false, 19108 cursor: "auto",
19109 cursorAt: false, 19110 grid: false, 19111 handle: false, 19112 helper: "original", 19113 iframeFix: false, 19114 opacity: false, 19115 refreshPositions: false, 19116 revert: false, 19117 revertDuration: 500, 19118 scope: "default", 19119 scroll: true, 19120 scrollSensitivity: 20, 19121 scrollSpeed: 20, 19122 snap: false, 19123 snapMode: "both", 19124 snapTolerance: 20, 19125 stack: false, 19126 zIndex: false 19127 }, 19128 _create: function() { 19129 19130 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position"))) 19131 this.element[0].style.position = 'relative'; 19132 19133 (this.options.addClasses && this.element.addClass("ui-draggable")); 19134 (this.options.disabled && this.element.addClass("ui-draggable-disabled")); 19135 19136 this._mouseInit(); 19137 19138 }, 19139 19140 destroy: function() { 19141 if(!this.element.data('draggable')) return; 19142 this.element 19143 .removeData("draggable") 19144 .unbind(".draggable") 19145 .removeClass("ui-draggable" 19146 + " ui-draggable-dragging" 19147 + " ui-draggable-disabled"); 19148 this._mouseDestroy(); 19149 19150 return this; 19151 }, 19152 19153 _mouseCapture: function(event) { 19154 19155 var o = this.options; 19156 19157 // among others, prevent a drag on a resizable-handle 19158 if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle')) 19159 return false; 19160 19161 //Quit if we're not on a valid handle 19162 this.handle = this._getHandle(event); 19163 if (!this.handle) 19164 return false; 19165 19166 if ( o.iframeFix ) { 19167 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() { 19168 $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>') 19169 .css({ 19170 width: this.offsetWidth+"px", height: this.offsetHeight+"px", 19171 position: "absolute", opacity: "0.001", zIndex: 1000 19172 }) 19173 .css($(this).offset()) 19174 .appendTo("body"); 19175 }); 19176 } 19177 19178 return true; 19179 19180 }, 19181 19182 _mouseStart: function(event) { 19183 19184 var o = this.options; 19185 19186 //Create and append the visible helper 19187 this.helper = this._createHelper(event); 19188 19189 //Cache the helper size 19190 this._cacheHelperProportions(); 19191 19192 //If ddmanager is used for droppables, set the global draggable 19193 if($.ui.ddmanager) 19194 $.ui.ddmanager.current = this; 19195 19196 /* 19197 * - Position generation - 19198 * This block generates everything position related - it's the core of draggables. 19199 */ 19200 19201 //Cache the margins of the original element 19202 this._cacheMargins(); 19203 19204 //Store the helper's css position 19205 this.cssPosition = this.helper.css("position"); 19206 this.scrollParent = this.helper.scrollParent(); 19207 19208 //The element's absolute position on the page minus margins 19209 this.offset = this.positionAbs = this.element.offset(); 19210 this.offset = { 19211 top: this.offset.top - this.margins.top, 19212 left: this.offset.left - this.margins.left 19213 }; 19214 19215 $.extend(this.offset, { 19216 click: { //Where the click happened, relative to the element 19217 left: event.pageX - this.offset.left, 19218 top: event.pageY - this.offset.top 19219 }, 19220 parent: this._getParentOffset(), 19221 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper 19222 }); 19223 19224 //Generate the original position 19225 this.originalPosition = this.position = this._generatePosition(event); 19226 this.originalPageX = event.pageX; 19227 this.originalPageY = event.pageY; 19228 19229 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied 19230 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); 19231 19232 //Set a containment if given in the options 19233 if(o.containment) 19234 this._setContainment(); 19235 19236 //Trigger event + callbacks 19237 if(this._trigger("start", event) === false) { 19238 this._clear(); 19239 return false; 19240 } 19241 19242 //Recache the helper size 19243 this._cacheHelperProportions(); 19244 19245 //Prepare the droppable offsets 19246 if ($.ui.ddmanager && !o.dropBehaviour) 19247 $.ui.ddmanager.prepareOffsets(this, event); 19248 19249 this.helper.addClass("ui-draggable-dragging"); 19250 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position 19251 19252 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) 19253 if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event); 19254 19255 return true; 19256 }, 19257 19258 _mouseDrag: function(event, noPropagation) { 19259 19260 //Compute the helpers position 19261 this.position = this._generatePosition(event); 19262 this.positionAbs = this._convertPositionTo("absolute"); 19263 19264 //Call plugins and callbacks and use the resulting position if something is returned 19265 if (!noPropagation) { 19266 var ui = this._uiHash(); 19267 if(this._trigger('drag', event, ui) === false) { 19268 this._mouseUp({}); 19269 return false;
19270 } 19271 this.position = ui.position; 19272 } 19273 19274 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px'; 19275 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px'; 19276 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event); 19277 19278 return false; 19279 }, 19280 19281 _mouseStop: function(event) { 19282 19283 //If we are using droppables, inform the manager about the drop 19284 var dropped = false; 19285 if ($.ui.ddmanager && !this.options.dropBehaviour) 19286 dropped = $.ui.ddmanager.drop(this, event); 19287 19288 //if a drop comes from outside (a sortable) 19289 if(this.dropped) { 19290 dropped = this.dropped; 19291 this.dropped = false; 19292 } 19293 19294 //if the original element is removed, don't bother to continue if helper is set to "original" 19295 if((!this.element[0] || !this.element[0].parentNode) && this.options.helper == "original") 19296 return false; 19297 19298 if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) { 19299 var self = this; 19300 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { 19301 if(self._trigger("stop", event) !== false) { 19302 self._clear(); 19303 } 19304 }); 19305 } else { 19306 if(this._trigger("stop", event) !== false) { 19307 this._clear(); 19308 } 19309 } 19310 19311 return false; 19312 }, 19313 19314 _mouseUp: function(event) { 19315 if (this.options.iframeFix === true) { 19316 $("div.ui-draggable-iframeFix").each(function() { 19317 this.parentNode.removeChild(this); 19318 }); //Remove frame helpers 19319 } 19320 19321 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) 19322 if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event); 19323 19324 return $.ui.mouse.prototype._mouseUp.call(this, event); 19325 }, 19326 19327 cancel: function() { 19328 19329 if(this.helper.is(".ui-draggable-dragging")) { 19330 this._mouseUp({}); 19331 } else { 19332 this._clear(); 19333 } 19334 19335 return this; 19336 19337 }, 19338 19339 _getHandle: function(event) { 19340 19341 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false; 19342 $(this.options.handle, this.element) 19343 .find("*") 19344 .andSelf() 19345 .each(function() { 19346 if(this == event.target) handle = true; 19347 }); 19348 19349 return handle; 19350 19351 }, 19352 19353 _createHelper: function(event) { 19354 19355 var o = this.options; 19356 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element); 19357 19358 if(!helper.parents('body').length) 19359 helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo)); 19360 19361 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) 19362 helper.css("position", "absolute"); 19363 19364 return helper; 19365 19366 }, 19367 19368 _adjustOffsetFromHelper: function(obj) { 19369 if (typeof obj == 'string') { 19370 obj = obj.split(' '); 19371 } 19372 if ($.isArray(obj)) { 19373 obj = {left: +obj[0], top: +obj[1] || 0}; 19374 } 19375 if ('left' in obj) { 19376 this.offset.click.left = obj.left + this.margins.left; 19377 } 19378 if ('right' in obj) { 19379 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 19380 } 19381 if ('top' in obj) { 19382 this.offset.click.top = obj.top + this.margins.top; 19383 } 19384 if ('bottom' in obj) { 19385 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 19386 } 19387 }, 19388 19389 _getParentOffset: function() { 19390 19391 //Get the offsetParent and cache its position 19392 this.offsetParent = this.helper.offsetParent(); 19393 var po = this.offsetParent.offset(); 19394 19395 // This is a special case where we need to modify a offset calculated on start, since the following happened: 19396 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent 19397 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that 19398 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag 19399 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) { 19400 po.left += this.scrollParent.scrollLeft(); 19401 po.top += this.scrollParent.scrollTop(); 19402 } 19403 19404 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information 19405 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix 19406 po = { top: 0, left: 0 }; 19407 19408 return { 19409 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),
1940910) || 0), 19410 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) 19411 }; 19412 19413 }, 19414 19415 _getRelativeOffset: function() { 19416 19417 if(this.cssPosition == "relative") { 19418 var p = this.element.position(); 19419 return { 19420 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), 19421 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() 19422 }; 19423 } else { 19424 return { top: 0, left: 0 }; 19425 } 19426 19427 }, 19428 19429 _cacheMargins: function() { 19430 this.margins = { 19431 left: (parseInt(this.element.css("marginLeft"),10) || 0), 19432 top: (parseInt(this.element.css("marginTop"),10) || 0), 19433 right: (parseInt(this.element.css("marginRight"),10) || 0), 19434 bottom: (parseInt(this.element.css("marginBottom"),10) || 0) 19435 }; 19436 }, 19437 19438 _cacheHelperProportions: function() { 19439 this.helperProportions = { 19440 width: this.helper.outerWidth(), 19441 height: this.helper.outerHeight() 19442 }; 19443 }, 19444 19445 _setContainment: function() { 19446 19447 var o = this.options; 19448 if(o.containment == 'parent') o.containment = this.helper[0].parentNode; 19449 if(o.containment == 'document' || o.containment == 'window') this.containment = [ 19450 o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left, 19451 o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top, 19452 (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, 19453 (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top 19454 ]; 19455 19456 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) { 19457 var c = $(o.containment); 19458 var ce = c[0]; if(!ce) return; 19459 var co = c.offset(); 19460 var over = ($(ce).css("overflow") != 'hidden'); 19461 19462 this.containment = [ 19463 (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0), 19464 (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0),
19465 (over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right, 19466 (over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top - this.margins.bottom 19467 ]; 19468 this.relative_container = c; 19469 19470 } else if(o.containment.constructor == Array) { 19471 this.containment = o.containment; 19472 } 19473 19474 }, 19475 19476 _convertPositionTo: function(d, pos) { 19477 19478 if(!pos) pos = this.position; 19479 var mod = d == "absolute" ? 1 : -1; 19480 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); 19481 19482 return { 19483 top: ( 19484 pos.top // The absolute mouse position 19485 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent 19486 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) 19487 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) 19488 ), 19489 left: ( 19490 pos.left // The absolute mouse position 19491 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent 19492 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) 19493 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) 19494 ) 19495 }; 19496 19497 }, 19498 19499 _generatePosition: function(event) { 19500 19501 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); 19502 var pageX = event.pageX; 19503 var pageY = event.pageY; 19504 19505 /* 19506 * - Position constraining - 19507 * Constrain the position to a mix of grid, containment. 19508 */ 19509 19510 if(this.originalPosition) { //If we are not dragging yet, we won't check for options 19511 var containment; 19512 if(this.containment) { 19513 if (this.relative_container){ 19514 var co = this.relative_container.offset(); 19515 containment = [ this.containment[0] + co.left, 19516 this.containment[1] + co.top, 19517 this.containment[2] + co.left, 19518 this.containment[3] + co.top ]; 19519 } 19520 else { 19521 containment = this.containment; 19522 } 19523 19524 if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left; 19525 if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top; 19526 if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left; 19527 if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top; 19528 } 19529 19530 if(o.grid) { 19531 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) 19532 var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; 19533 pageY = containment ? (!(top - this.offset.click.top < containment[1] || top - this.offset.click.top > containment[3]) ? top : (!(top - this.offset.click.top < containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; 19534 19535 var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; 19536 pageX = containment ? (!(left - this.offset.click.left < containment[0] || left - this.offset.click.left > containment[2]) ? left : (!(left - this.offset.click.left < containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; 19537 } 19538 19539 } 19540 19541 return { 19542 top: ( 19543 pageY // The absolute mouse position 19544 - this.offset.click.top // Click offset (relative to the element) 19545 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent 19546 - this.offset.parent.top // The offsetParent's offset without borders (offset + border) 19547 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) 19548 ), 19549 left: ( 19550 pageX // The absolute mouse position 19551 - this.offset.click.left // Click offset (relative to the element) 19552 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent 19553 - this.offset.parent.left // The offsetParent's offset without borders (offset + border) 19554 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) 19555 ) 19556 }; 19557 19558 }, 19559 19560 _clear: function() { 19561 this.helper.removeClass("ui-draggable-dragging"); 19562 if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove(); 19563 //if($.ui.ddmanager) $.ui.ddmanager.current = null; 19564 this.helper = null; 19565 this.cancelHelperRemoval = false;
19566 }, 19567 19568 // From now on bulk stuff - mainly helpers 19569 19570 _trigger: function(type, event, ui) { 19571 ui = ui || this._uiHash(); 19572 $.ui.plugin.call(this, type, [event, ui]); 19573 if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins 19574 return $.Widget.prototype._trigger.call(this, type, event, ui); 19575 }, 19576 19577 plugins: {}, 19578 19579 _uiHash: function(event) { 19580 return { 19581 helper: this.helper, 19582 position: this.position, 19583 originalPosition: this.originalPosition, 19584 offset: this.positionAbs 19585 }; 19586 } 19587 19588}); 19589 19590$.extend($.ui.draggable, { 19591 version: "1.8.16" 19592}); 19593 19594$.ui.plugin.add("draggable", "connectToSortable", { 19595 start: function(event, ui) { 19596 19597 var inst = $(this).data("draggable"), o = inst.options, 19598 uiSortable = $.extend({}, ui, { item: inst.element }); 19599 inst.sortables = []; 19600 $(o.connectToSortable).each(function() { 19601 var sortable = $.data(this, 'sortable'); 19602 if (sortable && !sortable.options.disabled) { 19603 inst.sortables.push({ 19604 instance: sortable, 19605 shouldRevert: sortable.options.revert 19606 }); 19607 sortable.refreshPositions(); // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page). 19608 sortable._trigger("activate", event, uiSortable); 19609 } 19610 }); 19611 19612 }, 19613 stop: function(event, ui) { 19614 19615 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper 19616 var inst = $(this).data("draggable"), 19617 uiSortable = $.extend({}, ui, { item: inst.element }); 19618 19619 $.each(inst.sortables, function() { 19620 if(this.instance.isOver) { 19621 19622 this.instance.isOver = 0; 19623 19624 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance 19625 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work) 19626 19627 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid' 19628 if(this.shouldRevert) this.instance.options.revert = true; 19629 19630 //Trigger the stop of the sortable 19631 this.instance._mouseStop(event); 19632 19633 this.instance.options.helper = this.instance.options._helper; 19634 19635 //If the helper has been the original item, restore properties in the sortable 19636 if(inst.options.helper == 'original') 19637 this.instance.currentItem.css({ top: 'auto', left: 'auto' }); 19638 19639 } else { 19640 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance 19641 this.instance._trigger("deactivate", event, uiSortable); 19642 } 19643 19644 }); 19645 19646 }, 19647 drag: function(event, ui) { 19648 19649 var inst = $(this).data("draggable"), self = this; 19650 19651 var checkPos = function(o) { 19652 var dyClick = this.offset.click.top, dxClick = this.offset.click.left; 19653 var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left; 19654 var itemHeight = o.height, itemWidth = o.width; 19655 var itemTop = o.top, itemLeft = o.left; 19656 19657 return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth); 19658 }; 19659 19660 $.each(inst.sortables, function(i) { 19661 19662 //Copy over some variables to allow calling the sortable's native _intersectsWith 19663 this.instance.positionAbs = inst.positionAbs; 19664 this.instance.helperProportions = inst.helperProportions; 19665 this.instance.offset.click = inst.offset.click; 19666 19667 if(this.instance._intersectsWith(this.instance.containerCache)) { 19668 19669 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once 19670 if(!this.instance.isOver) { 19671 19672 this.instance.isOver = 1; 19673 //Now we fake the start of dragging for the sortable instance, 19674 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem 19675 //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one) 19676 this.instance.currentItem = $(self).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true); 19677 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it 19678 this.instance.options.helper = function() { return ui.helper[0]; }; 19679 19680 event.target = this.instance.currentItem[0]; 19681 this.instance._mouseCapture(event, true); 19682 this.instance._mouseStart(event, true, true); 19683
19684 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes 19685 this.instance.offset.click.top = inst.offset.click.top; 19686 this.instance.offset.click.left = inst.offset.click.left; 19687 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left; 19688 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top; 19689 19690 inst._trigger("toSortable", event); 19691 inst.dropped = this.instance.element; //draggable revert needs that 19692 //hack so receive/update callbacks work (mostly) 19693 inst.currentItem = inst.element; 19694 this.instance.fromOutside = inst; 19695 19696 } 19697 19698 //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable 19699 if(this.instance.currentItem) this.instance._mouseDrag(event); 19700 19701 } else { 19702 19703 //If it doesn't intersect with the sortable, and it intersected before, 19704 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval 19705 if(this.instance.isOver) { 19706 19707 this.instance.isOver = 0; 19708 this.instance.cancelHelperRemoval = true; 19709 19710 //Prevent reverting on this forced stop 19711 this.instance.options.revert = false; 19712 19713 // The out event needs to be triggered independently 19714 this.instance._trigger('out', event, this.instance._uiHash(this.instance)); 19715 19716 this.instance._mouseStop(event, true); 19717 this.instance.options.helper = this.instance.options._helper; 19718 19719 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size 19720 this.instance.currentItem.remove(); 19721 if(this.instance.placeholder) this.instance.placeholder.remove(); 19722 19723 inst._trigger("fromSortable", event); 19724 inst.dropped = false; //draggable revert needs that 19725 } 19726 19727 }; 19728 19729 }); 19730 19731 } 19732}); 19733 19734$.ui.plugin.add("draggable", "cursor", { 19735 start: function(event, ui) { 19736 var t = $('body'), o = $(this).data('draggable').options; 19737 if (t.css("cursor")) o._cursor = t.css("cursor"); 19738 t.css("cursor", o.cursor); 19739 }, 19740 stop: function(event, ui) { 19741 var o = $(this).data('draggable').options; 19742 if (o._cursor) $('body').css("cursor", o._cursor); 19743 } 19744}); 19745 19746$.ui.plugin.add("draggable", "opacity", { 19747 start: function(event, ui) { 19748 var t = $(ui.helper), o = $(this).data('draggable').options; 19749 if(t.css("opacity")) o._opacity = t.css("opacity"); 19750 t.css('opacity', o.opacity); 19751 }, 19752 stop: function(event, ui) { 19753 var o = $(this).data('draggable').options; 19754 if(o._opacity) $(ui.helper).css('opacity', o._opacity); 19755 } 19756}); 19757 19758$.ui.plugin.add("draggable", "scroll", { 19759 start: function(event, ui) { 19760 var i = $(this).data("draggable"); 19761 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset(); 19762 }, 19763 drag: function(event, ui) { 19764 19765 var i = $(this).data("draggable"), o = i.options, scrolled = false; 19766 19767 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') { 19768 19769 if(!o.axis || o.axis != 'x') { 19770 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) 19771 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed; 19772 else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) 19773 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed; 19774 } 19775 19776 if(!o.axis || o.axis != 'y') { 19777 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) 19778 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed; 19779 else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) 19780 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed; 19781 } 19782 19783 } else { 19784 19785 if(!o.axis || o.axis != 'x') { 19786 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) 19787 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); 19788 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) 19789 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); 19790 } 19791 19792 if(!o.axis || o.axis != 'y') { 19793 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) 19794 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); 19795 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) 19796 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); 19797 } 19798 19799 } 19800 19801 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) 19802 $.ui.ddmanager.prepareOffsets(i, event); 19803 19804 } 19805}); 19806 19807$.ui.plugin.add("draggable", "snap", { 19808 start: function(event, ui) { 19809 19810 var i = $(this).data("draggable"), o = i.options; 19811 i.snapElements = []; 19812 19813 $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() { 19814 var $t = $(this); var $o = $t.offset(); 19815 if(this != i.element[0]) i.snapElements.push({ 19816 item: this, 19817 width: $t.outerWidth(), height: $t.outerHeight(), 19818 top: $o.top, left: $o.left 19819 }); 19820 }); 19821 19822 }, 19823 drag: function(event, ui) { 19824 19825 var inst = $(this).data("draggable"), o = inst.options; 19826 var d = o.snapTolerance; 19827 19828 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, 19829 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; 19830 19831 for (var i = inst.snapElements.length - 1; i >= 0; i--){ 19832 19833 var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width, 19834 t = inst.snapElements[i].top, b = t + inst.snapElements[i].height; 19835 19836 //Yes, I know, this is insane ;) 19837 if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) { 19838 if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); 19839 inst.snapElements[i].snapping = false;
19840 continue; 19841 } 19842 19843 if(o.snapMode != 'inner') { 19844 var ts = Math.abs(t - y2) <= d; 19845 var bs = Math.abs(b - y1) <= d; 19846 var ls = Math.abs(l - x2) <= d; 19847 var rs = Math.abs(r - x1) <= d; 19848 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top; 19849 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top; 19850 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left; 19851 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left; 19852 } 19853 19854 var first = (ts || bs || ls || rs); 19855 19856 if(o.snapMode != 'outer') { 19857 var ts = Math.abs(t - y1) <= d; 19858 var bs = Math.abs(b - y2) <= d; 19859 var ls = Math.abs(l - x1) <= d; 19860 var rs = Math.abs(r - x2) <= d; 19861 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top; 19862 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top; 19863 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left; 19864 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left; 19865 } 19866 19867 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) 19868 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); 19869 inst.snapElements[i].snapping = (ts || bs || ls || rs || first); 19870 19871 }; 19872 19873 } 19874}); 19875 19876$.ui.plugin.add("draggable", "stack", { 19877 start: function(event, ui) { 19878 19879 var o = $(this).data("draggable").options; 19880 19881 var group = $.makeArray($(o.stack)).sort(function(a,b) { 19882 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0); 19883 }); 19884 if (!group.length) { return; } 19885 19886 var min = parseInt(group[0].style.zIndex) || 0; 19887 $(group).each(function(i) { 19888 this.style.zIndex = min + i; 19889 }); 19890 19891 this[0].style.zIndex = min + group.length; 19892 19893 } 19894}); 19895 19896$.ui.plugin.add("draggable", "zIndex", { 19897 start: function(event, ui) { 19898 var t = $(ui.helper), o = $(this).data("draggable").options; 19899 if(t.css("zIndex")) o._zIndex = t.css("zIndex"); 19900 t.css('zIndex', o.zIndex); 19901 }, 19902 stop: function(event, ui) { 19903 var o = $(this).data("draggable").options; 19904 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex); 19905 } 19906}); 19907 19908})(jQuery); 19909 19910/* 19911 * jQuery UI Droppable 1.8.16 19912 * 19913 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 19914 * Dual licensed under the MIT or GPL Version 2 licenses. 19915 * http://jquery.org/license 19916 * 19917 * http://docs.jquery.com/UI/Droppables 19918 * 19919 * Depends: 19920 * jquery.ui.core.js 19921 * jquery.ui.widget.js 19922 * jquery.ui.mouse.js 19923 * jquery.ui.draggable.js 19924 */ 19925(function( $, undefined ) { 19926 19927$.widget("ui.droppable", { 19928 widgetEventPrefix: "drop", 19929 options: { 19930 accept: '*', 19931 activeClass: false, 19932 addClasses: true, 19933 greedy: false, 19934 hoverClass: false, 19935 scope: 'default', 19936 tolerance: 'intersect' 19937 }, 19938 _create: function() { 19939 19940 var o = this.options, accept = o.accept; 19941 this.isover = 0; this.isout = 1; 19942 19943 this.accept = $.isFunction(accept) ? accept : function(d) { 19944 return d.is(accept); 19945 }; 19946 19947 //Store the droppable's proportions 19948 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight }; 19949 19950 // Add the reference and positions to the manager 19951 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || []; 19952 $.ui.ddmanager.droppables[o.scope].push(this); 19953 19954 (o.addClasses && this.element.addClass("ui-droppable")); 19955 19956 }, 19957 19958 destroy: function() { 19959 var drop = $.ui.ddmanager.droppables[this.options.scope]; 19960 for ( var i = 0; i < drop.length; i++ ) 19961 if ( drop[i] == this ) 19962 drop.splice(i, 1); 19963 19964 this.element 19965 .removeClass("ui-droppable ui-droppable-disabled") 19966 .removeData("droppable") 19967 .unbind(".droppable"); 19968 19969 return this; 19970 }, 19971 19972 _setOption: function(key, value) { 19973 19974 if(key == 'accept') { 19975 this.accept = $.isFunction(value) ? value : function(d) { 19976 return d.is(value); 19977 }; 19978 } 19979 $.Widget.prototype._setOption.apply(this, arguments); 19980 }, 19981 19982 _activate: function(event) { 19983 var draggable = $.ui.ddmanager.current; 19984 if(this.options.activeClass) this.element.addClass(this.options.activeClass); 19985 (draggable && this._trigger('activate', event, this.ui(draggable))); 19986 }, 19987 19988 _deactivate: function(event) { 19989 var draggable = $.ui.ddmanager.current; 19990 if(this.options.activeClass) this.element.removeClass(this.options.activeClass); 19991 (draggable && this._trigger('deactivate', event, this.ui(draggable))); 19992 }, 19993 19994 _over: function(event) { 19995 19996 var draggable = $.ui.ddmanager.current; 19997 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element 19998 19999 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 20000 if(this.options.hoverClass) this.element.addClass(this.options.hoverClass); 20001 this._trigger('over', event, this.ui(draggable)); 20002 } 20003 20004 }, 20005 20006 _out: function(event) { 20007 20008 var draggable = $.ui.ddmanager.current; 20009 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element 20010 20011 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 20012 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); 20013 this._trigger('out', event, this.ui(draggable)); 20014 } 20015 20016 }, 20017 20018 _drop: function(event,custom) { 20019 20020 var draggable = custom || $.ui.ddmanager.current; 20021 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element 20022 20023 var childrenIntersection = false;
20024 this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() { 20025 var inst = $.data(this, 'droppable'); 20026 if( 20027 inst.options.greedy 20028 && !inst.options.disabled 20029 && inst.options.scope == draggable.options.scope 20030 && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) 20031 && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance) 20032 ) { childrenIntersection = true; return false; } 20033 }); 20034 if(childrenIntersection) return false; 20035 20036 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 20037 if(this.options.activeClass) this.element.removeClass(this.options.activeClass); 20038 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); 20039 this._trigger('drop', event, this.ui(draggable)); 20040 return this.element; 20041 } 20042 20043 return false; 20044 20045 }, 20046 20047 ui: function(c) { 20048 return { 20049 draggable: (c.currentItem || c.element), 20050 helper: c.helper, 20051 position: c.position, 20052 offset: c.positionAbs 20053 }; 20054 } 20055 20056}); 20057 20058$.extend($.ui.droppable, { 20059 version: "1.8.16" 20060}); 20061 20062$.ui.intersect = function(draggable, droppable, toleranceMode) { 20063 20064 if (!droppable.offset) return false; 20065 20066 var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width, 20067 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height; 20068 var l = droppable.offset.left, r = l + droppable.proportions.width, 20069 t = droppable.offset.top, b = t + droppable.proportions.height; 20070 20071 switch (toleranceMode) { 20072 case 'fit': 20073 return (l <= x1 && x2 <= r 20074 && t <= y1 && y2 <= b); 20075 break; 20076 case 'intersect': 20077 return (l < x1 + (draggable.helperProportions.width / 2) // Right Half 20078 && x2 - (draggable.helperProportions.width / 2) < r // Left Half 20079 && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half 20080 && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half 20081 break; 20082 case 'pointer': 20083 var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left), 20084 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top), 20085 isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width); 20086 return isOver; 20087 break; 20088 case 'touch': 20089 return ( 20090 (y1 >= t && y1 <= b) || // Top edge touching 20091 (y2 >= t && y2 <= b) || // Bottom edge touching 20092 (y1 < t && y2 > b) // Surrounded vertically 20093 ) && ( 20094 (x1 >= l && x1 <= r) || // Left edge touching 20095 (x2 >= l && x2 <= r) || // Right edge touching 20096 (x1 < l && x2 > r) // Surrounded horizontally 20097 ); 20098 break; 20099 default: 20100 return false; 20101 break; 20102 } 20103 20104}; 20105 20106/* 20107 This manager tracks offsets of draggables and droppables 20108*/ 20109$.ui.ddmanager = { 20110 current: null, 20111 droppables: { 'default': [] }, 20112 prepareOffsets: function(t, event) { 20113 20114 var m = $.ui.ddmanager.droppables[t.options.scope] || []; 20115 var type = event ? event.type : null; // workaround for #2317 20116 var list = (t.currentItem || t.element).find(":data(droppable)").andSelf(); 20117 20118 droppablesLoop: for (var i = 0; i < m.length; i++) { 20119 20120 if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted 20121 for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item 20122 m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue 20123 20124 if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables 20125 20126 m[i].offset = m[i].element.offset(); 20127 m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight }; 20128 20129 } 20130 20131 }, 20132 drop: function(draggable, event) { 20133 20134 var dropped = false;
20135 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { 20136 20137 if(!this.options) return; 20138 if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) 20139 dropped = dropped || this._drop.call(this, event); 20140 20141 if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 20142 this.isout = 1; this.isover = 0; 20143 this._deactivate.call(this, event); 20144 } 20145 20146 }); 20147 return dropped; 20148 20149 }, 20150 dragStart: function( draggable, event ) { 20151 //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003) 20152 draggable.element.parents( ":not(body,html)" ).bind( "scroll.droppable", function() { 20153 if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event ); 20154 }); 20155 }, 20156 drag: function(draggable, event) { 20157 20158 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. 20159 if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event); 20160 20161 //Run through all droppables and check their positions based on specific tolerance options 20162 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { 20163 20164 if(this.options.disabled || this.greedyChild || !this.visible) return; 20165 var intersects = $.ui.intersect(draggable, this, this.options.tolerance); 20166 20167 var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null); 20168 if(!c) return; 20169 20170 var parentInstance; 20171 if (this.options.greedy) { 20172 var parent = this.element.parents(':data(droppable):eq(0)'); 20173 if (parent.length) { 20174 parentInstance = $.data(parent[0], 'droppable'); 20175 parentInstance.greedyChild = (c == 'isover' ? 1 : 0); 20176 } 20177 } 20178 20179 // we just moved into a greedy child 20180 if (parentInstance && c == 'isover') { 20181 parentInstance['isover'] = 0; 20182 parentInstance['isout'] = 1; 20183 parentInstance._out.call(parentInstance, event); 20184 } 20185 20186 this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0; 20187 this[c == "isover" ? "_over" : "_out"].call(this, event); 20188 20189 // we just moved out of a greedy child 20190 if (parentInstance && c == 'isout') { 20191 parentInstance['isout'] = 0; 20192 parentInstance['isover'] = 1; 20193 parentInstance._over.call(parentInstance, event); 20194 } 20195 }); 20196 20197 }, 20198 dragStop: function( draggable, event ) { 20199 draggable.element.parents( ":not(body,html)" ).unbind( "scroll.droppable" ); 20200 //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003) 20201 if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event ); 20202 } 20203}; 20204 20205})(jQuery); 20206 20207/* 20208 * jQuery UI Resizable 1.8.16 20209 * 20210 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 20211 * Dual licensed under the MIT or GPL Version 2 licenses. 20212 * http://jquery.org/license 20213 * 20214 * http://docs.jquery.com/UI/Resizables 20215 * 20216 * Depends: 20217 * jquery.ui.core.js 20218 * jquery.ui.mouse.js 20219 * jquery.ui.widget.js 20220 */ 20221(function( $, undefined ) { 20222 20223$.widget("ui.resizable", $.ui.mouse, { 20224 widgetEventPrefix: "resize", 20225 options: { 20226 alsoResize: false, 20227 animate: false, 20228 animateDuration: "slow", 20229 animateEasing: "swing", 20230 aspectRatio: false, 20231 autoHide: false, 20232 containment: false, 20233 ghost: false, 20234 grid: false, 20235 handles: "e,s,se", 20236 helper: false, 20237 maxHeight: null, 20238 maxWidth: null, 20239 minHeight: 10, 20240 minWidth: 10, 20241 zIndex: 1000 20242 }, 20243 _create: function() { 20244 20245 var self = this, o = this.options; 20246 this.element.addClass("ui-resizable"); 20247 20248 $.extend(this, { 20249 _aspectRatio: !!(o.aspectRatio), 20250 aspectRatio: o.aspectRatio, 20251 originalElement: this.element, 20252 _proportionallyResizeElements: [], 20253 _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null 20254 }); 20255 20256 //Wrap the element if it cannot hold child nodes 20257 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) { 20258 20259 //Opera fix for relative positioning 20260 if (/relative/.test(this.element.css('position')) && $.browser.opera) 20261 this.element.css({ position: 'relative', top: 'auto', left: 'auto' }); 20262 20263 //Create a wrapper element and set the wrapper to the new current internal element 20264 this.element.wrap( 20265 $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({ 20266 position: this.element.css('position'), 20267 width: this.element.outerWidth(), 20268 height: this.element.outerHeight(), 20269 top: this.element.css('top'), 20270 left: this.element.css('left') 20271 }) 20272 ); 20273 20274 //Overwrite the original this.element 20275 this.element = this.element.parent().data( 20276 "resizable", this.element.data('resizable') 20277 ); 20278 20279 this.elementIsWrapper = true; 20280 20281 //Move margins to the wrapper 20282 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") }); 20283 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0}); 20284 20285 //Prevent Safari textarea resize 20286 this.originalResizeStyle = this.originalElement.css('resize'); 20287 this.originalElement.css('resize', 'none'); 20288 20289 //Push the actual element to our proportionallyResize internal array 20290 this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' })); 20291 20292 // avoid IE jump (hard set the margin) 20293 this.originalElement.css({ margin: this.originalElement.css('margin') }); 20294 20295 // fix handlers offset 20296 this._proportionallyResize(); 20297 20298 } 20299 20300 this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' }); 20301 if(this.handles.constructor == String) { 20302 20303 if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw'; 20304 var n = this.handles.split(","); this.handles = {}; 20305 20306 for(var i = 0; i < n.length; i++) { 20307 20308 var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle; 20309 var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>'); 20310 20311 // increase zIndex of sw, se, ne, nw axis 20312 //TODO : this modifies original option 20313 if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex }); 20314 20315 //TODO : What's going on here? 20316 if ('se' == handle) { 20317 axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se'); 20318 }; 20319 20320 //Insert into internal handles object and append to element 20321 this.handles[handle] = '.ui-resizable-'+handle; 20322 this.element.append(axis); 20323 } 20324 20325 } 20326 20327 this._renderAxis = function(target) { 20328 20329 target = target || this.element; 20330 20331 for(var i in this.handles) { 20332 20333 if(this.handles[i].constructor == String) 20334 this.handles[i] = $(this.handles[i], this.element).show(); 20335 20336 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls) 20337 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) { 20338 20339 var axis = $(this.handles[i], this.element), padWrapper = 0; 20340 20341 //Checking the correct pad and border 20342 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); 20343 20344 //The padding type i have to apply... 20345 var padPos = [ 'padding',
20346 /ne|nw|n/.test(i) ? 'Top' : 20347 /se|sw|s/.test(i) ? 'Bottom' : 20348 /^e$/.test(i) ? 'Right' : 'Left' ].join(""); 20349 20350 target.css(padPos, padWrapper); 20351 20352 this._proportionallyResize(); 20353 20354 } 20355 20356 //TODO: What's that good for? There's not anything to be executed left 20357 if(!$(this.handles[i]).length) 20358 continue; 20359 20360 } 20361 }; 20362 20363 //TODO: make renderAxis a prototype function 20364 this._renderAxis(this.element); 20365 20366 this._handles = $('.ui-resizable-handle', this.element) 20367 .disableSelection(); 20368 20369 //Matching axis name 20370 this._handles.mouseover(function() { 20371 if (!self.resizing) { 20372 if (this.className) 20373 var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); 20374 //Axis, default = se 20375 self.axis = axis && axis[1] ? axis[1] : 'se'; 20376 } 20377 }); 20378 20379 //If we want to auto hide the elements 20380 if (o.autoHide) { 20381 this._handles.hide(); 20382 $(this.element) 20383 .addClass("ui-resizable-autohide") 20384 .hover(function() { 20385 if (o.disabled) return; 20386 $(this).removeClass("ui-resizable-autohide"); 20387 self._handles.show(); 20388 }, 20389 function(){ 20390 if (o.disabled) return; 20391 if (!self.resizing) { 20392 $(this).addClass("ui-resizable-autohide"); 20393 self._handles.hide(); 20394 } 20395 }); 20396 } 20397 20398 //Initialize the mouse interaction 20399 this._mouseInit(); 20400 20401 }, 20402 20403 destroy: function() { 20404 20405 this._mouseDestroy(); 20406 20407 var _destroy = function(exp) { 20408 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing") 20409 .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove(); 20410 }; 20411 20412 //TODO: Unwrap at same DOM position 20413 if (this.elementIsWrapper) { 20414 _destroy(this.element); 20415 var wrapper = this.element; 20416 wrapper.after( 20417 this.originalElement.css({ 20418 position: wrapper.css('position'), 20419 width: wrapper.outerWidth(), 20420 height: wrapper.outerHeight(), 20421 top: wrapper.css('top'), 20422 left: wrapper.css('left') 20423 }) 20424 ).remove(); 20425 } 20426 20427 this.originalElement.css('resize', this.originalResizeStyle); 20428 _destroy(this.originalElement); 20429 20430 return this; 20431 }, 20432 20433 _mouseCapture: function(event) { 20434 var handle = false; 20435 for (var i in this.handles) { 20436 if ($(this.handles[i])[0] == event.target) { 20437 handle = true; 20438 } 20439 } 20440 20441 return !this.options.disabled && handle; 20442 }, 20443 20444 _mouseStart: function(event) { 20445 20446 var o = this.options, iniPos = this.element.position(), el = this.element; 20447 20448 this.resizing = true; 20449 this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() }; 20450 20451 // bugfix for http://dev.jquery.com/ticket/1749 20452 if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) { 20453 el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left }); 20454 } 20455 20456 //Opera fixing relative position 20457 if ($.browser.opera && (/relative/).test(el.css('position'))) 20458 el.css({ position: 'relative', top: 'auto', left: 'auto' }); 20459 20460 this._renderProxy(); 20461 20462 var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top')); 20463 20464 if (o.containment) { 20465 curleft += $(o.containment).scrollLeft() || 0; 20466 curtop += $(o.containment).scrollTop() || 0; 20467 } 20468 20469 //Store needed variables 20470 this.offset = this.helper.offset(); 20471 this.position = { left: curleft, top: curtop }; 20472 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; 20473 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; 20474 this.originalPosition = { left: curleft, top: curtop }; 20475 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() }; 20476 this.originalMousePosition = { left: event.pageX, top: event.pageY }; 20477 20478 //Aspect Ratio 20479 this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1); 20480 20481 var cursor = $('.ui-resizable-' + this.axis).css('cursor'); 20482 $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor); 20483 20484 el.addClass("ui-resizable-resizing"); 20485 this._propagate("start", event); 20486 return true; 20487 }, 20488 20489 _mouseDrag: function(event) { 20490 20491 //Increase performance, avoid regex 20492 var el = this.helper, o = this.options, props = {}, 20493 self = this, smp = this.originalMousePosition, a = this.axis; 20494 20495 var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0; 20496 var trigger = this._change[a]; 20497 if (!trigger) return false;
20498 20499 // Calculate the attrs that will be change 20500 var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff; 20501 20502 // Put this in the mouseDrag handler since the user can start pressing shift while resizing 20503 this._updateVirtualBoundaries(event.shiftKey); 20504 if (this._aspectRatio || event.shiftKey) 20505 data = this._updateRatio(data, event); 20506 20507 data = this._respectSize(data, event); 20508 20509 // plugins callbacks need to be called first 20510 this._propagate("resize", event); 20511 20512 el.css({ 20513 top: this.position.top + "px", left: this.position.left + "px", 20514 width: this.size.width + "px", height: this.size.height + "px" 20515 }); 20516 20517 if (!this._helper && this._proportionallyResizeElements.length) 20518 this._proportionallyResize(); 20519 20520 this._updateCache(data); 20521 20522 // calling the user callback at the end 20523 this._trigger('resize', event, this.ui()); 20524 20525 return false; 20526 }, 20527 20528 _mouseStop: function(event) { 20529 20530 this.resizing = false; 20531 var o = this.options, self = this; 20532 20533 if(this._helper) { 20534 var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), 20535 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height, 20536 soffsetw = ista ? 0 : self.sizeDiff.width; 20537 20538 var s = { width: (self.helper.width() - soffsetw), height: (self.helper.height() - soffseth) }, 20539 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null, 20540 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null; 20541 20542 if (!o.animate) 20543 this.element.css($.extend(s, { top: top, left: left })); 20544 20545 self.helper.height(self.size.height); 20546 self.helper.width(self.size.width); 20547 20548 if (this._helper && !o.animate) this._proportionallyResize(); 20549 } 20550 20551 $('body').css('cursor', 'auto'); 20552 20553 this.element.removeClass("ui-resizable-resizing"); 20554 20555 this._propagate("stop", event); 20556 20557 if (this._helper) this.helper.remove(); 20558 return false; 20559 20560 }, 20561 20562 _updateVirtualBoundaries: function(forceAspectRatio) { 20563 var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b; 20564 20565 b = { 20566 minWidth: isNumber(o.minWidth) ? o.minWidth : 0, 20567 maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity, 20568 minHeight: isNumber(o.minHeight) ? o.minHeight : 0, 20569 maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity 20570 }; 20571 20572 if(this._aspectRatio || forceAspectRatio) { 20573 // We want to create an enclosing box whose aspect ration is the requested one 20574 // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension 20575 pMinWidth = b.minHeight * this.aspectRatio; 20576 pMinHeight = b.minWidth / this.aspectRatio; 20577 pMaxWidth = b.maxHeight * this.aspectRatio; 20578 pMaxHeight = b.maxWidth / this.aspectRatio; 20579 20580 if(pMinWidth > b.minWidth) b.minWidth = pMinWidth; 20581 if(pMinHeight > b.minHeight) b.minHeight = pMinHeight; 20582 if(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth; 20583 if(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight; 20584 } 20585 this._vBoundaries = b; 20586 }, 20587 20588 _updateCache: function(data) { 20589 var o = this.options; 20590 this.offset = this.helper.offset(); 20591 if (isNumber(data.left)) this.position.left = data.left; 20592 if (isNumber(data.top)) this.position.top = data.top; 20593 if (isNumber(data.height)) this.size.height = data.height; 20594 if (isNumber(data.width)) this.size.width = data.width; 20595 }, 20596 20597 _updateRatio: function(data, event) { 20598 20599 var o = this.options, cpos = this.position, csize = this.size, a = this.axis; 20600 20601 if (isNumber(data.height)) data.width = (data.height * this.aspectRatio); 20602 else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio); 20603 20604 if (a == 'sw') { 20605 data.left = cpos.left + (csize.width - data.width); 20606 data.top = null; 20607 } 20608 if (a == 'nw') { 20609 data.top = cpos.top + (csize.height - data.height); 20610 data.left = cpos.left + (csize.width - data.width); 20611 } 20612 20613 return data; 20614 }, 20615 20616 _respectSize: function(data, event) { 20617 20618 var el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis, 20619 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), 20620 isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height); 20621 20622 if (isminw) data.width = o.minWidth; 20623 if (isminh) data.height = o.minHeight; 20624 if (ismaxw) data.width = o.maxWidth; 20625 if (ismaxh) data.height = o.maxHeight; 20626 20627 var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height; 20628 var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); 20629 20630 if (isminw && cw) data.left = dw - o.minWidth; 20631 if (ismaxw && cw) data.left = dw - o.maxWidth; 20632 if (isminh && ch) data.top = dh - o.minHeight; 20633 if (ismaxh && ch) data.top = dh - o.maxHeight; 20634 20635 // fixing jump error on top/left - bug #2330 20636 var isNotwh = !data.width && !data.height; 20637 if (isNotwh && !data.left && data.top) data.top = null; 20638 else if (isNotwh && !data.top && data.left) data.left = null; 20639 20640 return data; 20641 }, 20642 20643 _proportionallyResize: function() { 20644 20645 var o = this.options; 20646 if (!this._proportionallyResizeElements.length) return; 20647 var element = this.helper || this.element; 20648 20649 for (var i=0; i < this._proportionallyResizeElements.length; i++) { 20650 20651 var prel = this._proportionallyResizeElements[i]; 20652 20653 if (!this.borderDif) { 20654 var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')], 20655 p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')]; 20656 20657 this.borderDif = $.map(b, function(v, i) { 20658 var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0; 20659 return border + padding; 20660 }); 20661 } 20662 20663 if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length))) 20664 continue; 20665 20666 prel.css({ 20667 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0, 20668 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0 20669 }); 20670 20671 }; 20672 20673 }, 20674 20675 _renderProxy: function() { 20676 20677 var el = this.element, o = this.options; 20678 this.elementOffset = el.offset(); 20679 20680 if(this._helper) { 20681 20682 this.helper = this.helper || $('<div style="overflow:hidden;"></div>'); 20683 20684 // fix ie6 offset TODO: This seems broken 20685 var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0), 20686 pxyoffset = ( ie6 ? 2 : -1 ); 20687 20688 this.helper.addClass(this._helper).css({ 20689 width: this.element.outerWidth() + pxyoffset, 20690 height: this.element.outerHeight() + pxyoffset, 20691 position: 'absolute', 20692 left: this.elementOffset.left - ie6offset +'px', 20693 top: this.elementOffset.top - ie6offset +'px', 20694 zIndex: ++o.zIndex //TODO: Don't modify option 20695 }); 20696 20697 this.helper 20698 .appendTo("body") 20699 .disableSelection(); 20700 20701 } else { 20702 this.helper = this.element; 20703 } 20704 20705 }, 20706 20707 _change: { 20708 e: function(event, dx, dy) { 20709 return { width: this.originalSize.width + dx }; 20710 }, 20711 w: function(event, dx, dy) { 20712 var o = this.options, cs = this.originalSize, sp = this.originalPosition; 20713 return { left: sp.left + dx, width: cs.width - dx }; 20714 }, 20715 n: function(event, dx, dy) { 20716 var o = this.options, cs = this.originalSize, sp = this.originalPosition; 20717 return { top: sp.top + dy, height: cs.height - dy }; 20718 }, 20719 s: function(event, dx, dy) { 20720 return { height: this.originalSize.height + dy }; 20721 }, 20722 se: function(event, dx, dy) { 20723 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); 20724 }, 20725 sw: function(event, dx, dy) { 20726 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); 20727 }, 20728 ne: function(event, dx, dy) { 20729 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); 20730 }, 20731 nw: function(event, dx, dy) { 20732 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); 20733 } 20734 }, 20735 20736 _propagate: function(n, event) { 20737 $.ui.plugin.call(this, n, [event, this.ui()]); 20738 (n != "resize" && this._trigger(n, event, this.ui())); 20739 }, 20740 20741 plugins: {}, 20742 20743 ui: function() { 20744 return { 20745 originalElement: this.originalElement, 20746 element: this.element, 20747 helper: this.helper, 20748 position: this.position, 20749 size: this.size, 20750 originalSize: this.originalSize, 20751 originalPosition: this.originalPosition 20752 }; 20753 } 20754 20755}); 20756 20757$.extend($.ui.resizable, { 20758 version: "1.8.16" 20759}); 20760 20761/* 20762 * Resizable Extensions 20763 */ 20764 20765$.ui.plugin.add("resizable", "alsoResize", { 20766 20767 start: function (event, ui) { 20768 var self = $(this).data("resizable"), o = self.options; 20769 20770 var _store = function (exp) { 20771 $(exp).each(function() { 20772 var el = $(this); 20773 el.data("resizable-alsoresize", { 20774 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), 20775 left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10), 20776 position: el.css('position') // to reset Opera on stop() 20777 }); 20778 }); 20779 }; 20780 20781 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) { 20782 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); } 20783 else { $.each(o.alsoResize, function (exp) { _store(exp); }); } 20784 }else{ 20785 _store(o.alsoResize); 20786 } 20787 }, 20788 20789 resize: function (event, ui) { 20790 var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition; 20791 20792 var delta = { 20793 height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0, 20794 top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0 20795 }, 20796 20797 _alsoResize = function (exp, c) { 20798 $(exp).each(function() { 20799 var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, 20800 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left']; 20801
20802 $.each(css, function (i, prop) { 20803 var sum = (start[prop]||0) + (delta[prop]||0); 20804 if (sum && sum >= 0) 20805 style[prop] = sum || null; 20806 }); 20807 20808 // Opera fixing relative position 20809 if ($.browser.opera && /relative/.test(el.css('position'))) { 20810 self._revertToRelativePosition = true; 20811 el.css({ position: 'absolute', top: 'auto', left: 'auto' }); 20812 } 20813 20814 el.css(style); 20815 }); 20816 }; 20817 20818 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) { 20819 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); }); 20820 }else{ 20821 _alsoResize(o.alsoResize); 20822 } 20823 }, 20824 20825 stop: function (event, ui) { 20826 var self = $(this).data("resizable"), o = self.options; 20827 20828 var _reset = function (exp) { 20829 $(exp).each(function() { 20830 var el = $(this); 20831 // reset position for Opera - no need to verify it was changed 20832 el.css({ position: el.data("resizable-alsoresize").position }); 20833 }); 20834 }; 20835 20836 if (self._revertToRelativePosition) { 20837 self._revertToRelativePosition = false; 20838 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) { 20839 $.each(o.alsoResize, function (exp) { _reset(exp); }); 20840 }else{ 20841 _reset(o.alsoResize); 20842 } 20843 } 20844 20845 $(this).removeData("resizable-alsoresize"); 20846 } 20847}); 20848 20849$.ui.plugin.add("resizable", "animate", { 20850 20851 stop: function(event, ui) { 20852 var self = $(this).data("resizable"), o = self.options; 20853 20854 var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), 20855 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height, 20856 soffsetw = ista ? 0 : self.sizeDiff.width; 20857 20858 var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) }, 20859 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null, 20860 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null; 20861 20862 self.element.animate( 20863 $.extend(style, top && left ? { top: top, left: left } : {}), { 20864 duration: o.animateDuration, 20865 easing: o.animateEasing, 20866 step: function() { 20867 20868 var data = { 20869 width: parseInt(self.element.css('width'), 10), 20870 height: parseInt(self.element.css('height'), 10), 20871 top: parseInt(self.element.css('top'), 10), 20872 left: parseInt(self.element.css('left'), 10) 20873 }; 20874 20875 if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height }); 20876 20877 // propagating resize, and updating values for each animation step 20878 self._updateCache(data); 20879 self._propagate("resize", event); 20880 20881 } 20882 } 20883 ); 20884 } 20885 20886}); 20887 20888$.ui.plugin.add("resizable", "containment", { 20889 20890 start: function(event, ui) { 20891 var self = $(this).data("resizable"), o = self.options, el = self.element; 20892 var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc; 20893 if (!ce) return; 20894 20895 self.containerElement = $(ce); 20896 20897 if (/document/.test(oc) || oc == document) { 20898 self.containerOffset = { left: 0, top: 0 }; 20899 self.containerPosition = { left: 0, top: 0 }; 20900 20901 self.parentData = { 20902 element: $(document), left: 0, top: 0, 20903 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight 20904 }; 20905 } 20906 20907 // i'm a node, so compute top, left, right, bottom 20908 else { 20909 var element = $(ce), p = []; 20910 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); }); 20911 20912 self.containerOffset = element.offset(); 20913 self.containerPosition = element.position(); 20914 self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) }; 20915 20916 var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width, 20917 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch); 20918 20919 self.parentData = { 20920 element: ce, left: co.left, top: co.top, width: width, height: height 20921 }; 20922 } 20923 }, 20924 20925 resize: function(event, ui) { 20926 var self = $(this).data("resizable"), o = self.options, 20927 ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position, 20928 pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left
20928:0 }, ce = self.containerElement; 20929 20930 if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co; 20931 20932 if (cp.left < (self._helper ? co.left : 0)) { 20933 self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left)); 20934 if (pRatio) self.size.height = self.size.width / o.aspectRatio; 20935 self.position.left = o.helper ? co.left : 0; 20936 } 20937 20938 if (cp.top < (self._helper ? co.top : 0)) { 20939 self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top); 20940 if (pRatio) self.size.width = self.size.height * o.aspectRatio; 20941 self.position.top = self._helper ? co.top : 0; 20942 } 20943 20944 self.offset.left = self.parentData.left+self.position.left; 20945 self.offset.top = self.parentData.top+self.position.top; 20946 20947 var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ), 20948 hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height ); 20949 20950 var isParent = self.containerElement.get(0) == self.element.parent().get(0), 20951 isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position')); 20952 20953 if(isParent && isOffsetRelative) woset -= self.parentData.left; 20954 20955 if (woset + self.size.width >= self.parentData.width) { 20956 self.size.width = self.parentData.width - woset; 20957 if (pRatio) self.size.height = self.size.width / self.aspectRatio; 20958 } 20959 20960 if (hoset + self.size.height >= self.parentData.height) { 20961 self.size.height = self.parentData.height - hoset; 20962 if (pRatio) self.size.width = self.size.height * self.aspectRatio; 20963 } 20964 }, 20965 20966 stop: function(event, ui){ 20967 var self = $(this).data("resizable"), o = self.options, cp = self.position, 20968 co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement; 20969 20970 var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height; 20971 20972 if (self._helper && !o.animate && (/relative/).test(ce.css('position'))) 20973 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); 20974 20975 if (self._helper && !o.animate && (/static/).test(ce.css('position'))) 20976 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); 20977 20978 } 20979}); 20980 20981$.ui.plugin.add("resizable", "ghost", { 20982 20983 start: function(event, ui) { 20984 20985 var self = $(this).data("resizable"), o = self.options, cs = self.size; 20986 20987 self.ghost = self.originalElement.clone(); 20988 self.ghost 20989 .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }) 20990 .addClass('ui-resizable-ghost') 20991 .addClass(typeof o.ghost == 'string' ? o.ghost : ''); 20992 20993 self.ghost.appendTo(self.helper); 20994 20995 }, 20996 20997 resize: function(event, ui){ 20998 var self = $(this).data("resizable"), o = self.options; 20999 if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width }); 21000 }, 21001 21002 stop: function(event, ui){ 21003 var self = $(this).data("resizable"), o = self.options; 21004 if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0)); 21005 } 21006 21007}); 21008 21009$.ui.plugin.add("resizable", "grid", { 21010 21011 resize: function(event, ui) { 21012 var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey; 21013 o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid; 21014 var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1); 21015 21016 if (/^(se|s|e)$/.test(a)) { 21017 self.size.width = os.width + ox; 21018 self.size.height = os.height + oy; 21019 } 21020 else if (/^(ne)$/.test(a)) { 21021 self.size.width = os.width + ox; 21022 self.size.height = os.height + oy; 21023 self.position.top = op.top - oy; 21024 } 21025 else if (/^(sw)$/.test(a)) { 21026 self.size.width = os.width + ox; 21027 self.size.height = os.height + oy; 21028 self.position.left = op.left - ox; 21029 } 21030 else { 21031 self.size.width = os.width + ox; 21032 self.size.height = os.height + oy; 21033 self.position.top = op.top - oy; 21034 self.position.left = op.left - ox; 21035 } 21036 } 21037 21038}); 21039 21040var num = function(v) { 21041 return parseInt(v, 10) || 0; 21042}; 21043 21044var isNumber = function(value) { 21045 return !isNaN(parseInt(value, 10)); 21046}; 21047 21048})(jQuery); 21049 21050/* 21051 * jQuery UI Sortable 1.8.16 21052 * 21053 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 21054 * Dual licensed under the MIT or GPL Version 2 licenses. 21055 * http://jquery.org/license 21056 * 21057 * http://docs.jquery.com/UI/Sortables 21058 * 21059 * Depends: 21060 * jquery.ui.core.js 21061 * jquery.ui.mouse.js 21062 * jquery.ui.widget.js 21063 */ 21064(function( $, undefined ) { 21065 21066$.widget("ui.sortable", $.ui.mouse, { 21067 widgetEventPrefix: "sort", 21068 options: { 21069 appendTo: "parent", 21070 axis: false, 21071 connectWith: false, 21072 containment: false, 21073 cursor: 'auto', 21074 cursorAt: false, 21075 dropOnEmpty: true, 21076 forcePlaceholderSize: false, 21077 forceHelperSize: false, 21078 grid: false, 21079 handle: false, 21080 helper: "original", 21081 items: '> *', 21082 opacity: false, 21083 placeholder: false, 21084 revert: false, 21085 scroll: true, 21086 scrollSensitivity: 20, 21087 scrollSpeed: 20, 21088 scope: "default", 21089 tolerance: "intersect", 21090 zIndex: 1000 21091 }, 21092 _create: function() { 21093 21094 var o = this.options; 21095 this.containerCache = {}; 21096 this.element.addClass("ui-sortable"); 21097 21098 //Get the items 21099 this.refresh(); 21100 21101 //Let's determine if the items are being displayed horizontally 21102 this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false;
21103 21104 //Let's determine the parent's offset 21105 this.offset = this.element.offset(); 21106 21107 //Initialize mouse events for interaction 21108 this._mouseInit(); 21109 21110 }, 21111 21112 destroy: function() { 21113 this.element 21114 .removeClass("ui-sortable ui-sortable-disabled") 21115 .removeData("sortable") 21116 .unbind(".sortable"); 21117 this._mouseDestroy(); 21118 21119 for ( var i = this.items.length - 1; i >= 0; i-- ) 21120 this.items[i].item.removeData("sortable-item"); 21121 21122 return this; 21123 }, 21124 21125 _setOption: function(key, value){ 21126 if ( key === "disabled" ) { 21127 this.options[ key ] = value; 21128 21129 this.widget() 21130 [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" ); 21131 } else { 21132 // Don't call widget base _setOption for disable as it adds ui-state-disabled class 21133 $.Widget.prototype._setOption.apply(this, arguments); 21134 } 21135 }, 21136 21137 _mouseCapture: function(event, overrideHandle) { 21138 21139 if (this.reverting) { 21140 return false; 21141 } 21142 21143 if(this.options.disabled || this.options.type == 'static') return false; 21144 21145 //We have to refresh the items data once first 21146 this._refreshItems(event); 21147 21148 //Find out if the clicked node (or one of its parents) is a actual item in this.items 21149 var currentItem = null, self = this, nodes = $(event.target).parents().each(function() { 21150 if($.data(this, 'sortable-item') == self) { 21151 currentItem = $(this); 21152 return false; 21153 } 21154 }); 21155 if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target); 21156 21157 if(!currentItem) return false; 21158 if(this.options.handle && !overrideHandle) { 21159 var validHandle = false; 21160 21161 $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; }); 21162 if(!validHandle) return false; 21163 } 21164 21165 this.currentItem = currentItem; 21166 this._removeCurrentsFromItems(); 21167 return true; 21168 21169 }, 21170 21171 _mouseStart: function(event, overrideHandle, noActivation) { 21172 21173 var o = this.options, self = this; 21174 this.currentContainer = this; 21175 21176 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture 21177 this.refreshPositions(); 21178 21179 //Create and append the visible helper 21180 this.helper = this._createHelper(event); 21181 21182 //Cache the helper size 21183 this._cacheHelperProportions(); 21184 21185 /* 21186 * - Position generation - 21187 * This block generates everything position related - it's the core of draggables. 21188 */ 21189 21190 //Cache the margins of the original element 21191 this._cacheMargins(); 21192 21193 //Get the next scrolling parent 21194 this.scrollParent = this.helper.scrollParent(); 21195 21196 //The element's absolute position on the page minus margins 21197 this.offset = this.currentItem.offset(); 21198 this.offset = { 21199 top: this.offset.top - this.margins.top, 21200 left: this.offset.left - this.margins.left 21201 }; 21202 21203 // Only after we got the offset, we can change the helper's position to absolute 21204 // TODO: Still need to figure out a way to make relative sorting possible 21205 this.helper.css("position", "absolute"); 21206 this.cssPosition = this.helper.css("position"); 21207 21208 $.extend(this.offset, { 21209 click: { //Where the click happened, relative to the element 21210 left: event.pageX - this.offset.left, 21211 top: event.pageY - this.offset.top 21212 }, 21213 parent: this._getParentOffset(), 21214 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper 21215 }); 21216 21217 //Generate the original position 21218 this.originalPosition = this._generatePosition(event); 21219 this.originalPageX = event.pageX; 21220 this.originalPageY = event.pageY; 21221 21222 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied 21223 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); 21224 21225 //Cache the former DOM position 21226 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; 21227 21228 //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way 21229 if(this.helper[0] != this.currentItem[0]) { 21230 this.currentItem.hide(); 21231 } 21232 21233 //Create the placeholder 21234 this._createPlaceholder(); 21235 21236 //Set a containment if given in the options 21237 if(o.containment) 21238 this._setContainment(); 21239 21240 if(o.cursor) { // cursor option 21241 if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor"); 21242 $('body').css("cursor", o.cursor); 21243 } 21244 21245 if(o.opacity) { // opacity option 21246 if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity"); 21247 this.helper.css("opacity", o.opacity); 21248 } 21249 21250 if(o.zIndex) { // zIndex option 21251 if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex"); 21252 this.helper.css("zIndex", o.zIndex); 21253 } 21254 21255 //Prepare scrolling 21256 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') 21257 this.overflowOffset = this.scrollParent.offset(); 21258 21259 //Call callbacks 21260 this._trigger("start", event, this._uiHash()); 21261 21262 //Recache the helper size 21263 if(!this._preserveHelperProportions) 21264 this._cacheHelperProportions(); 21265 21266 21267 //Post 'activate' events to possible containers 21268 if(!noActivation) { 21269 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); } 21270 } 21271 21272 //Prepare possible droppables 21273 if($.ui.ddmanager) 21274 $.ui.ddmanager.current = this; 21275 21276 if ($.ui.ddmanager && !o.dropBehaviour) 21277 $.ui.ddmanager.prepareOffsets(this, event); 21278 21279 this.dragging = true; 21280 21281 this.helper.addClass("ui-sortable-helper"); 21282 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position 21283 return true; 21284 21285 }, 21286 21287 _mouseDrag: function(event) { 21288 21289 //Compute the helpers position 21290 this.position = this._generatePosition(event); 21291 this.positionAbs = this._convertPositionTo("absolute"); 21292 21293 if (!this.lastPositionAbs) { 21294 this.lastPositionAbs = this.positionAbs; 21295 } 21296 21297 //Do scrolling 21298 if(this.options.scroll) { 21299 var o = this.options, scrolled = false;
21300 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') { 21301 21302 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) 21303 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; 21304 else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) 21305 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; 21306 21307 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) 21308 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; 21309 else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) 21310 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; 21311 21312 } else { 21313 21314 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) 21315 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); 21316 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) 21317 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); 21318 21319 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) 21320 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); 21321 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) 21322 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); 21323 21324 } 21325 21326 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) 21327 $.ui.ddmanager.prepareOffsets(this, event); 21328 } 21329 21330 //Regenerate the absolute position used for position checks 21331 this.positionAbs = this._convertPositionTo("absolute"); 21332 21333 //Set the helper position 21334 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px'; 21335 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px'; 21336 21337 //Rearrange 21338 for (var i = this.items.length - 1; i >= 0; i--) { 21339 21340 //Cache variables and intersection, continue if no intersection 21341 var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item); 21342 if (!intersection) continue; 21343 21344 if(itemElement != this.currentItem[0] //cannot intersect with itself 21345 && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before 21346 && !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked 21347 && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true) 21348 //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container 21349 ) { 21350 21351 this.direction = intersection == 1 ? "down" : "up"; 21352 21353 if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) { 21354 this._rearrange(event, item); 21355 } else { 21356 break; 21357 } 21358 21359 this._trigger("change", event, this._uiHash()); 21360 break; 21361 } 21362 } 21363 21364 //Post events to containers 21365 this._contactContainers(event); 21366 21367 //Interconnect with droppables 21368 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event); 21369 21370 //Call callbacks 21371 this._trigger('sort', event, this._uiHash()); 21372 21373 this.lastPositionAbs = this.positionAbs; 21374 return false; 21375 21376 }, 21377 21378 _mouseStop: function(event, noPropagation) { 21379 21380 if(!event) return; 21381 21382 //If we are using droppables, inform the manager about the drop 21383 if ($.ui.ddmanager && !this.options.dropBehaviour) 21384 $.ui.ddmanager.drop(this, event); 21385 21386 if(this.options.revert) { 21387 var self = this; 21388 var cur = self.placeholder.offset(); 21389 21390 self.reverting = true; 21391 21392 $(this.helper).animate({ 21393 left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft), 21394 top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop) 21395 }, parseInt(this.options.revert, 10) || 500, function() { 21396 self._clear(event); 21397 }); 21398 } else { 21399 this._clear(event, noPropagation); 21400 } 21401 21402 return false;
21403 21404 }, 21405 21406 cancel: function() { 21407 21408 var self = this; 21409 21410 if(this.dragging) { 21411 21412 this._mouseUp({ target: null }); 21413 21414 if(this.options.helper == "original") 21415 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); 21416 else 21417 this.currentItem.show(); 21418 21419 //Post deactivating events to containers 21420 for (var i = this.containers.length - 1; i >= 0; i--){ 21421 this.containers[i]._trigger("deactivate", null, self._uiHash(this)); 21422 if(this.containers[i].containerCache.over) { 21423 this.containers[i]._trigger("out", null, self._uiHash(this)); 21424 this.containers[i].containerCache.over = 0; 21425 } 21426 } 21427 21428 } 21429 21430 if (this.placeholder) { 21431 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! 21432 if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]); 21433 if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove(); 21434 21435 $.extend(this, { 21436 helper: null, 21437 dragging: false, 21438 reverting: false, 21439 _noFinalSort: null 21440 }); 21441 21442 if(this.domPosition.prev) { 21443 $(this.domPosition.prev).after(this.currentItem); 21444 } else { 21445 $(this.domPosition.parent).prepend(this.currentItem); 21446 } 21447 } 21448 21449 return this; 21450 21451 }, 21452 21453 serialize: function(o) { 21454 21455 var items = this._getItemsAsjQuery(o && o.connected); 21456 var str = []; o = o || {}; 21457 21458 $(items).each(function() { 21459 var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/)); 21460 if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2])); 21461 }); 21462 21463 if(!str.length && o.key) { 21464 str.push(o.key + '='); 21465 } 21466 21467 return str.join('&'); 21468 21469 }, 21470 21471 toArray: function(o) { 21472 21473 var items = this._getItemsAsjQuery(o && o.connected); 21474 var ret = []; o = o || {}; 21475 21476 items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); }); 21477 return ret; 21478 21479 }, 21480 21481 /* Be careful with the following core functions */ 21482 _intersectsWith: function(item) { 21483 21484 var x1 = this.positionAbs.left, 21485 x2 = x1 + this.helperProportions.width, 21486 y1 = this.positionAbs.top, 21487 y2 = y1 + this.helperProportions.height; 21488 21489 var l = item.left, 21490 r = l + item.width, 21491 t = item.top, 21492 b = t + item.height; 21493 21494 var dyClick = this.offset.click.top, 21495 dxClick = this.offset.click.left; 21496 21497 var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r; 21498 21499 if( this.options.tolerance == "pointer" 21500 || this.options.forcePointerForContainers 21501 || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height']) 21502 ) { 21503 return isOverElement; 21504 } else { 21505 21506 return (l < x1 + (this.helperProportions.width / 2) // Right Half 21507 && x2 - (this.helperProportions.width / 2) < r // Left Half 21508 && t < y1 + (this.helperProportions.height / 2) // Bottom Half 21509 && y2 - (this.helperProportions.height / 2) < b ); // Top Half 21510 21511 } 21512 }, 21513 21514 _intersectsWithPointer: function(item) { 21515 21516 var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), 21517 isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), 21518 isOverElement = isOverElementHeight && isOverElementWidth, 21519 verticalDirection = this._getDragVerticalDirection(), 21520 horizontalDirection = this._getDragHorizontalDirection(); 21521 21522 if (!isOverElement) 21523 return false; 21524 21525 return this.floating ? 21526 ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 ) 21527 : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) ); 21528 21529 }, 21530 21531 _intersectsWithSides: function(item) { 21532 21533 var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), 21534 isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width), 21535 verticalDirection = this._getDragVerticalDirection(), 21536 horizontalDirection = this._getDragHorizontalDirection(); 21537 21538 if (this.floating && horizontalDirection) { 21539 return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf)); 21540 } else { 21541 return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf)); 21542 } 21543 21544 }, 21545 21546 _getDragVerticalDirection: function() { 21547 var delta = this.positionAbs.top - this.lastPositionAbs.top; 21548 return delta != 0 && (delta > 0 ? "down" : "up"); 21549 }, 21550 21551 _getDragHorizontalDirection: function() { 21552 var delta = this.positionAbs.left - this.lastPositionAbs.left; 21553 return delta != 0 && (delta > 0 ? "right" : "left"); 21554 }, 21555 21556 refresh: function(event) { 21557 this._refreshItems(event); 21558 this.refreshPositions(); 21559 return this; 21560 }, 21561 21562 _connectWith: function() { 21563 var options = this.options; 21564 return options.connectWith.constructor == String
21565 ? [options.connectWith] 21566 : options.connectWith; 21567 }, 21568 21569 _getItemsAsjQuery: function(connected) { 21570 21571 var self = this; 21572 var items = []; 21573 var queries = []; 21574 var connectWith = this._connectWith(); 21575 21576 if(connectWith && connected) { 21577 for (var i = connectWith.length - 1; i >= 0; i--){ 21578 var cur = $(connectWith[i]); 21579 for (var j = cur.length - 1; j >= 0; j--){ 21580 var inst = $.data(cur[j], 'sortable'); 21581 if(inst && inst != this && !inst.options.disabled) { 21582 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]); 21583 } 21584 }; 21585 }; 21586 } 21587 21588 queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]); 21589 21590 for (var i = queries.length - 1; i >= 0; i--){ 21591 queries[i][0].each(function() { 21592 items.push(this); 21593 }); 21594 }; 21595 21596 return $(items); 21597 21598 }, 21599 21600 _removeCurrentsFromItems: function() { 21601 21602 var list = this.currentItem.find(":data(sortable-item)"); 21603 21604 for (var i=0; i < this.items.length; i++) { 21605 21606 for (var j=0; j < list.length; j++) { 21607 if(list[j] == this.items[i].item[0]) 21608 this.items.splice(i,1); 21609 }; 21610 21611 }; 21612 21613 }, 21614 21615 _refreshItems: function(event) { 21616 21617 this.items = []; 21618 this.containers = [this]; 21619 var items = this.items; 21620 var self = this; 21621 var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]]; 21622 var connectWith = this._connectWith(); 21623 21624 if(connectWith) { 21625 for (var i = connectWith.length - 1; i >= 0; i--){ 21626 var cur = $(connectWith[i]); 21627 for (var j = cur.length - 1; j >= 0; j--){ 21628 var inst = $.data(cur[j], 'sortable'); 21629 if(inst && inst != this && !inst.options.disabled) { 21630 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); 21631 this.containers.push(inst); 21632 } 21633 }; 21634 }; 21635 } 21636 21637 for (var i = queries.length - 1; i >= 0; i--) { 21638 var targetData = queries[i][1]; 21639 var _queries = queries[i][0]; 21640 21641 for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) { 21642 var item = $(_queries[j]); 21643 21644 item.data('sortable-item', targetData); // Data for target checking (mouse manager) 21645 21646 items.push({ 21647 item: item, 21648 instance: targetData, 21649 width: 0, height: 0, 21650 left: 0, top: 0 21651 }); 21652 }; 21653 }; 21654 21655 }, 21656 21657 refreshPositions: function(fast) { 21658 21659 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change 21660 if(this.offsetParent && this.helper) { 21661 this.offset.parent = this._getParentOffset(); 21662 } 21663 21664 for (var i = this.items.length - 1; i >= 0; i--){ 21665 var item = this.items[i]; 21666 21667 //We ignore calculating positions of all connected containers when we're not over them 21668 if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0]) 21669 continue; 21670 21671 var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; 21672 21673 if (!fast) { 21674 item.width = t.outerWidth(); 21675 item.height = t.outerHeight(); 21676 } 21677 21678 var p = t.offset(); 21679 item.left = p.left; 21680 item.top = p.top; 21681 }; 21682 21683 if(this.options.custom && this.options.custom.refreshContainers
21683) { 21684 this.options.custom.refreshContainers.call(this); 21685 } else { 21686 for (var i = this.containers.length - 1; i >= 0; i--){ 21687 var p = this.containers[i].element.offset(); 21688 this.containers[i].containerCache.left = p.left; 21689 this.containers[i].containerCache.top = p.top; 21690 this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); 21691 this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); 21692 }; 21693 } 21694 21695 return this; 21696 }, 21697 21698 _createPlaceholder: function(that) { 21699 21700 var self = that || this, o = self.options; 21701 21702 if(!o.placeholder || o.placeholder.constructor == String) { 21703 var className = o.placeholder; 21704 o.placeholder = { 21705 element: function() { 21706 21707 var el = $(document.createElement(self.currentItem[0].nodeName)) 21708 .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder") 21709 .removeClass("ui-sortable-helper")[0]; 21710 21711 if(!className) 21712 el.style.visibility = "hidden"; 21713 21714 return el; 21715 }, 21716 update: function(container, p) { 21717 21718 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that 21719 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified 21720 if(className && !o.forcePlaceholderSize) return; 21721 21722 //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
21723 if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); }; 21724 if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); }; 21725 } 21726 }; 21727 } 21728 21729 //Create the placeholder 21730 self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem)); 21731 21732 //Append it after the actual current item 21733 self.currentItem.after(self.placeholder); 21734 21735 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) 21736 o.placeholder.update(self, self.placeholder); 21737 21738 }, 21739 21740 _contactContainers: function(event) { 21741 21742 // get innermost container that intersects with item 21743 var innermostContainer = null, innermostIndex = null; 21744 21745 21746 for (var i = this.containers.length - 1; i >= 0; i--){ 21747 21748 // never consider a container that's located within the item itself 21749 if($.ui.contains(this.currentItem[0], this.containers[i].element[0])) 21750 continue; 21751 21752 if(this._intersectsWith(this.containers[i].containerCache)) { 21753 21754 // if we've already found a container and it's more "inner" than this, then continue 21755 if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0])) 21756 continue; 21757 21758 innermostContainer = this.containers[i]; 21759 innermostIndex = i; 21760 21761 } else { 21762 // container doesn't intersect. trigger "out" event if necessary 21763 if(this.containers[i].containerCache.over) { 21764 this.containers[i]._trigger("out", event, this._uiHash(this)); 21765 this.containers[i].containerCache.over = 0; 21766 } 21767 } 21768 21769 } 21770 21771 // if no intersecting containers found, return 21772 if(!innermostContainer) return; 21773 21774 // move the item into the container if it's not there already 21775 if(this.containers.length === 1) { 21776 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 21777 this.containers[innermostIndex].containerCache.over = 1; 21778 } else if(this.currentContainer != this.containers[innermostIndex]) { 21779 21780 //When entering a new container, we will find the item with the least distance and append our item near it 21781 var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; 21782 for (var j = this.items.length - 1; j >= 0; j--) { 21783 if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; 21784 var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; 21785 if(Math.abs(cur - base) < dist) { 21786 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; 21787 } 21788 } 21789 21790 if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled 21791 return; 21792 21793 this.currentContainer = this.containers[innermostIndex]; 21794 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 21795 this._trigger("change", event, this._uiHash()); 21796 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 21797 21798 //Update the placeholder 21799 this.options.placeholder.update(this.currentContainer, this.placeholder); 21800 21801 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 21802 this.containers[innermostIndex].containerCache.over = 1; 21803 } 21804 21805 21806 }, 21807 21808 _createHelper: function(event) { 21809 21810 var o = this.options; 21811 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem); 21812 21813 if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already 21814 $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); 21815 21816 if(helper[0] == this.currentItem[0]) 21817 this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left
21817: this.currentItem.css("left") }; 21818 21819 if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width()); 21820 if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height()); 21821 21822 return helper; 21823 21824 }, 21825 21826 _adjustOffsetFromHelper: function(obj) { 21827 if (typeof obj == 'string') { 21828 obj = obj.split(' '); 21829 } 21830 if ($.isArray(obj)) { 21831 obj = {left: +obj[0], top: +obj[1] || 0}; 21832 } 21833 if ('left' in obj) { 21834 this.offset.click.left = obj.left + this.margins.left; 21835 } 21836 if ('right' in obj) { 21837 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 21838 } 21839 if ('top' in obj) { 21840 this.offset.click.top = obj.top + this.margins.top; 21841 } 21842 if ('bottom' in obj) { 21843 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 21844 } 21845 }, 21846 21847 _getParentOffset: function() { 21848 21849 21850 //Get the offsetParent and cache its position 21851 this.offsetParent = this.helper.offsetParent(); 21852 var po = this.offsetParent.offset(); 21853 21854 // This is a special case where we need to modify a offset calculated on start, since the following happened: 21855 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent 21856 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that 21857 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag 21858 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) { 21859 po.left += this.scrollParent.scrollLeft(); 21860 po.top += this.scrollParent.scrollTop(); 21861 } 21862 21863 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information 21864 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix 21865 po = { top: 0, left: 0 }; 21866 21867 return { 21868 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), 21869 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) 21870 }; 21871 21872 }, 21873 21874 _getRelativeOffset: function() { 21875 21876 if(this.cssPosition == "relative") { 21877 var p = this.currentItem.position(); 21878 return { 21879 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), 21880 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() 21881 }; 21882 } else { 21883 return { top: 0, left: 0 }; 21884 } 21885 21886 }, 21887 21888 _cacheMargins: function() { 21889 this.margins = { 21890 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0), 21891 top: (parseInt(this.currentItem.css("marginTop"),10) || 0) 21892 }; 21893 }, 21894 21895 _cacheHelperProportions: function() { 21896 this.helperProportions = { 21897 width: this.helper.outerWidth(), 21898 height: this.helper.outerHeight() 21899 }; 21900 }, 21901 21902 _setContainment: function() { 21903 21904 var o = this.options; 21905 if(o.containment == 'parent') o.containment = this.helper[0].parentNode; 21906 if(o.containment == 'document' || o.containment == 'window') this.containment = [ 21907 0 - this.offset.relative.left - this.offset.parent.left, 21908 0 - this.offset.relative.top - this.offset.parent.top, 21909 $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, 21910 ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top 21911 ]; 21912 21913 if(!(/^(document|window|parent)$/).test(o.containment)) { 21914 var ce = $(o.containment)[0]; 21915 var co = $(o.containment).offset(); 21916 var over = ($(ce).css("overflow") != 'hidden'); 21917 21918 this.containment = [ 21919 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, 21920 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, 21921 co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left, 21922 co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),
2192210) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top 21923 ]; 21924 } 21925 21926 }, 21927 21928 _convertPositionTo: function(d, pos) { 21929 21930 if(!pos) pos = this.position; 21931 var mod = d == "absolute" ? 1 : -1; 21932 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); 21933 21934 return { 21935 top: ( 21936 pos.top // The absolute mouse position 21937 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent 21938 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) 21939 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) 21940 ), 21941 left: ( 21942 pos.left // The absolute mouse position 21943 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent 21944 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) 21945 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) 21946 ) 21947 }; 21948 21949 }, 21950 21951 _generatePosition: function(event) { 21952 21953 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); 21954 21955 // This is another very weird special case that only happens for relative elements: 21956 // 1. If the css position is relative 21957 // 2. and the scroll parent is the document or similar to the offset parent 21958 // we have to refresh the relative offset during the scroll so there are no jumps 21959 if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) { 21960 this.offset.relative = this._getRelativeOffset(); 21961 } 21962 21963 var pageX = event.pageX; 21964 var pageY = event.pageY; 21965 21966 /* 21967 * - Position constraining - 21968 * Constrain the position to a mix of grid, containment. 21969 */ 21970 21971 if(this.originalPosition) { //If we are not dragging yet, we won't check for options 21972 21973 if(this.containment) { 21974 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left; 21975 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top; 21976 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left; 21977 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top; 21978 } 21979 21980 if(o.grid) { 21981 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; 21982 pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; 21983 21984 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; 21985 pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; 21986 } 21987 21988 } 21989 21990 return { 21991 top: ( 21992 pageY // The absolute mouse position 21993 - this.offset.click.top // Click offset (relative to the element) 21994 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent 21995 - this.offset.parent.top // The offsetParent's offset without borders (offset + border) 21996 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) 21997 ), 21998 left: ( 21999 pageX // The absolute mouse position 22000 - this.offset.click.left // Click offset (relative to the element) 22001 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent 22002 - this.offset.parent.left // The offsetParent's offset without borders (offset + border) 22003 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) 22004 ) 22005 }; 22006 22007 }, 22008 22009 _rearrange: function(event, i, a, hardRefresh) { 22010 22011 a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling)); 22012 22013 //Various things done here to improve the performance: 22014 // 1. we create a setTimeout, that calls refreshPositions 22015 // 2. on the instance, we have a counter variable, that get's higher after every append 22016 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same 22017 // 4. this lets only the last addition to the timeout stack through 22018 this.counter = this.counter ? ++this.counter : 1;
22019 var self = this, counter = this.counter; 22020 22021 window.setTimeout(function() { 22022 if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove 22023 },0); 22024 22025 }, 22026 22027 _clear: function(event, noPropagation) { 22028 22029 this.reverting = false; 22030 // We delay all events that have to be triggered to after the point where the placeholder has been removed and 22031 // everything else normalized again 22032 var delayedTriggers = [], self = this; 22033 22034 // We first have to update the dom position of the actual currentItem 22035 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) 22036 if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem); 22037 this._noFinalSort = null; 22038 22039 if(this.helper[0] == this.currentItem[0]) { 22040 for(var i in this._storedCSS) { 22041 if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = ''; 22042 } 22043 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); 22044 } else { 22045 this.currentItem.show(); 22046 } 22047 22048 if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); }); 22049 if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed 22050 if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element 22051 if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); }); 22052 for (var i = this.containers.length - 1; i >= 0; i--){ 22053 if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) { 22054 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.containers[i])); 22055 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.containers[i])); 22056 } 22057 }; 22058 }; 22059 22060 //Post events to containers 22061 for (var i = this.containers.length - 1; i >= 0; i--){ 22062 if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i])); 22063 if(this.containers[i].containerCache.over) { 22064 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i])); 22065 this.containers[i].containerCache.over = 0; 22066 } 22067 } 22068 22069 //Do what was originally in plugins 22070 if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor 22071 if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity 22072 if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index 22073 22074 this.dragging = false; 22075 if(this.cancelHelperRemoval) { 22076 if(!noPropagation) { 22077 this._trigger("beforeStop", event, this._uiHash()); 22078 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events 22079 this._trigger("stop", event, this._uiHash()); 22080 } 22081 return false; 22082 } 22083 22084 if(!noPropagation) this._trigger("beforeStop", event, this._uiHash()); 22085 22086 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! 22087 this.placeholder[0].parentNode.removeChild(this.placeholder[0]); 22088 22089 if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null; 22090 22091 if(!noPropagation) { 22092 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events 22093 this._trigger("stop", event, this._uiHash()); 22094 } 22095 22096 this.fromOutside = false;
22097 return true; 22098 22099 }, 22100 22101 _trigger: function() { 22102 if ($.Widget.prototype._trigger.apply(this, arguments) === false) { 22103 this.cancel(); 22104 } 22105 }, 22106 22107 _uiHash: function(inst) { 22108 var self = inst || this; 22109 return { 22110 helper: self.helper, 22111 placeholder: self.placeholder || $([]), 22112 position: self.position, 22113 originalPosition: self.originalPosition, 22114 offset: self.positionAbs, 22115 item: self.currentItem, 22116 sender: inst ? inst.element : null 22117 }; 22118 } 22119 22120}); 22121 22122$.extend($.ui.sortable, { 22123 version: "1.8.16" 22124}); 22125 22126})(jQuery); 22127 22128/* 22129 * jQuery UI Slider 1.8.16 22130 * 22131 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 22132 * Dual licensed under the MIT or GPL Version 2 licenses. 22133 * http://jquery.org/license 22134 * 22135 * http://docs.jquery.com/UI/Slider 22136 * 22137 * Depends: 22138 * jquery.ui.core.js 22139 * jquery.ui.mouse.js 22140 * jquery.ui.widget.js 22141 */ 22142(function( $, undefined ) { 22143 22144// number of pages in a slider 22145// (how many times can you page up/down to go through the whole range) 22146var numPages = 5; 22147 22148$.widget( "ui.slider", $.ui.mouse, { 22149 22150 widgetEventPrefix: "slide", 22151 22152 options: { 22153 animate: false, 22154 distance: 0, 22155 max: 100, 22156 min: 0, 22157 orientation: "horizontal", 22158 range: false, 22159 step: 1, 22160 value: 0, 22161 values: null 22162 }, 22163 22164 _create: function() { 22165 var self = this, 22166 o = this.options, 22167 existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ), 22168 handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>", 22169 handleCount = ( o.values && o.values.length ) || 1, 22170 handles = []; 22171 22172 this._keySliding = false; 22173 this._mouseSliding = false; 22174 this._animateOff = true; 22175 this._handleIndex = null; 22176 this._detectOrientation(); 22177 this._mouseInit(); 22178 22179 this.element 22180 .addClass( "ui-slider" + 22181 " ui-slider-" + this.orientation + 22182 " ui-widget" + 22183 " ui-widget-content" + 22184 " ui-corner-all" + 22185 ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) ); 22186 22187 this.range = $([]); 22188 22189 if ( o.range ) { 22190 if ( o.range === true ) { 22191 if ( !o.values ) { 22192 o.values = [ this._valueMin(), this._valueMin() ]; 22193 } 22194 if ( o.values.length && o.values.length !== 2 ) { 22195 o.values = [ o.values[0], o.values[0] ]; 22196 } 22197 } 22198 22199 this.range = $( "<div></div>" ) 22200 .appendTo( this.element ) 22201 .addClass( "ui-slider-range" + 22202 // note: this isn't the most fittingly semantic framework class for this element, 22203 // but worked best visually with a variety of themes 22204 " ui-widget-header" + 22205 ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) ); 22206 } 22207 22208 for ( var i = existingHandles.length; i < handleCount; i += 1 ) { 22209 handles.push( handle ); 22210 } 22211 22212 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( self.element ) ); 22213 22214 this.handle = this.handles.eq( 0 ); 22215 22216 this.handles.add( this.range ).filter( "a" ) 22217 .click(function( event ) { 22218 event.preventDefault(); 22219 }) 22220 .hover(function() { 22221 if ( !o.disabled ) { 22222 $( this ).addClass( "ui-state-hover" ); 22223 } 22224 }, function() { 22225 $( this ).removeClass( "ui-state-hover" ); 22226 }) 22227 .focus(function() { 22228 if ( !o.disabled ) { 22229 $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" ); 22230 $( this ).addClass( "ui-state-focus" ); 22231 } else { 22232 $( this ).blur(); 22233 } 22234 }) 22235 .blur(function() { 22236 $( this ).removeClass( "ui-state-focus" ); 22237 }); 22238 22239 this.handles.each(function( i ) { 22240 $( this ).data( "index.ui-slider-handle", i ); 22241 }); 22242 22243 this.handles 22244 .keydown(function( event ) { 22245 var ret = true, 22246 index = $( this ).data( "index.ui-slider-handle" ), 22247 allowed, 22248 curVal, 22249 newVal, 22250 step; 22251 22252 if ( self.options.disabled ) { 22253 return; 22254 } 22255 22256 switch ( event.keyCode ) { 22257 case $.ui.keyCode.HOME: 22258 case $.ui.keyCode.END: 22259 case $.ui.keyCode.PAGE_UP: 22260 case $.ui.keyCode.PAGE_DOWN: 22261 case $.ui.keyCode.UP: 22262 case $.ui.keyCode.RIGHT: 22263 case $.ui.keyCode.DOWN: 22264 case $.ui.keyCode.LEFT: 22265 ret = false;
22266 if ( !self._keySliding ) { 22267 self._keySliding = true; 22268 $( this ).addClass( "ui-state-active" ); 22269 allowed = self._start( event, index ); 22270 if ( allowed === false ) { 22271 return; 22272 } 22273 } 22274 break; 22275 } 22276 22277 step = self.options.step; 22278 if ( self.options.values && self.options.values.length ) { 22279 curVal = newVal = self.values( index ); 22280 } else { 22281 curVal = newVal = self.value(); 22282 } 22283 22284 switch ( event.keyCode ) { 22285 case $.ui.keyCode.HOME: 22286 newVal = self._valueMin(); 22287 break; 22288 case $.ui.keyCode.END: 22289 newVal = self._valueMax(); 22290 break; 22291 case $.ui.keyCode.PAGE_UP: 22292 newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) ); 22293 break; 22294 case $.ui.keyCode.PAGE_DOWN: 22295 newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) ); 22296 break; 22297 case $.ui.keyCode.UP: 22298 case $.ui.keyCode.RIGHT: 22299 if ( curVal === self._valueMax() ) { 22300 return; 22301 } 22302 newVal = self._trimAlignValue( curVal + step ); 22303 break; 22304 case $.ui.keyCode.DOWN: 22305 case $.ui.keyCode.LEFT: 22306 if ( curVal === self._valueMin() ) { 22307 return; 22308 } 22309 newVal = self._trimAlignValue( curVal - step ); 22310 break; 22311 } 22312 22313 self._slide( event, index, newVal ); 22314 22315 return ret; 22316 22317 }) 22318 .keyup(function( event ) { 22319 var index = $( this ).data( "index.ui-slider-handle" ); 22320 22321 if ( self._keySliding ) { 22322 self._keySliding = false; 22323 self._stop( event, index ); 22324 self._change( event, index ); 22325 $( this ).removeClass( "ui-state-active" ); 22326 } 22327 22328 }); 22329 22330 this._refreshValue(); 22331 22332 this._animateOff = false; 22333 }, 22334 22335 destroy: function() { 22336 this.handles.remove(); 22337 this.range.remove(); 22338 22339 this.element 22340 .removeClass( "ui-slider" + 22341 " ui-slider-horizontal" + 22342 " ui-slider-vertical" + 22343 " ui-slider-disabled" + 22344 " ui-widget" + 22345 " ui-widget-content" + 22346 " ui-corner-all" ) 22347 .removeData( "slider" ) 22348 .unbind( ".slider" ); 22349 22350 this._mouseDestroy(); 22351 22352 return this; 22353 }, 22354 22355 _mouseCapture: function( event ) { 22356 var o = this.options, 22357 position, 22358 normValue, 22359 distance, 22360 closestHandle, 22361 self, 22362 index, 22363 allowed, 22364 offset, 22365 mouseOverHandle; 22366 22367 if ( o.disabled ) { 22368 return false; 22369 } 22370 22371 this.elementSize = { 22372 width: this.element.outerWidth(), 22373 height: this.element.outerHeight() 22374 }; 22375 this.elementOffset = this.element.offset(); 22376 22377 position = { x: event.pageX, y: event.pageY }; 22378 normValue = this._normValueFromMouse( position ); 22379 distance = this._valueMax() - this._valueMin() + 1; 22380 self = this; 22381 this.handles.each(function( i ) { 22382 var thisDistance = Math.abs( normValue - self.values(i) ); 22383 if ( distance > thisDistance ) { 22384 distance = thisDistance; 22385 closestHandle = $( this ); 22386 index = i; 22387 } 22388 }); 22389 22390 // workaround for bug #3736 (if both handles of a range are at 0, 22391 // the first is always used as the one with least distance, 22392 // and moving it is obviously prevented by preventing negative ranges) 22393 if( o.range === true && this.values(1) === o.min ) { 22394 index += 1; 22395 closestHandle = $( this.handles[index] ); 22396 } 22397 22398 allowed = this._start( event, index ); 22399 if ( allowed === false ) { 22400 return false; 22401 } 22402 this._mouseSliding = true; 22403 22404 self._handleIndex = index; 22405 22406 closestHandle 22407 .addClass( "ui-state-active" ) 22408 .focus(); 22409 22410 offset = closestHandle.offset(); 22411 mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" ); 22412 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { 22413 left: event.pageX - offset.left - ( closestHandle.width() / 2 ), 22414 top: event.pageY - offset.top - 22415 ( closestHandle.height() / 2 ) - 22416 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) - 22417 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) + 22418 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0) 22419 }; 22420 22421 if ( !this.handles.hasClass( "ui-state-hover" ) ) { 22422 this._slide( event, index, normValue ); 22423 } 22424 this._animateOff = true; 22425 return true; 22426 }, 22427 22428 _mouseStart: function( event ) { 22429 return true; 22430 }, 22431 22432 _mouseDrag: function( event ) { 22433 var position = { x: event.pageX, y: event.pageY }, 22434 normValue = this._normValueFromMouse( position ); 22435 22436 this._slide( event, this._handleIndex, normValue ); 22437 22438 return false;
vendor: 11,008 bytes, lines 22439-22845
22439 }, 22440 22441 _mouseStop: function( event ) { 22442 this.handles.removeClass( "ui-state-active" ); 22443 this._mouseSliding = false; 22444 22445 this._stop( event, this._handleIndex ); 22446 this._change( event, this._handleIndex ); 22447 22448 this._handleIndex = null; 22449 this._clickOffset = null; 22450 this._animateOff = false; 22451 22452 return false; 22453 }, 22454 22455 _detectOrientation: function() { 22456 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; 22457 }, 22458 22459 _normValueFromMouse: function( position ) { 22460 var pixelTotal, 22461 pixelMouse, 22462 percentMouse, 22463 valueTotal, 22464 valueMouse; 22465 22466 if ( this.orientation === "horizontal" ) { 22467 pixelTotal = this.elementSize.width; 22468 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 ); 22469 } else { 22470 pixelTotal = this.elementSize.height; 22471 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 ); 22472 } 22473 22474 percentMouse = ( pixelMouse / pixelTotal ); 22475 if ( percentMouse > 1 ) { 22476 percentMouse = 1; 22477 } 22478 if ( percentMouse < 0 ) { 22479 percentMouse = 0; 22480 } 22481 if ( this.orientation === "vertical" ) { 22482 percentMouse = 1 - percentMouse; 22483 } 22484 22485 valueTotal = this._valueMax() - this._valueMin(); 22486 valueMouse = this._valueMin() + percentMouse * valueTotal; 22487 22488 return this._trimAlignValue( valueMouse ); 22489 }, 22490 22491 _start: function( event, index ) { 22492 var uiHash = { 22493 handle: this.handles[ index ], 22494 value: this.value() 22495 }; 22496 if ( this.options.values && this.options.values.length ) { 22497 uiHash.value = this.values( index ); 22498 uiHash.values = this.values(); 22499 } 22500 return this._trigger( "start", event, uiHash ); 22501 }, 22502 22503 _slide: function( event, index, newVal ) { 22504 var otherVal, 22505 newValues, 22506 allowed; 22507 22508 if ( this.options.values && this.options.values.length ) { 22509 otherVal = this.values( index ? 0 : 1 ); 22510 22511 if ( ( this.options.values.length === 2 && this.options.range === true ) && 22512 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) ) 22513 ) { 22514 newVal = otherVal; 22515 } 22516 22517 if ( newVal !== this.values( index ) ) { 22518 newValues = this.values(); 22519 newValues[ index ] = newVal; 22520 // A slide can be canceled by returning false from the slide callback 22521 allowed = this._trigger( "slide", event, { 22522 handle: this.handles[ index ], 22523 value: newVal, 22524 values: newValues 22525 } ); 22526 otherVal = this.values( index ? 0 : 1 ); 22527 if ( allowed !== false ) { 22528 this.values( index, newVal, true ); 22529 } 22530 } 22531 } else { 22532 if ( newVal !== this.value() ) { 22533 // A slide can be canceled by returning false from the slide callback 22534 allowed = this._trigger( "slide", event, { 22535 handle: this.handles[ index ], 22536 value: newVal 22537 } ); 22538 if ( allowed !== false ) { 22539 this.value( newVal ); 22540 } 22541 } 22542 } 22543 }, 22544 22545 _stop: function( event, index ) { 22546 var uiHash = { 22547 handle: this.handles[ index ], 22548 value: this.value() 22549 }; 22550 if ( this.options.values && this.options.values.length ) { 22551 uiHash.value = this.values( index ); 22552 uiHash.values = this.values(); 22553 } 22554 22555 this._trigger( "stop", event, uiHash ); 22556 }, 22557 22558 _change: function( event, index ) { 22559 if ( !this._keySliding && !this._mouseSliding ) { 22560 var uiHash = { 22561 handle: this.handles[ index ], 22562 value: this.value() 22563 }; 22564 if ( this.options.values && this.options.values.length ) { 22565 uiHash.value = this.values( index ); 22566 uiHash.values = this.values(); 22567 } 22568 22569 this._trigger( "change", event, uiHash ); 22570 } 22571 }, 22572 22573 value: function( newValue ) { 22574 if ( arguments.length ) { 22575 this.options.value = this._trimAlignValue( newValue ); 22576 this._refreshValue(); 22577 this._change( null, 0 ); 22578 return; 22579 } 22580 22581 return this._value(); 22582 }, 22583 22584 values: function( index, newValue ) { 22585 var vals, 22586 newValues, 22587 i; 22588 22589 if ( arguments.length > 1 ) { 22590 this.options.values[ index ] = this._trimAlignValue( newValue ); 22591 this._refreshValue(); 22592 this._change( null, index ); 22593 return; 22594 } 22595 22596 if ( arguments.length ) { 22597 if ( $.isArray( arguments[ 0 ] ) ) { 22598 vals = this.options.values; 22599 newValues = arguments[ 0 ]; 22600 for ( i = 0; i < vals.length; i += 1 ) { 22601 vals[ i ] = this._trimAlignValue( newValues[ i ] ); 22602 this._change( null, i ); 22603 } 22604 this._refreshValue(); 22605 } else { 22606 if ( this.options.values && this.options.values.length ) { 22607 return this._values( index ); 22608 } else { 22609 return this.value(); 22610 } 22611 } 22612 } else { 22613 return this._values(); 22614 } 22615 }, 22616 22617 _setOption: function( key, value ) { 22618 var i, 22619 valsLength = 0; 22620 22621 if ( $.isArray( this.options.values ) ) { 22622 valsLength = this.options.values.length; 22623 } 22624 22625 $.Widget.prototype._setOption.apply( this, arguments ); 22626 22627 switch ( key ) { 22628 case "disabled": 22629 if ( value ) { 22630 this.handles.filter( ".ui-state-focus" ).blur(); 22631 this.handles.removeClass( "ui-state-hover" ); 22632 this.handles.propAttr( "disabled", true ); 22633 this.element.addClass( "ui-disabled" ); 22634 } else { 22635 this.handles.propAttr( "disabled", false ); 22636 this.element.removeClass( "ui-disabled" ); 22637 } 22638 break; 22639 case "orientation": 22640 this._detectOrientation(); 22641 this.element 22642 .removeClass( "ui-slider-horizontal ui-slider-vertical" ) 22643 .addClass( "ui-slider-" + this.orientation ); 22644 this._refreshValue(); 22645 break; 22646 case "value": 22647 this._animateOff = true; 22648 this._refreshValue(); 22649 this._change( null, 0 ); 22650 this._animateOff = false; 22651 break; 22652 case "values": 22653 this._animateOff = true; 22654 this._refreshValue(); 22655 for ( i = 0; i < valsLength; i += 1 ) { 22656 this._change( null, i ); 22657 } 22658 this._animateOff = false; 22659 break; 22660 } 22661 }, 22662 22663 //internal value getter 22664 // _value() returns value trimmed by min and max, aligned by step 22665 _value: function() { 22666 var val = this.options.value; 22667 val = this._trimAlignValue( val ); 22668 22669 return val; 22670 }, 22671 22672 //internal values getter 22673 // _values() returns array of values trimmed by min and max, aligned by step 22674 // _values( index ) returns single value trimmed by min and max, aligned by step 22675 _values: function( index ) { 22676 var val, 22677 vals, 22678 i; 22679 22680 if ( arguments.length ) { 22681 val = this.options.values[ index ]; 22682 val = this._trimAlignValue( val ); 22683 22684 return val; 22685 } else { 22686 // .slice() creates a copy of the array 22687 // this copy gets trimmed by min and max and then returned 22688 vals = this.options.values.slice(); 22689 for ( i = 0; i < vals.length; i+= 1) { 22690 vals[ i ] = this._trimAlignValue( vals[ i ] ); 22691 } 22692 22693 return vals; 22694 } 22695 }, 22696 22697 // returns the step-aligned value that val is closest to, between (inclusive) min and max 22698 _trimAlignValue: function( val ) { 22699 if ( val <= this._valueMin() ) { 22700 return this._valueMin(); 22701 } 22702 if ( val >= this._valueMax() ) { 22703 return this._valueMax(); 22704 } 22705 var step = ( this.options.step > 0 ) ? this.options.step : 1, 22706 valModStep = (val - this._valueMin()) % step, 22707 alignValue = val - valModStep; 22708 22709 if ( Math.abs(valModStep) * 2 >= step ) { 22710 alignValue += ( valModStep > 0 ) ? step : ( -step ); 22711 } 22712 22713 // Since JavaScript has problems with large floats, round 22714 // the final value to 5 digits after the decimal point (see #4124) 22715 return parseFloat( alignValue.toFixed(5) ); 22716 }, 22717 22718 _valueMin: function() { 22719 return this.options.min; 22720 }, 22721 22722 _valueMax: function() { 22723 return this.options.max; 22724 }, 22725 22726 _refreshValue: function() { 22727 var oRange = this.options.range, 22728 o = this.options, 22729 self = this, 22730 animate = ( !this._animateOff ) ? o.animate : false, 22731 valPercent, 22732 _set = {}, 22733 lastValPercent, 22734 value, 22735 valueMin, 22736 valueMax; 22737 22738 if ( this.options.values && this.options.values.length ) { 22739 this.handles.each(function( i, j ) { 22740 valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100; 22741 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 22742 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 22743 if ( self.options.range === true ) { 22744 if ( self.orientation === "horizontal" ) { 22745 if ( i === 0 ) { 22746 self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate ); 22747 } 22748 if ( i === 1 ) { 22749 self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); 22750 } 22751 } else { 22752 if ( i === 0 ) { 22753 self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate ); 22754 } 22755 if ( i === 1 ) { 22756 self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); 22757 } 22758 } 22759 } 22760 lastValPercent = valPercent; 22761 }); 22762 } else { 22763 value = this.value(); 22764 valueMin = this._valueMin(); 22765 valueMax = this._valueMax(); 22766 valPercent = ( valueMax !== valueMin ) ? 22767 ( value - valueMin ) / ( valueMax - valueMin ) * 100 : 22768 0; 22769 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 22770 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 22771 22772 if ( oRange === "min" && this.orientation === "horizontal" ) { 22773 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate ); 22774 } 22775 if ( oRange === "max" && this.orientation === "horizontal" ) { 22776 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); 22777 } 22778 if ( oRange === "min" && this.orientation === "vertical" ) { 22779 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate ); 22780 } 22781 if ( oRange === "max" && this.orientation === "vertical" ) { 22782 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); 22783 } 22784 } 22785 } 22786 22787}); 22788 22789$.extend( $.ui.slider, { 22790 version: "1.8.16" 22791}); 22792 22793}(jQuery)); 22794 22795jQuery.extend({ 22796 22797 handleError: function () {}, 22798 22799 createUploadIframe: function (id, uri) { 22800 var frameId = 'jQuery' + id; 22801 22802 if (window.ActiveXObject) { 22803 /*/ 22804 var io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />'); 22805 /*/ 22806 var io = document.createElement("iframe"); 22807 io.setAttribute("id", frameId); 22808 io.setAttribute("name", frameId); 22809 /**/ 22810 22811 if (typeof uri == 'boolean') { 22812 io.src = 'javascript:false'; 22813 } else if (typeof uri == 'string') { 22814 io.src = uri; 22815 } 22816 22817 } else { 22818 22819 var io = document.createElement('iframe'); 22820 io.id = frameId; 22821 io.name = frameId; 22822 } 22823 22824 io.style.position = 'absolute'; 22825 io.style.top = '-1000px'; 22826 io.style.left = '-1000px'; 22827 22828 document.body.appendChild(io); 22829 22830 return io; 22831 }, 22832 22833 ajaxUpload: function (s) { 22834 // TODO introduce global settings, allowing the client to modify them for all requests, not only timeout 22835 s = jQuery.extend({}, jQuery.ajaxSettings, s); 22836 22837 var id = new Date().getTime(); 22838 22839 io = jQuery.createUploadIframe(id, s.secureuri); 22840 22841 // Watch for a new set of requests 22842 if (s.global && !jQuery.active++) 22843 jQuery.event.trigger("ajaxStart"); 22844 22845 var requestDone = false;
22846 22847 // Create the request object 22848 var xml = {}; 22849 22850 if (s.global) 22851 jQuery.event.trigger("ajaxSend", [xml, s]); 22852 22853 // Wait for a response to come back 22854 var uploadCallback = function (isTimeout) { 22855 22856 function showErrorInfo(e) { 22857 } 22858 22859 try { 22860 22861 xml.responseText = io.contentWindow.document.body ? io.contentWindow.document.body.innerHTML : null; 22862 22863 xml.responseXML = io.contentWindow.document.XMLDocument ? io.contentWindow.document.XMLDocument : io.contentWindow.document; 22864 22865 } catch (e) { 22866 showErrorInfo(e); 22867 } 22868 22869 if (xml || isTimeout == "timeout") { 22870 requestDone = true; 22871 var status; 22872 try { 22873 status = isTimeout != "timeout" ? "success" : "error"; 22874 // Make sure that the request was successful or notmodified 22875 22876 if (status != "error") { 22877 22878 // process the data (runs the xml through httpData regardless of callback) 22879 var data = jQuery.uploadHttpData(xml, s.dataType); 22880 22881 // If a local callback was specified, fire it and pass it the data 22882 if (s.success) s.success(data, status); 22883 22884 // Fire the global callback 22885 if (s.global) jQuery.event.trigger("ajaxSuccess", [xml, s]); 22886 22887 } else jQuery.handleError(s, xml, status); 22888 22889 } catch (e) { 22890 22891 status = "error"; 22892 jQuery.handleError(s, xml, status, e); 22893 } 22894 22895 // The request was completed 22896 if (s.global) jQuery.event.trigger("ajaxComplete", [xml, s]); 22897 22898 // Handle the global AJAX counter 22899 if (s.global && !--jQuery.active) jQuery.event.trigger("ajaxStop"); 22900 22901 // Process result 22902 if (s.complete) s.complete(xml, status); 22903 22904 jQuery(io).unbind(); 22905 22906 setTimeout(function () { 22907 try { 22908 jQuery(io).remove(); 22909 jQuery(form).remove(); 22910 22911 } catch (e) { 22912 xml = null; 22913 } 22914 22915 }, 100); 22916 22917 } 22918 22919 } 22920 22921 // Timeout checker 22922 if (s.timeout > 0) { 22923 22924 setTimeout(function () { 22925 // Check to see if the request is still happening 22926 if (!requestDone) { 22927 uploadCallback("timeout"); 22928 } 22929 22930 }, s.timeout); 22931 22932 } 22933 22934 try { 22935 22936 var frameId = 'jQuery' + id; 22937 var io = document.getElementById(frameId); 22938 22939 // Initialize the HTML form properties in case they are 22940 // not defined in the HTML form. 22941 s.uploadform.action = s.url; 22942 s.uploadform.method = 'POST'; 22943 s.uploadform.target = frameId; 22944 // s.uploadform.target = '_blank'; 22945 22946 if (s.uploadform.encoding) { 22947 // IE does not respect property enctype for HTML forms. 22948 // Instead use property encoding. 22949 s.uploadform.encoding = 'multipart/form-data'; 22950 } else { 22951 s.uploadform.enctype = 'multipart/form-data'; 22952 } 22953 22954 if (window.attachEvent) { 22955 io.attachEvent('onload', uploadCallback); 22956 } else { 22957 io.addEventListener('load', uploadCallback, false); 22958 } 22959 22960 s.uploadform.submit(); 22961 22962 } catch (e) { 22963 jQuery.handleError(s, xml, null, e); 22964 } 22965 22966 return { 22967 abort: function () {} 22968 }; 22969 22970 }, 22971 22972 uploadHttpData: function (r, type) { 22973 var data = !type; 22974 data = type == "xml" || data ? r.responseXML : r.responseText; 22975 22976 // If the type is "script", eval it in global context 22977 if ( type == "script" ) jQuery.globalEval( data ); // only for jquery 1.1... 22978 22979 // Get the JavaScript object, if JSON is used. 22980 if ( type == "json" ) eval( "data = " + data ); // only for jquery 1.1... 22981 22982 // evaluate scripts within html 22983 if ( type == "html" ) jQuery("<div>").html(data); // only for jquery 1.1... 22984 22985 return data; 22986 } 22987}); 22988(function($){ 22989 /* hoverIntent by Brian Cherne */ 22990 $.fn.hoverIntent = function(f,g) { 22991 // default configuration options 22992 var cfg = { 22993 sensitivity: 7, 22994 interval: 100, 22995 timeout: 0 22996 }; 22997 // override configuration options with user supplied object 22998 cfg = $.extend(cfg, g ? { over: f, out: g } : f ); 22999 23000 // instantiate variables 23001 // cX, cY = current X and Y position of mouse, updated by mousemove event 23002 // pX, pY = previous X and Y position of mouse, set by mouseover and polling interval 23003 var cX, cY, pX, pY; 23004 23005 // A private function for getting mouse position 23006 var track = function(ev) { 23007 cX = ev.pageX; 23008 cY = ev.pageY; 23009 }; 23010 23011 // A private function for comparing current and previous mouse position 23012 var compare = function(ev,ob) { 23013 ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); 23014 // compare mouse positions to see if they've crossed the threshold 23015 if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) { 23016 $(ob).unbind("mousemove",track); 23017 // set hoverIntent state to true (so mouseOut can be called) 23018 ob.hoverIntent_s = 1; 23019 return cfg.over.apply(ob,[ev]); 23020 } else {
23021 // set previous coordinates for next time 23022 pX = cX; pY = cY; 23023 // use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs) 23024 ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval ); 23025 } 23026 }; 23027 23028 // A private function for delaying the mouseOut function 23029 var delay = function(ev,ob) { 23030 ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); 23031 ob.hoverIntent_s = 0; 23032 return cfg.out.apply(ob,[ev]); 23033 }; 23034 23035 // A private function for handling mouse 'hovering' 23036 var handleHover = function(e) { 23037 // next three lines copied from jQuery.hover, ignore children onMouseOver/onMouseOut 23038 var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget; 23039 while ( p && p != this ) { try { p = p.parentNode; } catch(e) { p = this; } } 23040 if ( p == this ) { return false; } 23041 23042 // copy objects to be passed into t (required for event object to be passed in IE) 23043 var ev = jQuery.extend({},e); 23044 var ob = this; 23045 23046 // cancel hoverIntent timer if it exists 23047 if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); } 23048 23049 // else e.type == "onmouseover" 23050 if (e.type == "mouseover") { 23051 // set "previous" X and Y position based on initial entry point 23052 pX = ev.pageX; pY = ev.pageY; 23053 // update "current" X and Y position based on mousemove 23054 $(ob).bind("mousemove",track); 23055 // start polling interval (self-calling timeout) to compare mouse coordinates over time 23056 if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );} 23057 23058 // else e.type == "onmouseout" 23059 } else { 23060 // unbind expensive mousemove event 23061 $(ob).unbind("mousemove",track); 23062 // if hoverIntent state is true, then call the mouseOut function after the specified delay 23063 if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );} 23064 } 23065 }; 23066 23067 // bind the function to the two event listeners 23068 return this.mouseover(handleHover).mouseout(handleHover); 23069 }; 23070 23071})(jQuery); 23072 23073/* 23074 * Superfish v1.4.8 - jQuery menu widget 23075 * Copyright (c) 2008 Joel Birch 23076 * 23077 * Dual licensed under the MIT and GPL licenses: 23078 * http://www.opensource.org/licenses/mit-license.php 23079 * http://www.gnu.org/licenses/gpl.html 23080 * 23081 * CHANGELOG: http://users.tpg.com.au/j_birch/plugins/superfish/changelog.txt 23082 */ 23083 23084;(function($){ 23085 $.fn.superfish = function(op){ 23086 23087 var sf = $.fn.superfish, 23088 c = sf.c, 23089 $arrow = $(['<span class="',c.arrowClass,'"> »</span>'].join('')), 23090 over = function(){ 23091 var $$ = $(this), menu = getMenu($$); 23092 clearTimeout(menu.sfTimer); 23093 $$.showSuperfishUl().siblings().hideSuperfishUl(); 23094 }, 23095 out = function(){ 23096 var $$ = $(this), menu = getMenu($$), o = sf.op; 23097 clearTimeout(menu.sfTimer); 23098 menu.sfTimer=setTimeout(function(){ 23099 o.retainPath=($.inArray($$[0],o.$path)>-1); 23100 $$.hideSuperfishUl(); 23101 if (o.$path.length && $$.parents(['li.',o.hoverClass].join('')).length<1){over.call(o.$path);} 23102 },o.delay); 23103 }, 23104 getMenu = function($menu){ 23105 var menu = $menu.parents(['ul.',c.menuClass,':first'].join(''))[0]; 23106 sf.op = sf.o[menu.serial]; 23107 return menu; 23108 }, 23109 addArrow = function($a){ $a.addClass(c.anchorClass).append($arrow.clone()); }; 23110 23111 return this.each(function() { 23112 var s = this.serial = sf.o.length; 23113 var o = $.extend({},sf.defaults,op); 23114 o.$path = $('li.'+o.pathClass,this).slice(0,o.pathLevels).each(function(){ 23115 $(this).addClass([o.hoverClass,c.bcClass].join(' ')) 23116 .filter('li:has(ul)').removeClass(o.pathClass); 23117 }); 23118 sf.o[s] = sf.op = o; 23119 23120 $('li:has(ul)',this)[($.fn.hoverIntent && !o.disableHI) ? 'hoverIntent' : 'hover'](over,out).each(function() { 23121 if (o.autoArrows) addArrow( $('>a:first-child',this) ); 23122 }) 23123 .not('.'+c.bcClass) 23124 .hideSuperfishUl(); 23125 23126 var $a = $('a',this); 23127 $a.each(function(i){ 23128 var $li = $a.eq(i).parents('li'); 23129 $a.eq(i).focus(function(){over.call($li);}).blur(function(){out.call($li);}); 23130 }); 23131 o.onInit.call(this); 23132 23133 }).each(function() { 23134 var menuClasses = [c.menuClass]; 23135 if (sf.op.dropShadows && !($.browser.msie && $.browser.version < 7)) menuClasses.push(c.shadowClass); 23136 $(this).addClass(menuClasses.join(' ')); 23137 }); 23138 }; 23139 23140 var sf = $.fn.superfish; 23141 sf.o = []; 23142 sf.op = {}; 23143 sf.IE7fix = function(){ 23144 var o = sf.op; 23145 if ($.browser.msie && $.browser.version >
23145 6 && o.dropShadows && o.animation.opacity!=undefined) 23146 this.toggleClass(sf.c.shadowClass+'-off'); 23147 }; 23148 sf.c = { 23149 bcClass : 'sf-breadcrumb', 23150 menuClass : 'sf-js-enabled', 23151 anchorClass : 'sf-with-ul', 23152 arrowClass : 'sf-sub-indicator', 23153 shadowClass : 'sf-shadow' 23154 }; 23155 sf.defaults = { 23156 hoverClass : 'sfHover', 23157 pathClass : 'overideThisToUse', 23158 pathLevels : 1, 23159 delay : 800, 23160 animation : {opacity:'show'}, 23161 speed : 'normal', 23162 autoArrows : true, 23163 dropShadows : true, 23164 disableHI : false, // true disables hoverIntent detection 23165 onInit : function(){}, // callback functions 23166 onBeforeShow: function(){}, 23167 onShow : function(){}, 23168 onHide : function(){} 23169 }; 23170 $.fn.extend({ 23171 hideSuperfishUl : function(){ 23172 var o = sf.op, 23173 not = (o.retainPath===true) ? o.$path : ''; 23174 o.retainPath = false; 23175 var $ul = $(['li.',o.hoverClass].join(''),this).add(this).not(not).removeClass(o.hoverClass) 23176 .find('>ul').hide().css('visibility','hidden'); 23177 o.onHide.call($ul); 23178 return this; 23179 }, 23180 showSuperfishUl : function(){ 23181 var o = sf.op, 23182 sh = sf.c.shadowClass+'-off', 23183 $ul = this.addClass(o.hoverClass) 23184 .find('>ul:hidden').css('visibility','visible'); 23185 sf.IE7fix.call($ul); 23186 o.onBeforeShow.call($ul); 23187 $ul.animate(o.animation,o.speed,function(){ sf.IE7fix.call($ul); o.onShow.call($ul); }); 23188 return this; 23189 } 23190 }); 23191 23192})(jQuery); 23193 23194/*! 23195 * imagesLoaded PACKAGED v3.1.8 23196 * JavaScript is all like "You images are done yet or what?" 23197 * MIT License 23198 */ 23199 23200 23201/*! 23202 * EventEmitter v4.2.6 - git.io/ee 23203 * Oliver Caldwell 23204 * MIT license 23205 * @preserve 23206 */ 23207 23208(function () { 23209 23210 23211 /** 23212 * Class for managing events. 23213 * Can be extended to provide event functionality in other classes. 23214 * 23215 * @class EventEmitter Manages event registering and emitting. 23216 */ 23217 function EventEmitter() {} 23218 23219 // Shortcuts to improve speed and size 23220 var proto = EventEmitter.prototype; 23221 var exports = this; 23222 var originalGlobalValue = exports.EventEmitter; 23223 23224 /** 23225 * Finds the index of the listener for the event in it's storage array. 23226 * 23227 * @param {Function[]} listeners Array of listeners to search through. 23228 * @param {Function} listener Method to look for. 23229 * @return {Number} Index of the specified listener, -1 if not found 23230 * @api private 23231 */ 23232 function indexOfListener(listeners, listener) { 23233 var i = listeners.length; 23234 while (i--) { 23235 if (listeners[i].listener === listener) { 23236 return i; 23237 } 23238 } 23239 23240 return -1; 23241 } 23242 23243 /** 23244 * Alias a method while keeping the context correct, to allow for overwriting of target method. 23245 * 23246 * @param {String} name The name of the target method. 23247 * @return {Function} The aliased method 23248 * @api private 23249 */ 23250 function alias(name) { 23251 return function aliasClosure() { 23252 return this[name].apply(this, arguments); 23253 }; 23254 } 23255 23256 /** 23257 * Returns the listener array for the specified event. 23258 * Will initialise the event object and listener arrays if required. 23259 * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object c
vendor: 10,814 bytes, lines 23259-23552
23259ontaining bar and baz. But only if you have either defined them with defineEvent or added some listeners to them. 23260 * Each property in the object response is an array of listener functions. 23261 * 23262 * @param {String|RegExp} evt Name of the event to return the listeners from. 23263 * @return {Function[]|Object} All listener functions for the event. 23264 */ 23265 proto.getListeners = function getListeners(evt) { 23266 var events = this._getEvents(); 23267 var response; 23268 var key; 23269 23270 // Return a concatenated array of all matching events if 23271 // the selector is a regular expression. 23272 if (typeof evt === 'object') { 23273 response = {}; 23274 for (key in events) { 23275 if (events.hasOwnProperty(key) && evt.test(key)) { 23276 response[key] = events[key]; 23277 } 23278 } 23279 } 23280 else { 23281 response = events[evt] || (events[evt] = []); 23282 } 23283 23284 return response; 23285 }; 23286 23287 /** 23288 * Takes a list of listener objects and flattens it into a list of listener functions. 23289 * 23290 * @param {Object[]} listeners Raw listener objects. 23291 * @return {Function[]} Just the listener functions. 23292 */ 23293 proto.flattenListeners = function flattenListeners(listeners) { 23294 var flatListeners = []; 23295 var i; 23296 23297 for (i = 0; i < listeners.length; i += 1) { 23298 flatListeners.push(listeners[i].listener); 23299 } 23300 23301 return flatListeners; 23302 }; 23303 23304 /** 23305 * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful. 23306 * 23307 * @param {String|RegExp} evt Name of the event to return the listeners from. 23308 * @return {Object} All listener functions for an event in an object. 23309 */ 23310 proto.getListenersAsObject = function getListenersAsObject(evt) { 23311 var listeners = this.getListeners(evt); 23312 var response; 23313 23314 if (listeners instanceof Array) { 23315 response = {}; 23316 response[evt] = listeners; 23317 } 23318 23319 return response || listeners; 23320 }; 23321 23322 /** 23323 * Adds a listener function to the specified event. 23324 * The listener will not be added if it is a duplicate. 23325 * If the listener returns true then it will be removed after it is called. 23326 * If you pass a regular expression as the event name then the listener will be added to all events that match it. 23327 * 23328 * @param {String|RegExp} evt Name of the event to attach the listener to. 23329 * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. 23330 * @return {Object} Current instance of EventEmitter for chaining. 23331 */ 23332 proto.addListener = function addListener(evt, listener) { 23333 var listeners = this.getListenersAsObject(evt); 23334 var listenerIsWrapped = typeof listener === 'object'; 23335 var key; 23336 23337 for (key in listeners) { 23338 if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) { 23339 listeners[key].push(listenerIsWrapped ? listener : { 23340 listener: listener, 23341 once: false 23342 }); 23343 } 23344 } 23345 23346 return this; 23347 }; 23348 23349 /** 23350 * Alias of addListener 23351 */ 23352 proto.on = alias('addListener'); 23353 23354 /** 23355 * Semi-alias of addListener. It will add a listener that will be 23356 * automatically removed after it's first execution. 23357 * 23358 * @param {String|RegExp} evt Name of the event to attach the listener to. 23359 * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. 23360 * @return {Object} Current instance of EventEmitter for chaining. 23361 */ 23362 proto.addOnceListener = function addOnceListener(evt, listener) { 23363 return this.addListener(evt, { 23364 listener: listener, 23365 once: true 23366 }); 23367 }; 23368 23369 /** 23370 * Alias of addOnceListener. 23371 */ 23372 proto.once = alias('addOnceListener'); 23373 23374 /** 23375 * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad. 23376 * You need to tell it what event names should be matched by a regex. 23377 * 23378 * @param {String} evt Name of the event to create. 23379 * @return {Object} Current instance of EventEmitter for chaining. 23380 */ 23381 proto.defineEvent = function defineEvent(evt) { 23382 this.getListeners(evt); 23383 return this; 23384 }; 23385 23386 /** 23387 * Uses defineEvent to define multiple events. 23388 * 23389 * @param {String[]} evts An array of event names to define. 23390 * @return {Object} Current instance of EventEmitter for chaining. 23391 */ 23392 proto.defineEvents = function defineEvents(evts) { 23393 for (var i = 0; i < evts.length; i += 1) { 23394 this.defineEvent(evts[i]); 23395 } 23396 return this; 23397 }; 23398 23399 /** 23400 * Removes a listener function from the specified event. 23401 * When passed a regular expression as the event name, it will remove the listener from all events that match it. 23402 * 23403 * @param {String|RegExp} evt Name of the event to remove the listener from. 23404 * @param {Function} listener Method to remove from the event. 23405 * @return {Object} Current instance of EventEmitter for chaining. 23406 */ 23407 proto.removeListener = function removeListener(evt, listener) { 23408 var listeners = this.getListenersAsObject(evt); 23409 var index; 23410 var key; 23411 23412 for (key in listeners) { 23413 if (listeners.hasOwnProperty(key)) { 23414 index = indexOfListener(listeners[key], listener); 23415 23416 if (index !== -1) { 23417 listeners[key].splice(index, 1); 23418 } 23419 } 23420 } 23421 23422 return this; 23423 }; 23424 23425 /** 23426 * Alias of removeListener 23427 */ 23428 proto.off = alias('removeListener'); 23429 23430 /** 23431 * Adds listeners in bulk using the manipulateListeners method. 23432 * If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added. 23433 * You can also pass it a regular expression to add the array of listeners to all events that match it. 23434 * Yeah, this function does quite a bit. That's probably a bad thing. 23435 * 23436 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once. 23437 * @param {Function[]} [listeners] An optional array of listener functions to add. 23438 * @return {Object} Current instance of EventEmitter for chaining. 23439 */ 23440 proto.addListeners = function addListeners(evt, listeners) { 23441 // Pass through to manipulateListeners 23442 return this.manipulateListeners(false, evt, listeners); 23443 }; 23444 23445 /** 23446 * Removes listeners in bulk using the manipulateListeners method. 23447 * If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. 23448 * You can also pass it an event name and an array of listeners to be removed. 23449 * You can also pass it a regular expression to remove the listeners from all events that match it. 23450 * 23451 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once. 23452 * @param {Function[]} [listeners] An optional array of listener functions to remove. 23453 * @return {Object} Current instance of EventEmitter for chaining. 23454 */ 23455 proto.removeListeners = function removeListeners(evt, listeners) { 23456 // Pass through to manipulateListeners 23457 return this.manipulateListeners(true, evt, listeners); 23458 }; 23459 23460 /** 23461 * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level. 23462 * The first argument will determine if the listeners are removed (true) or added (false). 23463 * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. 23464 * You can also pass it an event name and an array of listeners to be added/removed. 23465 * You can also pass it a regular expression to manipulate the listeners of all events that match it. 23466 * 23467 * @param {Boolean} remove True if you want to remove listeners, false if you want to add. 23468 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once. 23469 * @param {Function[]} [listeners] An optional array of listener functions to add/remove. 23470 * @return {Object} Current instance of EventEmitter for chaining. 23471 */ 23472 proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) { 23473 var i; 23474 var value; 23475 var single = remove ? this.removeListener : this.addListener; 23476 var multiple = remove ? this.removeListeners : this.addListeners; 23477 23478 // If evt is an object then pass each of it's properties to this method 23479 if (typeof evt === 'object' && !(evt instanceof RegExp)) { 23480 for (i in evt) { 23481 if (evt.hasOwnProperty(i) && (value = evt[i])) { 23482 // Pass the single listener straight through to the singular method 23483 if (typeof value === 'function') { 23484 single.call(this, i, value); 23485 } 23486 else { 23487 // Otherwise pass back to the multiple function 23488 multiple.call(this, i, value); 23489 } 23490 } 23491 } 23492 } 23493 else { 23494 // So evt must be a string 23495 // And listeners must be an array of listeners 23496 // Loop over it and pass each one to the multiple method 23497 i = listeners.length; 23498 while (i--) { 23499 single.call(this, evt, listeners[i]); 23500 } 23501 } 23502 23503 return this; 23504 }; 23505 23506 /** 23507 * Removes all listeners from a specified event. 23508 * If you do not specify an event then all listeners will be removed. 23509 * That means every event will be emptied. 23510 * You can also pass a regex to remove all events that match it. 23511 * 23512 * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed. 23513 * @return {Object} Current instance of EventEmitter for chaining. 23514 */ 23515 proto.removeEvent = function removeEvent(evt) { 23516 var type = typeof evt; 23517 var events = this._getEvents(); 23518 var key; 23519 23520 // Remove different things depending on the state of evt 23521 if (type === 'string') { 23522 // Remove all listeners for the specified event 23523 delete events[evt]; 23524 } 23525 else if (type === 'object') { 23526 // Remove all events matching the regex. 23527 for (key in events) { 23528 if (events.hasOwnProperty(key) && evt.test(key)) { 23529 delete events[key]; 23530 } 23531 } 23532 } 23533 else { 23534 // Remove all listeners in all events 23535 delete this._events; 23536 } 23537 23538 return this; 23539 }; 23540 23541 /** 23542 * Alias of removeEvent. 23543 * 23544 * Added to mirror the node API. 23545 */ 23546 proto.removeAllListeners = alias('removeEvent'); 23547 23548 /** 23549 * Emits an event of your choice. 23550 * When emitted, every listener attached to that event will be executed. 23551 * If you pass the optional argument array then those arguments will be passed to every listener upon execution. 23552 * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
23553 * So they will not arrive within the array on the other side, they will be separate. 23554 * You can also pass a regular expression to emit to all events that match it. 23555 * 23556 * @param {String|RegExp} evt Name of the event to emit and execute listeners for. 23557 * @param {Array} [args] Optional array of arguments to be passed to each listener. 23558 * @return {Object} Current instance of EventEmitter for chaining. 23559 */ 23560 proto.emitEvent = function emitEvent(evt, args) { 23561 var listeners = this.getListenersAsObject(evt); 23562 var listener; 23563 var i; 23564 var key; 23565 var response; 23566 23567 for (key in listeners) { 23568 if (listeners.hasOwnProperty(key)) { 23569 i = listeners[key].length; 23570 23571 while (i--) { 23572 // If the listener returns true then it shall be removed from the event 23573 // The function is executed either with a basic call or an apply if there is an args array 23574 listener = listeners[key][i]; 23575 23576 if (listener.once === true) { 23577 this.removeListener(evt, listener.listener); 23578 } 23579 23580 response = listener.listener.apply(this, args || []); 23581 23582 if (response === this._getOnceReturnValue()) { 23583 this.removeListener(evt, listener.listener); 23584 } 23585 } 23586 } 23587 } 23588 23589 return this; 23590 }; 23591 23592 /** 23593 * Alias of emitEvent 23594 */ 23595 proto.trigger = alias('emitEvent'); 23596 23597 /** 23598 * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on. 23599 * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it. 23600 * 23601 * @param {String|RegExp} evt Name of the event to emit and execute listeners for. 23602 * @param {...*} Optional additional arguments to be passed to each listener. 23603 * @return {Object} Current instance of EventEmitter for chaining. 23604 */ 23605 proto.emit = function emit(evt) { 23606 var args = Array.prototype.slice.call(arguments, 1); 23607 return this.emitEvent(evt, args); 23608 }; 23609 23610 /** 23611 * Sets the current value to check against when executing listeners. If a 23612 * listeners return value matches the one set here then it will be removed 23613 * after execution. This value defaults to true. 23614 * 23615 * @param {*} value The new value to check for when executing listeners. 23616 * @return {Object} Current instance of EventEmitter for chaining. 23617 */ 23618 proto.setOnceReturnValue = function setOnceReturnValue(value) { 23619 this._onceReturnValue = value; 23620 return this; 23621 }; 23622 23623 /** 23624 * Fetches the current value to check against when executing listeners. If 23625 * the listeners return value matches this one then it should be removed 23626 * automatically. It will return true by default. 23627 * 23628 * @return {*|Boolean} The current value to check for or the default, true. 23629 * @api private 23630 */ 23631 proto._getOnceReturnValue = function _getOnceReturnValue() { 23632 if (this.hasOwnProperty('_onceReturnValue')) { 23633 return this._onceReturnValue; 23634 } 23635 else { 23636 return true; 23637 } 23638 }; 23639 23640 /** 23641 * Fetches the events object and creates one if required. 23642 * 23643 * @return {Object} The events storage object. 23644 * @api private 23645 */ 23646 proto._getEvents = function _getEvents() { 23647 return this._events || (this._events = {}); 23648 }; 23649 23650 /** 23651 * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version. 23652 * 23653 * @return {Function} Non conflicting EventEmitter class. 23654 */ 23655 EventEmitter.noConflict = function noConflict() { 23656 exports.EventEmitter = originalGlobalValue; 23657 return EventEmitter; 23658 }; 23659 23660 // Expose the class either via AMD, CommonJS or the global object 23661 if (typeof define === 'function' && define.amd) { 23662 define('eventEmitter/EventEmitter',[],function () { 23663 return EventEmitter; 23664 }); 23665 } 23666 else if (typeof module === 'object' && module.exports){ 23667 module.exports = EventEmitter; 23668 } 23669 else { 23670 this.EventEmitter = EventEmitter; 23671 } 23672}.call(this)); 23673 23674/*! 23675 * eventie v1.0.4 23676 * event binding helper 23677 * eventie.bind( elem, 'click', myFn ) 23678 * eventie.unbind( elem, 'click', myFn ) 23679 */ 23680 23681/*jshint browser: true, undef: true, unused: true */ 23682/*global define: false */ 23683 23684( function( window ) { 23685 23686 23687 23688var docElem = document.documentElement; 23689 23690var bind = function() {}; 23691 23692function getIEEvent( obj ) { 23693 var event = window.event; 23694 // add event.target 23695 event.target = event.target || event.srcElement || obj; 23696 return event; 23697} 23698 23699if ( docElem.addEventListener ) { 23700 bind = function( obj, type, fn ) { 23701 obj.addEventListener( type, fn, false ); 23702 }; 23703} else if ( docElem.attachEvent ) { 23704 bind = function( obj, type, fn ) { 23705 obj[ type + fn ] = fn.handleEvent ? 23706 function() { 23707 var event = getIEEvent( obj ); 23708 fn.handleEvent.call( fn, event ); 23709 } : 23710 function() { 23711 var event = getIEEvent( obj ); 23712 fn.call( obj, event ); 23713 }; 23714 obj.attachEvent( "on" + type, obj[ type + fn ] ); 23715 }; 23716} 23717 23718var unbind = function() {}; 23719 23720if ( docElem.removeEventListener ) { 23721 unbind = function( obj, type, fn ) { 23722 obj.removeEventListener( type, fn, false ); 23723 }; 23724} else if ( docElem.detachEvent ) { 23725 unbind = function( obj, type, fn ) { 23726 obj.detachEvent( "on" + type, obj[ type + fn ] ); 23727 try { 23728 delete obj[ type + fn ]; 23729 } catch ( err ) { 23730 // can't delete window object properties 23731 obj[ type + fn ] = undefined; 23732 } 23733 }; 23734} 23735 23736var eventie = { 23737 bind: bind, 23738 unbind: unbind 23739}; 23740 23741// transport 23742if ( typeof define === 'function' && define.amd ) { 23743 // AMD 23744 define( 'eventie/eventie',eventie ); 23745} else { 23746 // browser global 23747 window.eventie = eventie; 23748} 23749 23750})( this ); 23751 23752/*! 23753 * imagesLoaded v3.1.8 23754 * JavaScript is all like "You images are done yet or what?" 23755 * MIT License 23756 */ 23757 23758( function( window, factory ) { 23759 // universal module definition 23760 23761 /*global define: false, module: false, require: false */ 23762 23763 if ( typeof define === 'function' && define.amd ) { 23764 // AMD 23765 define( [ 23766 'eventEmitter/EventEmitter', 23767 'eventie/eventie' 23768 ], function( EventEmitter, eventie ) { 23769 return factory( window, EventEmitter, eventie ); 23770 }); 23771 } else if ( typeof exports === 'object' ) { 23772 // CommonJS 23773 module.exports = factory( 23774 window, 23775 require('wolfy87-eventemitter'), 23776 require('eventie') 23777 ); 23778 } else { 23779 // browser global 23780 window.imagesLoaded = factory( 23781 window, 23782 window.EventEmitter, 23783 window.eventie 23784 ); 23785 } 23786 23787})( window, 23788 23789// -------------------------- factory -------------------------- // 23790 23791function factory( window, EventEmitter, eventie ) { 23792 23793 23794 23795var $ = window.jQuery; 23796var console = window.console; 23797var hasConsole = typeof console !== 'undefined'; 23798 23799// -------------------------- helpers -------------------------- // 23800 23801// extend objects 23802function extend( a, b ) { 23803 for ( var prop in b ) { 23804 a[ prop ] = b[ prop ]; 23805 } 23806 return a; 23807} 23808 23809var objToString = Object.prototype.toString; 23810function isArray( obj ) { 23811 return objToString.call( obj ) === '[object Array]'; 23812} 23813 23814// turn element or nodeList into an array 23815function makeArray( obj ) { 23816 var ary = []; 23817 if ( isArray( obj ) ) { 23818 // use object if already an array 23819 ary = obj; 23820 } else if ( typeof obj.length === 'number' ) { 23821 // convert nodeList to array 23822 for ( var i=0, len = obj.length; i < len; i++ ) { 23823 ary.push( obj[i] ); 23824 } 23825 } else { 23826 // array of single index 23827 ary.push( obj ); 23828 } 23829 return ary; 23830} 23831 23832 // -------------------------- imagesLoaded -------------------------- // 23833 23834 /** 23835 * @param {Array, Element, NodeList, String} elem 23836 * @param {Object or Function} options - if function, use as callback 23837 * @param {Function} onAlways - callback function 23838 */ 23839 function ImagesLoaded( elem, options, onAlways ) { 23840 // coerce ImagesLoaded() without new, to be new ImagesLoaded() 23841 if ( !( this instanceof ImagesLoaded ) ) { 23842 return new ImagesLoaded( elem, options ); 23843 } 23844 // use elem as selector string 23845 if ( typeof elem === 'string' ) { 23846 elem = document.querySelectorAll( elem ); 23847 } 23848 23849 this.elements = makeArray( elem ); 23850 this.options = extend( {}, this.options ); 23851 23852 if ( typeof options === 'function' ) { 23853 onAlways = options; 23854 } else { 23855 extend( this.options, options ); 23856 } 23857 23858 if ( onAlways ) { 23859 this.on( 'always', onAlways ); 23860 } 23861 23862 this.getImages(); 23863 23864 if ( $ ) { 23865 // add jQuery Deferred object 23866 this.jqDeferred = new $.Deferred(); 23867 } 23868 23869 // HACK check async to allow time to bind listeners 23870 var _this = this; 23871 setTimeout( function() { 23872 _this.check(); 23873 }); 23874 } 23875 23876 ImagesLoaded.prototype = new EventEmitter(); 23877 23878 ImagesLoaded.prototype.options = {}; 23879 23880 ImagesLoaded.prototype.getImages = function() { 23881 this.images = []; 23882 23883 // filter & find items if we have an item selector 23884 for ( var i=0, len = this.elements.length; i < len; i++ ) { 23885 var elem = this.elements[i]; 23886 // filter siblings 23887 if ( elem.nodeName === 'IMG' ) { 23888 this.addImage( elem ); 23889 } 23890 // find children 23891 // no non-element nodes, #143 23892 var nodeType = elem.nodeType; 23893 if ( !nodeType || !( nodeType === 1 || nodeType === 9 || nodeType === 11 ) ) { 23894 continue; 23895 } 23896 var childElems = elem.querySelectorAll('img'); 23897 // concat childElems to filterFound array 23898 for ( var j=0, jLen = childElems.length; j < jLen; j++ ) { 23899 var img = childElems[j]; 23900 this.addImage( img ); 23901 } 23902 } 23903 }; 23904 23905 /** 23906 * @param {Image} img 23907 */ 23908 ImagesLoaded.prototype.addImage = function( img ) { 23909 var loadingImage = new LoadingImage( img ); 23910 this.images.push( loadingImage ); 23911 }; 23912
23913 ImagesLoaded.prototype.check = function() { 23914 var _this = this; 23915 var checkedCount = 0; 23916 var length = this.images.length; 23917 this.hasAnyBroken = false; 23918 // complete if no images 23919 if ( !length ) { 23920 this.complete(); 23921 return; 23922 } 23923 23924 function onConfirm( image, message ) { 23925 if ( _this.options.debug && hasConsole ) { 23926 console.log( 'confirm', image, message ); 23927 } 23928 23929 _this.progress( image ); 23930 checkedCount++; 23931 if ( checkedCount === length ) { 23932 _this.complete(); 23933 } 23934 return true; // bind once 23935 } 23936 23937 for ( var i=0; i < length; i++ ) { 23938 var loadingImage = this.images[i]; 23939 loadingImage.on( 'confirm', onConfirm ); 23940 loadingImage.check(); 23941 } 23942 }; 23943 23944 ImagesLoaded.prototype.progress = function( image ) { 23945 this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded; 23946 // HACK - Chrome triggers event before object properties have changed. #83 23947 var _this = this; 23948 setTimeout( function() { 23949 _this.emit( 'progress', _this, image ); 23950 if ( _this.jqDeferred && _this.jqDeferred.notify ) { 23951 _this.jqDeferred.notify( _this, image ); 23952 } 23953 }); 23954 }; 23955 23956 ImagesLoaded.prototype.complete = function() { 23957 var eventName = this.hasAnyBroken ? 'fail' : 'done'; 23958 this.isComplete = true; 23959 var _this = this; 23960 // HACK - another setTimeout so that confirm happens after progress 23961 setTimeout( function() { 23962 _this.emit( eventName, _this ); 23963 _this.emit( 'always', _this ); 23964 if ( _this.jqDeferred ) { 23965 var jqMethod = _this.hasAnyBroken ? 'reject' : 'resolve'; 23966 _this.jqDeferred[ jqMethod ]( _this ); 23967 } 23968 }); 23969 }; 23970 23971 // -------------------------- jquery -------------------------- // 23972 23973 if ( $ ) { 23974 $.fn.imagesLoaded = function( options, callback ) { 23975 var instance = new ImagesLoaded( this, options, callback ); 23976 return instance.jqDeferred.promise( $(this) ); 23977 }; 23978 } 23979 23980 23981 // -------------------------- -------------------------- // 23982 23983 function LoadingImage( img ) { 23984 this.img = img; 23985 } 23986 23987 LoadingImage.prototype = new EventEmitter(); 23988 23989 LoadingImage.prototype.check = function() { 23990 // first check cached any previous images that have same src 23991 var resource = cache[ this.img.src ] || new Resource( this.img.src ); 23992 if ( resource.isConfirmed ) { 23993 this.confirm( resource.isLoaded, 'cached was confirmed' ); 23994 return; 23995 } 23996 23997 // If complete is true and browser supports natural sizes, 23998 // try to check for image status manually. 23999 if ( this.img.complete && this.img.naturalWidth !== undefined ) { 24000 // report based on naturalWidth 24001 this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' ); 24002 return; 24003 } 24004 24005 // If none of the checks above matched, simulate loading on detached element. 24006 var _this = this; 24007 resource.on( 'confirm', function( resrc, message ) { 24008 _this.confirm( resrc.isLoaded, message ); 24009 return true; 24010 }); 24011 24012 resource.check(); 24013 }; 24014 24015 LoadingImage.prototype.confirm = function( isLoaded, message ) { 24016 this.isLoaded = isLoaded; 24017 this.emit( 'confirm', this, message ); 24018 }; 24019 24020 // -------------------------- Resource -------------------------- // 24021 24022 // Resource checks each src, only once 24023 // separate class from LoadingImage to prevent memory leaks. See #115 24024 24025 var cache = {}; 24026 24027 function Resource( src ) { 24028 this.src = src; 24029 // add to cache 24030 cache[ src ] = this; 24031 } 24032 24033 Resource.prototype = new EventEmitter(); 24034 24035 Resource.prototype.check = function() { 24036 // only trigger checking once 24037 if ( this.isChecked ) { 24038 return; 24039 } 24040 // simulate loading on detached element 24041 var proxyImage = new Image(); 24042 eventie.bind( proxyImage, 'load', this ); 24043 eventie.bind( proxyImage, 'error', this ); 24044 proxyImage.src = this.src; 24045 // set flag 24046 this.isChecked = true; 24047 }; 24048 24049 // ----- events ----- // 24050 24051 // trigger specified handler for event type 24052 Resource.prototype.handleEvent = function( event ) { 24053 var method = 'on' + event.type; 24054 if ( this[ method ] ) { 24055 this[ method ]( event ); 24056 } 24057 }; 24058 24059 Resource.prototype.onload = function( event ) { 24060 this.confirm( true, 'onload' ); 24061 this.unbindProxyEvents( event ); 24062 }; 24063 24064 Resource.prototype.onerror = function( event ) { 24065 this.confirm( false, 'onerror' ); 24066 this.unbindProxyEvents( event ); 24067 }; 24068 24069 // ----- confirm ----- // 24070 24071 Resource.prototype.confirm = function( isLoaded, message ) { 24072 this.isConfirmed = true; 24073 this.isLoaded = isLoaded;
24074 this.emit( 'confirm', this, message ); 24075 }; 24076 24077 Resource.prototype.unbindProxyEvents = function( event ) { 24078 eventie.unbind( event.target, 'load', this ); 24079 eventie.unbind( event.target, 'error', this ); 24080 }; 24081 24082 // ----- ----- // 24083 24084 return ImagesLoaded; 24085 24086}); 24087 24088/**********************************************************************************\ 24089 * Set of common java helpers. 24090 * 24091 * The MIT License 24092 * 24093 * Copyright (c) 2008 Victor Denisenkov aka Mr.V!T 24094 * 24095 * Permission is hereby granted, free of charge, to any person obtaining a copy of 24096 * this software and associated documentation files (the "Software"), to deal in 24097 * the Software without restriction, including without limitation the rights to 24098 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 24099 * the Software, and to permit persons to whom the Software is furnished to do so, 24100 * subject to the following conditions: 24101 * 24102 * The above copyright notice and this permission notice shall be included in all 24103 * copies or substantial portions of the Software. 24104 * 24105 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24106 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 24107 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 24108 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 24109 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24110 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24111 * 24112 * @package vit-lib 24113 * @author Victor Denisenkov aka Mr.V!T 24114 * @version 1.0 24115\**********************************************************************************/ 24116 24117/** //** ----= escapeHtmlTags =----------------------------------------------\**//** \ 24118* 24119* Converts common HTML chars into entities. 24120* 24121* @param string str - HTML code to convert. 24122* @return string - Escaped HTML. 24123* 24124\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 24125var escapeHtmlTags_chars = { 24126 '&' : '&', 24127 '<' : '<', 24128 '>' : '>', 24129 '"' : '"', 24130 "'" : ''' 24131} //OBJECT escapeHtmlTags_chars 24132function escapeHtmlTags(str) { 24133 24134 //If smth wrong given, just returning it back 24135 if ( typeof(str) !== 'string' ) return str; 24136 24137 return str.replace(/['"&<>]/g, function (c) { 24138 return escapeHtmlTags_chars[c] || c; 24139 }); //FUNC string.replace.callback 24140} //FUNC escapeHtmlTags 24141 24142function decodeEntities ($str) { 24143 24144 for ( var $i in escapeHtmlTags_chars ) 24145 $str = $str.replace(escapeHtmlTags_chars[$i], $i); 24146 24147 return $str; 24148} //FUNC decodeEntities 24149 24150function getUrlHash () { 24151 return location.hash.replace(/^#/, ''); 24152} //FUNC getUrlHash 24153 24154/** //** ----= fullURL =----------------------------------------------------------------------------------------------\**//** \ 24155* 24156* Takes any URL and makes it full URL adding host if necesarry. 24157* Uses window.location for host value and autodetected scheme. 24158* 24159* @param string $url - Url to check. 24160* @param bool [$https] - Create https url. 24161* 24162* @return string - Full URL 24163* 24164\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 24165function fullURL ($url, $https) { 24166 24167 // Preparing desired shceme 24168 if ( isUndefined($https) ) 24169 $scheme = window.location.protocol+'//'; 24170 else 24171 $scheme = ($https) ? 'https://' : 'http://' ; 24172 24173 // Checking for sceme on string begining 24174 if ( $url.indexOf($scheme) !== 0 ) 24175 $url = $scheme+window.location.host+'/'+$url.ltrim(' \/'); 24176 24177 return $url; 24178} //FUNC fullURL 24179 24180/** //** ----= regexMatchAll =----------------------------------------------------------------------------------------------\**//** \ 24181* 24182* Executes regex on string multiple times, untill no further matches found. Returns array of matches. 24183* Supports PREG_SET_ORDER and PREG_PATTERN_ORDER similar to php's preg_match_all. 24184* 24185* @param string $str - String to match. 24186* @param regex $regex - Regular expression. 24187* 24188* @return array - All matches as array. 24189* 24190\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 24191var PREG_PATTERN_ORDER = 1; 24192var PREG_SET_ORDER = 2; 24193function regexMatchAll ($regex, $str, $order) { 24194 24195 // Order by default is PREG_PATTERN_ORDER to mimic php 24196 $order = $order || PREG_PATTERN_ORDER; 24197 24198 var $match; 24199 var $res = []; 24200 24201 // Looping through results 24202 // This will create results as for PREG_SET_ORDER flag 24203 while ( $match = $regex.exec($str) ) { 24204 24205 // Removing some trash, to end up with true array 24206 // It's important to allow [for var in array] code. 24207 delete($match['index']); 24208 delete($match['input']); 24209 24210 $res.push($match); 24211 } //WHILE matching 24212 24213 // Done if no need to reorder 24214 if ( $order === PREG_SET_ORDER ) 24215 return $res; 24216 24217 // Reordering in new array if necessary 24218 var $tmp = []; 24219 for ( var $i in $res ) 24220 for ( var $j in $res[$i] ) 24221 // Pushing matches if subset exists, or creating new one if not 24222 $tmp[$j] ? $tmp[$j].push($res[$i][$j]) : $tmp[$j] = [$res[$i][$j]]; 24223 24224 return $tmp; 24225} //FUNC regexMatchAll 24226 24227if ( isUndefined( jQuery.fn.disableSelection ) ) { 24228 24229jQuery.fn.disableSelection = function() { 24230 // Preparing event name, to allow selectstart or fallback to mousedown 24231 var $eventName = ( isUndefined(this.selectstart) ? 'mousedown' : 'selectstart' ) + '.vDisableSelection'; 24232 24233 this.on( $eventName, function( $e ) { 24234 $e.preventDefault(); 24235 }); //FUNC onMouseDown 24236 24237} //FUNC disableSelection 24238 24239jQuery.fn.enableSelection = function() { 24240 this.off('.vDisableSelection'); 24241} //FUNC enableSelection 24242 24243} //IF no disable seleciton 24244 24245function isDebug () { 24246 24247 if ( !isEmpty( getCookie('debug') ) ) 24248 return true; 24249 24250 if ( location.search.indexOf('debug=1') != -1 ) 24251 return true; 24252 24253 return false; 24254} //FUNC isDebug 24255 24256function isIframe () { 24257 try { 24258 return window.self !== window.top; 24259 } catch (e) { 24260 return true; 24261 } 24262} //FUNC isIframe 24263 24264function implode(glue, obj) { 24265 24266 // Faster will be call .join if array given 24267 24268 if ( obj instanceof Array ) 24269 return obj.join(glue); 24270 24271 // Or doing manually for object 24272 24273 var res = ''; 24274 24275 for ( var i in obj ) { 24276 if ( res ) res += glue; 24277 res += obj[i]; 24278 } //FOR each property 24279 24280 return res; 24281} //FUNC implode 24282 24283function ucfirst ($str) { 24284 return $str && $str[0].toUpperCase() + $str.slice(1); 24285} //FUNC ucfirst 24286 24287String.prototype.capitalize = function() { 24288 return ucfirst(this); 24289} //FUNC capitalize 24290 24291if ( !String.prototype.startsWith ) { 24292String.prototype.startsWith = function ($needle) { 24293 return this.lastIndexOf($needle, 0) === 0; 24294}} //FUNC startsWith 24295 24296if ( !String.prototype.endsWith ) { 24297String.prototype.endsWith = function ($needle) { 24298 var $lastIndex = this.lastIndexOf($needle); 24299 return ( $lastIndex != -1 ) && ( $lastIndex + $needle.length == this.length ); 24300}} //FUNC endsWith 24301 24302function strRepeat ($str, $multiplier) { 24303 24304 if ( !$multiplier ) 24305 return ''; 24306 24307 var $res = ''; 24308 24309 for ( var $i = 0; $i < $multiplier; $i++ ) { 24310 $res += $str; 24311 } //FOR multiple times 24312 24313 return $res; 24314} //FUNC strRepeat 24315 24316function instanceName ($var) { 24317 24318 // Determining instance using basic Object.toString() 24319 $res = Object.prototype.toString.call($var); 24320 24321 // Cutting usual [object ...] from it to get clean instance name 24322 $res = $res.slice(8, -1); 24323 24324 return $res; 24325} //FUNC instanceName 24326var getClassOf = instanceName; 24327 24328function isClass ($var, $class) { 24329 return getClassOf($var) === $class; 24330} // FUNC isBool 24331 24332function isBool ($var) { 24333 return typeof($var) == 'boolean'; 24334} // FUNC isBool 24335 24336function isNumber ($var) { 24337 return typeof($var) == 'number'; 24338} //FUNC isNumber 24339 24340function isNumeric ($var) { 24341 return $var !== '' && !isNaN($var) && isFinite($var); 24342} //FUNC isNumeric 24343 24344function isInt ($var) { 24345 return !isNaN($var) && (parseInt($var) == $var); 24346} //FUNC isInt 24347 24348function isFloat ($var) { 24349 return $var !== '' && !isNaN($var) && isFinite($var) && !isInt($var); 24350} //FUNC isFloat 24351 24352function isArray ($var) { 24353 return $var instanceof Array; 24354} //FUNC isArray 24355 24356function isObject ($var, $orArray) { 24357 24358 // If not object - then false anyway
24359 if ( typeof($var) != 'object' ) 24360 return false; 24361 24362 // If arrays allowed - we have result already 24363 if ( $orArray ) 24364 return true; 24365 24366 // Now need to check if it is array 24367 // Should not be array for strict check 24368 return ( !isArray($var) ); 24369 24370} //FUNC isArray 24371 24372var isString = isStr; 24373function isStr ($var) { 24374 return typeof($var) == 'string'; 24375} //FUNC isStr 24376 24377function isIn ($var, $values) { 24378 return $values.indexOf($var) > -1; 24379} //FUNC isIn 24380 24381// Global constant for undefined type checks 24382var UNDEFINED = 'undefined'; 24383 24384function isUndefined($var) { 24385 return $var === void 0; 24386} //FUNC isUndefined 24387 24388function isDefined($var) { 24389 return !isUndefined($var); 24390} //FUNC isDefined 24391 24392function setDefault($var, $default) { 24393 return isDefined($var)? $var : $default; 24394} //FUNC isDefined 24395 24396var isset = isSet; 24397function isSet ($var) { 24398 return !isUndefined($var); 24399} //FUNC isSet 24400 24401var empty = isEmpty; 24402function isEmpty ($var) { 24403 24404 // Fastest way to test 24405 if ( !$var ) 24406 return true; 24407 24408 // '0' means empty too 24409 if ( $var === '0' ) 24410 return true; 24411 24412 // Extra test need only for objects, so if it's not object - no need to test more 24413 if ( typeof($var) !== 'object' ) 24414 return false; 24415 24416 // Testing array first (faster test) 24417 if ( isArray($var) ) 24418 return $var.length == 0; 24419 24420 // If still here - its object and need to loop through to check properties 24421 // Any existing property ($i) means it's not empty 24422 for ( var $i in $var ) 24423 return false; 24424 24425 // If not triggered above - that's empty object 24426 return true; 24427} //FUNC isEmpty 24428 24429function asBool ($var) { 24430 24431 // Reacting to speciefic strings 24432 if ( $var === 'false' ) 24433 return false; 24434 24435 if ( $var === 'true' ) 24436 return true; 24437 24438 return !isEmpty($var); 24439} //FUNC asBool 24440 24441function isNumber ($var) { 24442 return typeof($var) == 'number'; 24443} //FUNC isArray 24444 24445function isFunction ($var) { 24446 return typeof($var) == 'function'; 24447} //FUNC isArray 24448 24449function isScalar ($var, $ex) { 24450 24451 // Testing common scalar types 24452 if ( (/boolean|number|string/).test(typeof($var)) ) 24453 return true; 24454 24455 // Extra test assumes that NULL and undefined are scalars 24456 if ( !$ex ) 24457 return false; 24458 24459 if ( typeof($var) == 'undefined' || $var === null ) 24460 return true; 24461 24462 return false; 24463} //FUNC isScalar 24464 24465function isScalarArray ($var, $ex) { 24466 24467 if ( !isArray($var) ) 24468 return false; 24469 24470 // If at least one array item is not scalar - that's not scalar array 24471 for ( var $i = 0; $i < $var.length; $i++ ) 24472 if ( !isScalar($var[$i], $ex) ) 24473 return false; 24474 24475 return true; 24476} //FUNC isScalar 24477 24478/** //** ----= arrayPath =--------------------------------------------------------------------------------------\**//** \ 24479* 24480* Traversing array using key paths. Allows to get or set values. 24481* 24482* @param array $array - Array to traverse. 24483* @param mixed $path - Path to navigate. Either string or array. 24484* E.g.: 'key1/key2/deepvalue' or ['key1', 'key2', 'deepvalue'] 24485* @param mixed [$value] - Value to set for setter mode (if omited, will return value instead) 24486* @param string [$divider] - Path divider (used only if path is given as string). 24487* 24488* @return mixed - Target value in getter mode, or new value in setter. 24489* 24490\**//** ---------------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 24491function arrayPath ($array, $path, $value, $divider) { 24492 24493 $divider = $divider || '/'; 24494 24495 // Checking for setter mode 24496 var $isSetter = ( !isUndefined($value) ); 24497 24498 // Splitting path to individual keys 24499 if ( !isArray($path) ) { 24500 $path = $path.split($divider); 24501 } //IF not array given 24502 24503 // Looping down to value in array 24504 // Using refs for recurcive looping 24505 // Thus saving parent for last step 24506 var $var = $array; 24507 var $parent = $array; 24508 24509 for ( var $i in $path ) { 24510 24511 $key = $path[$i]; 24512 24513 // In setter mode - need to make sure that var is array 24514 // In getter mode - if var is already not array - that's null return 24515 if ( !isObject($var) ) 24516 if ( $isSetter ) 24517 $var = []; 24518 else 24519 return; 24520 24521 // Checking for key presence 24522 // In getter mode unexisting key results to NULL result 24523 // In setter mode - path should be created 24524 // This should be done priror next iteration to avoid source array altering 24525 if ( isUndefined($var[$key]) ) 24526 if ( $isSetter ) 24527 $var[$key] = {}; 24528 else 24529 return; 24530 24531 // Saving ref for next iteration 24532 $parent = $var; 24533 $var = $var[$key]; 24534 24535 } //FOR each path key 24536 24537 // At this point ref points to end value 24538 // Can set and return it 24539 if ( $isSetter ) 24540 $parent[$key] = $value; 24541 24542 return $var; 24543 24544} //FUNC arrayPath 24545 24546if ( !Object.keys ) { 24547 Object.keys = function (obj) { 24548 var keys = [], 24549 k; 24550 24551 for ( k in obj ) 24552 if ( Object.prototype.hasOwnProperty.call(obj, k) ) 24553 keys.push(k); 24554 24555 return keys; 24556 }; //FUNC keys 24557} //IF Object have no keys method 24558 24559/** //** ----= objSize =----------------------------------------------------------------------------------------------\**//** \ 24560* 24561* Returns object properties count. Usefull as analog of [].length for data objects. 24562* 24563* @param object $obj - Object to count. 24564* 24565* @return int - Object "size". 24566* 24567\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 24568function objSize ($obj) { 24569 24570 var $res = 0; 24571 for ( $i in $obj) 24572 if ( $obj.hasOwnProperty($i) ) 24573 $res++; 24574 24575 return $res; 24576} //FUNC objSize 24577 24578/** //** ----= objStep =----------------------------------------------------------------------------------------------\**//** \ 24579* 24580* Returns object key in "step" away from given key. 24581* 24582* @param object $obj - Object to search key in
24583* @param $key $key - Key to step from 24584* @param $step $step - Step to count from given key (can be negatve to count backwards) 24585* 24586* @return string - Found key, or FALSE if smth failed 24587* 24588\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 24589function objStep ($obj, $key, $step) { 24590 24591 // Using array for indexing keys, and then searching keys in it 24592 // In case smth goes wrong - FALSE is returned 24593 24594 var $idx = Object.keys($obj); 24595 24596 if ( $idx.length == 0 ) 24597 return false; 24598 24599 var $i = $idx.indexOf($key); 24600 24601 if ( $i < 0 ) 24602 return false; 24603 24604 // Stepping from key 24605 $i += $step; 24606 24607 if ( $i < 0 || $i >= $idx.length ) 24608 return false; 24609 24610 return $idx[$i]; 24611} //FUNC objStep 24612 24613/** //** ----= objNext, objPrev =--------------------------------------------------------------------------------------\**//** \ 24614* 24615* Common use cases of objStep for searching next/prev keys in object 24616* 24617* @param object $obj - Object to search key in 24618* @param $key $key - Key to step from 24619* 24620* @return string - Found key, or FALSE if smth failed 24621* 24622\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 24623function objPrev ($obj, $key) { 24624 return objStep($obj, $key, -1); 24625} //FUNC objPrev 24626function objNext ($obj, $key) { 24627 return objStep($obj, $key, 1); 24628} //FUNC objNext 24629 24630/** //** ----= objFirst, objLast =------------------------------------------------------------------------------\**//** \ 24631* 24632* Returns first/last object key. 24633* 24634* @param object $obj - Object to search key in 24635* 24636* @return string - Found key, or FALSE if smth failed 24637* 24638\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 24639function objFirst ($obj) { 24640 24641 var $idx = Object.keys($obj); 24642 24643 if ( $idx.length == 0 ) 24644 return false; 24645 24646 return $idx[0]; 24647} //FUNC objFirst 24648function objLast ($obj) { 24649 24650 var $idx = Object.keys($obj); 24651 24652 if ( $idx.length == 0 ) 24653 return false; 24654 24655 return $idx[$idx.length-1]; 24656} //FUNC objLast 24657 24658/** //** ----= isSame =----------------------------------------------------------------------------------------------\**//** \ 24659* 24660* Compares two objects given. Designed for data objects. 24661* 24662* @param object x, y - Objects to compare. 24663* @param bool [oneway] - Set TRUE to test only by x values (i.e y can be bigger, in other words - if X is in Y) 24664* @param bool [presort] - Set TRUE to presort incoming arrays. This may 24665* be necessary if comparing arrys in order 24666* independent way. Usefull for values lists. 24667* 24668\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 24669function isSame (x, y, oneway, presort) { 24670 24671 // Fast check for nulls / empties 24672 if ( !x || !y ) { 24673 24674 if ( !x && y ) return false; 24675 if ( x && !y ) return false; 24676 24677 return true; 24678 24679 } //IF some is null or empty 24680 24681 // IF arrays come - first better check lengths 24682 if ( x instanceof Array && y instanceof Array ) { 24683 24684 if ( x.length != y.length ) 24685 return false; 24686 24687 if ( presort ) { 24688 x.sort(); 24689 y.sort(); 24690 } //IF presort seet 24691 24692 } //IF arrays come 24693 24694 // First checking properties existance. 24695 // After this check full comparasions will be done in opposite direction 24696 24697 if ( !oneway ) { 24698 for ( var p in y ) { 24699 if ( typeof(x[p]) == 'undefined') 24700 return false; 24701 } //FOR each property in y 24702 } //IF not one way comparasion 24703 24704 // Type based checking, in opposite comparasion direction 24705 for ( var p in x ) { 24706 24707 // Checking self properties in oppose object, jsut existance first 24708 if ( typeof(y[p]) == 'undefined' ) 24709 return false; 24710 24711 if ( x[p] ) { // Fast symantec check, everything that is logically FALSE - no need to check by type 24712 24713 switch( typeof(x[p]) ) { 24714 24715 case 'object' : 24716 24717 // Checking objects recursively 24718 // This allows multidimensional objects checks, 24719 // But can possibly hang browser. Normally will not. 24720 // ToDo: prevent possible reqursions 24721 if ( !isSame(x[p], y[p], oneway, presort) ) 24722 return false; 24723 24724 break; 24725
24726 case 'function' : 24727 24728 // Of course toString is not best way to compare functions. 24729 // But normally same named funcitons should have same source code, 24730 // and it's anyway better and faster than to full syntax parsing. 24731 // Fast toString comparation will work in most typical cases. 24732 // Just don't use this function if U need to compare functions in objects so much!. 24733 if ( this[p].toString() != x[p].toString() ) 24734 return false; 24735 24736 break; 24737 default: 24738 24739 // At last simple check that will usually used :). 24740 if ( x[p] != y[p] ) 24741 return false; 24742 24743 } //SWITCH type of x 24744 24745 } else { //IF is value 24746 24747 // Checking same property on other object 24748 if ( y[p] ) 24749 return false; 24750 24751 } //If false value 24752 24753 } //FOR each property in x 24754 24755 return true; 24756} //FUNC isSame 24757 24758function isXHR2 () { 24759 24760 if ( !window.FormData ) 24761 return false; 24762 24763 // Testing for XMLHttpRequest Level 2 24764 var xhr = new XMLHttpRequest(); 24765 if ( !xhr.upload ) 24766 return false; 24767 24768 return true; 24769} //FUNC isXHR2 24770 24771function isFilesAPI () { 24772 24773 if ( !isXHR2() ) 24774 return false; 24775 24776 if ( !(window.File && window.FileList && window.FileReader) ) 24777 return false; 24778 24779 return true; 24780} //FUNC isFilesAPI 24781 24782function isIos () { 24783 return /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream; 24784} //FUNC isIos 24785 24786/** //** ----= isTouchScreen =--------------------------------------------------------------------------------------\**//** \ 24787* 24788* Tests if device is touch screen enabled device. 24789* 24790* @return bool - TRUE if device supports touchs screen. (i.e. pointer:coarse from css4 media queries.) 24791* 24792\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 24793function isTouchScreen () { 24794 24795 var $res = 'ontouchstart' in document.documentElement; 24796 24797 return $res; 24798 24799} //FUNC isTouchScreen 24800 24801/** //** ----= isJQ =----------------------------------------------------------------------------------------------\**//** \ 24802* 24803* Tests if given object is jQuery element 24804* 24805* @param MIXED $val - Value to check. 24806* 24807* @return bool - Check result. 24808* 24809\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 24810function isJQ ($val) { 24811 24812 // Empty value is not jQuery 24813 if ( !$val ) 24814 return false; 24815 24816 return ($val instanceof jQuery || $val.jquery); 24817} //FUNC isJQ 24818 24819/** //** ----= _jq =----------------------------------------------------------------------------------------------\**//** \ 24820* 24821* Ensures that given parameter is valid jQuery object. Avoids jQuery object clone. 24822* 24823* @param MIXED $element - jQuery selector, DOM element or jQuery object. 24824* @param MIXED [$context] - Valid jQuery context. 24825* 24826* @return object(jQuery) - jQuery object. 24827* 24828\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 24829function _jq ($element, $context) { 24830 24831 if ( !isJQ($element) ) 24832 return jQuery($element, $context); 24833 24834 return $element; 24835} //FUNC _jq 24836 24837function formatFileSize (bytes) { 24838 24839 if ( !bytes ) return bytes; 24840 24841 var labels = ['b','Kb','Mb','Gb','Tb','Pb','Eb','Zb','Yb']; 24842 var ex = Math.floor( Math.log(bytes) / Math.log(1024) ); 24843 24844 var res = bytes / Math.pow(1024, ex); 24845 24846 return res.toFixed(2) + ' ' + labels[ex]; 24847} //FUNC formatFileSize 24848 24849/** //** ----= setObjectOptions =--------------------------------------------------------------------------------------\**//** \ 24850* 24851* Initiates object properties from given data object. Sets properties directly, without test if property really existed. 24852* Essentially copies one object properties into another. 24853* 24854* @param object $object - Object to apply options to. 24855* @param array $options - Options to set. 24856* 24857* @return object - Returns given object. 24858* 24859\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 24860function setObjectOptions ($object, $options) { 24861 24862 $options = $options || {}; 24863 24864 // Looping through each option given and setting it as property 24865 for ( var $opt in $options ) 24866 $object[$opt] = $options[$opt]; 24867 24868 return $object; 24869} //FUNC setObjectOptions 24870 24871/** //** ----= borderValue =--------------------------------------------------------------------------------------\**//** \ 24872* 24873* Ensures that given value is within bounds. 24874* 24875* @param MIXED $element - jQuery selector, DOM element or jQuery object. 24876* @param MIXED [$context] - Valid jQuery context. 24877* 24878* @return object(jQuery) - jQuery object. 24879* 24880\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 24881function borderValue ($value, $min, $max) { 24882 24883 if ( $value < $min ) 24884 $value = $min; 24885 24886 if ( $value > $max ) 24887 $value = $max; 24888 24889 return $value; 24890 24891} //FUNC borderValue 24892 24893/** //** ----= touchToMouse =--------------------------------------------------------------------------------------\**//** \ 24894* 24895* Enables translation of touch events into mouse events. 24896*
24897* @param DOMElement $el - Element to apply to. 24898* 24899* @return SELF 24900* 24901\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 24902jQuery.fn.touchToMouse = function () { 24903 24904 if ( !this.length ) 24905 return; 24906 24907 // Enabling touches for each element in set 24908 this.each( function () { 24909 touchToMouse(this); 24910 }); //each element 24911 24912} //FUNC touchToMouse 24913 24914function touchToMouse ( $el ) { 24915 24916 // Using solution found in internet with slight tweaks and adding explanation of what is going on 24917 // Basically - capturing touch events, creating similar mouse event and rethrowing it instead 24918 24919 // Using event wrapper to simplify code 24920 var $handler = function ( $event ) { 24921 24922 // Using first element (you can't have multitouch with mouse :) ) 24923 var $touchEvent = $event.changedTouches[0]; 24924 24925 // Defining event type from subst table 24926 var $eventType = { 24927 touchstart : 'mousedown', 24928 touchmove : 'mousemove', 24929 touchend : 'mouseup', 24930 }[$event.type]; //$types 24931 24932 // Using only translatable events, otherwise - returning 24933 if ( !$eventType ) 24934 return; 24935 24936 // Creating new mouse event 24937 // And initializing with data from captured touch event 24938 var $mouseEvent = document.createEvent('MouseEvent'); 24939 $mouseEvent.initMouseEvent( 24940 $eventType, true, true, window, 1, 24941 $touchEvent.screenX, $touchEvent.screenY, 24942 $touchEvent.clientX, $touchEvent.clientY, false, 24943 false, false, false, 0, null 24944 ); //initMouseEvent 24945 24946 // Rethrowing it from same target as original touch 24947 $touchEvent.target.dispatchEvent($mouseEvent); 24948 24949 // Clearing bubbling 24950 event.preventDefault(); 24951 24952 } //FUNC hanlder 24953 24954 // Adding custom handler 24955 $el.addEventListener('touchstart', $handler, true); 24956 $el.addEventListener('touchmove', $handler, true); 24957 $el.addEventListener('touchend', $handler, true); 24958 $el.addEventListener('touchcancel', $handler, true); 24959 24960} //FUNC touchToMouse 24961 24962/** //** ----= observeChange =--------------------------------------------------------------------------------------\**//** \ 24963* 24964* Adds MutationObserver to observer changes in input value. Triggers change when value updates. 24965* Good use for hidden and text based inputs, to have proper/imideate change. 24966* 24967* @param DOMElement $el - Element to apply to. 24968* 24969* @return SELF 24970* 24971\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 24972jQuery.fn.observeChange = function () { 24973 24974 if ( !this.length ) 24975 return; 24976 24977 // Enabling touches for each element in set 24978 this.each( function () { 24979 observeChange(this); 24980 }); //each element 24981 24982} //FUNC observeChange 24983 24984function observeChange ( $el ) { 24985 24986 // Using solution found in internet with slight tweaks and adding explanation of what is going on 24987 24988 // Creating MutationObserver (compatable with older webkit), and watching value attribute of element given (supposedly input) 24989 // Once value changed - triggering change with jQuery 24990 24991 // Preparing class, to be compatable with older webkit 24992 // Doing it globally, does not hurt anything 24993 MutationObserver = window.MutationObserver || window.WebKitMutationObserver; 24994 24995 // Saving observer in input, just in case 24996 // Adding callback that will check what's changed 24997 $el.vObserver = new MutationObserver( function ( $mutations, $observer ) { 24998 24999 // Should be only one mutation really 25000 // Interested in value change 25001 if ( $mutations[0].attributeName == 'value') { 25002 25003 // Using mutation target to trigger 25004 // Since it's basically a closure - can reference give element directly 25005 // Wrapping with jQuery if necessary 25006 _jq($el).trigger('change'); 25007 25008 } //IF value changed 25009 25010 }); //FUNC MutationObserver.callback 25011 25012 // Watching element attributes 25013 $el.vObserver.observe($el, { 25014 attributes : true, 25015 }); //observe 25016 25017 // Done here 25018 25019} //FUNC observeChange 25020 25021/** //** ----= vEventObject =--------------------------------------------------------------------------------------\**//** \ 25022* 25023* Extends given object to accept events callbacks. Allows events registering and chain calling later. Callback will 25024* run within object's context and accept parameters given to event trigger. 25025* 25026* @param array types - List of event types to create. 25027* 25028* @param object obj - Object to extend. 25029* 25030* @return object - Modified object. 25031* 25032\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 25033function vEventObject (types, obj) { 25034 25035 obj = obj || {}; 25036 25037 // Creating callbacks storage in parent 25038 if ( isEmpty(obj['__events']) ) 25039 obj['__events'] = {}; 25040 25041// ---- BIND/RUNNER ---- 25042 25043 /** //** ----= _runevent =------------------------------------------------------------------------------\**//** \ 25044 * 25045 * For Internal Use. Event runner, used to call events, or set new ones (in case if callback function given). 25046 * 25047 * @param string type - Event type to use. 25048 * 25049 * @return MIXED - Mixed return. 25050 * SELF - If setting event. 25051 * bool - Boolean FALSE in even return - interrupts chain, and also is returned. 25052 * TRUE is just returned. 25053 * VOID - Other cases. 25054 * 25055 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 25056 obj._runevent = function ( type, args ) { 25057 25058 // Setting callback if given as first argument 25059 if ( args[0] && typeof(args[0]) == 'function' ) { 25060 this.__events[type].push(args[0]); 25061 return obj; 25062 } //IF callback set 25063 25064 var res = false;
25065 25066 // If no callback given (getter mode) - running all calbacks of that type, cb should contain arguments then 25067 for ( var func in this.__events[type] ) { 25068 var eres = this.__events[type][func].apply(obj, args); 25069 25070 // False in result means even chain interruption, returning it to parent also 25071 if ( eres === false ) 25072 return false; 25073 25074 // True in one of events means smth for caller, we'll return it later 25075 if ( eres === true ) 25076 res = true; 25077 25078 } //FOR each callback 25079 25080 // If someone return true - we notify parent about, else - undefined return 25081 if ( res ) 25082 return res; 25083 25084 } //FUNC _runevent 25085 25086// ---- UNBIND ---- 25087 25088 /** //** ----= unbind =--------------------------------------------------------------------------------------\**//** \ 25089 * 25090 * Event remover. Unbings given event type, or given callback if specified. If no parameters specified - 25091 * unbinding all events (usefull to get clean object). 25092 * 25093 * @param string [type] - Event type to unbind. 25094 * @param function [fn] - Callback to unbind within type. 25095 * 25096 * @return SELF 25097 * 25098 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 25099 obj.unbind = function (type, fn) { 25100 25101 var $this = this; 25102 25103 // Event clearing helper 25104 function unbindEvent (e) { 25105 25106 // Deleting only speciefic events, skipping body ones 25107 for ( var i = 0; i < e.length; i++ ) { 25108 25109 // Skipping body ones 25110 if ( e[i]._bodyeventfunction ) continue; 25111 25112 // Skipping all non given (if some given) 25113 if ( fn && e[i] !== fn ) continue; 25114 25115 e.splice(i, 1); 25116 25117 } //FOR each callback 25118 25119 }; //FUNC unbindEvent 25120 25121 // If type specified - cleaning only that type, otherwise - all of them 25122 if ( type ) 25123 unbindEvent(this.__events[type]); 25124 else 25125 for ( var i in this.__events ) 25126 unbindEvent(this.__events[i]); 25127 25128 return obj; 25129 25130 }; //FUNC obj.unbind 25131 25132// ---- SHORTCUTS ---- 25133 25134 // Creating shortcut for each event 25135 for ( var ev in types ) { 25136 25137 var type = types[ev]; 25138 25139 // For each type we have own array with callbacks 25140 if ( isEmpty(obj.__events[type]) ) 25141 obj.__events[type] = []; 25142 25143 // Existing event functions became first events 25144 if ( isFunction(obj[type]) ) { 25145 25146 // Skipping event functions 25147 if ( obj[type]._runeventfunction ) 25148 continue; 25149 else { 25150 // Marking as body function - those can't be unbind 25151 obj[type]._bodyeventfunction = 1; 25152 obj._runevent(type, [obj[type]]); 25153 } //IF own function 25154 25155 } //IF function already exists in body 25156 25157 // Creating event trigger function in parent for each type 25158 obj[type] = function (t) { return function () { return this._runevent(t, arguments);};}(type); 25159 25160 // Marking as event function to recognise later 25161 obj[type]._runeventfunction = 1; 25162 25163 } //FOR each type 25164 25165 return obj; 25166} //FUNC vEventObject 25167 25168/** //** ----= PromiseEx =--------------------------------------------------------------------------------------\**//** \ 25169* 25170* Special promise version with outside controllers (custom resolve/reject methods). 25171* 25172* @param function $executor - Promise executor. 25173* 25174* @return object - Modified promise. 25175* 25176\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 25177var PromiseEx = function ( $executor ) { 25178 25179 // Saving controls outisde 25180 var $resolve, $reject; 25181 25182 var $res = new Promise ( function (resolve, reject) { 25183 25184 // Saving resolve and reject for later reuse 25185 $resolve = resolve; 25186 $reject = reject; 25187 25188 // Running executor as normal, it might resolve/reject as necessary 25189 if ( isFunction($executor) ) 25190 $executor(resolve, reject); 25191 25192 // Done here 25193 25194 }); //Promise 25195 25196 // Saving calls in object itself 25197 $res.doResolve = $resolve; 25198 $res.doReject = $reject; 25199 25200 return $res; 25201 25202} //promiseEx 25203 25204/** //** ----= reloadCSS =--------------------------------------\**//** \ 25205* 25206* Forces browser to reload CSS sheets dynamically. 25207* 25208* @param string url - CSS sheet URL. 25209* 25210\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 25211function reloadCSS (url) { 25212 25213 var salt = randomString(); 25214 var salt_url = url + '?reload=' + salt; 25215 25216 var new_sheet = jQuery('<link rel="stylesheet" href="' + salt_url + '" type="text/css" />'); 25217 var old_sheet = jQuery('LINK[href*="' + url + '"]'); 25218 25219 if ( document.createStyleSheet ) { 25220 document.createStyleSheet(salt_url); 25221 } else { //IF IE 25222 jQuery('HEAD').append( new_sheet ); 25223 } //IF normal browsers 25224 25225 // Removing old sheet if present. 25226 setTimeout( function () { old_sheet.remove(); }, 1000); 25227 25228} //FUNC reloadCSS 25229 25230/** //** ----= countElements =----------------------------------------------\**//** \ 25231* 25232* Returns overal page's elements count. Usefull for optimization. 25233* 25234* @param jQuery el - Count elements within give element. 25235* 25236* @return int - Elements count. 25237* 25238\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 25239function countElements (el) { 25240 25241 if ( !el ) 25242 return document.getElementsByTagName('*').length; 25243 25244 return jQuery(el).find('*').length; 25245} //FUNC countElements 25246 25247function randomString(type, length) { 25248 25249 if ( !type ) type = 'alnum'; 25250 if ( !length ) length = 8; 25251 25252 var chars = ''; 25253 25254 switch ( type.toLowerCase() ) { 25255 case 'alnum' : chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; 25256 break; 25257 case 'alpha' : chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; 25258 break; 25259 case 'hex' : chars = '0123456789ABCDEF'; 25260 break; 25261 case 'caps' : chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; 25262 break; 25263 case 'capnum' : chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; 25264 break; 25265 case 'numeric' : chars = '0123456789'; 25266 break; 25267 case 'nozero' : chars = '123456789'; 25268 break; 25269 case 'keyb' : chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ :;,.\'"\|/?[]{}()<>~`!@#$%^&*-=_+'; 25270 break; 25271 25272 default : chars = type; 25273 } //SWITCH $type 25274 25275 if ( !chars ) return ''; 25276 25277 var str = ''; 25278 25279 for (var i = 0; i < length; i++) { 25280 var rnum = Math.floor(Math.random() * chars.length); 25281 str += chars.substring(rnum, rnum + 1); 25282 } 25283 25284 return str; 25285} //FUNC randomString 25286 25287/** //** ----= newSN =---------------------------------------------------------------------------------------------\**//** \ 25288* 25289* Generates new random SN. SN is usually capnum unique string of 16 chars, starting from give char. 25290* 25291* @param string [$prefix] - Limit SN to start only with this char. 25292* @param string [$length] - SN length, 16 by default. 25293*
25294* @return string - Random SN string. 25295* 25296\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 25297function newSN ($prefix, $length) { 25298 25299 $prefix = $prefix || ''; 25300 $length = $length || 16; 25301 25302 return ($prefix + randomString('capnum', $length)).substring(0, $length); 25303} //FUNC newSN 25304 25305/** //** ----= fileName =----------------------------------------------\**//** \ 25306* 25307* Extracts file name from full path. 25308* 25309* @param string path - Full path and file name. 25310* @return string - File name. 25311* 25312\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 25313function fileName (path) { 25314 if ( !path ) return ''; 25315 return path.replace(/^.*\\/, ''); 25316} //FUNC fileName 25317 25318/** //** ----= fileExt =----------------------------------------------\**//** \ 25319* 25320* Extracts file extension from file name. 25321* 25322* @param string file - Full path and file name. 25323* @return string - File name. 25324* 25325\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 25326function fileExt (file) { 25327 var tmp = file.lastIndexOf('.'); 25328 25329 if ( !tmp ) return false; 25330 25331 return file.substr(tmp+1, file.length); 25332 25333} //FUNC fileExt 25334 25335/** //** ----= fileType =---------------------------------------------------------------------------------------------\**//** \ 25336* 25337* Detects one of general file types: image, doc, video, music etc. 25338* 25339* @param string $file - File name to test. 25340* 25341* @return string - File type. 25342* 25343\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 25344function fileType ( $file ) { 25345 25346 // Listing known file types by extensions 25347 // Simplified version. Complete version should be generated by php from mimes. To be implemented. 25348 var $types = { 25349 25350 // ToDo: add executables 25351 25352 'php' : 'script', 25353 'php4' : 'script', 25354 'php5' : 'script', 25355 'js' : 'script', 25356 'css' : 'script', 25357 'html' : 'script', 25358 'htm' : 'script', 25359 'html5' : 'script', 25360 'html4' : 'script', 25361 'cgi' : 'script', 25362 25363 'jpeg' : 'image', 25364 'jpg' : 'image', 25365 'jpe' : 'image', 25366 'png' : 'image', 25367 'bmp' : 'image', 25368 'gif' : 'image', 25369 'webp' : 'image', 25370 'svg' : 'image', 25371 'tiff' : 'image', 25372 'tif' : 'image', 25373 25374 'avi' : 'video', 25375 'flv' : 'video', 25376 'f4v' : 'video', 25377 'mpeg' : 'video', 25378 'mpg' : 'video', 25379 'mpe' : 'video', 25380 'mov' : 'video', 25381 'mp4' : 'video', 25382 'm4v' : 'video', 25383 'wmv' : 'video', 25384 'ogv' : 'video', 25385 'webm' : 'video', 25386 'mkv' : 'video', 25387 'qt' : 'video', 25388 'movie' : 'video', 25389 25390 'mp2' : 'audio', 25391 'mp3' : 'audio', 25392 'wav' : 'audio', 25393 'wma' : 'audio', 25394 25395 'doc' : 'doc', 25396 'docx' : 'doc', 25397 'txt' : 'doc', 25398 'text' : 'doc', 25399 'xls' : 'doc', 25400 'xlsx' : 'doc', 25401 'pdf' : 'doc', 25402 25403 }; //$ex 25404 25405 // Getting file extension, need it in lowercase 25406 var $ext = fileExt($file) || ''; 25407 $ext = $ext.toLowerCase(); 25408 25409 // Checking it it's known 25410 if ( $types[$ext] ) 25411 return $types[$ext]; 25412 25413 // Nothing to return if unknown 25414 return ''; 25415 25416} //FUNC fileType 25417 25418function isFileScript ( $file ) { 25419 return fileType($file) === 'script'; 25420} //FUNC isFileScript 25421function isFileImage ( $file ) { 25422 return fileType($file) === 'image'; 25423} //FUNC isFileImage 25424function isFileVideo ( $file ) { 25425 return fileType($file) === 'video'; 25426} //FUNC isFileVideo 25427function isFileAudio ( $file ) { 25428 return fileType($file) === 'audio'; 25429} //FUNC isFileAudio 25430function isFileDoc ( $file ) { 25431 return fileType($file) === 'doc'; 25432} //FUNC isFileDoc 25433 25434 25435/*--------------------------------------------------------------------------------*\ 25436| Humanize 25437|---------------------------------------------------------------------------------- 25438| Ensures that number will be displayed as normal value (fix for JavaScript numbers) 25439| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 25440| Params: 25441| [base] int - Base value to round value to. 25442| Return: 25443| string - Human looking number rounded to certain base. 25444\*--------------------------------------------------------------= by Mr.V!T =-----*/ 25445Number.prototype.Humanize = Number.prototype.humanize = function (base) { 25446 25447 base = base || 10; 25448 25449 var tmp = this.toFixed(base) + ''; 25450 return tmp; 25451 25452 var res = tmp.rtrim('0.'); 25453 if ( res == '' ) res = '0'; 25454 25455 return res; 25456} //FUNC Humanize 25457 25458/*--------------------------------------------------------------------------------*\ 25459| indexOf 25460|---------------------------------------------------------------------------------- 25461| Fixes indexOf for IE6. 25462| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
25463| Params: 25464| obj MIXED - Item to search. 25465| fromIndex integer - Search starting from index. 25466| Return: 25467| integer - Item position in array, or -1 if not found. 25468\*--------------------------------------------------------------= by Mr.V!T =-----*/ 25469/**/ 25470if ( !Array.prototype.indexOf ) 25471Array.prototype.indexOf = function (obj, fromIndex) { 25472 25473 if ( !fromIndex ) fromIndex = 0; 25474 25475 for ( var i in this ) 25476 if ( this[i] === obj ) return i; 25477 25478 return -1; 25479} //FUNC indexOf 25480/**/ 25481 25482/*--------------------------------------------------------------------------------*\ 25483| arrayJoin 25484|---------------------------------------------------------------------------------- 25485| Extended join for arrays. 25486| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 25487| Params: 25488| array array - Array to process. 25489| separator string - String to use as separator. 25490| include_keys bool - Set TRUE to encode keys in result string. 25491| Return: 25492| string - Array as string. 25493\*--------------------------------------------------------------= by Mr.V!T =-----*/ 25494function arrayJoin (array, separator, include_keys) { 25495 25496 if ( !separator ) separator = ','; 25497 25498 var res = ''; 25499 25500 var j = 0; 25501 25502 for ( var i in array ) { 25503 25504 if ( typeof(array[i]) == 'function' ) continue; 25505 25506 if ( res ) res += separator; 25507 25508 if ( include_keys ) { 25509 25510 if ( i != j ) 25511 res += i + ' = '; 25512 25513 } //IF need to include keys 25514 25515 res += array[i]; 25516 j++; 25517 25518 } //FOR each item 25519 25520 return res; 25521} //FUNC arrayJoin 25522 25523/*--------------------------------------------------------------------------------*\ 25524| arraySplit 25525|---------------------------------------------------------------------------------- 25526| Splits array. Extended version with keys support. 25527| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 25528| Params: 25529| string string - String to process. 25530| separator string - String to use as separator. 25531| auto_tirm string - Allow to trim values on split. 25532| Return: 25533| array - Array with values. 25534\*--------------------------------------------------------------= by Mr.V!T =-----*/ 25535function arraySplit (string, separator, auto_tirm) { 25536 25537 var res = []; 25538 var tmp = string.split(separator); 25539 25540 for ( var i in tmp ) { 25541 25542 var pos = tmp[i].indexOf('='); 25543 25544 if ( pos != -1 ) { 25545 25546 var key = tmp[i].substr(0, pos); 25547 if ( auto_tirm ) key = key.trim(); 25548 25549 var val = tmp[i].substr(pos+1); 25550 if ( auto_tirm ) val = val.trim(); 25551 25552 res[key] = val; 25553 25554 } else { //IF eq symbol found 25555 25556 if ( auto_tirm ) tmp[i] = tmp[i].trim(); 25557 res.push(tmp[i]); 25558 25559 } //IF single value 25560 25561 } //FOR each value 25562 25563 return res; 25564} //FUNC arraySplit 25565 25566String.prototype.limit = function(l, append) { 25567 25568 if ( this.length <= l ) 25569 return this.toString(); 25570 25571 append = append || '…'; 25572 al = append.substr(0, 1) == '&' ? 1 : append.length; 25573 25574 return this.substr(0, l - al) + append; 25575} //FUNC limit 25576 25577String.prototype.ucfirst = function() { 25578 25579 // Nothing to do with empty string 25580 if ( !this.length ) return this; 25581 25582 return this.charAt(0).toUpperCase() + this.substr(1); 25583} //FUNC ucfirst 25584 25585/*--------------------------------------------------------------------------------*\ 25586| escape 25587|---------------------------------------------------------------------------------- 25588| Escapes string for using in REGex. 25589| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 25590| Params: 25591| NONE 25592| Return: 25593| NULL 25594\*--------------------------------------------------------------= by Mr.V!T =-----*/ 25595String.prototype.escape = function() { 25596 return this.replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!<>\|\:])/g, '\\$1'); 25597} //FUNC escape 25598 25599/*--------------------------------------------------------------------------------*\ 25600| _trim 25601|---------------------------------------------------------------------------------- 25602| Base function for trimming strings. 25603| ***TNX*** Ideas taken from phpjs.org 25604| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 25605| Params: 25606| [charlist] string - Optional characteres to trim. 25607| [left] bool - Trim left. 25608| [right] bool - Trim right. 25609| Return: 25610| string - Trimmed string. 25611\*--------------------------------------------------------------= by Mr.V!T =-----*/
25612String.prototype._trim = function(charlist, left, right) { 25613 25614 var str = this; 25615 25616 if ( !str ) 25617 return this; 25618 25619 charlist = (charlist) ? charlist.escape() : ' \\n\\t\\s\u00A0'; 25620 25621 if ( left ) str = str.replace(new RegExp('^[' + charlist + ']+', 'gm'), ''); 25622 if ( right ) str = str.replace(new RegExp('[' + charlist + ']+$', 'gm'), ''); 25623 25624 return str; 25625} //FUNC _trim 25626 25627/*--------------------------------------------------------------------------------*\ 25628| ltrim 25629|---------------------------------------------------------------------------------- 25630| Strips whitespace from the beginning of a string. 25631| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 25632| Params: 25633| [charlist] string - Optional characteres to trim. 25634| Return: 25635| string - Trimmed string. 25636\*--------------------------------------------------------------= by Mr.V!T =-----*/ 25637String.prototype.ltrim = function(charlist) { 25638 return this._trim(charlist, 1, 0); 25639} //FUNC ltrim 25640 25641/*--------------------------------------------------------------------------------*\ 25642| rtrim 25643|---------------------------------------------------------------------------------- 25644| Removes trailing whitespace. 25645| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 25646| Params: 25647| [charlist] string - Optional characteres to trim. 25648| Return: 25649| string - Trimmed string. 25650\*--------------------------------------------------------------= by Mr.V!T =-----*/ 25651String.prototype.rtrim = function(charlist) { 25652 return this._trim(charlist, 0, 1); 25653} //FUNC rtrim 25654 25655/*--------------------------------------------------------------------------------*\ 25656| trim 25657|----------------------------------------------------------------------------------
25658| Removes whitespaces from both sides. 25659| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 25660| Params: 25661| [charlist] string - Optional characteres to trim. 25662| Return: 25663| string - Trimmed string. 25664\*--------------------------------------------------------------= by Mr.V!T =-----*/ 25665String.prototype.trim = function(charlist) { 25666 return this._trim(charlist, 1, 1); 25667} //FUNC trim 25668 25669/*--------------------------------------------------------------------------------*\ 25670| xtrim 25671|---------------------------------------------------------------------------------- 25672| Very fast function for trimming strings. 25673| ***TNX*** Big thanx for Steve at steves_list (at) hotmail.com. 25674| ***TNX*** http://blog.stevenlevithan.com/ 25675| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 25676| Params: 25677| NONE 25678| Return: 25679| NULL 25680\*--------------------------------------------------------------= by Mr.V!T =-----*/ 25681String.prototype.xtrim = function() { 25682 var str = this; 25683 str = str.replace(/^\s+/, ''); 25684 for (var i = str.length - 1; i >= 0; i--) { 25685 if (/\S/.test(str.charAt(i))) { 25686 str = str.substring(0, i + 1); 25687 break; 25688 } 25689 } 25690 return str; 25691} //FUNC xtrim 25692 25693/*--------------------------------------------------------------------------------*\ 25694| multiClean 25695|---------------------------------------------------------------------------------- 25696| Cleans double repeated characters. E.g. doublespaces. 25697| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 25698| Params: 25699| [character] string - Optional character to clean. 25700| Return: 25701| string - Result string. 25702\*--------------------------------------------------------------= by Mr.V!T =-----*/ 25703String.prototype.multiClean = function(character) { 25704 25705 character = character || ' '; 25706 25707 return this.replace(new RegExp('[' + character.escape() + ']{2,}', 'g'), character); 25708} //FUNC multiClean 25709 25710/*--------------------------------------------------------------------------------*\ 25711| toSafe 25712|---------------------------------------------------------------------------------- 25713| Generates safe value from give string. I.E. safe to use as variable names. 25714| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 25715| Params: 25716| [separator] string - Optional characteres to use as word 25717| separator. 25718| Return: 25719| string - Result string. 25720\*--------------------------------------------------------------= by Mr.V!T =-----*/ 25721String.prototype.toSafe = function(separator) { 25722 25723 if ( !separator ) 25724 separator = '_'; 25725 25726 var res = this; 25727 res = res.replace(/[^a-zA-Z0-9_]/g, separator); 25728 res = res.multiClean(separator); 25729 res = res.trim(separator); 25730 25731 return res; 25732} //FUNC toSafe 25733 25734/*--------------------------------------------------------------------------------*\ 25735| compilePath 25736|---------------------------------------------------------------------------------- 25737| Compile path from several pieces using '/' as glue. 25738| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 25739| Params: 25740| * string - One or several path pieces. 25741| Return: 25742| string - Valid path. 25743\*--------------------------------------------------------------= by Mr.V!T =-----*/ 25744function compilePath () { 25745 25746 var len = arguments.length; 25747 if ( len == 1 ) return arguments[0]; 25748 25749 var res = (arguments[0]+'').rtrim('/'); 25750 25751 for (var i = 1; i < len; i++ ) { 25752 res += '/' + (arguments[i]+'').ltrim('/'); 25753 } //FOR each argument 25754 25755 return res; 25756} //FUNC compilePath 25757var compileUrl = compilePath; 25758 25759/** //** ----= arraySelectKey =----------------------------------------------\**//** \ 25760* 25761* Chooses existing key from list given in associated array. 25762* 25763* @param array array - Source array. 25764* 25765* @param MIXED keys 25766* array - Array with possible keys. 25767* string - Single key for case insensitive search or regEx 25768* mask for possible keys (slower). 25769* 25770* @param bool [regex] - Search mode for string key. 25771* 25772* @return MIXED 25773* string - Existing key. 25774* bool - FALSE if none exists. 25775* 25776\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 25777function arraySelectKey (array, keys, regex) { 25778 25779 if ( typeof(keys) == 'object' ) { 25780 25781 for ( var i = 0; i < keys.length; i++ ) { 25782 25783 if ( array[keys[i]] != undefined ) return keys[i]; 25784 25785 } //FOR each key 25786 25787 } else { //IF searching by array 25788 25789 var reg = keys; 25790 if ( !regex ) 25791 reg = new RegExp('^' + keys.escape() + '$', 'i'); 25792 25793 for ( var key in array ) { 25794 25795 // __(key); 25796 25797 if ( reg.test(key) ) return key; 25798 } //FOR each 25799 25800 } //IF searshing by regex 25801 25802 return undefined; 25803} //FUNC arraySelectKey 25804 25805/** //** ----= arraySelectValue =----------------------------------------------\**//** \ 25806*
25807* Chooses value by one of existing keys given. 25808* 25809* @param array array - Source array. 25810* @param array keys - Array with possible keys. 25811* @param MIXED [default] - Default value to use if nothing found. 25812* 25813* @return MIXED - Found value or default if none found. 25814* 25815\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 25816function arraySelectValue (array, keys, def) { 25817 25818 var key = arraySelectKey(array, keys); 25819 25820 if ( !key || !array[key] == undefined ) return def; 25821 25822 return array[key]; 25823} //FUNC arraySelectValue 25824 25825/*--------------------------------------------------------------------------------*\ 25826| arrayToPost 25827|---------------------------------------------------------------------------------- 25828| Prepares multidimentional array to post in native PHP format. 25829| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 25830| Params: 25831| array object - Common JavaScript array object. 25832| Return: 25833| array - Array in POST format. 25834\*--------------------------------------------------------------= by Mr.V!T =-----*/ 25835function arrayToPost (array, prefix) { 25836 25837 var res = {}; 25838 25839 for ( i in array ) { 25840 25841 var key = ( prefix )? prefix + '[' + i + ']' : i; 25842 25843 if ( typeof(array[i]) == 'object' ) { 25844 25845 var sub = arrayToPost(array[i], key); 25846 25847 for ( j in sub ) res[j] = sub[j]; 25848 25849 } else { //IF sub array 25850 res[key] = array[i]; 25851 } //IF other type 25852 25853 } //FOR each array 25854 25855 return res; 25856} //FUNC arrayToPost 25857 25858/** //** ----= submitUrl =--------------------------------------------------------------------------------------\**//** \ 25859* 25860* Submits given data as POST/GET to given url. Literally simulates form submit. 25861* 25862* @param string $url - Url to submit to. 25863* @param object $data - Data to submit. 25864* @param string [$blank] - Set TRUE to open in new tab. 25865* 25866* @return bool - Always FALSE. 25867* 25868\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 25869function submitUrl($url, $data, $blank) { 25870 25871 $method = 'post'; // No real need to have method optional 25872 $data = $data || {}; 25873 $target = ''; 25874 25875 if ( $blank ) 25876 $target = ' target="_blank"'; 25877 25878 // Generating form html as string and appending it to body 25879 // Each data will be hidden input in form 25880 var $f = '<form method="' + $method + '" action="' + $url + '"' + $target + ' style="display:none">'; 25881 25882 for ( $i in $data ) { 25883 25884 $f += '<input type="hidden" name="' + $i + '" value="' + $data[$i] + '" />'; 25885 25886 } //FOR each data 25887 25888 $f += '</form>'; 25889 25890 // Appending form, getting it's element, and submiting 25891 var $el = jQuery($f).appendTo('BODY').submit(); 25892 25893 return false; 25894 25895} //FUNC submitUrl 25896 25897/** //** ----= parseVariables =--------------------------------------------------------------------------------------\**//** \ 25898* 25899* Parses {varables} in a template. Supporting complex vairables like {var-sub} and {var.sub} 25900* 25901* @param string $str - Template to parse. 25902* @param object $vars - Data object with variable to parse. 25903* @param bool [$clean] - Set TRUE to cleanup unused variables from template (default behavior). 25904* @param string [$wrap] - Brackets pair to use on vairables. '{}' by default. Use '[]' for bb codes. 25905* 25906* @return string - Parsed template. 25907* 25908\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 25909function parseVariables ($str, $vars, $clean, $wrap) { 25910 25911 // Using {vars} by default 25912 $wrap = $wrap || '{}'; 25913 25914 // Nothing to do if string is empty 25915 if ( !$str ) 25916 return $str; 25917 25918 if ( isUndefined($clean) ) 25919 $clean = true; 25920 25921 // Preparing wrap pairs 25922 // Assuming 2 char pair like '{}' or '[]' 25923 if ( $wrap.length != 2 ) 25924 throw('Invalid var wrapper'); 25925 25926 // Preparing 2 wrap variants: normal and escaped one 25927 // Oftenly strings end up as url escaped strings, escaped by parsers 25928 // Thus just searching this too 25929 var $l = $wrap.charAt(0); 25930 var $r = $wrap.charAt(1); 25931 var $xl = '%' + $wrap.charCodeAt(0).toString(16).toUpperCase(); 25932 var $xr = '%' + $wrap.charCodeAt(1).toString(16).toUpperCase(); 25933 25934 // Looping though all vars and replacing given variables 25935 for ( var $i in $vars ) { 25936 25937 // Preparing value separately, in case need to modify something about it 25938 var $value = $vars[$i]; 25939 25940 // Can display simple arrays as lists 25941 if ( isArray($value) ) 25942 $value = $value.join(','); 25943 25944 // Skipping anything that can't be placed on template 25945 if ( !isStr($value) && !isNumber($value) ) 25946 continue; 25947 25948 // Searching both vars variants 25949 $str = $str.replace( new RegExp( ($l + $i + $r).escape(), 'ig'), $value); 25950 $str = $str.replace( new RegExp( ($xl + $i + $xr).escape(), 'ig'), $value); 25951 25952 } //FOR each var 25953 25954 if ( $clean ) { 25955 25956 // Now cleaning unused, both normal and escaped 25957 $str = $str.replace( new RegExp( $l.escape() + '[\\w\\.-]+' + $r.escape(), 'ig'), ''); 25958 $str = $str.replace( new RegExp( $xl.escape() + '[\\w\\.-]+' + $xr.escape(), 'ig'), ''); 25959 25960 } //IF autoClean 25961 25962 return $str; 25963 25964} //FUNC parseVariables 25965 25966/** //** ----= arrayToTemplate =--------------------------------------------------------------------------------------\**//** \ 25967* 25968* Parses {varables} in a template. PHP counterpart alias to parseVariables. 25969* 25970* @param object $vars - Data object with variable to parse. 25971* @param string $str - Template to parse.
25972* @param bool [$clean] - Set TRUE to cleanup unused variables from template (default behavior). 25973* @param string [$wrap] - Brackets pair to use on vairables. '{}' by default. Use '[]' for bb codes. 25974* 25975* @return string - Parsed template. 25976* 25977\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 25978function arrayToTemplate ($vars, $str, $clean, $wrap) { return parseVariables($str, $vars, $clean, $wrap); } 25979 25980/*--------------------------------------------------------------------------------*\ 25981| isNumeric 25982|---------------------------------------------------------------------------------- 25983| Simple function for checking if given string numnber. 25984| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 25985| Params: 25986| value string - Value to check. 25987| Return: 25988| bool - Check status. 25989\*--------------------------------------------------------------= by Mr.V!T =-----*/ 25990function isNumeric (value) { 25991 25992 // Numerics are numeric o_O 25993 if ( typeof(value) == 'number' ) 25994 return true; 25995 25996 return (value - 0) == value && value.length > 0; 25997} //FUNC isNumeric 25998 25999/*--------------------------------------------------------------------------------*\ 26000| isEmail 26001|---------------------------------------------------------------------------------- 26002| Simple function for checking if given string is correct mail. 26003| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 26004| Params: 26005| value string - Value to check. 26006| Return: 26007| bool - Check status. 26008\*--------------------------------------------------------------= by Mr.V!T =-----*/ 26009function isEmail (value) { 26010 var filter = /^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9_\-]+\.)+[a-z]{2,6}$/i; 26011 return filter.test(value); 26012} //FUNC isEmail 26013 26014jQuery.fn.findExclude = function($selector, $exclude, $res){ 26015 26016 $res = $res || new jQuery(); 26017 26018 // Looping through children, saving matching ones, 26019 // and recursively traversing deeper in each 26020 // Skipping ones that match exclusions ofc 26021 this.children().each( function() { 26022 26023 var $el = jQuery(this); 26024 26025 // Checking self to be saved in result 26026 if ( $el.is($selector) ) 26027 $res.push(this); 26028 26029 // Traversing deeper if allowed 26030 if( !$el.is($exclude) ) 26031 $el.findExclude($selector, $exclude, $res); 26032 }); //jQuery each children 26033 26034 return $res; 26035} //FUNC findExclude 26036 26037/** //** ----= jQuery.align =-----------------------------------------\**//** \ 26038* 26039* Aligns selected element with another element or browser window. 26040* 26041* @param string align - Align type. 26042* @param object target - Element to align with. 26043* @param bool fit - Set TRUE to fit inside element (forced if no target) 26044* 26045* @return jQuery - Aligned element. 26046* 26047\*--------------------------------------------------------------= by Mr.V!T =-----*/ 26048jQuery.fn.align = function (align, target, fit, fixed) { 26049 26050// ---- Preparing environment 26051 26052 // Default align is center 26053 if ( align == 'center' ) align = false; 26054 align = align || 'center-center'; 26055 26056 align = align.split('-'); 26057 26058 if ( fit === undefined ) fit = false; 26059 26060 if ( !target ) fit = true; 26061 26062 // If no target - we will use screen dimensions 26063 if ( !target ) 26064 var screen = screenSize(); 26065 26066 // Target element dimensions 26067 var tDim = { 26068 width : ( target )? target.outerWidth() : screen.width, 26069 height : ( target )? target.outerHeight() : screen.height 26070 }; //OBJECT elDim 26071 26072// ---- Little complicated logic goes next, no comments there - hard to explain :) 26073 26074 var bases = { 26075 'left' : 0, 26076 'top' : 0, 26077 'center' : 0.5, 26078 'right' : 1, 26079 'bottom' : 1 26080 } //OBJ bases 26081 26082 var ly = false; 26083 26084 if ( align[0] == 'center' ) 26085 align = align.reverse(); 26086 26087 if ( ['left', 'right'].indexOf(align[1]) !== -1 ) { 26088 ly = true; 26089 align = align.reverse(); 26090 } //IF 26091 26092 if ( ['top', 'bottom'].indexOf(align[0]) !== -1 ) { 26093 ly = true; 26094 align = align.reverse(); 26095 } //IF 26096 26097 // Sub function to process aligment separately for each dimension 26098 // Using sub func to avoid copy/paste 26099 function _alignDim (t, l, s, e) { 26100 26101 if ( fit ) l = false; 26102 26103 var d = ds = bases[t]; 26104 26105 if ( l && ds != 0.5 ) 26106 ds = ( ds )? 0 : 1; 26107 26108 return e * d - s * ds; 26109 26110 } //FUNC _alignDim 26111
26112// ---- Result CSS ---- 26113 26114 // preCompiling css 26115 var css = { 26116 'left' : _alignDim( align[0], !ly, this.outerWidth(true), tDim.width ), 26117 'top' : _alignDim( align[1], ly, this.outerHeight(true), tDim.height ) 26118 } //OBJECT css 26119 26120 // Correcting position, relating to target 26121 if ( target ) { 26122 var pos = (fixed) ? target.offset() : target.position(); 26123 26124 css.left += pos.left; 26125 css.top += pos.top; 26126 } //IF target set 26127 26128 this.css(css); 26129 26130 return this; 26131} //FUNC align 26132 26133/*--------------------------------------------------------------------------------*\ 26134| centerWindow 26135|---------------------------------------------------------------------------------- 26136| Adds function to jQuery for centering windows 26137| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 26138| Params: 26139| NONE 26140| Return: 26141| SELF 26142\*--------------------------------------------------------------= by Mr.V!T =-----*/ 26143jQuery.fn.centerWindow = function () { 26144 26145 var wnd_width = this.width(); 26146 var wnd_height = this.height(); 26147 26148 var screen = screenSize(); 26149 26150 var wnd_left = ( screen.width - wnd_width ) / 2; 26151 var wnd_top = ( screen.height - wnd_height ) / 2; 26152 26153 var css = {'top' : wnd_top, 'left' : wnd_left}; 26154 26155 this.css(css); 26156 26157 return this; 26158} //FUNC centerWindow 26159 26160jQuery.fn.maxWidth = function ($outer, $margins) { 26161 var $max = 0; 26162 this.each( function() { 26163 $max = Math.max($max, $outer ? jQuery(this).outerWidth($margins) : jQuery(this).width() ); 26164 }); //FUNC each in result 26165 return $max; 26166} //FUNC maxWidth 26167 26168jQuery.fn.maxHeight = function ($outer, $margins) { 26169 var $max = 0; 26170 this.each( function() { 26171 $max = Math.max($max, $outer ? jQuery(this).outerHeight($margins) : jQuery(this).height() ); 26172 }); //FUNC each in result 26173 return $max; 26174} //FUNC maxHeight 26175 26176jQuery.fn.screenOffset = function () { 26177 26178 var $pos = this.offset(); 26179 26180// var $top = jQuery('html, body').scrollTop(); 26181 var $top = jQuery(window).scrollTop(); 26182 26183 $pos.top -= $top; 26184 26185 return $pos; 26186} //FUNC screenOffset 26187 26188jQuery.fn.wrapAround = function ($target) { 26189 26190 // Wrapping assumes border and padding to be same around, so checking only top ones 26191 var $border = parseInt( this.css('border-top-width') ); 26192 var $padding = parseInt( this.css('padding-top') ); 26193 26194 // Supporting direct coordinates input as 4 items array: [left, top, width, height] 26195 if ( isArray($target) ) { 26196 26197 // In array mode coords are given directly 26198 var $css = { 26199 'left' : $target[0] - $border - $padding, 26200 'top' : $target[1] - $border - $padding, 26201 'width' : $target[2], 26202 'height': $target[3] 26203 }; //OBJECT $css 26204 26205 } else { //If dimensions given 26206 26207 if ( !$target.length ) 26208 return this; 26209 26210 // Initial values, huge top/left and small width/height 26211 var $x = 10000; 26212 var $y = 10000; 26213 26214 var $toX = 0; 26215 var $toY = 0; 26216 26217 // Looking through all elmements and searching for ourter max dimensions 26218 $target.each( function () { 26219 26220 var $el = jQuery(this); 26221 26222 // Not counting invisible elements 26223 if ( !$el.is(':visible') ) 26224 return; 26225 26226 // Getting offset and calculating tox/toy for element 26227 // Then comparing this to found ones already 26228 var $o = $el.screenOffset(); 26229 26230 var $tx = $o.left + $el.outerWidth(); 26231 var $ty = $o.top + $el.outerHeight(); 26232 26233 if ( $o.left < $x ) $x = $o.left; 26234 if ( $o.top < $y ) $y = $o.top; 26235 if ( $toX < $tx ) $toX = $tx; 26236 if ( $toY < $ty ) $toY = $ty; 26237 26238 }); //FUNC jQuery.each 26239 26240 // Now we can build helper box 26241 var $css = { 26242 'left' : $x - $border - $padding, 26243 'top' : $y - $border - $padding, 26244 'width' : $toX - $x, 26245 'height': $toY - $y 26246 }; //OBJECT $css 26247 26248 } //IF jQuery 26249 26250 // And apply it to self 26251 this.css($css); 26252 26253 // Continuing chain 26254 return this; 26255} //FUNC wrapAround 26256 26257jQuery.fn.hoverClass = function ($class, $allSet) { 26258 26259 var $this = this; 26260 26261 // Binding with namespaces, using class as namespace 26262 var $ns = $class.replace(/\W+/g, ''); 26263 var $enter = 'mouseenter.hoverClass.' + $ns; 26264 var $leave = 'mouseleave.hoverClass.' + $ns; 26265 26266 this.off($enter); 26267 this.off($leave); 26268 26269 // Adding class on enter to whole set, or only one hoverred 26270 this.on($enter, function ($e) { 26271 if ( $allSet ) 26272 $this.addClass($class); 26273 else 26274 jQuery(this).addClass($class); 26275 }); //FUNC onMouseenter 26276 26277 this.on($leave, function ($e) { 26278 if ( $allSet ) 26279 $this.removeClass($class); 26280 else 26281 jQuery(this).removeClass($class); 26282 }); //FUNC onMouseenter 26283 26284 return this; 26285} //FUNC hoverClass 26286 26287jQuery.fn.groupBy = function ($attribute) { 26288 26289 // Defaulting to data-group attribute. 26290 $attribute = $attribute || 'data-group'; 26291 26292 var $res = {}; // Will store groups here 26293 26294 // Looping through each element, and storing as groups 26295 this.each( function () { 26296 26297 var $el = jQuery(this); 26298 26299 // Getting groups attribute 26300 var $attr = $el.attr($attribute); 26301 26302 // Nothing to do if no attribute set (ungrouped element) 26303 if ( !$attr ) 26304 return; 26305 26306 // Parsing into groups, allowing common delimiters 26307 var $groups = strToArray($attr, ',.|'); 26308 26309 // Assigning element into each group, adding into existing, or creating new ones 26310 for ( var $i in $groups ) { 26311 var $group = $groups[$i]; 26312 26313 if ( !$res[$group] ) 26314 $res[$group] = $el; 26315 else 26316 $res[$group] = $res[$group].add($el); 26317 26318 } //FOR each group 26319 26320 }); //FUNC each.result 26321 26322 // Returning results 26323 return $res; 26324} //FUNC groupBy 26325 26326function centerWindow (el) { 26327 jQuery(el).centerWindow(); 26328} //FUNC centerWindow 26329 26330/*--------------------------------------------------------------------------------*\ 26331| jqmShowCSS 26332|---------------------------------------------------------------------------------- 26333| Apllies given css to jQM window and shows it. 26334| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
26335| Params: 26336| selector string - Window to show. 26337| css string - Object with css to apply. 26338| effect string - Effect to use on displaying. 26339| Return: 26340| bool - Alwyas false. 26341\*--------------------------------------------------------------= by Mr.V!T =-----*/ 26342function jqmShowCSS (selector, css, effect) { 26343 26344 jQuery(selector).css(css); 26345 26346 if ( jqmVisible(selector) ) return false; 26347 26348 if ( !isJQM(selector) ) { 26349 26350 var opt = {}; 26351 26352 if ( effect == 'fade' ) 26353 opt = { 26354 onShow: function(h) { 26355 h.w.fadeIn(300); 26356 }, 26357 onHide: function(h) { 26358 h.w.fadeOut(300); 26359 h.o.remove(); 26360 } 26361 }; //Object o 26362 26363 jQuery(selector).jqm(opt); 26364 if ( jQuery().jqDrag ) jQuery(selector).jqDrag('.jqmHeader'); 26365 if ( jQuery().jqResize ) jQuery(selector).jqResize('.jqmResize'); 26366 } //IF element is not jqm window already 26367 26368 jQuery(selector).jqmShow(); 26369 26370 return false; 26371 26372} //FUNC jqmShowCSS 26373 26374/*--------------------------------------------------------------------------------*\ 26375| jqmShowCentered 26376|---------------------------------------------------------------------------------- 26377| Fixes coordinates of jQM window to match center. 26378| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 26379| Params: 26380| selector string - Window to show. 26381| effect string - Effect to use on displaying. 26382| Return: 26383| bool - Alwyas false. 26384\*--------------------------------------------------------------= by Mr.V!T =-----*/ 26385function jqmShowCentered (selector, effect) { 26386/**/ 26387 var wnd_width = jQuery(selector).width(); 26388 var wnd_height = jQuery(selector).height(); 26389 26390 var parent_window = screenSize(); 26391 26392 var wnd_left = ( parent_window.width - wnd_width ) / 2; 26393 var wnd_top = ( parent_window.height - wnd_height ) / 2; 26394 26395 var new_css = {'top':wnd_top,'left':wnd_left}; 26396/*/ 26397 var new_css = {'top':0,'left':0, 'margin': 'auto auto'}; 26398 26399/**/ 26400 return jqmShowCSS(selector, new_css, effect); 26401} //FUNC jqmShowCentered 26402 26403/*--------------------------------------------------------------------------------*\ 26404| jqmShowDocked 26405|---------------------------------------------------------------------------------- 26406| Fixes coordinates of jQM window to dock to given element. 26407| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 26408| Params: 26409| selector string - Window to show. 26410| dock_to string - Selector of element to dock to. 26411| effect string - Effect to use on displaying. 26412| Return: 26413| bool - Alwyas false. 26414\*--------------------------------------------------------------= by Mr.V!T =-----*/ 26415function jqmShowDocked (selector, dock_to, effect) { 26416 26417 var offset = jQuery(dock_to).offset(); 26418 if ( !offset.top ) return false; 26419 26420 var outer = jQuery(dock_to).outerHeight(); 26421 26422 var new_css = { 26423 'top' : offset.top + outer + 3, 26424 'left' : offset.left 26425 }; //New CSS 26426 26427 return jqmShowCSS(selector, new_css, effect); 26428} //FUNC jqmShowDocked 26429 26430/*--------------------------------------------------------------------------------*\ 26431| jqmHide 26432|---------------------------------------------------------------------------------- 26433| Hides JQM window. 26434| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 26435| Params: 26436| selector string - Window to hide. 26437| effect string - Effect to use on hiding. 26438| Return: 26439| bool - Alwyas false. 26440\*--------------------------------------------------------------= by Mr.V!T =-----*/ 26441function jqmHide (selector, effect) { 26442 jQuery(selector).jqmHide(); 26443 return false; 26444} //FUNC jqmHide 26445 26446/*--------------------------------------------------------------------------------*\ 26447| isJQM 26448|---------------------------------------------------------------------------------- 26449| Check if element is already jqModal window. 26450| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 26451| Params: 26452| selector string - Element to check. 26453| Return: 26454| NULL 26455\*--------------------------------------------------------------= by Mr.V!T =-----*/ 26456function isJQM (selector) { 26457 26458 var tmp = jQuery(selector).attr('class'); 26459 if ( tmp.indexOf('jqmID') < 0 ) return false; 26460 26461 return true; 26462 26463} //FUNC isJQM 26464 26465/*--------------------------------------------------------------------------------*\ 26466| jqmVisible 26467|---------------------------------------------------------------------------------- 26468| Checks if jqm window is visible. 26469| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
26470| Params: 26471| selector string - Element to check. 26472| Return: 26473| NULL 26474\*--------------------------------------------------------------= by Mr.V!T =-----*/ 26475function jqmVisible (element) { 26476 26477 if ( !(element instanceof jQuery) ) 26478 element = jQuery(element); 26479 26480 var disp = element.css('display'); 26481 26482 return (disp != 'none'); 26483} //FUNC jqmVisible 26484 26485function centerWindow (win) { 26486 var wnd_width = jQuery('#'+win).width(); 26487 var wnd_height = jQuery('#'+win).height(); 26488 26489 var parent_window = screenSize(); 26490 26491 var wnd_left = ( parent_window.width - wnd_width ) / 2; 26492 var wnd_top = ( parent_window.height - wnd_height ) / 2; 26493 26494 var new_css = {'top':wnd_top,'left':wnd_left}; 26495 jQuery('#'+win).css(new_css); 26496} //FUNC 26497 26498function getOuterHTML (el) { 26499 26500 if ( el.outerHTML ) return el.outerHTML; 26501 26502 var tmp = document.createElement(el.parentNode.tagName); 26503 tmp.appendChild(el.cloneNode(true)); 26504 26505 return tmp.innerHTML; 26506} //FUNC getOuterHTML 26507 26508function strToElement (html) { 26509 var tmp = document.createElement('div'); 26510 tmp.innerHTML = html; 26511 26512 return tmp.firstChild; 26513} //FUNC strToElement 26514 26515function setOuterHTML (el, html) { 26516 26517 if ( el.outerHTML ) return el.outerHTML = html; 26518 26519 var n = strToElement(html); 26520 26521 el.parentNode.replaceChild(n, el); 26522} //FUNC setOuterHTML 26523 26524/** //** ----= formToArray =--------------------------------------------------------------------------------------\**//** \ 26525* 26526* Collects input values as data object. Result is exactly same as one you get with $_POST. 26527* Supports nested arrays and sets in naming. E.g.: name="lvl1[lvl2][lvl3][]" 26528* 26529* @param object(HTMLFormElement) 26530* $form - Source form. 26531* 26532* @return object - Data collected from form. 26533* 26534\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 26535function formToArray ($form, $options) { 26536 26537 // Storing results in object 26538 var $data = {}; 26539 26540 // Defaulting options 26541 $options = $options || {}; 26542 26543// ---- 3rd parties ---- 26544 26545 // If there is tiny - forcing it to save editors 26546 if ( typeof(tinyMCE) != 'undefined' ) 26547 tinyMCE.triggerSave(); 26548 26549 // Optionally supporting jQuery elements, though shold point exactly to form 26550 if ( isJQ($form) ) { 26551 26552 // Not proceesing if not form though 26553 if ( !$form.is('form') ) 26554 return $data; 26555 26556 // Getting DOM from jQuery 26557 $form = $form.get(0); 26558 } //IF jQuery given 26559 26560// ---- Form ---- 26561 26562 // Counting inputs with same name for sets resolving 26563 var $index = {}; 26564 26565 // Looping through elements and getting values for each 26566 for ( var $i = 0; $i < $form.elements.length; $i++ ) { 26567 26568 // ---- Element ---- 26569 26570 // Getting element to work with 26571 var $el = $form.elements.item($i); 26572 26573 // Collecting value, and then storing it in data object 26574 var $val; 26575 26576 // Skipping it if it does not have name 26577 if ( !$el.name ) 26578 continue; 26579 26580 // ---- Input ---- 26581 26582 switch ( $el.type ) { 26583 case 'file' : 26584 // In HTML files are not included in post 26585 continue; 26586 26587 case 'radio' : 26588 case 'checkbox' : 26589 26590 $val = $el.value; 26591 26592 if ( $val == 'on' ) { 26593 26594 // Using slightly alternate behavior 26595 // where checkboxes without values (val == on) return 1/0 instead of 1/unset 26596 $val = ( $el.checked )? 1 : 0; 26597 26598 } //IF no value 26599 else if ( !$el.checked ) { 26600 26601 if ( $options['emptyChecks'] ) { 26602 26603 $val = ''; 26604 26605 } //IF empty checkboxes should present 26606 26607 else { 26608 26609 // For valued checkboxes - regular behavior 26610 continue; 26611 26612 } //IF standard behavior 26613 26614 } //IF value is set 26615 26616 break; 26617 26618 case 'select-one' : 26619 26620 // Using dedicated tool 26621 $val = getValue_Select($el); 26622 26623 break; 26624 26625 case 'select-multiple' : 26626 26627 // Using dedicated tool 26628 $val = getValue_MutliSelect($el); 26629 26630 break; 26631 26632 default : 26633 26634 // Regular inputs have just value 26635 $val = $el.value; 26636 } //SWITCH 26637 26638 // Nothing to do with null 26639 if ( isUndefined($val) ) 26640 continue; 26641 26642 // ---- Data ---- 26643 26644 var $name = $el.name; // That will be working name 26645 26646 // Expecting array to happen, so parsing as path right away 26647 var $path = regexMatchAll(/[\w\-]+/g, $name); 26648 26649 // Problematic paths are skipped too 26650 if ( !$path[0] ) 26651 continue; 26652 26653 // Full match is all we need 26654 $path = $path[0]; 26655 26656 // Indexing now, as it looks like valid name 26657 $index[$name] = isSet($index[$name]) ? ++$index[$name] : 0; 26658 26659 // Special case for sets 26660 // Those should be stored as simple array 26661 // Exception for multiarrays: those always have [] to work properly 26662 // (except rare cases when multiple same named selects used... which is never... currently only one will be allowed) 26663 26664 if ( ($el.type != 'select-multiple') && $name.endsWith('[]') ) { 26665 26666 // Need to merge with existing array if one is present 26667 var $set = arrayPath($data, $path); 26668 26669 // Merging value into set, which will be set into data 26670 26671 if ( isObject($set, true) ) 26672 26673 // Adding into objectx using index 26674 $set[$index[$name]] = $val; 26675 26676 else if ( isArray($set) ) 26677 26678 // Pushing if array 26679 $set.push($val) 26680 26681 else 26682 // Non arrays are overwritten 26683 $set = [$val]; 26684 26685 // Preparing to be set back to data 26686 $val = $set; 26687 26688 } //IF set given 26689 26690 // Now we have both value and path 26691 // Just setting it 26692 arrayPath($data, $path, $val); 26693 26694 } //FOR each element 26695 26696 return $data; 26697} //FUNC formToArray 26698 26699/** //** ----= formFromArray =--------------------------------------------------------------------------------------\**//** \ 26700* 26701* Sets form inputs values from given data object. 26702* Supports arrays and sets in elements names and tinyMCE Editor if applied to textarea. 26703* 26704* @param object(HTMLFormElement) 26705* $form - Form to setup. 26706* 26707* @param object $source - Values to set. 26708* 26709\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 26710function formFromArray ($form, $source) { 26711 26712 // Resaving to do not break source 26713 var $data = jQuery.extend({}, $source); 26714 26715 // Counting inputs with same name for sets resolving 26716 var $index = {}; 26717 26718// ---- Form ---- 26719 26720 for ( var $i = 0; $i < $form.elements.length; $i++ ) { 26721 26722 // ---- Element ---- 26723 26724 // Getting form element, it's name and value that should be applied 26725 var $el = $form.elements.item($i); 26726 26727 // Skipping it if it does not have name 26728 if ( !$el.name ) 26729 continue; 26730 26731 // Getting element name 26732 var $name = $el.name; 26733 26734 // Expecting array to happen, so parsing as path right away 26735 var $path = regexMatchAll(/[\w\-]+/g, $name); 26736 26737 // Problematic paths are skipped too 26738 if ( !$path[0] ) 26739 continue; 26740 26741 // Full match is all we need 26742 $path = $path[0]; 26743 26744 // Indexing now, as it looks like valid name 26745 $index[$name] = isSet($index[$name]) ? ++$index[$name] : 0; 26746 26747 // ---- Value ---- 26748 26749 var $val = arrayPath($data, $path); 26750 26751 // Resolving set 26752 var $set = $val; 26753 if ( $set && $name.endsWith('[]') ) { 26754 26755 // Getting value by index 26756 $val = $set[$index[$name]]; 26757 26758 } //IF set given 26759 26760 // Making sure value is valid after all 26761 $val = ( isUndefined($val) || $val === false || $val === null ) ? '' : $val; 26762 26763 // Special case for date inputs 26764 if ( $val == '0000-00-00' || $val == '0000-00-00 00:00:00' ) 26765 $val = ''; 26766 26767 // ---- Inputs ---- 26768 26769 switch ($el.type) { 26770 26771 case 'checkbox' : 26772 case 'radio' : 26773 26774 // For simple checkboxes - comparing against found value 26775 // Value will be either set directly or indexed in set 26776 if ( $el.value == 'on' ) { 26777 26778 $el.checked = ( !isEmpty($val) ); 26779 break; 26780 26781 } //IF simple checkbox 26782 26783 // If not part of set - just checking values to match 26784 // Casting incoming value to string manually to ensure that match is correct for numbers
26785 // Input value is always string anyway 26786 if ( !isObject($set, true) ) { 26787 26788 $el.checked = ( $val.toString() === $el.value ); 26789 break; 26790 26791 } //IF not a set 26792 26793 // Custom behavior if part of set - checking by value presense 26794 // Looping through and checking if value is there 26795 // Doing manually instead of array's indexOf cuz assoc array or object could happen 26796 var $tmp = false; 26797 for ( var $t in $set ) 26798 if ( $t in $set && $set[$t].toString() === $el.value ) 26799 $tmp = true; 26800 26801 $el.checked = $tmp; 26802 26803 break; 26804 26805 case 'select-one' : 26806 case 'select-multiple' : 26807 26808 // Using entire set 26809 setValue_Select($el, $set); 26810 26811 break; 26812 26813 case 'file' : 26814 26815 // File just resetting to default. 26816 // Files can't have values, unless selected 26817 // So if we're setting form from array - it better have no value than old some 26818 $el.value = ''; 26819 26820 // Alternatively - can recreate input completely 26821 // Getting input HTML, then creating new element from it, 26822 // Doing this way since simple clone will not help 26823 // var $html = getOuterHTML($el); 26824 // setOuterHTML($el, $html); 26825 26826 // Skipping styled forms 26827 // ToDo: capture events instead 26828 26829 // Special case for morweb inputs - those are not recreated 26830 // And values are handled differently 26831 // ToDo: remove morweb hardcode and allow custom inputs handling 26832 if ( $el.className.indexOf('mw') !== -1 ) { 26833 26834 // Adding as dedicated attribute, which will be handled by morweb later on 26835 var $jFile = jQuery($el); 26836 $jFile.attr('data-file', $val || ''); 26837 26838 // Also setting value 26839 26840 // Triggering change 26841 $jFile.change(); 26842 26843 } //IF morweb input 26844 26845 break; 26846 26847 case 'textarea' : 26848 26849 // Checking if textarea can be tinyMCE 26850 if ( $el.style.display == 'none' && ( typeof tinyMCE != 'undefined' ) ) { 26851 26852 // Checking if tiny really applied to it 26853 var $tiny = tinyMCE.get($el.id); 26854 26855 // If it's tiny - setting values into it too. 26856 if ( $tiny ) 26857 $tiny.setContent($val); 26858 26859 }; //IF hidden and tinyMCE exists 26860 26861 $el.value = $val; 26862 26863 break; 26864 26865 case 'button' : 26866 case 'submit' : 26867 26868 break; 26869 26870 default : 26871 $el.value = $val; 26872 } //SWITCH 26873 26874 // Triggering onChange in case if some set. 26875 if ( isSet(jQuery) ) 26876 jQuery($el).change(); 26877 26878 } //FOR each element 26879 26880} //FUNC formFromArray 26881 26882/** //** ----= jQuery.asArray =--------------------------------------------------------------------------------------\**//** \ 26883* 26884* Simple jQuery wrapper for formToArray() function. 26885* 26886* @return array - Form elements valus as array. 26887* 26888\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 26889jQuery.fn.asArray = function ($options) { 26890 26891 if ( !this.is('FORM') ) return {}; 26892 26893 return formToArray(this.get(0), $options); 26894} //FUNC asArray 26895 26896/** //** ----= jQuery.fromArray =--------------------------------------------------------------------------------------\**//** \ 26897* 26898* Simple jQuery wrapper for formFromArray() function. 26899* 26900* @param object data - Array with values to set to elements. 26901* @return jQuery - jQuery object for chain calls. 26902* 26903\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 26904jQuery.fn.fromArray = function (data) { 26905 26906 if ( !this.is('FORM') ) return this; 26907 26908 formFromArray( this.get(0), data ); 26909 26910 return this; 26911} //FUNC fromArray 26912 26913/*--------------------------------------------------------------------------------*\ 26914| getValue_Select 26915|---------------------------------------------------------------------------------- 26916| Returns correct value of <select> based in setted or not value attribute. IE FIX. 26917| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 26918| Params: 26919| element object - DOM elemnt to get value. 26920| Return: 26921| MIXED 26922| bool - FALSE in case of error. 26923| string - Element value. 26924\*--------------------------------------------------------------= by Mr.V!T =-----*/ 26925function getValue_Select (element) { 26926 26927 if ( element.options.selectedIndex < 0 ) return false;
26928 26929 var option = element.options[element.options.selectedIndex]; 26930 var value = getValue_Option(option); 26931 //(option.attributes.value && option.attributes.value.specified)? option.value : option.text 26932 26933 return value; 26934} //FUNC getValue_Select 26935 26936/*--------------------------------------------------------------------------------*\ 26937| getValue_MutliSelect 26938|---------------------------------------------------------------------------------- 26939| Returns values of <select> with multiple selection enabled as an array. 26940| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 26941| Params: 26942| element object - DOM elemnt to get value. 26943| Return: 26944| array - Array with values. Can be emty. 26945\*--------------------------------------------------------------= by Mr.V!T =-----*/ 26946function getValue_MutliSelect (element) { 26947 26948 var res = [] ; 26949 26950 if ( !element.options || element.options.length <= 0 ) return res; 26951 26952 for ( var i = 0; i < element.options.length; i++ ) { 26953 26954 if ( !element.options[i].selected ) continue; 26955 26956 res.push(getValue_Option(element.options[i])); 26957 } //FOR all managers 26958 26959 return res; 26960} //FUNC getValue_MutliSelect 26961 26962/*--------------------------------------------------------------------------------*\ 26963| setValue_Select 26964|---------------------------------------------------------------------------------- 26965| Correctly sets value to selector. Works in old IE. 26966| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 26967| Params: 26968| element object - DOM elemnt to set value. 26969| values MIXED - Single string value or array with selected values. 26970| Return: 26971| VOID 26972\*--------------------------------------------------------------= by Mr.V!T =-----*/ 26973function setValue_Select (element, values) { 26974 26975 if ( element.options.length <= 0 ) return; 26976 26977 if ( !values ) 26978 values = []; 26979 26980 if ( typeof(values) != 'object' ) { 26981 26982 // Converting values depending on multiple attribute 26983 // If multiple - most likely it's simple array string. 26984 if ( element.multiple || element.size ) 26985 values = strToArray(values); 26986 else 26987 // Stringifying value, cuz if integer come - indexOf will ignore it 26988 values = [values+'']; 26989 26990 } //IF not array come 26991 26992 for ( var i = 0; i < element.options.length; i++ ) { 26993 26994 var val = getValue_Option(element.options[i]); 26995 26996 element.options[i].selected = (values.indexOf(val) != -1); 26997 26998 } //FOR all elements 26999 27000} //FUNC setValue_Select 27001 27002/*--------------------------------------------------------------------------------*\ 27003| getValue_Option 27004|---------------------------------------------------------------------------------- 27005| Returns correct value of <option> based in setted or not value attribute. IE FIX. 27006| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 27007| Params: 27008| element object - DOM elemnt to get value. 27009| Return: 27010| string - Element value. 27011\*--------------------------------------------------------------= by Mr.V!T =-----*/ 27012function getValue_Option (element) { 27013 var value = (element.attributes.value && element.attributes.value.specified)? element.value : element.text; 27014 return value; 27015} //FUNC getValue_Option 27016 27017/*--------------------------------------------------------------------------------*\ 27018| getSelectorOptions 27019|---------------------------------------------------------------------------------- 27020| Returns array with selector values. 27021| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 27022| Params: 27023| element object - DOM elemnt to get value. 27024| Return: 27025| array - Selector values. 27026\*--------------------------------------------------------------= by Mr.V!T =-----*/ 27027function getSelectorOptions (element) { 27028 27029 var res = [] ; 27030 27031 if ( !element.options || element.options.length <= 0 ) return res; 27032 27033 for ( var i = 0; i < element.options.length; i++ ) { 27034 27035 var option = element.options[i]; 27036 27037 if ( option.attributes.value && option.attributes.value.specified ) { 27038 res[option.value] = option.text; 27039 } else { //IF value set 27040 res.push(option.text); 27041 } //IF value not set 27042 27043 } //FOR each option 27044 27045 return res; 27046} //FUNC getSelectorOptions 27047 27048/** //** ----= strToArray =--------------------------------------\**//** \ 27049* 27050* Splits string into array with given delimeters, trimming resulting items. 27051* 27052* @param string str - String to split. 27053* @return array - Resulting array. 27054* 27055\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 27056function strToArray(str, delim) { 27057 27058 // No need to split if already array 27059 if ( isArray(str) ) 27060 return str; 27061 27062 delim = delim || ',|'; 27063 27064 var tmp = str.split( new RegExp('\\s*[' + delim + ']\\s*') ); 27065 27066 var res = []; 27067 27068 // Skipping empties 27069 for ( var i in tmp ) 27070 if ( tmp[i] ) res.push(tmp[i]); 27071 27072 return res; 27073} //FUNC strToArray 27074 27075/** //** ----= strToObj =----------------------------------------------\**//** \ 27076* 27077* Splits string into object array with given delimeters 27078* 27079* @param string str - String to split. 27080* @return array - Resulting array. 27081* 27082\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 27083function strToObj (str, delim, auto_tirm) { 27084 27085 var res = {}; 27086 27087 if ( !str ) 27088 return res; 27089 27090 var tmp = str.split(delim); 27091 27092 var j = 0; 27093 27094 for ( var i in tmp ) { 27095 27096 var pos = tmp[i].indexOf('='); 27097 27098 if ( pos != -1 ) { 27099 var key = tmp[i].substr(0, pos); 27100 var val = tmp[i].substr(pos+1); 27101 } else { //IF eq symbol found 27102 var key = j+''; 27103 var val = tmp[i]; 27104 } //IF single value 27105 27106 key = key.trim(); 27107 27108 if ( auto_tirm ) 27109 val = val.trim(); 27110 27111 res[key] = val; 27112 27113 j++; 27114 27115 } //FOR each value 27116 27117 return res; 27118} //FUNC strToObj 27119 27120/** //** ----= cb =--------------------------------------\**//** \ 27121* 27122* Callback runner helper. Used to simplify code. Checks if funciton given. 27123* 27124* @param function func - Function to run. 27125* @param MIXED * - All next parameters will be passed to function. 27126* 27127* @return MIXED - Funciton restult. 27128* 27129\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 27130function cb(func, args) { 27131 27132 // ToDo: apply is not applicable here, so think better way; 27133 27134} //FUNC cb 27135 27136/** //** ----= checkAll =--------------------------------------\**//** \ 27137* 27138* Sets value to all checkboxes in an element. 27139* 27140* @param bool value - Checkbox state. 27141* @param string element - jQuery selector. 27142* @return bool - Initial value. 27143* 27144\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 27145function checkAll (value, element) { 27146 27147 jQuery(element).find('INPUT[type=checkbox]').attr('checked', value); 27148 27149 return false; 27150} //FUNC checkAll 27151 27152function ToggleDisplay(elementID, state) { 27153 element = document.getElementById(elementID); 27154 27155 if ( !element ) return; 27156 27157 if (state == undefined) { 27158 state = ( element.style.display == 'none' ); 27159 } //IF no state specified 27160 27161 element.style.display = state ? 'inline' : 'none'; 27162} //FUNC ToggleDisplay 27163 27164function screenSize() { 27165 var w, h; 27166 w = (window.innerWidth ? window.innerWidth : (document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.offsetWidth)); 27167 h = (window.innerHeight ? window.innerHeight : (document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.offsetHeight)); 27168 return {width:w, height:h}; 27169} 27170 27171function selectRow(row, state) { 27172 var row_class = jQuery('#'+row).attr('class'); 27173 row_class = row_class.replace('_selected',''); 27174 row_class += ( state )? '_selected' : ''; 27175 jQuery('#'+row).attr('class', row_class); 27176} //FUNC selectRow 27177 27178/*/ 27179function insert_bar (bar_place) { 27180 jQuery('#'+bar_place).html('<IMG src="/images/processing/bar.gif" alt="Loading...">'); 27181} //FUNC insert_bar 27182 27183function insert_green_bar (bar_place) { 27184 jQuery('#'+bar_place).html('<IMG src="/images/processing/bar_green.gif" alt="Loading...">'); 27185} //FUNC insert_bar 27186//*/ 27187 27188/** //** ----= getCookie =--------------------------------------\**//** \ 27189* 27190* Returns cookie with given name. 27191* 27192* @param string name - Cookie name to search. 27193* @param string [def] - Default value to return if cookie not found. 27194* 27195* @return string - Cookie value. 27196* 27197\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 27198function getCookie (name, def) { 27199 27200 if ( def == undefined ) def = ''; 27201 27202 var cookieValue = def; 27203 var cookieName = name + '='; 27204 27205 if ( document.cookie.length > 0 ) { 27206 27207 offset = document.cookie.lastIndexOf(cookieName); 27208 if ( offset != -1 ) { 27209 27210 offset += cookieName.length; 27211 27212 end = document.cookie.indexOf(';', offset); 27213 if (end == -1) end = document.cookie.length; 27214 27215 cookieValue = unescape(document.cookie.substring(offset, end)) 27216 27217 } //IF found smth 27218 27219 } //IF there are cookies 27220 27221 return cookieValue; 27222} //FUNC getCookie 27223 27224/** //** ----= setCookie =----------------------------------------------\**//** \ 27225* 27226* Sets cookie with given name. 27227* 27228* @param string name - Cookie name to set. 27229* @param string value - Value of cookie. 27230* @param string [hours] - Expiration date in hours. 27231* 27232\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 27233function setCookie (name, value, hours) { 27234 27235 var expire = ""; 27236 27237 if ( hours ) { 27238 expire = new Date((new Date()).getTime() + hours * 3600000); 27239 expire = "; expires=" + expire.toGMTString(); 27240 } //IF there is set expiration 27241 27242 document.cookie = name + "=" + escape(value) + expire + ';path=/;'; 27243 27244} //FUNC setCookie 27245 27246function get_controller_views(views) { 27247 insert_bars(views);
27248 insert_views(views,0); 27249} //FUNC get_controller_views 27250 27251function mark_checkboxes(container_form,val) { 27252 for (var i = 0; i < container_form.elements.length; i++) { 27253 el = container_form.elements[i]; 27254 if (el.type=='checkbox') 27255 el.checked=val; 27256 } 27257} //FUNC mark_checkboxes 27258 27259function status_string(message,style_class,padding) { 27260 if (message == '') return ''; 27261 if (!style_class) style_class = 'status_error'; 27262 if (!padding) padding = 0; 27263 return '<div class="'+style_class+'" style="padding:'+padding+'px">'+message+'</div>'; 27264} //FUNC error_string 27265 27266function ajax_pack_data(controller_url,place_to_put, data, ajax_options) { 27267 var res = []; 27268 res['controller'] = controller_url; 27269 res['place'] = place_to_put; 27270 if (!data) data = {}; 27271 res['data'] = data; 27272 if (!ajax_options) ajax_options = {}; 27273 res['options'] = ajax_options; 27274 return res; 27275} //FUNC pack_view 27276 27277function ajax_insert_bars(views) { 27278 for (i=0; i < views.length; i++) { 27279 insert_bar(views[i]['place']); 27280 } //FOR each views 27281} //FUNC insert_bars 27282 27283function ajax_insert_views(views,num) { 27284 if (num >= views.length) return false; 27285 27286 var tdata = views[num]['data']; 27287 27288 if (views[num]['options'].onLoad) {views[num]['options'].onLoad(tdata)}; 27289 jQuery.ajax({ 27290 type : 'POST', dataType: 'html', 27291 url : views[num]['controller'], 27292 data : views[num]['data'], 27293 success : function(obj){ 27294 jQuery('#'+views[num]['place']).html(obj); 27295 ajax_insert_views(views,num+1); 27296 if (views[num]['options'].onSuccess) {views[num]['options'].onSuccess(tdata)}; 27297 },//FUNC success 27298 error : function (XMLHttpRequest, textStatus, errorThrown) { 27299 jQuery('#'+views[num]['place']).html(status_string('This section is not avaible now (Possibly under construction). Try again later.')); 27300 ajax_insert_views(views,num+1); 27301 } //FUNC error 27302 }); //ajax 27303}//FUNC insert_views 27304 27305function ajax_get_views(views) { 27306 ajax_insert_bars(views); 27307 ajax_insert_views(views,0); 27308} //FUNC get_controller_views 27309 27310function ajax_get_view(controller_url,place_to_put,data, ajax_options) { 27311 ajax_get_views([ajax_pack_data(controller_url,place_to_put,data, ajax_options)]); 27312} //FUNC get_controller_view 27313 27314function ajax_post (post_form,controller,status_place,settings) { 27315 insert_bar(status_place); 27316 var tt = document.getElementById(post_form); 27317 if (!tt) alert('no form'); 27318//*/ 27319 jQuery.ajaxUpload ({ 27320 type : 'POST', dataType : 'html', 27321 url : controller, 27322 secureuri : false, 27323 uploadform : document.getElementById(post_form), 27324 success : function (res, status) { 27325 data = res.split('<!-- CUT -->'); 27326 jQuery('#'+status_place).html(data[0]); 27327 27328 if ((data.length != 1) && (data[1] == 'success') ) { 27329 if (settings.success) settings.success(data); 27330 } else { 27331 if (settings.error) settings.error(data); 27332 } //IF returned status 27333 27334 }, //FUNC sucess 27335 error : function (res, status) { 27336 alert('error'); 27337 jQuery('#'+status_place).html(status_string('Error: '+status)); 27338 if (settings.error) settings.error(); 27339 } //FUNC error 27340 27341 }); //AJAX 27342//*/ 27343} //FUNC ajax_post 27344 27345/** //** ----= getDimensions =--------------------------------------------------------------------------------------\**//** \ 27346* 27347* Parses strings like '100x200' into [x,y] dimensions pair (with Y being optional). 27348* Returns FALSE if string does not contain valid dimensions string. 27349* 27350* @param string $dimensions - Dimensions string. 27351* @param bool [$strict] - Strict validation. Will require Y to present 27352* 27353* @return MIXED - Array with named dimensons or FALSE if failed. 27354* 27355\**//** ---------------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 27356function getDimensions ($dimensions, $strict) { 27357 27358 // Nothing to do if notihng fiven 27359 if ( !$dimensions ) 27360 return false; 27361 27362 // Simple check for compatability with parsed dimensions, allowing mixed params in callee funcions. 27363 if ( isArray($dimensions) || isObject($dimensions) ) { 27364 27365 // Fast validation for X to be present: it's minimal requirement for valid dimensions array 27366 if ( !isSet($dimensions['x']) ) 27367 return false; 27368 27369 // Fast validation for strict mode 27370 if ( $strict && !isSet($dimensions['y']) ) 27371 return false;
27372 27373 return $dimensions; 27374 } //IF array given 27375 27376 // Parsing for dimensions, using regex. It also allows to validate dimensions stirng. 27377 // X and Y will be named in matches, which makes it easyer to return. 27378 27379 // Strict option really changes counter for second (x200) match 27380 $strict = $strict ? '+' : '?'; 27381 27382 // Capturing groups and then checking once that good 27383 var $reg = '^([0-9]+)(x([0-9]+))' + $strict + '$'; 27384 var $match = $dimensions.match( new RegExp($reg, 'i') ); 27385 27386 // Checking existing params 27387 if ( !$match ) 27388 return false; 27389 27390 // Grabbing only named matches into result (to keep result clear) 27391 var $res = {}; 27392 27393 // X always present at this step (othewise we'd returned already) 27394 $res['x'] = $match[1]; 27395 27396 // Y is optional 27397 if ( isSet($match[3]) ) 27398 $res['y'] = $match[3]; 27399 27400 // Can return now 27401 return $res; 27402} //FUNC getDimensions 27403 27404/* #### MATH ################################################################################################################ */ 27405 27406/** //** ----= asDeg =----------------------------------------------------------------------------------------------\**//** \ 27407* 27408* Converts radians to degrees. 27409* 27410* @param float $angle - Angle in radians. 27411* 27412* @return flaot - Angle in degrees. 27413* 27414\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 27415function asDeg ($angle) { 27416 return $angle * (180 / Math.PI); 27417} //FUNC asDeg 27418 27419/** //** ----= asRad =----------------------------------------------------------------------------------------------\**//** \ 27420* 27421* Converts degrees to radians. 27422* 27423* @param float $angle - Angle in degrees. 27424* 27425* @return flaot - Angle in radians. 27426* 27427\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 27428function asRad ($angle) { 27429 return $angle * (Math.PI / 180); 27430} //FUNC asRad 27431 27432/** ************************************************************************************************************************ **\ 27433* 27434* Set of classes and functions that will help generate and process AJAX queries. 27435* 27436* @package VIT-Lib 27437* @subpackage Ajax 27438* 27439* @license MIT License 27440* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 27441* associated documentation files (the "Software"), to deal in the Software without restriction, including 27442* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 27443* copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to 27444* the following conditions: 27445* 27446* The above copyright notice and this permission notice shall be included in all copies or substantial 27447* portions of the Software. 27448* 27449* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 27450* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 27451* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 27452* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 27453* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27454* 27455* @author Victor Denisenkov aka Mr.V!T 27456* @copyright Copyright (c) 2008 - 2012 Victor Denisenkov aka Mr.V!T 27457* @version 1.0 27458* 27459\** ************************************************************************************************************************ **/ 27460 27461/** //** ----= OBJECT vAjax =--------------------------------------------------------------------------------------\**//** \ 27462* 27463* Ajax procesing object. Implements both jQuery common ajax and ajaxUpload plugin for iframe upload tricks (for old 27464* browsers). Designed to use together with server side vAjax object. Supports POST progress monitoring using server 27465* side plugins like APC or HTML5 files API. By default enables progress monitoring for forms with files and progressbar 27466* present. 27467* 27468* @package VIT-Lib 27469* @subpackage Ajax 27470* @category Helper 27471* 27472* @param string url - Path to controller to make request to. 27473* 27474* @param MIXED [data] - Data to post on request. Can be DOM form, HTML5 FormData object, jQuery selector 27475* or object which points to form, or plain object with parameters. 27476* 27477* @param object [options] - Additional options if necessary. 27478* 27479* @todo Known bug: ajaxUpload can't handle server errors. Need workaround (possible write own iframe upload?) 27480* 27481\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 27482 27483// ToDo: Cross domain support with both JSONP and Access-Control-Allow-Origin: * 27484 27485function vAjax (url, data, options) { 27486 27487 // Creating basic object with events assigned 27488 var obj = vEventObject(['success', 'error', 'start', 'stop', 'done', 'progressStart', 'progressStop'], { 27489 27490 opt : { // Default object options 27491 async : true, // Set FALSE to make sync call 27492 simple : false, // Expect simple answers and threat them as success or trigger errors on those. 27493 modern : true, // Allow or not modern APIs 27494 27495 progress : '.progressFill', // Default progressbar fill element selector. Can be replaced with callback or own selector. 27496 progressNum : '.progressNum', // Default progressbar Numeric indicator. Will be set to current %. Ignored if callback given for fill. 27497 progressOn : false, // Forces progress monitoring (not used currently). 27498 27499 progressUrl : '/upload/?key=', // Progress monitoring controller. Key marker will be added to end of this. 27500 progressDelay : 500, // Delay before starting progress monitoring using server side plugin. 27501 progressInterval : 500 // Interval to update progress. 27502 }, //OBJECT options 27503 27504 resSplit : "-=-CUT-=-", // Unique marker used to split results. 27505 27506 controller : url, // Url to make request to. 27507 source : data || {}, // Source given. 27508 27509 sourceForm : false, // Source form if available. 27510 sourceData : {}, // Source data if available (if form given - will contain form inputs as array). 27511 sourceElement : false, // Source form as jQuery pointer. 27512 27513 isModern : false, // HMTL5 usage marker. Will be set to TRUE if system decides to use HTML5 27514 // formData and XHR2 to post data 27515 27516 Method : '', // Will store used upload method. 27517 27518 27519 prgInterval : false, // Progress bar monitor interval resource 27520 prgTimeout : false, // Progress bar monitoring timeout resource 27521 27522 _processor : false, // Stores custom XHR processor if specified. 27523 27524 /** //** ----= options =--------------------------------------------------------------------------------------\**//** \ 27525 * 27526 * Used to setup options on run time. 27527 * 27528 * @param object options - Data object with options to setup. 27529 * 27530 * @return SELF 27531 * 27532 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 27533 options : function (options) { 27534 27535 options = options || {}; 27536 27537 // Merging options 27538 jQuery.extend(this.opt, options); 27539 27540 // Testing browser to be modern 27541 this.isModern = this.opt.modern && isXHR2(); 27542 27543 return this; 27544 }, //FUNC options 27545 27546 /** //** ----= processor =------------------------------------------------------------------------------\**//** \ 27547 * 27548 * Custom processor is used to use external ajax xhr implementation. vAjax is passed as parameter to processor to 27549 * allow implementation of final events. Processor should call .ajaxSuccess() / .ajaxError() for appropiate events. 27550 * 27551 * @param function proc - Processor callback. 27552 * 27553 * @return SELF 27554 * 27555 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 27556 processor : function ( proc ) { 27557 this._processor = proc; 27558 return this; 27559 }, //FUNC processor 27560 27561 /** //** ----= parseResult =------------------------------------------------------------------------------\**//** \ 27562 * 27563 * Prses and format result data. Generates result to pass to callbacks. For internal use. 27564 * 27565 * @param object result - Request responce. 27566 * 27567 * @return object - Object with result data. 27568 * 27569 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 27570 parseResult : function (result) { 27571 27572 var self = this; 27573
27574 // Making sure that result have all vields 27575 if ( !result.responseText ) 27576 result.responseText = ''; 27577 27578 // ---- Preparing data ---- 27579 27580 // Preparing result wrapper 27581 var data = { 27582 27583 req : self.sourceData, // Request source data. 27584 27585 status : { // Responce meta like status and fields list. Default one for simple responces. Full responce will provide own head. 27586 major : (result.statusMinor == 'success'), // Major operation status TRUE or FALSE. Simples are TRUE normally. 27587 minor : result.statusMinor, // Minor/detailed status as string (like 'success', 'error', 'warning', 'simple' etc) 27588 code : result.status, // Satus code if available 27589 text : result.statusText, // Request status text 27590 full : false, // Full(complex) responce marker 27591 fields : [] // Custom responce fileds/types list 27592 }, //OBJECT meta 27593 27594 res : '' // Request basic response - whole simple request, or head/status message for complex response. Will be added with parsing below. 27595 }; //OBJECT data 27596 27597 // Trying to split as complex result 27598 var tmp = result.responseText.split(this.resSplit); 27599 27600 // Smth basic will present even for plain responce 27601 // (for example in case of server script fatal erorrs). 27602 // Correcting res to have at least smth 27603 data.res = tmp[0] || ''; 27604 27605 // Determinig wether result was full(complex) or simple 27606 data.status.full = tmp.length > 1; 27607 27608 // ---- Simple result ---- 27609 27610 // If got simple result (either error or success) 27611 if ( !data.status.full ) { 27612 27613 // Updating status 27614 data.status.major = data.status.major ? this.opt.simple : data.status.major; 27615 data.status.minor = 'simple'; 27616
27617 // If simple is threating as error - filling result as status text (expecting server errors) 27618 if ( !this.opt.simple && !data.status.text ) 27619 data.status.text = data.res; 27620 27621 // Running callbacks 27622 27623 // We are done anyway, so triggering stop event, passing self as param 27624 this.stop(data, this); 27625 27626 // Error/success 27627 if ( data.status.major && this.opt.simple ) 27628 this.success(data, this); 27629 else 27630 this.error(data, this); 27631 27632 // Both stop and done are called anyway, difference is calling order: stop, success/error, done 27633 this.done(data, this); 27634 27635 return data; 27636 27637 } // If simple 27638 27639 // ---- Complex result head and fields ---- 27640 27641 // For full responce status - header will go second (after possible debug) 27642 var head = JSON.parse(tmp[1]); 27643 27644 // Updating data status, merging existing response with given one 27645 // Mergin only if no text supplied already (usually errors have text) 27646 if ( !data.status.text ) 27647 jQuery.extend(data.status, head); 27648 27649 // Looping through given fields (if present) and decoding them to response 27650 var di = 2; 27651 if ( head.fields ) { 27652 27653 for ( var name in head.fields ) { 27654 27655 // Decoding non scalar values 27656 if ( !head.fields[name] ) { 27657 data[name] = JSON.parse(tmp[di]); 27658 } else { //IF need to decode 27659 data[name] = tmp[di]; 27660 } //IF no need to decode (scalar) 27661 27662 // Increasing split counter 27663 di++; 27664 } //FOR each field 27665 27666 } //IF was fields posted 27667 27668 // Running callbacks 27669 27670 // We are done anyway, so triggering stop event, passing self as param 27671 this.stop(data, this); 27672 27673 // Error/success 27674 if ( data.status.major ) 27675 this.success(data, this); 27676 else 27677 this.error(data, this); 27678 27679 // Both stop and done are called anyway, difference is calling order: stop, success/error, done 27680 this.done(data, this); 27681 27682 return data; 27683 27684 }, //FUNC parseResult 27685 27686// ==== CALLBAKCS ============================================================================================================== 27687 27688 /** //** ----= ajaxSuccess =------------------------------------------------------------------------------\**//** \ 27689 * 27690 * Ajax success event callback. For internal use, can be altered though. 27691 * 27692 * @see jQuery.ajax callbacks for parameters. 27693 * 27694 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 27695 ajaxSuccess : function (res, status) { 27696 27697 this.ajaxProgressStop(100); 27698 27699 status = status || 'success'; 27700 27701 // Creating result object 27702 return this.parseResult({ 27703 responseText : res, 27704 status : 0, 27705 statusText : '', 27706 statusMinor : status 27707 }); //parseResult.result 27708 27709 }, //FUNC ajaxSuccess 27710 27711 /** //** ----= ajaxError =------------------------------------------------------------------------------\**//** \ 27712 * 27713 * Ajax Error event callback. For internal use, can be altered though. 27714 * 27715 * @see jQuery.ajax callbacks for parameters. 27716 * 27717 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 27718 ajaxError : function (res, status) { 27719 27720 this.ajaxProgressStop('error'); 27721 27722 // Adding minor status to common result 27723 res.statusMinor = status; 27724 27725 return this.parseResult(res); 27726 27727 }, //FUNC ajaxError 27728 27729 /** //** ----= ajaxXHR =--------------------------------------------------------------------------------------\**//** \ 27730 * 27731 * Ajax XHR callback. Used to alter jQuery XHR. 27732 * 27733 * @see jQuery.ajax callbacks for parameters. 27734 * 27735 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 27736 ajaxXHR : function () { 27737 27738 var self = this; 27739 27740 var x = jQuery.ajaxSettings.xhr(); 27741 27742 // Adding listener only if really needed. If not - xhr goes back untouched 27743 if ( this.hasProgress() ) { 27744 27745 // If have progress - good place to reset it 27746 this.ajaxProgressStart(); 27747 27748 // We are sure that .upload exists: previously it was tested in .post() 27749 x.upload.addEventListener('progress', function (e) { 27750 27751 if ( e.lengthComputable ) { 27752 27753 // Calculating procents 27754 var proc = (e.loaded * 100) / e.total; 27755 27756 self.ajaxProgress( Math.floor(proc) ); 27757 27758 } //IF there is progress available 27759 27760 }, false); 27761 27762 } //IF need progress monitoring 27763 27764 return x; 27765 }, //FUNC ajaxXHR 27766 27767// ==== Progress =============================================================================================================== 27768 27769 /** //** ----= getFormElement =------------------------------------------------------------------------------\**//** \ 27770 * 27771 * For internal use. Checks given parameter as for element. Mainly used for progress indication elements search. 27772 * 27773 * @param MIXED - jQuery selector to search. 27774 * 27775 * @return MIXED - jQuery element to use as progress element, or FALSE if not applicable. 27776 * 27777 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 27778 getFormElement : function (el) { 27779 27780 // This does not assumes callback functions. Those should be checked outside this and processed separately. 27781 27782 // If already jQuery - only checking length 27783 if ( isJQ(el) ) { 27784 if ( el.length > 0 ) 27785 return el; 27786 27787 return false;
27788 } //IF jQuery given 27789 27790 // If string selector given - searching it within form 27791 // Search on form or FALSE, done this way for optimization 27792 // and to avoid multiple for updates with common class selectors 27793 // If user needs global selector search - he still can pass ready jQuery or use callback 27794 if ( isStr(el) ) { 27795 27796 // Not allowing selector search outside of form. 27797 if ( !this.sourceElement ) 27798 return false; 27799 27800 var j = this.sourceElement.find(el); 27801 27802 // If smth found - we're good to go 27803 if ( j.length > 0 ) 27804 return j; 27805 27806 return false; 27807 } //IF string passsed 27808 27809 // At this point assuming that element is given as DOM element 27810 // Then just wrapping it with jQuery 27811 return jQuery(el); 27812 27813 }, //FUNC getFormElement 27814 27815 /** //** ----= progress =--------------------------------------------------------------------------------------\**//** \ 27816 * 27817 * Progress monitoring event. Triggers on progress update event. Can accept either callbacks or valid jQuery 27818 * selectors (string, jQuery or DOMElement). Callbacks will get current precentage as parameter. In case if 27819 * selector given - for progressBar system will set width, for numeric indicator will set .html(). jQuery selectors 27820 * do not process errors or other status updates, though those will be passed into callbacks. 27821 * 27822 * @param MIXED bar[,num] - Progress bar and numeric bar callbacks or elements to process. 27823 * 27824 * @param bool [force] - Forcing progress event. If set to FALSE system will try to detect if progress 27825 * monitoring is necessary. 27826 * 27827 * @return SELF 27828 * 27829 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 27830 progress : function (bar, num, force) { 27831 27832 this.opt.progress = bar; 27833 this.opt.progressNum = num; 27834 27835 this.opt.progressOn = force || false; 27836 27837 return this; 27838 }, //FUNC progress 27839 27840 /** //** ----= hasProgress =------------------------------------------------------------------------------\**//** \ 27841 * 27842 * For internal use. Checks if need to even setup progress indication. 27843 * 27844 * @return MIXED - jQuery element to use as progress element, or 27845 * 27846 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 27847 hasProgress : function () { 27848 27849 // Nothing to do if nothing is given as progress 27850 if ( !this.opt.progress && !this.opt.progressNum ) 27851 return false; 27852 27853 // Progress is always enabled for callbacks 27854 // ToDo: review this behavior, mb add hasFiles for testing. 27855 27856 // If not callbacks - checking to be jQuery 27857 if ( !isFunction(this.opt.progress) ) 27858 this.opt.progress = this.getFormElement(this.opt.progress); 27859 27860 if ( !isFunction(this.opt.progressNum) ) 27861 this.opt.progressNum = this.getFormElement(this.opt.progressNum); 27862 27863 // Now they are callback, jQuery or just disabled, so fast to check. Enough one of either. 27864 if ( this.opt.progress || this.opt.progressNum ) 27865 return true; 27866 27867 return false; 27868 }, //FUNC hasProgress 27869 27870 /** //** ----= ajaxProgressStart =----------------------------------------------------------------------\**//** \ 27871 * 27872 * Resets progress elements if set. 27873 * 27874 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 27875 ajaxProgressStart : function (proc) { 27876 27877 // If jQuery element set for progress - good to show them 27878 27879 if ( isJQ(this.opt.progress) ) 27880 this.opt.progress.fadeIn(); 27881 27882 if ( isJQ(this.opt.progressNum) ) 27883 this.opt.progressNum.fadeIn(); 27884 27885 this.ajaxProgress(0); 27886 this.progressStart(0); 27887 27888 }, //FUNC ajaxProgressStart 27889 27890 /** //** ----= ajaxProgress =------------------------------------------------------------------------------\**//** \ 27891 * 27892 * Progress event callback. Used on progress monitoring. For internal use, can be altered though. 27893 * 27894 * @param int proc - Current progress precentage. 27895 * 27896 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 27897 ajaxProgress : function (proc) { 27898 27899 // Nothing to do if nothing is given as progress 27900 if ( !this.opt.progress && !this.opt.progressNum ) 27901 return; 27902 27903 // For selectors processing only numeric proc 27904 // Errors and other mess will be processed in callbacks if necessary 27905 27906 // ---- Progress bar ---- 27907 27908 if ( this.opt.progress ) { 27909 27910 // Can be callback or jQuery at this poing 27911 if ( isFunction(this.opt.progress) ) 27912 this.opt.progress(proc); 27913 27914 else if ( isNumeric(proc) ) 27915 this.opt.progress.width(proc + '%'); 27916 27917 } //IF progress given 27918 27919 // ---- Numeric indicator ---- 27920 27921 if ( this.opt.progressNum ) { 27922 27923 // Can be callback or jQuery at this poing 27924 if ( isFunction(this.opt.progressNum) ) 27925 this.opt.progressNum(proc); 27926 27927 else if ( isNumeric(proc) ) 27928 this.opt.progressNum.html( proc != 0 ? proc + '%' : ''); 27929 27930 } //IF progress given 27931 27932 }, //FUNC ajaxProgress 27933
27934 /** //** ----= ajaxProgressStop =------------------------------------------------------------------------------\**//** \ 27935 * 27936 * Forces progress monitoring stop. 27937 * 27938 * @param int proc - Current progress precentage. 27939 * 27940 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 27941 ajaxProgressStop : function (proc) { 27942 27943 if ( this.prgInterval ) 27944 clearInterval(this.prgInterval); 27945 27946 if ( this.prgTimeout ) 27947 clearInterval(this.prgTimeout); 27948 27949 if ( this.hasProgress() ) 27950 this.ajaxProgress(proc); 27951 27952 this.progressStop(proc); 27953 27954 }, //FUNC ajaxProgressStop 27955 27956// ==== Processors ============================================================================================================= 27957 27958 /** //** ----= hasFiles =--------------------------------------------------------------------------------------\**//** \ 27959 * 27960 * Checks if form or data object contains files inputs. 27961 * 27962 * @param jQuery form - Form element to search within. 27963 * 27964 * @return SELF 27965 * 27966 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 27967 hasFiles : function ($source) { 27968 27969 // If jQuery for form given - just searching for file inputs 27970 if ( isJQ($source) ) { 27971 if ( $source.find('INPUT[type=file]').length > 0 ) 27972 return true; 27973 } //IF form given 27974 else { 27975 27976 // Non modern browsers can't have files anyway 27977 if ( !this.isModern ) 27978 return false; 27979 27980 // Looking for files in dataObject 27981 for ( var $i in $source ) { 27982 27983 // Doing className check in addition, 27984 // because of sometimes weird brwosers passing data between windows 27985 if ( $source[$i] instanceof File || getClassOf($source[$i]) === 'File' ) 27986 return true; 27987 } 27988 } //IF dataObject 27989 27990 return false; 27991 }, //FUNC hasFiles 27992 27993 /** //** ----= postArray =------------------------------------------------------------------------------\**//** \ 27994 * 27995 * For internal use. Sends data object using common jQuery ajax. Does not supports progress monitoring 27996 * (no reason for arrays). 27997 * 27998 * @return SELF 27999 * 28000 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 28001 postArray : function () { 28002 28003 var self = this; 28004 28005 this.Method = 'array'; 28006 28007 jQuery.ajax({ 28008 type : 'POST', 28009 dataType : 'text', 28010 async : self.opt.async, 28011 context : self, 28012 url : self.controller, 28013 data : self.sourceData, 28014 success : self.ajaxSuccess, 28015 error : self.ajaxError 28016 }); //OBJECT jQuery.ajax.settings 28017 28018 return this; 28019 }, //FUNC postArray 28020 28021 /** //** ----= postData =--------------------------------------------------------------------------------------\**//** \ 28022 * 28023 * For internal use. Sends data using formData object. Optionally uses xhr for progress monitoring. 28024 * 28025 * @return SELF 28026 * 28027 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 28028 postData : function () { 28029 28030 var self = this; 28031 var post = false; 28032 var $form = this.sourceForm ? _jq(this.sourceForm) : false; 28033 var $files = false; 28034 28035 // Marking method as data 28036 this.Method = 'data'; 28037 28038 // Disabling empty files if happen on form 28039 // Doing this to fix XHR multipart bug in some Safari versions 28040 // https://bugs.webkit.org/show_bug.cgi?id=184490 28041 28042 if ( $form ) { 28043 28044 // Looking for non disabled file inputs 28045 $files = $form.find('input[type="file"]:not([disabled])'); 28046 $files.each( function () { 28047 28048 // Disabling input 28049 if ( this.files.length == 0 ) 28050 jQuery(this).prop('disabled', true); 28051 28052 }); //each file 28053 28054 } //IF form provided 28055 28056 // Need to generate FormData object 28057 // Creating FormData from form, if one given 28058 // Or using one if one come as sourceData 28059 // Otherwise generating one from dataObject 28060 28061 if ( this.sourceData instanceof FormData ) { 28062 post = this.sourceData 28063 }
28063 //IF sourceData is FormData 28064 else if ( this.sourceForm ) { 28065 post = new FormData(this.sourceForm); 28066 } //IF form given 28067 else { 28068 post = new FormData(); 28069 for ( var $i in this.sourceData ) 28070 post.append($i, this.sourceData[$i]); 28071 } //IF dataObject given 28072 28073 // Restoring disabled file inputs (see bugfix above) 28074 if ( $files ) 28075 $files.prop('disabled', false); 28076 28077 // Sending ajax using custom XHR 28078 jQuery.ajax({ 28079 type : 'POST', 28080 dataType : 'text', 28081 async : self.opt.async, 28082 context : self, 28083 url : self.controller, 28084 data : post, 28085 success : self.ajaxSuccess, 28086 error : self.ajaxError, 28087 28088 // Disablong jQuery headers and source processing 28089 contentType : false, 28090 processData : false, 28091 28092 // Adding progress monitoring, upload listener will be added optionally if necessary 28093 // With function wrapper to have proper this 28094 xhr : function () { return self.ajaxXHR() } 28095 }); //OBJECT jQuery.ajax.settings 28096 28097 return this; 28098 28099 }, //FUNC postData 28100 28101 /** //** ----= postFrame =------------------------------------------------------------------------------\**//** \ 28102 * 28103 * For internal use. Sends data using iframe send trick. Used to simulate ajax upload on classic systems. 28104 * Uses ajaxupload jQuery plugin if available. Uses server side progress monitoring if necessary. 28105 * 28106 * @return SELF 28107 * 28108 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 28109 postFrame : function () { 28110 28111 var self = this; 28112 28113 this.Method = 'frame'; 28114 28115 if ( !self.sourceForm ) 28116 throw('Source form is not set.'); 28117 28118 // ---- Setting up progress ---- 28119 28120 // Saving test result, for later reuse 28121 var prg = this.opt.progressUrl && this.hasProgress(); 28122 28123 if ( prg ) { 28124 28125 var sn = 'PRG' + randomString(); 28126 28127 // Adding additional inputs for monitoring on server side 28128 this.sourceElement.append('<input type="hidden" name="UPLOAD_IDENTIFIER" value="' + sn + '" />'); 28129 this.sourceElement.append('<input type="hidden" name="APC_UPLOAD_PROGRESS" value="' + sn + '" />'); 28130 28131 // Resetting filler 28132 this.ajaxProgressStart(); 28133 28134 } //IF progress is set 28135 28136 // ---- Posting ---- 28137 28138 // Saving action and target, cuz ajaxUpload breaks them sometimes 28139 var action = this.sourceForm.action; 28140 var target = this.sourceForm.target; 28141 28142 jQuery.ajaxUpload ({ 28143 type : 'POST', 28144 dataType : 'text', 28145 url : self.controller, 28146 secureuri : false, 28147 uploadform : self.sourceForm, 28148 // Simulating context with wrappers 28149 success : function ( res, status ) { self.ajaxSuccess(res, status) }, 28150 error : function ( res, status ) { self.ajaxError(res, status) } 28151 }); //AJAX 28152 28153 // ---- Monitoring progress ---- 28154 28155 if ( prg ) { 28156 28157 // Bar should start progressing with additional delay, to do not overflow on small files 28158 self.prgTimeout = setTimeout( function () { 28159 28160 // Adding check timer 28161 self.prgInterval = setInterval( function() { 28162 28163 jQuery.get(self.opt.progressUrl + sn, {}, function(data) { 28164 28165 self.ajaxProgress(data, self); 28166 28167 // If got 100 or error - stopping timer 28168 if ( data == '100' || !isNumeric(data) ) { 28169 clearInterval(self.prgInterval); 28170 } //IF done 28171 28172 }); //FUNC jQuery.get.callback 28173 28174 }, self.opt.progressInterval); //FUNC setInterval.callback 28175 }, self.opt.progressDelay); //FUNC setTimeout.callback 28176 28177 // Cleaning progress inputs 28178 this.sourceElement.find('INPUT[name="APC_UPLOAD_PROGRESS"], INPUT[name="UPLOAD_IDENTIFIER"]').remove(); 28179 } //IF progress set 28180 28181 // ---- Cleaning form ---- 28182 28183 this.sourceForm.action = action; 28184 this.sourceForm.target = target; 28185 28186 return this; 28187 }, //FUNC postFrame 28188 28189 /** //** ----= post =--------------------------------------------------------------------------------------\**//** \ 28190 * 28191 * Fires request with settings given. 28192 * 28193 * @return SELF 28194 * 28195 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 28196 post : function () { 28197 28198 // ---- Checking source ---- 28199 28200 var source = this.source; // Just shortcut 28201 28202 // Making sure that there is smth meaningfull 28203 if ( !source ) 28204 source = {}; 28205 28206 // Restting sources 28207 this.sourceElement = false; // jQuery pointer to form element 28208 this.sourceForm = false; // DOM form element 28209 this.sourceData = source; // By default assuming data object or formData 28210
28211 // Converting jQuery selector to jQuery 28212 if ( typeof this.source == 'string' ) 28213 source = jQuery(this.source); 28214 28215 // Getting DOM form from jQuery 28216 if ( source instanceof jQuery ) { 28217 28218 if ( source.length < 1 ) 28219 throw('Source form is not found.'); 28220 28221 // Saving jQuery 28222 this.sourceElement = source; 28223 source = source.get(0); 28224 } //IF got jQuery 28225 28226 // At this step source should be either DOM form or data object 28227 // Checking it and setting sources 28228 // ToDo: tricky check for DOM form, improove 28229 if ( source.elements ) { 28230 28231 // Trying to correct url using form action 28232 if ( !this.controller ) 28233 this.controller = source.action; 28234 28235 this.sourceForm = source; 28236 28237 // Serializing form as array anyway for callbacks 28238 this.sourceData = formToArray(source); 28239 28240 // Adding jQuery if not already there 28241 if ( !this.sourceElement ) 28242 this.sourceElement = jQuery(source); 28243 28244 } //If got form 28245 28246 // ---- Testing environment ---- 28247 28248 // If still no controller (even after from action correction) - nothing to do 28249 if ( !this.controller ) 28250 throw('Destination url is not set.'); 28251 28252 // ---- Selecting method and sending ---- 28253 28254 // Triggering start event, passing self as param 28255 this.start(this); 28256 28257 // In most cases postData will be used 28258 // Only reason to use tricky frame ajaxUpload is in old browser 28259 // and files really present on form 28260 // Of course if ajaxUpload is available 28261 // So checking it in complexity order i.e. easyer checks goes first 28262 28263 // Checking if custom processor is given 28264 if ( isFunction(this._processor) ) { 28265 this._processor(this); 28266 return this; 28267 } //IF custom processor 28268 28269 // Form data is always served with postData 28270 if ( this.isModern && this.sourceData instanceof FormData ) 28271 return this.postData(); 28272 28273 // If form or files were not given uploading with common jQuery 28274 // Non modern browser can't have files anyway 28275 if ( !this.sourceForm && !this.hasFiles(this.sourceData) ) 28276 return this.postArray(); 28277 28278 // If modern - using formData for all other cases 28279 if ( this.isModern ) 28280 return this.postData(); 28281 28282 // If form is not for files, and modern uploading is not available - uploading as array 28283 if ( this.sourceForm.enctype != 'multipart/form-data' ) 28284 return this.postArray(); 28285 28286 // Now looking for files on form (last chance to not use .postFrame() ) 28287 if ( !this.hasFiles(this.sourceElement) ) 28288 return this.postArray(); 28289 28290 // Finally we tried everything, have to use ajaxUpload 28291 // Testing if ajaxUpload even exists first 28292 if ( !isSet(jQuery.ajaxUpload) ) 28293 throw('Can\'t upload files with ajax on this browser.'); 28294 28295 return this.postFrame(); 28296 } //FUNC post 28297 28298 }); //OBJECT vAjax 28299 28300 // Setting options on startup 28301 obj.options(options); 28302 28303 return obj; 28304 28305} //CONSTRUCTOR vAjax 28306 28307// #### DEPRECATED ############################################################################################################# 28308 28309var ajaxReturn = function (status_place, destination) { 28310 if (status_place) this.statusPlace = status_place; 28311 if (destination) this.controller = destination; 28312} //CONSTRUCTOR ajaxReturn 28313 28314ajaxReturn.prototype = { 28315 controller : '', 28316 post : {}, 28317 ModalDialog : '', 28318 ModalLoader : '', 28319 statusPlace : '', 28320 28321 onSuccess : function (data) {}, 28322 onError : function (data) {}, 28323 onFail : function (data) {}, 28324 onSimple : function (data) {}, 28325 onStart : function () {}, 28326 onStatus : function (html) {}, 28327 onProgress : function (proc) {}, 28328 28329 parseResult : function (result) { 28330 28331 var res = {}; 28332 res._post = this.post; 28333 28334 var data = result.split('-=-CUT-=-'); 28335 res._message = data[0]; 28336 if ( !res._message ) res._message = ''; 28337 28338 res._fullhead = data.length != 1; 28339 28340 if (res._fullhead) { 28341 var head = JSON.parse(data[1]); 28342 res._major = head.major; 28343 res._minor = head.minor; 28344 res._status = head.minor; 28345 res._fields = head.fields; 28346// res.data = []; 28347 var di = 2; 28348 if ( res._fields.length != 0 ) { 28349 for (i = 0; i < res._fields.length; i++) { 28350 res[res._fields[i]] = data[di]; 28351 di++; 28352 } //FOR each field 28353 } //IF was fields posted 28354 } //IF was full result 28355 return res; 28356 },//FUNC parseResult 28357 28358 /*--------------------------------------------------------------------------------*\ 28359 | DoStatus 28360 |---------------------------------------------------------------------------------- 28361 | Updates status. 28362 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 28363 | Params: 28364 | message string - Status message to display. 28365 | callback funciton - Funciton to call. 28366 | data MIXED - Data to pass to callback function. 28367 | Return: 28368 | bool - ALways FALSE. 28369 \*--------------------------------------------------------------= by Mr.V!T =-----*/ 28370 DoStatus : function (message, callback, data) { 28371 28372 if ( this.statusPlace && message ) jQuery('#'+this.statusPlace).html( status_string(message) ); 28373 28374 if ( callback instanceof Function ) callback(data); 28375 28376 this.doModals('finish'); 28377 28378 return false;
28379 }, //FUNC DoStatus 28380 28381 ajax_success : function (res) { 28382 var data = this.parseResult(res); 28383 28384 if (this.statusPlace) jQuery('#'+this.statusPlace).html(data._message); 28385 28386 var cb = this.onSimple; 28387 if ( data._fullhead ) 28388 cb = ( data._major )? this.onSuccess : this.onError; 28389 28390 this.DoStatus('', cb, data); 28391 28392 }, //FUNC sucess 28393 28394 ajax_error : function (message, res) { 28395 28396 this.DoStatus(message, this.onFail, res); 28397 28398 }, //FUNC error 28399 28400 postForm : function (form_id) { 28401 var _ar = this; 28402 28403 if (!_ar.controller) return this.DoStatus('Invalid destination. Aborting.'); 28404 28405 if ( !form_id ) return this.postData(); 28406 28407 var form = (form_id.elements)? form_id : document.getElementById(form_id); 28408 if ( !form.elements ) return this.DoStatus('Can\'t find data to POST. Aborting.'); 28409 28410 if ( form.enctype != 'multipart/form-data' ) return this.postData( formToArray(form) ); 28411 28412 //if ( _ar.statusPlace ) insert_bar(_ar.statusPlace); 28413 28414 this.doModals('start'); 28415 28416 this.onStart(); 28417 28418 var old_action = form.action; 28419 28420 jQuery.ajaxUpload ({ 28421 type : 'POST', dataType : 'html', 28422 url : _ar.controller, 28423 secureuri : false, 28424 uploadform : form, 28425 success : function (res) { 28426 _ar.ajax_success(res); 28427 }, //FUNC success 28428 error : function (res, status) { 28429 _ar.ajax_error(res.statusText, res.responseText); 28430 } //FUNC error 28431 }); //AJAX 28432 28433 form.action = old_action; 28434 form.target = ''; 28435 28436 return false; 28437 }, //FUNC postForm 28438 28439 postData : function (post_data) { 28440 28441 if ( !post_data ) post_data = {}; 28442 28443 // post_data = arrayToPost(post_data); 28444 28445 this.post = post_data; 28446 var _ar = this; 28447 28448 //if ( _ar.statusPlace ) insert_bar(_ar.statusPlace); 28449 28450 this.doModals('start'); 28451 28452 if (!_ar.controller) return this.DoStatus('Invalid destination. Aborting.'); 28453 28454 this.onStart(); 28455 28456 jQuery.ajax({ 28457 type : 'POST', dataType: 'html', 28458 url : _ar.controller, 28459 data : post_data, 28460 success : function (res) { 28461 _ar.ajax_success(res); 28462 }, //FUNC success 28463 error : function (res, status) { 28464 _ar.ajax_error(res.statusText, res.responseText); 28465 } //FUNC error 28466 }); //AJAX 28467 28468 return false; 28469 }, //FUNC postData 28470 28471 postFormData : function (post_data) { 28472 28473 this.post = post_data; 28474 var _ar = this; 28475 var self = this; 28476 28477 this.doModals('start'); 28478 28479 if (!_ar.controller) return this.DoStatus('Invalid destination. Aborting.'); 28480 28481 this.onStart(); 28482 28483 jQuery.ajax({ 28484 type : 'POST', dataType: 'html', 28485 url : _ar.controller, 28486 data : post_data, 28487 contentType : false, 28488 processData : false, 28489 28490 success : function (res) { 28491 _ar.ajax_success(res); 28492 }, //FUNC success 28493 28494 error : function (res,status) { 28495 _ar.ajax_error(res.statusText, res.responseText); 28496 }, //FUNC error 28497 28498 // Attempting to alter xhr to add progress listener 28499 xhr : function() { 28500 28501 var req = $.ajaxSettings.xhr(); 28502 28503 if (req) { 28504 28505 req.upload.addEventListener('progress', function(e) { 28506 28507 if ( e.lengthComputable ) { 28508 var proc = (e.loaded * 100) / e.total; 28509 28510 self.onProgress( Math.floor(proc) ); 28511 28512 } //IF there is progress available 28513 28514 }, false); //FUNC XHR.upload.onProgress 28515 28516 } //IF xhr returned 28517 28518 return req; 28519 } //FUNC xhr 28520 28521 }); //AJAX 28522 28523 return false; 28524 }, //FUNC postFormData 28525 28526 /*--------------------------------------------------------------------------------*\need 28527 | post 28528 |---------------------------------------------------------------------------------- 28529 | Autoselects best post method and posts source. 28530 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 28531 | Params: 28532 | source MIXED - Data source. 28533 | Return: 28534 | bool - Always FALSE. 28535 \*--------------------------------------------------------------= by Mr.V!T =-----*/ 28536 post : function (source) { 28537 28538 if ( typeof source == 'string' ) return this.postForm(source); 28539 if ( source.elements ) return this.postForm(source); 28540 28541 if ( source instanceof FormData ) return this.postFormData(source); 28542 28543 return this.postData(source); 28544 }, //FUNC post 28545 28546 /*--------------------------------------------------------------------------------*\ 28547 | setModals 28548 |---------------------------------------------------------------------------------- 28549 | Set modal windows parameters. 28550 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 28551 | Params: 28552 | dialog string - ID of window to use as Dialog. 28553 | loader string - ID of window to use as loader window. 28554 | Return: 28555 | SELF 28556 \*--------------------------------------------------------------= by Mr.V!T =-----*/ 28557 setModals : function (dialog, loader) { 28558 28559 this.ModalDialog = dialog; 28560 28561 if ( !loader ) return this; 28562
28563 tmp = document.getElementById(loader); 28564 if ( !tmp ) return this; 28565 28566 this.ModalLoader = loader; 28567 28568 return this; 28569 }, //FUNC setModals 28570 28571 /*--------------------------------------------------------------------------------*\ 28572 | doModals 28573 |---------------------------------------------------------------------------------- 28574 | Displays or hides modals windows. 28575 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 28576 | Params: 28577 | mode string - Status mode: 28578 | 'start' - Set starting mode. 28579 | *other* - Finished mode. 28580 | Return: 28581 | NULL 28582 \*--------------------------------------------------------------= by Mr.V!T =-----*/ 28583 doModals : function ( mode ) { 28584 28585 if ( mode == 'start' ) { 28586 if ( this.ModalLoader ) { 28587 jQuery('#'+this.ModalDialog).jqm(); 28588 jQuery('#'+this.ModalDialog).jqmHide(); 28589 jqmShowCentered('#'+this.ModalLoader); 28590 } //IF loader is set 28591 28592 if ( this.ModalDialog && !this.ModalLoader ) jqmShowCentered('#'+this.ModalDialog); 28593 } else { //IF 28594 if ( this.ModalLoader ) jQuery('#'+this.ModalLoader).jqmHide(); 28595 if ( this.ModalDialog ) jqmShowCentered('#'+this.ModalDialog); 28596 } //IF 28597 28598 } //FUNC doModals 28599 28600} //CLASS ajaxReturn 28601 28602/** ************************************************************************************************************************ **\ 28603* 28604* Set of classes and functions that will help create debugging consoles. 28605* 28606* @package VIT-Lib 28607* @subpackage Debug 28608* 28609* @license MIT License 28610* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 28611* associated documentation files (the "Software"), to deal in the Software without restriction, including 28612* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 28613* copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to 28614* the following conditions: 28615* 28616* The above copyright notice and this permission notice shall be included in all copies or substantial 28617* portions of the Software. 28618* 28619* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 28620* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 28621* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 28622* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 28623* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28624* 28625* @author Victor Denisenkov aka Mr.V!T 28626* @copyright Copyright (c) 2008+ Victor Denisenkov aka Mr.V!T 28627* @version 1.0 28628* 28629\** ************************************************************************************************************************ **/ 28630 28631/** //** ----= OBJECT vConsole =--------------------------------------------------------------------------------------\**//** \ 28632* 28633* Debug console. 28634* 28635* @package VIT-Lib 28636* @subpackage Debug 28637* @category Helper 28638* 28639\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 28640function vConsole ($options) { 28641 28642var $class = { 28643 28644 enabled : true, // Working state. If disabled - doing nothing, untill it's manually enabled. 28645 28646 width : 600, // Default widndow width 28647 zIndex : 6000, // zIndex to use for window 28648 28649 panels : {}, // Custom panels list and their properties/elements 28650 28651 dom : { // Set of valuable elements as jQuery shortcuts and dom elements 28652 window : false, // Main window object 28653 panels : false, // Panels container (dumps watches) 28654 console : false, // Common console (manual dumps) 28655 }, //dom 28656 28657 autoupdate : false, // Set TRUE to enable watch timer. It will cause updates of watched elements in specified inteval. 28658 updateInterval : 70, // Autoupdate interval. Lower value - more lag, but more accurate readings. 28659 updateDelay : 1, // Delay in ms between nearest updates. Increase if updates cause lags. 28660 // Having even 1ms, causes another thread exec, and multiupdates filetering. 28661 28662 interval : false, // Autoupdate interval object 28663 timer : false, // Update delay timer object 28664 28665 dumper : false, // Variable dumper used to style debug 28666 28667// ==== SET/GET ================================================================================================================ 28668 28669 /** //** ----= set =--------------------------------------------------------------------------------------\**//** \ 28670 * 28671 * Initiates self parameters from given options array.
28672 * 28673 * @return SELF 28674 * 28675 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 28676 set : function ($name, $value) { 28677 28678 // ToDo: .set() in basic class 28679 // ToDo: proper events extension support 28680 28681 var $o = {}; 28682 28683 // Extending from object, so if pair given - forming object from there 28684 // Otherwise name is needed object 28685 if ( isStr($name) ) 28686 $o[$name] = $value; 28687 else 28688 $o = $name; 28689 28690 jQuery.extend(this, $o); 28691 28692 // init/deinit 28693 if ( this.enabled ) 28694 this.init(); 28695 else 28696 this.deinit(); 28697 28698 return this; 28699 }, //FUNC set 28700 28701 /** //** ----= get =--------------------------------------------------------------------------------------\**//** \ 28702 * 28703 * Returns property. 28704 * 28705 * @return SELF 28706 * 28707 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 28708 get : function ($name) { 28709 // ToDo: .get() in basic class with getters support 28710 // ToDo: proper events extension support 28711 return this[$name]; 28712 }, //FUNC get 28713 28714 /** //** ----= toggle =--------------------------------------------------------------------------------------\**//** \ 28715 * 28716 * Toggles console. 28717 * 28718 * @return SELF 28719 * 28720 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 28721 toggle : function ($state) { 28722 28723 if ( isUndefined($state) ) 28724 $state = !this.enabled; 28725 28726 return this.set('enabled', $state); 28727 }, //FUNC toggle 28728 28729 /** //** ----= show =--------------------------------------------------------------------------------------\**//** \ 28730 * 28731 * Shows console. 28732 * 28733 * @return SELF 28734 * 28735 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 28736 show : function () { 28737 return this.toggle(true); 28738 }, //FUNC show 28739 28740 /** //** ----= hide =--------------------------------------------------------------------------------------\**//** \ 28741 * 28742 * Hides console. 28743 * 28744 * @return SELF 28745 * 28746 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 28747 hide : function () { 28748 return this.toggle(false); 28749 }, //FUNC hide 28750 28751// ==== INIT =================================================================================================================== 28752 28753 /** //** ----= init =--------------------------------------------------------------------------------------\**//** \ 28754 * 28755 * Initiates console, creates panels and prepares for output. 28756 * 28757 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 28758 init : function () { 28759 28760 // Setting up dumper 28761 if ( isEmpty(this.dumper) ) 28762 this.dumper = vDump({ 28763 'useHtml' : true, 28764 'dumpFunctions' : false 28765 }); //vDump 28766 28767 // Initiating elements 28768 this.initWindow(); 28769 this.initPanels(); 28770 28771 // Initial update, which will also console with info 28772 this.update(); 28773 28774 // Triggering autoupdate if necessary 28775 this.setAutoupdate(this.autoupdate); 28776 }, //FUNC init 28777 28778 /** //** ----= deinit =--------------------------------------------------------------------------------------\**//** \ 28779 * 28780 * Deinitiates console, removes dom and stops timers. 28781 * 28782 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 28783 deinit : function () { 28784 28785 // Removing dumper 28786 this.dumper = false; 28787 28788 // Removing elements 28789 this.deinitPanels(); 28790 this.deinitWindow(); 28791 28792 // Updating autoupdate :) 28793 this.setAutoupdate(this.autoupdate); 28794 }, //FUNC deinit 28795 28796// ==== DOM ==================================================================================================================== 28797 28798 /** //** ----= initWindow =------------------------------------------------------------------------------\**//** \ 28799 * 28800 * Initiates main window and common panel. 28801 * 28802 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 28803 initWindow : function () { 28804 28805 // Checking if draggable available 28806 var $isDraggable = isFunction(jQuery().draggable); 28807 28808 // Compiling window css (it is updated anyway) 28809 var $css = { 28810 'position' : 'fixed', 28811 28812 'left' : 0, 28813 'top' : 0, 28814 'width' : this.width, 28815 28816 'z-index' : 6000, 28817 'cursor' : $isDraggable ? 'move' : 'default', 28818 }; // $css 28819 28820 // Creating window, or updating if created 28821 if ( this.dom.window ) { 28822 28823 this.dom.window.css($css); 28824 28825 } else { 28826 28827 this.dom.window = jQuery('<div class="debug"></div>').css($css); 28828 28829 // Creating common console wrapper 28830 this.dom.console = jQuery('<div></div>') 28831 // .css({'overflow' : 'scroll'}) //css 28832 .appendTo(this.dom.window) 28833 ; //jQuery.debug 28834 28835 // Making window draggable if possible 28836 if ( $isDraggable ) 28837 this.dom.window 28838 .draggable('destroy') 28839 .draggable({}); 28840 28841 this.dom.window.appendTo('body'); 28842 } //IF new window 28843 28844 }, //FUNC initWindow 28845 28846 /** //** ----= deinitWindow =------------------------------------------------------------------------------\**//** \ 28847 * 28848 * Deinitiates main window. 28849 * 28850 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 28851 deinitWindow : function () { 28852 28853 // Nothing to do if removed already 28854 if ( !this.dom.window ) 28855 return; 28856 28857 // Destroying draggable 28858 if ( this.dom.window.is('.ui-draggable') ) 28859 this.dom.window.draggable('destroy'); 28860 28861 // Removing window element 28862 this.dom.window.remove(); 28863 28864 // Cleaning self 28865 this.dom.window = false;
28866 28867 }, //FUNC deinitWindow 28868 28869// ---- PANELS ----------------------------------------------------------------------------------------------------------------- 28870 28871 /** //** ----= initPanels =------------------------------------------------------------------------------\**//** \ 28872 * 28873 * Initiates panels. 28874 * 28875 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 28876 initPanels : function () { 28877 28878 // Creating panels wrapper 28879 if ( !this.dom.panels ) 28880 this.dom.panels = jQuery('<div></div>') 28881 // .css({}) //css 28882 .prependTo(this.dom.window) 28883 ; //jQuery.debug 28884 28885 // Adding/updating custom panels, converting ones which given as arrays 28886 for ( var $i in this.panels ) 28887 if ( isArray(this.panels[$i]) ) 28888 this.setPanel($i); 28889 else 28890 this.initPanel(this.panels[$i]); 28891 28892 }, //FUNC initPanels 28893 28894 /** //** ----= deinitPanels =------------------------------------------------------------------------------\**//** \ 28895 * 28896 * Initiates panels. 28897 * 28898 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 28899 deinitPanels : function () { 28900 28901 // Nothing to do if no panels already 28902 if ( !this.dom.panels ) 28903 return; 28904 28905 // Clearing panels 28906 for ( var $i in this.panels ) 28907 this.deinitPanel(this.panels[$i]); 28908 28909 // Removing element 28910 this.dom.panels.remove(); 28911 28912 // Cleaning self 28913 this.dom.panels = false; 28914 28915 }, //FUNC deinitPanels 28916 28917 /** //** ----= setPanel =--------------------------------------------------------------------------------------\**//** \ 28918 * 28919 * Adds named debug panel. 28920 * 28921 * @param string $name - Panel name to add. 28922 * @param int [$size] - Panel relative size (width) percentage. 28923 * @param object [$watchObject] - Object to watch in this panel. 28924 * @param array [$watchProps] - Watch only this properties from this object. 28925 * 28926 * @return SELF 28927 * 28928 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 28929 setPanel : function ($name, $size, $watchObject, $watchProps) { 28930 28931 // Checking for panel params 28932 var $panel = this.panels[$name] || {}; 28933 28934 // Converting array 28935 if ( isArray($panel) ) { 28936 // Setting params from that array 28937 $size = $size || $panel[0]; 28938 $watchObject = $watchObject || $panel[1]; 28939 $watchProps = $watchProps || $panel[2]; 28940 28941 // Making sure it's object now, and resetting 28942 $panel = {}; 28943 } //IF array given 28944 28945 // Setting up 28946 $panel.name = $name; 28947 $panel.title = $name.capitalize(); 28948 $panel.size = $size || 100; 28949 $panel.watch = $watchObject || false; 28950 $panel.props = $watchProps || false; 28951 28952 // Resaving panel back, in case it's new 28953 this.panels[$name] = $panel; 28954 28955 // Done if not enabled 28956 if ( !this.enabled ) 28957 return this; 28958 28959 // Initiating panel 28960 this.initPanel($panel); 28961 28962 return this; 28963 }, //FUNC setPanel 28964 28965 /** //** ----= removePanel =------------------------------------------------------------------------------\**//** \ 28966 * 28967 * Removes specified panel from console. 28968 * 28969 * @param string $panel - Panel name to remove. 28970 * 28971 * @return SELF 28972 * 28973 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 28974 removePanel : function ($panel) { 28975 28976 if ( !this.panels[$panel] ) 28977 return; 28978 28979 // Deinitiating it first 28980 this.deinitPanel(this.panels[$panel]); 28981 28982 // Removing from list 28983 delete(this.panels[$panel]); 28984 28985 return this; 28986 }, //FUNC removePanel 28987 28988 /** //** ----= initPanel =------------------------------------------------------------------------------\**//** \ 28989 * 28990 * Initiates given panel dom and events. 28991 * 28992 * @param object $panel - Panel to init. Should be link from internal .panels list. 28993 * 28994 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 28995 initPanel : function ($panel) { 28996 28997 // Checking if panel should take full size or it's floating 28998 var $isFull = $panel.size == 100; 28999 29000 // Compiling css 29001 var $css = { 29002 'float' : $isFull ? 'none' : 'left', 29003 'clear' : $isFull ? 'both' : 'none', 29004 'width' : $isFull ? 'auto' : $panel.size+'%', 29005 'overflow' : 'hidden', 29006 'border-bottom' : '1px solid gray', 29007 } // $css 29008 29009 // Creating or updating element 29010 if ( $panel.el ) { 29011 29012 $panel.el.css($css); 29013 29014 } else { //IF existing panel 29015 29016 $panel.el = jQuery('<div></div>') 29017 .css($css) //css 29018 .appendTo(this.dom.panels) 29019 ; //jQuery.$panel 29020 29021 } //IF new panel 29022 29023 }, //FUNC initPanel 29024 29025 /** //** ----= deinitPanel =------------------------------------------------------------------------------\**//** \ 29026 *
29027 * Initiates given panel dom and events. 29028 * 29029 * @param object $panel - Panel to deinit. Should be link from internal .panels list. 29030 * 29031 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 29032 deinitPanel : function ($panel) { 29033 29034 if ( !$panel.el ) 29035 return; 29036 29037 // Removing panel from dom 29038 $panel.el.remove(); 29039 29040 // Cleaning panel element 29041 $panel.el = false; 29042 29043 }, //FUNC deinitPanel 29044 29045// ==== DUMP =================================================================================================================== 29046 29047 /** //** ----= dumpTo =--------------------------------------------------------------------------------------\**//** \ 29048 * 29049 * Dumps given var into specified console panel (replaces contents). Uses delays to output. 29050 * Precise output: no output delay. 29051 * 29052 * @param string $panel - Panel name to input into. 29053 * @param MIXED $var - Variable to dump 29054 * 29055 * @return SELF 29056 * 29057 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 29058 dumpTo : function ($panel, $var) { 29059 29060 // Doing nothing if not enabled 29061 if ( !this.enabled ) 29062 return this; 29063 29064 // Panel can be ether string or object directly 29065 if ( isStr($panel) ) 29066 $panel = this.panels[$panel]; 29067 29068 if ( !$panel || !$panel.el ) 29069 return this; 29070 29071 $panel.el.html( this.dumper.dumpCap($panel.title, $var) ); 29072 29073 return this; 29074 }, //FUNC dumpTo 29075 29076 /** //** ----= dump =--------------------------------------------------------------------------------------\**//** \ 29077 * 29078 * Dumps given var into common console panel (adds at bottom). 29079 * Precise output: no output delay. 29080 * 29081 * @param MIXED $var - Variable to dump 29082 * 29083 * @return SELF 29084 * 29085 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 29086 dump : function ($var) { 29087 29088 // Doing nothing if not enabled 29089 if ( !this.enabled ) 29090 return this; 29091 29092 var $con = this.dom.console; 29093 $con.html( $con.html() + this.dumper.dump($var) ); 29094 29095 return this; 29096 }, //FUNC dump 29097 29098 /** //** ----= clear =--------------------------------------------------------------------------------------\**//** \ 29099 * 29100 * Clears common panel contents. 29101 * Precise output: no output delay. 29102 * 29103 * @return SELF 29104 * 29105 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 29106 clear : function () { 29107 29108 // Doing nothing if not enabled 29109 if ( !this.enabled ) 29110 return this; 29111 29112 var $con = this.dom.console; 29113 $con.html(''); 29114 29115 return this; 29116 }, //FUNC clear 29117 29118// ---- UPDATES ---------------------------------------------------------------------------------------------------------------- 29119 29120 /** //** ----= updateNow =------------------------------------------------------------------------------\**//** \ 29121 * 29122 * Imideately updates watched objects (no update delay). 29123 * 29124 * @return SELF 29125 * 29126 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 29127 updateNow : function () { 29128 29129 // Doing nothing if not enabled 29130 if ( !this.enabled ) 29131 return this; 29132 29133 // Checking panels, which can be updated 29134 for ( var $i in this.panels ) { 29135 var $panel = this.panels[$i]; 29136 29137 // Skipping if panel was not created somehow 29138 if ( !$panel.el ) 29139 continue; 29140 29141 // Skipping if not watchable 29142 if ( $panel.watch === false ) 29143 continue; 29144 29145 // Dumping whole object if no props specified 29146 if ( $panel.props === false ) { 29147 // Just dump into panel 29148 $panel.el.html( this.dumper.dumpCap($panel.title, $panel.watch) ); 29149 } else { //IF whole object 29150 29151 var $html = ''; 29152 29153 // Looping through all vars and compiling dump 29154 for ( var $j in $panel.props ) { 29155 29156 var $p = $panel.props[$j]; 29157 29158 // Skipping functions 29159 if ( isFunction($p) ) 29160 continue; 29161 29162 $html += this.dumper.dumpCap($p.capitalize(), $panel.watch[$p]); 29163 } //FOR each $j 29164 29165 $panel.el.html( $html ); 29166 } //IF properties specified 29167 29168 } //FOR each panel 29169 29170 return this; 29171 }, //FUNC updateNow 29172 29173 /** //** ----= update =--------------------------------------------------------------------------------------\**//** \ 29174 * 29175 * Updates watched objects, with small delay (no lag update). 29176 * 29177 * @return SELF 29178 * 29179 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 29180 update : function () { 29181 29182 // Doing nothing if not enabled 29183 if ( !this.enabled ) 29184 return this; 29185
29186 var $this = this; 29187 29188 // Clearing prev delay, avoiding double updates 29189 clearTimeout(this.timer); 29190 29191 // Updating after small delay 29192 this.timer = setTimeout( function () { 29193 $this.updateNow(); 29194 }, this.updateDelay); 29195 29196 return this; 29197 }, //FUNC update 29198 29199 /** //** ----= setAutoupdate =------------------------------------------------------------------------------\**//** \ 29200 * 29201 * Enables or disables autoupdate timer. Always disables if console disabled 29202 * 29203 * @param bool $state - Set TRUE to enable, FALSE otherwise. 29204 * 29205 * @return SELF 29206 * 29207 \**//** --------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 29208 setAutoupdate : function ($state) { 29209 29210 $state = !isEmpty($state); 29211 var $this = this; 29212 29213 this.autoupdate = $state; 29214 29215 // Clearing interval anyway, to be extra safe 29216 clearInterval(this.interval); 29217 29218 // Nothing to do if no autoupdate 29219 if ( !this.enabled || !this.autoupdate ) 29220 return this; 29221 29222 // Making sure update interval is bigget that delay 29223 var $upd = this.updateInterval > this.updateDelay ? this.updateInterval : this.updateDelay + 5; 29224 29225 // Setting up interval 29226 this.interval = setInterval( function () { 29227 $this.update(); 29228 }, $upd); 29229 29230 return this; 29231 }, //FUNC setAutoupdate 29232 29233}; //CLASS mwImgEd 29234 29235 // Applying options 29236 $class.set($options); 29237 29238 // Adding events 29239 $class = vEventObject([], $class); 29240 29241 return $class; 29242} //CONSTRUCTOR vConsole 29243 29244CMS_ALIAS = 'cms3t';CMS_RES = 'res';CMS_JS = 'js';CMS_CSS = 'css';CMS_IMAGES = 'images'; 29245/** //** ----= CLASS mwUrl =--------------------------------------------------------------------------------------\**//** \ 29246* 29247* Morweb urls compilation helper. 29248* 29249* @package Morweb 29250* @subpackage Core 29251* @category helper 29252* 29253\**//** ---------------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 29254function mwUrl ($section) { 29255return { 29256 29257 section : $section || false, // Sectional url. Set TRUE for sectional core resoureces (applicable only for resources). 29258 _full : false, // Set TRUE to generate full url (inluding protocol and domain). Usefull for emails and standalone pages. 29259 _ssl : null, // HTTPS use for full urls, set TRUE to force, FALSE to force non SSL, NULL (default) for autodetect. 29260 _salt : false, // Set TRUE or give random string value to prevent browser caching, adding salt to url. 29261 29262/* ==== SETUP =============================================================================================================== */ 29263 29264 /** //** ----= full =--------------------------------------------------------------------------------------\**//** \ 29265 * 29266 * Full mode switcher. 29267 * 29268 * @param bool [$value] - Value to set. 29269 * @param bool [$ssl] - Force ssl usage. 29270 * 29271 * @return SELF 29272 * 29273 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 29274 full : function ($value, $ssl) { 29275 29276 $value = setDefault($value, true); 29277 29278 this._full = $value; 29279 this._ssl = $ssl; 29280 29281 return this; 29282 }, //FUNC full 29283 29284 /** //** ----= salt =--------------------------------------------------------------------------------------\**//** \ 29285 * 29286 * Initiates url salting. Use with precaution - this dastically slows down site loading speed. 29287 * 29288 * @param MIXED [$value] - Set TRUE to randomize salt, or random string value to preset hash value. 29289 * 29290 * @return SELF 29291 * 29292 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 29293 salt : function ($value) { 29294 29295 $value = setDefault($value, true); 29296 29297 this._salt = ($value === true) ? randomString() : $value; 29298 29299 return this; 29300 }, //FUNC salt 29301 29302/* ==== RESOURCES =========================================================================================================== */ 29303 29304 /** //** ----= res =--------------------------------------------------------------------------------------\**//** \ 29305 * 29306 * Miscellaneous system resource load. Always uses direct load. 29307 * 29308 * @param string - Path segments to compile. 29309 * 29310 * @return SELF 29311 * 29312 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 29313 res : function () { 29314 var $arr = Array.prototype.slice.call(arguments); 29315 return this.compile( [CMS_ALIAS, CMS_RES].concat($arr) ); 29316 }, //FUNC res 29317 29318 /** //** ----= js =--------------------------------------------------------------------------------------\**//** \ 29319 * 29320 * JS resource url. For system resource uses direct load by default. 29321 * 29322 * @param string - Path segments to compile. 29323 * 29324 * @return SELF 29325 * 29326 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 29327 js : function () { 29328 return this.compile( this.resSegments(CMS_JS, arguments) ); 29329 }, //FUNC js 29330 29331 /** //** ----= css =--------------------------------------------------------------------------------------\**//** \ 29332 * 29333 * CSS resource url. For system resource uses direct load by default. 29334 * 29335 * @param string - Path segments to compile. 29336 * 29337 * @return SELF 29338 * 29339 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 29340 css : function () { 29341 return this.compile( this.resSegments(CMS_CSS, arguments) ); 29342 }, //FUNC css 29343 29344 /** //** ----= images =--------------------------------------------------------------------------------------\**//** \ 29345 * 29346 * Images resource url. For system resource uses direct load by default. 29347 * 29348 * @param string $path - Path parts to compile. 29349 * 29350 * @return SELF 29351 * 29352 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 29353 images : function () { 29354 return this.compile( this.resSegments(CMS_IMAGES, arguments) ); 29355 }, //FUNC images 29356 29357 /** //** ----= image =--------------------------------------------------------------------------------------\**//** \ 29358 * 29359 * Image resizer url. 29360 * 29361 * @param string $path - Image path. 29362 * 29363 * @return SELF 29364 * 29365 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 29366 image : function ($path, $arguments) { 29367 29368 $arguments = $arguments || []; 29369 29370 // Hardcoded resizer path, which always present 29371 var $url = this.compile('get/files/image', $path); 29372 29373 // Nothing else to do, if no arguments given 29374 if ( isEmpty($arguments) ) 29375 return $url; 29376 29377 // If arguments provided - compiling GET and appending to url 29378 $url += '?'+implode('&', $arguments); 29379 29380 return $url; 29381 }, //FUNC image 29382 29383/* ==== CONTROLLERS ========================================================================================================= */ 29384 29385 // ToDo: ajax/call funcitons for sectional controllers calls. 29386 29387/* ==== HELPERS ============================================================================================================= */ 29388 29389 /** //** ----= resSegments =------------------------------------------------------------------------------\**//** \ 29390 * 29391 * Prepares resource segments, based on current settings. 29392 * Concatenates resources segments with provided path segments. 29393 * 29394 * @param string $resource - Resource type path. 29395 * @param array [$segments] - Additional segments to concat with. 29396 * 29397 * @return SELF 29398 * 29399 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 29400 resSegments : function ($resource, $segments) { 29401 29402 $resource = $resource || ''; 29403
29404 // Converting segments into array, in case of arguments object given 29405 $segments = Array.prototype.slice.call($segments); 29406 29407 // Adding section segments 29408 var $res = []; 29409 29410 // Direct resources are using alias 29411 if ( isEmpty(this.section) ) 29412 $res.push(CMS_ALIAS); 29413 29414 // Pointing to resource 29415 $res.push(CMS_RES); 29416 29417 // Adding section if specified 29418 if ( isString(this.section) ) 29419 $res.push(this.section); 29420 29421 // Finishing with resource segment 29422 $res.push($resource); 29423 29424 // Concatenating with segments 29425 $res = $res.concat($segments); 29426 29427 return $res; 29428 }, //FUNC resSegments 29429 29430 /** //** ----= compile =--------------------------------------------------------------------------------------\**//** \ 29431 * 29432 * Compiles url from given URI segments. Parts can be passed as array, or as multiple funciton arguments. 29433 * 29434 * @param string $segments - URI segments to compile. 29435 * 29436 * @return SELF 29437 * 29438 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 29439 compile : function ($segments) { 29440 29441 var $seg = isArray($segments) ? $segments : arguments; 29442 29443 // Concatenating each non empty segment, trimming slashes and spaces 29444 var $res = ''; 29445 for ( var $i in $seg ) { 29446 $s = $seg[$i]; 29447 29448 // Making sure strings come 29449 if ( !isString($s) ) 29450 continue; 29451 29452 // Timming garbage 29453 $s = $s.trim(' /\\'); 29454 29455 // Skipping empties 29456 if ( isEmpty($s) ) 29457 continue; 29458 29459 // Concatenating with leading '/', which always present 29460 $res += '/'+$s; 29461 29462 } //FOR each segment 29463 29464 // Adding domain if specified 29465 if ( this._full ) 29466 $res = fullURL($res, this._ssl); 29467 29468 // Adding salt if specified 29469 if ( this._salt ) 29470 $res += '?'+this._salt; 29471 29472 // Done. 29473 return $res; 29474 }, //FUNC compile 29475 29476}} //CLASS mwUrl 29477 29478/** //** ----= ___ =----------------------------------------------------------------------------------------------\**//** \ 29479* 29480* Shortcut to console.log() 29481* 29482* @param MIXED * - Variables to dump. 29483* 29484\**//** ----------------------------------------------------------------------------------------------= by Mr.V!T =----/** //**/ 29485function ___() { 29486 29487 console.log.apply(console, arguments); 29488 29489} //FUNC ___ 29490 29491function mwError (msg) { 29492 return '<div class="status error">' + msg + '</div>'; 29493} //FUNC mwError 29494 29495function mwSuccess (msg) { 29496 return '<div class="status success">' + msg + '</div>'; 29497} //FUNC mwSuccess 29498 29499function mwHint (msg) { 29500 return '<div class="status hint">' + msg + '</div>'; 29501} //FUNC mwHint 29502 29503function mwWarning (msg) { 29504 return '<div class="status warning">' + msg + '</div>'; 29505} //FUNC mwWarning 29506 29507function mwFormToggle ($form, $target, $state) { 29508 29509 // Makikng sure it's jQuery 29510 $form = _jq($form); 29511 29512 // One of form elements can be provided instead of form itself 29513 // Checking if that's the case. 29514 if ( !$form.is('form') ) 29515 $form = $form.closest('form'); 29516 29517 // Searching target on form 29518 var $tEl = $form.find($target); 29519 29520 // Toggling 29521 if ( !isEmpty($state) ) 29522 $tEl.show(); 29523 else 29524 $tEl.hide(); 29525 29526} //FUNC mwFormToggle 29527 29528/*--------------------------------------------------------------------------------*\ 29529| updateDimensions 29530|---------------------------------------------------------------------------------- 29531| Updates current dimensions setting for future use. 29532| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 29533| Params: 29534| NONE 29535| Return: 29536| NULL 29537\*--------------------------------------------------------------= by Mr.V!T =-----*/ 29538function updateDimensions () { 29539 29540 var wnd = screenSize(); 29541 var desktop_height = wnd.height - jQuery('#HintBarContainer').height() - jQuery('#NavigationContainer').height(); 29542 29543 setCookie('mwWorkSpaceWidth', wnd.width); 29544 setCookie('mwWorkSpaceHeight', desktop_height); 29545 29546} //FUNC updateDimensions 29547/*/ 29548function initLTRows () { 29549 jQuery('.ListingTable TR:even').addClass('Even'); 29550} //FUNC initLTRows 29551/**/ 29552 29553/*--------------------------------------------------------------------------------*\ 29554| pulseAncor 29555|---------------------------------------------------------------------------------- 29556| Pulsates given block. 29557| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
29558| Params: 29559| ancor string - Block name to pulsate. 29560| Return: 29561| bool - Always FALSE. 29562\*--------------------------------------------------------------= by Mr.V!T =-----*/ 29563function pulseAncor (ancor) { 29564 29565 // DEPRECATED, left just as dummy 29566 return false; 29567 29568 if ( !ancor ) 29569 return false; 29570 29571 jQuery('A[name='+ancor+']').effect('pulsate'); 29572 29573 return false; 29574} //FUNC pulseAncor 29575 29576/*--------------------------------------------------------------------------------*\ 29577| initDatePicker 29578|---------------------------------------------------------------------------------- 29579| Initiates DatePickers on page. 29580| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 29581| Params: 29582| NONE 29583| Return: 29584| bool - Always false. 29585\*--------------------------------------------------------------= by Mr.V!T =-----*/ 29586function initDatePicker () { 29587 29588 Date.format = 'yyyy-mm-dd'; 29589 29590 jQuery('INPUT.Date').each( function () { 29591 29592 var el = jQuery(this); 29593 29594 el.datePicker({clickInput:true, createButton:false, startDate: '2000-01-01'}); 29595 // el.dpSetSelected(el.val()); 29596 29597 }); //jQuery each 29598 29599 return false; 29600} //FUNC initDatePicker 29601 29602/*--------------------------------------------------------------------------------*\ 29603| updateAjaxLinks 29604|---------------------------------------------------------------------------------- 29605| Updates page links wich should be loaded using AJAX. 29606| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 29607| Params: 29608| NONE 29609| Return: 29610| bool - Always FALSE. 29611\*--------------------------------------------------------------= by Mr.V!T =-----*/ 29612function updateAjaxLinks () { 29613 jQuery('A.ajax').each( function () { 29614 this.onload = this.onclick; 29615 this.onclick = ''; 29616 }); 29617 jQuery('A.ajax').unbind('click'); 29618 jQuery('A.ajax').click( function() { 29619 return pageAjax(this); 29620 }); //FUNC click 29621 29622} //FUNC updateAjaxLinks 29623 29624var mwPerson = { 29625 29626 /** //** ----= getTitle =----------------------------------------------\**//** \ 29627 * 29628 * Attempts to retrieve person title name to show in dialogs. 29629 * 29630 * @param object person - Person data object. 29631 * @param string [template] - Custom template to use. 29632 * 29633 * @return string - Contact title. 29634 * 29635 \**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 29636 getTitle : function (person, template) { 29637 29638 template = template || '{name} {first_name} {last_name} {firstname} {lastname}'; 29639 29640 return parseVariables(template, person).multiClean().trim(); 29641 }, //FUNC getName 29642 29643 /** //** ----= getEmail =----------------------------------------------\**//** \ 29644 * 29645 * Attempts to retrieve person email to show in dialogs. 29646 * 29647 * @param object person - Person data object. 29648 * 29649 * @return string - Contact title. 29650 * 29651 \**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 29652 getEmail : function (person) { 29653 return arraySelectValue(person, ['email', 'mail'], '').trim(); 29654 } //FUNC getName 29655 29656} //OBJECT mwPerson 29657 29658function mwSkinLoader ($el) { 29659 $el = _jq($el); 29660 29661 // Copying loader html from system loader 29662 var $sysLoader = jQuery('#systemLoader'); 29663 var $html = $sysLoader.html(); 29664 29665 // And inserting it into target element 29666 $el.html($html); 29667 29668} //FUNC mwSkinLoader 29669 29670/** //** ----= mwState =----------------------------------------------\**//** \ 29671* 29672* Sets system to processing/idle state. 29673* 29674* @param MIXED state 29675* bool - TRUE for loading indication, FALSE - idle. 29676* string - Status message for idle state (usually operation result) 29677* 29678* @param MIXED [dialog] 29679* bool - FALSE for background (hintbar only). TRUE for common 29680* system loading. 29681* string - Dialog name, to use for indications. 29682* 29683* @return bool - Always FALSE. 29684* 29685\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 29686function mwState (state, dialog) { 29687 29688 // Since mwState meant to be used with windows and backend - doing nothing if windows are not loaded 29689 // Done this way due to while windows are supported, but are not required for basic toolkit 29690 if ( typeof(mwWindow) === 'undefined' ) 29691 return false; 29692 29693 // Omited dialog is TRUE 29694 if ( !isSet(dialog) ) 29695 dialog = true; 29696 29697 // Flush hint bar test, it's used with hintbar 29698 HINT_SAVE = false;
29699 29700 // Updating system indicator 29701 if ( state !== true ) { 29702 29703 // ---- Setting IDLE state ---- 29704 29705 jQuery('#hint_bar_status_ready').show(); 29706 jQuery('#hint_bar_status_working').hide(); 29707 29708 // Loader should be hided on this step anyway 29709 // In some cases when window was created during loading, loader may miss this 29710 // So it does not heart to forcehide 29711 29712 mwWindow('LoaderWindow').hide(); 29713 29714 // Updating modal loaders 29715 if ( typeof(dialog) == 'string' ) { 29716 29717 // ---- Custom dialog ---- 29718 29719 mwWindow(dialog).State(state); 29720 29721 } else { 29722 29723 // ---- Common loader and background ---- 29724 29725 if ( state !== false ) 29726 jQuery('#HintPlaceholder').html(state); 29727 29728 } //IF no dialog 29729 29730 } else { //IF working 29731 29732 // ---- Setting WORKING state ---- 29733 29734 jQuery('#hint_bar_status_ready').hide(); 29735 jQuery('#hint_bar_status_working').show(); 29736 29737 // Updating modal loaders 29738 if ( typeof(dialog) == 'string' && mwWindow(dialog).Visible ) { 29739 29740 // ---- Custom dialog ---- 29741 29742 mwWindow(dialog).State(state); 29743 29744 } else if ( dialog ) { //IF dialog set 29745 29746 // ---- Common loader ---- 29747 29748 mwWindow('LoaderWindow').show(); 29749 29750 } //IF common loader 29751 29752 } //IF idle 29753 29754 return false; 29755 29756} //FUNC mwState 29757 29758/** //** ----= mwExHandle =--------------------------------------------------------------------------------------\**//** \ 29759* 29760* Morweb global exceptions handler. Basic handlinng for now. This way user can say at least smth. 29761* 29762* @see window.onerror handler doc for parameters list. 29763* 29764\**//** ---------------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 29765function mwExHandle (msg, url, lineNo) { 29766 29767 // ToDo: test compatability 29768 // ToDo: Implement class based exceptions logic, 29769 // and filter errors to separate debug (not shown to user) and user friendly messages 29770 29771 // If nothing to show - showing nothing 29772 if ( !msg ) 29773 return; 29774 29775 // Forcing message to be string (in case object given - relying on native toString() ) 29776 var msg = msg + ''; 29777 29778 // Removing trash 29779 msg = msg.replace('uncaught exception:', ''); 29780 29781 mwState( mwError(msg) ); 29782 29783} //FUNC mwExHandle 29784 29785var mwHintShow = false; 29786 29787function mwWatchHints ($context, $dialog) { 29788 29789 var $target = ( $dialog ) ? '#' + $dialog + ' .winStatus' : '#HintPlaceholder'; 29790 29791 $context = _jq($context); 29792 29793 $context 29794 .off('mouseenter.mwHints') 29795 .off('mouseleave.mwHints') 29796 .on('mouseenter.mwHints', '[title], [hint], [error]', function() { 29797 29798 if ( mwHintShow ) 29799 return; 29800 29801 mwHintShow = true; 29802 29803 // Saving hintbar content 29804 this.HINT_SAVE = jQuery($target).html(); 29805 29806 // Temporary allowing 'title' attribute to act as hint. 29807 // Later only 'hint' will be used to avoid title tricks 29808 29809 // First trying if there is error 29810 var hint = jQuery(this).attr('error'); 29811 var cls = 'error'; 29812 29813 // If no error, trying hint 29814 if ( !hint ) { 29815 hint = jQuery(this).attr('hint') || jQuery(this).attr('title'); 29816 cls = 'hint'; 29817 } //IF no error 29818 29819 // Placing hint 29820 if ( hint ) 29821 jQuery($target).html('<div class="status ' + cls + '">' + hint + '</div>'); 29822 29823 // Removing title ( unnecessary later ) 29824 this.TITLE_SAVE = this.title; 29825 this.title = ''; 29826 29827 }) //FUNC mouseenter 29828 .on('mouseleave.mwHints', '[title], [hint], [error]', function() { 29829 29830 this.title = this.TITLE_SAVE; 29831 jQuery($target).html(this.HINT_SAVE); 29832 29833 mwHintShow = false; 29834 }) //FUNC mouseleave 29835 ; //jQuery(context) 29836 29837} //FUNC mwWatchHints 29838
29839/*--------------------------------------------------------------------------------*\ 29840| setHintElements 29841|---------------------------------------------------------------------------------- 29842| Set's elements for dynamic hints. 29843| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 29844| Params: 29845| selector string - Target elements jQuery selector. 29846| Return: 29847| bool - Always FALSE. 29848\*--------------------------------------------------------------= by Mr.V!T =-----*/ 29849function setHintElements (selector, dialog) { 29850 29851 var target = ( dialog ) ? '#' + dialog + ' .winStatus' : '#HintPlaceholder'; 29852 29853 selector = _jq(selector); 29854 29855 selector 29856 .unbind('mouseenter') 29857 .unbind('mouseleave') 29858 .hover( function() { 29859 29860 // Saving hintbar content 29861 HINT_SAVE = jQuery(target).html(); 29862 29863 // Temporary allowing 'title' attribute to act as hint. 29864 // Later only 'hint' will be used to avoid title tricks 29865 29866 // First trying if there is error 29867 var hint = jQuery(this).attr('error'); 29868 var cls = 'error'; 29869 29870 // If no error, trying hint 29871 if ( !hint ) { 29872 hint = jQuery(this).attr('hint') || jQuery(this).attr('title'); 29873 cls = 'hint'; 29874 } //IF no error 29875 29876 // Placing hint 29877 if ( hint ) 29878 jQuery(target).html('<div class="status ' + cls + '">' + hint + '</div>'); 29879 29880 // Removing title ( unnecessary later ) 29881 TITLE_SAVE = this.title; 29882 this.title = ''; 29883 29884 }, //FUNC over 29885 function() { 29886 29887 this.title = TITLE_SAVE; 29888 29889 if ( HINT_SAVE !== false ) 29890 jQuery(target).html(HINT_SAVE); 29891 } //FUNC out 29892 ); //jQuery onclick 29893 29894} //FUNC setHintElements 29895 29896/** //** ----= mwUpdateScrolls =--------------------------------------------------------------------------------------\**//** \ 29897* 29898* Updates scollable contents. 29899* 29900* @param jQuery [$context] - Context to search scrolls within. 29901* 29902* @return jQuery - Scrollable elements found. 29903* 29904\**//** ---------------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 29905function mwUpdateScrolls ($context) { 29906 29907 if ( !isFunction(jQuery.fn.mCustomScrollbar) ) 29908 return false; 29909 29910 $context = $context ? _jq($context) : jQuery(document); 29911 29912 var $scrolls = $context.find('.mwScroll'); 29913 29914 $scrolls.mCustomScrollbar('destroy') 29915 $scrolls.mCustomScrollbar({ 29916 theme : 'dark', 29917 autoHideScrollbar : true, 29918 // scrollInertia : false, 29919 contentTouchScroll : true, 29920 advanced : { 29921 // autoScrollOnFocus : true 29922 } 29923 }); //mCustomScrollbar 29924 29925 return $scrolls; 29926} //FUNC mwUpdateScrolls 29927 29928/** //** ----= OBJECT mwAjax =--------------------------------------------------------------------------------------\**//** \ 29929* 29930* Morweb system Ajax procesing object. 29931* 29932* @package Morweb 29933* @subpackage System 29934* @category helper 29935* 29936* @param string url - Path to controller to request from. 29937* 29938* @param MIXED [post] - Data to post on request. Can be DOM form, jQuery selector 29939* or object which points to form, or object with parameters. 29940* 29941* @param MIXED [dialog]- Any valid mwState() dialog value. 29942* 29943\**//** ---------------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 29944function mwAjax (url, data, dialog) { 29945 29946 // Creating morweb extension object 29947 var exObj = { 29948 29949 'dialog' : dialog, // Dialog related to call. Will be used to display status. 29950 29951// ==== CONTENTS =============================================================================================================== 29952 29953 /** //** ----= parseContents =------------------------------------------------------------------------------\**//** \ 29954 * 29955 * Parses AraxResult for different content types. 29956 * 29957 * @param object(AjaxResult) data - Result in vAjax object format. 29958 * 29959 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 29960 parseContents : function (data) { 29961 29962 var self = this; 29963 29964 // If smth wrong come - nothing to do 29965 if ( !data ) return; 29966 29967 // ---- Processing debug (unexpected output) ---- 29968 29969 if ( data._debug && typeof(mwRawDump) != 'undefined' ) 29970 mwRawDump('#wDebugCurrent', data._debug); 29971 29972 delete data._debug; 29973 29974 // ---- Processing validations ---- 29975 29976 if ( data._validations ) { 29977 29978 // To be sure that smth correct come 29979 if ( typeof(data._validations) == 'object' ) { 29980 29981 //Processig each given validations form 29982 for ( var form in data._validations ) { 29983 29984 // Skipping not forms ( numeric indexies are allowed ) 29985 if ( isInt(form) ) continue; 29986 29987 // Normally forms are specified by ids, if not found, then it's for custom processing 29988 // Trying to define context first to speedup and avoid cross windows applying 29989 var context = ( typeof(this.dialog) == 'string ' ) ? mwWindow(this.dialog).Body : jQuery('#' + form); 29990 29991 // Setting validations 29992 setValidations(context, data._validations[form]); 29993 29994 } //FOR each form 29995 29996 }
29996 //IF object comed 29997 29998 } //IF validations given 29999 30000 // ---- Processing cahces ----- 30001 30002 if ( !data._cache ) return; 30003 30004 var cache = data._cache; 30005 delete data._cache; 30006 30007 // HTML comed can contain errors, 30008 // though jQuery may still insert it, exception is happen right AFTER insert. 30009 // To prevent script stop (content was inserted anyway) - catching exceptions 30010 // for each insert individually (to process others which are succeed) and relogging them in console. 30011 30012 // ---- Setting up data cache ---- 30013 30014 // Making sure mwData exists at all 30015 if ( typeof(mwData) == 'undefined' ) 30016 mwData = {}; 30017 30018 if ( cache.Data ) { 30019 30020 /*/ 30021 if (mwData.Users); 30022 __(mwData.Users); 30023 30024 /**/ 30025 // ToDo: Seems that jQuery.extend() does not merge arrays propertly 30026 // And empty objects/assoc arrays (which meant to be data objects) 30027 // come as list arrays, which are not merged 30028 jQuery.extend(true, mwData, cache.Data); 30029 /*/ 30030 30031 if (mwData.Users); 30032 __(mwData.Users); 30033 /**/ 30034 } //IF Data set 30035 30036 // ---- Setting up windows ---- 30037 30038 // Only supporting windows when windows lib is loaded (backend/liveEd) 30039 // Windows are not created/supported for bare frontend currently 30040 30041 if ( cache.Windows && (typeof(mwWindow) !== 'undefined') ) { 30042 30043 // Using mwWinManager to get windows system container 30044 var $winContainer = mwWinManager.init().Container; 30045 30046 for ( var i in cache.Windows ) { 30047 30048 // Checking for html within regular results 30049 if ( !data['_wc_'+i] ) continue; 30050 30051 var wnd = mwWindow(i); 30052 var $old = wnd.Window; 30053 30054 // Disablingg old window, but keeping it's element 30055 // This allows updated window to init in background, with smooth transition 30056 // In addition - increasing z-index, to make sure it stays on top, covering new version 30057 if ( $old && $old.length ) { 30058 30059 // Removing IDs and names from old elements, to allow proper init 30060 $old.removeAttr('id') 30061 $old.find('[id], [name]').removeAttr('id name'); 30062 30063 // Increasing z-index, just setting it notably higher 30064 $old.css('z-index', $old.css('z-index')*1+100 ); 30065 30066 } //IF old window present 30067 30068 try { 30069 var el = jQuery('<div id="' + i + '" class="winEl">' + data['_wc_'+i] + '</div>') 30070 .appendTo($winContainer); 30071 30072 } catch (e) { 30073 30074 // Researching window, cuz it still may be inserted 30075 var el = $winContainer.find('#' + i); 30076 30077 console.error(e); 30078 } //TRY 30079 30080 // Initiating window 30081 wnd.Element(el).align(); 30082 30083 // Removing old window element if there was one 30084 if ( $old && $old.length ) 30085 $old.remove(); 30086 30087 // Initiating title 30088 if ( cache.Windows[i] ) 30089 wnd.Title(cache.Windows[i]); 30090 30091 delete data['_wc_'+i]; 30092 30093 } //FOR each window in system 30094 30095 } //IF windows set 30096 30097 // ---- Setting up contents ---- 30098 30099 if ( cache.Contents ) { 30100 30101 for ( var i in cache.Contents ) { 30102 // Checking for html within regular results 30103 if ( !data['_cc_'+i] ) continue; 30104 30105 try { 30106 jQuery('#' + i).html(data['_cc_'+i]); 30107 } catch (e) { 30108 console.error(e); 30109 } //TRY 30110 30111 delete data['_cc_'+i]; 30112 } //FOR each contents 30113 30114 } //IF contents set 30115 30116 // ---- Setting up subcontents ---- 30117 30118 // Making sure mwSubContents exists at all 30119 if ( typeof(mwSubContents) == 'undefined' ) 30120 mwSubContents = {}; 30121 30122 if ( cache.SubContents ) { 30123 30124 for ( var i in cache.SubContents ) { 30125 30126 // Checking for html within regular results 30127 if ( !data['_sc_'+i] ) continue; 30128 30129 mwSubContents[i] = data['_sc_'+i]; 30130 30131 delete data['_sc_'+i]; 30132 } //FOR each subcontents 30133 30134 } //IF subcontents set 30135 30136 // ---- Running java init ---- 30137 30138 if ( cache.Java ) { 30139 30140 // Executing each given java init 30141 for ( var i in cache.Java ) { 30142 jQuery.globalEval(cache.Java[i]); 30143 } //FOR each java init 30144 30145 } //IF subcontents set 30146 30147 }, //FUNC parseResult 30148 30149// ==== GENERAL ================================================================================================================ 30150 30151 /** //** ----= init =--------------------------------------------------------------------------------------\**//** \ 30152 * 30153 * Sets up basic events. Used before constructor return, to make sure that processing triggers before custom events. 30154 * 30155 * @return SELF 30156 * 30157 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 30158 init : function () { 30159 30160 // ---- START ---- 30161 30162 this.start( function (data) { 30163 30164 // Setting loading state 30165 mwState(true, this.dialog); 30166 30167 }); //FUNC vAjax.stop.callback 30168 30169 // ---- STOP ---- 30170 30171 this.stop( function (data) { 30172 30173 // Parsing contentns 30174 this.parseContents(data); 30175 30176 }); //FUNC vAjax.stop.callback 30177 30178 // ---- SUCCESS ---- 30179 30180 this.success( function (data) { 30181 30182 // If some of contents come defined updater - calling it. 30183 // DEPRECATED: Not used anymore, left from old code for compatability 30184 if ( typeof(updateDesktop) == 'function' ) 30185 updateDesktop(); 30186 30187 }); //FUNC vAjax.success.callback 30188
30189 // ---- ERROR ---- 30190 30191 this.error( function (data) { 30192 30193 // Simple results are threated as debug/errors 30194 if ( data.status.minor == 'simple' ) { 30195 30196 if ( data._debug && typeof(mwRawDump) != 'undefined' ) 30197 mwRawDump('#wDebugCurrent', data.res); 30198 30199 // Updating status 30200 mwState(false, this.dialog); 30201 30202 return; 30203 } //IF simple 30204 30205 }); //FUNC vAjax.error.callback 30206 30207 // ---- DONE ---- 30208 30209 this.done( function (data) { 30210 30211 // Updating status 30212 mwState(data.status.text, this.dialog); 30213 30214 }); //FUNC vAjax.stop.callback 30215 30216 return this; 30217 30218 }, //FUNC init 30219 30220 /** //** ----= go =--------------------------------------------------------------------------------------\**//** \ 30221 * 30222 * Basic posting method. Proceeds ajax requests, parses contents, calls callbacks and updates system status. 30223 * 30224 * @param object(AjaxResult) data - Result in vAjax object format. 30225 * 30226 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 30227 go : function () { 30228 30229 // Before posting attempting to reset current validations on dialog (if one specified) 30230 if ( typeof(this.dialog) == 'string' && (typeof(mwWindow) !== 'undefined') ) 30231 setValidations( mwWindow(this.dialog).Body, {}); 30232 30233 this.post(); 30234 30235 return this; 30236 30237 }, //FUNC go 30238 30239// ==== CONTENT TYPES ========================================================================================================== 30240 30241 /** //** ----= content =--------------------------------------------------------------------------------------\**//** \ 30242 * 30243 * Loads content from contoller specified. And applies to specified element if supplied.
30244 * 30245 * @param MIXED target - Target to insert content to. Can be jQuery selector, 30246 * jQuery object, DOM element, or callback function. Function 30247 * passed as target will act as onSuccess callback. 30248 * 30249 * @return SELF 30250 * 30251 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 30252 content : function (target) { 30253 30254 this.go(); 30255 30256 if ( isFunction(target) ) 30257 this.success(target); 30258 else 30259 this.success( function (data) { 30260 30261 if ( !target ) return; 30262 30263 // If common content come - inserting it into target 30264 if ( data.content !== undefined ) { 30265 30266 target = _jq(target); 30267 30268 target.html(data.content); 30269 30270 } //IF content set. 30271 30272 }); //FUNC onSuccess 30273 30274 return this; 30275 }, //FUNC content 30276 30277 /** //** ----= index =--------------------------------------------------------------------------------------\**//** \ 30278 * 30279 * This was designed with idea of index reload. Can take optional callback parameter. 30280 * On success action it reloads index from controller specified, closes related dialogs, calls given callback and 30281 * triggers status. Callback will be called after success reload, all elements positioning and status updates. 30282 * 30283 * @param function 30284 * [callback] - Callback to call upon success. 30285 * If callback returns FALSE, dialog will be not 30286 * canceled and status will be not updated. 30287 * 30288 * @return SELF 30289 * 30290 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 30291 index : function (callback) { 30292 30293 // Getting scroll position of scroll table to be fancy 30294 // ToDo: scrollTable instance method for reinit 30295 var $pos = jQuery('.mwScrollTable.body').scrollTop(); 30296 30297 return this 30298 .go() 30299 .success( function (data) { 30300 30301 var res = true; 30302 30303 if ( typeof(callback) == 'function' ) 30304 res = callback(data); 30305 30306 if ( res !== false ) { 30307 30308 if ( typeof(this.dialog) == 'string' && (typeof(mwWindow) !== 'undefined') ) 30309 mwWindow(this.dialog).hide(); 30310 30311 // Status was updated in window, but if it's closed - text status should go in hintbar 30312 if ( data.status.text ) 30313 mwState(data.status.text); 30314 30315 // Index tables 30316 jQuery('.mwIndexTable').each( function () { 30317 30318 mwScrollTable( jQuery(this), { 30319 container : jQuery('.mwDesktop'), 30320 }); 30321 30322 }); //jQuery.each scroll table 30323 30324 // Resetting scroll position to top 30325 jQuery('.mwScrollTable.body').scrollTop($pos); 30326 30327 } //IF all ok 30328 30329 return res; 30330 30331 }) //FUNC onSuccess 30332 ; //this 30333 30334 }, //FUNC index 30335 30336 /** //** ----= window =--------------------------------------------------------------------------------------\**//** \ 30337 * 30338 * Based on content loading it targets one specified window and shows it on success. 30339 * Can take optional callback parameter, which will be called on success, but before show window. 30340 * 30341 * @param string name - Name of dialog to show upon loading. 30342 * 30343 * @param function 30344 * [callback] - Callback to call upon success. 30345 * If callback returns FALSE, dialog will be not 30346 * opened and status will be not updated. 30347 * 30348 * @return SELF 30349 * 30350 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 30351 window : function (name, callback) { 30352 30353 return this 30354 .go() 30355 .success( function (data) { 30356 30357 var res = true; 30358 30359 if ( typeof(callback) == 'function' ) 30360 res = callback(data); 30361 30362 if ( res !== false ) 30363 mwWindow(name).show(); 30364 30365 return res; 30366 }); //FUNC 30367 30368 } //FUNC window 30369 30370 }; //OBJECT mwAjax 30371 30372 // Getting basic vAjax object, and extending it with morweb behavior 30373 var vAjaxObj = vAjax(url, data); 30374 30375 jQuery.extend(vAjaxObj, exObj); 30376 30377 // Initiating basic events 30378 vAjaxObj.init(); 30379 30380 // Returning it to user 30381 return vAjaxObj; 30382} //CONSTRUCTOR mwAjax 30383 30384/** //** ----= OBJECT mwSubContent =--------------------------------------------\**//** \ 30385* 30386* System SubContents processing tools. 30387* 30388* @param jQuery container - Container element to setup with subcontents. 30389* @param jQuery [animation] - Element to use for animations. Possible values: 30390* jQuery compatable pointer to element to animate, 30391* TRUE to animate container element (default behavior), 30392* FALSE to cancel animations (for manual animating). 30393* 30394\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 30395function mwSubContent (_container, _animation) { 30396 30397 // Validating environment 30398 _container = _jq(_container); 30399 30400 if ( _animation === undefined ) 30401 _animation = true; 30402 30403 return { 30404 30405 storage : jQuery('#sysSubContents'), // System subContents storage. 30406 container : _container, // Container element to operatie with. 30407 animation : _animation, // Element to animate on operations. For internal use. To setup use animate() method. 30408 30409 /** //** ----= animate =----------------------------------------------\**//** \ 30410 * 30411 * Applies animation to set element and calls callback on final. For internal use. 30412 *
30413 * @param string type - Animation type: 'show' or 'hide'. 30414 * @param function [callback] - Callback to call on final. 30415 * 30416 * @return SELF 30417 * 30418 \**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 30419 animate : function ( type, callback ) { 30420 30421 // Calculating animation target 30422 var a; 30423 30424 if ( this.animation === true ) 30425 a = this.container; 30426 else if ( this.animation === false ) 30427 a = false; 30428 else 30429 a = _jq(this.animation); 30430 30431 // Ensuring callback is a function 30432 callback = callback || function(){}; 30433 30434 // ---- Applying animation if set ---- 30435 30436 if ( a ) { 30437 30438 // If animation target set - calling proper animation and returning. 30439 // If no valid animation - doing nothing, it will proceed to default no animation flow. 30440 switch ( type ) { 30441 case 'show' : 30442 mwShow(a, callback); 30443 return this; 30444 case 'hide' : 30445 mwHide(a, callback); 30446 return this; 30447 } //SWITCH type 30448 30449 } //IF animation 30450 30451 // ---- No animation ---- 30452 30453 if ( typeof(callback) == 'function' ) 30454 callback(); 30455 30456 return this; 30457 }, //FUNC animate 30458 30459 /** //** ----= setup =----------------------------------------------\**//** \ 30460 * 30461 * Replaces container subContents with subContent specified, cleaning container. 30462 * Applies animations if set. Calls callback after subContent inserted and before show. 30463 * New subContent will be passed to callbacks. 30464 * 30465 * @param string id - SubContainer system ID. 30466 * 30467 * @param function [callback] - Callback to call after hide and setup. 30468 * @param function [onfinal] - Callback to call after final show. 30469 * 30470 * @return SELF 30471 * 30472 \**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 30473 setup : function (id, callback, onfinal) { 30474 30475 var self = this; // Shortcut to use in callback 30476 30477 // Calling cleaner, this will also hide container 30478 this.unset( function () { 30479 30480 // Attaching content 30481 // var el = jQuery('#' + id); 30482 var el = jQuery(mwSubContents[id]); 30483 el.appendTo(self.container); 30484 30485 // Showing container 30486 self.animate('show', function () { 30487 // Calling final callback 30488 if ( typeof(onfinal) == 'function' ) 30489 onfinal(el); 30490 30491 }); //FUNC onShow 30492 30493 // Small delay to allow to update contents dimensions 30494 setTimeout( function () { 30495 // Calling callback, it will start before animated, 30496 // but after animaiton start - contents become real 30497 if ( typeof(callback) == 'function' ) 30498 callback(el); 30499 }, 1); 30500 30501 }); //FUNC onHide 30502 30503 return this; 30504 }, //FUNC setup 30505 30506 /** //** ----= unset =----------------------------------------------\**//** \ 30507 * 30508 * Clears container from subContents, moving them to system storage. 30509 * Calls callback after clean. 30510 * 30511 * @param function [callback] - Callback to call on done. 30512 * 30513 * @return SELF 30514 * 30515 \**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 30516 unset : function ( callback ) { 30517 30518 var self = this; // Shortcut to use in callback 30519 30520 this.animate('hide', function () { 30521 30522 // Removing all childs in container. Container means only subcontents 30523 // self.container.find('.subContent').appendTo('#sysSubContents'); 30524 self.container.empty(); 30525 30526 if ( typeof(callback) == 'function' ) 30527 callback(); 30528 30529 }); //FUNC onHide 30530 30531 return this; 30532 } //FUNC unset 30533 30534 }; //OBJECT mwSubContent 30535 30536} //CONSTRUCTOR mwSubContent 30537 30538//ToDo: Redo everything!!! 30539 30540// Simple cache to do not monitor same values 30541var upload_procesing_cache = {}; 30542 30543/** //** ----= setFormsSubmit =----------------------------------------------\**//** \ 30544* 30545* Sets forms to have submit control. Applies to forms with set onsubmit attribute. 30546* 30547* @param MIXED element - jQuery selector to search forms within 30548* (set to speed up search). 30549* 30550* @return bool - Always FALSE. 30551* 30552\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 30553function setFormsSubmit ( element ) { 30554 30555 if ( element && !(element instanceof jQuery) ) 30556 element = jQuery(element); 30557 30558 // Searching for forms, only with onsubmit attribute 30559 var forms = ( element )? jQuery(element).find('FORM[onsubmit]') : jQuery('FORM[onsubmit]'); 30560
30561 // Processing each form for submit control 30562 forms.each( function() { 30563 30564 var form = jQuery(this); 30565 var form_id = form.attr('id'); 30566 30567 // Checking if form has no submit already 30568 // ToDo: More complex check 30569 if ( form.find('[type=submit]').length ) return; 30570 30571 // If still here - form have no submit, but have onsubmit attribute 30572 // So adding hidden submit control 30573 // Adding on top, to do not mess with winContents and layout 30574 form.prepend('<input type="submit" style="display: none;" />'); 30575 30576 if ( !form_id ) return; 30577 30578 // If element is window with footer buttons related to form (by id) - set them to submit form too. 30579 element.find('.winFooter A[rel=' + form_id + ']') 30580 .addClass('hi') 30581 .unbind('click') 30582 .click( function () { 30583 30584 jQuery('#' + form_id).submit(); 30585 30586 return false; 30587 } ); //FUNC onClick 30588 30589 }); //FUNC each form 30590 30591 return false; 30592} //FUNC setFormsSubmit 30593 30594/** //** ----= mwUpdateSelector =--------------------------------------------------------------------------------------\**//** \ 30595* 30596* Updates selector options with items given. Optionally marks certain items as selected. 30597* 30598\**//** ---------------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 30599function mwUpdateSelector (input, options, selected) { 30600 30601 input = _jq(input); 30602 30603 // Removing all styles from selector 30604 var sel = unstyleInput(input); 30605 30606 // Cleanning old options 30607 sel.find('OPTION').remove(); 30608 30609 // Adding given options 30610 // Supporting maps if one is given 30611 if ( isClass(options, 'Map') ) { 30612 30613 30614 /**/ // Using method to iterate, to stay compatible with older JS parsers 30615 options.forEach( function ( $val, $key ) { 30616 jQuery('<option value="' + $key + '">' + $val + '</option>').appendTo(sel); 30617 }); //forEach 30618 30619 /*/ 30620 for ( var i of options ) 30621 jQuery('<option value="' + i[0] + '">' + i[1] + '</option>').appendTo(sel); 30622 /**/ 30623 } //IF map given 30624 30625 else { 30626 30627 for ( var i in options ) 30628 jQuery('<option value="' + i + '">' + options[i] + '</option>').appendTo(sel); 30629 30630 } //IF regular data object 30631 30632 // Setting selected values if given some 30633 if ( selected ) 30634 setValue_Select(sel.get(0), selected); 30635 30636 // Restyling input back 30637 styleDialog( sel.parent() ); 30638 30639 // Triggering update 30640 sel.trigger('update'); 30641 30642 return false; 30643} //FUNC mwUpdateSelector 30644 30645/** //** ----= filterSelect =----------------------------------------------\**//** \ 30646* 30647* Filters styled selector with values. 30648* 30649* @param MIXED select - Valid jQuery element selector. 30650* Sould point to .mwinput.List control. 30651* 30652* @param string filter - Comma separated filters. 30653* @return bool - Always FALSE. 30654* 30655\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 30656function filterSelect ( select, filter ) { 30657 30658 if ( !filter ) { 30659// jQuery(select).find('.Item').fadeIn(200); 30660 jQuery(select).find('.item').show(); 30661 return false; 30662 } //IF empty filter 30663 30664 // Trimming filters, and composing regex 30665 var filter = strToArray(filter, ','); 30666 var reg = new RegExp('(' + filter.join('|') + ')', 'i'); 30667 30668 jQuery(select + ' .item').each( function () { 30669 var el = jQuery(this); 30670 30671 var title = el.find('div').first().html(); 30672 30673 if ( reg.test(title) ) 30674 el.show(); 30675 else 30676 el.hide(); 30677 30678 }); //jQuery each 30679 30680 return false; 30681} //FUNC filterSelect 30682 30683/** //** ----= selectAddItem =----------------------------------------------\**//** \ 30684* 30685* Adds items to target styled selector. 30686* 30687* @param MIXED select - Valid jQuery element selector. 30688* @param string values - Comma separated values. 30689* @return bool - Always FALSE. 30690* 30691\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 30692function selectAddItem ( select, values, checked ) { 30693 30694 if ( !values ) return false; 30695 30696 var select = _jq(select); 30697 30698 checked = ( checked )? ' selected="selected"' : ''; 30699 30700 // If input given as value, it should be cleaned after all 30701 var relate = false; 30702 if ( values instanceof jQuery ) { 30703 relate = values; 30704 values = relate.val(); 30705 } //IF parent element given 30706 30707 if ( isStr(values) ) { 30708 var tmp = strToArray(values, ','); 30709 30710 // Reindexing to have meaningfull keys to use as values 30711 // Normally associated arrays or objects should be passed 30712 values = {}; 30713 30714 for ( var i in tmp ) 30715 values[tmp[i]] = tmp[i]; 30716 30717 } //IF string given 30718 30719 // Before have to save selected inputs, cuz unstyle will reset all to beginning 30720 var checks = [];
30721 select.find('input:checked').each( function () { 30722 checks.push( jQuery(this).val() ); 30723 }); //FUNC each.callback 30724 30725 // Destyling select for easy add new inputs 30726 select = unstyleInput(select); 30727 30728 // Resetting options to to new setting 30729 select.find('option').each( function () { 30730 30731 var el = jQuery(this); 30732 if ( checks.indexOf( el.val() ) != -1 ) 30733 el.attr('selected', 'selected'); 30734 else 30735 el.removeAttr('selected'); 30736 30737 }); //FUNC each.callback 30738 30739 for ( var i in values ) { 30740 select.prepend('<option value="' + i + '"' + checked + '>' + values[i] + '</option>'); 30741 } //FOR each value 30742 30743 // Styling input back again 30744 styleDialog(select.parent()); 30745 30746 return false; 30747} //FUNC selectAddItem 30748 30749/** //** ----= inputClassString =----------------------------------------------\**//** \ 30750* 30751* Takes source element, and type classes. Prepares full class and style attributes. 30752* 30753* @param object el - Source input jQuery object. 30754* @param string typeClass - Additional classes to add. 30755* @return string - Attributes to add to element. 30756 bool - FALSE if no modification necessary. 30757* 30758\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 30759function inputClassString(el, typeClass) { 30760 30761 // If already styled - nothing to do again 30762 if ( el.hasClass('mw') ) return false; 30763 30764 // Saving source to allow fast unstyle 30765 el.data('source', getOuterHTML( el.get(0) )); 30766 30767 // Getting existing attributes 30768 var cls = el.attr('class'); 30769 30770 // Getting other transferrable attributes 30771 var $attr = {'class' : ''}; 30772 var $aList = ['style', 'size', 'data-prefix', 'data-suffix']; 30773 for ( var $i in $aList ) 30774 $attr[ $aList[$i] ] = el.attr($aList[$i]); 30775 30776 var styles = el.attr('style'); 30777 30778 // Composing classes 30779 var ctmp = ['mwInput', typeClass, cls]; 30780 30781 var name = el.attr('name'); 30782 if ( name ) { 30783 name = name.replace(/[\[\]]/g, ''); 30784 ctmp.push('name-'+name); 30785 } //IF name 30786 30787 // Storing class as attribute 30788 $attr['class'] = ctmp.join(' ').trim(); 30789 30790 // Processing results 30791 var $res = ''; 30792 for ( var $i in $attr ) 30793 if ( !isEmpty($attr[$i]) ) 30794 $res += ' '+$i+'="'+$attr[$i]+'"'; 30795 30796 // Cleaning source attributes 30797 el[0].className = ''; 30798 30799 for ( var $i in $aList ) 30800 el.removeAttr($aList[$i]); 30801 30802 // Adding styled marker 30803 el.addClass('mw'); 30804 30805 return $res; 30806} //FUNC inputClassString 30807 30808/** //** ----= styleDialog =----------------------------------------------\**//** \ 30809* 30810* Applies style to all inputs childs to specified element. 30811* 30812* @param MIXED el - Valid jQuery element selector. 30813* @return bool - Always FALSE. 30814* 30815\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 30816function styleDialog ( dialog ) { 30817 30818 dialog = _jq(dialog); 30819 30820// ---- TEXT ---- 30821 30822 dialog.find('INPUT[type=text], INPUT[type=search], INPUT[type=password], INPUT[type=email], INPUT[type=date], INPUT[type=number], INPUT[type=tel], INPUT[type=url]').each( function () { 30823 30824 var el = jQuery(this); 30825 30826 // Cleaning errors state on load 30827 //el.closest('.mwInput').removeClass('Error'); 30828 30829 // Checking if some of subcontrol classes are set and reading sub class 30830 var subs = false; 30831 var $sClass = ['plus', 'go', 'ok']; 30832 for ( var $i in $sClass ) 30833 if ( el.is('.'+$sClass[$i]) ) 30834 subs = $sClass[$i]; 30835 30836 // Compatabilty with renamed sub 30837 if ( subs == 'go' ) 30838 subs = 'ok'; 30839 30840 var tclass = 'text'; 30841 if ( subs ) tclass += ' wSub'; 30842 30843 var attr = inputClassString(el, tclass); 30844 if ( !attr ) return; 30845 30846 var wrap = jQuery('<div ' + attr + '></div>'); 30847 el.wrapAll(wrap); 30848 30849 // Researching wrap 30850 wrap = el.closest('.mwInput'); 30851 30852 // Adding some common subcontrols if set 30853 if ( subs ) { 30854 30855 var sub = jQuery('<div class="subcontrol button hi icon light '+ subs+'"></div>').insertBefore(el); 30856 var click = el.attr('onclick'); 30857 30858 if ( click ) 30859 sub.attr('onclick', click); 30860 30861 el.removeAttr('onclick'); 30862 } //IF is Plus 30863 30864 // Initiating date picker 30865 Date.format = 'yyyy-mm-dd'; 30866 if ( wrap.is('.date') ) { 30867 el.datePicker({ 30868 clickInput : true, 30869 createButton : false, 30870 verticalOffset : 26, 30871 startDate : '2000-01-01' 30872 }); 30873 } //IF date input 30874 30875 // Search input is special 30876 // Then adding icon and subcontrol 30877 // This allows better compatability than regular search, and finer styles control 30878 // Skipping manually added icons 30879 if ( wrap.is('.search:not(.icon)') ) { 30880 30881 // Adding search icon on left (it's already search, so just adding icon class) 30882 wrap.addClass('icon left'); 30883 30884 // Padding right is exactly same as left 30885 wrap.css( 'padding-right', wrap.css('padding-left') ); 30886 30887 // Adding clear subcontrol 30888 var $sub = jQuery('<div class="subcontrol icon right declined" style="display:none"></div>
30888').appendTo(wrap); 30889 30890 // Adding change event on input 30891 el.on('keyup.mwInput.search', function () { 30892 30893 if ( this.value ) 30894 $sub.show(); 30895 else 30896 $sub.hide(); 30897 30898 }); //On change 30899 30900 // Adding clear action 30901 $sub.on('click.mwInput.search.clear', function () { 30902 30903 el.val(''); 30904 $sub.hide(); 30905 30906 el.trigger('keyup'); 30907 30908 }); //on click 30909 30910 30911 } //IF search found 30912 30913 // Ensuring input size for prefix/suffix 30914 if ( wrap.is('[data-prefix], [data-suffix]') ) { 30915 30916 } //IF pfx 30917 30918 // Text inputs should select on forcus 30919 el.focus( function () { this.select() } ); 30920 30921 30922 /*/ 30923 // Adding required check 30924 if ( wrap.hasClass('required') ) { 30925 30926 el.keyup( function () { 30927 var e = jQuery(this); 30928 if ( e.val().trim() ) 30929 e.closest('.mwInput').removeClass('Error'); 30930 else 30931 e.closest('.mwInput').addClass('Error'); 30932 }); 30933 30934 } //IF required 30935 /**/ 30936 30937 }); //jQuery each text input 30938 30939// ---- TEXTAREA ---- 30940 30941 dialog.find('TEXTAREA').not('.mw, .tinyMCE, .mwTinyMCE, .richEdit').each( function () { 30942 var $el = jQuery(this); 30943 30944 $el.addClass('multiline'); 30945 30946 var $attr = inputClassString($el, 'textarea'); 30947 if ( !$attr ) return; 30948 30949 $el.wrapAll('<div ' + $attr + '></div>'); 30950 30951 // Researching wrapper 30952 var $wrap = $el.parent(); 30953 30954 // 100% size inputs are marked with class instead 30955 // and triggers default size for fallbacks 30956 if ( $wrap.attr('size') == '100%' ) 30957 $wrap.addClass('fullHeight').removeAttr('size'); 30958 30959 // Adding default height 30960 if ( !$wrap.attr('size') ) 30961 $wrap.attr('size', '3'); 30962 30963 }); //jQuery each textarea input 30964 30965 dialog.find('TEXTAREA.richEdit').not('.mw').each( function () { 30966 30967 // Doing nothing if no tinyMCE defined on page 30968 // No fallbacks, as developer should see that smth went wrong 30969 if ( typeof(tinyMCE) == 'undefined' ) 30970 return; 30971 30972 var el = jQuery(this); 30973 30974 el.addClass('multiline'); 30975 30976 // Marking element as initiated 30977 el.addClass('mw'); 30978 30979 // 100% size inputs are marked with class instead 30980 // and triggers default size for fallbacks 30981 if ( el.attr('size') == '100%' ) 30982 el.addClass('fullHeight').removeAttr('size'); 30983 30984 // Adding default height 30985 if ( !el.attr('size') ) 30986 el.attr('size', '5'); 30987 30988 // Giving it small delay, to let freshly loaded windows to cool a bit. 30989 setTimeout( function () { 30990 mwTinyMCE().init(el); 30991 }, 10); 30992 30993 }); //jQuery each textarea input 30994 30995// ---- BUTTONS ---- 30996 30997// dialog.find('BUTTON, INPUT[type=button], INPUT[type=submit]').each( function () { 30998 dialog.find('INPUT[type=button], INPUT[type=submit]').each( function () { 30999 31000 var el = jQuery(this); 31001 31002 // Quickly skipping tinyMCE buttons 31003 // Bit dirty, but tiny is supported natively 31004 // ToDo: init styles from original input instead (would come naturally once proper mwForms are implemented) 31005 if ( el.parent().is('.mce-btn') ) 31006 return; 31007 31008 var attr = inputClassString(el, 'button'); 31009 if ( !attr ) return; 31010 31011 el.wrapAll('<div ' + attr + '></div>'); 31012 31013 // Sumulating active for parent 31014 el 31015 .bind('mousedown', function () { 31016 jQuery(this).parent().addClass('active'); 31017 }) //FUNC onMouseDown 31018 .bind('mouseup', function () { 31019 jQuery(this).parent().removeClass('active'); 31020 }) //FUNC onMouseUp 31021 ; //jQuery element 31022 }); //jQuery each textarea input 31023 31024 dialog.find('INPUT[type=image]').each( function () { 31025 var el = jQuery(this); 31026 31027 var attr = inputClassString(el, 'button image'); 31028 if ( !attr ) return; 31029 31030 el.wrapAll('<div ' + attr + '></div>'); 31031 31032 // Sumulating active for parent 31033 el 31034 .bind('mousedown', function () { 31035 jQuery(this).parent().addClass('active'); 31036 }) //FUNC onMouseDown 31037 .bind('mouseup', function () { 31038 jQuery(this).parent().removeClass('active'); 31039 }) //FUNC onMouseUp 31040 ; //jQuery element 31041 }); //jQuery each textarea input 31042 31043// ---- SELECT ---- 31044 31045 dialog.find('SELECT').not('.checkList, .radioList, .browseButton, .selectEx').each( function () { 31046 var el = jQuery(this); 31047 31048 if ( el.is('SELECT[multiple], SELECT[size]') ) { 31049 31050 el.addClass('multiline'); 31051 31052 var attr = inputClassString(el, 'multiple'); 31053 if ( !attr ) return; 31054 31055 el.wrapAll('<div ' + attr + '></div>'); 31056 31057 // Researching wrapper 31058 var $wrap = el.parent(); 31059 31060 // 100% size inputs are marked with class instead 31061 // and triggers default size for fallbacks 31062 if ( $wrap.attr('size') == '100%' ) 31063 $wrap.addClass('fullHeight').removeAttr('size'); 31064 31065 // Adding default height 31066 if ( !$wrap.attr('size') ) 31067 $wrap.attr('size', '3'); 31068 31069 } //IF multiselect 31070 else { 31071 31072 var nowidth = el.hasClass('nowidth'); 31073 31074 var attr = inputClassString(el, 'select'); 31075 if ( !attr ) return; 31076 31077 // ---- Calculating selector min width ---- 31078 31079 var width = ''; 31080 31081 if ( !nowidth ) { 31082 var tmp = el.clone(); 31083 tmp.appendTo('BODY'); 31084 width = tmp.width() + 30; 31085 tmp.remove(); 31086 31087 width = ' style="min-width : ' + width + 'px"'; 31088 } //IF need width 31089 31090 el.wrapAll('<div ' + attr + '></div>'); 31091 el.addClass('hidden'); 31092 31093 var val = el.find('OPTION:selected').text(); 31094 31095 el.before('<div class="subcontrol icon gray dropdown"></div>'); 31096 el.before('<div class="value"' + width + '>
31096' + val + '</div>'); 31097 31098 el.on('change update', function () { 31099 el.prev('.value').html( el.find('OPTION:selected').text() ); 31100 }); //jQuery onChange 31101 31102 } //IF regular select 31103 31104 }); //jQuery each select input 31105 31106/**/ 31107// ---- CHECKLIST and RADIOLIST ---- 31108 31109// dialog.find('SELECT.checkList, SELECT.radioList').not('.old').each( function () { 31110 dialog.find('SELECT.checkList.new, SELECT.radioList.new').each( function () { 31111 31112 var $input = jQuery(this); 31113 31114 // ---- Defaults ----- 31115 31116 // Checklist forces multiselect 31117 if ( $input.is('.checkList') ) 31118 $input.attr('multiple', 'multiple'); 31119 31120 // Adding default height 31121 if ( !$input.attr('size') ) { 31122 31123 if ( $input.is('[multiple], .checkList, .radioList') ) 31124 $input.attr('size', '5'); 31125 else 31126 $input.attr('size', '1'); 31127 31128 // For mobiles - size is always 1 31129 if ( $input.is('.noMobile') && isTouchScreen() ) 31130 $input.attr('size', '1'); 31131 31132 } //IF autodeciding on size 31133 31134 // Preparing attributes 31135 var $attr = inputClassString($input, ''); 31136 if ( !$attr ) return; 31137 31138 // ---- Creating container element ---- 31139 31140 $input.wrapAll('<div ' + $attr + '></div>'); 31141 31142 // Researching wrapper, for later use 31143 var $wrap = $input.parent(); 31144 31145 // Flagging input type: inline/multiline 31146 if ( $wrap.attr('size') != '1' ) 31147 $wrap.addClass('multiline'); 31148 31149 // 100% size inputs are marked with class instead 31150 // and triggers default size for fallbacks 31151 if ( $wrap.attr('size') == '100%' ) 31152 $wrap.addClass('fullHeight').removeAttr('size'); 31153 31154 // ---- Model ---- 31155 31156 // Initiating selector model 31157 var $select = $input.mwSelectInput(); 31158 31159 }); //jQuery each morweb selector input 31160 31161 dialog.find('SELECT.checkList, SELECT.radioList').not('.new').each( function () { 31162// dialog.find('SELECT.checkList.old, SELECT.radioList.old').each( function () { 31163 31164 var sel = jQuery(this); 31165 31166 sel.addClass('multiline'); 31167 31168 if ( sel.is('.checkList') ) 31169 sel.attr('multiple', 'multiple'); 31170 31171 var attr = inputClassString(sel, 'list'); 31172 if ( !attr ) return; 31173 31174 // ---- Creating container and subcontainer elements ---- 31175 31176 var el = jQuery('<div ' + attr + '><div class="list"></div></div>'); 31177 var items = el.find('.list'); 31178 31179 // 100% size inputs are marked with class instead 31180 // and triggers default size for fallbacks 31181 if ( el.attr('size') == '100%' ) 31182 el.addClass('fullHeight').removeAttr('size'); 31183 31184 // Adding default height 31185 if ( !el.attr('size') ) 31186 el.attr('size', '5'); 31187 31188 // ---- Saving source ---- 31189 31190 // Selector itself will be replaced, so we need to save source in separate hidden element which will not affect nothing 31191 31192 var source_data = sel.data('source'); 31193 31194 var source = jQuery('<input type="hidden" class="mw">'); 31195 source.data('source', source_data); 31196 source.appendTo(el); 31197 31198 // ---- Transferring hint ---- 31199 31200 var hint = sel.attr('hint'); 31201 if ( hint ) 31202 items.attr('hint', hint); 31203 31204 // ---- Composing common attributes ---- 31205 31206 var radio = el.hasClass('radioList'); 31207 var name = sel.attr('name'); 31208 31209 // Checkboxes should be arrays 31210 // Not doing for selects that alrady had this 31211 if ( !radio && name && !name.endsWith('[]') ) 31212 name += '[]'; 31213 31214 // Input type 31215 var type = ( radio )? 'radio' : 'checkbox'; 31216 31217 // ---- Processing sub controls ---- 31218 31219 sel.find('OPTION').each( function () { 31220 31221 var op = jQuery(this); 31222 var title = op.html(); 31223 31224 // ---- Parsing title for special things ---- 31225 31226 // Column 31227 var col = ''; 31228 var d = title.indexOf('|'); 31229 if ( d >= 0 ) { 31230 col = title.substr(d + 1); 31231 title = title.substr(0, d) + '<div class="col">' + col + '</div>'; 31232 } //IF divider come 31233 31234 var $icon = op.attr('data-icon'); 31235 if ( $icon ) 31236 $icon = '<div class="icon" style="background-image: url(' + $icon + ');"></div>'; 31237 31238 31239 // Value/checked 31240 var val = op.val(); 31241 var checked = op.attr('selected'); 31242 31243 title = $icon + '<div class="title">' + title + '</div>'; 31244 31245 var titem = jQuery(title); 31246 31247 var input = jQuery('<input type="' + type + '" class="meta" name="' + name + '" value="' + val + '" />'); 31248 if ( checked ) input.attr('checked', 'checked'); 31249 31250 // Setting up actions 31251 var actions = ['onclick', 'onchange', 'ondblclick']; 31252 for ( var i in actions ) 31253 input.attr(actions[i], sel.attr(actions[i]) ); 31254 31255 input.change( function () { 31256 31257 var check = this.checked; 31258 31259 var el = jQuery(this); 31260 31261 if ( check ) { 31262 el.parent().addClass('selected icon hi left'); 31263 } else { //IF checked 31264 el.parent().removeClass('selected icon hi left') 31265 } //IF not checked 31266 31267 if ( this.type == 'radio') { 31268 if ( this.checked ) { 31269 jQuery(this) 31270 .parents('.mwInput.list') // Searching parent container 31271 .find('INPUT[type="radio"][name="' + this.name + '"]') //
31271Searching all items 31272 .not(this) // Excluding self 31273 .each( function () { // Triggering change on each 31274 jQuery(this).change(); 31275 }); //each radio 31276 } //IF got cheked state 31277 } //IF radio 31278 31279 }); //jQuery onChange 31280 31281 var $itemClass = 'item'; 31282 var $itemStyle = ''; 31283 31284 if ( checked ) $itemClass+=' selected icon hi left'; 31285/*/ 31286 var $src = op.attr('data-icon'); 31287 if ( $src ) { 31288 $itemClass += ' icon'; 31289 $itemStyle = 'background-image: url(' + $src + ');'; 31290 } //IF class 31291/**/ 31292 31293 $itemClass = $itemClass ? ' class="' + $itemClass + '"' : ''; 31294 $itemStyle = $itemStyle ? ' style="' + $itemStyle + '"' : ''; 31295 31296 var item = jQuery('<div' + $itemClass + $itemStyle + '></div>'); 31297 item.append(titem).append(input); 31298 31299 item.appendTo(items); 31300 }); //jQuery each option 31301 31302 sel.replaceWith(el); 31303 }); //jQuery each multiselect input 31304 31305 // ---- CHECKBOX and RADIO ---- 31306 31307 dialog.find('INPUT[type="checkbox"], INPUT[type="radio"]').not('.meta').each( function () { 31308 31309 var el = jQuery(this); 31310 31311 // Checking if custom titles are set 31312 var custom = el.attr('cap'); 31313 31314 var attr = inputClassString(el, 'checkbox' + ((custom)? ' custom' : '')); 31315 if ( !attr ) return; 31316 31317// ---- Processing custom titles ---- 31318 31319 // Webkit browsers require smth to have inside to propertly align, so setting nbsp as default 31320 var on = ' '; 31321 var off = ' '; 31322 31323 if ( custom ) { 31324 31325 // el.removeAttr('cap'); 31326 31327 custom = custom.split('|'); 31328 31329 var on = custom[0]; 31330 var off = (custom[1])? custom[1] : custom[0]; 31331 31332 } //IF title set 31333 31334 // ---- Wrapping layout structure ---- 31335 31336 el.wrapAll('<div ' + attr + '></div>'); 31337 el.addClass('hidden'); 31338 31339 el.before('<div class="icon hi left">_</div>'); 31340 31341 // ---- Applying change function ---- 31342 31343 el.change( function () { 31344 31345 var check = this.checked; 31346 31347 if ( check ) { 31348 el.parent().addClass('checked'); 31349 el.prev().html(on).addClass('selected'); 31350 el.addClass('checked'); 31351 } else { //IF checked 31352 el.parent().removeClass('checked') 31353 el.prev().html(off).removeClass('selected'); 31354 el.removeClass('checked'); 31355 } //IF not checked 31356 31357 }); //jQuery onChange 31358 31359 // Initiating first time 31360 el.change(); 31361 31362 // ---- Radio buttins refresh fix ---- 31363 31364 if ( this.type == 'radio' ) { 31365 31366 el.change( function () { 31367 31368 var radio = jQuery(this); 31369 31370 if ( this.checked ) { 31371 31372 // Searching neighbours via closest parent form. Fastest way. Usually there is form around. 31373 radio.closest('FORM') 31374 .find('INPUT[type="radio"][name="' + this.name + '"].checked') 31375 .not(this).change(); 31376 31377 } //IF got cheked state 31378 31379 }); //jQuery onChange 31380 31381 } //IF radio button 31382 31383 }); //jQuery each checbox and radio input 31384 31385// ---- FILES ---- 31386 31387 dialog.find('INPUT[type=file]').each( function () { 31388 31389 var el = jQuery(this); 31390 31391 var attr = inputClassString(el, 'file'); 31392 if ( !attr ) return; 31393 31394 // Detecting SN if set, and applying it as uBar 31395 var fid = el.attr('sn') || ''; 31396 31397 if ( fid ) 31398 fid = ' uBar_' + fid; 31399 31400 // Preparing structure and layout 31401 el.wrapAll('<div ' + attr + '></div>'); 31402 31403 // Reading input wrapper 31404 var $jWrap = el.closest('.mwInput'); 31405 31406 // Saving some properties 31407 var $size = el.attr('size') || $jWrap.attr('size') || 6; 31408 var $preview = el.attr('preview') || ''; 31409 31410 // Preparing preview element, it goes first 31411 var $jPreview = jQuery('<div class="filePreview"></div>'); 31412 el.before($jPreview); 31413 31414 // Adding additional face wrapper for layout control 31415 var $jFace = jQuery('<div class="fileFace divider"></div>'); 31416 31417 // Adding title progress control inside face 31418 var $jProgress = jQuery('<div class="subcontrol hi fill progressFill' + fid + '"></div>').appendTo($jFace); 31419 var $jTitle = jQuery('<div class="fileName"></div>').appendTo($jFace); 31420 var $jNum = jQuery('<div class="num progressNum' + fid + '"> </div>').appendTo($jFace); 31421 31422 // Attaching face 31423 el.before($jFace); 31424 31425 // Preparing controls 31426 // Upload/browse is unconditional, goes right after the face 31427 var $jUpload = jQuery('<div class="subcontrol button icon upload"></div>').insertAfter($jFace); 31428 31429 // Preparing download button, but not attaching it yet (this will be decided in updateFace() ) 31430 var $jDownload = jQuery('<div class="subcontrol button icon download hi"></div>'); 31431 31432 // Delete button present only if specified 31433 // Always inserted last 31434 // var $jDelete = jQuery('<div class="subcontrol button icon delete red"></div>');
31435 // $jDelete.insertBefore(el); 31436 31437 // Testing varying subcontrols count 31438 // el.before('<div class="subcontrol button icon ok"></div>'); 31439 // el.before('<div class="subcontrol button icon delete"></div>'); 31440 // el.before('<div class="subcontrol button icon download"></div>'); 31441 // el.before('<div class="subcontrol button icon search"></div>'); 31442 31443 // Autoconfiguring path for morweb editors 31444 // This is supported only for inputs added through form editor, which are part of files section 31445 // They should have gallery attribute, input should be part of window (this will indicate presence of morweb) 31446 // ToDo: This validation should be done outside by forms editor/custom inputs 31447 31448 // Custom paths are still supported normally 31449 var $fPath = el.attr('data-path'); 31450 var $fGallery = el.attr('gallery'); 31451 var $fPrivate = el.attr('private') || 0; 31452 var $fStorage = $fPrivate ? 'download' : 'files'; 31453 31454 // Path for gallery files are known 31455 // Checking if running inside window 31456 if ( !$fPath && $fGallery && el.closest('.mwWindow').length ) { 31457 31458 // Default path is in gallery 31459 var $fPath = '/'+$fStorage+'/galleries/'; 31460 31461 // Setting path as attribute 31462 el.attr('data-path', $fPath); 31463 31464 } //If no path set 31465 31466 // Using dedicated face update function 31467 function mwFileInputUpdateFace ($el) { 31468 31469 // Need jQuery 31470 $el = _jq($el); 31471 31472 // Checking if file/path set. 31473 // Both are required for preview and download 31474 var $file = $el.attr('data-file'); 31475 var $fileVal = fileName($el.get(0).value); 31476 var $path = $el.attr('data-path'); 31477 31478 31479 // Detecting value is present, and using as visual title 31480 var $title = $fileVal || $el.attr('data-file') || $el.attr('value') || $el.attr('src') || $el.attr('img') || $el.attr('cap') || 'Select File...'; 31481 31482 // Setting title 31483 $jTitle.html($title); 31484 31485 // Preparing preview url right away 31486 var $previewUrl = ''; 31487 31488 // File and path should be just present to create download button 31489 if ( $file && $path ) { 31490 31491 // Attaching download button 31492 $jDownload.insertAfter($jUpload); 31493 31494 // Preparing preview with direct path 31495 // Replacing /files with resizer: /getimage 31496 // This way - images available for resizer will be run through resizer, 31497 // and very custom images will stay as they are 31498 31499 // Previews are available only for images currently 31500 if ( isFileImage($file) ) { 31501 31502 var $previewUrl = $path.replace('/'+$fStorage+'/', '/getimage/'); 31503 $previewUrl += $file+'?resize='+Math.ceil( $jWrap.width() || 600 )+'x0'; 31504 31505 } //IF image file 31506 31507 } //IF file defined 31508 31509 else { 31510 31511 // Detaching download 31512 $jDownload.detach(); 31513 31514 // Resetting preview 31515 $previewUrl = ''; 31516 31517 } //IF no file 31518 31519 // ToDo: split input (hidden text with input name and name_file for file input) 31520 // ToDo: delete button support. Automated for split inputs, ondelete="" event enables delete button 31521 31522 // For preview - need to do additional checks 31523 // It's visibe when forced or when both file and path are present 31524 // Previe is visible in auto mode when either URL is set, or file source is set 31525 if ( !$fPrivate && (($preview == 'on') || ($preview && ($previewUrl || $fileVal))) ) { 31526 31527 // Filling in preview BG 31528 // Using as is, even if it happen to be empty (when preview box is forced) 31529 $jPreview.css({'background-image' : "url('"+$previewUrl+"')"}).show(); 31530 31531 // Setting input height 31532 $jWrap.attr('size', $size); 31533 31534 } //IF file defined 31535 31536 else { 31537 31538 // Clearing preview 31539 $jPreview.css({'background-image' : "url('')"}).hide(); 31540 31541 $jWrap.attr('size', ''); 31542 31543 } //IF no file 31544 31545 } //FUNC mwFileInputUpdateFace 31546 31547 // Adding download click 31548 $jDownload.click( function () { 31549 31550 // Support for "view file" requires both data path and value 31551 // Supporting download only for values set through fromArray() calls. 31552 // If file was browsed - can't download anyway 31553 var $file = el.attr('data-file'); 31554 var $path = el.attr('data-path'); 31555 31556 if ( !$file || !$path ) 31557 return; 31558 31559 // If gallery specified - using it to view file 31560 if ( !isEmpty($fGallery) ) { 31561 31562 // Compiling path to gallery view in backend 31563 $path = '/site/files/'+$fGallery+'/'; 31564 31565 } //IF actual gallery specified 31566 31567 // Using virtual form to safely click into new tab 31568 submitUrl($path+$file, {}, true); 31569 31570 });
31570 //FUNC $jDownload.click 31571 31572 // Adding preview click 31573 $jPreview.click( function () { 31574 31575 // Just triggering download 31576 $jDownload.click(); 31577 31578 }); //$jPreview.click 31579 31580 // Adding update on change 31581 el.change( function () { 31582 31583 // Preparing face 31584 mwFileInputUpdateFace(this); 31585 31586 // Preloading image if defined/selected 31587 if ( $preview && this.value ) 31588 mwBackgroundPreview($jPreview, this); 31589 31590 }); //el.change 31591 31592 // Running initial update 31593 mwFileInputUpdateFace(el); 31594 31595 }); //jQuery each select input 31596 31597// ---- BROWSER ---- 31598 31599 dialog.find('SELECT.selectEx').each( function () { 31600 31601 var $el = jQuery(this); 31602 31603 $el.addClass('multiline'); 31604 31605 var $attr = inputClassString($el, ''); 31606 if ( !$attr ) return; 31607 31608 // ---- Creating container element ---- 31609 31610 $el.wrapAll('<div ' + $attr + '></div>'); 31611 31612 // Researching wrapper, for later use 31613 var $wrap = $el.parent(); 31614 31615 // 100% size inputs are marked with class instead 31616 // and triggers default size for fallbacks 31617 if ( $wrap.attr('size') == '100%' ) 31618 $wrap.addClass('fullHeight').removeAttr('size'); 31619 31620 // Adding default height 31621 if ( !$wrap.attr('size') ) 31622 $wrap.attr('size', '6'); 31623 31624 // ---- Options ---- 31625 31626 var $o = { 31627 inline : $wrap.is('.inline') 31628 }; //$o 31629 31630 if ( $el.data('title') ) 31631 $o.title = $el.data('title'); 31632 31633 // Initiating selector 31634 // Checking inline mode by resulitng wrapper class 31635 var $sx = mwSelectEx($el, $o); 31636 31637 $el.data('selectEx', $sx); 31638 31639 }); //jQuery.each select 31640 31641// ---- COMMON ---- 31642 31643 // Tracking hovers/focus via java and classes to have extra styling options. 31644 // Unfortunately have to exclude few inputs 31645 31646 dialog.find('.mwInput').each( function () { 31647 31648 var $el = jQuery(this); 31649 31650 // Hover 31651 $el 31652 .off('mouseenter.mwInput') 31653 .on('mouseenter.mwInput', function () { 31654 $el.addClass('hover'); 31655 31656 if ( $el.parent().is('.combo') ) 31657 $el.parent().addClass('hover'); 31658 31659 }) //FUNC hoverin 31660 31661 .off('mouseleave.mwInput') 31662 .on('mouseleave.mwInput', function () { 31663 $el.removeClass('hover'); 31664 31665 if ( $el.parent().is('.combo') ) 31666 $el.parent().removeClass('hover'); 31667 31668 }) //FUNC hoverout 31669 ; //$el 31670 31671 $el.not('.selectEx') 31672 .off('focusin.mwInput') 31673 .on('focusin.mwInput', function () { 31674 $el.addClass('focus'); 31675 31676 if ( $el.parent().is('.combo') ) 31677 $el.parent().addClass('focus'); 31678 }) //FUNC hoverout 31679 31680 .off('focusout.mwInput') 31681 .on('focusout.mwInput', function () { 31682 $el.removeClass('focus'); 31683 31684 if ( $el.parent().is('.combo') ) 31685 $el.parent().removeClass('focus'); 31686 }) //FUNC hoverout 31687 ; //$el 31688 31689 }); //jQuery.each input 31690 31691 return false; 31692} //FUNC styleDialog 31693 31694/** //** ----= unstyleInput =----------------------------------------------\**//** \ 31695* 31696* Removes styles from input given. 31697* 31698* @param jQuery input - Valid jQuery input element selector. 31699* @return jQuery - New input element. 31700* 31701\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 31702function unstyleInput ( input ) { 31703 31704 // All styled inputs have .mw class. 31705 // Source is stored under jQuery's .data(). 31706 input = _jq(input); 31707 31708 // Making sure that we are pointing to input itself 31709/*/ 31710 if ( !input.is('.mw') ) 31711 input = input.find('.mw'); 31712 31713 var source = input.data('source'); 31714/*/ 31715 var source = input.find('.mw').data('source'); 31716/**/ 31717 31718 if ( source ) { 31719 source = jQuery(source); 31720 input.replaceWith(source); 31721 return source; 31722 } //IF source was stored 31723 31724 return input; 31725} //FUNC unstyleInput 31726 31727/** //** ----= unstyleDialog =----------------------------------------------\**//** \ 31728* 31729* Removes styles from inputs in given element. 31730* 31731* @param MIXED el - Valid jQuery element selector. 31732* @return bool - Always FALSE. 31733* 31734\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 31735function unstyleDialog ( dialog ) { 31736 31737 // All styled inputs have .mw class. 31738 // Source is stored under jQuery's .data(). 31739 dialog.find('.mw').each( function () { 31740 31741 var el = jQuery(this); 31742 31743 var source = el.data('source'); 31744 31745 if ( source ) 31746 el.closest('.mwInput', dialog).replaceWith(source); 31747 31748 }); //jQuery each .mw 31749 31750 return false;
31751} //FUNC unstyleDialog 31752 31753function setValidations (dialog, validations) { 31754 31755 if ( !dialog ) 31756 return; 31757 31758 dialog.find('INPUT, SELECT, TEXTAREA') 31759 .each( function () { 31760 31761 // Shortcuts to input and it's parent (morweb forms) 31762 var input = jQuery(this); 31763 var parent = input.closest('.mwInput'); 31764 if ( !parent.length ) 31765 parent = input; 31766 31767 // Input should have name to be validatable 31768 var name = input.attr('name'); 31769 if ( !name ) return; 31770 31771 // Shortcut to messages array to simplify code 31772 var msgs = validations[name]; 31773 31774 // Might be complex input name, so checking for that 31775 if ( isUndefined(msgs) ) { 31776 31777 // Splitting name to parts 31778 // Safe to do event if it's not complext - will end up with same name 31779 var $tmp = name.split(/\[|\]/); 31780 31781 // Clearing empties 31782 // $tmp = $tmp.filter(n => n); 31783 $tmp = $tmp.filter(Boolean); 31784 31785 // Finally - using last element 31786 name = $tmp.slice(-1)[0]; 31787 msgs = validations[name]; 31788 31789 } //IF nothing found 31790 31791 // TinyMCE support 31792 // Marking tinyEditor instead of input itself 31793 if ( input.is('.mwTinyMCE') ) { 31794 31795 // If it's tinyMCE input - there should be sibling mceEditor input 31796 input = input.siblings('.mceEditor'); 31797 parent = input; 31798 31799 // If none - smth went wrong 31800 if ( !input.length ) 31801 return; 31802 } //IF tinyMCE input 31803 31804 // Removing errors attribute if no messages 31805 if ( !msgs ) { 31806 31807 input.removeAttr('error'); 31808 31809 // Class for parent 31810 parent.removeClass('error'); 31811 31812 return; 31813 } //IF no messages 31814 31815 // Compiling messages, very simple br can be stored inside attribute 31816 var msg = implode('<br />', msgs); 31817 31818 // Setting error 31819 input.attr('error', msg); 31820 31821 // Class for parent 31822 parent.addClass('error'); 31823 31824 }); //jQuery.each.callback 31825 31826 return; 31827} //FUNC setValidations 31828 31829/** //** ----= fillViews =----------------------------------------------\**//** \ 31830* 31831* Fills fileds views within specified element. 31832* 31833* @param jQuery el - Context element. 31834* @param object obj - Data object to pull views from. 31835* 31836* @return bool - Always FALSE. 31837* 31838\**//** ------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 31839function fillViews (el, obj) { 31840 31841 el = _jq(el); 31842 31843 for ( var i in obj ) { 31844 el.find('.view-' + i).html(obj[i]); 31845 } //FOR each field 31846 31847 return false; 31848} //FUNC fillViews 31849/** //** ----= CLASS mwSelectInput =------------------------------------------------------------------------------\**//** \ 31850* 31851* Selector input JS model. Supports dropdowns, multiselects, custom item input, inline filtering and adding new items. 31852* 31853* @package morweb 31854* @subpackage system 31855* @category model 31856* 31857\**//** ---------------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 31858jQuery.fn.mwSelectInput = function ($options) { 31859 31860 if ( !this.length ) 31861 return; 31862 31863 // Retrieving or creating model 31864 var $obj = this.data('mwSelectInput') || mwSelectInput(this); //.set($options); 31865 31866 // Storing in element 31867 this.data('mwSelectInput', $obj); 31868 31869 // Done 31870 return $obj; 31871 31872} //FUNC mwSelectInput 31873 31874function mwSelectInput ( $el, $options ) { return vEventObject(['onInit', 'onChange', 'onFilter', 'onAdd'], { 31875 31876 dom : { // Contains shortcuts to usable elements 31877 31878 // Main 31879 container : false, // mwInput element 31880 input : false, // Main input (hidden) 31881 31882 // Panels 31883 face : false, // Face bar, wrapping around value input and dropdown button 31884 filter : false, // Filter input, used to filter items in list 31885 body : false, // Main dropdown body (filter and items container) 31886 list : false, // Items wrapper 31887 31888 // Controls 31889 iValue : false, // Value input, used to to display selected value or as custom input 31890 iSearch : false, // Search input, used to filter items in list 31891 btnDown : false, // Dropdown button subcontrol 31892 btnAdd : false, // Button for adding custom values 31893 btnClear : false, // Button for resetting search filter 31894 31895 // Misc 31896 items : false, // Individual rendered option items 31897 31898 overlay : false, // Overlay, when used 31899 31900 }, //dom 31901 31902 multiselect : false, // Set TRUE to allow multiple values (checkList) 31903 multiline : false, // Set TRUE to use as multiline input 31904 filter : false, // Set TRUE to use inline filtering 31905 custom : false, // Set TRUE to allow custom values (additinal input) 31906 noMobile : false, // Set TRUE to skip init when used with mobile device (relies on native experience) 31907 31908 resizeDelay : 5, // Resize update delay 31909 resizeTimout : false, // Stores timout during window resizing 31910 31911/* ==== SETUP =============================================================================================================== */ 31912 31913 /** //** ----= set =--------------------------------------------------------------------------------------\**//** \ 31914 * 31915 * Updates self properties with given values. 31916 * 31917 * @param MIXED $option - Option to set. Can be data object to setup several properties. 31918 * @param MIXED [$value] - Value to set. Not used if object passes as first parameter. 31919 * 31920 * @return SELF 31921 * 31922 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 31923 set : function ($option, $value) { 31924 31925 var $this = this; 31926 31927 // Values can come as object, or single value 31928 // Applying using object, for code unification below 31929 // Any variable are accepted, to allow custom data storage 31930 var $o = {}; 31931 31932 if ( arguments.length === 1 ) 31933 $o = $option; 31934 else 31935 $o[$option] = $value; 31936 31937 // ==== Events ==== 31938 31939 // Processing events, as those should be cleared before extending 31940 for ( var $i in $o ) { 31941 31942 // Skipping non events and non funcitons 31943 if ( !this.__events[$i] || !isFunction($o[$i]) ) 31944 continue; 31945 31946 // Setting up event, and removing it from opitons 31947 this[$i]($o[$i]); 31948 delete($o[$i]); 31949 31950 } //FOR each opiton 31951 31952 // ==== Self ==== 31953 31954 jQuery.extend(this, $o); 31955 31956 return this; 31957 31958 }, //FUNC set 31959 31960/* ==== INIT ================================================================================================================ */ 31961 31962 /** //** ----= init =--------------------------------------------------------------------------------------\**//** \ 31963 * 31964 * Initiates payment form. 31965 * 31966 * @return self 31967 * 31968 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 31969 init : function () { 31970 31971 var $this = this; 31972 31973 // ---- Main ---- 31974
31975 // Saving main input and looking for wrapper 31976 $this.dom.input = $el; 31977 $this.dom.container = $el.closest('.mwInput'); 31978 31979 // Few shortcuts 31980 var $container = $this.dom.container; 31981 var $input = $this.dom.input; 31982 31983 // Adding required classes to wrapper 31984 $this.dom.container.addClass('list'); 31985 31986 // ---- Flags ---- 31987 31988 // Reading flags from wrapper and input 31989 // ToDo: improove flags management: classes should be guaranteed during render, for CSS. 31990 // Need to put back applied flags 31991 $this.set({ 31992 multiselect : $input.is('[multiple]'), 31993 multiline : $container.is('.multiline'), 31994 filter : $container.is('.filter'), 31995 custom : $container.is('.custom'), 31996 noMobile : $container.is('.noMobile'), 31997 }); //set 31998 31999 // ---- Mobile ---- 32000 32001 // If mobile is used - need to skip render optionally 32002 if ( $this.noMobile && isTouchScreen() ) { 32003 32004 // For mobile version - skipping render, but showing regular select instead 32005 // Adding marker 32006 $this.dom.container.addClass('isMobile'); 32007 32008 return; 32009 32010 } //IF mobile 32011 32012 // ---- DOM ---- 32013 32014 // Hiding main select element 32015 $this.dom.input.hide(); 32016 32017 // Rendering face first 32018 $this.renderFace(); 32019 32020 // Then goes body, everything else would be inside 32021 $this.renderBody(); 32022 32023 // ---- Styles ---- 32024 32025 32026 // ---- Events ---- 32027 32028 $this.initEvents(); 32029 32030 // Initial update 32031 $this.update(); 32032 32033 return $this; 32034 32035 }, //FUNC init 32036 32037 /** //** ----= initEvents =------------------------------------------------------------------------------\**//** \ 32038 * 32039 * Initializes events. All in one place, for easier management. 32040 * 32041 * @return SELF 32042 * 32043 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 32044 initEvents : function ( ) { 32045 32046 // Few shortucts 32047 var $this = this; 32048 var $input = $this.dom.input; 32049 var $container = $this.dom.container; 32050 32051 // When select updates - it should update items and face 32052 $this.dom.input.on('change.mwSelect', function () { 32053 32054 $this.update(); 32055 32056 }); //FUNC input.onchange 32057 32058 // Adding item clicks, listening on body, in case reinit/changes happen in list or items 32059 $this.dom.body.on( 'click.mwSelect', '.item', function () { 32060 32061 // Getting elements 32062 var $item = jQuery(this); 32063 var $option = $item.data('option'); 32064 32065 // No need to do anything if already selected option is clicked again 32066 // Applicable only for non-multiselect 32067 if ( !$this.multiselect && $option.prop('selected') ) 32068 return; 32069 32070 // Updating property only. Attribute will be also updated by updateItems() 32071 // Doing this way to ensure that correct attributes are updated on all items 32072 $option.prop( 'selected', !$option.prop('selected') ); 32073 32074 // Triggering change on main input 32075 $this.dom.input.trigger('change'); 32076 32077 }); //FUNC item.onclick 32078 32079 // Filter executs on key presses, if input available 32080 if ( $this.filter ) { 32081 32082 $this.dom.iSearch.on('keyup.mwSelect', function () { 32083 32084 // Updating items, this will apply filter 32085 $this.update(); 32086 32087 }); //FUNC input.onchange 32088 32089 $this.dom.btnClear.on('click.mwSelect', function () { 32090 32091 // Just clearing filter value and updating items 32092 $this.dom.iSearch.val(''); 32093 32094 // Updating items, this will apply filter 32095 $this.update(); 32096 32097 }); //FUNC input.onchange 32098 32099 } //IF filter enabled 32100 32101 // In inline mode - need to show/hide body 32102 if ( !$this.multiline ) { 32103 32104 // Dropdown button always works 32105 $this.dom.btnDown.on('click.mwSelect', function () { 32106 32107 // Showing/hiding depending on state 32108 $this.toggleBody(); 32109 32110 }); //FUNC button.onclick 32111 32112 // For non-custom inputs - value also toggles body 32113 if ( !$this.custom ) 32114 // Dropdown button always works 32115 $this.dom.iValue.on('click.mwSelect', function () { 32116 32117 // Showing/hiding depending on state 32118 $this.toggleBody(); 32119 32120 }); //FUNC input.onclick 32121 32122 32123 } //IF inline mode 32124 32125 }, //FUNC initEvents 32126 32127/* ==== Render ============================================================================================================== */ 32128 32129 /** //** ----= renderBody =------------------------------------------------------------------------------\**//** \ 32130 * 32131 * Renders main body element. 32132 * 32133 * @return SELF 32134 * 32135 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 32136 renderBody : function ( ) { 32137 32138 // Few shortucts 32139 var $this = this; 32140 var $input = $this.dom.input; 32141 var $container = $this.dom.container; 32142 32143 // Marking body as inline if necessary for CSS 32144 var $mode = $this.multiline ? 'multiline absoluteFill' : 'mwInput oneline'; 32145 $this.dom.body = jQuery('<div class="body '+$mode+'"></div>').appendTo($container); 32146 32147 // Reset of css would be set on display 32148 32149 // ---- Children ---- 32150
32151 // Rendering filter, it goes inside body 32152 $this.renderFilter(); 32153 32154 // Now can render items list 32155 $this.renderList(); 32156 32157 return $this; 32158 32159 }, //FUNC renderBody 32160 32161 /** //** ----= renderFace =------------------------------------------------------------------------------\**//** \ 32162 * 32163 * Renders face panel. Used to display current value and entering custom value for inline mode. 32164 * 32165 * @return SELF 32166 * 32167 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 32168 renderFace : function ( ) { 32169 32170 // Few shortucts 32171 var $this = this; 32172 var $input = $this.dom.input; 32173 var $container = $this.dom.container; 32174 32175 // Adding face controls only for inline input 32176 if ( $this.multiline ) 32177 return $this; 32178 32179 // Creating elements as one html chunk, then finding referrences afterwards 32180 var $html = ''; 32181 32182 // Subcontrol button goes first, as it's floating 32183 $html = '<div class="subcontrol right icon gray dropdown"></div>'; 32184 32185 // Input is wrapped in div to behave properly with floated element nearby 32186 $html = $html+'<div class="subInput value"><input type="text" class="mw" /></div>'; 32187 32188 // Finally - entire thing is wrapped into another element 32189 $html = '<div class="face">'+$html+'</div>'; 32190 32191 // Appending entire thing to container 32192 jQuery($html).appendTo($container); 32193 32194 // Looking for individual elements now 32195 $this.dom.iValue = $container.find('.subInput.value input'); 32196 $this.dom.btnDown = $container.find('.subcontrol.dropdown'); 32197 $this.dom.face = $container.find('.face'); 32198 32199 // If custom input is not used - value is only for display, so making it readonly 32200 if ( !$this.custom ) 32201 $this.dom.iValue.attr('readonly', 'readonly'); 32202 32203 return $this; 32204 32205 }, //FUNC renderFace 32206 32207 /** //** ----= renderFilter =------------------------------------------------------------------------------\**//** \ 32208 * 32209 * Renders filter panel. Used to filter items list, and adding custom values for multiselects. 32210 * 32211 * @return SELF 32212 * 32213 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 32214 renderFilter : function ( ) { 32215 32216 // Few shortucts 32217 var $this = this; 32218 var $input = $this.dom.input; 32219 var $container = $this.dom.container; 32220 32221 // Adding filter only if it's allowed 32222 if ( !$this.filter ) 32223 return $this; 32224 32225 // Filter is positioned inside body wrapper, to display and hide together with list 32226 // Preparing html for filter bar 32227 32228 // Subcontrols buttons go first, as they're floating 32229 var $html = ''; 32230 $html += '<div class="subcontrol left icon gray search"></div>'; 32231 $html += '<div class="subcontrol right button icon hi plus add"></div>'; 32232 $html += '<div class="subcontrol right icon delete clear gray"></div>'; 32233 32234 // Input is wrapped in div to behave properly with floated element nearby 32235 $html = $html+'<div class="subInput search"><input type="text" class="mw" /></div>'; 32236 32237 // Finally - entire thing is wrapped into another element 32238 $html = '<div class="filter">'+$html+'</div>'; 32239 32240 // Appending entire thing to container 32241 jQuery($html).appendTo($this.dom.body); 32242 32243 // Looking for individual elements now 32244 $this.dom.filter = $this.dom.body.find('.filter'); 32245 32246 $this.dom.iSearch = $this.dom.filter.find('.subInput.search input'); 32247 $this.dom.btnAdd = $this.dom.filter.find('.subcontrol.add'); 32248 $this.dom.btnClear = $this.dom.filter.find('.subcontrol.clear'); 32249 32250 return $this; 32251 32252 }, //FUNC renderFilter 32253 32254 /** //** ----= renderList =------------------------------------------------------------------------------\**//** \ 32255 * 32256 * Renders items panel, including individual items. 32257 * 32258 * @return SELF 32259 * 32260 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 32261 renderList : function ( ) { 32262 32263 // Few shortucts 32264 var $this = this; 32265 var $input = $this.dom.input; 32266 var $container = $this.dom.container; 32267 32268 // ---- Wrap ---- 32269 32270 // Clearing old wrapper if any happen 32271 if ( $this.dom.list ) 32272 $this.dom.list.remove(); 32273 32274 // Recreating items wrapper 32275 $this.dom.list = jQuery('<div class="list"></div>').appendTo( $this.dom.body ); 32276 32277 // ---- Items ---- 32278 32279 // Resetting items collection 32280 $this.dom.items = jQuery([]); 32281 32282 // Looping through options and generating items 32283 // ToDo: support grouping, custom icons, columns and more 32284 $input.find('option').each( function () { 32285 32286 var $option = jQuery(this); 32287 32288 // Rendering item into body 32289 var $item = $this.renderItem($option).appendTo( $this.dom.list ); 32290 32291 // And storing it in self for future reuse 32292 $this.dom.items = $this.dom.items.add($item); 32293 32294 }); //FOR each item 32295
32296 return $this; 32297 32298 }, //FUNC renderList 32299 32300 /** //** ----= renderItem =------------------------------------------------------------------------------\**//** \ 32301 * 32302 * Renders single item. 32303 * 32304 * @return SELF 32305 * 32306 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 32307 renderItem : function ( $option ) { 32308 32309 // Few shortucts 32310 var $this = this; 32311 32312 // ---- Text ---- 32313 32314 var $text = $option.html(); 32315 32316 // ---- Image ---- 32317 32318 // Preparing image if any 32319 var $image = $option.attr('data-image'); 32320 var $imageHtml = ''; 32321 32322 if ( $image ) { 32323 32324 $imageHtml = '<div class="image" style="background-image: url(\''+$image+'\')"></div>'; 32325 32326 } //IF image provided 32327 32328 // ---- Counter ---- 32329 32330 // Adding counter 32331 var $count = $option.attr('data-count'); 32332 var $countHtml = ''; 32333 32334 if ( $count ) { 32335 32336 $countHtml = '<div class="count">'+$count+'</div>'; 32337 32338 } //IF count provided 32339 32340 // ---- Item ---- 32341 32342 // Creating item 32343 var $item = jQuery('<div class="item icon hi left">'+$imageHtml+$countHtml+$text+'</div>'); 32344 32345 // Setting up links 32346 $option.data('item', $item); 32347 $item.data('option', $option); 32348 32349 return $item; 32350 32351 }, //FUNC renderItem 32352 32353 /** //** ----= renderOverlay =------------------------------------------------------------------------------\**//** \ 32354 * 32355 * Renders overlay. 32356 * 32357 * @return SELF 32358 * 32359 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 32360 renderOverlay : function ( ) { 32361 32362 // Few shortucts 32363 var $this = this; 32364 32365 // Adding overlay to page 32366 $this.dom.overlay = jQuery('<div class="mwInputOverlay mwInput list"></div>').appendTo('body'); 32367 32368 // Marking body with class as flag 32369 // And Moving body inside overlay 32370 $this.dom.body 32371 // .addClass('show') 32372 .appendTo($this.dom.overlay); 32373 32374 // Click on overlay hides stuff 32375 $this.dom.overlay.on('click', function ($e) { 32376 32377 $this.hideBody(); 32378 32379 $e.stopPropagation(); 32380 32381 }); //FUNC overlay.click 32382 32383 // Preventing click on body for closing (only for multiselects) 32384 32385 if ( $this.multiselect ) 32386 $this.dom.body.on('click', function ($e) { 32387 32388 $e.stopPropagation(); 32389 32390 }); //FUNC body.click 32391 32392 // Filter never closes anyway 32393 if ( $this.filter ) 32394 $this.dom.filter.on('click', function ($e) { 32395 32396 $e.stopPropagation(); 32397 32398 }); //FUNC body.click 32399 32400 // ---- Resize ---- 32401 32402 // If body resizes for some readon - need to update selector position 32403 // Doing this only for inline mode 32404 32405 // Initiating window resize after small delay 32406 // to skip initial browser resizie events 32407 setTimeout( function () { 32408 32409 // Updating dimensions on resize 32410 jQuery(window).on('resize.mwSelect', function ($e) { 32411 32412 // Using timeout during resize, to reduce updates count 32413 if ( $this.resizeTimout ) 32414 clearTimeout($this.resizeTimout); 32415 32416 $this.resizeTimout = setTimeout( function () { 32417 32418 $this.updatePosition(); 32419 32420 }, $this.resizeDelay); 32421 32422 }); //window.onResize 32423 32424 }, 50); 32425 32426 return $this; 32427 32428 }, //FUNC renderOverlay 32429 32430/* ==== Display ============================================================================================================= */ 32431 32432 /** //** ----= showBody =--------------------------------------------------------------------------------------\**//** \ 32433 * 32434 * Displays body, recalculating positions. 32435 * 32436 * @return SELF 32437 * 32438 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 32439 showBody : function ( ) { 32440 32441 // Few shortucts 32442 var $this = this; 32443 32444 // Creating overlay, this will also move body inside 32445 $this.renderOverlay(); 32446 32447 // Displaying overlay 32448 $this.dom.overlay.show(); 32449 32450 setTimeout( function () { 32451 32452 // While it adjusts - can now reposition body 32453 // At this point - everything is rendered and have dimensions 32454 $this.updatePosition(); 32455 32456 // Finally - executing fade/slide animation 32457 $this.dom.body.addClass('show') 32458 $this.dom.overlay.addClass('show'); 32459 32460 }, 1); 32461 32462 }, //FUNC showBody 32463 32464 /** //** ----= hideBody =--------------------------------------------------------------------------------------\**//** \ 32465 * 32466 * Hides body. 32467 * 32468 * @return SELF 32469 * 32470 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 32471 hideBody : function ( ) { 32472 32473 // Few shortucts 32474 var $this = this; 32475 32476 // Hiding overlay and unflagging body 32477 $this.dom.overlay.removeClass('show'); 32478 $this.dom.body.removeClass('show'); 32479 32480 // Allowing it to play animation with timeout 32481 setTimeout( function () { 32482 32483 // Putting body back, where it belongs :) 32484 // This will also hide it. Inline body is display:none outside overlay 32485 $this.dom.body.appendTo( $this.dom.container ); 32486 32487 // Removing overlay from DOM now 32488 $this.dom.overlay.remove(); 32489 32490 // Clearing resizing tracking 32491 jQuery(window).off('resize.mwSelect'); 32492 32493 }, 200); 32494 32495 }, //FUNC hideBody 32496
32497 /** //** ----= toggleBody =------------------------------------------------------------------------------\**//** \ 32498 * 32499 * Toggles body visibility, depending on current state. 32500 * 32501 * @return SELF 32502 * 32503 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 32504 toggleBody : function ( ) { 32505 32506 // Few shortucts 32507 var $this = this; 32508 32509 // Just looking at body state 32510 if ( $this.dom.body.is('.show') ) { 32511 $this.hideBody(); 32512 } //IF visible 32513 else { 32514 $this.showBody(); 32515 } //IF hidden 32516 32517 }, //FUNC toggleBody 32518 32519/* ==== HELPERS ============================================================================================================= */ 32520 32521 /** //** ----= getPosition =-------------------------------------------------------------------------------\**//** \ 32522 * 32523 * Returns panel position relative to screen. 32524 * 32525 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 32526 getPosition : function () { 32527 32528 var $this = this; 32529 var $el = $this.dom.container; 32530 32531 var $offs = $el.offset(); 32532 var $sTop = jQuery(window).scrollTop(); 32533 var $sLeft = jQuery(window).scrollLeft(); 32534 32535 // Recalculating coords based on scroll position 32536 $offs.top = $offs.top - $sTop; 32537 $offs.left = $offs.left - $sLeft; 32538 32539 return $offs; 32540 32541 }, //FUNC getPosition 32542 32543 /** //** ----= updatePosition =-------------------------------------------------------------------------------\**//** \ 32544 * 32545 * Updates body position against element 32546 * 32547 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 32548 updatePosition : function () { 32549 32550 var $this = this; 32551 32552 // Not doing anything for non-inline mode and if not visible 32553 if ( $this.multiline ) 32554 return; 32555 32556 // Few shortcuts 32557 var $input = $this.dom.container; 32558 var $body = $this.dom.body; 32559 32560 // Getting input coordinates and screen size 32561 var $pos = $this.getPosition(); 32562 var $screen = screenSize(); 32563 32564 // Calculating margi as % of screen height 32565 // Carrying only about height, since that's what is mostly positioned 32566 var $margin = $screen.height * 0.05; 32567 32568 // Getting real body height and calculating max allowed 32569 // For this - clearing height first 32570 $this.dom.list.css('max-height', ''); 32571 32572 var $height = $body.height(); 32573 var $limit = $height; 32574 var $max = $screen.height - ($margin * 2); 32575 32576 // Calculating real height limit (should be set on list inside body) 32577 // Clearing if not necessary anymore (screen resize) 32578 if ( $height > $max ) { 32579 32580 $limit = $max; 32581 32582 // Accounting for filter if present 32583 $this.dom.list.css('max-height', $limit - ($this.filter ? $this.dom.filter.outerHeight() : 0)); 32584 32585 } //IF too big 32586 32587 // Calculating new top based on real height and limits 32588 // Starting from middle of input 32589 var $top = ($pos.top + ($this.dom.container.height() / 2)) - ($limit / 2); 32590 32591 // Correcting top: it should be lower than margin 32592 if ( $top < $margin ) 32593 $top = $margin; 32594 32595 // But also can't be too low (top+height higher than margin) 32596 if ( $top + $limit > $screen.height - $margin ) 32597 $top = $screen.height - $margin - $limit; 32598 32599 // Adjusting body 32600 // Slightly adjusting sizes, to do not mess with borders recalculations 32601 // ToDo: read borders from skin 32602 $this.dom.body.css({ 32603 width : $this.dom.container.width() - 2, 32604 left : $pos.left + 1, 32605 top : $top, //$pos.top + ($this.dom.container.height() / 2), 32606 }); //$css 32607 32608 }, //FUNC updatePosition 32609 32610 /** //** ----= update =--------------------------------------------------------------------------------------\**//** \ 32611 * 32612 * Updates item states based on current selector state. Uses filtering if available. 32613 * Additionally updats filter states, and face if available. 32614 * 32615 * @return SELF 32616 * 32617 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 32618 update : function ( ) { 32619 32620 // Few shortucts 32621 var $this = this; 32622 32623 // Reading/updating filter 32624 var $filter = ''; 32625 32626 if ( $this.filter ) { 32627 32628 $filter = $this.dom.iSearch.val(); 32629 32630 // Showing/hiding clear button 32631 if ( $filter ) 32632 $this.dom.btnClear.show(); 32633 else 32634 $this.dom.btnClear.hide(); 32635 32636 } //IF filter used 32637 32638 // Updating face when applicable 32639 // For this - collecting selected values, and concatenating them into lavel afterwards 32640 var $val = []; 32641 32642 // Just looping through items list and setting selected class 32643 $this.dom.items.each( function () { 32644 32645 var $item = jQuery(this); 32646 var $option = $item.data('option'); 32647 32648 // Checking if matching filter, or just showing them all 32649 if ( $filter ) { 32650 32651 // Using regex seaerch for case insensitivity 32652 // ToDo: escape filter value 32653 if ( $option.html().search( new RegExp($filter, 'i') ) == -1 ) 32654 $item.hide(); 32655 else 32656 $item.show(); 32657 32658 } //If filter applied 32659 else { 32660 32661 // Just showing, this makes sure we display all items if filter was just cleared 32662 $item.show(); 32663 32664 } //IF filter not applied or just cleared 32665 32666 // Marking item as selected 32667 if ( $option.prop('selected') ) 32668 $item.addClass('selected'); 32669 else 32670 $item.removeClass('selected'); 32671 32672 // Collecting selected values for face update 32673 if ( $option.prop('selected') ) { 32674 32675 $val.push( $option.text().trim() ); 32676 32677 } //IF found selected 32678 /*/ 32679 // Additionally - setting selected atribute on option, for whoever needs this 32680 // But this is supported only on multiselects 32681 // This appears to be quite slow for obvious reasons, so skipping it for now as noone really needs it :) 32682 if ( !$this.dom.input.is('[multiple]') ) 32683 return; 32684 32685 if ( $option.prop('selected') ) 32686 $option.attr('selected', 'selected'); 32687 else 32688 $option.removeAttr('selected', ''); 32689 /**/ 32690 }); //FOR each item 32691 32692 // If nothing found - using first option to display something (that's what would be submitted in the end) 32693 // Only for non multiline selectors though 32694 if ( !$this.multiselect && isEmpty($val) && $this.dom.items.length ) { 32695 $val.push( $this.dom.items.first().data('option').text().trim() ); 32696 } //IF no values 32697 32698 // Now can apply value 32699 if ( !$this.multiline ) 32700 $this.dom.iValue.val( $val.join(', ') || '- Please select one or multiple -' ); 32701 32702 }, //FUNC update 32703 32704}).init()} //CONSTRUCTOR mwCodeInput 32705 32706/** //** ----= updateLandingCookie =--------------------------------------------------------------------------------------\**//** \ 32707* 32708* Basic landing cookie manager. 32709* 32710* @param string [$page] - Source page to redirect from. By default current page is used. 32711* @param MIXED $url - Target url. If link element specified - will use href attribute. 32712* If set to FALSE redirect will be deleted. 32713* 32714\**//** ---------------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 32715function updateLandingCookie ($page, $url) { 32716 32717 // Preparing target 32718 $page = !isEmpty($page) ? $page : location.pathname; 32719 32720 // Reading url 32721 $url = $url.pathname ? $url.pathname : $url; 32722 32723 // Reading current cookie, to update/add new redirect 32724 var $c = getCookie('mwLandingUrls', {}); 32725 32726 if ( !isObject($c) ) 32727 $c = JSON.parse($c); 32728 32729 // Adding/updating/removing redirect 32730 if ( $url ) 32731 $c[$page] = $url; 32732 else 32733 delete($c[$page]); 32734 32735 // Saving cookie 32736 $c = JSON.stringify($c); 32737 setCookie('mwLandingUrls', $c); 32738 32739} //FUNC updateLandingCookie 32740 32741/** //** ----= setLandingUrl =--------------------------------------------------------------------------------------\**//** \ 32742* 32743* Stores landing cookie for specified page. 32744* 32745* @param MIXED $url - Target url. If link element specified - will use href attribute. 32746* @param string [$page] - Source page to redirect from. By default current page is used. 32747* 32748\**//** ---------------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 32749function setLandingUrl ($url, $page) { 32750 updateLandingCookie($page, $url); 32751} //FUNC setLandingUrl 32752 32753/** //** ----= clearLandingUrl =--------------------------------------------------------------------------------------\**//** \ 32754* 32755* Clears landing cookie for specified page. 32756* 32757* @param string $page - Source page to clear redirect for. If link element specified - will use href attribute. 32758* 32759\**//** ---------------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 32760function clearLandingUrl ($page) { 32761 32762 // Reading target 32763 $page = $page.pathname ? $page.pathname : $page; 32764 32765 if ( !$page ) 32766 return; 32767 32768 updateLandingCookie($page, false); 32769 32770} //FUNC clearLandingUrl 32771/** //** ----= CLASS mwImgEd =--------------------------------------------------------------------------------------\**//** \ 32772* 32773* Morweb express image editor. Used to fast edit images inside <img>. 32774* 32775* @package MorwebManager 32776* @subpackage Core 32777* @category editor 32778* 32779* @param jQuery $img - Image to edit 32780* @param object [$o] - Initial options. 32781* 32782* @todo Implement disabled moving and/or resizing. 32783* 32784\**//** ---------------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 32785function mwImgEd ($img, $options) { 32786 32787 if ( !$img ) 32788 throw( 'Image unspecified' ); 32789 32790 $img = _jq($img); 32791 32792 // Checking if editor was cached in element 32793 // Not using currently to do not bother with unbinds 32794// var $class = $img.data('mwImgEd') || { 32795 var $class = { 32796 32797// ==== PROPERTIES ============================================================================================================= 32798 32799 url : '', // Source image url 32800 query : {}, // Stores parsed query of image 32801 queryStr : '', // Stores string version of size query 32802 view : '', // Resized image url, used to do not load full image for editing (slightly bigger than current viewport) 32803 viewFactor : 2, // View image size, comparing to current viewport 32804 viewLimit : 1920, // Mximum size of fiew in result 32805 32806 aspectRatio : 0, // Stores original aspect ratio. 32807 resizeOn : 'xy', // Allowed resize axis 32808 32809 angle : 0, // Current rotation angle 32810 32811 zoomMin : 1, // Minimal zoom allowed during edit session 32812 zoomValue : 1, // Current zoom against original image 32813 zoomMax : 4, // Maximum zoom allowed during edit session 32814 zoomStep : 0.1, // Zoom size change step 32815 zoomButtonStep : 0.05, // Zoom size change step using buttons 32816 32817 mouseRepeatTime : 10, // Mouse action repeat 32818 mouseTimer : false, // Stores mouseDown timer 32819 32820 maxWidth : 0, // | 32821 maxHeight : 0, // |- Maximum allowed dimensions for image
32822 minWidth : 125, // | 32823 minHeight : 50, // |- Minimum allowed dimensions for image 32824 zIndex : 5000, // Z-Index to use for editor positioning (affects overlay too) 32825 modal : true, // Set FALSE to do not use overlay and "click-out" 32826 overlay : true, // Set FALSE to create hidden overlay, but still have "click-out" 32827 forcePosition : false, // Set TRUE to force position style on parent element. Used to make sure it's not changed outside 32828 updateOnly : false, // Set TRUE to init only math for update 32829 32830 history : [], // Stores changes history, for undo operations 32831 historyLock : false, // Indicated history save lock 32832 historyDelay : 500, // Delay between history steps, to do not save too often operations 32833 historyTimer : false, // History saving timer 32834 isUndo : false, // Undo flag to prevent history updates 32835 32836 x : { // Current math values for X axis 32837 originSize : 0, // Original image size (used to indicate relative change) 32838 32839 imageSize : 0, // Image size 32840 imagePos : 0, // Image position relative to viewport (for crop) 32841 imageOff : 0, // Image offset 32842 32843 wrapSize : 0, // Wrapper size (viewport) 32844 wrapPos : 0, // Wrapper position 32845 wrapOff : 0, // Wrapper offset 32846 32847 pageMouse : 0, // Cursor position relative to document 32848 wrapMouse : 0, // Cursor position relative to wrapper 32849 imageMouse : 0, // Cursor position relative to image 32850 32851 flip : false, // Axis flip marker 32852 }, //x 32853 y : {}, // Current math values for Y axis (same structure as is, will be set in .init() ) 32854 32855 dom : { // Set of valuable elements as jQuery shortcuts 32856 parent : false, // Image parent box 32857 source : $img, // Initial image being edited 32858 wrap : false, // Viewport div, main editor wrapper 32859 image : false, // Viewed image, used to show changed 32860 overlay : false, // Editor overlay 32861 32862 tools : false, // Main tools bar 32863 32864 dummy : false, // Tools dummy used to trick tolls position around slider (slider on center when visible) 32865 slider : false, // Slider element 32866 32867 zoomIn : false, // | 32868 zoomOut : false, // |- Zoom controls 32869 32870 rotateL : false, // | 32871 rotateR : false, // |- Rotate controls 32872 32873 flipH : false, // | 32874 flipV : false, // |- Flip controls 32875 32876 undo : false, // Undo control 32877 reset : false, // Reset control 32878 32879 debug : false, // Debug tools 32880 }, //dom 32881 32882 origin : { // Stores changes made by editor, to be able to revert those 32883 url : '', // Original url 32884 width : 0, // | 32885 height : 0, // |- Original dimensions 32886 }, // origin 32887 32888 responsive : { // Describes set of responsive classes to be applied on resizing. No rotation set 32889 'no-dummy' : 600, 32890 'no-reset' : 500, 32891 'no-slider' : 450, 32892 'no-flip' : 150, 32893 'no-zoom' : 125, 32894 }, //responsive 32895 32896 responsiveY : 65, // Minimal height untill tools are hidden 32897 32898 debug : false, // Set TRUE to enable realtime debug console 32899 con : false, // Will store console object 32900 32901 loaderState : false, // Indicates loading state 32902 loaderDelay : 200, // If loading process happens faster than this value - loader will not even show 32903 loaderTimer : false, // Used to prevent flicker (or what seems to look like flicker ;) ) 32904 32905 resizable : {}, // Initial resizable settings. If set to FALSE, will disable manual resizing 32906 draggable : {}, // Initial draggable settings. If set to FALSE, will disable manual dragging 32907 32908// ==== INIT =================================================================================================================== 32909 32910 /** //** ----= set =--------------------------------------------------------------------------------------\**//** \ 32911 * 32912 * Initiates self parameters from given options array. 32913 * 32914 * @return SELF 32915 * 32916 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 32917 set : function ($o) { 32918 32919 // ToDo: .set() in basic class 32920 // ToDo: proper events extension support 32921 $o = $o || {}; 32922 jQuery.extend(this, $o); 32923 return this; 32924 32925 }, //FUNC set 32926 32927 /** //** ----= edit =--------------------------------------------------------------------------------------\**//** \ 32928 * 32929 * Initiates editing of image. 32930 * 32931 * @return SELF 32932 * 32933 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 32934 edit : function () { 32935 32936 var $this = this; 32937
32938 // If failed to init - that might be caused by rare crome onLoad/render bug 32939 // Trying again bit later (giving crome time to deal with it's caches) 32940 if ( this.init() === false ) 32941 setTimeout( function () { 32942 $this.init(); 32943 }, 100); //FUNC setTimeout 32944 32945 return this; 32946 32947 }, //FUNC edit 32948 32949 /** //** ----= save =--------------------------------------------------------------------------------------\**//** \ 32950 * 32951 * Stops editing and saves changes. 32952 * 32953 * @return SELF 32954 * 32955 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 32956 save : function () { 32957 32958 var $this = this; 32959 32960 this.onBeforeSave(); 32961 32962 // ---- URL ---- 32963 32964 var $query = ''; 32965 32966 // Compiling url, to load into image 32967 // Using width resize, to make sure aspect is preserved 32968 $query = 'resize=' + Math.round(this.x.imageSize); 32969 32970 // Checking if crop needed 32971 if ( 32972 (this.x.imageSize != this.x.wrapSize) 32973 || (this.y.imageSize != this.y.wrapSize) 32974 ) { 32975 32976 $query += '&crop=' + Math.round(this.x.wrapSize) + 'x' + Math.round(this.y.wrapSize); 32977 32978 // Checking if crop moved (inverting values) 32979 // Need to spciefy 0x0 anyway, othewise crop will be just centered 32980 // if ( this.x.imagePos != 0 || this.y.imagePos != 0 ) 32981 $query += ',' + Math.round(this.x.imagePos)*-1 + 'x' + Math.round(this.y.imagePos)*-1; 32982 32983 } //IF crop used 32984 32985 var $flip = []; 32986 // Checking if flip used 32987 if ( this.x.flip ) 32988 $flip.push('vrt'); 32989 32990 if ( this.y.flip ) 32991 $flip.push('hor'); 32992 32993 if ( $flip.length ) 32994 $query += '&flip=' + $flip.join(); 32995 32996 var $url = this.url + '?' + $query; 32997 32998 this.queryStr = $query; 32999 33000 // ---- IMAGE ---- 33001 33002 // Loading updated image 33003 this.state(true); 33004 33005 // Saving origin dimensions (saving here, to allow dynamic updates from callee) 33006 this.origin.width = this.dom.source.get(0).style.width; 33007 this.origin.height = this.dom.source.get(0).style.height; 33008 33009 // Sticking source box dimensions to be same as wrapper 33010 this.dom.source.css({ 33011 'width' : this.x.wrapSize, 33012 'height' : this.y.wrapSize, 33013 }); //source.css 33014 33015 // Resetting src, to be prepared for next load 33016 // Firefox needs this mostly, but it does not heart anyway 33017 $this.dom.source.attr('src', ''); 33018 33019 // Removing self only after resized image was loaded (for smoother transaction) 33020 // Setting load event before setting src (to make sure that even cache hit was captured) 33021 this.dom.source 33022 .imagesLoaded() 33023 .always( function () { 33024 33025 // Getting original image back visible 33026 // And returning original dimensions 33027 $this.dom.source.css({ 33028 'width' : $this.origin.width, 33029 'height' : $this.origin.height, 33030 'visibility' : '', 33031 33032 }); 33033 33034 // Done loading 33035 $this.state(false); 33036 33037 // Removing self 33038 $this.deinit(); 33039 33040 // Calling event 33041 $this.onAfterSave(); 33042 33043 }); //source.onLoad 33044 33045 this.dom.source.attr('src', $url); 33046 33047 // ---- TOOLS ---- 33048 33049 // Partially deinitiating before load 33050 $this.deinitTools(); 33051 $this.deinitMouse(); 33052 33053 // ---- DONE ---- 33054 33055 // Triggering event 33056 this.onSave(); 33057 33058 return this; 33059 33060 }, //FUNC save 33061 33062 /** //** ----= cancel =--------------------------------------------------------------------------------------\**//** \ 33063 * 33064 * Stops editing and reverts changes. 33065 * 33066 * @return SELF 33067 * 33068 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 33069 cancel : function () { 33070 33071 this.onCancel(); 33072 33073 return this; 33074 }, //FUNC cancel 33075 33076 /** //** ----= init =--------------------------------------------------------------------------------------\**//** \ 33077 * 33078 * Initiates self properties. Adds editor elements. 33079 * 33080 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 33081 init : function () { 33082 33083 var $this = this; 33084 33085 // X and Y axis data have same initial structure 33086 this.y = jQuery.extend({}, this.x); 33087 33088 // ---- DOM --- 33089 33090 // Initiating main elements 33091 if ( this.initEssentials() === false ) 33092 return false; 33093 33094 // Attaching editor into document 33095 this.dom.wrap.insertAfter(this.dom.source); 33096 33097 // Optionally adding overlay and disabling events around 33098 // Update mode - forces non-modal init 33099 33100 if ( this.updateOnly ) 33101 this.modal = false;
33102 33103 if ( this.modal ) { 33104 33105 jQuery('BODY').addClass('scroll-off'); 33106 this.initOverlay(); 33107 33108 } //IF modal 33109 33110 // Debug is always initiated, but not always enabled 33111 if ( !this.updateOnly ) 33112 this.initDebug(); 33113 33114 // ---- Tools ---- 33115 33116 // Tools and buttons are initiated only after image was really loaded. 33117 this.dom.image.on('load', function () { 33118 33119 // Once image is loaded - can get real ratio now 33120 // Using naturalWidth/Height to ensure correct ratio is returned 33121 // Ofc using those only of available, else falling back to css width/height 33122 // Fallback is safe as height is not forced, thus ratio is normally kept 33123 var $img = $this.dom.image.get(0); 33124 33125 // Getting natural dims 33126 var $nWidth = $img.naturalWidth; 33127 var $nHeight = $img.naturalHeight; 33128 33129 // Faling back to css ones 33130 if ( !$nWidth || !$nHeight ) { 33131 $nWidth = $this.dom.image.width(); 33132 $nHeight = $this.dom.image.height(); 33133 } //IF no natural dims 33134 33135 // If got some - can recalc ratio 33136 if ( $nWidth && $nHeight ) 33137 $this.aspectRatio = $nWidth / $nHeight; 33138 33139 // Tools and button controls 33140 if ( !$this.updateOnly ) { 33141 33142 $this.initTools(); 33143 $this.initMouse(); 33144 33145 } //IF normal edit 33146 33147 // Updating math and main css 33148 $this.updatePositionsCss(); 33149 33150 // After all init - can update UI, to be extra safe 33151 // This will update positions and sizes of visual controls 33152 if ( !$this.updateOnly ) { 33153 33154 $this.updateUI(); 33155 33156 } //IF normal edit 33157 33158 $this.onEdit(); 33159 33160 }); //image.onLoad 33161 33162 // Updating transition css right away, to avoid blink 33163 $this.updatePositionsCss(); 33164 $this.updateFlipRotateCss(); 33165 33166 }, //FUNC init 33167 33168 /** //** ----= deinit =--------------------------------------------------------------------------------------\**//** \ 33169 * 33170 * Removes self element from pages, and finalizes editing. 33171 * 33172 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 33173 deinit : function () { 33174 33175 // Removing main elements 33176 if ( this.modal ) 33177 this.dom.overlay.remove(); 33178 33179 this.dom.wrap.remove(); 33180 33181 // Restoring events handling 33182 jQuery('BODY').removeClass('scroll-off'); 33183 33184 // Can safely return position now 33185 if ( this.forcePosition ) { 33186 this.dom.source.parent().css('position', ''); 33187 this.dom.source.parent().css('display', ''); 33188 } //IF positioning corrected 33189 33190 this.deinitDebug(); 33191 }, //FUNC deinit 33192 33193 /** //** ----= initEssentials =------------------------------------------------------------------------------\**//** \ 33194 * 33195 * Initiates main DOM elements. 33196 * 33197 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 33198 initEssentials : function () { 33199 33200 var $src = this.dom.source; 33201 var $this = this; 33202 33203 // ---- SCALE ---- 33204 33205 // Image might be scaled, so have to correct all values by that scale 33206 // Scale can be determined on crop (that's actually when it matters) 33207 var $scale = 1; 33208 33209 // Calculating scale by comparing original image real dimensions and wrap size 33210 var $img = $src.get(0); 33211 var $nWidth = $img.naturalWidth; 33212 var $sWidth = $src.width(); 33213 33214 if ( $nWidth ) { 33215 $scale = $nWidth / $sWidth; 33216 } //IF natural size given 33217 33218 // ---- POSITION ---- 33219 33220 // Forcing position to make sure that it will not change (with events?) 33221 if ( this.forcePosition ) { 33222 33223 var $parent = $src.parent(); 33224 33225 if ( $parent.css('position') == 'static' ) 33226 $parent.css('position', 'relative'); 33227 33228 if ( $parent.css('display') == 'inline' ) 33229 $parent.css('display', 'block'); 33230 33231 } //IF position udpate 33232 33233 // ---- AXIS ---- 33234 33235 // Getting initial dimensions/positions 33236 var $p = this.realPosition($src, true); 33237 var $o = $src.offset(); 33238 33239 // Most of sizes are same initially, but are corrected on url parsing 33240 33241 // X 33242 this.x.originSize = $src.width(); 33243 33244 this.x.wrapSize = this.x.originSize; 33245 this.x.wrapPos = $p.left; 33246 this.x.wrapOff = $o.left; 33247 33248 this.x.imageSize = this.x.originSize; 33249 this.x.imagePos = 0; 33250 this.x.imageOff = $o.left; 33251 33252 //Y 33253 this.y.originSize = $src.height(); 33254 33255 this.y.wrapSize = this.y.originSize; 33256 this.y.wrapPos = $p.top; 33257 this.y.wrapOff = $o.top; 33258 33259 this.y.imageSize = this.y.originSize; 33260 this.y.imagePos = 0; 33261 this.y.imageOff = $o.top; 33262 33263 // In some rare cases chrome triggers onLoad faster then img loads 33264 // Attempting to detect this 33265 if ( this.y.originSize == 0 ) 33266 return false;
33267 33268 // Calculating aspect ratio for dimensions corrections 33269 // Optinally, cuz this might be provided by caller already 33270 if ( !this.aspectRatio ) 33271 this.aspectRatio = this.x.originSize / this.y.originSize; 33272 33273 // ---- URL ---- 33274 33275 // Parsing source image url and composing view url 33276 // View should be slighly bigger than current viewport 33277 // Resizing by width 33278 33279 var $srcUrl = this.origin.url = this.url || $src.attr('src'); 33280 33281 this.url = $srcUrl; 33282 this.query = {}; 33283 this.queryStr = ''; 33284 this.view = $srcUrl; 33285 33286 // Splitting query from url (if it's present) 33287 var $qpos = $srcUrl.indexOf('?'); 33288 if ( $qpos > -1 ) { 33289 33290 // Correcting starting values, reading them from url 33291 this.url = $srcUrl.substring(0, $qpos); 33292 this.queryStr = $srcUrl.substring($qpos+1) 33293 var $query = this.queryStr; 33294 33295 parse_str($query, this.query); 33296 33297 // ---- CROP ---- 33298 33299 if ( this.query['crop'] ) { 33300 var $tmp = this.query['crop'].split(','); 33301 var $size = getDimensions($tmp[0]); 33302 var $from = isSet($tmp[1]) ? getDimensions($tmp[1], true) : false; 33303 33304 // Proceeding only if correct size given 33305 if ( $size ) { 33306 33307 // Not really necessary, but doing to be consistant 33308 this.x.wrapSize = $size['x'] / $scale; 33309 this.y.wrapSize = $size['y'] / $scale; 33310 33311 // And position if set 33312 if ( $from ) { 33313 // Inverting values as it's viewport 33314 this.x.imagePos = $from['x'] * -1 / $scale; 33315 this.y.imagePos = $from['y'] * -1 / $scale; 33316 } //IF position set 33317 33318 } //If size given 33319 33320 } //IF crop set 33321 33322 // ---- RESIZE ---- 33323 33324 if ( this.query['resize'] ) { 33325 33326 var $size = getDimensions(this.query['resize']); 33327 33328 // If shorthand resize given - calculating second side by side given 33329 // Preffering width, assuming at least one is given (otherwise it's failed image anyway) 33330 if ( !isEmpty($size['x']) ) { 33331 this.x.imageSize = $size['x'] / $scale; 33332 this.y.imageSize = Math.round($size['x'] / this.aspectRatio / $scale); 33333 } //IF width given 33334 else { 33335 this.y.imageSize = $size['y'] / $scale; 33336 this.x.imageSize = Math.round($size['y'] * this.aspectRatio / $scale); 33337 } //IF height given 33338 33339 } //IF resize set 33340 33341 // ---- FLIP ---- 33342 33343 if ( this.query['flip'] ) { 33344 33345 // Fast checking for keywords. Image with invalid params is impossible to edit anyway (it will just not load) 33346 if ( this.query['flip'].indexOf('vrt') != -1 ) 33347 this.x.flip = true; 33348 33349 if ( this.query['flip'].indexOf('hor') != -1 ) 33350 this.y.flip = true; 33351 33352 } //IF flip is set 33353 33354 // ---- ROTATE ---- 33355 33356 // ToDo: complete rotate support 33357 33358 33359 } //IF ? found 33360 33361 var $viewX = Math.floor(this.x.imageSize * this.viewFactor); 33362 if ( $viewX > this.viewLimit ) 33363 $viewX = this.viewLimit; 33364 33365 this.view = this.url + '?' + $viewX; 33366 33367 // ---- WRAP ---- 33368 33369 this.dom.parent = $src.parent(); 33370 33371 // Creating main container, will be attached last after all init is complete 33372 // By default editor it's in loading state, which will be cleared once view loaded 33373 this.dom.wrap = jQuery('<div class="mwImgEd"></div>') 33374 .css({ 33375 'position' : 'absolute', 33376 33377 'left' : this.x.wrapPos, 33378 'top' : this.y.wrapPos, 33379 33380 'width' : this.x.wrapSize, 33381 'height' : this.y.wrapSize, 33382 33383 'overflow' : 'hidden', 33384 'z-index' : this.zIndex + 1, 33385 }) //css 33386 ; //jQuery.wrap 33387 33388 this.dom.wrap.disableSelection(); 33389 33390 // ---- VIEW ---- 33391 33392 // Loading view might take time 33393 this.state(true); 33394 33395 // Creating view image, setting initial params, to make sure it have correct box while loading 33396 // Creating invisible image initially, and setting visibility only after load 33397 // This allows to avoid initial blinking when swapping images and applying correcting css 33398 this.dom.image = jQuery('<img src="' + this.view + '" />') 33399 .css({ 33400 'position' : 'absolute', 33401 'border' : 'none', 33402 'visibility' : 'hidden', 33403 33404 'left' : this.x.imagePos, 33405 'top' : this.y.imagePos, 33406 33407 'width' : this.x.imageSize, 33408 'height' : this.y.imageSize, 33409 33410 'cursor' : 'move', 33411 }) //css 33412 .appendTo(this.dom.wrap) 33413 ; //jQuery.image 33414 33415 // Completing image initiation once loaded 33416 // this.dom.image.on('load', function () { 33417 imagesLoaded( this.dom.image, function () { 33418 33419 // Hiding original image, after view loads, giving small pause, to do not blink 33420 setTimeout( function () { 33421 33422 // And hiding to avoid artifacts, 33423 if ( !$this.debug && !$this.updateOnly ) 33424 $this.dom.source.css('visibility', 'hidden'); 33425 }, 1); 33426 33427 // Showing view image 33428 $this.dom.image.css('visibility', 'visible'); 33429 33430 // Done loading 33431 $this.state(false); 33432 33433 }); //image.onLoad 33434 33435 }, //FUNC initEssentials 33436 33437 /** //** ----= initOverlay =------------------------------------------------------------------------------\**//** \ 33438 * 33439 * Initiates overlay element 33440 * 33441 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 33442 initOverlay : function () { 33443 33444 var $this = this; 33445 33446 // Preventing parent clicks during editing 33447 this.dom.wrap.click( function ($e) { 33448 $e.stopPropagation(); 33449 return false; 33450 }); //FUNC onClick 33451
33452 this.dom.overlay = jQuery('<div class="mwImgEdOverlay ' + (this.overlay ? '' : 'invisible') + '"></div>') 33453 .css({ 33454 'z-index' : this.zIndex, 33455 }) //css 33456 .insertAfter(this.dom.wrap) 33457 .on('click', function ($e) { 33458 33459 // On overlay click - saving changes 33460 $this.save(); 33461 33462 $e.stopPropagation(); 33463 return false; 33464 }) //FUNC onClick 33465 ; //jQuery.image 33466 33467 }, //FUNC initOverlay 33468 33469// ==== DEBUG ================================================================================================================== 33470 33471 /** //** ----= initDebug =------------------------------------------------------------------------------\**//** \ 33472 * 33473 * Initiates debug elements. 33474 * 33475 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 33476 initDebug : function () { 33477 33478 var $this = this; 33479 33480 // Console always exists to do not cause errors 33481 this.con = vConsole({ 33482 'enabled' : this.debug && isDebug(), 33483 'width' : 500, 33484 // 'autoupdate' : true, 33485 'panels' : { 33486 'main' : [100, this, ['view', 'aspectRatio', 'angle', 'zoomValue', 'maxWidth']], 33487 'x' : [50, this.x], 33488 'y' : [50, this.y], 33489 } 33490 }); //con 33491 33492 // Debug should be possible 33493 if ( !isDebug() ) 33494 return; 33495 33496 // Creating debug button 33497 this.dom.debug = jQuery('<div class="button debug"></div>') 33498 .css({ 33499 'position' : 'absolute', 33500 'left' : 10, 33501 'top' : 10, 33502 }) //css 33503 .appendTo(this.dom.wrap) 33504 .on('click', function () { 33505 $this.debug = !$this.debug 33506 $this.con.toggle(); 33507 }) //FUNC onClick 33508 ; //jQuery.image 33509 33510 }, //FUNC initDebug 33511 33512 /** //** ----= deinitDebug =------------------------------------------------------------------------------\**//** \ 33513 * 33514 * Deinitiates debug console. 33515 * 33516 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 33517 deinitDebug : function () { 33518 33519 // Removing button 33520 if ( this.dom.debug ) 33521 this.dom.debug.remove(); 33522 33523 // And console 33524 if ( this.con ) 33525 this.con.deinit(); 33526 33527 }, //FUNC deinitDebug 33528 33529// ---- TOOLS ------------------------------------------------------------------------------------------------------------------ 33530 33531 /** //** ----= initTools =------------------------------------------------------------------------------\**//** \ 33532 * 33533 * Initiates visual tools and button controls. 33534 * 33535 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 33536 initTools : function () { 33537 33538 var $this = this; 33539 33540 // Creating main bar 33541 this.dom.tools = jQuery('<div class="main tools"></div>'); 33542 33543 // Creating tools 33544 this.initSlider(); 33545 this.initRotate(); 33546 this.initFlip(); 33547 this.initReset(); 33548 33549 // Attaching toolbar into editor 33550 this.dom.tools.appendTo(this.dom.wrap); 33551 33552 // Global mouse repeat cancel on mouseUP 33553 // This enables simple way to create mouseRepeat events 33554 // ToDo: Unbind on destroy 33555 jQuery(document).on('mouseup', function () { 33556 33557 // Doing nothing if not interval (to do not interferee with other events) 33558 if ( !$this.mouseTimer ) return; 33559 33560 // Clearing interval, to stop action 33561 clearInterval($this.mouseTimer); 33562 33563 // Canceling current event 33564 return false; 33565 }); //FUNC onMouseup 33566 33567 }, //FUNC initTools 33568 33569 /** //** ----= deinitTools =------------------------------------------------------------------------------\**//** \ 33570 * 33571 * Removes mouse control. 33572 * 33573 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 33574 deinitTools : function () { 33575 33576 // Removing tools bar 33577 if ( this.dom.tools ) 33578 this.dom.tools.remove(); 33579 33580 }, //FUNC deinitTools 33581 33582 /** //** ----= initSlider =------------------------------------------------------------------------------\**//** \ 33583 * 33584 * Initiates zoom slider and it's buttons. Also adds centering dummy. 33585 * 33586 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 33587 initSlider : function () { 33588 33589 var $this = this; 33590 33591 // ---- DOM ---- 33592 33593 this.dom.dummy = jQuery('<div class="dummy"></div>').appendTo(this.dom.tools); 33594 this.dom.slider = jQuery('<div class="slider"></div>').appendTo(this.dom.tools); 33595 33596 this.dom.zoomOut = jQuery('<div class="button zoom out"></div>').insertBefore(this.dom.slider); 33597 this.dom.zoomIn = jQuery('<div class="button zoom in"></div>').insertAfter(this.dom.slider); 33598 33599 // ---- CONTROLS: slider ---- 33600 33601 this.dom.slider.slider({ 33602 min : $this.zoomMin, 33603 max : $this.zoomMax, 33604 step : 0.01, 33605 value : $this.zoomValue, 33606 slide : function ($e, $ui) { 33607 $this.zoom($ui.value, 'wrap'); 33608 } //FUNC slide 33609 }); //jQuery.slider 33610 33611 // ---- CONTROLS: buttons ---- 33612 33613 this.dom.zoomIn.on('mousedown', function () { 33614 33615 // Enabling mouse repeating action 33616 $this.mouseTimer = setInterval( function () { 33617 $this.zoom($this.zoomValue + $this.zoomButtonStep, 'wrap'); 33618 }, $this.mouseRepeatTime); //FUNC mouseTimer.callback 33619 33620 }); //FUNC zoomIn.onClick 33621 33622 this.dom.zoomOut.on('mousedown', function () { 33623 33624 // Enabling mouse repeating action 33625 $this.mouseTimer = setInterval( function () { 33626 $this.zoom($this.zoomValue - $this.zoomButtonStep, 'wrap'); 33627 }, $this.mouseRepeatTime); //FUNC mouseTimer.callback 33628 33629 }); //FUNC zoomOut.onClick 33630 33631 }, //FUNC initSlider 33632 33633 /** //** ----= initRotate =------------------------------------------------------------------------------\**//** \ 33634 * 33635 * Initiates rotate controls. 33636 * 33637 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 33638 initRotate : function () { 33639 33640 // Not using currently, cuz buggy 33641 return; 33642 33643 var $this = this; 33644 33645 // ---- DOM ---- 33646 33647 // Adding visual divider 33648 jQuery('<div class="rotate divider"></div>').appendTo(this.dom.tools); 33649 33650 this.dom.rotateL = jQuery('<div class="button rotate left"></div>').appendTo(this.dom.tools); 33651 this.dom.rotateR = jQuery('<div class="button rotate right"></div>').appendTo(this.dom.tools); 33652 33653 // ---- CONTROLS ---- 33654 33655 this.dom.rotateL.on('click', function () { 33656 $this.rotate('l'); 33657 }); //FUNC rotateL.onClick 33658 33659 this.dom.rotateR.on('click', function () { 33660 $this.rotate('r'); 33661 }); //FUNC rotateR.onClick 33662 33663 33664 }, //FUNC initRotate 33665 33666 /** //** ----= initReset =------------------------------------------------------------------------------\**//** \ 33667 * 33668 * Initiates reset and undo controls. 33669 * 33670 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 33671 initReset : function () { 33672 33673 var $this = this; 33674 33675 // ---- DOM ---- 33676 33677 // Adding visual divider 33678 jQuery('<div class="rst divider"></div>').appendTo(this.dom.tools); 33679 33680 this.dom.undo = jQuery('<div class="button rst undo"></div>').appendTo(this.dom.tools); 33681 this.dom.reset = jQuery('<div class="button rst reset"></div>').appendTo(this.dom.tools); 33682 33683 // ---- CONTROLS ---- 33684 33685 this.dom.undo.on('click', function () { 33686 $this.undo(); 33687 }); //FUNC rotateL.onClick 33688 33689 this.dom.reset.on('click', function () { 33690 $this.reset(); 33691 }); //FUNC rotateR.onClick 33692 33693 33694 }, //FUNC initReset 33695 33696 /** //** ----= initFlip =--------------------------------------------------------------------------------------\**//** \ 33697 * 33698 * Initiates flip controls. 33699 * 33700 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 33701 initFlip : function () { 33702 33703 var $this = this; 33704 33705 // ---- DOM ---- 33706
33707 jQuery('<div class="flip divider"></div>').appendTo(this.dom.tools); 33708 33709 this.dom.flipH = jQuery('<div class="button flip hor"></div>').appendTo(this.dom.tools); 33710 this.dom.flipV = jQuery('<div class="button flip ver"></div>').appendTo(this.dom.tools); 33711 33712 // ---- CONTROLS ---- 33713 33714 this.dom.flipH.on('click', function () { 33715 $this.flip('y'); 33716 }); //FUNC flipH.onClick 33717 33718 this.dom.flipV.on('click', function () { 33719 $this.flip('x'); 33720 }); //FUNC flipV.onClick 33721 33722 }, //FUNC initFlip 33723 33724 /** //** ----= updateUI =--------------------------------------------------------------------------------------\**//** \ 33725 * 33726 * Updates UI elements visibility and positions. 33727 * 33728 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 33729 updateUI : function () { 33730 33731 // Checking viewport size agains set of responsive classes, 33732 // applying onces that needed, removing ones that are not 33733 33734 // Checking if height is too small, and disabling visual tools completely in this case 33735 if ( this.y.wrapSize <= this.responsiveY ) 33736 this.dom.wrap.addClass('no-tools'); 33737 else 33738 this.dom.wrap.removeClass('no-tools'); 33739 33740 for ( var $i in this.responsive ) { 33741 var $r = this.responsive[$i]; 33742 33743 // Adding if less than border value, removing othewise 33744 if ( this.x.wrapSize <= $r ) 33745 this.dom.wrap.addClass($i); 33746 else 33747 this.dom.wrap.removeClass($i); 33748 33749 } //FOR each responsive class 33750 33751 }, //FUNC updateUI 33752 33753// ---- MOUSE ------------------------------------------------------------------------------------------------------------------ 33754 33755 /** //** ----= initMouse =------------------------------------------------------------------------------\**//** \ 33756 * 33757 * Initiates mouse controls, like drag/zoom/resize 33758 * 33759 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 33760 initMouse : function () { 33761 33762 var $this = this; 33763 33764 // ---- CURSOR ---- 33765 33766 // Tracking mouse cursor 33767 this.dom.wrap.on('mousemove', function ($e) { 33768 33769 $this.x.pageMouse = $e.pageX; 33770 $this.x.wrapMouse = $e.pageX - $this.x.wrapOff; 33771 $this.x.imageMouse = $e.pageX - $this.x.imageOff; 33772 33773 $this.y.pageMouse = $e.pageY; 33774 $this.y.wrapMouse = $e.pageY - $this.y.wrapOff; 33775 $this.y.imageMouse = $e.pageY - $this.y.imageOff; 33776 33777 if ( $this.con ) 33778 $this.con.update(); 33779 33780 }); //wrap.onMousemove 33781 33782 // ---- CONTROLS ---- 33783 33784 this.initResize(); 33785 this.initZoom(); 33786 this.initDrag(); 33787 33788 }, //FUNC initMouse 33789 33790 /** //** ----= deinitMouse =------------------------------------------------------------------------------\**//** \ 33791 * 33792 * Removes mouse control. 33793 * 33794 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 33795 deinitMouse : function () { 33796 33797 // Stop zoom 33798 this.dom.wrap.off('mousewheel'); 33799 33800 // Stop drag 33801 this.dom.image.draggable('destroy'); 33802 33803 // Stop resize 33804 this.dom.wrap.resizable('destroy'); 33805 33806 }, //FUNC deinitMouse 33807 33808 /** //** ----= initZoom =--------------------------------------------------------------------------------------\**//** \ 33809 * 33810 * Initiates mouse zoom. 33811 * 33812 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 33813 initZoom : function () { 33814 33815 var $this = this; 33816 33817 this.dom.wrap.on('mousewheel', function ($e) { 33818 $this.zoom($this.zoomValue + $this.zoomStep * $e.deltaY, 'mouse'); 33819 }); //img.onMousewheel 33820 33821 }, //FUNC initZoom 33822 33823 /** //** ----= initDrag =--------------------------------------------------------------------------------------\**//** \ 33824 * 33825 * Initiates image dragging. 33826 * 33827 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 33828 initDrag : function () { 33829 33830 var $this = this; 33831 33832 // Setting up 33833 var $res = this.setupJQ(this.draggable, { 33834 start : function ($event, $ui) { 33835 33836 // Saving current state in history 33837 $this.saveHistory(); 33838 33839 }, //start 33840 33841 drag : function ($e, $ui) { 33842 // Getting actual position, and updating image data 33843 var $p = $this.dom.image.position(); 33844 $this.move($p.left, $p.top); 33845 } //onDrag 33846 }); //$res 33847 33848 // Init 33849 this.dom.image 33850 .draggable('destroy') 33851 .draggable($res); 33852 33853 }, //FUNC initDrag 33854 33855 /** //** ----= initResize =------------------------------------------------------------------------------\**//** \ 33856 * 33857 * Initiates resizable viewport. 33858 * 33859 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 33860 initResize : function () { 33861 33862 var $this = this; 33863
33864 // Setting up 33865 var $res = this.setupJQ(this.resizable, { 33866 minWidth : this.minWidth, 33867 minHeight : this.minHeight, 33868 maxWidth : this.maxWidth, 33869 maxHeight : this.maxHeight, 33870 33871 start : function ($event, $ui) { 33872 33873 // Saving current state in history 33874 $this.saveHistory(); 33875 33876 // Adding size hint to show dimensions while resizing 33877 this.h = jQuery('<div class="mwSizeHint bottom right"></div>').appendTo($this.dom.wrap); 33878 33879 }, //start 33880 33881 stop : function ($event, $ui) { 33882 // Removing size hint 33883 this.h.remove(); 33884 }, //stop 33885 33886 resize : function ($event, $ui) { 33887 33888 // Updating wrapper sizes and math 33889 $this.setWrapSize($this.dom.wrap.width(), $this.dom.wrap.height()); 33890 33891 // ---- HINT ---- 33892 33893 // Updating info on size hint 33894 this.h.html($this.x.wrapSize + 'px x ' + $this.y.wrapSize + 'px'); 33895 33896 // ---- DONE ---- 33897 33898 // Updatin UI to make sure controls look right 33899 $this.updateUI(); 33900 33901 if ( $this.con ) 33902 $this.con.update(); 33903 33904 $this.onResize(); 33905 $this.updatePositionsCss(); 33906 33907 } //FUNC resize 33908 }); 33909 33910 if ( $res === false ) return; 33911 33912 // Initiating handles (if none set already) 33913 if ( !$res['handles'] ) { 33914 33915 switch ( this.resizeOn ) { 33916 case 'x': 33917 $res['handles'] = 'e'; 33918 break; 33919 case 'y': 33920 $res['handles'] = 's'; 33921 break; 33922 case 'xy' : 33923 $res['handles'] = 's, e, se'; 33924 break; 33925 case 'no' : 33926 default : 33927 return; 33928 } //SWITCH resizeOn 33929 33930 } //IF no handles specified 33931 33932 // Init 33933 this.dom.wrap 33934 .resizable('destroy') 33935 .resizable($res); 33936 33937 }, //FUNC initResize 33938 33939// ==== MATH =================================================================================================================== 33940 33941// ==== TRANSFORM ============================================================================================================== 33942 33943 /** //** ----= setWrapSize =------------------------------------------------------------------------------\**//** \ 33944 * 33945 * Applies new wrap size. 33946 * 33947 * @param int $width - New width 33948 * @param int $height - New height 33949 * 33950 * @return SELF 33951 * 33952 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 33953 setWrapSize : function ($width, $height) { 33954 33955 // Updating wrapper math 33956 this.x.wrapSize = $width; 33957 this.y.wrapSize = $height; 33958 33959 // Updating original image, and it's data 33960 this.x.originSize = this.x.wrapSize; 33961 this.y.originSize = this.y.wrapSize; 33962 33963 this.dom.source.css({ 33964 'width' : this.x.originSize, 33965 'height' : this.y.originSize, 33966 }); //css 33967 33968 this.dom.wrap.css({ 33969 'width' : $width, 33970 'height' : $height, 33971 }); 33972 33973 // Updating wrap position 33974 this.updateWrapPos(); 33975 33976 return this; 33977 }, //FUNC setWrapSize 33978 33979 /** //** ----= updateWrapPos =------------------------------------------------------------------------------\**//** \ 33980 * 33981 * Updates wrap positioning against source image (in case it was centered/margined) 33982 * 33983 * @return SELF 33984 * 33985 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 33986 updateWrapPos : function () { 33987 33988 // Making sure we are positioned correctly still 33989 // Need to update position in case image was centered originally 33990 var $src = this.dom.source; 33991 33992 // Getting initial dimensions/positions 33993 var $p = this.realPosition($src, true); 33994 33995 this.dom.wrap.css({ 33996 'left' : $p.left, 33997 'top' : $p.top 33998 }); 33999 34000 // Getting updated offset back 34001 var $o = this.dom.wrap.offset(); 34002 34003 // Updating wrap offset values 34004 this.x.wrapOff = $o.left; 34005 this.y.wrapOff = $o.top; 34006 34007 }, //FUNC updateWrapPos 34008 34009 /** //** ----= resize =--------------------------------------------------------------------------------------\**//** \ 34010 * 34011 * Resize image to new dimensions. 34012 * WARNING: Dimensions are set strictly, no aspect preserve used. 34013 * 34014 * @param int $width - New width 34015 * @param int $height - New height 34016 * 34017 * @return SELF 34018 * 34019 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 34020 resize : function ($width, $height) { 34021 34022 if ( $width < this.x.wrapSize ) 34023 return; 34024 34025 if ( $height < this.y.wrapSize ) 34026 return; 34027 34028 this.x.imageSize = $width; 34029 this.y.imageSize = $height; 34030 /*/ 34031 var $maxWidth = this.maxWidth ? Math.min(this.x.imageSize, this.maxWidth) : this.x.imageSize; 34032 var $maxHeight = this.maxHeight ? Math.min(this.y.imageSize, this.maxHeight) : this.y.imageSize; 34033 /*/ 34034 var $maxWidth = this.maxWidth ? this.maxWidth : this.x.imageSize; 34035 var $maxHeight = this.maxHeight ? this.maxHeight : this.y.imageSize; 34036 /**/ 34037 this.dom.wrap.resizable('option', 'maxWidth', $maxWidth ); 34038 this.dom.wrap.resizable('option', 'maxHeight', $maxHeight ); 34039 34040 // this.onResize($width, $height); 34041 // this.con.update(); 34042 // this.updatePositionsCss(); 34043 34044 }, //FUNC resize 34045 34046 /** //** ----= move =--------------------------------------------------------------------------------------\**//** \ 34047 * 34048 * Moves image to given position. 34049 * 34050 * @param int $left - New horisontal position 34051 * @param int $top - New vertical position 34052 * 34053 * @return SELF 34054 * 34055 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 34056 move : function ($left, $top) { 34057 34058 // Saving distance 34059 var $deltaX = this.x.imagePos - $left; 34060 var $deltaY = this.y.imagePos - $top; 34061 34062 // Updating image position and offset 34063 this.x.imagePos = $left; 34064 this.y.imagePos = $top; 34065 34066 this.x.imageOff -= $deltaX; 34067 this.y.imageOff -= $deltaY; 34068 34069 // Updating mouse positions (to ensure fresh values without actual cursor moving) 34070 this.x.imageMouse += $deltaX; 34071 this.y.imageMouse += $deltaY; 34072 34073 // this.onMove(); 34074 34075 // this.con.update(); 34076 34077 // this.updatePositionsCss(); 34078 34079 }, //FUNC move 34080 34081 /** //** ----= zoom =--------------------------------------------------------------------------------------\**//** \ 34082 * 34083 * Zooms image to given value. Zoom is counted against original image. 34084 * Essencially zoom is combination or resize and move. Updates image position durin resize to keep 34085 * point specified on screen. 34086 * 34087 * @param float $zoom - New zoom level to set. 34088 * @param string [$position] - Center point to position against. 34089 * Possible values: 34090 * 'wrap' - positions against viewport center. 34091 * 'image' - positions against image center (default). 34092 * 'mouse' - positions against mouse cursor. 34093 * 'zero' - positions agains top left corner of image (no move). 34094 * 34095 * @return SELF 34096 * 34097 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 34098 zoom : function ($zoom, $position) { 34099 34100 var $this = this; 34101 34102 // ---- Validating values ---- 34103 34104 if ( !$position || !isIn($position, ['wrap', 'image', 'mouse', 'zero']) ) 34105 $position = 'image'; 34106 34107 if ( $zoom > this.zoomMax ) 34108 return; 34109 34110 if ( $zoom < this.zoomMin ) 34111 return; 34112 34113 // Saving history 34114 this.saveHistory(); 34115 34116 // Saving value 34117 this.zoomValue = $zoom; 34118 34119 // ---- Zooming ---- 34120 34121 // Using math helper for each axis 34122 // It does all math and saves results into axis data as subarray 34123 34124 var zoomAxis = function ($axis, $size) { 34125 34126 // Cleaning prev results if any, and creating shortcut 34127 var $ax = $axis.ex = {}; 34128 34129 // ---- SIZE ---- 34130 34131 $ax.newSize = $size || ($axis.wrapSize * $zoom); 34132 34133 // ---- POSITION ---- 34134 34135 $ax.center = 0; 34136 34137 // Calculating central point based on params given 34138 switch ( $position ) { 34139 case 'zero' : // Top left of image 34140 $ax.center = 0; 34141 break; 34142
34143 case 'image' : // Center of image (delta == 0.5) 34144 $ax.center = $axis.imageSize / 2; 34145 break; 34146 34147 case 'mouse' : // Mouse cursor position 34148 $ax.center = $axis.imageMouse; 34149 break; 34150 34151 case 'wrap' : // Center of viewport 34152 default : 34153 $ax.center = ($axis.wrapSize / 2) - $axis.imagePos; 34154 } //SWITCH $position 34155 34156 // Calculating move proportions, commenting as simple questions to show logic 34157 34158 // How much image size was changed? 34159 $ax.sizeDelta = $ax.newSize - $axis.imageSize; 34160 34161 // How close zoom point was to one side? 34162 $ax.centerDelta = $ax.center / $axis.imageSize; 34163 34164 // Correcting position based on central point proportion 34165 $ax.posAdd = $ax.sizeDelta * $ax.centerDelta; 34166 34167 // Have new position now 34168 $ax.newPos = $axis.imagePos - $ax.posAdd; 34169 34170 } //FUNC zoomAxis 34171 34172 // Calculating zoom (resize and move) 34173 // Making sure ratio is still correct (with X as priority) 34174 zoomAxis(this.x); 34175 zoomAxis(this.y, this.x.ex.newSize / this.aspectRatio); 34176 34177 // Resizing and moving 34178 this.resize(this.x.ex.newSize, this.y.ex.newSize); 34179 this.move(this.x.ex.newPos, this.y.ex.newPos); 34180 34181 // ---- DONE ---- 34182 34183 // Calling event, given possibility to do smth 34184 this.onZoom($zoom); 34185 34186 // Updating slider, css and debug 34187 // this.dom.slider.slider('option', 'value', $zoom); 34188 34189 this.con.update(); 34190 34191 this.updatePositionsCss(); 34192 34193 return this; 34194 }, //FUNC zoom 34195 34196 /** //** ----= flip =--------------------------------------------------------------------------------------\**//** \ 34197 * 34198 * Flips image by given axis. 34199 * 34200 * @param string [$axis] - Axis to flip by. If omited - just updates image css. 34201 * Valid values are 'x' or 'y'. 34202 * 34203 * @return SELF 34204 * 34205 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 34206 flip : function ($axis) { 34207 34208 // Saving history 34209 this.saveHistory(); 34210 34211 // Flip cancels rotation and opposite flip currently 34212 // ToDo: Simultanious support for both in resizer 34213 this.angle = 0; 34214 34215 // If axis specified - inverting that one 34216 if ( $axis == 'x' || $axis == 'y' ) 34217 this[$axis].flip = !this[$axis].flip; 34218 34219 this.updateFlipRotateCss(); 34220 34221 this.con.update(); 34222 34223 this.onFlip($axis); 34224 34225 return this; 34226 }, //FUNC flip 34227 34228 /** //** ----= rotate =--------------------------------------------------------------------------------------\**//** \ 34229 * 34230 * Rotates image in direction specified. 34231 * 34232 * @param string [$direction] - Axis to flip by. If omited - just updates image css. 34233 * Valid values are 'l' or 'r'. 34234 * 34235 * @return SELF 34236 * 34237 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 34238 rotate : function ($direction) { 34239 34240 // Flip cancels flip currently 34241 // ToDo: Simultanious support for both in resizer 34242 this.x.flip = false; 34243 this.y.flip = false; 34244 34245 // Updating angle depending on direction 34246 if ( $direction == 'r' ) 34247 this.angle += 90; 34248 34249 if ( $direction == 'l' ) 34250 this.angle -= 90; 34251 34252 // Correcting if necessary 34253 // Safe to check exact values, cuz steps are exactly 90 34254 if ( this.angle == 360 ) 34255 this.angle = 0; 34256 34257 if ( this.angle == -90 ) 34258 this.angle = 270; 34259 34260 // Setting up css 34261 this.updateFlipRotateCss(); 34262 34263 this.con.update(); 34264 34265 this.onRotate(this.angle); 34266 34267 return this; 34268 }, //FUNC rotate 34269 34270 /** //** ----= saveHistory =------------------------------------------------------------------------------\**//** \ 34271 * 34272 * Saves current math state as undo step. 34273 * 34274 * @return SELF 34275 * 34276 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 34277 saveHistory : function () { 34278 34279 var $this = this; 34280 34281 // Not saving history while doing undo 34282 if ( this.isUndo ) 34283 return; 34284 34285 if ( this.historyTimer ) 34286 clearTimeout($this.historyTimer); 34287 34288 this.historyTimer = setTimeout( function () { 34289 $this.historyLock = false; 34290 }, this.historyDelay); 34291 34292 if ( this.historyLock ) 34293 return; 34294 34295 this.historyLock = true; 34296 34297 var $state = { 34298 x : jQuery.extend({}, this.x), 34299 y : jQuery.extend({}, this.y), 34300 zoom : this.zoomValue, 34301 }; //$state 34302 34303 this.history.push($state); 34304 34305 }, //FUNC saveHistory 34306 34307 /** //** ----= undo =--------------------------------------------------------------------------------------\**//** \ 34308 * 34309 * Reverts changes done to image since last undo state. 34310 * 34311 * @return SELF 34312 * 34313 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 34314 undo : function () { 34315 34316 // Checking for last step, and removing it from history 34317 if ( !this.history.length ) 34318 return this; 34319 34320 // Flagging undo to prevent history updates 34321 this.isUndo = true; 34322 34323 var $state = this.history.pop(); 34324 34325 // Resizing wrapper (this will also resize source) 34326 this.setWrapSize($state.x.wrapSize, $state.y.wrapSize); 34327 34328 // Resetting positions and zoom 34329 this.move($state.x.imagePos, $state.y.imagePos); 34330 this.resize($state.x.imageSize, $state.y.imageSize); 34331 34332 // Issuing zoom events 34333 this.onMove($state.x.imagePos, $state.y.imagePos); 34334 this.onResize($state.x.imageSize, $state.y.imageSize); 34335 this.onZoom($state.zoom); 34336 34337 // Checking flip 34338 if ( $state.x.flip !== this.x.flip ) 34339 this.flip('x'); 34340 34341 if ( $state.y.flip !== this.y.flip ) 34342 this.flip('y'); 34343 34344 this.con.update(); 34345 this.updatePositionsCss(); 34346 34347 // Unflagging undo 34348 this.isUndo = false;
34349 34350 }, //FUNC undo 34351 34352 /** //** ----= reset =--------------------------------------------------------------------------------------\**//** \ 34353 * 34354 * Reverts any changes done to image, setting it's original dimensions and zoom. 34355 * 34356 * @return SELF 34357 * 34358 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 34359 reset : function () { 34360 34361 // Defaulting to parent element width, as in 99% cases image is responsive and takes whole width of parent 34362 // Calculating height from aspectRatio 34363 // ToDo: envestigate, mb better to resize against current wrap width, or have optional (no width resize - using wrap size then) 34364 34365 var $isResize = this.resizeOn && this.resizeOn != 'no'; 34366 34367 if ( $isResize ) { 34368 switch ( this.resizeOn ) { 34369 case 'x': 34370 // Resizing to parent width, keeping height 34371 this.setWrapSize(this.dom.parent.width(), this.y.wrapSize); 34372 break; 34373 case 'y': 34374 // Resizing to proportional height, keeping width 34375 this.setWrapSize(this.x.wrapSize, this.x.wrapSize / this.aspectRatio); 34376 break; 34377 case 'xy' : 34378 this.setWrapSize(this.dom.parent.width(), this.dom.parent.width() / this.aspectRatio); 34379 break; 34380 } //SWITCH resizeOn 34381 34382 } //IF resizing enabled 34383 34384 // Calculating width/height from wrapper size, to propertly resize/center 34385 var $wrapRatio = this.x.wrapSize / this.y.wrapSize; 34386 34387 if ( $wrapRatio > this.aspectRatio ) { 34388 var $width = this.x.wrapSize; 34389 var $height = $width / this.aspectRatio; 34390 34391 var $top = Math.round((this.y.wrapSize - $height) / 2); 34392 var $left = 0; 34393 } //IF loose height 34394 else if ( $wrapRatio < this.aspectRatio ) { 34395 var $height = this.y.wrapSize; 34396 var $width = $height * this.aspectRatio; 34397 34398 var $top = 0; 34399 var $left = Math.round((this.x.wrapSize - $width) / 2); 34400 } //IF loose width 34401 else { 34402 var $width = this.x.wrapSize; 34403 var $height = this.y.wrapSize; 34404 34405 var $top = 0; 34406 var $left = 0; 34407 } //IF exactly same 34408 34409 // Resetting positions and zoom, centering image 34410 this.move($left, $top); 34411 this.resize($width, $height); 34412 34413 this.onMove($left, $top); 34414 this.onResize($width, $height); 34415 this.onZoom(this.zoomValue); 34416 34417 this.con.update(); 34418 this.updatePositionsCss(); 34419 34420 }, //FUNC reset 34421 34422// ==== CSS ==================================================================================================================== 34423 34424 /** //** ----= refresh =--------------------------------------------------------------------------------------\**//** \ 34425 * 34426 * Refreshes positins and sizes from current css. 34427 * 34428 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 34429 refresh : function ($width, $height) { 34430 34431 // Getting fresh dimensions/positions 34432 var $p = this.dom.image.position(); 34433 var $o = this.dom.image.offset(); 34434 34435 this.x.imageSize = this.dom.image.width(); 34436 this.x.imagePos = $p.left; 34437 this.x.imageOff = $o.left; 34438 34439 this.y.imageSize = this.dom.image.height(); 34440 this.y.imagePos = $p.left; 34441 this.y.imageOff = $o.top; 34442 34443 }, //FUNC refresh 34444 34445 /** //** ----= updatePositionsCss =----------------------------------------------------------------------\**//** \ 34446 * 34447 * Validates current image properties, corrects them and updates css. 34448 * 34449 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 34450 updatePositionsCss : function () { 34451 34452 var $this = this; 34453 34454 // Validating positions 34455 // Using math helper for each axis 34456 var checkAxis = function ( $axis ) { 34457 34458 // Cleaning prev results if any, and creating shortcut 34459 // Making sure structure is set 34460 var $a = $axis.ex = { 34461 newSize : $axis.imageSize, 34462 newPos : $axis.imagePos, 34463 deltaPos : 0, 34464 }; // $a 34465 34466 // ---- Size ---- 34467 34468 // Image can't be smaller than viewport 34469 if ( $a.newSize < $axis.wrapSize ) 34470 $a.newSize = $axis.wrapSize; 34471 34472 // Calculating axis value here, then will check for both same time outside 34473 $a.zoomValue = $a.newSize / $axis.wrapSize; 34474 34475 // ---- Position ---- 34476 34477 // No positive positions (left/top gap) 34478 if ( $a.newPos > 0 ) 34479 $a.newPos = 0; 34480 34481 // Checking right/bottom gap, calculating position difference 34482 $a.deltaPos = $axis.wrapSize - $a.newSize - $a.newPos; 34483 34484 // No positive value, correcting if necessary 34485 if ( $a.deltaPos > 0 ) 34486 $a.newPos = $a.newPos + $a.deltaPos; 34487 34488 } //FUNC checkAxis 34489 34490 // Checking both axis 34491 checkAxis(this.x); 34492 checkAxis(this.y); 34493
34494 // Making sure resulting ratio if correct. Checking to bigger size 34495 34496 var $newY = this.x.ex.newSize / this.aspectRatio; 34497 if ( $newY > this.y.ex.newSize ) 34498 this.y.ex.newSize = $newY; 34499 34500 var $newX = this.y.ex.newSize * this.aspectRatio; 34501 if ( $newX > this.x.ex.newSize ) 34502 this.x.ex.newSize = $newX; 34503 34504 // Updating zoom value - it's proportion of wrap size to image size (using x Axis) 34505 // Need to check if that is too big (might happen during resizing + zooming) 34506 // Sticking to max zoom in this case 34507 // Updating zoom value. Using X axis, it's anyway proportional at this point 34508 this.zoomValue = this.x.imageSize / this.x.wrapSize; 34509 if ( this.zoomValue > this.zoomMax ) { 34510 34511 // Decreasing both axis by zoom delta 34512 var $zoomDelta = this.zoomValue - this.zoomMax; 34513 34514 this.x.ex.newSize -= this.x.ex.newSize * $zoomDelta; 34515 this.y.ex.newSize -= this.y.ex.newSize * $zoomDelta; 34516 34517 // Correcting zoom 34518 this.zoomValue = this.zoomMax; 34519 } //IF zoom happend to be too big 34520 34521 // Resizing and moving 34522 this.resize(this.x.ex.newSize, this.y.ex.newSize); 34523 this.move(this.x.ex.newPos, this.y.ex.newPos); 34524 34525 this.dom.image.css({ 34526 'left' : this.x.imagePos, 34527 'top' : this.y.imagePos, 34528 34529 'width' : this.x.imageSize, 34530 'max-width' : 'none', 34531 // 'height' : this.y.imageSize, 34532 'height' : '', 34533 }); //css 34534 34535 if ( this.dom.slider ) 34536 // Updating slider position 34537 this.dom.slider.slider('option', 'value', this.zoomValue); 34538 34539 // Updating draggable, setting image containment 34540 // Box selected such way that it can fit corners in all directions 34541 34542 // Getting difference in box and image size, and adding those around wrap box as containment 34543 var $dx = this.x.imageSize - this.x.wrapSize; 34544 var $dy = this.y.imageSize - this.y.wrapSize; 34545 34546 // Using original offset as base 34547 var $cnt = [this.x.wrapOff - $dx, this.y.wrapOff - $dy, this.x.wrapOff, this.y.wrapOff]; 34548 34549 this.dom.image.draggable('option', 'containment', $cnt ); 34550 34551 }, //FUNC updatePositionsCss 34552 34553 /** //** ----= updateFlipRotateCss =----------------------------------------------------------------------\**//** \ 34554 * 34555 * Update image transform css. 34556 * 34557 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 34558 updateFlipRotateCss : function () { 34559 34560 var $tr = ''; 34561 34562 // Adding scale only if specified, othewise - cleaning it 34563 if ( this.x.flip || this.y.flip ) 34564 $tr += ' scale(' + (this.y.flip ? '-1' : '1') + ', ' + (this.x.flip ? '-1' : '1') + ')' 34565 34566 // Adding rotation only if specified, othewise - cleaning it 34567 if ( this.angle != 0 ) 34568 $tr += ' rotate(' + this.angle + 'deg)'; 34569 34570 // Updating css 34571 this.dom.image.css({ 34572 'transform' : $tr, 34573 }); //css 34574 34575 }, //FUNC updateFlipRotateCss 34576 34577// ==== HELPERS ================================================================================================================ 34578 34579 /** //** ----= realPosition =------------------------------------------------------------------------------\**//** \ 34580 * 34581 * Returns real element position, counting parent scrolls. 34582 * Based on fact that jQuery fails to get correct element position if one of parents was scrolled. 34583 * 34584 * @todo More testing required. BOSY and immideate parent might be counted correctly already by jQuery. 34585 * 34586 * @param jQuery $el - Element to count posititon for. 34587 * 34588 * @return object - Element relative position in jQuery native format { left: 0, top: 0 } 34589 * 34590 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 34591 realPosition : function ($el, $countMargin) { 34592 34593 var $pos = $el.position(); 34594 34595 // Who's scrolled?! 34596 // Looping through all parents and checking scoll values. 34597 // Using those to correct position of element, cuz jQuery fails to return proper posiiton for scrolled elements 34598 var $parents = $el.parents(); 34599 var $scrollX = 0; 34600 var $scrollY = 0; 34601 34602 $parents.each( function () { 34603 var $p = jQuery(this); 34604 34605 // Skipping body 34606 if ( $p.is('BODY, HTML') ) 34607 return; 34608 34609 // Adding scroll values (for non scrolled that will be 0 anyway) 34610 $scrollX += $p.scrollLeft(); 34611 $scrollY += $p.scrollTop(); 34612 }); //jQuery(parents).each 34613 34614 // For now fixing using summared scroll 34615 // ToDo: Test more and see if that's working good 34616 // ToDo: Test with document scroll and immediate parent scroll (those might be propertly counted by jQuery) 34617 34618 $pos.left += $scrollX; 34619 $pos.top += $scrollY; 34620 34621 // Might need to count margins 34622 if ( $countMargin ) { 34623 34624 $pos.left += parseInt($el.css('margin-left')); 34625 $pos.top += parseInt($el.css('margin-top')); 34626 34627 } //IF margins matter 34628 34629 return $pos; 34630 }, //FUNC realPosition 34631 34632 /** //** ----= setupJQ =--------------------------------------------------------------------------------------\**//** \ 34633 * 34634 * Helps validate/initiate jQuery.ui settings. Takes initial settings and extesion object and mixes all together. 34635 * Allows FALSE as initial setting, to cancel process. 34636 * 34637 * @param object $settings - Initial settings to validate 34638 * @param object $ex - Extention settings to add. 34639 * 34640 * @return object - jQuery.ui setup object, or FALSE if cancel. 34641 * 34642 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 34643 setupJQ : function ($settings, $ex) { 34644 34645 // Canceling if set so 34646 if ( $settings === false ) 34647 return false;
34648 34649 // If not canceled - need to make sure it's object 34650 if ( !isObject($settings) ) 34651 $settings = {}; 34652 34653 // Creating setup object 34654 return jQuery.extend({}, $settings, $ex); 34655 }, //FUNC setupJQ 34656 34657 /** //** ----= state =--------------------------------------------------------------------------------------\**//** \ 34658 * 34659 * Sets loading state (on/off). Uses slight delay, to prevent flicker. 34660 * 34661 * @param bool $state - Current loading state. 34662 * 34663 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 34664 state : function ($state) { 34665 34666 var $this = this; 34667 34668 this.loaderState = $state; 34669 34670 if ( $state === true ) { 34671 34672 // Delaying show 34673 this.loaderTimer = setTimeout( function () { 34674 $this.dom.wrap.addClass('loading'); 34675 }, this.loaderDelay); 34676 34677 } else { //IF loading 34678 34679 // Clearing loader timer if any happen 34680 clearTimeout(this.loaderTimer); 34681 34682 $this.dom.wrap.removeClass('loading'); 34683 } //IF not loading 34684 34685 }, //FUNC state 34686 34687// ==== ENDofOBJECT ============================================================================================================ 34688 34689 }; //CLASS mwImgEd 34690 34691 // Applying options 34692 $class.set($options); 34693 34694 // Adding events 34695 $class = vEventObject(['onInit', 'onEdit', 'onBeforeSave', 'onSave', 'onAfterSave', 'onCancel', 'onDone', 'onChange', 'onZoom', 'onResize', 'onMove', 'onRotate', 'onFlip', 'onReset', 'onUndo'], $class); 34696 34697 // Storing class as data in image element 34698 $img.data('mwImgEd', $class); 34699 34700 // Autorun if options set 34701 if ( !isEmpty($options) ) 34702 $class.edit(); 34703 34704 return $class; 34705 34706} //CONSTRUCTOR mwImgEd 34707 34708/* 34709 This JS makes liveEd responsive, still having paddings/borders on blocks. 34710 New liveEd will have responsive nature, which will make most of this object obsolete 34711 34712 liveEd uses "Rows" conception, when several blocks with float:left form row. Several rows are broken with cler:both 34713 liveEd have own responsive math, which is kinda duped here. Again - this is obsolete. 34714 */ 34715 34716mwResponsive = { 34717 34718 pageArea : 'DIV.mwPageArea', // Page area selector 34719 pageBlock : 'DIV.mwPageBlock', // Page widget element selector 34720 classFloat : 'Float', // Class applied to floating blocks 34721 classHost : 'rowHost', // Class applied to first col in a row 34722 classPlaceholder : 'Placeholder', // Class applied to placeholder blocks 34723 34724 blocks : false, // All found page blocks 34725 rows : [], // Filtered rows 34726 34727 /** //** ----= init =--------------------------------------------------------------------------------------\**//** \ 34728 * 34729 * Initiates responsive math on page. 34730 * 34731 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 34732 init : function () { 34733 var $this = this; 34734 34735 $this.updateRowsData(); 34736 34737 // Hiding liveEd for small windows 34738 jQuery(window).resize( function ($e) { 34739 for ( var $i = 0; $i < $this.rows.length; $i++ ) { 34740 $this.setRowHeight($this.rows[$i]); 34741 } //FOR each row 34742 }); //FUNC jQuery.resize 34743 34744 jQuery(window).resize(); 34745 34746 }, //FUNC init 34747 34748 /** //** ----= updateRowsData =------------------------------------------------------------------------------\**//** \ 34749 * 34750 * Searches for blocks on page and updates rows map. 34751 * 34752 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 34753 updateRowsData : function () { 34754 34755 var $this = this; 34756 34757 $this.blocks = jQuery($this.pageBlock); 34758 $this.rows = $this.getRows($this.blocks); 34759 34760 // Updating found rows widths and heights 34761 for ( var $i = 0; $i < $this.rows.length; $i++ ) { 34762 $this.setRowWidth($this.rows[$i]); 34763 $this.setRowHeight($this.rows[$i]); 34764 } //FOR each row 34765 34766 }, //FUNC updateRowsData 34767 34768 /** //** ----= isFloat =--------------------------------------------------------------------------------------\**//** \ 34769 * 34770 * Checks if given element is floating block. This counts any element which behaves like floating block, 34771 * either block or placeholder (which inherits initial float property from block) 34772 * 34773 * @param jQuery $el - Element to check. 34774 * 34775 * @return bool - Check result. 34776 * 34777 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 34778 isFloat : function ($el) { 34779 return $el.hasClass(this.classFloat); 34780 }, //FUNC isFloat 34781 34782 /** //** ----= isHost =--------------------------------------------------------------------------------------\**//** \ 34783 * 34784 * Checks if given floating block starts new row. 34785 * 34786 * @param jQuery $el - Element to check. 34787 * 34788 * @return bool - Check result. 34789 * 34790 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 34791 isHost : function ($el) { 34792 return $el.hasClass(this.classHost); 34793 }, //FUNC isHost 34794 34795 /** //** ----= isPlaceholder =------------------------------------------------------------------------------\**//** \ 34796 * 34797 * Checks if given element is sorting placeholder. 34798 * 34799 * @param jQuery $el - Element to check. 34800 * 34801 * @return bool - Check result. 34802 * 34803 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 34804 isPlaceholder : function ($el) { 34805 return $el.hasClass(this.classPlaceholder); 34806 }, //FUNC isPlaceholder 34807 34808 /** //** ----= getAreas =--------------------------------------------------------------------------------------\**//** \ 34809 * 34810 * Searches areas within context or on page body if omited. If area is given as context -
34811 * it will be included in results. Returns jQuery object containing found areas. 34812 * 34813 * @param jQuery [$context] - Context to search within. 34814 * 34815 * @return jQuery - jQuery object containing found areas. 34816 * 34817 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 34818 getAreas : function ($context) { 34819 34820 $context = $context || jQuery('BODY'); 34821 34822 // Looking up for areas within context 34823 var $areas = $context.find(this.pageArea); 34824 34825 // If area given as context, it shold be included too 34826 if ( $context.is(this.pageArea) ) 34827 $areas = $areas.add($context); 34828 34829 return $areas; 34830 }, //FUNC getAreas 34831 34832 /** //** ----= getRow =--------------------------------------------------------------------------------------\**//** \ 34833 * 34834 * Returns row which current block belongs as array of jQuery blocks. If it's not part of a row, returns FALSE. 34835 * 34836 * @param jQuery $block - Block to return row for. 34837 * 34838 * @return MIXED - Array with siblings or FALSE if not part of row. 34839 * 34840 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 34841 getRow : function ($block) { 34842 34843 // If not floating - not part of row 34844 // Exception is placeholder - it can happen between floats, and I will need to know which row it is 34845 if ( !this.isFloat($block) && !this.isPlaceholder($block) ) 34846 return false; 34847 34848 var $res = []; 34849 34850 // Searching all blocks before block 34851 // If host already, no need to search previous blocks 34852 if ( !$block.is('.rowHost') ) 34853 $block.prevUntil(':not(.' + this.classFloat + '), .rowHost').each( function () { 34854 34855 var $el = jQuery(this); 34856 34857 $res.push( $el ); 34858 34859 // Should include host, if happen 34860 var $prev = $el.prev(); 34861 34862 if ( $prev.is('.rowHost') ) 34863 $res.push( $prev ); 34864 34865 }); //jQuery.each(not floating).callback 34866 34867 // jQuery prev searches from current to top, which gives reversed order 34868 $res.reverse(); 34869 34870 // Adding self 34871 $res.push($block); 34872 34873 // Searching all blocks after block 34874 $block.nextUntil(':not(.' + this.classFloat + '), .rowHost').each( function () { 34875 $res.push( jQuery(this) ); 34876 }); //jQuery.each(not floating).callback 34877 34878 return $res; 34879 }, //FUNC getRow 34880 34881 /** //** ----= getRows =--------------------------------------------------------------------------------------\**//** \ 34882 * 34883 * Returns rows map from given set of elements. 34884 * 34885 * @param jQuery $context - Elements context to arrange. 34886 * 34887 * @return array - Array with found rows map. 34888 * 34889 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 34890 getRows : function ($context) { 34891 34892 var $this = this; 34893 34894 var $rows = []; // Will store all rows, with one there already 34895 34896 // Filtering contect to hosts 34897 // Then getting row of each host 34898 var $hosts = $context.filter( '.'+this.classHost ); 34899 34900 $hosts.each( function () { 34901 34902 // Doing all in one line 34903 $rows.push( $this.getRow( jQuery(this) ) ); 34904 34905 }); // each host 34906 34907 return $rows; 34908 34909 /*/ 34910 var $row = []; // Will store current row 34911 var $rows = [$row]; // Will store all rows, with one there already 34912 34913 // Storing length for referrence 34914 var $l = $context.length; 34915 34916 // First calculating rows and storing them in array for fast access later 34917 for ( var $i = 0; $i < $l; $i++ ) { 34918 34919 // Shortcut to block 34920 var $block = $context.eq($i); 34921 34922 // Skipping invisible blocks, if they will become visible - they will be recalculated 34923 if ( !$block.is(':visible') ) 34924 continue; 34925 34926 if ( this.isFloat($block) ) { 34927 34928 // Row hosts are starting new row anyway 34929 if ( this.isHost($block) ) { 34930 $row = []; 34931 $rows.push($row); 34932 } //IF new row 34933 34934 // Floating blocks are added into current row 34935 $row.push($block); 34936 34937 } //IF float 34938 else if ( $row.length ) { 34939 34940 // Others are starting new row if needed 34941 $row = []; 34942 $rows.push($row); 34943 34944 } //IF new row 34945 34946 } //FOR each block 34947 34948 return $rows; 34949 /**/ 34950 }, //FUNC getRows 34951 34952 /** //** ----= setRowWidth =------------------------------------------------------------------------------\**//** \ 34953 * 34954 * Updates given row with % dimensions instead of static px. Initially page is rendered with px, resizing 34955 * also does px. 34956 * 34957 * @param array $row - Array with blocks in a row. 34958 * @param MIXED [$width] - Numeric width to set. If omited will be calculated from parent area. 34959 * Can be given as jQuery area. 34960 * @param bool [$px] - Set TRUE to correct widhts into absolute px instead of %. 34961 * 34962 * @return SELF 34963 * 34964 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
34965 setRowWidth : function ($row, $width, $px) { 34966 34967 $width = $width || 0; 34968 $px = $px || false; 34969 34970 if ( !$row || !$row.length ) 34971 return this; 34972 34973 if ( $width instanceof jQuery ) { 34974 34975 // Got parent area to use as source 34976 $width = $width.width(); 34977 34978 } else if ( !$width ) { 34979 34980 // Nothing given - using parent area of first block (it exists - checked above) 34981 $width = $row[0].parent().width(); 34982 34983 } //IF nothing given 34984 34985 var $row_width = 0; // Summary row width 34986 var $l = $row.length; // Saving row array length for fast access 34987 34988 // ---- WIDTHS ---- 34989 34990 // Calculating summary row width 34991 for ( var $i = 0; $i < $l; $i++ ) { 34992 34993 var $block = $row[$i]; 34994 34995 // Getting width and padding 34996 var $block_width = $block.width(); 34997 var $block_pad = $block.outerWidth() - $block_width; 34998 34999 // Adding padding back to width 35000 $block_width += $block_pad; 35001 35002 // Correcting block width - can't be more than area width 35003 if ( $block_width > $width ) { 35004 $block_width = $width; 35005 $block.width($width - $block_pad); 35006 } //IF block is too big 35007 35008 // Adding total 35009 $row_width += $block_width; 35010 35011 // Saving width into block object to do not regain later, 35012 // should not interferee with internal properties 35013 $block.tmp_width = $block_width; 35014 $block.tmp_pad = $block_pad; 35015 } //FOR each block in row 35016 35017 // Nothing to do for empty row (possibly everything was invisible) 35018 if ( !$row_width ) 35019 return this; 35020 35021 var $precision = 100; 35022 var $total = 100; 35023 var $totalPx = $row_width; 35024 35025 // Converting width for each block 35026 for ( var $i = 0; $i < $l; $i++ ) { 35027 35028 var $block = $row[$i]; 35029 35030 var $pw = $block.tmp_width; 35031 var $w = Math.round($block.tmp_width / ($row_width / 100) * $precision) / $precision; 35032 35033 // Correcting to total, adding delta to last block 35034 $totalPx -= $pw; 35035 $total -= $w; 35036 35037 // Correcting last column if total is not 0 35038 if ( $i == $l-1 ) { 35039 $pw = $pw + $totalPx; 35040 $w = Math.round(($w + $total) * $precision) / $precision; 35041 } //IF last element 35042 35043 if ( $px ) 35044 // Setting css in px. Nothing tricky here 35045 $block.width($pw); 35046 else 35047 // Setting width css in %. Using calc() in case padding happen, or classic % width if not 35048 $block.css('width', $block.tmp_pad ? 'calc(' + $w + '% - ' + $block.tmp_pad + 'px)' : $w + '%' ); 35049 35050 } //FOR each block in row 35051 35052 return this; 35053 }, //FUNC setRowWidth 35054 35055 /** //** ----= setRowHeight =------------------------------------------------------------------------------\**//** \ 35056 * 35057 * Sets row height, updating all blocks in it with min-height property. 35058 * 35059 * @param array $row - Array with blocks in a row. 35060 * @param int $height - Height to set. 35061 * 35062 * @return SELF 35063 * 35064 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 35065 setRowHeight : function ($row, $height) { 35066 35067 $height = $height || 0; 35068 35069 var $l = $row.length; // Saving row length for fast access 35070 35071 // Recalculating height if none given 35072 if ( !$height ) { 35073 35074 for ( var $i = 0; $i < $l; $i++ ) { 35075 35076 // Ressetting block height to recalculate 35077 $row[$i].css('min-height', ''); 35078 35079 // Getting resulting height 35080 var $tmp_height = $row[$i].height(); 35081 var $tmp_pad = $row[$i].outerHeight() - $tmp_height; 35082 35083 $tmp_height += $tmp_pad; 35084 35085 if ( $tmp_height > $height ) 35086 $height = $tmp_height; 35087 35088 // Saving block pad to count on resize 35089 $row[$i].tmp_hieght_pad = $tmp_pad; 35090 35091 } //FOR each block in row 35092 } //IF no height 35093 35094 // Now updating heights 35095 for ( var $i = 0; $i < $l; $i++ ) { 35096 $row[$i].css('min-height', $height - $row[$i].tmp_hieght_pad); 35097 } //FOR each block in row 35098 35099 return this; 35100 }, //FUNC setRowHeight 35101 35102} //OBJECT mwResponsive 35103 35104jQuery( function () { 35105 // Initiating right away 35106// mwResponsive.init(); 35107}); //jQuery.onLoad 35108 35109var mwCrop = { 35110 35111 items_ids_list : [], // array of ids to make img croppable 35112 35113 init : function() { 35114 35115 var $this = this; 35116 35117 //remove old images (for ajax load) 35118 jQuery('.blogs-post-crop-icon').remove(); 35119 35120 jQuery.each(this.items_ids_list, function(i){ 35121 35122 //var $i = jQuery('#' + $this.items_ids_list[i]); 35123 var $i = jQuery('[data-crop-sn=' + $this.items_ids_list[i] + ']'); 35124 //___($i); 35125 var run_crop = function(e) { 35126 35127 mwLiveEd.toggle(false); 35128 mwLiveEd.noResize = true; 35129 35130 var $ed = mwImgEd($i, { 35131 // 'debug' : true, 35132 'zoomValue' : 1, 35133 'modal' : true, 35134 'overlay' : false, 35135 'resizeOn' : 'y', 35136 // 'resizeOn' : false, 35137 }) 35138 .onSave( function () { 35139 35140 //___(this.queryStr); 35141 //$this.Data.pwidth = Math.round($this.Data.pwidth); 35142 //$this.Data.ewidth = Math.round(this.x.wrapSize); 35143 //$this.Data.eheight = Math.round(this.y.wrapSize); 35144 35145 var $data = {}; 35146 35147 $data['id'] = $this.items_ids_list[i]; 35148 $data['crop'] = this.queryStr; 35149 35150 mwAjax('/site/ajax/blogs/cropcontroller/saveCropDB', $data, false) 35151 .go() 35152 .success( function($data) { 35153 35154 ___('imged crop save done'); 35155 35156 } ) 35157 .error( function() { 35158 35159 ___('imged crop save error'); 35160 35161 } ) 35162 ; // mwAjax 35163 35164 } 35165 ) //FUNC onSave 35166 .onAfterSave( function () { 35167 35168 // Finalizing dimensions 35169 // ToDo: autodetect if necessary in imgEd 35170 this.onResize(); 35171 35172 mwLiveEd.toggle(true); 35173 mwLiveEd.noResize = false;
35174 35175 } 35176 ) //FUNC onAfterSave 35177 ; // $ed 35178 35179 }; 35180 35181 //check is current image local 35182 var isLocal = false; 35183 if ( $i.attr('src').indexOf('://') == -1 ) { 35184 35185 //this is local url 35186 isLocal = true; 35187 35188 } 35189 else { 35190 35191 var url = new URL($i.attr('src')); 35192 35193 //local url 35194 if ( location.host == url.host ) 35195 isLocal = true; 35196 35197 } 35198 35199 //if local url 35200 if ( isLocal ) { 35201 35202 var btn = jQuery('<div class="blogs-post-crop-icon"></div>'); 35203 $i.before(btn); 35204 btn.click(run_crop); 35205 //setTimeout( function() { btn.css('left', $i.width() - 35); btn.css('top', 35); }, 100); 35206 $i.load( function() { btn.css('left', $i.width() - 35); btn.css('top', 35); } ); 35207 35208 $i.off('dblclick').on('dblclick', run_crop); 35209 35210 } 35211 35212 }); 35213 }, 35214 35215 /** //** ----= add_items =------------------------------------------------------------------------------\**//** \ 35216 * 35217 * Add ids of items to list 35218 * 35219 * @param array items - items must be array of text ids 35220 * 35221 * @return nothing 35222 * 35223 \**//** -------------------------------------------------------------------= by Alex @ Morad Media Inc. =------/** //**/ 35224 35225 add_items : function(items) { 35226 35227 jQuery.each(items, function(i){ 35228 35229 //___(this, i, items[i]); 35230 35231 if ( mwCrop.items_ids_list.indexOf(items[i]) == -1 ) 35232 mwCrop.items_ids_list.push(items[i]); 35233 35234 }); 35235 }, 35236 35237 35238 35239} // OBJ mwCrop 35240 35241jQuery( function () { 35242 35243 if ( typeof mwData != "undefined" ) { 35244 35245 mwCrop.init(); 35246 35247 } 35248 35249}); 35250 35251var mwPostEd = { 35252 35253 /* ---- jQuery shortcuts ---- */ 35254 35255 windowId : 'wPostEd', // Editor window ID 35256 window : false, // Editor window object 35257 35258 postEdit : false, // Specal flag for Access Ping process 35259 35260 dom : {}, // Stores interesting window elements 35261 35262 Defaults : { 35263 35264 is_news : 0, 35265 35266 }, 35267 35268 /* ---- Init ---------------------------------------------------------------------------------------------------------------- */ 35269 35270 initDom : function () { 35271 35272 var $this = this; 35273 35274 // Creating shortcuts to window and it's body 35275 $this.window = mwWindow($this.windowId); 35276 $this.dom.body = $this.window.Body; 35277 35278 // Defining complete element prefix 35279 var $pfx = $this.windowId+'_'; 35280 35281 // Looking for special elements in entire window 35282 $this.window.Window.find('[id^='+$pfx+']').each( function () { 35283 35284 var $el = jQuery(this); 35285 35286 // Cutting element name from ID 35287 var $name = this.id.substr($pfx.length); 35288 35289 // Adding class marker to these items 35290 $el.addClass($name); 35291 35292 // Storing it as part of DOM set 35293 $this.dom[$name] = $el; 35294 35295 }); //FUNC each.id 35296 35297 // Reordering element for fast debug 35298 // For this - recreating object in order 35299 var $keys = Object.keys($this.dom).sort(); 35300 var $tmp = {}; 35301 35302 for ( var $i in $keys ) 35303 $tmp[ $keys[$i] ] = $this.dom[$keys[$i]]; 35304 35305 // Resaving back in dom 35306 $this.dom = $tmp; 35307 35308 //___(this.dom); 35309 35310 }, //FUNC initDom 35311 35312 initDimensions : function () { 35313 35314 var $this = this; 35315 35316 // Maximum content width. Browser width and some white space on sides 35317 var $maxWidth = jQuery(window).width() - 80; 35318 35319 // Setting body width 35320 $this.dom.body.width($maxWidth); 35321 35322 }, //FUNC initDimensions 35323 35324 init : function () { 35325 35326 var $this = this; 35327 35328 //init counters once 35329 if ( !$this.meta_title_counter ) { 35330 35331 $this.meta_title_counter = mwTextLengthCounter('#w_wPostEd [name=meta_title]', '#w_wPostEd .meta-title-counter'); 35332 $this.meta_title_counter.min = 10; 35333 $this.meta_title_counter.max = 60; 35334 $this.meta_description_counter = mwTextLengthCounter('#w_wPostEd [name=meta_description]', '#w_wPostEd .meta-description-counter'); 35335 $this.meta_description_counter.min = 100; 35336 $this.meta_description_counter.max = 160; 35337 35338 }//init counters 35339 35340 if ( $this.window ) return; 35341 35342 $this.initDom(); 35343 //$this.initDimensions(); 35344 $this.hidePanel(); 35345 35346 $this.Form = jQuery('#mwPostEd_form'); 35347 $this.TabsControl = jQuery('#mwPostEd_toolsRight'); 35348 $this.PostContent = jQuery('.mwPostEd_PostContent'); 35349 $this.Tabs = jQuery('.mwPostEd_Tabs'); 35350 $this.hideTabsButton = this.TabsControl.find('td[rel=hideTabs]'); 35351 $this.TagTitleInput = jQuery('#tagsFilterPostEd'); 35352 35353 if ( mwData.show_post_id ) { 35354 35355 setTimeout(function(){ mwPostEd.edit(mwData.show_post_id); }, 500); 35356 35357 } 35358 35359 $this.Form.find('.datepicker_icon').click( function(event) { 35360 //___(this); 35361 //mwPostEd.Form.find('.name-published_date input').click(); 35362 jQuery(this).closest('dd').find('input[type=text]').click(); 35363 35364 } ); 35365
35366 jQuery('select[name=header_select]').change(function(e){ 35367 35368 var el = jQuery(this); 35369 if ( el.val() == 'none' ) { 35370 35371 jQuery('.header-row').hide(); 35372 35373 } else if ( el.val() == 'single' ) { 35374 35375 jQuery('.header-row').hide(); 35376 jQuery('.header-row.single').show(); 35377 35378 } else if ( el.val() == 'gallery' ) { 35379 35380 jQuery('.header-row').hide(); 35381 jQuery('.header-row.gallery').show(); 35382 35383 } 35384 35385 }) 35386 35387 35388 35389 return false; 35390 35391 35392 }, //FUNC init 35393 35394 initAccessPing : function() { 35395 ___('initAccessPing'); 35396 var $this = this; 35397 35398 //check is access icon enabled 35399 if ( mwData.accessIcon && $this.ID ) { 35400 35401 var doPing = function() { 35402 35403 mwAjax('/site/ajax/blogs/accessPing/' + $this.ID, null, false ) 35404 .go() 35405 .success( function($data) { 35406 //___($data); 35407 if ( typeof($data.content) != 'undefined' ) { 35408 35409 35410 //check is there are some other users in same post 35411 if ( $data.content.accessUsers ) { 35412 35413 ___('we have some users', $data.content.accessUsers); 35414 $this.accessInfo = $data.content.accessUsers; 35415 35416 $this.showAccessInfo(false); 35417 35418 jQuery('#accessIcon').css('background-image', "url('/res/blogs/images/block-user-red.svg')"); 35419 35420 }//there are other users in same post 35421 else { 35422 ___('no access users'); 35423 $this.accessInfo = []; 35424 35425 //clean up messages 35426 mwState(false, 'wPostEd'); 35427 35428 jQuery('#accessIcon').css('background-image', "url('/res/blogs/images/block-user-grey.svg')"); 35429 35430 }//no users 35431 35432 ___($data.content); 35433 35434 } else { 35435 35436 ___('no data'); 35437 return false; 35438 35439 } 35440 } ); 35441 35442 }//FUNC doPing 35443 35444 //access icon config value should store period in seconds 35445 var timer = mwData.accessIcon; 35446 35447 //do 1st ping without delay 35448 doPing(); 35449 35450 //loop function 35451 (function myLoop() { 35452 35453 //prevent double run 35454 if ( $this.loopTimer ) clearTimeout($this.loopTimer); 35455 35456 $this.loopTimer = setTimeout( function() { 35457 35458 //make ping call 35459 doPing(); 35460 35461 //continue 35462 if ( $this.postEdit ) myLoop(); 35463 35464 }, timer * 1000) 35465 35466 })(); 35467 35468 }//access icon enabled 35469 35470 }, //FUNC initAccessPing 35471 35472 showAccessInfo : function(asPopup = false) { 35473 35474 var $this = this; 35475 35476 if ( $this.accessInfo.length ) { 35477 35478 var spl = ''; 35479 var t = ''; 35480 for ( i in $this.accessInfo ) { 35481 35482 t += spl + '<b>' + $this.accessInfo[i].email + '</b>'; 35483 spl = ', '; 35484 35485 } 35486 35487 if ( !asPopup ) { 35488 35489 //mwState( mwError('User(s) editing this post: ' + t), 'wPostEd') 35490 35491 } 35492 else 35493 mwConfirmation( function() { mwWindow('systemConfirmation').hide(); } 35494 , 'User(s) viewing this post: ' + t); 35495 35496 } 35497 35498 35499 }, //FUNC showAccessInfo 35500 35501 showUsersInPost : function(post_id = 0) { 35502 35503 var $this = this; 35504 35505 if ( !post_id ) return; 35506 35507 mwAjax('/site/ajax/blogs/accessPing/' + post_id, null, false ) 35508 .go() 35509 .success( function($data) { 35510 //___($data); 35511 if ( typeof($data.content) != 'undefined' ) { 35512 35513 35514 //check is there are some other users in same post 35515 if ( $data.content.accessUsers ) { 35516 35517 ___('we have some users', $data.content.accessUsers); 35518 $this.accessInfo = $data.content.accessUsers; 35519 35520 $this.showAccessInfo(true); 35521 35522 35523 35524 }//there are other users in same post 35525 else { 35526 ___('no access users'); 35527 $this.accessInfo = [{'email' : 'None! Update active User by <a href="">refreshing</a> the page.'}]; 35528 35529 $this.showAccessInfo(true); 35530 35531 }//no users 35532 35533 ___($data.content); 35534 35535 } else { 35536 35537 ___('no data'); 35538 return false; 35539 35540 } 35541 } ); 35542 35543 }, //FUNC showUsersInPost 35544 35545 edit : function (id, open_drafts = 0) { 35546 35547 var $this = this; 35548 35549 //clean up messages 35550 mwState(false, 'wPostEd'); 35551 35552 //clean up icon 35553 jQuery('#accessIcon').css('background-image', "url('/res/blogs/images/block-user.png')"); 35554 35555 $this.postEdit = true; 35556 35557 $this.init(); 35558 35559 //init access ping script 35560 $this.initAccessPing(); 35561 35562 $this.hidePanel(); 35563 35564 $this.window.maximized = true; 35565 //___($this.window); 35566 $this.window.show(); 35567 35568 //? 35569 mwPostEd.Form.get(0).reset(); 35570 35571 // clear temporary selected tags 35572 mwPostEd.checked_tags = []; 35573 35574 $this.tiny4_body = jQuery('.mwPostEd_PostContent iframe').off('keyup'); 35575 $this.post_title = mwPostEd.Form.find('input[name=title]').off('keyup'); 35576 35577 $this.post_title.off('change').change( function(e) { 35578 35579 if ( mwPostEd.Form.find('input[name=alias_custom]').val() != '1' ) 35580 mwPostEd.Form.find('input[name=alias]').val( $this.post_title.val() ) 35581 35582 } ); 35583
35584 $this.alias_input = mwPostEd.Form.find('input[name=alias]').off('keyup').keyup( function(e) { 35585 35586 $this.post_title.off('change'); 35587 mwPostEd.Form.find('input[name=alias_custom]').val('1'); 35588 $this.checkAliasValid(this); 35589 35590 } ); 35591 35592 $this.unpublish_start = false; 35593 35594 jQuery('.publish-on-soc-button').show(); 35595 jQuery('.publish-on-soc-success').hide(); 35596 //jQuery('#mwPostEd_form .mce-tinymce').height(517); 35597 //jQuery('#mwPostEd_form #tinyPostEditor_ifr').height(453); 35598 jQuery('.socials-custom-wrapper').hide(); 35599 35600 delete mwData.temp_thumb_name; // remove temporary pictures names 35601 delete mwData.temp_banner_name; 35602 35603 var slider_internal_option = jQuery('#mwPostEd_form select[name=slider_gallery] option#internal'); 35604 35605 //clear error hightlight for tabs controls 35606 mwPostEd.Form.find('.mwWinTabs .error').removeClass('error'); 35607 35608 //for kind select category for new and existing posts - hide categories section and rename tab to TAGS 35609 /* 35610 if ( mwData.kind_category_id ) { 35611 35612 //$this.Tabs.find('#wPostEdCategories').hide(); 35613 $this.TabsControl.find('td[rel=postCategoriesTags]').html('Tags'); 35614 //make tags block full width 35615 //$this.Tabs.find('#wPostEdTags').removeClass('cell-even'); 35616 35617 } else { 35618 35619 //$this.Tabs.find('#wPostEdCategories').show(); 35620 $this.TabsControl.find('td[rel=postCategoriesTags]').html('Categories'); 35621 //make tags block half width 35622 //$this.Tabs.find('#wPostEdTags').addClass('cell-even'); 35623 35624 } 35625 */ 35626 35627 if ( !id ) { 35628 35629 slider_internal_option.hide().val('none'); 35630 35631 mwPostEd.Form.fromArray(this.Defaults); 35632 mwWindow('wPostEd').Title('Add New Post').show( 35633 35634 function() { mwPostEd.resetTabs(); } 35635 35636 ); 35637 this.ID = 0; 35638 mwPostEd.refreshCategoriesSelect(); 35639 mwPostEd.refreshTagsSelect(); 35640 mwPostEd.doDemoThumb(); 35641 35642 jQuery('td[rel=postHistory]').hide(); 35643 35644 if ( mwPostEd.live ) { 35645 35646 var page = []; 35647 page['published'] = 1; // for live Ed new post published by default 35648 mwPostEd.Form.fromArray(page); 35649 mwPostEd.publishSwitch(1, true); 35650 35651 } else 35652 mwPostEd.publishSwitch(0); 35653 35654 mwPostEd.unpublishSwitch(); 35655 35656 mwPostEd.secondarySwitch(); 35657 35658 //for kind select category by default for new post 35659 if ( mwData.kind_category_id ) { 35660 35661 $this.Form.find('#postEdCategoriesList .item>input[value=' + mwData.kind_category_id + ']').click(); 35662 35663 } 35664 35665 return false; 35666 35667 } 35668 35669 this.ID = id; 35670 35671 //regualr load from cache 35672 //var page = mwData.Posts[id]; 35673 35674 //try to load from last loaded via ajax post 35675 if ( mwPostEd.lastAjaxPost ) 35676 page = mwPostEd.lastAjaxPost 35677 35678 //___(id, page); 35679 if ( !page ) { //page is not loaded 35680 35681 mwAjax('/site/ajax/blogs/getPostListDB/' + id + '/0/0', null, true ) 35682 .go() 35683 .success( function($data) { 35684 //___($data); 35685 if ( typeof($data.content) != 'undefined' ) { 35686 35687 mwData.Posts[id] = $data.content[id]; 35688 mwPostEd.lastAjaxPost = $data.content[id]; 35689 mwPostEd.edit(id, open_drafts); 35690 35691 } else { 35692 35693 return false; 35694 35695 } 35696 } ); 35697 35698 return false; 35699 35700 } 35701 else { //page is loaded 35702 35703 //we need to clear last ajax post 35704 mwPostEd.lastAjaxPost = false; 35705 35706 } //page is loaded 35707 35708 // set value for internal gallery (if exist) 35709 if ( page.slider_gallery_internal != 0 ) { 35710 35711 slider_internal_option.show().val(page.slider_gallery_internal); 35712 35713 } else { 35714 35715 slider_internal_option.hide().val('none'); 35716 35717 } 35718 35719 // Resetting form 35720 mwPostEd.Form.fromArray(page); 35721 35722 // store prev custom values for marge on save - dont lose empty file inputs data 35723 mwPostEd.Form.find('input[name=prev_custom_fields]').val(JSON.stringify(mwData.Posts[id].custom_fields)); 35724 //__(JSON.stringify(mwData.Posts[id].custom_fields)); 35725 35726 mwWindow('wPostEd').Title('Edit post (<span>' + page.title + '</span>)').show( 35727 35728 function() { mwPostEd.resetTabs(id); /*mwWindow('wPostEd').adjustHeights(); mwWindow('wPostEd').align();*/ } 35729 35730 ); // mwWindow 35731 35732 var show_current_unsaved = function(event) { 35733 35734 if ( id ) { // dont run for new posts 35735 35736 mwPostEd.CurrentUnsaved_text = mwPostEd.tiny4_body.contents().find('body').html(); 35737 mwPostEd.CurrentUnsaved_title = mwPostEd.post_title.val(); 35738 35739 mwPostEd.doHistoryTab(); 35740 35741 if ( $this.CurrentUnsaved ) 35742 if ( mwPostEd.CurrentUnsaved_text != mwData.Posts[id].content || mwPostEd.CurrentUnsaved_title != mwData.Posts[id].title ) { 35743 35744 $this.CurrentUnsaved.show(); 35745 //$this.CurrentUnsaved.change(); 35746 //jQuery('#postHistory div.Item').removeClass('Selected'); 35747 //jQuery('#postHistory div.Item:has(input[value=edited])>div').addClass('Selected'); 35748 //jQuery('#postHistory div.Item:has(input[value=edited])').mouseup(); 35749 35750 } else { 35751 35752 $this.CurrentUnsaved.hide(); 35753 //$this.LastSaved.show().change(); 35754 //jQuery('#postHistory div.Item').removeClass('Selected'); 35755 //jQuery('#postHistory div.Item:has(input[value=saved])>div').addClass('Selected'); 35756 //jQuery('#postHistory div.Item:has(input[value=saved])').mouseup(); 35757 35758 } 35759 } 35760 }; 35761 35762 jQuery('td[rel=postHistory]').show(); 35763 35764 mwPostEd.CurrentUnsaved_text = mwData.Posts[id].content; 35765 mwPostEd.CurrentUnsaved_title = mwData.Posts[id].title; 35766 35767 $this.tiny4_body.contents().find('body').keyup(show_current_unsaved); 35768 $this.post_title.keyup(show_current_unsaved); 35769 35770 mwPostEd.refreshCategoriesSelect(id); 35771 mwPostEd.refreshTagsSelect(id); 35772 mwPostEd.doDemoThumb(id); 35773 mwPostEd.publishSwitch(mwData.Posts[id].published); 35774 35775 mwPostEd.unpublishSwitch(); 35776 35777 mwPostEd.secondarySwitch(); 35778 35779 //reset counters 35780 $this.meta_title_counter.reset(); 35781 $this.meta_description_counter.reset(); 35782 35783 //add href for links with same class as custom field name in custom tabs 35784 if ( typeof page.custom_fields != 'undefined') { 35785 35786 for(var i in page.custom_fields) { 35787 35788 mwPostEd.Form.find('#postCustom a.' + i).attr('href', page.custom_fields[i]); 35789 35790 } 35791 35792 }//loop custom fields 35793 35794 //store last opened post data 35795 $this.post_data = page; 35796 35797 //open drafts tab if requested 35798 if ( open_drafts ) mwPostEd.Form.find('[rel=postHistory]').click(); 35799 35800 return false;
35801 35802 }, //FUNC edit 35803 35804 showPanel : function ($el) { 35805 35806 var $this = this; 35807 35808 $this.dom.panel.removeClass('hidden'); 35809 35810 if ( jQuery($el).attr('rel') == 'postHistory' ) 35811 mwPostEd.doHistoryTab($this); 35812 35813 mwSwitchTab($el, false, false); 35814 35815 }, //FUNC showPanel 35816 35817 hidePanel : function () { 35818 35819 var $this = this; 35820 35821 $this.dom.panel.addClass('hidden'); 35822 35823 mwSwitchTab($this.dom.hidePanel, false, false); 35824 35825 }, //FUNC showPanel 35826 35827 deletePost : function(id) { 35828 35829 mwConfirmation( function() { 35830 35831 var data = {}; 35832 35833 //check is current category exist (if no - there are no category filter, this means its filtered by kind) 35834 var cur_cat = mwCategoryEd.getCurrentFilterCategoryID(); 35835 if ( cur_cat ) { 35836 35837 data.filter_by_category_id = cur_cat; 35838 35839 } else { 35840 35841 data.filter_by_category_id = mwData.kind_category_id; 35842 data.kind_category_id = mwData.kind_category_id; 35843 35844 } 35845 35846 mwAjax( '/site/ajax/blogs/deletePostDB/' + id, data, 'systemConfirmation' ) 35847 .content() 35848 .success( function($data) { 35849 35850 mwPostEd.manualOrder_sort(); 35851 mwWindow('systemConfirmation').hide(); 35852 35853 } ); 35854 } 35855 , 'Delete Post: ' + mwData.Posts[id]['title'] + '?'); 35856 35857 }, //FUNC deletePost 35858 35859 open_gallery : function(type, gallery_id) { 35860 35861 var id = this.ID; 35862 var $this = this; 35863 35864 var options = {} 35865 var show_selector = false; 35866 35867 if ( type == 'thumb' || type == 'banner' ) { 35868 35869 options = { 35870 35871 'Apply' : { 35872 35873 'class' : 'hi', 35874 'action' : function ($file) { 35875 35876 //__(type, $file); 35877 if ( isEmpty($file) ) return; 35878 35879 jQuery('input[name=' + type + ']').val($file['id']); 35880 mwData['temp_' + type + '_name'] = $file['base'] + '.' + $file['ext']; 35881 mwPostEd.doDemoThumb(id); 35882 35883 } //FUNC setActions.apply.action 35884 } 35885 } 35886 35887 show_selector = true; // need to have selector on thumb/banner choosing 35888 35889 } 35890 35891 if ( type == 'og_image' ) { 35892 35893 options = { 35894 35895 'Apply' : { 35896 35897 'class' : 'Hi', 35898 'action' : function ($file) { 35899 35900 //___(type, $file); 35901 if ( isEmpty($file) ) return; 35902 35903 35904 $this.Form.find('[name=og_image]').val( location.protocol + '//' + location.host + $file.__thumb); 35905 35906 } //FUNC setActions.apply.action 35907 } 35908 } 35909 35910 show_selector = true; 35911 35912 } 35913 35914 //file id false by default 35915 var file_id = false; 35916 35917 if ( !jQuery.isNumeric(gallery_id) ) { 35918 35919 //for new post there are no post data 35920 if ( typeof $this.post_data == 'undefined' ) { 35921 35922 gallery_id = false; 35923 35924 }//new post 35925 else {//existing post 35926 35927 //use internal post gallery as default 35928 gallery_id = $this.post_data.slider_gallery_internal; 35929 35930 }//existing post 35931 35932 } 35933 35934 //not new post 35935 //post already have some file selected in some gallery 35936 if ( typeof $this.post_data != 'undefined' && jQuery.isNumeric($this.post_data.thumb) ) { 35937 35938 //clean up gallery id - let gallery to find itself 35939 gallery_id = false; 35940 35941 //provide gallery with selected file id 35942 var file_id = $this.post_data.thumb 35943 35944 } 35945 35946 //___('show_selector', show_selector); 35947 mwFilesEd.galleriesSelector = show_selector; 35948 mwFilesEd 35949 .setActions( options ) //OBJECT mwFilesEd.setActions.actions 35950 .load(gallery_id, file_id); 35951 //___('mwFilesEd.galleriesSelector', mwFilesEd.galleriesSelector); 35952 }, //FUNC open_gallery 35953 35954 open_selected_gallery : function() { 35955 35956 var gallery_id = jQuery('select[name=slider_gallery]').val(); 35957 35958 this.open_gallery('', gallery_id); 35959 35960 }, //FUNC open_selected_gallery 35961 35962 savePost : function () { 35963 35964 if ( mwData.saveSecureValidation ) 35965 35966 //run save secure validation 35967 mwPostEd.validateSecureSave(mwPostEd.save); 35968 35969 else { 35970 35971 mwPostEd.save(); 35972 35973 } 35974 35975 }, //FUNC savePost 35976 35977 save : function (dont_hide) { 35978 35979 var $this = this; 35980 35981 //post is closing 35982 $this.postEdit = false; 35983 ___('save', $this.postEdit); 35984 mwPostEd.tags_temp = mwData.Tags; 35985 delete mwData.Tags; 35986 if ( mwPostEd.ID ) { 35987 35988 delete mwData.Posts[mwPostEd.ID].tag_selected; 35989 mwPostEd.post_tags_temp = mwData.Posts[mwPostEd.ID].tag_selected; 35990 35991 } 35992 35993 if (mwData.Archive && mwData.Archive[mwPostEd.ID] === null) delete mwData.Archive[mwPostEd.ID]; 35994 35995 //check is current category exist (if no - there are no category filter, this means its filtered by kind) 35996 var cur_cat = mwCategoryEd.getCurrentFilterCategoryID(); 35997 if ( cur_cat ) { 35998 35999 mwPostEd.Form.find('input[name=filter_by_category_id]').val( cur_cat ); 36000 36001 } else { 36002 36003 mwPostEd.Form.find('input[name=filter_by_category_id]').val( mwData.kind_category_id ); 36004 mwPostEd.Form.find('input[name=kind_category_id]').val( mwData.kind_category_id ); 36005 36006 } 36007 36008 var alias_new = jQuery('#mwPostEd_form').find('input[name=alias]').val(); 36009 36010 //clear error hightlight for tabs controls 36011 mwPostEd.Form.find('.mwWinTabs .error').removeClass('error'); 36012 36013 ___('save start'); 36014 mwAjax('/site/ajax/blogs/savePostDB', '#mwPostEd_form', 'wPostEd') 36015 .go() 36016 .success( function($data) { 36017 ___('save success'); 36018 if ( mwPostEd.live ) { 36019 36020 var uri = window.location.pathname.split('/'); 36021 var alias_old = uri[uri.length - 1]; 36022 36023 if ( alias_old == alias_new ) { 36024 36025 mwPostEd.liveCallback($data.block); 36026 mwWindow('wPostEd').hide(); 36027 36028 } else { 36029 36030 //___(alias_old, alias_new, window.location); 36031 var pre_slash = '/'; 36032 if ( !uri[0] ) pre_slash = ''; 36033 uri[uri.length - 1] = alias_new; 36034 var path = uri.join('/'); 36035 var new_url = window.location.origin + pre_slash + path; 36036 window.location = new_url; 36037 36038 } 36039 36040 } else { 36041 36042 //if ( $data.fb_publishing == 'fail' ) mwState( mwError('FB publishing fail!')); 36043 36044 if ( !dont_hide ) { 36045 36046 mwPostEd.resetTabs(); 36047 mwWindow('wPostEd').hide(); 36048 36049 } else { 36050 36051 //jQuery('.publish-on-soc-button').hide(); 36052 jQuery('.publish-on-soc-success').show(); 36053 setTimeout( function() {mwState( mwSuccess('Social Posting Complete'), 'wPostEd' )}, 10); 36054 36055 } 36056 36057 mwPostEd.manualOrder_sort(); 36058 36059 } 36060 } ) 36061 .error( function($data) { 36062 36063 //___('save error', $data); 36064 36065 mwData.Tags = mwPostEd.tags_temp; 36066 if ( mwPostEd.ID ) 36067 mwData.Posts[mwPostEd.ID].tag_selected = mwPostEd.post_tags_temp; 36068 36069 //check is data contain validation and post editor form 36070 if ( typeof $data._validations != 'undefined' && typeof $data._validations.mwPostEd_form != 'undefined' ) { 36071 36072 //loop all validation items and highlight tabs 36073 for( var i in $data._validations.mwPostEd_form ) { 36074 36075 //get the input tab id 36076 var tab_id = jQuery(mwPostEd.Form.find('[name=' + i + ']')).parents('.tabs-container').attr('id'); 36077 36078 //check is current input in some tab 36079 if ( tab_id != undefined ) { 36080 36081 //add error class to highlight tab with validation error input 36082 mwPostEd.Form.find('.mwWinTabs [rel=' + tab_id + ']').addClass('error'); 36083 36084 } 36085 } 36086 } 36087 36088 } ) 36089 ; // mwAjax 36090 ___('save end'); 36091 }, //FUNC save 36092 36093 saveDraft : function () { 36094 36095 if ( mwData.saveSecureValidation ) 36096 36097 //run save secure validation 36098 mwPostEd.validateSecureSave(mwPostEd.saveDraft_origin); 36099 36100 else { 36101 36102 mwPostEd.saveDraft_origin(); 36103 36104 } 36105 36106 }, //FUNC saveDraft 36107 36108 saveDraft_origin : function () { 36109 36110 //jQuery('#mwPostEd_form .published_now input').click(); 36111 mwPostEd.Form.find('[name="publish_button"]').remove(); 36112 mwPostEd.save(false); 36113 mwWindow('systemConfirmation').hide(); 36114 36115 }, //FUNC saveDraft 36116 36117 PublishNow : function (dont_hide) { 36118 36119 if ( mwData.saveSecureValidation ) 36120 36121 //run save secure validation 36122 mwPostEd.validateSecureSave(mwPostEd.PublishNow_origin); 36123 36124 else { 36125 36126 mwPostEd.PublishNow_origin(); 36127 36128 } 36129 36130 }, //FUNC PublishNow 36131 36132 PublishNow_origin : function (dont_hide) { 36133 36134 //jQuery('#mwPostEd_form .published_now input').click();
36135 mwPostEd.Form.append('<input type="hidden" name="publish_button" value="1"/>'); 36136 mwPostEd.save(dont_hide); 36137 mwWindow('systemConfirmation').hide(); 36138 36139 }, //FUNC PublishNow 36140 36141 validateSecureSave : function (callback) { 36142 36143 var post_id = this.ID; 36144 36145 //validate only existing post 36146 if ( post_id ) { 36147 36148 ___('validateSecureSave - post id: ' + post_id); 36149 36150 mwAjax('/site/ajax/blogs/checkSaveSecureValidation/' + post_id, null, true ) 36151 .go() 36152 .success( function($data) { 36153 //___($data); 36154 if ( typeof($data.content) != 'undefined' ) { 36155 36156 //var current_data = $data.content[post_id]; 36157 var current_data = $data.content; 36158 ___('current_data', current_data.date, current_data.user_id); 36159 ___('post data', mwData.Posts[post_id].date, mwData.Posts[post_id].user_id); 36160 36161 //post saved by other user - warning! 36162 if ( current_data.date != mwData.Posts[post_id].date ) { 36163 36164 ___('post saved by other user - warning!'); 36165 36166 var $new_tab = '<a href="/site/blogs/" onclick="document.getElementById(\'open_post_in_new_tab\').submit(); return false;">view the latest saved post in a new tab.</a>'; 36167 $new_tab += '<form target="_blank" action="/site/blogs/" method="post" id="open_post_in_new_tab"><input type="hidden" name="show_post_id" value="' + post_id + '"/></form>'; 36168 36169 mwConfirmation( function() { callback(); } 36170 //, ' Post Saved by other User at ' + current_data.date + ' (' + current_data.login + '|' + current_data.email + '): you may overwrite content! Proceed?'); 36171 , ' Caution! The post was recently modified by ' + current_data.login + '|' + current_data.email + ' on ' + current_data.date + '. If you continue, your changes will overwrite theirs. Click save to overwrite or ' + $new_tab); 36172 36173 } 36174 else {//post safe to save 36175 36176 callback(); 36177 36178 } 36179 36180 } else { 36181 36182 return false; 36183 36184 } 36185 36186 } ); 36187 36188 }//existing post 36189 else {//new post - ignore validation 36190 36191 ___('validateSecureSave - new post - ignore!'); 36192 callback(); 36193 36194 }//new post 36195 36196 }, //FUNC validateSecureSave 36197 36198 closePost : function() { 36199 36200 var $this = this; 36201 36202 //post is closing 36203 $this.postEdit = false; 36204 36205 }, //FUNC closePost 36206 36207 UnPublishNow : function () { 36208 36209 this.unpublish_start = true; 36210 mwPostEd.publishSwitch(0); 36211 mwPostEd.Form.find('.unpublished_now input').click(); 36212 36213 }, //FUNC UnPublishNow 36214 36215 resetTabs : function (id) { 36216 36217 return false; 36218 36219 /* 36220 this.tabsWidth = this.TabsControl.width(); 36221 this.contentWidth = jQuery('#mwPostEd_toolsLeft').width(); 36222 this.basePadding = this.TabsControl.outerWidth() - this.tabsWidth; 36223 ___(this.tabsWidth, this.contentWidth, this.basePadding); 36224 36225 mwSwitchTab(mwPostEd.hideTabsButton); 36226 // Total width: content min width (with scroll):700 + tabs:450 36227 mwPostEd.PostContent.css('margin-right', '0px').width( this.tabsWidth + this.contentWidth + this.basePadding * 1.5 ); //1145 1079 36228 mwPostEd.Tabs.width(0); 36229 //mwPostEd.hideTabsButton.hide(); 36230 36231 //mwWindow('wPostEd').Body.width(mwWindow('wPostEd').Body.width()); 36232 */ 36233 36234 }, //FUNC resetTabs 36235 36236 refreshCategoriesSelect : function (id) { 36237 36238 var $sel = jQuery('.name-categories_list'); 36239 36240 //there are no categories list for kind posts 36241 if ( $sel.length > 0 ) { 36242 36243 $o = {}; 36244 $k = {}; 36245 for ( var $i in mwData.Categories ) { 36246 36247 if ( mwData.nav_list[ mwData.Categories[$i]['title'].toLowerCase() ] != undefined ) { 36248 36249 $k[ mwData.Categories[$i].id ] = '* ' + mwData.Categories[$i].title; 36250 36251 } 36252 else { 36253 $o[ mwData.Categories[$i].id ] = mwData.Categories[$i].title; 36254 } 36255 } 36256 36257 $selected = null; 36258 if ( id ) $selected = mwData.Posts[id].category_selected 36259 36260 //add 'id' prefix to selected list 36261 if ( $selected != null ) 36262 for(var $i in $selected) $selected[$i] = 'id' + $selected[$i]; 36263 36264 //loop selected to move on top 36265 for (var $i in $selected) { 36266 36267 //ignore some trash categories 36268 if ( typeof($o[$selected[$i]]) != 'undefined' ) { 36269 36270 //add selected item to list 36271 $k[$selected[$i]] = $o[$selected[$i]]; 36272 36273 //remove selected item from list 36274 delete($o[$selected[$i]]); 36275 36276 }//real category 36277 36278 }//loop selected 36279 36280 //apply all items to list 36281 for (var $i in $o) $k[$i] = $o[$i]; 36282 36283 //generate select ordered by title 36284 //___($sel, $o, $selected, $k, jQuery.extend({}, $k, $o)); 36285 mwUpdateSelector($sel, $k, $selected); 36286 36287 //remove id prefix from values 36288 jQuery('.name-categories_list .item input').each(function(i){ 36289 36290 var el = jQuery(this); 36291 el.val(el.val().substring(2)); 36292 36293 }); 36294 36295 mwCategoryEd.doFilterCategories( mwCategoryEd.catInputPostEd, jQuery('#postEdCategoriesList .Item'), '.title' ); // add filter 36296 mwCategoryEd.catInputPostEd.keyup( function() { mwState(false, 'wPostEd'); jQuery('.name-categoriesFilterPostEd').removeClass('error'); } ) 36297 36298 } 36299 36300 }, //FUNC refreshCategoriesSelect 36301 36302 refreshTagsSelect : function (id, selected) { 36303 36304 /* 36305 $o = {}; 36306 for ( var $i in mwData.Tags ) 36307 $o[$i] = mwData.Tags[$i].title; 36308 36309 $selected = null; 36310 if ( id ) $selected = mwData.Posts[id].tag_selected 36311 36312 var $sel = jQuery('.name-tags_list'); 36313 mwUpdateSelector($sel, $o, $selected); 36314 36315 mwCategoryEd.doFilterCategories( mwPostEd.TagTitleInput, jQuery('#postEdTagsList .Item'), '.title' ); // add filter 36316 mwPostEd.TagTitleInput.keyup( function() { mwState(false, 'wPostEd'); jQuery('.name-tagsFilterPostEd').removeClass('error'); } ) 36317 */ 36318 36319 $selected = null; 36320 36321 $o = {}; 36322 36323 if ( mwData.ShowAllTagsInPostEd ) { 36324 for ( var $i in mwData.Tags ) 36325 $o[ mwData.Tags[$i].id ] = mwData.Tags[$i].title; 36326 36327 } 36328 36329 if ( id ) { 36330 //___(selected); 36331 if ( typeof(selected) != 'undefined' && selected.length > 0 ) 36332 $selected = selected; 36333 else { 36334 36335 $selected = mwData.Posts[id].tag_selected; 36336 //add 'id' prefix to selected list 36337 for(var $i in $selected) $selected[$i] = 'id' + $selected[$i]; 36338 36339 } 36340 36341 //___('$selected', $selected); 36342 36343 //$selected = jQuery.extend($selected, mwData.Posts[id].tag_selected); 36344 if ( typeof $selected[0] != 'undefined' ) //check is 1st element not empty string "" 36345 for ( var $i in $selected ) { 36346 //___($i, $selected[$i], mwData.Tags[$selected[$i]]); 36347 if ( typeof mwData.Tags[$selected[$i]] != 'undefined' ) 36348 $o[$selected[$i]] = mwData.Tags[$selected[$i]].title; 36349 36350 } 36351 } 36352 //___(jQuery('.name-tags_list'), $o, $selected); 36353
36354 //new list 36355 var $new_o = []; 36356 36357 //loop selected to move on top 36358 for (var $i in $selected) { 36359 36360 //ignore some trash categories 36361 if ( typeof($o[$selected[$i]]) != 'undefined' ) { 36362 36363 //add selected item to list 36364 $new_o[$selected[$i]] = $o[$selected[$i]]; 36365 36366 //remove selected item from list 36367 delete($o[$selected[$i]]); 36368 36369 }//real category 36370 36371 }//loop selected 36372 36373 //apply all items to list 36374 for (var $i in $o) $new_o[$i] = $o[$i]; 36375 36376 mwUpdateSelector(jQuery('.name-tags_list'), $new_o, $selected); 36377 36378 //mwCategoryEd.doFilterCategories( mwPostEd.TagTitleInput, jQuery('#postEdTagsList .Item'), '.title' ); // add filter 36379 //doFilterCategories : function ( input, elements, searchSelector ) 36380 36381 var delay = (function(){ 36382 var timer = 0; 36383 return function(callback, ms){ 36384 clearTimeout (timer); 36385 timer = setTimeout(callback, ms); 36386 }; 36387 })(); 36388 36389 mwPostEd.TagTitleInput.keyup( function(event) { 36390 36391 var $this = this; 36392 36393 delay( function() { 36394 36395 $selected = []; 36396 //___('before', $selected); 36397 //___(jQuery('.name-tags_list').find(':checked')); 36398 jQuery('.name-tags_list').find(':checked').each(function() { 36399 $selected.push(jQuery(this).val()); 36400 }); 36401 //___('after', $selected); 36402 36403 var text = jQuery($this).val(); 36404 36405 if (text.length >= mwData.minTagsFilterLength) { 36406 36407 //$o_new = jQuery.extend({}, $o); 36408 $o_new = []; 36409 jQuery.each($selected, function(i) { 36410 $o_new[$selected[i]] = mwData.Tags['id' + $selected[i]].title; 36411 //___('selected add', $selected[i], mwData.Tags[$selected[i]].title); 36412 } ); 36413 36414 jQuery.each(mwData.Tags, function(i) { 36415 36416 var reg = new RegExp(text, "gi"); 36417 36418 if ( reg.test(mwData.Tags[i].title) ) { 36419 36420 //___('regexp add', i, mwData.Tags[i].title); 36421 $o_new[i] = mwData.Tags[i].title; 36422 36423 } 36424 } ); 36425 //___($o_new); 36426 mwUpdateSelector(jQuery('.name-tags_list'), $o_new, $selected); 36427 36428 } else { 36429 36430 $o_new = []; 36431 jQuery.each($selected, function(i) { 36432 $o_new[$selected[i]] = mwData.Tags[$selected[i]].title; 36433 } ); 36434 36435 mwUpdateSelector(jQuery('.name-tags_list'), $o_new, $selected); 36436 36437 } 36438 36439 cleanUpIds(); 36440 36441 }, 500); 36442 36443 } ); 36444 36445 //remove id prefix from values 36446 var cleanUpIds = function() { 36447 36448 jQuery('.name-tags_list .item input').each(function(i){ 36449 36450 var el = jQuery(this); 36451 var val = el.val(); 36452 36453 //clean up only ids 36454 if ( val.indexOf('id') != -1 ) 36455 el.val(val.substring(2)); 36456 36457 }); 36458 36459 };//cleanUpIds 36460 36461 cleanUpIds(); 36462 36463 mwPostEd.TagTitleInput.keyup( function() { mwState(false, 'wPostEd'); jQuery('.name-tagsFilterPostEd').removeClass('error'); } ) 36464 36465 }, //FUNC refreshTagsSelect 36466 36467 addTag : function () { 36468 36469 var $this = this; 36470 36471 var data = {}; 36472 data.id = 0; 36473 data.title = mwPostEd.TagTitleInput.val(); 36474 36475 var is_valid = true; 36476 36477 if ( data.title.length == 0 ) { 36478 36479 is_valid = false; 36480 mwState(mwError('Title is required'), 'wPostEd'); 36481 36482 } else { 36483 36484 for ( var $i in mwData.Tags ) 36485 if ( mwData.Tags[$i].title == data.title ) { 36486 36487 is_valid = false; 36488 mwState(mwError('Title already exist'), 'wPostEd'); 36489 36490 } 36491 } 36492 36493 //check is current category exist (if no - there are no category filter, this means its filtered by kind) 36494 var cur_cat = mwCategoryEd.getCurrentFilterCategoryID(); 36495 if ( cur_cat ) { 36496 36497 data.filter_by_category_id = cur_cat; 36498 36499 } else { 36500 36501 data.filter_by_category_id = mwData.kind_category_id; 36502 data.kind_category_id = mwData.kind_category_id; 36503 36504 } 36505 36506 if ( is_valid ) { 36507 36508 mwState(false, 'wPostEd'); 36509 jQuery('.name-tagsFilterPostEd').removeClass('error'); 36510 36511 mwAjax( '/site/ajax/blogs/saveTagDB', data ) 36512 .content() 36513 .success( function() { 36514 36515 $selected = []; 36516 jQuery('.name-tags_list').find(':checked').each(function() { 36517 $selected.push(jQuery(this).val()); 36518 }); 36519 36520 mwPostEd.refreshTagsSelect($this.ID, $selected); 36521 mwPostEd.manualOrder_sort(); 36522 mwPostEd.TagTitleInput.keyup(); 36523 36524 } ); 36525 36526 } else { 36527 36528 jQuery('.name-tagsFilterPostEd').addClass('error'); 36529 36530 } 36531 36532 }, //FUNC addTag 36533 36534 publish : function (id, published, published_date) { 36535 36536 var phrase_start = 'Publish'; 36537 if( !published ) phrase_start = 'Unpublish'; 36538 36539 mwConfirmation( function() { 36540 36541 var data = {}; 36542 36543 data.id = id; 36544 data.published = published; 36545 if ( published_date ) data.published_date = published_date; 36546 36547 //check is current category exist (if no - there are no category filter, this means its filtered by kind) 36548 var cur_cat = mwCategoryEd.getCurrentFilterCategoryID(); 36549 if ( cur_cat ) { 36550 36551 data.filter_by_category_id = cur_cat; 36552 36553 } else { 36554
36555 data.filter_by_category_id = mwData.kind_category_id; 36556 data.kind_category_id = mwData.kind_category_id; 36557 36558 } 36559 36560 mwAjax( '/site/ajax/blogs/doPublish', data, 'systemConfirmation' ) 36561 .index('#categoriesListContent, #categoriesTreeContent') 36562 .success( function($data) { mwPostEd.manualOrder_sort(); } ) 36563 36564 } 36565 , phrase_start + ' Post: ' + mwData.Posts[id]['title'] + '?'); 36566 36567 }, //FUNC publish 36568 36569 publishSwitch : function (state, dont_hide) { 36570 36571 var $this = this; 36572 36573 var publish_tr = mwPostEd.Form.find('.post_publish_tr'); 36574 var unpublish_tr = mwPostEd.Form.find('.post_unpublish_tr'); 36575 var date_time_tr = mwPostEd.Form.find('.date_time_tr'); 36576 var publish_button = jQuery('#publish_button_body'); 36577 var save_button = jQuery('#save_button_body'); 36578 var draft_button = jQuery('#draft_button_body'); 36579 var input_published = mwPostEd.Form.find('input[name=published]'); 36580 36581 if ( state == 2 ) { 36582 36583 date_time_tr.show(); 36584 36585 } else { 36586 36587 date_time_tr.hide(); 36588 36589 } 36590 36591 if ( state > 0 && !dont_hide ) { 36592 36593 publish_tr.hide(); 36594 unpublish_tr.show(); 36595 date_time_tr.hide(); 36596 36597 } else { 36598 36599 publish_tr.show(); 36600 unpublish_tr.hide(); 36601 36602 } 36603 36604 if ( this.ID ) { 36605 36606 if ( mwData.Posts[this.ID]['published_date'] != '' ) 36607 jQuery('#published_date_span').html('Post Published by Schedule: ' + mwData.Posts[this.ID]['published_date_view']); 36608 else 36609 jQuery('#published_date_span').html('Post Published: ' + mwData.Posts[this.ID]['published_date_min']); 36610 36611 } 36612 36613 if ( typeof(mwData.Posts[this.ID]) == 'undefined' || mwData.Posts[this.ID]['published'] == 0 || this.unpublish_start ) { 36614 36615 $this.dom.submitDraft.show(); 36616 $this.dom.submitPublish.show(); 36617 36618 $this.dom.submitSave.hide(); 36619 36620 //publish_button.show(); 36621 //draft_button.show(); 36622 //save_button.removeClass('hi'); 36623 //save_button.html('Save Draft'); 36624 input_published.val(0); 36625 36626 } else { 36627 36628 $this.dom.submitDraft.hide(); 36629 $this.dom.submitPublish.hide(); 36630 36631 $this.dom.submitSave.show(); 36632 36633 //publish_button.hide(); 36634 //save_button.addClass('hi'); 36635 //save_button.html('Save'); 36636 input_published.val(state); 36637 36638 } 36639 36640 }, //FUNC publishSwitch 36641 36642 unpublishSwitch : function(state) { 36643 //___('unpublishSwitch', 111, state); 36644 var input_unpublish = mwPostEd.Form.find('input[name=unpublish]'); 36645 var unpublish_tr = mwPostEd.Form.find('.unpublish_time_tr'); 36646 var unpublished_flag = jQuery('input[name=unpublished_flag]'); 36647 36648 if ( typeof(state) == 'undefined' ) { 36649 36650 state = input_unpublish.val() * 1; 36651 36652 } else { 36653 36654 state = input_unpublish.val() * 1; 36655 36656 if ( state ) 36657 state = 0; 36658 else 36659 state = 1; 36660 36661 input_unpublish.val(state); 36662 36663 //___('unpublishSwitch', 222, state); 36664 input_unpublish.val(state); 36665 36666 } 36667 //___('unpublishSwitch', 333, state); 36668 if ( state ) { 36669 36670 unpublish_tr.show(); 36671 36672 } else { 36673 36674 unpublish_tr.hide(); 36675 36676 } 36677 36678 /* 36679 if ( typeof(mwData.Posts[this.ID]) != 'undefined' && mwData.Posts[this.ID]['unpublished_date'] != '' ) { 36680 36681 unpublish_status.show(); 36682 jQuery('#unpublished_date_span').html('Post Unpublished by Schedule: ' + mwData.Posts[this.ID]['unpublished_date_view']); 36683 36684 36685 } else { 36686 36687 unpublish_status.hide(); 36688 36689 } 36690 */ 36691 36692 }, //FUNC unpublishSwitch 36693 36694 secondarySwitch : function(state) { 36695 36696 setTimeout(function(){ 36697 36698 var tr = mwPostEd.Form.find('.secondary_time_tr'); 36699 var input = mwPostEd.Form.find('[name=secondary_flag]'); 36700 //___(state, tr, input); 36701 if ( typeof(state) == 'undefined' ) { 36702 36703 if ( this.ID ) { 36704 36705 state = mwData.Posts[this.ID]['secondary_flag']; 36706 36707 } else { 36708 36709 state = input.parent().find('.checked').length; 36710 36711 } 36712 } 36713 //___(state); 36714 if ( state ) { 36715 36716 tr.show(); 36717 36718 } else { 36719 36720 tr.hide(); 36721 36722 } 36723 36724 }, 1) 36725 36726 }, //FUNC secondarySwitch 36727 36728 doDemoThumb : function (id) { 36729 36730 /*if ( !id ) { 36731 36732 jQuery('#demo_thumb_icon, #demo_banner_icon').hide(); 36733 return false;
36734 36735 } */ 36736 36737 if ( id ) { 36738 36739 mwData.Posts[id].delete_thumb = false; 36740 mwData.Posts[id].delete_banner = false; 36741 36742 } 36743 36744 /* 36745 var del_pic_ajax = function(type) { 36746 36747 var data = {}; 36748 data.id = id; 36749 data.img_type = type; 36750 36751 mwAjax( '/site/ajax/blogs/deletePicture', data ) 36752 .content() 36753 .success( function($response) { mwPostEd.doDemoThumb(id); } ); 36754 36755 }; 36756 */ 36757 36758 var del_pic = function(type) { 36759 36760 if ( type == 'thumb' ) { 36761 36762 mwData.Posts[id].delete_thumb = true; 36763 delete mwData.Posts[id].temp_thumb_name; 36764 36765 } 36766 36767 if ( type == 'banner' ) { 36768 36769 mwData.Posts[id].delete_banner = true; 36770 delete mwData.Posts[id].temp_banner_name; 36771 36772 } 36773 36774 var img_div = jQuery('#demo_' + type + '_icon'); 36775 img_div.slideUp( function() { 36776 36777 img_div.html('<input type="hidden" name="delete_' + type + '" value=""/>'); 36778 36779 } ); 36780 //reinit_file_input( jQuery('#demo_' + type + '_icon_td') ); 36781 36782 }; 36783 36784 /* 36785 var reinit_file_input = function(name) { 36786 36787 var wrapper = jQuery('#demo_' + n
36787ame + '_icon_td span'); 36788 if ( name == 'banner' ) name = 'header'; 36789 wrapper.html('<input type="file" name="' + name + '_icon">'); 36790 styleDialog(wrapper); 36791 36792 } 36793 */ 36794 36795 /* 36796 var do_field = function(type, animate) { 36797 36798 var pic = ''; 36799 36800 if ( type == 'thumb' && mwData.Posts[id].thumb && !mwData.Posts[id].delete_thumb ) 36801 var pic = '<img src="/files/galleries/' + mwData.Posts[id].thumb + '">'; 36802 36803 if ( type == 'banner' && mwData.Posts[id].banner && !mwData.Posts[id].delete_banner ) 36804 var pic = '<img src="/files/galleries/' + mwData.Posts[id].banner + '">'; 36805 36806 var img_div = jQuery('#demo_' + type + '_icon'); 36807 36808 if ( pic != '' ) 36809 img_div.html(pic) 36810 .append('<div class="demo_delete"></div>') 36811 .show() 36812 .find('.demo_delete') 36813 .click( function(event) { del_pic(type); } ); 36814 else 36815 img_div.html('').hide(); 36816 36817 //reinit_file_input(type); 36818 36819 }; 36820 */ 36821 36822 var do_field = function(type) { 36823 36824 //var pic_start = '<img src="/files/galleries/'; 36825 var pic_start = '<img src="'; 36826 var pic_end = '">'; 36827 var pic = ''; 36828 36829 if ( type == 'thumb' ) { 36830 36831 36832 36833 if ( mwData.temp_thumb_name ) { 36834 36835 //add files/galleries folder in case images selected from gallery just right now 36836 if (mwData.temp_thumb_name.indexOf('/') == -1 ) 36837 pic_start += '/files/galleries/'; 36838 36839 pic = pic_start + mwData.temp_thumb_name + pic_end; 36840 36841 } 36842 else if ( id && mwData.Posts[id].thumb_file ) { 36843 36844 pic = pic_start + mwData.Posts[id].thumb_file + pic_end; 36845 36846 } 36847 36848 } 36849 36850 if ( type == 'banner' ) { 36851 36852 if ( mwData.temp_banner_name ) { 36853 36854 //add files/galleries folder in case images selected from gallery just right now 36855 if (mwData.temp_banner_name.indexOf('/') == -1 ) 36856 pic_start += '/files/galleries/'; 36857 36858 pic = pic_start + mwData.temp_banner_name + pic_end; 36859 36860 } 36861 else if ( id && mwData.Posts[id].banner_file ) { 36862 36863 pic = pic_start + mwData.Posts[id].banner_file + pic_end; 36864 36865 } 36866 36867 } 36868 36869 var img_div = jQuery('#demo_' + type + '_icon'); 36870 //__(img_div, pic); 36871 if ( pic != '' ) { 36872 img_div.html(pic) 36873 .append('<div class="demo_delete"></div>') 36874 .show(); 36875 36876 jQuery('#demo_' + type + '_icon_td') 36877 .find('.demo_delete') 36878 .click( function(event) { del_pic(type); } ); 36879 } 36880 else { 36881 img_div.html('').hide(); 36882 } 36883 36884 }; 36885 36886 do_field('thumb'); 36887 do_field('banner'); 36888
36889 }, //FUNC doDemoThumb 36890 36891 dataSocialsUpload : function() { 36892 36893 var form = mwPostEd.Form; 36894 36895 var data = {}; 36896 data.message = mwSocials().removeTags( form.find('textarea[name=content]').val() ); 36897 data.picture = window.location.host + '/' + form.find('div#demo_thumb_icon img').attr('src'); 36898 data.link = mwData.postPageURL + '/' + this.ID + '/' + mwData.Posts[this.ID].title_url; 36899 data.name = form.find('input[name=title]').val(); 36900 data.description = form.find('textarea[name=description]').val(); 36901 36902 return data; 36903 36904 }, //FUNC dataSocialsUpload 36905 36906 postOnSocials : function() { 36907 36908 mwSocials().publishOnSoc(this.dataSocialsUpload()); 36909 36910 }, //FUNC postOnSocials 36911 36912 manualOrderInit : function() { 36913 36914 jQuery('.sort_td').hide(); 36915 36916 mwPostEd.is_manually_sort = false; 36917 36918 jQuery('#order_select').change( function(event) { 36919 36920 var $el = jQuery(this); 36921 var $val = $el.val(); 36922 36923 // Special case for manual sorting 36924 mwPostEd.is_manually_sort = ($val == 'manual'); 36925 36926 // Sorting things 36927 mwPostEd.doSortTable($val); 36928 } ); 36929 36930 mwPostEd.manualOrder_sort(); 36931 36932 }, //FUNC manualOrderInit 36933 36934 manualOrder_sort : function() { 36935 36936 mwPostEd.posts_list = jQuery('.mwIndexTable tbody'); 36937 36938 mwPostEd.posts_list.sortable( { 36939 36940 handle : '.manual_sort_handle', 36941 forceHelperSize : true, 36942 forcePlaceholderSize : true, 36943 placeholder : 'Placeholder', 36944 errorClass : 'PlaceholderErr', 36945 helper : 'clone', 36946 appendTo : 'parent', 36947 axis : 'y', 36948 scroll : false, 36949 forceHelperSize : true, 36950 update : function(event, ui) { 36951 36952 var data = {}; 36953 data.posts_list = mwPostEd.posts_list.sortable( "toArray" ); 36954 36955 mwAjax('/site/ajax/blogs/savePostsOrder', data, false) 36956 .index('#postListContent') 36957 .success( function($data) { mwPostEd.manualOrder_sort(); } ) 36958 .error( function() { } ) 36959 ; // mwAjax 36960 36961 }, 36962 start : function(event, ui) { 36963 36964 var tds_helper = ui.helper.find('th, td'); 36965 var tds_table = jQuery('.mwIndexTable thead').find('th, td'); 36966 36967 jQuery.each(tds_helper, function(i) { 36968 36969 jQuery(this).attr('id', 'no_transition_width').width( jQuery(tds_table.get(i)).width() ); 36970 36971 } ); 36972 } 36973 } ); 36974 36975 jQuery('#order_select').change(); 36976 36977 if ( typeof mwData.AjaxFilter == "undefined" ) { 36978 36979 jQuery('#categories_filter').change(); 36980 36981 } 36982 36983 }, //FUNC manualOrder_sort 36984 36985 doSortTable : function (sort_by) { 36986 36987 sort_by_parts = sort_by.split('_'); 36988 //___('sort_by', sort_by, sort_by_parts); 36989 36990 var rows = mwPostEd.posts_list.find('tr'); 36991 36992 if ( mwPostEd.is_manually_sort ) sort_by = 'manual'; 36993 36994 if ( sort_by == 'default' ) sort_by = 'id'; 36995 36996 if ( sort_by == 'manual' ) 36997 jQuery('.manual_sort_handle').show(); 36998 else 36999 jQuery('.manual_sort_handle').hide(); 37000 37001 rows.sort( function(a, b){ 37002 37003 var compA = jQuery(a).attr(sort_by_parts[0]); 37004 var compB = jQuery(b).attr(sort_by_parts[0]) 37005 37006 //___(sort_by, compA, compB); 37007 37008 if ( sort_by_parts[0] != 'alpha' ) { 37009 37010 compA = parseInt(compA, 10); 37011 compB = parseInt(compB, 10); 37012 37013 var intRegex = /^\d+$/; 37014 if( ! intRegex.test(compA) ) { compA = 0; } 37015 if( ! intRegex.test(compB) ) { compB = 0; } 37016 37017 if ( sort_by_parts[1] == 'asc' ) 37018 return (compA < compB) ? 1 : (compA > compB) ? -1 : 0; 37019 else 37020 return (compA < compB) ? -1 : (compA > compB) ? 1 : 0; 37021 37022 } else { 37023 //___(compA, compB, compA.localeCompare(compB)); 37024 //return compA.localeCompare(compB); 37025 37026 compA = compA.toLocaleLowerCase(); 37027 compB = compB.toLocaleLowerCase(); 37028 37029 if ( sort_by_parts[1] == 'asc' ) 37030 return (compA < compB) ? -1 : (compA > compB) ? 1 : 0; 37031 else 37032 return (compA < compB) ? 1 : (compA > compB) ? -1 : 0; 37033 37034 } 37035 37036 37037 } ); 37038 37039 jQuery.each( rows, function(i) { 37040 37041 mwPostEd.posts_list.append(this); 37042 37043 } ); 37044 37045 }, //FUNC doSortTable 37046 37047 doSortTableButton : function () { 37048 37049 var rows = mwPostEd.posts_list.find('tr'); 37050 37051 if ( jQuery('.manual_sort_handle').is(':visible') ) { 37052 37053 mwPostEd.is_manually_sort = false; 37054 mwPostEd.doSortTable( jQuery('#order_select').val() ); 37055 37056 } else { 37057 37058 mwPostEd.is_manually_sort = true; 37059 mwPostEd.doSortTable( 'manual' ); 37060 37061 } 37062 37063 }, //FUNC doSortTableButton 37064 37065 doHistoryTab : function ($this) { 37066 37067 var obj = this; 37068
37069 var doIt = function() { 37070 37071 //special check - bugfix 37072 //sometimes, rly rare mwData.Posts[obj.ID] doesnt exists 37073 if ( !mwData.Posts || !mwData.Posts[obj.ID] ) return; 37074 37075 var tiny_content = obj.PostContent.find('textarea[name=content]'); 37076 37077 var post_title = jQuery('input[name=title]'); 37078 37079 var $o = {}; 37080 $o['edited'] = 'Current Unsaved'; 37081 $o['saved'] = 'Last Saved'; 37082 37083 var selected = 'saved'; 37084 if ( mwPostEd.CurrentUnsaved_text != mwData.Posts[obj.ID].content || mwPostEd.CurrentUnsaved_title != mwData.Posts[obj.ID].title ) 37085 selected = 'edited'; 37086 37087 for ( var $i in mwData.Archive[obj.ID] ) 37088 $o[ 'id' + $i ] = mwData.Archive[obj.ID][$i].create_date + ' (' + mwData.Archive[obj.ID][$i].user_display_name + ')'; 37089 37090 var $sel = jQuery('.name-postEdHistoryList'); 37091 mwUpdateSelector($sel, $o, selected); 37092 37093 obj.CurrentUnsaved = jQuery('div.item:has(input[value=edited])'); 37094 obj.LastSaved = jQuery('div.item:has(input[value=saved])'); 37095 37096 if ( selected != 'edited' ) obj.CurrentUnsaved.hide(); 37097 37098 jQuery('.name-postEdHistoryList').click( function(event) { 37099 37100 var clicked_id = jQuery(event.target).val(); 37101 37102 //___(mwData.Archive[obj.ID], clicked_id, mwData.Archive[obj.ID][clicked_id] ) 37103 37104 if ( clicked_id ) 37105 if ( clicked_id == 'saved' ) { 37106 37107 tiny_content.val(mwData.Posts[obj.ID].content); 37108 post_title.val(mwData.Posts[obj.ID].title); 37109 37110 } else if (clicked_id == 'edited') { 37111 37112 tiny_content.val(mwPostEd.CurrentUnsaved_text); 37113 post_title.val(mwPostEd.CurrentUnsaved_title); 37114 37115 } else { 37116 37117 tiny_content.val(mwData.Archive[obj.ID][clicked_id.substring(2)].content); 37118 post_title.val(mwData.Archive[obj.ID][clicked_id.substring(2)].title); 37119 37120 } 37121 }); 37122 37123 //mwSwitchTab($this); 37124 37125 } 37126 37127 if ( mwData.saveSecureValidation || !mwData.Archive || ( !mwData.Archive[obj.ID] && mwData.Archive[obj.ID] !== null ) ) 37128 mwAjax( '/site/ajax/blogs/getHistorySelect', { 'ID' : obj.ID }, 'wPostEd' ) 37129 .content() 37130 .success( function($data) { doIt(); } ) 37131 .error( function() { } ) 37132 else 37133 doIt(); 37134 37135 }, //FUNC doHistoryTab 37136 37137 show_hide_soc_customs : function ($this) { 37138 37139 var soc = jQuery($this).attr('rel'); 37140 jQuery('.socials-custom-wrapper.' + soc).toggle(400); 37141 37142 }, //FUNC show_hide_soc_customs 37143 37144 isValidChr : function(str){ 37145 37146 return !/[~`!#$%\^&*@()+=\[\]\\';,/{}\\":<>\?]/g.test(str); 37147 37148 }, //FUNC isValidChr 37149 37150 checkAliasValid : function($this) { 37151 37152 if ( !mwPostEd.isValidChr(jQuery($this).val()) ) { 37153 37154 mwState(mwError('"-", "_", "|" are only special character allowed for alias, all other characters will be removed on save'), 'wPostEd'); 37155 jQuery('.name-alias').addClass('error'); 37156 37157 } else { 37158 37159 jQuery('.name-alias').removeClass('error'); 37160 mwState(false, 'wPostEd'); 37161 37162 } 37163 37164 }, //FUNC checkAliasValid 37165 37166}; //CLASS mwPostEd 37167 37168//--------------------------------------------------------------------------------------------------------------------------------------------------- 37169 37170var mwCategoryEd = { 37171 37172 ID : 0, // Current category ID 37173 37174 LastItem : 0, // last used item from list - dom object 37175 37176 NewCounter : 0, 37177 37178 Defaults : { // Form defaults for resetting dialog 37179 37180 id : 0, 37181 parent_id : 0, 37182 title : '', 37183 comment : '', 37184 is_news : 0, 37185 no_index : 0, 37186 no_follow : 0, 37187 37188 }, //OBJECT Defaults 37189 37190 init : function() { 37191 37192 mwCategoryEd.updateCategories = {};
37192 // array for updating existing categories on save 37193 mwCategoryEd.deleteCategories = []; // array for delete existing categories on save 37194 mwCategoryEd.newCategories = {}; // array for create new categories on save 37195 mwCategoryEd.ID = 0; 37196 mwCategoryEd.LastItem = 0; 37197 mwCategoryEd.NewCounter = 0; 37198 37199 mwCategoryEd.form = jQuery('#saveCategory_form'); 37200 mwCategoryEd.listContainer = jQuery('.categories_list_container'); 37201 mwCategoryEd.catInputPostEd = jQuery('#categoriesFilterPostEd'); 37202 37203 //mwCategoryEd.buildCategoriesList(); 37204 mwCategoryEd.buildCategoriesTree(); 37205 mwCategoryEd.doCategoriesMainFilter(); 37206 mwCategoryEd.doDraggableItems(); 37207 mwCategoryEd.doFilterCategoriesTree( jQuery('#categoriesFilter'), jQuery('.categories_list li'), 'a span' ); 37208 37209 }, //FUNC init 37210 37211 refreshCategoriesList : function (id) { // this function using with special control (folders-like) 37212 37213 this.ID = id; 37214 mwAjax( '/site/ajax/blogs/index', { 'categoryID' : this.ID } ) 37215 .index('#categoriesListContent, #categoriesTreeContent'); 37216 37217 }, //FUNC refreshCategoriesList 37218 37219 manageCategories : function () { 37220 37221 //this.init(); 37222 37223 //hide special (kind) categories 37224 for(var c in mwData.Categories) { 37225 37226 if ( mwData.nav_list[ mwData.Categories[c]['title'].toLowerCase() ] != undefined ) { 37227 37228 mwCategoryEd.listContainer.find('li#' + c).hide(); 37229 37230 } 37231 } 37232 37233 mwWindow('wManageCategories').show(); 37234 37235 mwCategoryEd.editItemGrant = false; // this flag using for disable/enable change event on form fields 37236 this.form.hide().fromArray(this.Defaults); 37237 37238 return false; 37239 37240 }, //FUNC manageCategories 37241 37242 saveCategoriesEd : function () { 37243 37244 var data = {}; 37245 37246 //check is current category exist (if no - there are no category filter, this means its filtered by kind) 37247 var cur_cat = mwCategoryEd.getCurrentFilterCategoryID(); 37248 if ( cur_cat ) { 37249 37250 data.filter_by_category_id = cur_cat; 37251 37252 } else { 37253 37254 data.filter_by_category_id = mwData.kind_category_id; 37255 data.kind_category_id = mwData.kind_category_id; 37256 37257 } 37258 37259 data.updateCategories = []; 37260 for ( var $i in this.updateCategories ) 37261 data.updateCategories.push( this.updateCategories[$i] ); 37262 37263 data.deleteCategories = this.deleteCategories; 37264 37265 data.newCategories = []; 37266 for ( var $i in this.newCategories ) 37267 data.newCategories.push( this.newCategories[$i] ); 37268 37269 if ( mwCategoryEd.isSorted ) 37270 data.orderCategories = mwCategoryEd.treeToArray(); 37271 37272 /* 37273 __('update',mwCategoryEd.updateCategories); 37274 __('delete',mwCategoryEd.deleteCategories); 37275 __('new',mwCategoryEd.newCategories); 37276 __('order',mwCategoryEd.orderCategories); 37277 */ 37278 37279 mwCategoryEd.cat_temp = mwData.Categories; 37280 delete mwData.Categories; 37281 37282 mwAjax('/site/ajax/blogs/saveCategoryDB', data, 'wManageCategories') 37283 .index('#categoriesListContent, #categoriesTreeContent') 37284 .success( function() { 37285 37286 //mwCategoryEd.deleteCategories.forEach( function(value) { delete mwData.Categories[value]; } ); // remove all deleted categories from mwData (after succes) 37287 mwPostEd.refreshCategoriesSelect(mwPostEd.ID); // refresh categories list on postEd categories tab 37288 mwCategoryEd.init(); 37289 mwPostEd.manualOrder_sort(); 37290 37291 //refresh categories on desktop 37292 mwCategoryEd.doCategoriesMainFilter(); 37293 37294 } ) 37295 .error( function() { 37296 37297 mwData.Categories = mwCategoryEd.cat_temp; 37298 37299 } ) 37300 ; 37301 37302 }, //FUNC save 37303 37304 addCategory : function () { 37305 37306 var cat_data = {}; 37307 cat_data.id = 0; 37308 cat_data.parent_id = 0; 37309 cat_data.title = jQuery('#categoriesFilterPostEd').val(); 37310 37311 var is_valid = true; 37312 37313 if ( cat_data.title.length == 0 ) { 37314 37315 is_valid = false; 37316 mwState(mwError('Title is required'), 'wPostEd'); 37317 37318 } else { 37319 37320 for ( var $i in mwData.Categories ) 37321 if ( mwData.Categories[$i].title == cat_data.title ) { 37322 37323 is_valid = false; 37324 mwState(mwError('Title already exist'), 'wPostEd'); 37325 37326 } 37327 } 37328 ___(is_valid); 37329 if ( is_valid ) { 37330 37331 mwState(false, 'wPostEd'); 37332 jQuery('.name-categoriesFilterPostEd').removeClass('error'); 37333 37334 var data = {}; 37335 data.newCategories = []; 37336 data.newCategories.push( cat_data ); 37337 37338 //check is current category exist (if no - there are no category filter, this means its filtered by kind) 37339 var cur_cat = mwCategoryEd.getCurrentFilterCategoryID(); 37340 if ( cur_cat ) { 37341 37342 data.filter_by_category_id = cur_cat; 37343 37344 } else { 37345
37346 data.filter_by_category_id = mwData.kind_category_id; 37347 data.kind_category_id = mwData.kind_category_id; 37348 37349 } 37350 ___(data); 37351 mwAjax( '/site/ajax/blogs/saveCategoryDB', data ) 37352 .content() 37353 .success( function() { 37354 37355 mwPostEd.refreshCategoriesSelect(mwPostEd.ID); 37356 37357 mwCategoryEd.doCategoriesMainFilter(); 37358 37359 } ); 37360 37361 } else { 37362 37363 jQuery('.name-categoriesFilterPostEd').addClass('error'); 37364 37365 } 37366 37367 }, //FUNC addCategory 37368 37369 treeToArray : function() { 37370 37371 var cat_list = []; 37372 37373 jQuery('.categories_list>ul').find('li[id]').each( function(i) { 37374 37375 el = jQuery(this); 37376 var id = el.attr('id'); 37377 var parent_id = el.parent().parent('li[id]').attr('id'); 37378 if ( parent_id == undefined ) parent_id = 0; 37379 37380 cat_list.push( { id : id, parent_id : parent_id } ); 37381 37382 //__(i + ' | id - ' + id + ' | parent_id - ' + parent_id + ' | ' + el.find('span').html()); 37383 37384 } ); 37385 37386 return cat_list; 37387 37388 }, //FUNC toArray 37389 37390 editItem : function (id, $this) { 37391 // ___('EDIT START', id); 37392 if ( mwCategoryEd.ID != 0 ) // if there was already some edition of items - save changes (fix bug - click on sortable items after editing fields not trigger onchange) 37393 if ( ! mwCategoryEd.saveItem() ) return false; // if cant save - dont let edit new item 37394 37395 mwCategoryEd.ID = id; 37396 mwCategoryEd.LastItem = $this; 37397 37398 var page = mwCategoryEd.Defaults; 37399 37400 id = id.substring(2); // remove "id" symbols 37401 // ___('page Defaults', page); 37402 if ( !isNaN(id-0) ) { // if ID numeric - its existing category, else - new 37403 37404 id = 'id' + id; 37405 37406 page = mwCategoryEd.updateCategories[id]; // try check category on update list (mb its already changed) 37407 // ___('!page start', !page, page); 37408 if ( !page ) page = mwData.Categories[id]; // if not changed then try default 37409 // ___('!page', !page, page); 37410 if ( !page ) { throw 'ERROR: wrong ID provided for mwCategoryEd.editItem()'; return false; } 37411 // ___('!page 2', !page, page); 37412 } else { 37413 37414 id = 'ne' + id; 37415 page = jQuery.extend(true, {}, mwCategoryEd.newCategories[id]); 37416 // ___('else page', page); 37417 } 37418 // ___('final page', page); 37419 mwCategoryEd.form.fadeOut( 'fast', function() { 37420 37421 setTimeout( function() { 37422 37423 mwCategoryEd.editItemGrant = false; 37424 mwCategoryEd.form.fromArray(page) 37425 mwCategoryEd.form.find('input[name=title]').focus(); 37426 mwCategoryEd.editItemGrant = true; 37427 37428 }, 1 ); // set focus on title input 37429 37430 } ).fadeIn('fast', function() { 37431 37432 37433 37434 } ); 37435 jQuery('.categories_list').find('.Selected').removeClass('Selected'); 37436 jQuery($this).parent().addClass('Selected'); 37437 37438 return false; 37439 37440 }, //FUNC editItem 37441 37442 saveItem : function () { 37443 37444 if ( mwCategoryEd.editItemGrant && ! mwCategoryEd.form.is(':animated') ) { 37445 37446 var item = {}; 37447 item.id = this.form.find('input[name=id]').val(); 37448 item.parent_id = this.form.find('input[name=parent_id]').val(); 37449 item.title = this.form.find('input[name=title]').val(); 37450 item.comment = this.form.find('textarea[name=comment]').val(); 37451 item.is_news = this.form.find('input[name=is_news]').is(':checked') ? 1 : 0; 37452 item.no_index = this.form.find('input[name=no_index]').is(':checked') ? 1 : 0; 37453 item.no_follow = this.form.find('input[name=no_follow]').is(':checked') ? 1 : 0; 37454 37455 //___('save item', item); 37456 if ( ! mwCategoryEd.validateItem(item) ) return false; 37457 37458 item.id = item.id.substring(2); // remove "id" symbols 37459 37460 if ( !isNaN(item.id-0) ) { // if is numeric - its existing category, else - new 37461 37462 item.id = 'id' + item.id; 37463 37464 //if ( item.title == mwData.Categories[item.id].title && item.comment == mwData.Categories[item.id].comment && item.is_news == mwData.Categories[item.id].is_news ) { 37465 37466 // if ( mwCategoryEd.updateCategories[item.id] ) delete mwCategoryEd.updateCategories[item.id]; // if category changed back on default - remove it from update list 37467 37468 //} else { 37469 37470 mwCategoryEd.updateCategories[item.id] = item; 37471 37472 //} 37473 37474 } else { 37475 37476 item.id = 'ne' + item.id; 37477 if ( mwCategoryEd.newCategories[item.id] ) // protection from click on droping new category 37478 mwCategoryEd.newCategories[item.id] = item; 37479 37480 } 37481 37482 jQuery(mwCategoryEd.LastItem).find('span').html(item.title); 37483 37484 } 37485 37486 return true; 37487 37488 }, //FUNC saveItem 37489 37490 validateItem : function(item) { 37491 37492 var is_valid = true; 37493 37494 if ( item.title.length == 0 ) { 37495 37496 is_valid = false;
37497 mwState(mwError('Title is required'), 'wManageCategories'); 37498 37499 } else { 37500 37501 var items = jQuery.extend( {}, mwData.Categories, mwCategoryEd.updateCategories ) 37502 37503 mwCategoryEd.deleteCategories.forEach( function(value) { delete items[value]; } ); 37504 37505 delete items[item.id]; 37506 37507 for ( var $i in items ) 37508 if ( items[$i].title == item.title ) { 37509 37510 is_valid = false; 37511 mwState(mwError('Title already exist'), 'wManageCategories'); 37512 37513 } 37514 } 37515 37516 if ( is_valid ) { 37517 37518 mwState(false, 'wManageCategories'); 37519 jQuery('#saveCategory_form .name-title').removeClass('error'); 37520 37521 } else { 37522 37523 jQuery('#saveCategory_form .name-title').addClass('error'); 37524 37525 } 37526 37527 return is_valid; 37528 37529 }, //FUNC validateItem 37530 37531 deleteItem : function( event, ui ) { 37532 37533 var el = jQuery(ui.draggable); 37534 37535 var del_item = function(item) { // take jQuery wrapped item 37536 37537 var id = item.attr('id'); 37538 37539 id = id.substring(2); // remove "id" symbols 37540 37541 if ( !isNaN(id-0) ) { // if ID numeric - its existing category, else - new 37542 37543 id = 'id' + id; 37544 delete mwCategoryEd.updateCategories[id]; // no need update category before delete it 37545 mwCategoryEd.deleteCategories.push( id ); 37546 37547 } else { // new category 37548 37549 id = 'ne' + id; 37550 delete mwCategoryEd.newCategories[id]; 37551 37552 } 37553 37554 }; 37555 37556 mwConfirmation( 37557 37558 function() { 37559 37560 if ( el.attr('id') == mwCategoryEd.ID ) { // if delete selected item disable validation and hide inputs 37561 37562 mwCategoryEd.ID = 0; 37563 mwCategoryEd.form.fadeOut('fast'); 37564 37565 } 37566 37567 del_item(el); 37568 37569 el.find('li[id]').each( function() { 37570 37571 del_item(jQuery(this)); // delete all childrens 37572 37573 } ); 37574 37575 mwWindow('systemConfirmation').hide(); 37576 el.remove(); 37577 37578 if( jQuery('.categories_list li').size() == 0) 37579 mwCategoryEd.listContainer.addClass('winBgHint'); 37580 37581 }, 37582 'Delete Category "' + el.find('span').html() + '" and all child categories?' 37583 37584 ); 37585 }, //FUNC deleteItem 37586 37587 addItem : function() { 37588 37589 mwCategoryEd.NewCounter += 1; 37590 37591 jQuery('.categories_list #no_items').slideUp(); 37592 37593 var item = jQuery.extend(true, {}, mwCategoryEd.Defaults) 37594 //jQuery.extend(item, mwCategoryEd.Defaults); 37595 item.id = 'new' + mwCategoryEd.NewCounter; 37596 37597 var el = mwCategoryEd.listContainer.find('.ui-draggable-new-category'); 37598 el.removeClass('ui-draggable-new-category') 37599 .addClass('draggable_item') 37600 .attr('id', item.id); 37601 37602 el = el.find('a') 37603 .click( function() { mwCategoryEd.editItem(item.id, el); } ) 37604 ; 37605 37606 el.find('span').html(item.title); 37607 37608 mwCategoryEd.newCategories[item.id] = item; 37609 37610 el.click(); 37611 37612 }, //FUNC addItem 37613 37614 buildCategoriesList : function () { 37615 37616 var html = '<div class="winSideTabs winContent thinpads categories_list">'; 37617 html += '<ul class="ui-sortable-categories-list">'; 37618 37619 for ( var $i in mwData.Categories ) { 37620 37621 var item = mwData.Categories[$i]; 37622 html += '<li id="' + item.id + '" class="newItem draggable_item" title="' + item.comment + '">'; 37623 html += '<a onclick="mwCategoryEd.editItem(\'' + item.id + '\', this);"><span class="Title">' + item.title + '</span></a>'; 37624 html += '</li>'; 37625 37626 } 37627 37628 html += '</ul>'; 37629 html += '</div>'; 37630 mwCategoryEd.listContainer.html(html); 37631 37632 }, //FUNC buildCategoriesList 37633 37634 buildCategoriesTree : function () { 37635 37636 var build_childrens = function (id) { 37637 37638 var html = ''; 37639 37640 for ( var $i in mwData.Categories ) 37641 if ( mwData.Categories[$i].parent_id == id ) { 37642 37643 var item = mwData.Categories[$i]; 37644 html += '<li id="' + item.id + '" class="newItem draggable_item dragItem">'; 37645 html += '<a onclick="mwCategoryEd.editItem(\'' + item.id + '\', this);"><span class="Title">' + item.title + '</span></a>'; 37646 html += build_childrens(item.id); 37647 html += '</li>'; 37648 37649 } 37650 37651 if ( html != '' ) html = '<ul>' + html + '</ul>'; 37652 37653 return html; 37654 37655 } 37656 37657 var html = '<div class="categories_list">'; 37658 37659 html_items = build_childrens('id0'); 37660 //html += '<ul>'; 37661 //html += '<div id="no_items">No Categories. Drop New Category here.</div>'; 37662 //___(html_items); 37663 if ( html_items == '' ) 37664 mwCategoryEd.listContainer.addClass('winBgHint'); 37665 else 37666 mwCategoryEd.listContainer.removeClass('winBgHint'); 37667 37668 if ( html_items == '' ) 37669 html += '<ul></ul>'; 37670 else 37671 html += html_items; 37672 37673 //html += '</ul>'; 37674 html += '</div>'; 37675 mwCategoryEd.listContainer.html(html); 37676 37677 //jQuery('.categories_list ul:first').append('<div id="no_items">No Categories. Drop New Category here.</div>'); 37678 37679 }, //FUNC buildCategoriesTree 37680 37681 doCategoriesMainFilter : function () { 37682 37683 var html = '<option value="0">
37683Filter</option>'; 37684 html += '<option value="-1">no category</option>'; 37685 for ( var $i in mwData.Categories ) { 37686 37687 html +='<option '; 37688 html += 'value="' + mwData.Categories[$i].id + '">' + mwData.Categories[$i].title + '</option>' 37689 37690 37691 37692 } 37693 37694 var sel = jQuery('#categories_filter'); 37695 37696 sel.html(html); 37697 37698 //get select parent 37699 var parent = sel.parent() 37700 37701 //check is parent already generated select (skip this on page init) 37702 if ( parent.hasClass('mwDskSelect') ) { 37703 37704 //move select to main panel 37705 parent.before(sel); 37706 37707 //delete old one 37708 parent.remove(); 37709 37710 //regenerate it 37711 mwDskControls.Types['SELECT'](sel); 37712 37713 //show generated select 37714 jQuery('.mwDskSelect .New').show(); 37715 37716 } 37717 37718 sel.change( 37719 function(event) { 37720 37721 var categoryID = jQuery(this).val(); 37722 37723 if ( categoryID.length > 2 ) 37724 categoryID = categoryID.substring(2); // remove "id" symbols 37725 37726 if ( typeof mwData.AjaxFilter !== "undefined" ) { 37727 37728 mwCategoryEd.doAjaxFilter(categoryID); 37729 37730 } else { 37731 37732 if ( categoryID != 0 ) { 37733 37734 jQuery('.tr_post').hide(); 37735 jQuery( '.category' + categoryID ).show(); 37736 37737 if ( categoryID == -1 ) jQuery( '[class="tr_post "]' ).show(); 37738 37739 } else { 37740 37741 jQuery('.tr_post').show(); 37742 37743 } 37744 } 37745 } 37746 ); 37747 37748 }, //FUNC doCategoriesMainFilter 37749 37750 doAjaxFilter : function (category_id) { 37751 37752 //___('doAjaxFilter', category_id); 37753 var temp_posts = mwData.Posts; 37754 delete mwData.Posts; 37755 37756 mwAjax('/site/ajax/blogs/index', { 'filter_by_category_id' : category_id }) 37757 .go() 37758 .success( function($data) { 37759 37760 mwPostEd.manualOrder_sort(); 37761 delete temp_posts; 37762 37763 } ) 37764 .error( function() { 37765 37766 mwData.Posts = temp_posts; 37767 37768 } ) 37769 ; // mwAjax 37770 37771 }, //FUNC doAjaxFilter 37772 37773 getCurrentFilterCategoryID : function () { 37774 37775 if ( typeof(mwLiveEd) != 'undefined' ) return 0; 37776 37777 var categoryID = jQuery('#categories_filter').val(); 37778 37779 if ( categoryID && categoryID.length > 2 ) 37780 categoryID = categoryID.substring(2); // remove "id" symbols 37781 37782 return categoryID; 37783 37784 }, //FUNC getCurrentFilterCategoryID 37785 37786 doDraggableItems : function () { 37787 37788 jQuery('.categories_list>ul').nestedSortable( { 37789 37790 listType : 'ul', 37791 items : 'li', 37792 handle : 'a', 37793 37794 toleranceElement : '> a', 37795 tolerance : 'pointer', 37796 tabSize : 20, 37797 37798 maxLevels : 0, 37799 disableNesting : 'no-childs', 37800 37801 opacity : 0.5, 37802 37803 forceHelperSize : true, 37804 forcePlaceholderSize : true, 37805 placeholder : 'Placeholder', 37806 errorClass : 'PlaceholderErr', 37807 37808 receive : function( event, ui ) { mwCategoryEd.addItem(); }, 37809 update : function(event, ui) { mwCategoryEd.isSorted = true; }, 37810 37811 } ); 37812 37813 37814 jQuery('.ui-draggable-new-category').draggable( { 37815 37816 connectToSortable : '.categories_list>ul', 37817 helper : 'clone', 37818 37819 } ) 37820 .disableSelection(); 37821 37822 jQuery('.cat_recycle_droppable' ).droppable( { 37823 37824 activeClass : "dragHover", 37825 hoverClass : "drag", 37826 tolerance : "pointer", 37827 drop : mwCategoryEd.deleteItem, 37828 accept : ".draggable_item", 37829 37830 } ); 37831 37832 }, //FUNC doDraggableItems 37833 37834 // input - jQuery wrapped input for event 37835 // elements - jQuery wrapped list of elements (for show/hide) 37836 // searchSelector - jQuery selector for serch into elements filtered text 37837 37838 doFilterCategories : function ( input, elements, searchSelector ) { 37839 37840 input.keyup( function(event) { 37841 37842 var input = jQuery(this); 37843 37844 elements.hide().each( function() { 37845 37846 $this = jQuery(this); 37847 37848 var reg = new RegExp(input.val(), "gi"); 37849 37850 if ( reg.test($this.find(searchSelector).html()) ) 37851 $this.show(); 37852 37853 } ) 37854 37855 } ); 37856 37857 }, //FUNC doFilterCategories 37858 37859 doFilterCategoriesTree : function ( input, elements, searchSelector ) { 37860 37861 input.keyup( function(event) { 37862 37863 var input = jQuery(this); 37864 37865 elements.hide().each( function() { 37866 37867 $this = jQuery(this); 37868 37869 var reg = new RegExp(input.val(), "gi"); 37870 37871 if ( reg.test($this.find(searchSelector).html()) ) { 37872 37873 $this.show().parents().filter( function(index) { 37874 37875 var res = false;
37876 if( jQuery.inArray(this, elements) >= 0 ) res = true; // if in elements list - no need remove 37877 37878 return res; 37879 37880 } ).show(); 37881 } 37882 } ) 37883 } ); 37884 37885 }, //FUNC doFilterCategoriesTree 37886 37887}; //OBJECT mwCategoryEd 37888 37889var mwBlogsOptionsEd = { 37890 37891 ID : 1, // blog id (future options - possibility save more then 1 blog options) 37892 init : function() { 37893 37894 }, //FUNC init 37895 37896 edit : function (id) { 37897 37898 this.ID = id; 37899 var page = mwData.BlogsOptions[id]; 37900 if ( !page ) return false; 37901 37902 page = mwBlogsOptionsEd.add_default_soc_page(page); 37903 37904 // Resetting form 37905 jQuery('#mwBlogsOptions_form').fromArray(page); 37906 37907 if ( !this.soc_inited ) { 37908 37909 this.soc_inited = true; 37910 mwSocials().initConnectButtons(jQuery('#mwBlogsOptions_form tr td div[rel]')); 37911 37912 } 37913 37914 mwWindow('wBlogsOptions').Title('Blog Options <span>' + '' + '</span>').show( 37915 37916 function() {} 37917 37918 ); // mwWindow 37919 37920 //mwWindow().align() 37921 37922 return false; 37923 37924 }, //FUNC edit 37925 37926 save : function () { 37927 37928 mwAjax('/site/ajax/blogs/saveBlogsOptionsDB', '#mwBlogsOptions_form', 'wBlogsOptions') 37929 .index() 37930 .success( function($data) { 37931 37932 mwPostEd.manualOrder_sort(); 37933 37934 } ) 37935 ; // mwAjax 37936 37937 }, //FUNC save 37938 37939 add_default_soc_page : function(page) { 37940 37941 for (key in mwData.BlogsOptions[1]['publish_socials']) 37942 page['publish_' + key] = mwData.BlogsOptions[1]['publish_socials'][key]; 37943 37944 return page; 37945 37946 }, //FUNC add_default_soc_page 37947 37948} // CLASS mwBlogsOptionsEd 37949 37950var mwBlogsAjaxUpload = { 37951 37952 uploading_doing : false, 37953 37954 slideDownSpeed : 500, 37955 37956 init : function(posts_data, type) { 37957 37958 // __(type); 37959 // __(posts_data); 37960 37961 this.posts_data = posts_data; 37962 37963 this.uploading_doing = false; 37964 this.load_pos = jQuery("#blogs_posts_list_ajax_position_" + this.posts_data.ID); 37965 this.loader = jQuery("#blogs_list_loader_" + this.posts_data.ID); 37966 37967 if ( type == 1 ) this.doScrollAjax(); 37968 if ( type == 2 ) this.doClickAjax(); 37969 37970 }, 37971 37972 doLoad : function() { 37973 // ___('posts loading'); 37974 // ___(this); 37975 37976 if ( ! this.uploading_doing && this.posts_data.posts_limit > this.posts_data.posts_counter ) { 37977 37978 this.uploading_doing = true; 37979 //___('indexAjax', this.posts_data); 37980 mwAjax("/ajax/blogs/indexAjax", this.posts_data) 37981 .start( function () { 37982 mwBlogsAjaxUpload.loader.slideDown(); 37983 }) //FUNC mwAjax.success.callback 37984 .stop( function () { 37985 // mwBlogsAjaxUpload.uploading_doing = false; 37986 setTimeout(function() { mwBlogsAjaxUpload.loader.slideUp(); }, 2000); 37987 }) //FUNC mwAjax.success.callback 37988 .success( function($data) { 37989 37990 //__($data); 37991 if ( typeof $data.content !== "undefined" ) { 37992 37993 if ( $data.content.length > 0 ) { 37994 37995 //setTimeout(function() { mwBlogsAjaxUpload.loader.slideUp(); }, 3000); 37996 37997 jQuery("<div>" + $data.content + "</div>") 37998 .hide().insertBefore(mwBlogsAjaxUpload.load_pos) 37999 .delay(2000) 38000 .slideDown(mwBlogsAjaxUpload.posts_data.posts_per_once * mwBlogsAjaxUpload.slideDownSpeed, function() { 38001 38002 mwBlogsAjaxUpload.uploading_doing = false; 38003 jQuery(window).scroll(); 38004 38005 }); 38006 38007 mwBlogsAjaxUpload.posts_data.posts_counter = mwBlogsAjaxUpload.posts_data.posts_counter + mwBlogsAjaxUpload.posts_data.posts_per_once; 38008 38009 } 38010 } 38011 } 38012 ) 38013 .go(); 38014 38015 } else { 38016 38017 mwBlogsAjaxUpload.uploading_doing = true; // stop uploading if there no more to upload 38018 38019 } 38020 }, 38021 38022 doScrollAjax : function() { 38023 38024 jQuery(window).scroll( 38025 function(event) { 38026 38027 var block = jQuery(".blogs_posts_list_ajax_position").parent(); 38028 //___(1, block.offset().top + block.height(), jQuery(window).scrollTop() + jQuery(window).height()); 38029 //___(2, jQuery(window).scrollTop() + jQuery(window).height() - block.offset().top - block.height(), jQuery(window).height()); 38030 //___('doScrollAjax - block', block); 38031 //if ( jQuery(document).height() - jQuery(window).height() <= jQuery(window).scrollTop() + 250 ) { 38032 if ( block.offset().top + block.height() < jQuery(window).scrollTop() + jQuery(window).height() 38033 && jQuery(window).scrollTop() + jQuery(window).height() - block.offset().top - block.height() < jQuery(window).height() ) { 38034 38035 mwBlogsAjaxUpload.doLoad(); 38036 38037 } 38038 38039 } 38040 ); 38041 }, 38042 38043 doClickAjax : function() { 38044 38045 this.load_pos.after('<div class="blogs-show-more" onclick="mwBlogsAjaxUpload.doLoad();">Show More</div>'); 38046 38047 }, 38048 38049} //OBJECT mwBlogsAjaxUpload 38050 38051mwTextLengthCounter = function(input, display){ 38052 38053 //counter object 38054 var counter = { 38055 38056 min : 10, //allowed text length minimum 38057 max : 60, //allowed text length maximum 38058 input : {}, //jQuery object of input to track text length 38059 display : {}, //jQuery object of some element to display text length 38060 38061 init : function(input, display) { 38062 38063 var $this = this; 38064 38065 //expecting selector or jquery element 38066 $this.input = jQuery(input); 38067 38068 //expecting selector or jquery element 38069 $this.display = jQuery(display); 38070
38071 $this.input.keyup(function(){ 38072 38073 var l = $this.input.val().length; 38074 var html = l; 38075 38076 //length less minimum 38077 if ( l < $this.min ) { 38078 38079 $this.display.addClass('counter-red'); 38080 html += ' (+' + ($this.min - l) + ')'; 38081 38082 }//length more maximum 38083 else if ( l > $this.max ) { 38084 38085 $this.display.addClass('counter-red'); 38086 html += ' (-' + (l - $this.max) + ')'; 38087 38088 }//length match 38089 else { 38090 38091 $this.display.removeClass('counter-red'); 38092 38093 }//length match range 38094 38095 $this.display.html(html); 38096 38097 }); 38098 38099 }, //FUNC init 38100 38101 reset : function() { 38102 38103 var $this = this; 38104 38105 $this.input.keyup(); 38106 38107 }, //FUNC reset 38108 38109 }//counter object 38110 38111 counter.init(input, display); 38112 38113 //return initialized object 38114 return counter; 38115 38116}//mwTextLengthCounter 38117 38118jQuery( function () { 38119 38120 //special function to overwrite in templates 38121 if ( typeof onBlogsPostAliasUpdate == 'undefined' ) onBlogsPostAliasUpdate = function(alias) {}; 38122 38123 if ( typeof mwData != "undefined" ) { 38124 38125 //mwPostEd.init(); 38126 mwCategoryEd.init(); 38127 mwPostEd.manualOrderInit(); 38128 38129 //jQuery('#mwPostEd_form #published_date').datepicker(); 38130 38131 } 38132 //load without liveEd 38133 else { 38134 38135 //prepare socials variable - its only stored once 38136 var socials = ''; 38137 var soc_template = ''; 38138 38139 //load on scroll add 38140 if ( jQuery('.update-alias-on-scroll-bot').length > 0 ) { 38141 38142 var update_alias = function(alias, title) { 38143 //___('alias', alias); 38144 //___('title', title); 38145 var path = location.pathname.split('/'); 38146 //___(path); 38147 var url = location.origin; 38148 var current_alias = path[path.length - 1]; 38149 //___('current_alias', current_alias); 38150 //update only if current alias is different 38151 if ( current_alias != alias ) { 38152 38153 for ( var i in path ) { 38154 38155 if ( path[i] && i < path.length - 1 ) url += '/' + path[i]; 38156 38157 } 38158 38159 url += '/' + alias; 38160 38161 //___(url); 38162 //___('update alias', url, alias); 38163 window.history.pushState( title, title, url ); 38164 38165 //call event-function for templates usage 38166 onBlogsPostAliasUpdate(alias); 38167 38168 } 38169 }; 38170 38171 //special flag to prevent loads while load is on run 38172 var load_in_process = false; 38173 38174 //loop reload waupoints on timer 38175 var loop_waypoints = function() { 38176 38177 Waypoint.refreshAll(); 38178 setTimeout(loop_waypoints, 1000); 38179 38180 } 38181 loop_waypoints(); 38182 38183 var addLoadNewPostOnScroll = function(load_el_old) { 38184 38185 //do nothing if load already on process 38186 if ( load_in_process ) return; 38187 ___('run load'); 38188 38189 //set the load process flag 38190 load_in_process = true; 38191 38192 var load_id = load_el_old.attr('post-id'); 38193 var template = load_el_old.attr('post-template'); 38194 var categories = JSON.parse(load_el_old.attr('post-categories')); 38195 var order = load_el_old.attr('post-order'); 38196 38197 if ( !socials ) socials = load_el_old.attr('post-socials-list'); 38198 if ( !soc_template ) soc_template = load_el_old.attr('post-socials-template'); 38199 38200 mwAjax( 38201 '/ajax/blogs/renderPost/', 38202 { 'postID': load_id, 38203 'template': template, 38204 'PostsCategoriesList': categories, 38205 'PostsOrder': order, 38206 'SocialsList': socials, 38207 'SocialsTemplate' : soc_template 38208 }) 38209 .go() 38210 .success( function(response) { 38211 38212 ___('next post load response', response); 38213 38214 var PostData = response.content.PostData; 38215 38216 //add new post content 38217 load_el_old.after(response.content.html); 38218 38219 //no need to load again 38220 load_el_old.attr('post-do-load', 'no'); 38221 38222 //add waypoints 38223 addWaypoints(); 38224 38225 //set the load process flag 38226 load_in_process = false; 38227 38228 }); 38229 38230 }; //FUNC addLoadNewPostOnScroll 38231 38232 var addWaypoints = function() { 38233 38234 jQuery('.update-alias-on-scroll-bot') 38235 .waypoint({ 38236 handler: function(direction) { 38237 38238 var el = jQuery(this.element); 38239 //___(el); 38240 ___('scroll: ' + this.triggerPoint + ', direction: ' + direction); 38241 38242 if (el.attr('post-do-load') == 'yes') { 38243 ___('load', el.attr('post-alias'), el); 38244 addLoadNewPostOnScroll(el); 38245 38246 } 38247 38248 }, 38249 offset: '100%' 38250 }); 38251 38252 jQuery('.update-alias-on-scroll-bot') 38253 .removeClass('update-alias-on-scroll-bot') 38254 .addClass('update-alias-on-scroll-bot-updated') 38255 .waypoint({ 38256 handler: function(direction) { 38257 38258 var el = jQuery(this.element); 38259
38260 //update alias for current post 38261 if ( direction == 'down' ) { 38262 ___('down', el.attr('post-alias'), el); 38263 update_alias(el.attr('post-alias'), el.attr('post-title')); 38264 38265 } 38266 38267 }, 38268 offset: '100%' 38269 }); 38270 38271 jQuery('.update-alias-on-scroll-up') 38272 .removeClass('update-alias-on-scroll-up') 38273 .addClass('update-alias-on-scroll-up-updated') 38274 .waypoint({ 38275 handler: function(direction) { 38276 38277 var el = jQuery(this.element); 38278 38279 //update alias for current post 38280 if ( direction == 'up' ) { 38281 ___('up', el.attr('post-alias'), el); 38282 update_alias(el.attr('post-alias'), el.attr('post-title')); 38283 38284 } 38285 38286 }, 38287 offset: '100%' 38288 }); 38289 38290 }; 38291 38292 addWaypoints(); 38293 38294 } 38295 } 38296 38297}); 38298jQuery (function () { 38299 38300 // setTimeout(function(){ 38301 // __(mwLiveEd.Widgets); 38302 // },1000); 38303 38304 38305/* 38306 if (typeof jQuery('select[name=page_id]') !== 'undefined') { 38307 38308 var pageSelectorVal = JQuery('select[name=page_id]'); 38309 pageSelectorVal.change(function(){ 38310 38311 if(pageSelectorVal == '0') { 38312 console.log('555'); 38313 } 38314 38315 });*/ 38316 38317 38318 38319});
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.