1/** 2 * jQuery Validation Plugin @VERSION 3 * 4 * http://bassistance.de/jquery-plugins/jquery-plugin-validation/ 5 * http://docs.jquery.com/Plugins/Validation 6 * 7 * Copyright (c) 2006 - 2011 Jörn Zaefferer 8 * 9 * Dual licensed under the MIT and GPL licenses: 10 * http://www.opensource.org/licenses/mit-license.php 11 * http://www.gnu.org/licenses/gpl.html 12 */ 13 14 15(function($) { 16 17$.extend($.fn, { 18 // http://docs.jquery.com/Plugins/Validation/validate 19 validate: function( options ) { 20 21 // if nothing is selected, return nothing; can't chain anyway 22 if (!this.length) { 23 options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" ); 24 return; 25 } 26 27 // check if a validator for this form was already created 28 var validator = $.data(this[0], 'validator'); 29 if ( validator ) { 30 return validator; 31 } 32 33 validator = new $.validator( options, this[0] ); 34 $.data(this[0], 'validator', validator); 35 36 if ( validator.settings.onsubmit ) { 37 38 // allow suppresing validation by adding a cancel class to the submit button 39 this.find("input, button").filter(".cancel").click(function() { 40 validator.cancelSubmit = true; 41 }); 42 43 // when a submitHandler is used, capture the submitting button 44 if (validator.settings.submitHandler) { 45 this.find("input, button").filter(":submit").click(function() { 46 validator.submitButton = this; 47 }); 48 } 49 50 // validate the form on submit 51 this.submit( function( event ) { 52 if ( validator.settings.debug ) 53 // prevent form submit to be able to see console output 54 event.preventDefault(); 55 56 function handle() { 57 if ( validator.settings.submitHandler ) { 58 if (validator.submitButton) { 59 // insert a hidden input as a replacement for the missing submit button 60 var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm); 61 } 62 validator.settings.submitHandler.call( validator, validator.currentForm ); 63 if (validator.submitButton) { 64 // and clean up afterwards; thanks to no-block-scope, hidden can be referenced 65 hidden.remove(); 66 } 67 return false; 68 } 69 return true; 70 } 71 72 // prevent submit for invalid forms or custom submit handlers 73 if ( validator.cancelSubmit ) { 74 validator.cancelSubmit = false; 75 return handle(); 76 } 77 if ( validator.form() ) { 78 if ( validator.pendingRequest ) { 79 validator.formSubmitted = true; 80 return false; 81 } 82 return handle(); 83 } else { 84 validator.focusInvalid(); 85 return false; 86 } 87 }); 88 } 89 90 return validator; 91 }, 92 // http://docs.jquery.com/Plugins/Validation/valid 93 valid: function() { 94 if ( $(this[0]).is('form')) { 95 return this.validate().form(); 96 } else { 97 var valid = true; 98 var validator = $(this[0].form).validate(); 99 this.each(function() { 100 valid &= validator.element(this); 101 }); 102 return valid; 103 } 104 }, 105 // attributes: space seperated list of attributes to retrieve and remove 106 removeAttrs: function(attributes) { 107 var result = {}, 108 $element = this; 109 $.each(attributes.split(/\s/), function(index, value) { 110 result[value] = $element.attr(value); 111 $element.removeAttr(value); 112 }); 113 return result; 114 }, 115 // http://docs.jquery.com/Plugins/Validation/rules 116 rules: function(command, argument) { 117 var element = this[0]; 118 119 if (command) { 120 var settings = $.data(element.form, 'validator').settings; 121 var staticRules = settings.rules; 122 var existingRules = $.validator.staticRules(element); 123 switch(command) { 124 case "add": 125 $.extend(existingRules, $.validator.normalizeRule(argument)); 126 staticRules[element.name] = existingRules; 127 if (argument.messages) 128 settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages ); 129 break; 130 case "remove": 131 if (!argument) { 132 delete staticRules[element.name]; 133 return existingRules; 134 } 135 var filtered = {}; 136 $.each(argument.split(/\s/), function(index, method) { 137 filtered[method] = existingRules[method]; 138 delete existingRules[method]; 139 }); 140 return filtered; 141 } 142 } 143 144 var data = $.validator.normalizeRules( 145 $.extend( 146 {}, 147 $.validator.metadataRules(element), 148 $.validator.classRules(element), 149 $.validator.attributeRules(element), 150 $.validator.staticRules(element) 151 ), element); 152 153 // make sure required is at front 154 if (data.required) { 155 var param = data.required; 156 delete data.required; 157 data = $.extend({required: param}, data); 158 } 159 160 return data; 161 } 162}); 163 164// Custom selectors 165$.extend($.expr[":"], {
166 // http://docs.jquery.com/Plugins/Validation/blank 167 blank: function(a) {return !$.trim("" + a.value);}, 168 // http://docs.jquery.com/Plugins/Validation/filled 169 filled: function(a) {return !!$.trim("" + a.value);}, 170 // http://docs.jquery.com/Plugins/Validation/unchecked 171 unchecked: function(a) {return !a.checked;} 172}); 173 174// constructor for validator 175$.validator = function( options, form ) { 176 this.settings = $.extend( true, {}, $.validator.defaults, options ); 177 this.currentForm = form; 178 this.init(); 179}; 180 181$.validator.format = function(source, params) { 182 if ( arguments.length == 1 ) 183 return function() { 184 var args = $.makeArray(arguments); 185 args.unshift(source); 186 return $.validator.format.apply( this, args ); 187 }; 188 if ( arguments.length > 2 && params.constructor != Array ) { 189 params = $.makeArray(arguments).slice(1); 190 } 191 if ( params.constructor != Array ) { 192 params = [ params ]; 193 } 194 $.each(params, function(i, n) { 195 source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n); 196 }); 197 return source; 198}; 199 200$.extend($.validator, { 201 202 defaults: { 203 messages: {}, 204 groups: {}, 205 rules: {}, 206 errorClass: "error", 207 validClass: "valid", 208 errorElement: "label", 209 focusInvalid: true, 210 errorContainer: $( [] ), 211 errorLabelContainer: $( [] ), 212 onsubmit: true, 213 ignore: [], 214 ignoreTitle: false, 215 onfocusin: function(element) { 216 this.lastActive = element; 217 218 // hide error label and remove error class on focus if enabled 219 if ( this.settings.focusCleanup && !this.blockFocusCleanup ) { 220 this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass ); 221 this.addWrapper(this.errorsFor(element)).hide(); 222 } 223 }, 224 onfocusout: function(element) { 225 if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) { 226 this.element(element); 227 } 228 }, 229 onkeyup: function(element) { 230 if ( element.name in this.submitted || element == this.lastElement ) { 231 this.element(element); 232 } 233 }, 234 onclick: function(element) { 235 // click on selects, radiobuttons and checkboxes 236 if ( element.name in this.submitted ) 237 this.element(element); 238 // or option elements, check parent select in that case 239 else if (element.parentNode.name in this.submitted) 240 this.element(element.parentNode); 241 }, 242 highlight: function(element, errorClass, validClass) { 243 if (element.type === 'radio') { 244 this.findByName(element.name).addClass(errorClass).removeClass(validClass); 245 } else { 246 $(element).addClass(errorClass).removeClass(validClass); 247 } 248 }, 249 unhighlight: function(element, errorClass, validClass) { 250 if (element.type === 'radio') { 251 this.findByName(element.name).removeClass(errorClass).addClass(validClass); 252 } else { 253 $(element).removeClass(errorClass).addClass(validClass); 254 } 255 } 256 }, 257 258 // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults 259 setDefaults: function(settings) { 260 $.extend( $.validator.defaults, settings ); 261 }, 262 263 messages: { 264 required: "This field is required.", 265 remote: "Please fix this field.", 266 email: "Please enter a valid email address.", 267 url: "Please enter a valid URL.", 268 date: "Please enter a valid date.", 269 dateISO: "Please enter a valid date (ISO).", 270 number: "Please enter a valid number.", 271 digits: "Please enter only digits.", 272 creditcard: "Please enter a valid credit card number.", 273 equalTo: "Please enter the same value again.", 274 accept: "Please enter a value with a valid extension.", 275 maxlength: $.validator.format("Please enter no more than {0} characters."), 276 minlength: $.validator.format("Please enter at least {0} characters."), 277 rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."), 278 range: $.validator.format("Please enter a value between {0} and {1}."), 279 max: $.validator.format("Please enter a value less than or equal to {0}."), 280 min: $.validator.format("Please enter a value greater than or equal to {0}.") 281 }, 282 283 autoCreateRanges: false, 284 285 prototype: { 286 287 init: function() { 288 this.labelContainer = $(this.settings.errorLabelContainer); 289 this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm); 290 this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer ); 291 this.submitted = {}; 292 this.valueCache = {}; 293 this.pendingRequest = 0; 294 this.pending = {}; 295 this.invalid = {}; 296 this.reset(); 297 298 var groups = (this.groups = {}); 299 $.each(this.settings.groups, function(key, value) { 300 $.each(value.split(/\s/), function(index, name) { 301 groups[name] = key; 302 }); 303 }); 304 var rules = this.settings.rules; 305 $.each(rules, function(key, value) { 306 rules[key] = $.validator.normalizeRule(value); 307 }); 308 309 function delegate(event) {
310 var validator = $.data(this[0].form, "validator"), 311 eventType = "on" + event.type.replace(/^validate/, ""); 312 validator.settings[eventType] && validator.settings[eventType].call(validator, this[0] ); 313 } 314 $(this.currentForm) 315 .validateDelegate(":text, :password, :file, select, textarea", "focusin focusout keyup", delegate) 316 .validateDelegate(":radio, :checkbox, select, option", "click", delegate); 317 318 if (this.settings.invalidHandler) 319 $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler); 320 }, 321 322 // http://docs.jquery.com/Plugins/Validation/Validator/form 323 form: function() { 324 this.checkForm(); 325 $.extend(this.submitted, this.errorMap); 326 this.invalid = $.extend({}, this.errorMap); 327 if (!this.valid()) 328 $(this.currentForm).triggerHandler("invalid-form", [this]); 329 this.showErrors(); 330 return this.valid(); 331 }, 332 333 checkForm: function() { 334 this.prepareForm(); 335 for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) { 336 this.check( elements[i] ); 337 } 338 return this.valid(); 339 }, 340 341 // http://docs.jquery.com/Plugins/Validation/Validator/element 342 element: function( element ) { 343 element = this.clean( element ); 344 this.lastElement = element; 345 this.prepareElement( element ); 346 this.currentElements = $(element); 347 var result = this.check( element ); 348 if ( result ) { 349 delete this.invalid[element.name]; 350 } else { 351 this.invalid[element.name] = true; 352 } 353 if ( !this.numberOfInvalids() ) { 354 // Hide error containers on last error 355 this.toHide = this.toHide.add( this.containers ); 356 } 357 this.showErrors(); 358 return result; 359 }, 360 361 // http://docs.jquery.com/Plugins/Validation/Validator/showErrors 362 showErrors: function(errors) { 363 if(errors) { 364 // add items to error list and map 365 $.extend( this.errorMap, errors ); 366 this.errorList = []; 367 for ( var name in errors ) { 368 this.errorList.push({ 369 message: errors[name], 370 element: this.findByName(name)[0] 371 }); 372 } 373 // remove items from success list 374 this.successList = $.grep( this.successList, function(element) { 375 return !(element.name in errors); 376 }); 377 } 378 this.settings.showErrors 379 ? this.settings.showErrors.call( this, this.errorMap, this.errorList ) 380 : this.defaultShowErrors(); 381 }, 382 383 // http://docs.jquery.com/Plugins/Validation/Validator/resetForm 384 resetForm: function() { 385 if ( $.fn.resetForm ) 386 $( this.currentForm ).resetForm(); 387 this.submitted = {}; 388 this.prepareForm(); 389 this.hideErrors(); 390 this.elements().removeClass( this.settings.errorClass ); 391 }, 392 393 numberOfInvalids: function() { 394 return this.objectLength(this.invalid); 395 }, 396 397 objectLength: function( obj ) { 398 var count = 0; 399 for ( var i in obj ) 400 count++; 401 return count; 402 }, 403 404 hideErrors: function() { 405 this.addWrapper( this.toHide ).hide(); 406 }, 407 408 valid: function() { 409 return this.size() == 0; 410 }, 411 412 size: function() { 413 return this.errorList.length; 414 }, 415 416 focusInvalid: function() { 417 if( this.settings.focusInvalid ) { 418 try { 419 $(this.findLastActive() || this.errorList.length && this.errorList[0].element || []) 420 .filter(":visible") 421 .focus() 422 // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find 423 .trigger("focusin"); 424 } catch(e) { 425 // ignore IE throwing errors when focusing hidden elements 426 } 427 } 428 }, 429 430 findLastActive: function() { 431 var lastActive = this.lastActive; 432 return lastActive && $.grep(this.errorList, function(n) { 433 return n.element.name == lastActive.name; 434 }).length == 1 && lastActive; 435 }, 436 437 elements: function() { 438 var validator = this, 439 rulesCache = {}; 440 441 // select all valid inputs inside the form (no submit or reset buttons) 442 return $(this.currentForm) 443 .find("input, select, textarea") 444 .not(":submit, :reset, :image, [disabled]") 445 .not( this.settings.ignore ) 446 .filter(function() { 447 !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this); 448 449 // select only the first element for each name, and only those with rules specified 450 if ( this.name in rulesCache || !validator.objectLength($(this).rules()) ) 451 return false;
452 453 rulesCache[this.name] = true; 454 return true; 455 }); 456 }, 457 458 clean: function( selector ) { 459 return $( selector )[0]; 460 }, 461 462 errors: function() { 463 return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext ); 464 }, 465 466 reset: function() { 467 this.successList = []; 468 this.errorList = []; 469 this.errorMap = {}; 470 this.toShow = $([]); 471 this.toHide = $([]); 472 this.currentElements = $([]); 473 }, 474 475 prepareForm: function() { 476 this.reset(); 477 this.toHide = this.errors().add( this.containers ); 478 }, 479 480 prepareElement: function( element ) { 481 this.reset(); 482 this.toHide = this.errorsFor(element); 483 }, 484 485 check: function( element ) { 486 element = this.clean( element ); 487 488 // if radio/checkbox, validate first element in group instead 489 if (this.checkable(element)) { 490 element = this.findByName( element.name ).not(this.settings.ignore)[0]; 491 } 492 493 var rules = $(element).rules(); 494 var dependencyMismatch = false; 495 for (var method in rules ) { 496 var rule = { method: method, parameters: rules[method] }; 497 try { 498 var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters ); 499 500 // if a method indicates that the field is optional and therefore valid, 501 // don't mark it as valid when there are no other rules 502 if ( result == "dependency-mismatch" ) { 503 dependencyMismatch = true; 504 continue; 505 } 506 dependencyMismatch = false; 507 508 if ( result == "pending" ) { 509 this.toHide = this.toHide.not( this.errorsFor(element) ); 510 return; 511 } 512 513 if( !result ) { 514 this.formatAndAdd( element, rule ); 515 return false; 516 } 517 } catch(e) { 518 this.settings.debug && window.console && console.log("exception occurred when checking element " + element.id 519 + ", check the '" + rule.method + "' method", e); 520 throw e; 521 } 522 } 523 if (dependencyMismatch) 524 return; 525 if ( this.objectLength(rules) ) 526 this.successList.push(element); 527 return true; 528 }, 529 530 // return the custom message for the given element and validation method 531 // specified in the element's "messages" metadata 532 customMetaMessage: function(element, method) { 533 if (!$.metadata) 534 return; 535 536 var meta = this.settings.meta 537 ? $(element).metadata()[this.settings.meta] 538 : $(element).metadata(); 539 540 return meta && meta.messages && meta.messages[method]; 541 }, 542 543 // return the custom message for the given element name and validation method 544 customMessage: function( name, method ) { 545 var m = this.settings.messages[name]; 546 return m && (m.constructor == String 547 ? m 548 : m[method]); 549 }, 550 551 // return the first defined argument, allowing empty strings 552 findDefined: function() { 553 for(var i = 0; i < arguments.length; i++) { 554 if (arguments[i] !== undefined) 555 return arguments[i]; 556 } 557 return undefined; 558 }, 559 560 defaultMessage: function( element, method) { 561 return this.findDefined( 562 this.customMessage( element.name, method ), 563 this.customMetaMessage( element, method ), 564 // title is never undefined, so handle empty string as undefined 565 !this.settings.ignoreTitle && element.title || undefined, 566 $.validator.messages[method], 567 "<strong>Warning: No message defined for " + element.name + "</strong>" 568 ); 569 }, 570 571 formatAndAdd: function( element, rule ) { 572 var message = this.defaultMessage( element, rule.method ), 573 theregex = /\$?\{(\d+)\}/g; 574 if ( typeof message == "function" ) { 575 message = message.call(this, rule.parameters, element); 576 } else if (theregex.test(message)) { 577 message = $.format(message.replace(theregex, '{$1}'), rule.parameters); 578 } 579 this.errorList.push({ 580 message: message, 581 element: element 582 }); 583 584 this.errorMap[element.name] = message; 585 this.submitted[element.name] = message; 586 }, 587 588 addWrapper: function(toToggle) { 589 if ( this.settings.wrapper ) 590 toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) ); 591 return toToggle; 592 }, 593 594 defaultShowErrors: function() { 595 for ( var i = 0; this.errorList[i]; i++ ) { 596 var error = this.errorList[i]; 597 this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.val
597idClass ); 598 this.showLabel( error.element, error.message ); 599 } 600 if( this.errorList.length ) { 601 this.toShow = this.toShow.add( this.containers ); 602 } 603 if (this.settings.success) { 604 for ( var i = 0; this.successList[i]; i++ ) { 605 this.showLabel( this.successList[i] ); 606 } 607 } 608 if (this.settings.unhighlight) { 609 for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) { 610 this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass ); 611 } 612 } 613 this.toHide = this.toHide.not( this.toShow ); 614 this.hideErrors(); 615 this.addWrapper( this.toShow ).show(); 616 }, 617 618 validElements: function() { 619 return this.currentElements.not(this.invalidElements()); 620 }, 621 622 invalidElements: function() { 623 return $(this.errorList).map(function() { 624 return this.element; 625 }); 626 }, 627 628 showLabel: function(element, message) { 629 var label = this.errorsFor( element ); 630 if ( label.length ) { 631 // refresh error/success class 632 label.removeClass().addClass( this.settings.errorClass ); 633 634 // check if we have a generated label, replace the message then 635 label.attr("generated") && label.html(message); 636 } else { 637 // create label 638 label = $("<" + this.settings.errorElement + "/>") 639 .attr({"for": this.idOrName(element), generated: true}) 640 .addClass(this.settings.errorClass) 641 .html(message || ""); 642 if ( this.settings.wrapper ) { 643 // make sure the element is visible, even in IE 644 // actually showing the wrapped element is handled elsewhere 645 label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent(); 646 } 647 if ( !this.labelContainer.append(label).length ) 648 this.settings.errorPlacement 649 ? this.settings.errorPlacement(label, $(element) ) 650 : label.insertAfter(element); 651 } 652 if ( !message && this.settings.success ) { 653 label.text(""); 654 typeof this.settings.success == "string" 655 ? label.addClass( this.settings.success ) 656 : this.settings.success( label ); 657 } 658 this.toShow = this.toShow.add(label); 659 }, 660 661 errorsFor: function(element) { 662 var name = this.idOrName(element); 663 return this.errors().filter(function() { 664 return $(this).attr('for') == name; 665 }); 666 }, 667 668 idOrName: function(element) { 669 return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name); 670 }, 671 672 checkable: function( element ) { 673 return /radio|checkbox/i.test(element.type); 674 }, 675 676 findByName: function( name ) { 677 // select by name and filter by form for performance over form.find("[name=...]") 678 var form = this.currentForm; 679 return $(document.getElementsByName(name)).map(function(index, element) { 680 return element.form == form && element.name == name && element || null; 681 }); 682 }, 683 684 getLength: function(value, element) { 685 switch( element.nodeName.toLowerCase() ) { 686 case 'select': 687 return $("option:selected", element).length; 688 case 'input': 689 if( this.checkable( element) ) 690 return this.findByName(element.name).filter(':checked').length; 691 } 692 return value.length; 693 }, 694 695 depend: function(param, element) { 696 return this.dependTypes[typeof param] 697 ? this.dependTypes[typeof param](param, element) 698 : true; 699 }, 700 701 dependTypes: { 702 "boolean": function(param, element) { 703 return param; 704 }, 705 "string": function(param, element) { 706 return !!$(param, element.form).length; 707 }, 708 "function": function(param, element) { 709 return param(element); 710 } 711 }, 712 713 optional: function(element) { 714 return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch"; 715 }, 716 717 startRequest: function(element) { 718 if (!this.pending[element.name]) { 719 this.pendingRequest++; 720 this.pending[element.name] = true; 721 } 722 }, 723 724 stopRequest: function(element, valid) { 725 this.pendingRequest--; 726 // sometimes synchronization fails, make sure pendingRequest is never < 0 727 if (this.pendingRequest < 0) 728 this.pendingRequest = 0; 729 delete this.pending[element.name]; 730 if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) { 731 $(this.currentForm).submit(); 732 this.formSubmitted = false;
733 } else if (!valid && this.pendingRequest == 0 && this.formSubmitted) { 734 $(this.currentForm).triggerHandler("invalid-form", [this]); 735 this.formSubmitted = false; 736 } 737 }, 738 739 previousValue: function(element) { 740 return $.data(element, "previousValue") || $.data(element, "previousValue", { 741 old: null, 742 valid: true, 743 message: this.defaultMessage( element, "remote" ) 744 }); 745 } 746 747 }, 748 749 classRuleSettings: { 750 required: {required: true}, 751 email: {email: true}, 752 url: {url: true}, 753 date: {date: true}, 754 dateISO: {dateISO: true}, 755 dateDE: {dateDE: true}, 756 number: {number: true}, 757 numberDE: {numberDE: true}, 758 digits: {digits: true}, 759 creditcard: {creditcard: true} 760 }, 761 762 addClassRules: function(className, rules) { 763 className.constructor == String ? 764 this.classRuleSettings[className] = rules : 765 $.extend(this.classRuleSettings, className); 766 }, 767 768 classRules: function(element) { 769 var rules = {}; 770 var classes = $(element).attr('class'); 771 classes && $.each(classes.split(' '), function() { 772 if (this in $.validator.classRuleSettings) { 773 $.extend(rules, $.validator.classRuleSettings[this]); 774 } 775 }); 776 return rules; 777 }, 778 779 attributeRules: function(element) { 780 var rules = {}; 781 var $element = $(element); 782 783 for (var method in $.validator.methods) { 784 var value = $element.attr(method); 785 if (value) { 786 rules[method] = value; 787 } 788 } 789 790 // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs 791 if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) { 792 delete rules.maxlength; 793 } 794 795 return rules; 796 }, 797 798 metadataRules: function(element) { 799 if (!$.metadata) return {}; 800 801 var meta = $.data(element.form, 'validator').settings.meta; 802 return meta ? 803 $(element).metadata()[meta] : 804 $(element).metadata(); 805 }, 806 807 staticRules: function(element) { 808 var rules = {}; 809 var validator = $.data(element.form, 'validator'); 810 if (validator.settings.rules) { 811 rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {}; 812 } 813 return rules; 814 }, 815 816 normalizeRules: function(rules, element) { 817 // handle dependency check 818 $.each(rules, function(prop, val) { 819 // ignore rule when param is explicitly false, eg. required:false 820 if (val === false) { 821 delete rules[prop]; 822 return; 823 } 824 if (val.param || val.depends) { 825 var keepRule = true; 826 switch (typeof val.depends) { 827 case "string": 828 keepRule = !!$(val.depends, element.form).length; 829 break; 830 case "function": 831 keepRule = val.depends.call(element, element); 832 break; 833 } 834 if (keepRule) { 835 rules[prop] = val.param !== undefined ? val.param : true; 836 } else { 837 delete rules[prop]; 838 } 839 } 840 }); 841 842 // evaluate parameters 843 $.each(rules, function(rule, parameter) { 844 rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter; 845 }); 846 847 // clean number parameters 848 $.each(['minlength', 'maxlength', 'min', 'max'], function() { 849 if (rules[this]) { 850 rules[this] = Number(rules[this]); 851 } 852 }); 853 $.each(['rangelength', 'range'], function() { 854 if (rules[this]) { 855 rules[this] = [Number(rules[this][0]), Number(rules[this][1])]; 856 } 857 }); 858 859 if ($.validator.autoCreateRanges) { 860 // auto-create ranges 861 if (rules.min && rules.max) { 862 rules.range = [rules.min, rules.max]; 863 delete rules.min; 864 delete rules.max; 865 } 866 if (rules.minlength && rules.maxlength) { 867 rules.rangelength = [rules.minlength, rules.maxlength]; 868 delete rules.minlength; 869 delete rules.maxlength; 870 } 871 } 872 873 // To support custom messages in metadata ignore rule methods titled "messages" 874 if (rules.messages) { 875 delete rules.messages; 876 } 877 878 return rules; 879 }, 880 881 // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true} 882 normalizeRule: function(data) { 883 if( typeof data == "string" ) { 884 var transformed = {}; 885 $.each(data.split(/\s/), function() { 886 transformed[this] = true; 887 }); 888 data = transformed; 889 } 890 return data; 891 }, 892 893 // http://docs.jquery.com/Plugins/Validation/Validator/addMethod 894 addMethod: function(name, method, message) { 895 $.validator.methods[name] = method; 896 $.validator.messages[name] = message != undefined ? message : $.validator.messages[name]; 897 if (method.length < 3) { 898 $.validator.addClassRules(name, $.validator.normalizeRule(name)); 899 } 900 }, 901 902 methods: { 903 904 // http://docs.jquery.com/Plugins/Validation/Methods/required 905 required: function(value, element, param) { 906 // check if dependency is met 907 if ( !this.depend(param, element) ) 908 return "dependency-mismatch"; 909 switch( element.nodeName.toLowerCase() ) { 910 case 'select': 911 // could be an array for select-multiple or a string, both are fine this way 912 var val = $(element).val(); 913 return val && val.length > 0; 914 case 'input': 915 if ( this.checkable(element) ) 916 return this.getLength(value, element) > 0; 917 default: 918 return $.trim(value).length > 0; 919 } 920 }, 921 922 // http://docs.jquery.com/Plugins/Validation/Methods/remote 923 remote: function(value, element, param) { 924 if ( this.optional(element) ) 925 return "dependency-mismatch"; 926 927 var previous = this.previousValue(element); 928 if (!this.settings.messages[element.name] ) 929 this.settings.messages[element.name] = {}; 930 previous.originalMessage = this.settings.messages[element.name].remote; 931 this.settings.messages[element.name].remote = previous.message; 932 933 param = typeof param == "string" && {url:param} || param; 934 935 if ( this.pending[element.name] ) { 936 return "pending"; 937 } 938 if ( previous.old === value ) { 939 return previous.valid; 940 } 941 942 previous.old = value;
943 var validator = this; 944 this.startRequest(element); 945 var data = {}; 946 data[element.name] = value; 947 $.ajax($.extend(true, { 948 url: param, 949 mode: "abort", 950 port: "validate" + element.name, 951 dataType: "json", 952 data: data, 953 success: function(response) { 954 validator.settings.messages[element.name].remote = previous.originalMessage; 955 var valid = response === true; 956 if ( valid ) { 957 var submitted = validator.formSubmitted; 958 validator.prepareElement(element); 959 validator.formSubmitted = submitted; 960 validator.successList.push(element); 961 validator.showErrors(); 962 } else { 963 var errors = {}; 964 var message = response || validator.defaultMessage( element, "remote" ); 965 errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message; 966 validator.showErrors(errors); 967 } 968 previous.valid = valid; 969 validator.stopRequest(element, valid); 970 } 971 }, param)); 972 return "pending"; 973 }, 974 975 // http://docs.jquery.com/Plugins/Validation/Methods/minlength 976 minlength: function(value, element, param) { 977 return this.optional(element) || this.getLength($.trim(value), element) >= param; 978 }, 979 980 // http://docs.jquery.com/Plugins/Validation/Methods/maxlength 981 maxlength: function(value, element, param) { 982 return this.optional(element) || this.getLength($.trim(value), element) <= param; 983 }, 984 985 // http://docs.jquery.com/Plugins/Validation/Methods/rangelength 986 rangelength: function(value, element, param) { 987 var length = this.getLength($.trim(value), element); 988 return this.optional(element) || ( length >= param[0] && length <= param[1] ); 989 }, 990 991 // http://docs.jquery.com/Plugins/Validation/Methods/min 992 min: function( value, element, param ) { 993 return this.optional(element) || value >= param; 994 }, 995 996 // http://docs.jquery.com/Plugins/Validation/Methods/max 997 max: function( value, element, param ) { 998 return this.optional(element) || value <= param; 999 }, 1000 1001 // http://docs.jquery.com/Plugins/Validation/Methods/range 1002 range: function( value, element, param ) { 1003 return this.optional(element) || ( value >= param[0] && value <= param[1] ); 1004 }, 1005 1006 // http://docs.jquery.com/Plugins/Validation/Methods/email 1007 email: function(value, element) { 1008 // dfcarney - updated from StackOverflow 1009 // http://stackoverflow.com/questions/2855865/jquery-validate-e-mail-address-regex 1010 // http://ask.altervista.org/demo/jquery-validate-e-mail-address-regex/ 1011 // return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value); 1012 1013 // KISS: copied from authentication.rb 1014 return this.optional(element) || /^.+@.+\..+$/i.test(value); 1015 }, 1016 1017 // http://docs.jquery.com/Plugins/Validation/Methods/url 1018 url: function(value, element) { 1019 // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/ 1020 return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value); 1021 }, 1022 1023 // http://docs.jquery.com/Plugins/Validation/Methods/date 1024 date: function(value, element) { 1025 return this.optional(element) || !/Invalid|NaN/.test(new Date(value)); 1026 }, 1027 1028 // http://docs.jquery.com/Plugins/Validation/Methods/dateISO 1029 dateISO: function(value, element) { 1030 return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value); 1031 }, 1032 1033 // http://docs.jquery.com/Plugins/Validation/Methods/number 1034 number: function(value, element) { 1035 return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value); 1036 }, 1037 1038 // http://docs.jquery.com/Plugins/Validation/Methods/digits 1039 digits: function(value, element) { 1040 return this.optional(element) || /^\d+$/.test(value); 1041 }, 1042 1043 // http://docs.jquery.com/Plugins/Validation/Methods/creditcard 1044 // based on http://en.wikipedia.org/wiki/Luhn 1045 creditcard: function(value, element) { 1046 if ( this.optional(element) ) 1047 return "dependency-mismatch"; 1048 // accept only digits and dashes 1049 if (/[^0-9-]+/.test(value)) 1050 return false;
1051 var nCheck = 0, 1052 nDigit = 0, 1053 bEven = false; 1054 1055 value = value.replace(/\D/g, ""); 1056 1057 for (var n = value.length - 1; n >= 0; n--) { 1058 var cDigit = value.charAt(n); 1059 var nDigit = parseInt(cDigit, 10); 1060 if (bEven) { 1061 if ((nDigit *= 2) > 9) 1062 nDigit -= 9; 1063 } 1064 nCheck += nDigit; 1065 bEven = !bEven; 1066 } 1067 1068 return (nCheck % 10) == 0; 1069 }, 1070 1071 // http://docs.jquery.com/Plugins/Validation/Methods/accept 1072 accept: function(value, element, param) { 1073 param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif"; 1074 return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i")); 1075 }, 1076 1077 // http://docs.jquery.com/Plugins/Validation/Methods/equalTo 1078 equalTo: function(value, element, param) { 1079 // bind to the blur event of the target in order to revalidate whenever the target field is updated 1080 // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead 1081 var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() { 1082 $(element).valid(); 1083 }); 1084 return value == target.val(); 1085 } 1086 1087 } 1088 1089}); 1090 1091// deprecated, use $.validator.format instead 1092$.format = $.validator.format; 1093 1094})(_4ORMAT.$); 1095 1096// ajax mode: abort 1097// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]}); 1098// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 1099;(function($) { 1100 var pendingRequests = {}; 1101 // Use a prefilter if available (1.5+) 1102 if ( $.ajaxPrefilter ) { 1103 $.ajaxPrefilter(function(settings, _, xhr) { 1104 var port = settings.port; 1105 if (settings.mode == "abort") { 1106 if ( pendingRequests[port] ) { 1107 pendingRequests[port].abort(); 1108 } 1109 pendingRequests[port] = xhr; 1110 } 1111 }); 1112 } else { 1113 // Proxy ajax 1114 var ajax = $.ajax; 1115 $.ajax = function(settings) { 1116 var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode, 1117 port = ( "port" in settings ? settings : $.ajaxSettings ).port; 1118 if (mode == "abort") { 1119 if ( pendingRequests[port] ) { 1120 pendingRequests[port].abort(); 1121 } 1122 return (pendingRequests[port] = ajax.apply(this, arguments)); 1123 } 1124 return ajax.apply(this, arguments); 1125 }; 1126 } 1127})(_4ORMAT.$); 1128 1129// provides cross-browser focusin and focusout events 1130// IE has native support, in other browsers, use event caputuring (neither bubbles) 1131 1132// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation 1133// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target 1134;(function($) { 1135 // only implement if not provided by jQuery core (since 1.4) 1136 // TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs 1137 if (!$.event.special.focusin && !$.event.special.focusout && document.addEventListener) { 1138 $.each({ 1139 focus: 'focusin', 1140 blur: 'focusout' 1141 }, function( original, fix ){ 1142 $.event.special[fix] = { 1143 setup:function() { 1144 this.addEventListener( original, handler, true ); 1145 }, 1146 teardown:function() { 1147 this.removeEventListener( original, handler, true ); 1148 }, 1149 handler: function(e) { 1150 arguments[0] = $.event.fix(e); 1151 arguments[0].type = fix; 1152 return $.event.handle.apply(this, arguments); 1153 } 1154 }; 1155 function handler(e) { 1156 e = $.event.fix(e); 1157 e.type = fix; 1158 return $.event.handle.call(this, e); 1159 } 1160 }); 1161 }; 1162 $.extend($.fn, { 1163 validateDelegate: function(delegate, type, handler) { 1164 return this.bind(type, function(event) { 1165 var target = $(event.target); 1166 if (target.is(delegate)) { 1167 return handler.apply(target, arguments); 1168 } 1169 }); 1170 } 1171 }); 1172})(_4ORMAT.$); 1173 1174 _4ORMAT.$.validator.addMethod("alphanumeric", function(value, element) { 1175 return this.optional(element) || /^\w+$/i.test(value); 1176}, ""); 1177 1178/*! jQuery UI - v1.10.4 - 2014-04-02 1179* http://jqueryui.com 1180* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.effect.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.slider.js, jquery.ui.sortable.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js 1181* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */ 1182 1183 1184(function( $, undefined ) { 1185 1186var uuid = 0, 1187 runiqueId = /^ui-id-\d+$/; 1188
vendor: 5,456 bytes, lines 1189-1376
1189// $.ui might exist from components with no dependencies, e.g., $.ui.position 1190$.ui = $.ui || {}; 1191 1192$.extend( $.ui, { 1193 version: "1.10.4", 1194 1195 keyCode: { 1196 BACKSPACE: 8, 1197 COMMA: 188, 1198 DELETE: 46, 1199 DOWN: 40, 1200 END: 35, 1201 ENTER: 13, 1202 ESCAPE: 27, 1203 HOME: 36, 1204 LEFT: 37, 1205 NUMPAD_ADD: 107, 1206 NUMPAD_DECIMAL: 110, 1207 NUMPAD_DIVIDE: 111, 1208 NUMPAD_ENTER: 108, 1209 NUMPAD_MULTIPLY: 106, 1210 NUMPAD_SUBTRACT: 109, 1211 PAGE_DOWN: 34, 1212 PAGE_UP: 33, 1213 PERIOD: 190, 1214 RIGHT: 39, 1215 SPACE: 32, 1216 TAB: 9, 1217 UP: 38 1218 } 1219}); 1220 1221// plugins 1222$.fn.extend({ 1223 focus: (function( orig ) { 1224 return function( delay, fn ) { 1225 return typeof delay === "number" ? 1226 this.each(function() { 1227 var elem = this; 1228 setTimeout(function() { 1229 $( elem ).focus(); 1230 if ( fn ) { 1231 fn.call( elem ); 1232 } 1233 }, delay ); 1234 }) : 1235 orig.apply( this, arguments ); 1236 }; 1237 })( $.fn.focus ), 1238 1239 scrollParent: function() { 1240 var scrollParent; 1241 if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) { 1242 scrollParent = this.parents().filter(function() { 1243 return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x")); 1244 }).eq(0); 1245 } else { 1246 scrollParent = this.parents().filter(function() { 1247 return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x")); 1248 }).eq(0); 1249 } 1250 1251 return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent; 1252 }, 1253 1254 zIndex: function( zIndex ) { 1255 if ( zIndex !== undefined ) { 1256 return this.css( "zIndex", zIndex ); 1257 } 1258 1259 if ( this.length ) { 1260 var elem = $( this[ 0 ] ), position, value; 1261 while ( elem.length && elem[ 0 ] !== document ) { 1262 // Ignore z-index if position is set to a value where z-index is ignored by the browser 1263 // This makes behavior of this function consistent across browsers 1264 // WebKit always returns auto if the element is positioned 1265 position = elem.css( "position" ); 1266 if ( position === "absolute" || position === "relative" || position === "fixed" ) { 1267 // IE returns 0 when zIndex is not specified 1268 // other browsers return a string 1269 // we ignore the case of nested elements with an explicit value of 0 1270 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> 1271 value = parseInt( elem.css( "zIndex" ), 10 ); 1272 if ( !isNaN( value ) && value !== 0 ) { 1273 return value; 1274 } 1275 } 1276 elem = elem.parent(); 1277 } 1278 } 1279 1280 return 0; 1281 }, 1282 1283 uniqueId: function() { 1284 return this.each(function() { 1285 if ( !this.id ) { 1286 this.id = "ui-id-" + (++uuid); 1287 } 1288 }); 1289 }, 1290 1291 removeUniqueId: function() { 1292 return this.each(function() { 1293 if ( runiqueId.test( this.id ) ) { 1294 $( this ).removeAttr( "id" ); 1295 } 1296 }); 1297 } 1298}); 1299 1300// selectors 1301function focusable( element, isTabIndexNotNaN ) { 1302 var map, mapName, img, 1303 nodeName = element.nodeName.toLowerCase(); 1304 if ( "area" === nodeName ) { 1305 map = element.parentNode; 1306 mapName = map.name; 1307 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { 1308 return false; 1309 } 1310 img = $( "img[usemap=#" + mapName + "]" )[0]; 1311 return !!img && visible( img ); 1312 } 1313 return ( /input|select|textarea|button|object/.test( nodeName ) ? 1314 !element.disabled : 1315 "a" === nodeName ? 1316 element.href || isTabIndexNotNaN : 1317 isTabIndexNotNaN) && 1318 // the element and all of its ancestors must be visible 1319 visible( element ); 1320} 1321 1322function visible( element ) { 1323 return $.expr.filters.visible( element ) && 1324 !$( element ).parents().addBack().filter(function() { 1325 return $.css( this, "visibility" ) === "hidden"; 1326 }).length; 1327} 1328 1329$.extend( $.expr[ ":" ], { 1330 data: $.expr.createPseudo ? 1331 $.expr.createPseudo(function( dataName ) { 1332 return function( elem ) { 1333 return !!$.data( elem, dataName ); 1334 }; 1335 }) : 1336 // support: jQuery <1.8 1337 function( elem, i, match ) { 1338 return !!$.data( elem, match[ 3 ] ); 1339 }, 1340 1341 focusable: function( element ) { 1342 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); 1343 }, 1344 1345 tabbable: function( element ) { 1346 var tabIndex = $.attr( element, "tabindex" ), 1347 isTabIndexNaN = isNaN( tabIndex ); 1348 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); 1349 } 1350}); 1351 1352// support: jQuery <1.8 1353if ( !$( "<a>" ).outerWidth( 1 ).jquery ) { 1354 $.each( [ "Width", "Height" ], function( i, name ) { 1355 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], 1356 type = name.toLowerCase(), 1357 orig = { 1358 innerWidth: $.fn.innerWidth, 1359 innerHeight: $.fn.innerHeight, 1360 outerWidth: $.fn.outerWidth, 1361 outerHeight: $.fn.outerHeight 1362 }; 1363 1364 function reduce( elem, size, border, margin ) { 1365 $.each( side, function() { 1366 size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; 1367 if ( border ) { 1368 size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; 1369 } 1370 if ( margin ) { 1371 size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; 1372 } 1373 }); 1374 return size; 1375 } 1376
1377 $.fn[ "inner" + name ] = function( size ) { 1378 if ( size === undefined ) { 1379 return orig[ "inner" + name ].call( this ); 1380 } 1381 1382 return this.each(function() { 1383 $( this ).css( type, reduce( this, size ) + "px" ); 1384 }); 1385 }; 1386 1387 $.fn[ "outer" + name] = function( size, margin ) { 1388 if ( typeof size !== "number" ) { 1389 return orig[ "outer" + name ].call( this, size ); 1390 } 1391 1392 return this.each(function() { 1393 $( this).css( type, reduce( this, size, true, margin ) + "px" ); 1394 }); 1395 }; 1396 }); 1397} 1398 1399// support: jQuery <1.8 1400if ( !$.fn.addBack ) { 1401 $.fn.addBack = function( selector ) { 1402 return this.add( selector == null ? 1403 this.prevObject : this.prevObject.filter( selector ) 1404 ); 1405 }; 1406} 1407 1408// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413) 1409if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) { 1410 $.fn.removeData = (function( removeData ) { 1411 return function( key ) { 1412 if ( arguments.length ) { 1413 return removeData.call( this, $.camelCase( key ) ); 1414 } else { 1415 return removeData.call( this ); 1416 } 1417 }; 1418 })( $.fn.removeData ); 1419} 1420 1421 1422 1423 1424 1425// deprecated 1426$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() ); 1427 1428$.support.selectstart = "onselectstart" in document.createElement( "div" ); 1429$.fn.extend({ 1430 disableSelection: function() { 1431 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) + 1432 ".ui-disableSelection", function( event ) { 1433 event.preventDefault(); 1434 }); 1435 }, 1436 1437 enableSelection: function() { 1438 return this.unbind( ".ui-disableSelection" ); 1439 } 1440}); 1441 1442$.extend( $.ui, { 1443 // $.ui.plugin is deprecated. Use $.widget() extensions instead. 1444 plugin: { 1445 add: function( module, option, set ) { 1446 var i, 1447 proto = $.ui[ module ].prototype; 1448 for ( i in set ) { 1449 proto.plugins[ i ] = proto.plugins[ i ] || []; 1450 proto.plugins[ i ].push( [ option, set[ i ] ] ); 1451 } 1452 }, 1453 call: function( instance, name, args ) { 1454 var i, 1455 set = instance.plugins[ name ]; 1456 if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) { 1457 return; 1458 } 1459 1460 for ( i = 0; i < set.length; i++ ) { 1461 if ( instance.options[ set[ i ][ 0 ] ] ) { 1462 set[ i ][ 1 ].apply( instance.element, args ); 1463 } 1464 } 1465 } 1466 }, 1467 1468 // only used by resizable 1469 hasScroll: function( el, a ) { 1470 1471 //If overflow is hidden, the element might have extra content, but the user wants to hide it 1472 if ( $( el ).css( "overflow" ) === "hidden") { 1473 return false; 1474 } 1475 1476 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", 1477 has = false; 1478 1479 if ( el[ scroll ] > 0 ) { 1480 return true; 1481 } 1482 1483 // TODO: determine which cases actually cause this to happen 1484 // if the element doesn't have the scroll set, see if it's possible to 1485 // set the scroll 1486 el[ scroll ] = 1; 1487 has = ( el[ scroll ] > 0 ); 1488 el[ scroll ] = 0; 1489 return has; 1490 } 1491}); 1492 1493})( _4ORMAT.$ ); 1494(function( $, undefined ) { 1495 1496var uuid = 0, 1497 slice = Array.prototype.slice, 1498 _cleanData = $.cleanData; 1499$.cleanData = function( elems ) { 1500 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { 1501 try { 1502 $( elem ).triggerHandler( "remove" ); 1503 // http://bugs.jquery.com/ticket/8235 1504 } catch( e ) {} 1505 } 1506 _cleanData( elems ); 1507}; 1508 1509$.widget = function( name, base, prototype ) { 1510 var fullName, existingConstructor, constructor, basePrototype, 1511 // proxiedPrototype allows the provided prototype to remain unmodified 1512 // so that it can be used as a mixin for multiple widgets (#8876) 1513 proxiedPrototype = {}, 1514 namespace = name.split( "." )[ 0 ]; 1515 1516 name = name.split( "." )[ 1 ]; 1517 fullName = namespace + "-" + name; 1518 1519 if ( !prototype ) { 1520 prototype = base; 1521 base = $.Widget; 1522 } 1523 1524 // create selector for plugin 1525 $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { 1526 return !!$.data( elem, fullName ); 1527 }; 1528 1529 $[ namespace ] = $[ namespace ] || {}; 1530 existingConstructor = $[ namespace ][ name ]; 1531 constructor = $[ namespace ][ name ] = function( options, element ) { 1532 // allow instantiation without "new" keyword 1533 if ( !this._createWidget ) { 1534 return new constructor( options, element ); 1535 } 1536 1537 // allow instantiation without initializing for simple inheritance 1538 // must use "new" keyword (the code above always passes args) 1539 if ( arguments.length ) { 1540 this._createWidget( options, element ); 1541 } 1542 }; 1543 // extend with the existing constructor to carry over any static properties 1544 $.extend( constructor, existingConstructor, { 1545 version: prototype.version, 1546 // copy the object used to create the prototype in case we need to 1547 // redefine the widget later 1548 _proto: $.extend( {}, prototype ), 1549 // track widgets that inherit from this widget in case this widget is 1550 // redefined after a widget inherits from it 1551 _childConstructors: [] 1552 }); 1553 1554 basePrototype = new base(); 1555 // we need to make the options hash a property directly on the new instance 1556 // otherwise we'll modify the options hash on the prototype that we're 1557 // inheriting from 1558 basePrototype.options = $.widget.extend( {}, basePrototype.options ); 1559 $.each( prototype, function( prop, value ) { 1560 if ( !$.isFunction( value ) ) { 1561 proxiedPrototype[ prop ] = value; 1562 return; 1563 } 1564 proxiedPrototype[ prop ] = (function() { 1565 var _super = function() { 1566 return base.prototype[ prop ].apply( this, arguments ); 1567 }, 1568 _superApply = function( args ) { 1569 return base.prototype[ prop ].apply( this, args ); 1570 }; 1571 return function() { 1572 var __super = this._super, 1573 __superApply = this._superApply, 1574 returnValue; 1575 1576 this._super = _super; 1577 this._superApply = _superApply; 1578
vendor: 12,900 bytes, lines 1579-1990
1579 returnValue = value.apply( this, arguments ); 1580 1581 this._super = __super; 1582 this._superApply = __superApply; 1583 1584 return returnValue; 1585 }; 1586 })(); 1587 }); 1588 constructor.prototype = $.widget.extend( basePrototype, { 1589 // TODO: remove support for widgetEventPrefix 1590 // always use the name + a colon as the prefix, e.g., draggable:start 1591 // don't prefix for widgets that aren't DOM-based 1592 widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name 1593 }, proxiedPrototype, { 1594 constructor: constructor, 1595 namespace: namespace, 1596 widgetName: name, 1597 widgetFullName: fullName 1598 }); 1599 1600 // If this widget is being redefined then we need to find all widgets that 1601 // are inheriting from it and redefine all of them so that they inherit from 1602 // the new version of this widget. We're essentially trying to replace one 1603 // level in the prototype chain. 1604 if ( existingConstructor ) { 1605 $.each( existingConstructor._childConstructors, function( i, child ) { 1606 var childPrototype = child.prototype; 1607 1608 // redefine the child widget using the same prototype that was 1609 // originally used, but inherit from the new version of the base 1610 $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); 1611 }); 1612 // remove the list of existing child constructors from the old constructor 1613 // so the old child constructors can be garbage collected 1614 delete existingConstructor._childConstructors; 1615 } else { 1616 base._childConstructors.push( constructor ); 1617 } 1618 1619 $.widget.bridge( name, constructor ); 1620}; 1621 1622$.widget.extend = function( target ) { 1623 var input = slice.call( arguments, 1 ), 1624 inputIndex = 0, 1625 inputLength = input.length, 1626 key, 1627 value; 1628 for ( ; inputIndex < inputLength; inputIndex++ ) { 1629 for ( key in input[ inputIndex ] ) { 1630 value = input[ inputIndex ][ key ]; 1631 if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { 1632 // Clone objects 1633 if ( $.isPlainObject( value ) ) { 1634 target[ key ] = $.isPlainObject( target[ key ] ) ? 1635 $.widget.extend( {}, target[ key ], value ) : 1636 // Don't extend strings, arrays, etc. with objects 1637 $.widget.extend( {}, value ); 1638 // Copy everything else by reference 1639 } else { 1640 target[ key ] = value; 1641 } 1642 } 1643 } 1644 } 1645 return target; 1646}; 1647 1648$.widget.bridge = function( name, object ) { 1649 var fullName = object.prototype.widgetFullName || name; 1650 $.fn[ name ] = function( options ) { 1651 var isMethodCall = typeof options === "string", 1652 args = slice.call( arguments, 1 ), 1653 returnValue = this; 1654 1655 // allow multiple hashes to be passed on init 1656 options = !isMethodCall && args.length ? 1657 $.widget.extend.apply( null, [ options ].concat(args) ) : 1658 options; 1659 1660 if ( isMethodCall ) { 1661 this.each(function() { 1662 var methodValue, 1663 instance = $.data( this, fullName ); 1664 if ( !instance ) { 1665 return $.error( "cannot call methods on " + name + " prior to initialization; " + 1666 "attempted to call method '" + options + "'" ); 1667 } 1668 if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) { 1669 return $.error( "no such method '" + options + "' for " + name + " widget instance" ); 1670 } 1671 methodValue = instance[ options ].apply( instance, args ); 1672 if ( methodValue !== instance && methodValue !== undefined ) { 1673 returnValue = methodValue && methodValue.jquery ? 1674 returnValue.pushStack( methodValue.get() ) : 1675 methodValue; 1676 return false; 1677 } 1678 }); 1679 } else { 1680 this.each(function() { 1681 var instance = $.data( this, fullName ); 1682 if ( instance ) { 1683 instance.option( options || {} )._init(); 1684 } else { 1685 $.data( this, fullName, new object( options, this ) ); 1686 } 1687 }); 1688 } 1689 1690 return returnValue; 1691 }; 1692}; 1693 1694$.Widget = function( /* options, element */ ) {}; 1695$.Widget._childConstructors = []; 1696 1697$.Widget.prototype = { 1698 widgetName: "widget", 1699 widgetEventPrefix: "", 1700 defaultElement: "<div>", 1701 options: { 1702 disabled: false, 1703 1704 // callbacks 1705 create: null 1706 }, 1707 _createWidget: function( options, element ) { 1708 element = $( element || this.defaultElement || this )[ 0 ]; 1709 this.element = $( element ); 1710 this.uuid = uuid++; 1711 this.eventNamespace = "." + this.widgetName + this.uuid; 1712 this.options = $.widget.extend( {}, 1713 this.options, 1714 this._getCreateOptions(), 1715 options ); 1716 1717 this.bindings = $(); 1718 this.hoverable = $(); 1719 this.focusable = $(); 1720 1721 if ( element !== this ) { 1722 $.data( element, this.widgetFullName, this ); 1723 this._on( true, this.element, { 1724 remove: function( event ) { 1725 if ( event.target === element ) { 1726 this.destroy(); 1727 } 1728 } 1729 }); 1730 this.document = $( element.style ? 1731 // element within the document 1732 element.ownerDocument : 1733 // element is window or document 1734 element.document || element ); 1735 this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); 1736 } 1737 1738 this._create(); 1739 this._trigger( "create", null, this._getCreateEventData() ); 1740 this._init(); 1741 }, 1742 _getCreateOptions: $.noop, 1743 _getCreateEventData: $.noop, 1744 _create: $.noop, 1745 _init: $.noop, 1746 1747 destroy: function() { 1748 this._destroy(); 1749 // we can probably remove the unbind calls in 2.0 1750 // all event bindings should go through this._on() 1751 this.element 1752 .unbind( this.eventNamespace ) 1753 // 1.9 BC for #7810 1754 // TODO remove dual storage 1755 .removeData( this.widgetName ) 1756 .removeData( this.widgetFullName ) 1757 // support: jquery <1.6.3 1758 // http://bugs.jquery.com/ticket/9413 1759 .removeData( $.camelCase( this.widgetFullName ) ); 1760 this.widget() 1761 .unbind( this.eventNamespace ) 1762 .removeAttr( "aria-disabled" ) 1763 .removeClass( 1764 this.widgetFullName + "-disabled " + 1765 "ui-state-disabled" ); 1766 1767 // clean up events and states 1768 this.bindings.unbind( this.eventNamespace ); 1769 this.hoverable.removeClass( "ui-state-hover" ); 1770 this.focusable.removeClass( "ui-state-focus" ); 1771 }, 1772 _destroy: $.noop, 1773 1774 widget: function() { 1775 return this.element; 1776 }, 1777 1778 option: function( key, value ) { 1779 var options = key, 1780 parts, 1781 curOption, 1782 i; 1783 1784 if ( arguments.length === 0 ) { 1785 // don't return a reference to the internal hash 1786 return $.widget.extend( {}, this.options ); 1787 } 1788 1789 if ( typeof key === "string" ) { 1790 // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } 1791 options = {}; 1792 parts = key.split( "." ); 1793 key = parts.shift(); 1794 if ( parts.length ) { 1795 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); 1796 for ( i = 0; i < parts.length - 1; i++ ) { 1797 curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; 1798 curOption = curOption[ parts[ i ] ]; 1799 } 1800 key = parts.pop(); 1801 if ( arguments.length === 1 ) { 1802 return curOption[ key ] === undefined ? null : curOption[ key ]; 1803 } 1804 curOption[ key ] = value; 1805 } else { 1806 if ( arguments.length === 1 ) { 1807 return this.options[ key ] === undefined ? null : this.options[ key ]; 1808 } 1809 options[ key ] = value; 1810 } 1811 } 1812 1813 this._setOptions( options ); 1814 1815 return this; 1816 }, 1817 _setOptions: function( options ) { 1818 var key; 1819 1820 for ( key in options ) { 1821 this._setOption( key, options[ key ] ); 1822 } 1823 1824 return this; 1825 }, 1826 _setOption: function( key, value ) { 1827 this.options[ key ] = value; 1828 1829 if ( key === "disabled" ) { 1830 this.widget() 1831 .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value ) 1832 .attr( "aria-disabled", value ); 1833 this.hoverable.removeClass( "ui-state-hover" ); 1834 this.focusable.removeClass( "ui-state-focus" ); 1835 } 1836 1837 return this; 1838 }, 1839 1840 enable: function() { 1841 return this._setOption( "disabled", false ); 1842 }, 1843 disable: function() { 1844 return this._setOption( "disabled", true ); 1845 }, 1846 1847 _on: function( suppressDisabledCheck, element, handlers ) { 1848 var delegateElement, 1849 instance = this; 1850 1851 // no suppressDisabledCheck flag, shuffle arguments 1852 if ( typeof suppressDisabledCheck !== "boolean" ) { 1853 handlers = element; 1854 element = suppressDisabledCheck; 1855 suppressDisabledCheck = false; 1856 } 1857 1858 // no element argument, shuffle and use this.element 1859 if ( !handlers ) { 1860 handlers = element; 1861 element = this.element; 1862 delegateElement = this.widget(); 1863 } else { 1864 // accept selectors, DOM elements 1865 element = delegateElement = $( element ); 1866 this.bindings = this.bindings.add( element ); 1867 } 1868 1869 $.each( handlers, function( event, handler ) { 1870 function handlerProxy() { 1871 // allow widgets to customize the disabled handling 1872 // - disabled as an array instead of boolean 1873 // - disabled class as method for disabling individual parts 1874 if ( !suppressDisabledCheck && 1875 ( instance.options.disabled === true || 1876 $( this ).hasClass( "ui-state-disabled" ) ) ) { 1877 return; 1878 } 1879 return ( typeof handler === "string" ? instance[ handler ] : handler ) 1880 .apply( instance, arguments ); 1881 } 1882 1883 // copy the guid so direct unbinding works 1884 if ( typeof handler !== "string" ) { 1885 handlerProxy.guid = handler.guid = 1886 handler.guid || handlerProxy.guid || $.guid++; 1887 } 1888 1889 var match = event.match( /^(\w+)\s*(.*)$/ ), 1890 eventName = match[1] + instance.eventNamespace, 1891 selector = match[2]; 1892 if ( selector ) { 1893 delegateElement.delegate( selector, eventName, handlerProxy ); 1894 } else { 1895 element.bind( eventName, handlerProxy ); 1896 } 1897 }); 1898 }, 1899 1900 _off: function( element, eventName ) { 1901 eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace; 1902 element.unbind( eventName ).undelegate( eventName ); 1903 }, 1904 1905 _delay: function( handler, delay ) { 1906 function handlerProxy() { 1907 return ( typeof handler === "string" ? instance[ handler ] : handler ) 1908 .apply( instance, arguments ); 1909 } 1910 var instance = this; 1911 return setTimeout( handlerProxy, delay || 0 ); 1912 }, 1913 1914 _hoverable: function( element ) { 1915 this.hoverable = this.hoverable.add( element ); 1916 this._on( element, { 1917 mouseenter: function( event ) { 1918 $( event.currentTarget ).addClass( "ui-state-hover" ); 1919 }, 1920 mouseleave: function( event ) { 1921 $( event.currentTarget ).removeClass( "ui-state-hover" ); 1922 } 1923 }); 1924 }, 1925 1926 _focusable: function( element ) { 1927 this.focusable = this.focusable.add( element ); 1928 this._on( element, { 1929 focusin: function( event ) { 1930 $( event.currentTarget ).addClass( "ui-state-focus" ); 1931 }, 1932 focusout: function( event ) { 1933 $( event.currentTarget ).removeClass( "ui-state-focus" ); 1934 } 1935 }); 1936 }, 1937 1938 _trigger: function( type, event, data ) { 1939 var prop, orig, 1940 callback = this.options[ type ]; 1941 1942 data = data || {}; 1943 event = $.Event( event ); 1944 event.type = ( type === this.widgetEventPrefix ? 1945 type : 1946 this.widgetEventPrefix + type ).toLowerCase(); 1947 // the original event may come from any element 1948 // so we need to reset the target on the new event 1949 event.target = this.element[ 0 ]; 1950 1951 // copy original event properties over to the new event 1952 orig = event.originalEvent; 1953 if ( orig ) { 1954 for ( prop in orig ) { 1955 if ( !( prop in event ) ) { 1956 event[ prop ] = orig[ prop ]; 1957 } 1958 } 1959 } 1960 1961 this.element.trigger( event, data ); 1962 return !( $.isFunction( callback ) && 1963 callback.apply( this.element[0], [ event ].concat( data ) ) === false || 1964 event.isDefaultPrevented() ); 1965 } 1966}; 1967 1968$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { 1969 $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { 1970 if ( typeof options === "string" ) { 1971 options = { effect: options }; 1972 } 1973 var hasOptions, 1974 effectName = !options ? 1975 method : 1976 options === true || typeof options === "number" ? 1977 defaultEffect : 1978 options.effect || defaultEffect; 1979 options = options || {}; 1980 if ( typeof options === "number" ) { 1981 options = { duration: options }; 1982 } 1983 hasOptions = !$.isEmptyObject( options ); 1984 options.complete = callback; 1985 if ( options.delay ) { 1986 element.delay( options.delay ); 1987 } 1988 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { 1989 element[ method ]( options ); 1990 } else if ( effectName !== method && element[ effectName ] ) {
vendor: 61,186 bytes, lines 1991-3992
1991 element[ effectName ]( options.duration, options.easing, callback ); 1992 } else { 1993 element.queue(function( next ) { 1994 $( this )[ method ](); 1995 if ( callback ) { 1996 callback.call( element[ 0 ] ); 1997 } 1998 next(); 1999 }); 2000 } 2001 }; 2002}); 2003 2004})( _4ORMAT.$ ); 2005(function( $, undefined ) { 2006 2007var mouseHandled = false; 2008$( document ).mouseup( function() { 2009 mouseHandled = false; 2010}); 2011 2012$.widget("ui.mouse", { 2013 version: "1.10.4", 2014 options: { 2015 cancel: "input,textarea,button,select,option", 2016 distance: 1, 2017 delay: 0 2018 }, 2019 _mouseInit: function() { 2020 var that = this; 2021 2022 this.element 2023 .bind("mousedown."+this.widgetName, function(event) { 2024 return that._mouseDown(event); 2025 }) 2026 .bind("click."+this.widgetName, function(event) { 2027 if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) { 2028 $.removeData(event.target, that.widgetName + ".preventClickEvent"); 2029 event.stopImmediatePropagation(); 2030 return false; 2031 } 2032 }); 2033 2034 this.started = false; 2035 }, 2036 2037 // TODO: make sure destroying one instance of mouse doesn't mess with 2038 // other instances of mouse 2039 _mouseDestroy: function() { 2040 this.element.unbind("."+this.widgetName); 2041 if ( this._mouseMoveDelegate ) { 2042 $(document) 2043 .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate) 2044 .unbind("mouseup."+this.widgetName, this._mouseUpDelegate); 2045 } 2046 }, 2047 2048 _mouseDown: function(event) { 2049 // don't let more than one widget handle mouseStart 2050 if( mouseHandled ) { return; } 2051 2052 // we may have missed mouseup (out of window) 2053 (this._mouseStarted && this._mouseUp(event)); 2054 2055 this._mouseDownEvent = event; 2056 2057 var that = this, 2058 btnIsLeft = (event.which === 1), 2059 // event.target.nodeName works around a bug in IE 8 with 2060 // disabled inputs (#7620) 2061 elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); 2062 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { 2063 return true; 2064 } 2065 2066 this.mouseDelayMet = !this.options.delay; 2067 if (!this.mouseDelayMet) { 2068 this._mouseDelayTimer = setTimeout(function() { 2069 that.mouseDelayMet = true; 2070 }, this.options.delay); 2071 } 2072 2073 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { 2074 this._mouseStarted = (this._mouseStart(event) !== false); 2075 if (!this._mouseStarted) { 2076 event.preventDefault(); 2077 return true; 2078 } 2079 } 2080 2081 // Click event may never have fired (Gecko & Opera) 2082 if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) { 2083 $.removeData(event.target, this.widgetName + ".preventClickEvent"); 2084 } 2085 2086 // these delegates are required to keep context 2087 this._mouseMoveDelegate = function(event) { 2088 return that._mouseMove(event); 2089 }; 2090 this._mouseUpDelegate = function(event) { 2091 return that._mouseUp(event); 2092 }; 2093 $(document) 2094 .bind("mousemove."+this.widgetName, this._mouseMoveDelegate) 2095 .bind("mouseup."+this.widgetName, this._mouseUpDelegate); 2096 2097 event.preventDefault(); 2098 2099 mouseHandled = true; 2100 return true; 2101 }, 2102 2103 _mouseMove: function(event) { 2104 // IE mouseup check - mouseup happened when mouse was out of window 2105 if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) { 2106 return this._mouseUp(event); 2107 } 2108 2109 if (this._mouseStarted) { 2110 this._mouseDrag(event); 2111 return event.preventDefault(); 2112 } 2113 2114 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { 2115 this._mouseStarted = 2116 (this._mouseStart(this._mouseDownEvent, event) !== false); 2117 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); 2118 } 2119 2120 return !this._mouseStarted; 2121 }, 2122 2123 _mouseUp: function(event) { 2124 $(document) 2125 .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate) 2126 .unbind("mouseup."+this.widgetName, this._mouseUpDelegate); 2127 2128 if (this._mouseStarted) { 2129 this._mouseStarted = false; 2130 2131 if (event.target === this._mouseDownEvent.target) { 2132 $.data(event.target, this.widgetName + ".preventClickEvent", true); 2133 } 2134 2135 this._mouseStop(event); 2136 } 2137 2138 return false; 2139 }, 2140 2141 _mouseDistanceMet: function(event) { 2142 return (Math.max( 2143 Math.abs(this._mouseDownEvent.pageX - event.pageX), 2144 Math.abs(this._mouseDownEvent.pageY - event.pageY) 2145 ) >= this.options.distance 2146 ); 2147 }, 2148 2149 _mouseDelayMet: function(/* event */) { 2150 return this.mouseDelayMet; 2151 }, 2152 2153 // These are placeholder methods, to be overriden by extending plugin 2154 _mouseStart: function(/* event */) {}, 2155 _mouseDrag: function(/* event */) {}, 2156 _mouseStop: function(/* event */) {}, 2157 _mouseCapture: function(/* event */) { return true; } 2158}); 2159 2160})( _4ORMAT.$ ); 2161(function( $, undefined ) { 2162 2163$.ui = $.ui || {}; 2164 2165var cachedScrollbarWidth, 2166 max = Math.max, 2167 abs = Math.abs, 2168 round = Math.round, 2169 rhorizontal = /left|center|right/, 2170 rvertical = /top|center|bottom/, 2171 roffset = /[\+\-]\d+(\.[\d]+)?%?/, 2172 rposition = /^\w+/, 2173 rpercent = /%$/, 2174 _position = $.fn.position; 2175 2176function getOffsets( offsets, width, height ) { 2177 return [ 2178 parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ), 2179 parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 ) 2180 ]; 2181} 2182 2183function parseCss( element, property ) { 2184 return parseInt( $.css( element, property ), 10 ) || 0; 2185} 2186 2187function getDimensions( elem ) { 2188 var raw = elem[0]; 2189 if ( raw.nodeType === 9 ) { 2190 return { 2191 width: elem.width(), 2192 height: elem.height(), 2193 offset: { top: 0, left: 0 } 2194 }; 2195 } 2196 if ( $.isWindow( raw ) ) { 2197 return { 2198 width: elem.width(), 2199 height: elem.height(), 2200 offset: { top: elem.scrollTop(), left: elem.scrollLeft() } 2201 }; 2202 } 2203 if ( raw.preventDefault ) { 2204 return { 2205 width: 0, 2206 height: 0, 2207 offset: { top: raw.pageY, left: raw.pageX } 2208 }; 2209 } 2210 return { 2211 width: elem.outerWidth(), 2212 height: elem.outerHeight(), 2213 offset: elem.offset() 2214 }; 2215} 2216 2217$.position = { 2218 scrollbarWidth: function() { 2219 if ( cachedScrollbarWidth !== undefined ) { 2220 return cachedScrollbarWidth; 2221 } 2222 var w1, w2, 2223 div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ), 2224 innerDiv = div.children()[0]; 2225 2226 $( "body" ).append( div ); 2227 w1 = innerDiv.offsetWidth; 2228 div.css( "overflow", "scroll" ); 2229 2230 w2 = innerDiv.offsetWidth; 2231 2232 if ( w1 === w2 ) { 2233 w2 = div[0].clientWidth; 2234 } 2235 2236 div.remove(); 2237 2238 return (cachedScrollbarWidth = w1 - w2); 2239 }, 2240 getScrollInfo: function( within ) { 2241 var overflowX = within.isWindow || within.isDocument ? "" : 2242 within.element.css( "overflow-x" ), 2243 overflowY = within.isWindow || within.isDocument ? "" : 2244 within.element.css( "overflow-y" ), 2245 hasOverflowX = overflowX === "scroll" || 2246 ( overflowX === "auto" && within.width < within.element[0].scrollWidth ), 2247 hasOverflowY = overflowY === "scroll" || 2248 ( overflowY === "auto" && within.height < within.element[0].scrollHeight ); 2249 return { 2250 width: hasOverflowY ? $.position.scrollbarWidth() : 0, 2251 height: hasOverflowX ? $.position.scrollbarWidth() : 0 2252 }; 2253 }, 2254 getWithinInfo: function( element ) { 2255 var withinElement = $( element || window ), 2256 isWindow = $.isWindow( withinElement[0] ), 2257 isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9; 2258 return { 2259 element: withinElement, 2260 isWindow: isWindow, 2261 isDocument: isDocument, 2262 offset: withinElement.offset() || { left: 0, top: 0 }, 2263 scrollLeft: withinElement.scrollLeft(), 2264 scrollTop: withinElement.scrollTop(), 2265 width: isWindow ? withinElement.width() : withinElement.outerWidth(), 2266 height: isWindow ? withinElement.height() : withinElement.outerHeight() 2267 }; 2268 } 2269}; 2270 2271$.fn.position = function( options ) { 2272 if ( !options || !options.of ) { 2273 return _position.apply( this, arguments ); 2274 } 2275 2276 // make a copy, we don't want to modify arguments 2277 options = $.extend( {}, options ); 2278 2279 var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions, 2280 target = $( options.of ), 2281 within = $.position.getWithinInfo( options.within ), 2282 scrollInfo = $.position.getScrollInfo( within ), 2283 collision = ( options.collision || "flip" ).split( " " ), 2284 offsets = {}; 2285 2286 dimensions = getDimensions( target ); 2287 if ( target[0].preventDefault ) { 2288 // force left top to allow flipping 2289 options.at = "left top"; 2290 } 2291 targetWidth = dimensions.width; 2292 targetHeight = dimensions.height; 2293 targetOffset = dimensions.offset; 2294 // clone to reuse original targetOffset later 2295 basePosition = $.extend( {}, targetOffset ); 2296 2297 // force my and at to have valid horizontal and vertical positions 2298 // if a value is missing or invalid, it will be converted to center 2299 $.each( [ "my", "at" ], function() { 2300 var pos = ( options[ this ] || "" ).split( " " ), 2301 horizontalOffset, 2302 verticalOffset; 2303 2304 if ( pos.length === 1) { 2305 pos = rhorizontal.test( pos[ 0 ] ) ? 2306 pos.concat( [ "center" ] ) : 2307 rvertical.test( pos[ 0 ] ) ? 2308 [ "center" ].concat( pos ) : 2309 [ "center", "center" ]; 2310 } 2311 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center"; 2312 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center"; 2313 2314 // calculate offsets 2315 horizontalOffset = roffset.exec( pos[ 0 ] ); 2316 verticalOffset = roffset.exec( pos[ 1 ] ); 2317 offsets[ this ] = [ 2318 horizontalOffset ? horizontalOffset[ 0 ] : 0, 2319 verticalOffset ? verticalOffset[ 0 ] : 0 2320 ]; 2321 2322 // reduce to just the positions without the offsets 2323 options[ this ] = [ 2324 rposition.exec( pos[ 0 ] )[ 0 ], 2325 rposition.exec( pos[ 1 ] )[ 0 ] 2326 ]; 2327 }); 2328 2329 // normalize collision option 2330 if ( collision.length === 1 ) { 2331 collision[ 1 ] = collision[ 0 ]; 2332 } 2333 2334 if ( options.at[ 0 ] === "right" ) { 2335 basePosition.left += targetWidth; 2336 } else if ( options.at[ 0 ] === "center" ) { 2337 basePosition.left += targetWidth / 2; 2338 } 2339 2340 if ( options.at[ 1 ] === "bottom" ) { 2341 basePosition.top += targetHeight; 2342 } else if ( options.at[ 1 ] === "center" ) { 2343 basePosition.top += targetHeight / 2; 2344 } 2345 2346 atOffset = getOffsets( offsets.at, targetWidth, targetHeight ); 2347 basePosition.left += atOffset[ 0 ]; 2348 basePosition.top += atOffset[ 1 ]; 2349 2350 return this.each(function() { 2351 var collisionPosition, using, 2352 elem = $( this ), 2353 elemWidth = elem.outerWidth(), 2354 elemHeight = elem.outerHeight(), 2355 marginLeft = parseCss( this, "marginLeft" ), 2356 marginTop = parseCss( this, "marginTop" ), 2357 collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width, 2358 collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height, 2359 position = $.extend( {}, basePosition ), 2360 myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() ); 2361 2362 if ( options.my[ 0 ] === "right" ) { 2363 position.left -= elemWidth; 2364 } else if ( options.my[ 0 ] === "center" ) { 2365 position.left -= elemWidth / 2; 2366 } 2367 2368 if ( options.my[ 1 ] === "bottom" ) { 2369 position.top -= elemHeight; 2370 } else if ( options.my[ 1 ] === "center" ) { 2371 position.top -= elemHeight / 2; 2372 } 2373 2374 position.left += myOffset[ 0 ]; 2375 position.top += myOffset[ 1 ]; 2376 2377 // if the browser doesn't support fractions, then round for consistent results 2378 if ( !$.support.offsetFractions ) { 2379 position.left = round( position.left ); 2380 position.top = round( position.top ); 2381 } 2382 2383 collisionPosition = { 2384 marginLeft: marginLeft, 2385 marginTop: marginTop 2386 }; 2387 2388 $.each( [ "left", "top" ], function( i, dir ) { 2389 if ( $.ui.position[ collision[ i ] ] ) { 2390 $.ui.position[ collision[ i ] ][ dir ]( position, { 2391 targetWidth: targetWidth, 2392 targetHeight: targetHeight, 2393 elemWidth: elemWidth, 2394 elemHeight: elemHeight, 2395 collisionPosition: collisionPosition, 2396 collisionWidth: collisionWidth, 2397 collisionHeight: collisionHeight, 2398 offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], 2399 my: options.my, 2400 at: options.at, 2401 within: within, 2402 elem : elem 2403 }); 2404 } 2405 }); 2406 2407 if ( options.using ) { 2408 // adds feedback as second argument to using callback, if present 2409 using = function( props ) { 2410 var left = targetOffset.left - position.left, 2411 right = left + targetWidth - elemWidth, 2412 top = targetOffset.top - position.top, 2413 bottom = top + targetHeight - elemHeight, 2414 feedback = { 2415 target: { 2416 element: target, 2417 left: targetOffset.left, 2418 top: targetOffset.top, 2419 width: targetWidth, 2420 height: targetHeight 2421 }, 2422 element: { 2423 element: elem, 2424 left: position.left, 2425 top: position.top, 2426 width: elemWidth, 2427 height: elemHeight 2428 }, 2429 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", 2430 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" 2431 }; 2432 if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) { 2433 feedback.horizontal = "center"; 2434 } 2435 if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) { 2436 feedback.vertical = "middle"; 2437 } 2438 if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) { 2439 feedback.important = "horizontal"; 2440 } else { 2441 feedback.important = "vertical"; 2442 } 2443 options.using.call( this, props, feedback ); 2444 }; 2445 } 2446 2447 elem.offset( $.extend( position, { using: using } ) ); 2448 }); 2449}; 2450 2451$.ui.position = { 2452 fit: { 2453 left: function( position, data ) { 2454 var within = data.within, 2455 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, 2456 outerWidth = within.width, 2457 collisionPosLeft = position.left - data.collisionPosition.marginLeft, 2458 overLeft = withinOffset - collisionPosLeft, 2459 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, 2460 newOverRight; 2461 2462 // element is wider than within 2463 if ( data.collisionWidth > outerWidth ) { 2464 // element is initially over the left side of within 2465 if ( overLeft > 0 && overRight <= 0 ) { 2466 newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset; 2467 position.left += overLeft - newOverRight; 2468 // element is initially over right side of within 2469 } else if ( overRight > 0 && overLeft <= 0 ) { 2470 position.left = withinOffset; 2471 // element is initially over both left and right sides of within 2472 } else { 2473 if ( overLeft > overRight ) { 2474 position.left = withinOffset + outerWidth - data.collisionWidth; 2475 } else { 2476 position.left = withinOffset; 2477 } 2478 } 2479 // too far left -> align with left edge 2480 } else if ( overLeft > 0 ) { 2481 position.left += overLeft; 2482 // too far right -> align with right edge 2483 } else if ( overRight > 0 ) { 2484 position.left -= overRight; 2485 // adjust based on position and margin 2486 } else { 2487 position.left = max( position.left - collisionPosLeft, position.left ); 2488 } 2489 }, 2490 top: function( position, data ) { 2491 var within = data.within, 2492 withinOffset = within.isWindow ? within.scrollTop : within.offset.top, 2493 outerHeight = data.within.height, 2494 collisionPosTop = position.top - data.collisionPosition.marginTop, 2495 overTop = withinOffset - collisionPosTop, 2496 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, 2497 newOverBottom; 2498 2499 // element is taller than within 2500 if ( data.collisionHeight > outerHeight ) { 2501 // element is initially over the top of within 2502 if ( overTop > 0 && overBottom <= 0 ) { 2503 newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset; 2504 position.top += overTop - newOverBottom; 2505 // element is initially over bottom of within 2506 } else if ( overBottom > 0 && overTop <= 0 ) { 2507 position.top = withinOffset; 2508 // element is initially over both top and bottom of within 2509 } else { 2510 if ( overTop > overBottom ) { 2511 position.top = withinOffset + outerHeight - data.collisionHeight; 2512 } else { 2513 position.top = withinOffset; 2514 } 2515 } 2516 // too far up -> align with top 2517 } else if ( overTop > 0 ) { 2518 position.top += overTop; 2519 // too far down -> align with bottom edge 2520 } else if ( overBottom > 0 ) { 2521 position.top -= overBottom; 2522 // adjust based on position and margin 2523 } else { 2524 position.top = max( position.top - collisionPosTop, position.top ); 2525 } 2526 } 2527 }, 2528 flip: { 2529 left: function( position, data ) { 2530 var within = data.within, 2531 withinOffset = within.offset.left + within.scrollLeft, 2532 outerWidth = within.width, 2533 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, 2534 collisionPosLeft = position.left - data.collisionPosition.marginLeft, 2535 overLeft = collisionPosLeft - offsetLeft, 2536 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, 2537 myOffset = data.my[ 0 ] === "left" ? 2538 -data.elemWidth : 2539 data.my[ 0 ] === "right" ? 2540 data.elemWidth : 2541 0, 2542 atOffset = data.at[ 0 ] === "left" ? 2543 data.targetWidth : 2544 data.at[ 0 ] === "right" ? 2545 -data.targetWidth : 2546 0, 2547 offset = -2 * data.offset[ 0 ], 2548 newOverRight, 2549 newOverLeft; 2550 2551 if ( overLeft < 0 ) { 2552 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset; 2553 if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) { 2554 position.left += myOffset + atOffset + offset; 2555 } 2556 } 2557 else if ( overRight > 0 ) { 2558 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft; 2559 if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) { 2560 position.left += myOffset + atOffset + offset; 2561 } 2562 } 2563 }, 2564 top: function( position, data ) { 2565 var within = data.within, 2566 withinOffset = within.offset.top + within.scrollTop, 2567 outerHeight = within.height, 2568 offsetTop = within.isWindow ? within.scrollTop : within.offset.top, 2569 collisionPosTop = position.top - data.collisionPosition.marginTop, 2570 overTop = collisionPosTop - offsetTop, 2571 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, 2572 top = data.my[ 1 ] === "top", 2573 myOffset = top ? 2574 -data.elemHeight : 2575 data.my[ 1 ] === "bottom" ? 2576 data.elemHeight : 2577 0, 2578 atOffset = data.at[ 1 ] === "top" ? 2579 data.targetHeight : 2580 data.at[ 1 ] === "bottom" ? 2581 -data.targetHeight : 2582 0, 2583 offset = -2 * data.offset[ 1 ], 2584 newOverTop, 2585 newOverBottom; 2586 if ( overTop < 0 ) { 2587 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset; 2588 if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) { 2589 position.top += myOffset + atOffset + offset; 2590 } 2591 } 2592 else if ( overBottom > 0 ) { 2593 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop; 2594 if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) { 2595 position.top += myOffset + atOffset + offset; 2596 } 2597 } 2598 } 2599 }, 2600 flipfit: { 2601 left: function() { 2602 $.ui.position.flip.left.apply( this, arguments ); 2603 $.ui.position.fit.left.apply( this, arguments ); 2604 }, 2605 top: function() { 2606 $.ui.position.flip.top.apply( this, arguments ); 2607 $.ui.position.fit.top.apply( this, arguments ); 2608 } 2609 } 2610}; 2611 2612// fraction support test 2613(function () { 2614 var testElement, testElementParent, testElementStyle, offsetLeft, i, 2615 body = document.getElementsByTagName( "body" )[ 0 ], 2616 div = document.createElement( "div" ); 2617 2618 //Create a "fake body" for testing based on method used in jQuery.support 2619 testElement = document.createElement( body ? "div" : "body" ); 2620 testElementStyle = { 2621 visibility: "hidden", 2622 width: 0, 2623 height: 0, 2624 border: 0, 2625 margin: 0, 2626 background: "none" 2627 }; 2628 if ( body ) { 2629 $.extend( testElementStyle, { 2630 position: "absolute", 2631 left: "-1000px", 2632 top: "-1000px" 2633 }); 2634 } 2635 for ( i in testElementStyle ) { 2636 testElement.style[ i ] = testElementStyle[ i ]; 2637 } 2638 testElement.appendChild( div ); 2639 testElementParent = body || document.documentElement; 2640 testElementParent.insertBefore( testElement, testElementParent.firstChild ); 2641 2642 div.style.cssText = "position: absolute; left: 10.7432222px;"; 2643 2644 offsetLeft = $( div ).offset().left; 2645 $.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11; 2646 2647 testElement.innerHTML = ""; 2648 testElementParent.removeChild( testElement ); 2649})(); 2650 2651}( _4ORMAT.$ ) ); 2652(function( $, undefined ) { 2653 2654var uid = 0, 2655 hideProps = {}, 2656 showProps = {}; 2657 2658hideProps.height = hideProps.paddingTop = hideProps.paddingBottom = 2659 hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide"; 2660showProps.height = showProps.paddingTop = showProps.paddingBottom = 2661 showProps.borderTopWidth = showProps.borderBottomWidth = "show"; 2662 2663$.widget( "ui.accordion", { 2664 version: "1.10.4", 2665 options: { 2666 active: 0, 2667 animate: {}, 2668 collapsible: false, 2669 event: "click", 2670 header: "> li > :first-child,> :not(li):even", 2671 heightStyle: "auto", 2672 icons: { 2673 activeHeader: "ui-icon-triangle-1-s", 2674 header: "ui-icon-triangle-1-e" 2675 }, 2676 2677 // callbacks 2678 activate: null, 2679 beforeActivate: null 2680 }, 2681 2682 _create: function() { 2683 var options = this.options; 2684 this.prevShow = this.prevHide = $(); 2685 this.element.addClass( "ui-accordion ui-widget ui-helper-reset" ) 2686 // ARIA 2687 .attr( "role", "tablist" ); 2688 2689 // don't allow collapsible: false and active: false / null 2690 if ( !options.collapsible && (options.active === false || options.active == null) ) { 2691 options.active = 0; 2692 } 2693 2694 this._processPanels(); 2695 // handle negative values 2696 if ( options.active < 0 ) { 2697 options.active += this.headers.length; 2698 } 2699 this._refresh(); 2700 }, 2701 2702 _getCreateEventData: function() { 2703 return { 2704 header: this.active, 2705 panel: !this.active.length ? $() : this.active.next(), 2706 content: !this.active.length ? $() : this.active.next() 2707 }; 2708 }, 2709 2710 _createIcons: function() { 2711 var icons = this.options.icons; 2712 if ( icons ) { 2713 $( "<span>" ) 2714 .addClass( "ui-accordion-header-icon ui-icon " + icons.header ) 2715 .prependTo( this.headers ); 2716 this.active.children( ".ui-accordion-header-icon" ) 2717 .removeClass( icons.header ) 2718 .addClass( icons.activeHeader ); 2719 this.headers.addClass( "ui-accordion-icons" ); 2720 } 2721 }, 2722 2723 _destroyIcons: function() { 2724 this.headers 2725 .removeClass( "ui-accordion-icons" ) 2726 .children( ".ui-accordion-header-icon" ) 2727 .remove(); 2728 }, 2729 2730 _destroy: function() { 2731 var contents; 2732 2733 // clean up main element 2734 this.element 2735 .removeClass( "ui-accordion ui-widget ui-helper-reset" ) 2736 .removeAttr( "role" ); 2737 2738 // clean up headers 2739 this.headers 2740 .removeClass( "ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" ) 2741 .removeAttr( "role" ) 2742 .removeAttr( "aria-expanded" ) 2743 .removeAttr( "aria-selected" ) 2744 .removeAttr( "aria-controls" ) 2745 .removeAttr( "tabIndex" ) 2746 .each(function() { 2747 if ( /^ui-accordion/.test( this.id ) ) { 2748 this.removeAttribute( "id" ); 2749 } 2750 }); 2751 this._destroyIcons(); 2752 2753 // clean up content panels 2754 contents = this.headers.next() 2755 .css( "display", "" ) 2756 .removeAttr( "role" ) 2757 .removeAttr( "aria-hidden" ) 2758 .removeAttr( "aria-labelledby" ) 2759 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" ) 2760 .each(function() { 2761 if ( /^ui-accordion/.test( this.id ) ) { 2762 this.removeAttribute( "id" ); 2763 } 2764 }); 2765 if ( this.options.heightStyle !== "content" ) { 2766 contents.css( "height", "" ); 2767 } 2768 }, 2769 2770 _setOption: function( key, value ) { 2771 if ( key === "active" ) { 2772 // _activate() will handle invalid values and update this.options 2773 this._activate( value ); 2774 return; 2775 } 2776 2777 if ( key === "event" ) { 2778 if ( this.options.event ) { 2779 this._off( this.headers, this.options.event ); 2780 } 2781 this._setupEvents( value ); 2782 } 2783 2784 this._super( key, value ); 2785 2786 // setting collapsible: false while collapsed; open first panel 2787 if ( key === "collapsible" && !value && this.options.active === false ) { 2788 this._activate( 0 ); 2789 } 2790 2791 if ( key === "icons" ) { 2792 this._destroyIcons(); 2793 if ( value ) { 2794 this._createIcons(); 2795 } 2796 } 2797 2798 // #5332 - opacity doesn't cascade to positioned elements in IE 2799 // so we need to add the disabled class to the headers and panels 2800 if ( key === "disabled" ) { 2801 this.headers.add( this.headers.next() ) 2802 .toggleClass( "ui-state-disabled", !!value ); 2803 } 2804 }, 2805 2806 _keydown: function( event ) { 2807 if ( event.altKey || event.ctrlKey ) { 2808 return; 2809 } 2810 2811 var keyCode = $.ui.keyCode, 2812 length = this.headers.length, 2813 currentIndex = this.headers.index( event.target ), 2814 toFocus = false; 2815 2816 switch ( event.keyCode ) { 2817 case keyCode.RIGHT: 2818 case keyCode.DOWN: 2819 toFocus = this.headers[ ( currentIndex + 1 ) % length ]; 2820 break; 2821 case keyCode.LEFT: 2822 case keyCode.UP: 2823 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; 2824 break; 2825 case keyCode.SPACE: 2826 case keyCode.ENTER: 2827 this._eventHandler( event ); 2828 break; 2829 case keyCode.HOME: 2830 toFocus = this.headers[ 0 ]; 2831 break; 2832 case keyCode.END: 2833 toFocus = this.headers[ length - 1 ]; 2834 break; 2835 } 2836 2837 if ( toFocus ) { 2838 $( event.target ).attr( "tabIndex", -1 ); 2839 $( toFocus ).attr( "tabIndex", 0 ); 2840 toFocus.focus(); 2841 event.preventDefault(); 2842 } 2843 }, 2844 2845 _panelKeyDown : function( event ) { 2846 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) { 2847 $( event.currentTarget ).prev().focus(); 2848 } 2849 }, 2850 2851 refresh: function() { 2852 var options = this.options; 2853 this._processPanels(); 2854 2855 // was collapsed or no panel 2856 if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) { 2857 options.active = false; 2858 this.active = $(); 2859 // active false only when collapsible is true 2860 } else if ( options.active === false ) { 2861 this._activate( 0 ); 2862 // was active, but active panel is gone 2863 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { 2864 // all remaining panel are disabled 2865 if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) { 2866 options.active = false; 2867 this.active = $(); 2868 // activate previous panel 2869 } else { 2870 this._activate( Math.max( 0, options.active - 1 ) ); 2871 } 2872 // was active, active panel still exists 2873 } else { 2874 // make sure active index is correct 2875 options.active = this.headers.index( this.active ); 2876 } 2877 2878 this._destroyIcons(); 2879 2880 this._refresh(); 2881 }, 2882 2883 _processPanels: function() { 2884 this.headers = this.element.find( this.options.header ) 2885 .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" ); 2886 2887 this.headers.next() 2888 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ) 2889 .filter(":not(.ui-accordion-content-active)") 2890 .hide(); 2891 }, 2892 2893 _refresh: function() { 2894 var maxHeight, 2895 options = this.options, 2896 heightStyle = options.heightStyle, 2897 parent = this.element.parent(), 2898 accordionId = this.accordionId = "ui-accordion-" + 2899 (this.element.attr( "id" ) || ++uid); 2900 2901 this.active = this._findActive( options.active ) 2902 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ) 2903 .removeClass( "ui-corner-all" ); 2904 this.active.next() 2905 .addClass( "ui-accordion-content-active" ) 2906 .show(); 2907 2908 this.headers 2909 .attr( "role", "tab" ) 2910 .each(function( i ) { 2911 var header = $( this ), 2912 headerId = header.attr( "id" ), 2913 panel = header.next(), 2914 panelId = panel.attr( "id" ); 2915 if ( !headerId ) { 2916 headerId = accordionId + "-header-" + i; 2917 header.attr( "id", headerId ); 2918 } 2919 if ( !panelId ) { 2920 panelId = accordionId + "-panel-" + i; 2921 panel.attr( "id", panelId ); 2922 } 2923 header.attr( "aria-controls", panelId ); 2924 panel.attr( "aria-labelledby", headerId ); 2925 }) 2926 .next() 2927 .attr( "role", "tabpanel" ); 2928 2929 this.headers 2930 .not( this.active ) 2931 .attr({ 2932 "aria-selected": "false", 2933 "aria-expanded": "false", 2934 tabIndex: -1 2935 }) 2936 .next() 2937 .attr({ 2938 "aria-hidden": "true" 2939 }) 2940 .hide(); 2941 2942 // make sure at least one header is in the tab order 2943 if ( !this.active.length ) { 2944 this.headers.eq( 0 ).attr( "tabIndex", 0 ); 2945 } else { 2946 this.active.attr({ 2947 "aria-selected": "true", 2948 "aria-expanded": "true", 2949 tabIndex: 0 2950 }) 2951 .next() 2952 .attr({ 2953 "aria-hidden": "false" 2954 }); 2955 } 2956 2957 this._createIcons(); 2958 2959 this._setupEvents( options.event ); 2960 2961 if ( heightStyle === "fill" ) { 2962 maxHeight = parent.height(); 2963 this.element.siblings( ":visible" ).each(function() { 2964 var elem = $( this ), 2965 position = elem.css( "position" ); 2966 2967 if ( position === "absolute" || position === "fixed" ) { 2968 return; 2969 } 2970 maxHeight -= elem.outerHeight( true ); 2971 }); 2972 2973 this.headers.each(function() { 2974 maxHeight -= $( this ).outerHeight( true ); 2975 }); 2976 2977 this.headers.next() 2978 .each(function() { 2979 $( this ).height( Math.max( 0, maxHeight - 2980 $( this ).innerHeight() + $( this ).height() ) ); 2981 }) 2982 .css( "overflow", "auto" ); 2983 } else if ( heightStyle === "auto" ) { 2984 maxHeight = 0; 2985 this.headers.next() 2986 .each(function() { 2987 maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() ); 2988 }) 2989 .height( maxHeight ); 2990 } 2991 }, 2992 2993 _activate: function( index ) { 2994 var active = this._findActive( index )[ 0 ]; 2995 2996 // trying to activate the already active panel 2997 if ( active === this.active[ 0 ] ) { 2998 return; 2999 } 3000 3001 // trying to collapse, simulate a click on the currently active header 3002 active = active || this.active[ 0 ]; 3003 3004 this._eventHandler({ 3005 target: active, 3006 currentTarget: active, 3007 preventDefault: $.noop 3008 }); 3009 }, 3010 3011 _findActive: function( selector ) { 3012 return typeof selector === "number" ? this.headers.eq( selector ) : $(); 3013 }, 3014 3015 _setupEvents: function( event ) { 3016 var events = { 3017 keydown: "_keydown" 3018 }; 3019 if ( event ) { 3020 $.each( event.split(" "), function( index, eventName ) { 3021 events[ eventName ] = "_eventHandler"; 3022 }); 3023 } 3024 3025 this._off( this.headers.add( this.headers.next() ) ); 3026 this._on( this.headers, events ); 3027 this._on( this.headers.next(), { keydown: "_panelKeyDown" }); 3028 this._hoverable( this.headers ); 3029 this._focusable( this.headers ); 3030 }, 3031 3032 _eventHandler: function( event ) { 3033 var options = this.options, 3034 active = this.active, 3035 clicked = $( event.currentTarget ), 3036 clickedIsActive = clicked[ 0 ] === active[ 0 ], 3037 collapsing = clickedIsActive && options.collapsible, 3038 toShow = collapsing ? $() : clicked.next(), 3039 toHide = active.next(), 3040 eventData = { 3041 oldHeader: active, 3042 oldPanel: toHide, 3043 newHeader: collapsing ? $() : clicked, 3044 newPanel: toShow 3045 }; 3046 3047 event.preventDefault(); 3048 3049 if ( 3050 // click on active header, but not collapsible 3051 ( clickedIsActive && !options.collapsible ) || 3052 // allow canceling activation 3053 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 3054 return; 3055 } 3056 3057 options.active = collapsing ? false : this.headers.index( clicked ); 3058 3059 // when the call to ._toggle() comes after the class changes 3060 // it causes a very odd bug in IE 8 (see #6720) 3061 this.active = clickedIsActive ? $() : clicked; 3062 this._toggle( eventData ); 3063 3064 // switch classes 3065 // corner classes on the previously active header stay after the animation 3066 active.removeClass( "ui-accordion-header-active ui-state-active" ); 3067 if ( options.icons ) { 3068 active.children( ".ui-accordion-header-icon" ) 3069 .removeClass( options.icons.activeHeader ) 3070 .addClass( options.icons.header ); 3071 } 3072 3073 if ( !clickedIsActive ) { 3074 clicked 3075 .removeClass( "ui-corner-all" ) 3076 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ); 3077 if ( options.icons ) { 3078 clicked.children( ".ui-accordion-header-icon" ) 3079 .removeClass( options.icons.header ) 3080 .addClass( options.icons.activeHeader ); 3081 } 3082 3083 clicked 3084 .next() 3085 .addClass( "ui-accordion-content-active" ); 3086 } 3087 }, 3088 3089 _toggle: function( data ) { 3090 var toShow = data.newPanel, 3091 toHide = this.prevShow.length ? this.prevShow : data.oldPanel; 3092 3093 // handle activating a panel during the animation for another activation 3094 this.prevShow.add( this.prevHide ).stop( true, true ); 3095 this.prevShow = toShow; 3096 this.prevHide = toHide; 3097 3098 if ( this.options.animate ) { 3099 this._animate( toShow, toHide, data ); 3100 } else { 3101 toHide.hide(); 3102 toShow.show(); 3103 this._toggleComplete( data ); 3104 } 3105 3106 toHide.attr({ 3107 "aria-hidden": "true" 3108 }); 3109 toHide.prev().attr( "aria-selected", "false" ); 3110 // if we're switching panels, remove the old header from the tab order 3111 // if we're opening from collapsed state, remove the previous header from the tab order 3112 // if we're collapsing, then keep the collapsing header in the tab order 3113 if ( toShow.length && toHide.length ) { 3114 toHide.prev().attr({ 3115 "tabIndex": -1, 3116 "aria-expanded": "false" 3117 }); 3118 } else if ( toShow.length ) { 3119 this.headers.filter(function() { 3120 return $( this ).attr( "tabIndex" ) === 0; 3121 }) 3122 .attr( "tabIndex", -1 ); 3123 } 3124 3125 toShow 3126 .attr( "aria-hidden", "false" ) 3127 .prev() 3128 .attr({ 3129 "aria-selected": "true", 3130 tabIndex: 0, 3131 "aria-expanded": "true" 3132 }); 3133 }, 3134 3135 _animate: function( toShow, toHide, data ) { 3136 var total, easing, duration, 3137 that = this, 3138 adjust = 0, 3139 down = toShow.length && 3140 ( !toHide.length || ( toShow.index() < toHide.index() ) ), 3141 animate = this.options.animate || {}, 3142 options = down && animate.down || animate, 3143 complete = function() { 3144 that._toggleComplete( data ); 3145 }; 3146 3147 if ( typeof options === "number" ) { 3148 duration = options; 3149 } 3150 if ( typeof options === "string" ) { 3151 easing = options; 3152 } 3153 // fall back from options to animation in case of partial down settings 3154 easing = easing || options.easing || animate.easing; 3155 duration = duration || options.duration || animate.duration; 3156 3157 if ( !toHide.length ) { 3158 return toShow.animate( showProps, duration, easing, complete ); 3159 } 3160 if ( !toShow.length ) { 3161 return toHide.animate( hideProps, duration, easing, complete ); 3162 } 3163 3164 total = toShow.show().outerHeight(); 3165 toHide.animate( hideProps, { 3166 duration: duration, 3167 easing: easing, 3168 step: function( now, fx ) { 3169 fx.now = Math.round( now ); 3170 } 3171 }); 3172 toShow 3173 .hide() 3174 .animate( showProps, { 3175 duration: duration, 3176 easing: easing, 3177 complete: complete, 3178 step: function( now, fx ) { 3179 fx.now = Math.round( now ); 3180 if ( fx.prop !== "height" ) { 3181 adjust += fx.now; 3182 } else if ( that.options.heightStyle !== "content" ) { 3183 fx.now = Math.round( total - toHide.outerHeight() - adjust ); 3184 adjust = 0; 3185 } 3186 } 3187 }); 3188 }, 3189 3190 _toggleComplete: function( data ) { 3191 var toHide = data.oldPanel; 3192 3193 toHide 3194 .removeClass( "ui-accordion-content-active" ) 3195 .prev() 3196 .removeClass( "ui-corner-top" ) 3197 .addClass( "ui-corner-all" ); 3198 3199 // Work around for rendering bug in IE (#5421) 3200 if ( toHide.length ) { 3201 toHide.parent()[0].className = toHide.parent()[0].className; 3202 } 3203 this._trigger( "activate", null, data ); 3204 } 3205}); 3206 3207})( _4ORMAT.$ ); 3208(function( $, undefined ) { 3209 3210$.widget( "ui.autocomplete", { 3211 version: "1.10.4", 3212 defaultElement: "<input>", 3213 options: { 3214 appendTo: null, 3215 autoFocus: false, 3216 delay: 300, 3217 minLength: 1, 3218 position: { 3219 my: "left top", 3220 at: "left bottom", 3221 collision: "none" 3222 }, 3223 source: null, 3224 3225 // callbacks 3226 change: null, 3227 close: null, 3228 focus: null, 3229 open: null, 3230 response: null, 3231 search: null, 3232 select: null 3233 }, 3234 3235 requestIndex: 0, 3236 pending: 0, 3237 3238 _create: function() { 3239 // Some browsers only repeat keydown events, not keypress events, 3240 // so we use the suppressKeyPress flag to determine if we've already 3241 // handled the keydown event. #7269 3242 // Unfortunately the code for & in keypress is the same as the up arrow, 3243 // so we use the suppressKeyPressRepeat flag to avoid handling keypress 3244 // events when we know the keydown event was used to modify the 3245 // search term. #7799 3246 var suppressKeyPress, suppressKeyPressRepeat, suppressInput, 3247 nodeName = this.element[0].nodeName.toLowerCase(), 3248 isTextarea = nodeName === "textarea", 3249 isInput = nodeName === "input"; 3250 3251 this.isMultiLine = 3252 // Textareas are always multi-line 3253 isTextarea ? true : 3254 // Inputs are always single-line, even if inside a contentEditable element 3255 // IE also treats inputs as contentEditable 3256 isInput ? false : 3257 // All other element types are determined by whether or not they're contentEditable 3258 this.element.prop( "isContentEditable" ); 3259 3260 this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ]; 3261 this.isNewMenu = true; 3262 3263 this.element 3264 .addClass( "ui-autocomplete-input" ) 3265 .attr( "autocomplete", "off" ); 3266 3267 this._on( this.element, { 3268 keydown: function( event ) { 3269 if ( this.element.prop( "readOnly" ) ) { 3270 suppressKeyPress = true; 3271 suppressInput = true; 3272 suppressKeyPressRepeat = true; 3273 return; 3274 } 3275 3276 suppressKeyPress = false; 3277 suppressInput = false; 3278 suppressKeyPressRepeat = false; 3279 var keyCode = $.ui.keyCode; 3280 switch( event.keyCode ) { 3281 case keyCode.PAGE_UP: 3282 suppressKeyPress = true; 3283 this._move( "previousPage", event ); 3284 break; 3285 case keyCode.PAGE_DOWN: 3286 suppressKeyPress = true; 3287 this._move( "nextPage", event ); 3288 break; 3289 case keyCode.UP: 3290 suppressKeyPress = true; 3291 this._keyEvent( "previous", event ); 3292 break; 3293 case keyCode.DOWN: 3294 suppressKeyPress = true; 3295 this._keyEvent( "next", event ); 3296 break; 3297 case keyCode.ENTER: 3298 case keyCode.NUMPAD_ENTER: 3299 // when menu is open and has focus 3300 if ( this.menu.active ) { 3301 // #6055 - Opera still allows the keypress to occur 3302 // which causes forms to submit 3303 suppressKeyPress = true; 3304 event.preventDefault(); 3305 this.menu.select( event ); 3306 } 3307 break; 3308 case keyCode.TAB: 3309 if ( this.menu.active ) { 3310 this.menu.select( event ); 3311 } 3312 break; 3313 case keyCode.ESCAPE: 3314 if ( this.menu.element.is( ":visible" ) ) { 3315 this._value( this.term ); 3316 this.close( event ); 3317 // Different browsers have different default behavior for escape 3318 // Single press can mean undo or clear 3319 // Double press in IE means clear the whole form 3320 event.preventDefault(); 3321 } 3322 break; 3323 default: 3324 suppressKeyPressRepeat = true; 3325 // search timeout should be triggered before the input value is changed 3326 this._searchTimeout( event ); 3327 break; 3328 } 3329 }, 3330 keypress: function( event ) { 3331 if ( suppressKeyPress ) { 3332 suppressKeyPress = false; 3333 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { 3334 event.preventDefault(); 3335 } 3336 return; 3337 } 3338 if ( suppressKeyPressRepeat ) { 3339 return; 3340 } 3341 3342 // replicate some key handlers to allow them to repeat in Firefox and Opera 3343 var keyCode = $.ui.keyCode; 3344 switch( event.keyCode ) { 3345 case keyCode.PAGE_UP: 3346 this._move( "previousPage", event ); 3347 break; 3348 case keyCode.PAGE_DOWN: 3349 this._move( "nextPage", event ); 3350 break; 3351 case keyCode.UP: 3352 this._keyEvent( "previous", event ); 3353 break; 3354 case keyCode.DOWN: 3355 this._keyEvent( "next", event ); 3356 break; 3357 } 3358 }, 3359 input: function( event ) { 3360 if ( suppressInput ) { 3361 suppressInput = false; 3362 event.preventDefault(); 3363 return; 3364 } 3365 this._searchTimeout( event ); 3366 }, 3367 focus: function() { 3368 this.selectedItem = null; 3369 this.previous = this._value(); 3370 }, 3371 blur: function( event ) { 3372 if ( this.cancelBlur ) { 3373 delete this.cancelBlur; 3374 return; 3375 } 3376 3377 clearTimeout( this.searching ); 3378 this.close( event ); 3379 this._change( event ); 3380 } 3381 }); 3382 3383 this._initSource(); 3384 this.menu = $( "<ul>" ) 3385 .addClass( "ui-autocomplete ui-front" ) 3386 .appendTo( this._appendTo() ) 3387 .menu({ 3388 // disable ARIA support, the live region takes care of that 3389 role: null 3390 }) 3391 .hide() 3392 .data( "ui-menu" ); 3393 3394 this._on( this.menu.element, { 3395 mousedown: function( event ) { 3396 // prevent moving focus out of the text field 3397 event.preventDefault(); 3398 3399 // IE doesn't prevent moving focus even with event.preventDefault() 3400 // so we set a flag to know when we should ignore the blur event 3401 this.cancelBlur = true; 3402 this._delay(function() { 3403 delete this.cancelBlur; 3404 }); 3405 3406 // clicking on the scrollbar causes focus to shift to the body 3407 // but we can't detect a mouseup or a click immediately afterward 3408 // so we have to track the next mousedown and close the menu if 3409 // the user clicks somewhere outside of the autocomplete 3410 var menuElement = this.menu.element[ 0 ]; 3411 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { 3412 this._delay(function() { 3413 var that = this; 3414 this.document.one( "mousedown", function( event ) { 3415 if ( event.target !== that.element[ 0 ] && 3416 event.target !== menuElement && 3417 !$.contains( menuElement, event.target ) ) { 3418 that.close(); 3419 } 3420 }); 3421 }); 3422 } 3423 }, 3424 menufocus: function( event, ui ) { 3425 // support: Firefox 3426 // Prevent accidental activation of menu items in Firefox (#7024 #9118) 3427 if ( this.isNewMenu ) { 3428 this.isNewMenu = false; 3429 if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) { 3430 this.menu.blur(); 3431 3432 this.document.one( "mousemove", function() { 3433 $( event.target ).trigger( event.originalEvent ); 3434 }); 3435 3436 return; 3437 } 3438 } 3439 3440 var item = ui.item.data( "ui-autocomplete-item" ); 3441 if ( false !== this._trigger( "focus", event, { item: item } ) ) { 3442 // use value to match what will end up in the input, if it was a key event 3443 if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) { 3444 this._value( item.value ); 3445 } 3446 } else { 3447 // Normally the input is populated with the item's value as the 3448 // menu is navigated, causing screen readers to notice a change and 3449 // announce the item. Since the focus event was canceled, this doesn't 3450 // happen, so we update the live region so that screen readers can 3451 // still notice the change and announce it. 3452 this.liveRegion.text( item.value ); 3453 } 3454 }, 3455 menuselect: function( event, ui ) { 3456 var item = ui.item.data( "ui-autocomplete-item" ), 3457 previous = this.previous; 3458 3459 // only trigger when focus was lost (click on menu) 3460 if ( this.element[0] !== this.document[0].activeElement ) { 3461 this.element.focus(); 3462 this.previous = previous; 3463 // #6109 - IE triggers two focus events and the second 3464 // is asynchronous, so we need to reset the previous 3465 // term synchronously and asynchronously :-( 3466 this._delay(function() { 3467 this.previous = previous; 3468 this.selectedItem = item; 3469 }); 3470 } 3471 3472 if ( false !== this._trigger( "select", event, { item: item } ) ) { 3473 this._value( item.value ); 3474 } 3475 // reset the term after the select event 3476 // this allows custom select handling to work properly 3477 this.term = this._value(); 3478 3479 this.close( event ); 3480 this.selectedItem = item; 3481 } 3482 }); 3483 3484 this.liveRegion = $( "<span>", { 3485 role: "status", 3486 "aria-live": "polite" 3487 }) 3488 .addClass( "ui-helper-hidden-accessible" ) 3489 .insertBefore( this.element ); 3490 3491 // turning off autocomplete prevents the browser from remembering the 3492 // value when navigating through history, so we re-enable autocomplete 3493 // if the page is unloaded before the widget is destroyed. #7790 3494 this._on( this.window, { 3495 beforeunload: function() { 3496 this.element.removeAttr( "autocomplete" ); 3497 } 3498 }); 3499 }, 3500 3501 _destroy: function() { 3502 clearTimeout( this.searching ); 3503 this.element 3504 .removeClass( "ui-autocomplete-input" ) 3505 .removeAttr( "autocomplete" ); 3506 this.menu.element.remove(); 3507 this.liveRegion.remove(); 3508 }, 3509 3510 _setOption: function( key, value ) { 3511 this._super( key, value ); 3512 if ( key === "source" ) { 3513 this._initSource(); 3514 } 3515 if ( key === "appendTo" ) { 3516 this.menu.element.appendTo( this._appendTo() ); 3517 } 3518 if ( key === "disabled" && value && this.xhr ) { 3519 this.xhr.abort(); 3520 } 3521 }, 3522 3523 _appendTo: function() { 3524 var element = this.options.appendTo; 3525 3526 if ( element ) { 3527 element = element.jquery || element.nodeType ? 3528 $( element ) : 3529 this.document.find( element ).eq( 0 ); 3530 } 3531 3532 if ( !element ) { 3533 element = this.element.closest( ".ui-front" ); 3534 } 3535 3536 if ( !element.length ) { 3537 element = this.document[0].body; 3538 } 3539 3540 return element; 3541 }, 3542 3543 _initSource: function() { 3544 var array, url, 3545 that = this; 3546 if ( $.isArray(this.options.source) ) { 3547 array = this.options.source; 3548 this.source = function( request, response ) { 3549 response( $.ui.autocomplete.filter( array, request.term ) ); 3550 }; 3551 } else if ( typeof this.options.source === "string" ) { 3552 url = this.options.source; 3553 this.source = function( request, response ) { 3554 if ( that.xhr ) { 3555 that.xhr.abort(); 3556 } 3557 that.xhr = $.ajax({ 3558 url: url, 3559 data: request, 3560 dataType: "json", 3561 success: function( data ) { 3562 response( data ); 3563 }, 3564 error: function() { 3565 response( [] ); 3566 } 3567 }); 3568 }; 3569 } else { 3570 this.source = this.options.source; 3571 } 3572 }, 3573 3574 _searchTimeout: function( event ) { 3575 clearTimeout( this.searching ); 3576 this.searching = this._delay(function() { 3577 // only search if the value has changed 3578 if ( this.term !== this._value() ) { 3579 this.selectedItem = null; 3580 this.search( null, event ); 3581 } 3582 }, this.options.delay ); 3583 }, 3584 3585 search: function( value, event ) { 3586 value = value != null ? value : this._value(); 3587 3588 // always save the actual value, not the one passed as an argument 3589 this.term = this._value(); 3590 3591 if ( value.length < this.options.minLength ) { 3592 return this.close( event ); 3593 } 3594 3595 if ( this._trigger( "search", event ) === false ) { 3596 return; 3597 } 3598 3599 return this._search( value ); 3600 }, 3601 3602 _search: function( value ) { 3603 this.pending++; 3604 this.element.addClass( "ui-autocomplete-loading" ); 3605 this.cancelSearch = false; 3606 3607 this.source( { term: value }, this._response() ); 3608 }, 3609 3610 _response: function() { 3611 var index = ++this.requestIndex; 3612 3613 return $.proxy(function( content ) { 3614 if ( index === this.requestIndex ) { 3615 this.__response( content ); 3616 } 3617 3618 this.pending--; 3619 if ( !this.pending ) { 3620 this.element.removeClass( "ui-autocomplete-loading" ); 3621 } 3622 }, this ); 3623 }, 3624 3625 __response: function( content ) { 3626 if ( content ) { 3627 content = this._normalize( content ); 3628 } 3629 this._trigger( "response", null, { content: content } ); 3630 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) { 3631 this._suggest( content ); 3632 this._trigger( "open" ); 3633 } else { 3634 // use ._close() instead of .close() so we don't cancel future searches 3635 this._close(); 3636 } 3637 }, 3638 3639 close: function( event ) { 3640 this.cancelSearch = true; 3641 this._close( event ); 3642 }, 3643 3644 _close: function( event ) { 3645 if ( this.menu.element.is( ":visible" ) ) { 3646 this.menu.element.hide(); 3647 this.menu.blur(); 3648 this.isNewMenu = true; 3649 this._trigger( "close", event ); 3650 } 3651 }, 3652 3653 _change: function( event ) { 3654 if ( this.previous !== this._value() ) { 3655 this._trigger( "change", event, { item: this.selectedItem } ); 3656 } 3657 }, 3658 3659 _normalize: function( items ) { 3660 // assume all items have the right format when the first item is complete 3661 if ( items.length && items[0].label && items[0].value ) { 3662 return items; 3663 } 3664 return $.map( items, function( item ) { 3665 if ( typeof item === "string" ) { 3666 return { 3667 label: item, 3668 value: item 3669 }; 3670 } 3671 return $.extend({ 3672 label: item.label || item.value, 3673 value: item.value || item.label 3674 }, item ); 3675 }); 3676 }, 3677 3678 _suggest: function( items ) { 3679 var ul = this.menu.element.empty(); 3680 this._renderMenu( ul, items ); 3681 this.isNewMenu = true; 3682 this.menu.refresh(); 3683 3684 // size and position menu 3685 ul.show(); 3686 this._resizeMenu(); 3687 ul.position( $.extend({ 3688 of: this.element 3689 }, this.options.position )); 3690 3691 if ( this.options.autoFocus ) { 3692 this.menu.next(); 3693 } 3694 }, 3695 3696 _resizeMenu: function() { 3697 var ul = this.menu.element; 3698 ul.outerWidth( Math.max( 3699 // Firefox wraps long text (possibly a rounding bug) 3700 // so we add 1px to avoid the wrapping (#7513) 3701 ul.width( "" ).outerWidth() + 1, 3702 this.element.outerWidth() 3703 ) ); 3704 }, 3705 3706 _renderMenu: function( ul, items ) { 3707 var that = this; 3708 $.each( items, function( index, item ) { 3709 that._renderItemData( ul, item ); 3710 }); 3711 }, 3712 3713 _renderItemData: function( ul, item ) { 3714 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item ); 3715 }, 3716 3717 _renderItem: function( ul, item ) { 3718 return $( "<li>" ) 3719 .append( $( "<a>" ).text( item.label ) ) 3720 .appendTo( ul ); 3721 }, 3722 3723 _move: function( direction, event ) { 3724 if ( !this.menu.element.is( ":visible" ) ) { 3725 this.search( null, event ); 3726 return; 3727 } 3728 if ( this.menu.isFirstItem() && /^previous/.test( direction ) || 3729 this.menu.isLastItem() && /^next/.test( direction ) ) { 3730 this._value( this.term ); 3731 this.menu.blur(); 3732 return; 3733 } 3734 this.menu[ direction ]( event ); 3735 }, 3736 3737 widget: function() { 3738 return this.menu.element; 3739 }, 3740 3741 _value: function() { 3742 return this.valueMethod.apply( this.element, arguments ); 3743 }, 3744 3745 _keyEvent: function( keyEvent, event ) { 3746 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { 3747 this._move( keyEvent, event ); 3748 3749 // prevents moving cursor to beginning/end of the text field in some browsers 3750 event.preventDefault(); 3751 } 3752 } 3753}); 3754 3755$.extend( $.ui.autocomplete, { 3756 escapeRegex: function( value ) { 3757 return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"); 3758 }, 3759 filter: function(array, term) { 3760 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" ); 3761 return $.grep( array, function(value) { 3762 return matcher.test( value.label || value.value || value ); 3763 }); 3764 } 3765}); 3766 3767 3768// live region extension, adding a `messages` option 3769// NOTE: This is an experimental API. We are still investigating 3770// a full solution for string manipulation and internationalization. 3771$.widget( "ui.autocomplete", $.ui.autocomplete, { 3772 options: { 3773 messages: { 3774 noResults: "No search results.", 3775 results: function( amount ) { 3776 return amount + ( amount > 1 ? " results are" : " result is" ) + 3777 " available, use up and down arrow keys to navigate."; 3778 } 3779 } 3780 }, 3781 3782 __response: function( content ) { 3783 var message; 3784 this._superApply( arguments ); 3785 if ( this.options.disabled || this.cancelSearch ) { 3786 return; 3787 } 3788 if ( content && content.length ) { 3789 message = this.options.messages.results( content.length ); 3790 } else { 3791 message = this.options.messages.noResults; 3792 } 3793 this.liveRegion.text( message ); 3794 } 3795}); 3796 3797}( _4ORMAT.$ )); 3798(function( $, undefined ) { 3799 3800var lastActive, 3801 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all", 3802 typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only", 3803 formResetHandler = function() { 3804 var form = $( this ); 3805 setTimeout(function() { 3806 form.find( ":ui-button" ).button( "refresh" ); 3807 }, 1 ); 3808 }, 3809 radioGroup = function( radio ) { 3810 var name = radio.name, 3811 form = radio.form, 3812 radios = $( [] ); 3813 if ( name ) { 3814 name = name.replace( /'/g, "\\'" ); 3815 if ( form ) { 3816 radios = $( form ).find( "[name='" + name + "']" ); 3817 } else { 3818 radios = $( "[name='" + name + "']", radio.ownerDocument ) 3819 .filter(function() { 3820 return !this.form; 3821 }); 3822 } 3823 } 3824 return radios; 3825 }; 3826 3827$.widget( "ui.button", { 3828 version: "1.10.4", 3829 defaultElement: "<button>", 3830 options: { 3831 disabled: null, 3832 text: true, 3833 label: null, 3834 icons: { 3835 primary: null, 3836 secondary: null 3837 } 3838 }, 3839 _create: function() { 3840 this.element.closest( "form" ) 3841 .unbind( "reset" + this.eventNamespace ) 3842 .bind( "reset" + this.eventNamespace, formResetHandler ); 3843 3844 if ( typeof this.options.disabled !== "boolean" ) { 3845 this.options.disabled = !!this.element.prop( "disabled" ); 3846 } else { 3847 this.element.prop( "disabled", this.options.disabled ); 3848 } 3849 3850 this._determineButtonType(); 3851 this.hasTitle = !!this.buttonElement.attr( "title" ); 3852 3853 var that = this, 3854 options = this.options, 3855 toggleButton = this.type === "checkbox" || this.type === "radio", 3856 activeClass = !toggleButton ? "ui-state-active" : ""; 3857 3858 if ( options.label === null ) { 3859 options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html()); 3860 } 3861 3862 this._hoverable( this.buttonElement ); 3863 3864 this.buttonElement 3865 .addClass( baseClasses ) 3866 .attr( "role", "button" ) 3867 .bind( "mouseenter" + this.eventNamespace, function() { 3868 if ( options.disabled ) { 3869 return; 3870 } 3871 if ( this === lastActive ) { 3872 $( this ).addClass( "ui-state-active" ); 3873 } 3874 }) 3875 .bind( "mouseleave" + this.eventNamespace, function() { 3876 if ( options.disabled ) { 3877 return; 3878 } 3879 $( this ).removeClass( activeClass ); 3880 }) 3881 .bind( "click" + this.eventNamespace, function( event ) { 3882 if ( options.disabled ) { 3883 event.preventDefault(); 3884 event.stopImmediatePropagation(); 3885 } 3886 }); 3887 3888 // Can't use _focusable() because the element that receives focus 3889 // and the element that gets the ui-state-focus class are different 3890 this._on({ 3891 focus: function() { 3892 this.buttonElement.addClass( "ui-state-focus" ); 3893 }, 3894 blur: function() { 3895 this.buttonElement.removeClass( "ui-state-focus" ); 3896 } 3897 }); 3898 3899 if ( toggleButton ) { 3900 this.element.bind( "change" + this.eventNamespace, function() { 3901 that.refresh(); 3902 }); 3903 } 3904 3905 if ( this.type === "checkbox" ) { 3906 this.buttonElement.bind( "click" + this.eventNamespace, function() { 3907 if ( options.disabled ) { 3908 return false; 3909 } 3910 }); 3911 } else if ( this.type === "radio" ) { 3912 this.buttonElement.bind( "click" + this.eventNamespace, function() { 3913 if ( options.disabled ) { 3914 return false; 3915 } 3916 $( this ).addClass( "ui-state-active" ); 3917 that.buttonElement.attr( "aria-pressed", "true" ); 3918 3919 var radio = that.element[ 0 ]; 3920 radioGroup( radio ) 3921 .not( radio ) 3922 .map(function() { 3923 return $( this ).button( "widget" )[ 0 ]; 3924 }) 3925 .removeClass( "ui-state-active" ) 3926 .attr( "aria-pressed", "false" ); 3927 }); 3928 } else { 3929 this.buttonElement 3930 .bind( "mousedown" + this.eventNamespace, function() { 3931 if ( options.disabled ) { 3932 return false; 3933 } 3934 $( this ).addClass( "ui-state-active" ); 3935 lastActive = this; 3936 that.document.one( "mouseup", function() { 3937 lastActive = null; 3938 }); 3939 }) 3940 .bind( "mouseup" + this.eventNamespace, function() { 3941 if ( options.disabled ) { 3942 return false; 3943 } 3944 $( this ).removeClass( "ui-state-active" ); 3945 }) 3946 .bind( "keydown" + this.eventNamespace, function(event) { 3947 if ( options.disabled ) { 3948 return false; 3949 } 3950 if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) { 3951 $( this ).addClass( "ui-state-active" ); 3952 } 3953 }) 3954 // see #8559, we bind to blur here in case the button element loses 3955 // focus between keydown and keyup, it would be left in an "active" state 3956 .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() { 3957 $( this ).removeClass( "ui-state-active" ); 3958 }); 3959 3960 if ( this.buttonElement.is("a") ) { 3961 this.buttonElement.keyup(function(event) { 3962 if ( event.keyCode === $.ui.keyCode.SPACE ) { 3963 // TODO pass through original event correctly (just as 2nd argument doesn't work) 3964 $( this ).click(); 3965 } 3966 }); 3967 } 3968 } 3969 3970 // TODO: pull out $.Widget's handling for the disabled option into 3971 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can 3972 // be overridden by individual plugins 3973 this._setOption( "disabled", options.disabled ); 3974 this._resetButton(); 3975 }, 3976 3977 _determineButtonType: function() { 3978 var ancestor, labelSelector, checked; 3979 3980 if ( this.element.is("[type=checkbox]") ) { 3981 this.type = "checkbox"; 3982 } else if ( this.element.is("[type=radio]") ) { 3983 this.type = "radio"; 3984 } else if ( this.element.is("input") ) { 3985 this.type = "input"; 3986 } else { 3987 this.type = "button"; 3988 } 3989 3990 if ( this.type === "checkbox" || this.type === "radio" ) { 3991 // we don't search against the document in case the element 3992 // is disconnected from the DOM
vendor: 8,776 bytes, lines 3993-4227
3993 ancestor = this.element.parents().last(); 3994 labelSelector = "label[for='" + this.element.attr("id") + "']"; 3995 this.buttonElement = ancestor.find( labelSelector ); 3996 if ( !this.buttonElement.length ) { 3997 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings(); 3998 this.buttonElement = ancestor.filter( labelSelector ); 3999 if ( !this.buttonElement.length ) { 4000 this.buttonElement = ancestor.find( labelSelector ); 4001 } 4002 } 4003 this.element.addClass( "ui-helper-hidden-accessible" ); 4004 4005 checked = this.element.is( ":checked" ); 4006 if ( checked ) { 4007 this.buttonElement.addClass( "ui-state-active" ); 4008 } 4009 this.buttonElement.prop( "aria-pressed", checked ); 4010 } else { 4011 this.buttonElement = this.element; 4012 } 4013 }, 4014 4015 widget: function() { 4016 return this.buttonElement; 4017 }, 4018 4019 _destroy: function() { 4020 this.element 4021 .removeClass( "ui-helper-hidden-accessible" ); 4022 this.buttonElement 4023 .removeClass( baseClasses + " ui-state-active " + typeClasses ) 4024 .removeAttr( "role" ) 4025 .removeAttr( "aria-pressed" ) 4026 .html( this.buttonElement.find(".ui-button-text").html() ); 4027 4028 if ( !this.hasTitle ) { 4029 this.buttonElement.removeAttr( "title" ); 4030 } 4031 }, 4032 4033 _setOption: function( key, value ) { 4034 this._super( key, value ); 4035 if ( key === "disabled" ) { 4036 this.element.prop( "disabled", !!value ); 4037 if ( value ) { 4038 this.buttonElement.removeClass( "ui-state-focus" ); 4039 } 4040 return; 4041 } 4042 this._resetButton(); 4043 }, 4044 4045 refresh: function() { 4046 //See #8237 & #8828 4047 var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" ); 4048 4049 if ( isDisabled !== this.options.disabled ) { 4050 this._setOption( "disabled", isDisabled ); 4051 } 4052 if ( this.type === "radio" ) { 4053 radioGroup( this.element[0] ).each(function() { 4054 if ( $( this ).is( ":checked" ) ) { 4055 $( this ).button( "widget" ) 4056 .addClass( "ui-state-active" ) 4057 .attr( "aria-pressed", "true" ); 4058 } else { 4059 $( this ).button( "widget" ) 4060 .removeClass( "ui-state-active" ) 4061 .attr( "aria-pressed", "false" ); 4062 } 4063 }); 4064 } else if ( this.type === "checkbox" ) { 4065 if ( this.element.is( ":checked" ) ) { 4066 this.buttonElement 4067 .addClass( "ui-state-active" ) 4068 .attr( "aria-pressed", "true" ); 4069 } else { 4070 this.buttonElement 4071 .removeClass( "ui-state-active" ) 4072 .attr( "aria-pressed", "false" ); 4073 } 4074 } 4075 }, 4076 4077 _resetButton: function() { 4078 if ( this.type === "input" ) { 4079 if ( this.options.label ) { 4080 this.element.val( this.options.label ); 4081 } 4082 return; 4083 } 4084 var buttonElement = this.buttonElement.removeClass( typeClasses ), 4085 buttonText = $( "<span></span>", this.document[0] ) 4086 .addClass( "ui-button-text" ) 4087 .html( this.options.label ) 4088 .appendTo( buttonElement.empty() ) 4089 .text(), 4090 icons = this.options.icons, 4091 multipleIcons = icons.primary && icons.secondary, 4092 buttonClasses = []; 4093 4094 if ( icons.primary || icons.secondary ) { 4095 if ( this.options.text ) { 4096 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) ); 4097 } 4098 4099 if ( icons.primary ) { 4100 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" ); 4101 } 4102 4103 if ( icons.secondary ) { 4104 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" ); 4105 } 4106 4107 if ( !this.options.text ) { 4108 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" ); 4109 4110 if ( !this.hasTitle ) { 4111 buttonElement.attr( "title", $.trim( buttonText ) ); 4112 } 4113 } 4114 } else { 4115 buttonClasses.push( "ui-button-text-only" ); 4116 } 4117 buttonElement.addClass( buttonClasses.join( " " ) ); 4118 } 4119}); 4120 4121$.widget( "ui.buttonset", { 4122 version: "1.10.4", 4123 options: { 4124 items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)" 4125 }, 4126 4127 _create: function() { 4128 this.element.addClass( "ui-buttonset" ); 4129 }, 4130 4131 _init: function() { 4132 this.refresh(); 4133 }, 4134 4135 _setOption: function( key, value ) { 4136 if ( key === "disabled" ) { 4137 this.buttons.button( "option", key, value ); 4138 } 4139 4140 this._super( key, value ); 4141 }, 4142 4143 refresh: function() { 4144 var rtl = this.element.css( "direction" ) === "rtl"; 4145 4146 this.buttons = this.element.find( this.options.items ) 4147 .filter( ":ui-button" ) 4148 .button( "refresh" ) 4149 .end() 4150 .not( ":ui-button" ) 4151 .button() 4152 .end() 4153 .map(function() { 4154 return $( this ).button( "widget" )[ 0 ]; 4155 }) 4156 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" ) 4157 .filter( ":first" ) 4158 .addClass( rtl ? "ui-corner-right" : "ui-corner-left" ) 4159 .end() 4160 .filter( ":last" ) 4161 .addClass( rtl ? "ui-corner-left" : "ui-corner-right" ) 4162 .end() 4163 .end(); 4164 }, 4165 4166 _destroy: function() { 4167 this.element.removeClass( "ui-buttonset" ); 4168 this.buttons 4169 .map(function() { 4170 return $( this ).button( "widget" )[ 0 ]; 4171 }) 4172 .removeClass( "ui-corner-left ui-corner-right" ) 4173 .end() 4174 .button( "destroy" ); 4175 } 4176}); 4177 4178}( _4ORMAT.$ ) ); 4179(function( $, undefined ) { 4180 4181$.extend($.ui, { datepicker: { version: "1.10.4" } }); 4182 4183var PROP_NAME = "datepicker", 4184 instActive; 4185 4186/* Date picker manager. 4187 Use the singleton instance of this class, $.datepicker, to interact with the date picker. 4188 Settings for (groups of) date pickers are maintained in an instance object, 4189 allowing multiple different settings on the same page. */ 4190 4191function Datepicker() { 4192 this._curInst = null; // The current instance in use 4193 this._keyEvent = false; // If the last event was a key event 4194 this._disabledInputs = []; // List of date picker inputs that have been disabled 4195 this._datepickerShowing = false; // True if the popup picker is showing , false if not 4196 this._inDialog = false; // True if showing within a "dialog", false if not 4197 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division 4198 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class 4199 this._appendClass = "ui-datepicker-append"; // The name of the append marker class 4200 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class 4201 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class 4202 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class 4203 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class 4204 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class 4205 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class 4206 this.regional = []; // Available regional settings, indexed by language code 4207 this.regional[""] = { // Default regional settings 4208 closeText: "Done", // Display text for close link 4209 prevText: "Prev", // Display text for previous month link 4210 nextText: "Next", // Display text for next month link 4211 currentText: "Today", // Display text for current month link 4212 monthNames: ["January","February","March","April","May","June", 4213 "July","August","September","October","November","December"], // Names of months for drop-down and formatting 4214 monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting 4215 dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting 4216 dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting 4217 dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday 4218 weekHeader: "Wk", // Column header for week of the year 4219 dateFormat: "mm/dd/yy", // See format options on parseDate 4220 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... 4221 isRTL: false, // True if right-to-left language, false if left-to-right 4222 showMonthAfterYear: false, // True if the year select precedes month, false for month then year 4223 yearSuffix: "" // Additional text to append to the year in the month headers 4224 }; 4225 this._defaults = { // Global defaults for all the date picker instances 4226 showOn: "focus", // "focus" for popup on focus, 4227 // "button" for trigger button, or "both" for either
vendor: 5,736 bytes, lines 4228-4332
4228 showAnim: "fadeIn", // Name of jQuery animation for popup 4229 showOptions: {}, // Options for enhanced animations 4230 defaultDate: null, // Used when field is blank: actual date, 4231 // +/-number for offset from today, null for today 4232 appendText: "", // Display text following the input box, e.g. showing the format 4233 buttonText: "...", // Text for trigger button 4234 buttonImage: "", // URL for trigger button image 4235 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button 4236 hideIfNoPrevNext: false, // True to hide next/previous month links 4237 // if not applicable, false to just disable them 4238 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links 4239 gotoCurrent: false, // True if today link goes back to current selection instead 4240 changeMonth: false, // True if month can be selected directly, false if only prev/next 4241 changeYear: false, // True if year can be selected directly, false if only prev/next 4242 yearRange: "c-10:c+10", // Range of years to display in drop-down, 4243 // either relative to today's year (-nn:+nn), relative to currently displayed year 4244 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n) 4245 showOtherMonths: false, // True to show dates in other months, false to leave blank 4246 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable 4247 showWeek: false, // True to show week of the year, false to not show it 4248 calculateWeek: this.iso8601Week, // How to calculate the week of the year, 4249 // takes a Date and returns the number of the week for it 4250 shortYearCutoff: "+10", // Short year values < this are in the current century, 4251 // > this are in the previous century, 4252 // string value starting with "+" for current year + value 4253 minDate: null, // The earliest selectable date, or null for no limit 4254 maxDate: null, // The latest selectable date, or null for no limit 4255 duration: "fast", // Duration of display/closure 4256 beforeShowDay: null, // Function that takes a date and returns an array with 4257 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "", 4258 // [2] = cell title (optional), e.g. $.datepicker.noWeekends 4259 beforeShow: null, // Function that takes an input field and 4260 // returns a set of custom settings for the date picker 4261 onSelect: null, // Define a callback function when a date is selected 4262 onChangeMonthYear: null, // Define a callback function when the month or year is changed 4263 onClose: null, // Define a callback function when the datepicker is closed 4264 numberOfMonths: 1, // Number of months to show at a time 4265 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) 4266 stepMonths: 1, // Number of months to step back/forward 4267 stepBigMonths: 12, // Number of months to step back/forward for the big links 4268 altField: "", // Selector for an alternate field to store selected dates into 4269 altFormat: "", // The date format to use for the alternate field 4270 constrainInput: true, // The input is constrained by the current date format 4271 showButtonPanel: false, // True to show button panel, false to not show it 4272 autoSize: false, // True to size the input for the date format, false to leave as is 4273 disabled: false // The initial disabled state 4274 }; 4275 $.extend(this._defaults, this.regional[""]); 4276 this.dpDiv = bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")); 4277} 4278 4279$.extend(Datepicker.prototype, { 4280 /* Class name added to elements to indicate already configured with a date picker. */ 4281 markerClassName: "hasDatepicker", 4282 4283 //Keep track of the maximum number of rows displayed (see #7043) 4284 maxRows: 4, 4285 4286 // TODO rename to "widget" when switching to widget factory 4287 _widgetDatepicker: function() { 4288 return this.dpDiv; 4289 }, 4290 4291 /* Override the default settings for all instances of the date picker. 4292 * @param settings object - the new settings to use as defaults (anonymous object) 4293 * @return the manager object 4294 */ 4295 setDefaults: function(settings) { 4296 extendRemove(this._defaults, settings || {}); 4297 return this; 4298 }, 4299 4300 /* Attach the date picker to a jQuery selection. 4301 * @param target element - the target input field or division or span 4302 * @param settings object - the new settings to use for this date picker instance (anonymous) 4303 */ 4304 _attachDatepicker: function(target, settings) { 4305 var nodeName, inline, inst; 4306 nodeName = target.nodeName.toLowerCase(); 4307 inline = (nodeName === "div" || nodeName === "span"); 4308 if (!target.id) { 4309 this.uuid += 1; 4310 target.id = "dp" + this.uuid; 4311 } 4312 inst = this._newInst($(target), inline); 4313 inst.settings = $.extend({}, settings || {}); 4314 if (nodeName === "input") { 4315 this._connectDatepicker(target, inst); 4316 } else if (inline) { 4317 this._inlineDatepicker(target, inst); 4318 } 4319 }, 4320 4321 /* Create a new instance object. */ 4322 _newInst: function(target, inline) { 4323 var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars 4324 return {id: id, input: target, // associated target 4325 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection 4326 drawMonth: 0, drawYear: 0, // month being drawn 4327 inline: inline, // is datepicker inline or not 4328 dpDiv: (!inline ? this.dpDiv : // presentation div 4329 bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))}; 4330 }, 4331 4332 /* Attach the date picker to an input field. */
vendor: 7,031 bytes, lines 4333-4513
4333 _connectDatepicker: function(target, inst) { 4334 var input = $(target); 4335 inst.append = $([]); 4336 inst.trigger = $([]); 4337 if (input.hasClass(this.markerClassName)) { 4338 return; 4339 } 4340 this._attachments(input, inst); 4341 input.addClass(this.markerClassName).keydown(this._doKeyDown). 4342 keypress(this._doKeyPress).keyup(this._doKeyUp); 4343 this._autoSize(inst); 4344 $.data(target, PROP_NAME, inst); 4345 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) 4346 if( inst.settings.disabled ) { 4347 this._disableDatepicker( target ); 4348 } 4349 }, 4350 4351 /* Make attachments based on settings. */ 4352 _attachments: function(input, inst) { 4353 var showOn, buttonText, buttonImage, 4354 appendText = this._get(inst, "appendText"), 4355 isRTL = this._get(inst, "isRTL"); 4356 4357 if (inst.append) { 4358 inst.append.remove(); 4359 } 4360 if (appendText) { 4361 inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>"); 4362 input[isRTL ? "before" : "after"](inst.append); 4363 } 4364 4365 input.unbind("focus", this._showDatepicker); 4366 4367 if (inst.trigger) { 4368 inst.trigger.remove(); 4369 } 4370 4371 showOn = this._get(inst, "showOn"); 4372 if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field 4373 input.focus(this._showDatepicker); 4374 } 4375 if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked 4376 buttonText = this._get(inst, "buttonText"); 4377 buttonImage = this._get(inst, "buttonImage"); 4378 inst.trigger = $(this._get(inst, "buttonImageOnly") ? 4379 $("<img/>").addClass(this._triggerClass). 4380 attr({ src: buttonImage, alt: buttonText, title: buttonText }) : 4381 $("<button type='button'></button>").addClass(this._triggerClass). 4382 html(!buttonImage ? buttonText : $("<img/>").attr( 4383 { src:buttonImage, alt:buttonText, title:buttonText }))); 4384 input[isRTL ? "before" : "after"](inst.trigger); 4385 inst.trigger.click(function() { 4386 if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) { 4387 $.datepicker._hideDatepicker(); 4388 } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) { 4389 $.datepicker._hideDatepicker(); 4390 $.datepicker._showDatepicker(input[0]); 4391 } else { 4392 $.datepicker._showDatepicker(input[0]); 4393 } 4394 return false; 4395 }); 4396 } 4397 }, 4398 4399 /* Apply the maximum length for the date format. */ 4400 _autoSize: function(inst) { 4401 if (this._get(inst, "autoSize") && !inst.inline) { 4402 var findMax, max, maxI, i, 4403 date = new Date(2009, 12 - 1, 20), // Ensure double digits 4404 dateFormat = this._get(inst, "dateFormat"); 4405 4406 if (dateFormat.match(/[DM]/)) { 4407 findMax = function(names) { 4408 max = 0; 4409 maxI = 0; 4410 for (i = 0; i < names.length; i++) { 4411 if (names[i].length > max) { 4412 max = names[i].length; 4413 maxI = i; 4414 } 4415 } 4416 return maxI; 4417 }; 4418 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ? 4419 "monthNames" : "monthNamesShort")))); 4420 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ? 4421 "dayNames" : "dayNamesShort"))) + 20 - date.getDay()); 4422 } 4423 inst.input.attr("size", this._formatDate(inst, date).length); 4424 } 4425 }, 4426 4427 /* Attach an inline date picker to a div. */ 4428 _inlineDatepicker: function(target, inst) { 4429 var divSpan = $(target); 4430 if (divSpan.hasClass(this.markerClassName)) { 4431 return; 4432 } 4433 divSpan.addClass(this.markerClassName).append(inst.dpDiv); 4434 $.data(target, PROP_NAME, inst); 4435 this._setDate(inst, this._getDefaultDate(inst), true); 4436 this._updateDatepicker(inst); 4437 this._updateAlternate(inst); 4438 //If disabled option is true, disable the datepicker before showing it (see ticket #5665) 4439 if( inst.settings.disabled ) { 4440 this._disableDatepicker( target ); 4441 } 4442 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements 4443 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height 4444 inst.dpDiv.css( "display", "block" ); 4445 }, 4446 4447 /* Pop-up the date picker in a "dialog" box. 4448 * @param input element - ignored 4449 * @param date string or Date - the initial date to display 4450 * @param onSelect function - the function to call when a date is selected 4451 * @param settings object - update the dialog date picker instance's settings (anonymous object) 4452 * @param pos int[2] - coordinates for the dialog's position within the screen or 4453 * event - with x/y coordinates or 4454 * leave empty for default (screen centre) 4455 * @return the manager object 4456 */ 4457 _dialogDatepicker: function(input, date, onSelect, settings, pos) { 4458 var id, browserWidth, browserHeight, scrollX, scrollY, 4459 inst = this._dialogInst; // internal instance 4460 4461 if (!inst) { 4462 this.uuid += 1; 4463 id = "dp" + this.uuid; 4464 this._dialogInput = $("<input type='text' id='" + id + 4465 "' style='position: absolute; top: -100px; width: 0px;'/>"); 4466 this._dialogInput.keydown(this._doKeyDown); 4467 $("body").append(this._dialogInput); 4468 inst = this._dialogInst = this._newInst(this._dialogInput, false); 4469 inst.settings = {}; 4470 $.data(this._dialogInput[0], PROP_NAME, inst); 4471 } 4472 extendRemove(inst.settings, settings || {}); 4473 date = (date && date.constructor === Date ? this._formatDate(inst, date) : date); 4474 this._dialogInput.val(date); 4475 4476 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null); 4477 if (!this._pos) { 4478 browserWidth = document.documentElement.clientWidth; 4479 browserHeight = document.documentElement.clientHeight; 4480 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; 4481 scrollY = document.documentElement.scrollTop || document.body.scrollTop; 4482 this._pos = // should use actual width/height below 4483 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY]; 4484 } 4485 4486 // move input on screen for focus, but hidden behind dialog 4487 this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px"); 4488 inst.settings.onSelect = onSelect; 4489 this._inDialog = true; 4490 this.dpDiv.addClass(this._dialogClass); 4491 this._showDatepicker(this._dialogInput[0]); 4492 if ($.blockUI) { 4493 $.blockUI(this.dpDiv); 4494 } 4495 $.data(this._dialogInput[0], PROP_NAME, inst); 4496 return this; 4497 }, 4498 4499 /* Detach a datepicker from its control. 4500 * @param target element - the target input field or division or span 4501 */ 4502 _destroyDatepicker: function(target) { 4503 var nodeName, 4504 $target = $(target), 4505 inst = $.data(target, PROP_NAME); 4506 4507 if (!$target.hasClass(this.markerClassName)) { 4508 return; 4509 } 4510 4511 nodeName = target.nodeName.toLowerCase(); 4512 $.removeData(target, PROP_NAME); 4513 if (nodeName === "input") {
vendor: 11,673 bytes, lines 4514-4825
4514 inst.append.remove(); 4515 inst.trigger.remove(); 4516 $target.removeClass(this.markerClassName). 4517 unbind("focus", this._showDatepicker). 4518 unbind("keydown", this._doKeyDown). 4519 unbind("keypress", this._doKeyPress). 4520 unbind("keyup", this._doKeyUp); 4521 } else if (nodeName === "div" || nodeName === "span") { 4522 $target.removeClass(this.markerClassName).empty(); 4523 } 4524 }, 4525 4526 /* Enable the date picker to a jQuery selection. 4527 * @param target element - the target input field or division or span 4528 */ 4529 _enableDatepicker: function(target) { 4530 var nodeName, inline, 4531 $target = $(target), 4532 inst = $.data(target, PROP_NAME); 4533 4534 if (!$target.hasClass(this.markerClassName)) { 4535 return; 4536 } 4537 4538 nodeName = target.nodeName.toLowerCase(); 4539 if (nodeName === "input") { 4540 target.disabled = false; 4541 inst.trigger.filter("button"). 4542 each(function() { this.disabled = false; }).end(). 4543 filter("img").css({opacity: "1.0", cursor: ""}); 4544 } else if (nodeName === "div" || nodeName === "span") { 4545 inline = $target.children("." + this._inlineClass); 4546 inline.children().removeClass("ui-state-disabled"); 4547 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). 4548 prop("disabled", false); 4549 } 4550 this._disabledInputs = $.map(this._disabledInputs, 4551 function(value) { return (value === target ? null : value); }); // delete entry 4552 }, 4553 4554 /* Disable the date picker to a jQuery selection. 4555 * @param target element - the target input field or division or span 4556 */ 4557 _disableDatepicker: function(target) { 4558 var nodeName, inline, 4559 $target = $(target), 4560 inst = $.data(target, PROP_NAME); 4561 4562 if (!$target.hasClass(this.markerClassName)) { 4563 return; 4564 } 4565 4566 nodeName = target.nodeName.toLowerCase(); 4567 if (nodeName === "input") { 4568 target.disabled = true; 4569 inst.trigger.filter("button"). 4570 each(function() { this.disabled = true; }).end(). 4571 filter("img").css({opacity: "0.5", cursor: "default"}); 4572 } else if (nodeName === "div" || nodeName === "span") { 4573 inline = $target.children("." + this._inlineClass); 4574 inline.children().addClass("ui-state-disabled"); 4575 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). 4576 prop("disabled", true); 4577 } 4578 this._disabledInputs = $.map(this._disabledInputs, 4579 function(value) { return (value === target ? null : value); }); // delete entry 4580 this._disabledInputs[this._disabledInputs.length] = target; 4581 }, 4582 4583 /* Is the first field in a jQuery collection disabled as a datepicker? 4584 * @param target element - the target input field or division or span 4585 * @return boolean - true if disabled, false if enabled 4586 */ 4587 _isDisabledDatepicker: function(target) { 4588 if (!target) { 4589 return false; 4590 } 4591 for (var i = 0; i < this._disabledInputs.length; i++) { 4592 if (this._disabledInputs[i] === target) { 4593 return true; 4594 } 4595 } 4596 return false; 4597 }, 4598 4599 /* Retrieve the instance data for the target control. 4600 * @param target element - the target input field or division or span 4601 * @return object - the associated instance data 4602 * @throws error if a jQuery problem getting data 4603 */ 4604 _getInst: function(target) { 4605 try { 4606 return $.data(target, PROP_NAME); 4607 } 4608 catch (err) { 4609 throw "Missing instance data for this datepicker"; 4610 } 4611 }, 4612 4613 /* Update or retrieve the settings for a date picker attached to an input field or division. 4614 * @param target element - the target input field or division or span 4615 * @param name object - the new settings to update or 4616 * string - the name of the setting to change or retrieve, 4617 * when retrieving also "all" for all instance settings or 4618 * "defaults" for all global defaults 4619 * @param value any - the new value for the setting 4620 * (omit if above is an object or to retrieve a value) 4621 */ 4622 _optionDatepicker: function(target, name, value) { 4623 var settings, date, minDate, maxDate, 4624 inst = this._getInst(target); 4625 4626 if (arguments.length === 2 && typeof name === "string") { 4627 return (name === "defaults" ? $.extend({}, $.datepicker._defaults) : 4628 (inst ? (name === "all" ? $.extend({}, inst.settings) : 4629 this._get(inst, name)) : null)); 4630 } 4631 4632 settings = name || {}; 4633 if (typeof name === "string") { 4634 settings = {}; 4635 settings[name] = value; 4636 } 4637 4638 if (inst) { 4639 if (this._curInst === inst) { 4640 this._hideDatepicker(); 4641 } 4642 4643 date = this._getDateDatepicker(target, true); 4644 minDate = this._getMinMaxDate(inst, "min"); 4645 maxDate = this._getMinMaxDate(inst, "max"); 4646 extendRemove(inst.settings, settings); 4647 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided 4648 if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) { 4649 inst.settings.minDate = this._formatDate(inst, minDate); 4650 } 4651 if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) { 4652 inst.settings.maxDate = this._formatDate(inst, maxDate); 4653 } 4654 if ( "disabled" in settings ) { 4655 if ( settings.disabled ) { 4656 this._disableDatepicker(target); 4657 } else { 4658 this._enableDatepicker(target); 4659 } 4660 } 4661 this._attachments($(target), inst); 4662 this._autoSize(inst); 4663 this._setDate(inst, date); 4664 this._updateAlternate(inst); 4665 this._updateDatepicker(inst); 4666 } 4667 }, 4668 4669 // change method deprecated 4670 _changeDatepicker: function(target, name, value) { 4671 this._optionDatepicker(target, name, value); 4672 }, 4673 4674 /* Redraw the date picker attached to an input field or division. 4675 * @param target element - the target input field or division or span 4676 */ 4677 _refreshDatepicker: function(target) { 4678 var inst = this._getInst(target); 4679 if (inst) { 4680 this._updateDatepicker(inst); 4681 } 4682 }, 4683 4684 /* Set the dates for a jQuery selection. 4685 * @param target element - the target input field or division or span 4686 * @param date Date - the new date 4687 */ 4688 _setDateDatepicker: function(target, date) { 4689 var inst = this._getInst(target); 4690 if (inst) { 4691 this._setDate(inst, date); 4692 this._updateDatepicker(inst); 4693 this._updateAlternate(inst); 4694 } 4695 }, 4696 4697 /* Get the date(s) for the first entry in a jQuery selection. 4698 * @param target element - the target input field or division or span 4699 * @param noDefault boolean - true if no default date is to be used 4700 * @return Date - the current date 4701 */ 4702 _getDateDatepicker: function(target, noDefault) { 4703 var inst = this._getInst(target); 4704 if (inst && !inst.inline) { 4705 this._setDateFromField(inst, noDefault); 4706 } 4707 return (inst ? this._getDate(inst) : null); 4708 }, 4709 4710 /* Handle keystrokes. */ 4711 _doKeyDown: function(event) { 4712 var onSelect, dateStr, sel, 4713 inst = $.datepicker._getInst(event.target), 4714 handled = true, 4715 isRTL = inst.dpDiv.is(".ui-datepicker-rtl"); 4716 4717 inst._keyEvent = true; 4718 if ($.datepicker._datepickerShowing) { 4719 switch (event.keyCode) { 4720 case 9: $.datepicker._hideDatepicker(); 4721 handled = false; 4722 break; // hide on tab out 4723 case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." + 4724 $.datepicker._currentClass + ")", inst.dpDiv); 4725 if (sel[0]) { 4726 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); 4727 } 4728 4729 onSelect = $.datepicker._get(inst, "onSelect"); 4730 if (onSelect) { 4731 dateStr = $.datepicker._formatDate(inst); 4732 4733 // trigger custom callback 4734 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); 4735 } else { 4736 $.datepicker._hideDatepicker(); 4737 } 4738 4739 return false; // don't submit the form 4740 case 27: $.datepicker._hideDatepicker(); 4741 break; // hide on escape 4742 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? 4743 -$.datepicker._get(inst, "stepBigMonths") : 4744 -$.datepicker._get(inst, "stepMonths")), "M"); 4745 break; // previous month/year on page up/+ ctrl 4746 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ? 4747 +$.datepicker._get(inst, "stepBigMonths") : 4748 +$.datepicker._get(inst, "stepMonths")), "M"); 4749 break; // next month/year on page down/+ ctrl 4750 case 35: if (event.ctrlKey || event.metaKey) { 4751 $.datepicker._clearDate(event.target); 4752 } 4753 handled = event.ctrlKey || event.metaKey; 4754 break; // clear on ctrl or command +end 4755 case 36: if (event.ctrlKey || event.metaKey) { 4756 $.datepicker._gotoToday(event.target); 4757 } 4758 handled = event.ctrlKey || event.metaKey; 4759 break; // current on ctrl or command +home 4760 case 37: if (event.ctrlKey || event.metaKey) { 4761 $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D"); 4762 } 4763 handled = event.ctrlKey || event.metaKey; 4764 // -1 day on ctrl or command +left 4765 if (event.originalEvent.altKey) { 4766 $.datepicker._adjustDate(event.target, (event.ctrlKey ? 4767 -$.datepicker._get(inst, "stepBigMonths") : 4768 -$.datepicker._get(inst, "stepMonths")), "M"); 4769 } 4770 // next month/year on alt +left on Mac 4771 break; 4772 case 38: if (event.ctrlKey || event.metaKey) { 4773 $.datepicker._adjustDate(event.target, -7, "D"); 4774 } 4775 handled = event.ctrlKey || event.metaKey; 4776 break; // -1 week on ctrl or command +up 4777 case 39: if (event.ctrlKey || event.metaKey) { 4778 $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D"); 4779 } 4780 handled = event.ctrlKey || event.metaKey; 4781 // +1 day on ctrl or command +right 4782 if (event.originalEvent.altKey) { 4783 $.datepicker._adjustDate(event.target, (event.ctrlKey ? 4784 +$.datepicker._get(inst, "stepBigMonths") : 4785 +$.datepicker._get(inst, "stepMonths")), "M"); 4786 } 4787 // next month/year on alt +right 4788 break; 4789 case 40: if (event.ctrlKey || event.metaKey) { 4790 $.datepicker._adjustDate(event.target, +7, "D"); 4791 } 4792 handled = event.ctrlKey || event.metaKey; 4793 break; // +1 week on ctrl or command +down 4794 default: handled = false; 4795 } 4796 } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home 4797 $.datepicker._showDatepicker(this); 4798 } else { 4799 handled = false; 4800 } 4801 4802 if (handled) { 4803 event.preventDefault(); 4804 event.stopPropagation(); 4805 } 4806 }, 4807 4808 /* Filter entered characters - based on date format. */ 4809 _doKeyPress: function(event) { 4810 var chars, chr, 4811 inst = $.datepicker._getInst(event.target); 4812 4813 if ($.datepicker._get(inst, "constrainInput")) { 4814 chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat")); 4815 chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode); 4816 return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1); 4817 } 4818 }, 4819 4820 /* Synchronise manual entry and field/alternate field. */ 4821 _doKeyUp: function(event) { 4822 var date, 4823 inst = $.datepicker._getInst(event.target); 4824 4825 if (inst.input.val() !== inst.lastVal) {
vendor: 9,399 bytes, lines 4826-5082
4826 try { 4827 date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), 4828 (inst.input ? inst.input.val() : null), 4829 $.datepicker._getFormatConfig(inst)); 4830 4831 if (date) { // only if valid 4832 $.datepicker._setDateFromField(inst); 4833 $.datepicker._updateAlternate(inst); 4834 $.datepicker._updateDatepicker(inst); 4835 } 4836 } 4837 catch (err) { 4838 } 4839 } 4840 return true; 4841 }, 4842 4843 /* Pop-up the date picker for a given input field. 4844 * If false returned from beforeShow event handler do not show. 4845 * @param input element - the input field attached to the date picker or 4846 * event - if triggered by focus 4847 */ 4848 _showDatepicker: function(input) { 4849 input = input.target || input; 4850 if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger 4851 input = $("input", input.parentNode)[0]; 4852 } 4853 4854 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here 4855 return; 4856 } 4857 4858 var inst, beforeShow, beforeShowSettings, isFixed, 4859 offset, showAnim, duration; 4860 4861 inst = $.datepicker._getInst(input); 4862 if ($.datepicker._curInst && $.datepicker._curInst !== inst) { 4863 $.datepicker._curInst.dpDiv.stop(true, true); 4864 if ( inst && $.datepicker._datepickerShowing ) { 4865 $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] ); 4866 } 4867 } 4868 4869 beforeShow = $.datepicker._get(inst, "beforeShow"); 4870 beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {}; 4871 if(beforeShowSettings === false){ 4872 return; 4873 } 4874 extendRemove(inst.settings, beforeShowSettings); 4875 4876 inst.lastVal = null; 4877 $.datepicker._lastInput = input; 4878 $.datepicker._setDateFromField(inst); 4879 4880 if ($.datepicker._inDialog) { // hide cursor 4881 input.value = ""; 4882 } 4883 if (!$.datepicker._pos) { // position below input 4884 $.datepicker._pos = $.datepicker._findPos(input); 4885 $.datepicker._pos[1] += input.offsetHeight; // add the height 4886 } 4887 4888 isFixed = false; 4889 $(input).parents().each(function() { 4890 isFixed |= $(this).css("position") === "fixed"; 4891 return !isFixed; 4892 }); 4893 4894 offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]}; 4895 $.datepicker._pos = null; 4896 //to avoid flashes on Firefox 4897 inst.dpDiv.empty(); 4898 // determine sizing offscreen 4899 inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"}); 4900 $.datepicker._updateDatepicker(inst); 4901 // fix width for dynamic number of date pickers 4902 // and adjust position before showing 4903 offset = $.datepicker._checkOffset(inst, offset, isFixed); 4904 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ? 4905 "static" : (isFixed ? "fixed" : "absolute")), display: "none", 4906 left: offset.left + "px", top: offset.top + "px"}); 4907 4908 if (!inst.inline) { 4909 showAnim = $.datepicker._get(inst, "showAnim"); 4910 duration = $.datepicker._get(inst, "duration"); 4911 inst.dpDiv.zIndex($(input).zIndex()+1); 4912 $.datepicker._datepickerShowing = true; 4913 4914 if ( $.effects && $.effects.effect[ showAnim ] ) { 4915 inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration); 4916 } else { 4917 inst.dpDiv[showAnim || "show"](showAnim ? duration : null); 4918 } 4919 4920 if ( $.datepicker._shouldFocusInput( inst ) ) { 4921 inst.input.focus(); 4922 } 4923 4924 $.datepicker._curInst = inst; 4925 } 4926 }, 4927 4928 /* Generate the date picker content. */ 4929 _updateDatepicker: function(inst) { 4930 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043) 4931 instActive = inst; // for delegate hover events 4932 inst.dpDiv.empty().append(this._generateHTML(inst)); 4933 this._attachHandlers(inst); 4934 inst.dpDiv.find("." + this._dayOverClass + " a").mouseover(); 4935 4936 var origyearshtml, 4937 numMonths = this._getNumberOfMonths(inst), 4938 cols = numMonths[1], 4939 width = 17; 4940 4941 inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""); 4942 if (cols > 1) { 4943 inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em"); 4944 } 4945 inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") + 4946 "Class"]("ui-datepicker-multi"); 4947 inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") + 4948 "Class"]("ui-datepicker-rtl"); 4949 4950 if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) { 4951 inst.input.focus(); 4952 } 4953 4954 // deffered render of the years select (to avoid flashes on Firefox) 4955 if( inst.yearshtml ){ 4956 origyearshtml = inst.yearshtml; 4957 setTimeout(function(){ 4958 //assure that inst.yearshtml didn't change. 4959 if( origyearshtml === inst.yearshtml && inst.yearshtml ){ 4960 inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml); 4961 } 4962 origyearshtml = inst.yearshtml = null; 4963 }, 0); 4964 } 4965 }, 4966 4967 // #6694 - don't focus the input if it's already focused 4968 // this breaks the change event in IE 4969 // Support: IE and jQuery <1.9 4970 _shouldFocusInput: function( inst ) { 4971 return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" ); 4972 }, 4973 4974 /* Check positioning to remain on screen. */ 4975 _checkOffset: function(inst, offset, isFixed) { 4976 var dpWidth = inst.dpDiv.outerWidth(), 4977 dpHeight = inst.dpDiv.outerHeight(), 4978 inputWidth = inst.input ? inst.input.outerWidth() : 0, 4979 inputHeight = inst.input ? inst.input.outerHeight() : 0, 4980 viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()), 4981 viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop()); 4982 4983 offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0); 4984 offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0; 4985 offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0; 4986 4987 // now check if datepicker is showing outside window viewport - move to a better place if so. 4988 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? 4989 Math.abs(offset.left + dpWidth - viewWidth) : 0); 4990 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? 4991 Math.abs(dpHeight + inputHeight) : 0); 4992 4993 return offset; 4994 }, 4995 4996 /* Find an object's position on the screen. */ 4997 _findPos: function(obj) { 4998 var position, 4999 inst = this._getInst(obj), 5000 isRTL = this._get(inst, "isRTL"); 5001 5002 while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) { 5003 obj = obj[isRTL ? "previousSibling" : "nextSibling"]; 5004 } 5005 5006 position = $(obj).offset(); 5007 return [position.left, position.top]; 5008 }, 5009 5010 /* Hide the date picker from view. 5011 * @param input element - the input field attached to the date picker 5012 */ 5013 _hideDatepicker: function(input) { 5014 var showAnim, duration, postProcess, onClose, 5015 inst = this._curInst; 5016 5017 if (!inst || (input && inst !== $.data(input, PROP_NAME))) { 5018 return; 5019 } 5020 5021 if (this._datepickerShowing) { 5022 showAnim = this._get(inst, "showAnim"); 5023 duration = this._get(inst, "duration"); 5024 postProcess = function() { 5025 $.datepicker._tidyDialog(inst); 5026 }; 5027 5028 // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed 5029 if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) { 5030 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess); 5031 } else { 5032 inst.dpDiv[(showAnim === "slideDown" ? "slideUp" : 5033 (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess); 5034 } 5035 5036 if (!showAnim) { 5037 postProcess(); 5038 } 5039 this._datepickerShowing = false; 5040 5041 onClose = this._get(inst, "onClose"); 5042 if (onClose) { 5043 onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]); 5044 } 5045 5046 this._lastInput = null; 5047 if (this._inDialog) { 5048 this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" }); 5049 if ($.blockUI) { 5050 $.unblockUI(); 5051 $("body").append(this.dpDiv); 5052 } 5053 } 5054 this._inDialog = false; 5055 } 5056 }, 5057 5058 /* Tidy up after a dialog display. */ 5059 _tidyDialog: function(inst) { 5060 inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar"); 5061 }, 5062 5063 /* Close date picker if clicked elsewhere. */ 5064 _checkExternalClick: function(event) { 5065 if (!$.datepicker._curInst) { 5066 return; 5067 } 5068 5069 var $target = $(event.target), 5070 inst = $.datepicker._getInst($target[0]); 5071 5072 if ( ( ( $target[0].id !== $.datepicker._mainDivId && 5073 $target.parents("#" + $.datepicker._mainDivId).length === 0 && 5074 !$target.hasClass($.datepicker.markerClassName) && 5075 !$target.closest("." + $.datepicker._triggerClass).length && 5076 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) || 5077 ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) { 5078 $.datepicker._hideDatepicker(); 5079 } 5080 }, 5081 5082 /* Adjust one of the date sub-fields. */
vendor: 4,555 bytes, lines 5083-5224
5083 _adjustDate: function(id, offset, period) { 5084 var target = $(id), 5085 inst = this._getInst(target[0]); 5086 5087 if (this._isDisabledDatepicker(target[0])) { 5088 return; 5089 } 5090 this._adjustInstDate(inst, offset + 5091 (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning 5092 period); 5093 this._updateDatepicker(inst); 5094 }, 5095 5096 /* Action for current link. */ 5097 _gotoToday: function(id) { 5098 var date, 5099 target = $(id), 5100 inst = this._getInst(target[0]); 5101 5102 if (this._get(inst, "gotoCurrent") && inst.currentDay) { 5103 inst.selectedDay = inst.currentDay; 5104 inst.drawMonth = inst.selectedMonth = inst.currentMonth; 5105 inst.drawYear = inst.selectedYear = inst.currentYear; 5106 } else { 5107 date = new Date(); 5108 inst.selectedDay = date.getDate(); 5109 inst.drawMonth = inst.selectedMonth = date.getMonth(); 5110 inst.drawYear = inst.selectedYear = date.getFullYear(); 5111 } 5112 this._notifyChange(inst); 5113 this._adjustDate(target); 5114 }, 5115 5116 /* Action for selecting a new month/year. */ 5117 _selectMonthYear: function(id, select, period) { 5118 var target = $(id), 5119 inst = this._getInst(target[0]); 5120 5121 inst["selected" + (period === "M" ? "Month" : "Year")] = 5122 inst["draw" + (period === "M" ? "Month" : "Year")] = 5123 parseInt(select.options[select.selectedIndex].value,10); 5124 5125 this._notifyChange(inst); 5126 this._adjustDate(target); 5127 }, 5128 5129 /* Action for selecting a day. */ 5130 _selectDay: function(id, month, year, td) { 5131 var inst, 5132 target = $(id); 5133 5134 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) { 5135 return; 5136 } 5137 5138 inst = this._getInst(target[0]); 5139 inst.selectedDay = inst.currentDay = $("a", td).html(); 5140 inst.selectedMonth = inst.currentMonth = month; 5141 inst.selectedYear = inst.currentYear = year; 5142 this._selectDate(id, this._formatDate(inst, 5143 inst.currentDay, inst.currentMonth, inst.currentYear)); 5144 }, 5145 5146 /* Erase the input field and hide the date picker. */ 5147 _clearDate: function(id) { 5148 var target = $(id); 5149 this._selectDate(target, ""); 5150 }, 5151 5152 /* Update the input field with the selected date. */ 5153 _selectDate: function(id, dateStr) { 5154 var onSelect, 5155 target = $(id), 5156 inst = this._getInst(target[0]); 5157 5158 dateStr = (dateStr != null ? dateStr : this._formatDate(inst)); 5159 if (inst.input) { 5160 inst.input.val(dateStr); 5161 } 5162 this._updateAlternate(inst); 5163 5164 onSelect = this._get(inst, "onSelect"); 5165 if (onSelect) { 5166 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback 5167 } else if (inst.input) { 5168 inst.input.trigger("change"); // fire the change event 5169 } 5170 5171 if (inst.inline){ 5172 this._updateDatepicker(inst); 5173 } else { 5174 this._hideDatepicker(); 5175 this._lastInput = inst.input[0]; 5176 if (typeof(inst.input[0]) !== "object") { 5177 inst.input.focus(); // restore focus 5178 } 5179 this._lastInput = null; 5180 } 5181 }, 5182 5183 /* Update any alternate field to synchronise with the main field. */ 5184 _updateAlternate: function(inst) { 5185 var altFormat, date, dateStr, 5186 altField = this._get(inst, "altField"); 5187 5188 if (altField) { // update alternate field too 5189 altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat"); 5190 date = this._getDate(inst); 5191 dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst)); 5192 $(altField).each(function() { $(this).val(dateStr); }); 5193 } 5194 }, 5195 5196 /* Set as beforeShowDay function to prevent selection of weekends. 5197 * @param date Date - the date to customise 5198 * @return [boolean, string] - is this date selectable?, what is its CSS class? 5199 */ 5200 noWeekends: function(date) { 5201 var day = date.getDay(); 5202 return [(day > 0 && day < 6), ""]; 5203 }, 5204 5205 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. 5206 * @param date Date - the date to get the week for 5207 * @return number - the number of the week within the year that contains this date 5208 */ 5209 iso8601Week: function(date) { 5210 var time, 5211 checkDate = new Date(date.getTime()); 5212 5213 // Find Thursday of this week starting on Monday 5214 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); 5215 5216 time = checkDate.getTime(); 5217 checkDate.setMonth(0); // Compare with Jan 1 5218 checkDate.setDate(1); 5219 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; 5220 }, 5221 5222 /* Parse a string value into a date object. 5223 * See formatDate below for the possible formats. 5224 *
vendor: 4,117 bytes, lines 5225-5330
5225 * @param format string - the expected format of the date 5226 * @param value string - the date in the above format 5227 * @param settings Object - attributes include: 5228 * shortYearCutoff number - the cutoff year for determining the century (optional) 5229 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 5230 * dayNames string[7] - names of the days from Sunday (optional) 5231 * monthNamesShort string[12] - abbreviated names of the months (optional) 5232 * monthNames string[12] - names of the months (optional) 5233 * @return Date - the extracted date value or null if value is blank 5234 */ 5235 parseDate: function (format, value, settings) { 5236 if (format == null || value == null) { 5237 throw "Invalid arguments"; 5238 } 5239 5240 value = (typeof value === "object" ? value.toString() : value + ""); 5241 if (value === "") { 5242 return null; 5243 } 5244 5245 var iFormat, dim, extra, 5246 iValue = 0, 5247 shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff, 5248 shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp : 5249 new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)), 5250 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, 5251 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, 5252 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, 5253 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, 5254 year = -1, 5255 month = -1, 5256 day = -1, 5257 doy = -1, 5258 literal = false, 5259 date, 5260 // Check whether a format character is doubled 5261 lookAhead = function(match) { 5262 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 5263 if (matches) { 5264 iFormat++; 5265 } 5266 return matches; 5267 }, 5268 // Extract a number from the string value 5269 getNumber = function(match) { 5270 var isDoubled = lookAhead(match), 5271 size = (match === "@" ? 14 : (match === "!" ? 20 : 5272 (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))), 5273 digits = new RegExp("^\\d{1," + size + "}"), 5274 num = value.substring(iValue).match(digits); 5275 if (!num) { 5276 throw "Missing number at position " + iValue; 5277 } 5278 iValue += num[0].length; 5279 return parseInt(num[0], 10); 5280 }, 5281 // Extract a name from the string value and convert to an index 5282 getName = function(match, shortNames, longNames) { 5283 var index = -1, 5284 names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) { 5285 return [ [k, v] ]; 5286 }).sort(function (a, b) { 5287 return -(a[1].length - b[1].length); 5288 }); 5289 5290 $.each(names, function (i, pair) { 5291 var name = pair[1]; 5292 if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) { 5293 index = pair[0]; 5294 iValue += name.length; 5295 return false; 5296 } 5297 }); 5298 if (index !== -1) { 5299 return index + 1; 5300 } else { 5301 throw "Unknown name at position " + iValue; 5302 } 5303 }, 5304 // Confirm that a literal character matches the string value 5305 checkLiteral = function() { 5306 if (value.charAt(iValue) !== format.charAt(iFormat)) { 5307 throw "Unexpected literal at position " + iValue; 5308 } 5309 iValue++; 5310 }; 5311 5312 for (iFormat = 0; iFormat < format.length; iFormat++) { 5313 if (literal) { 5314 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 5315 literal = false; 5316 } else { 5317 checkLiteral(); 5318 } 5319 } else { 5320 switch (format.charAt(iFormat)) { 5321 case "d": 5322 day = getNumber("d"); 5323 break; 5324 case "D": 5325 getName("D", dayNamesShort, dayNames); 5326 break; 5327 case "o": 5328 doy = getNumber("o"); 5329 break; 5330 case "m":
vendor: 15,219 bytes, lines 5331-5767
5331 month = getNumber("m"); 5332 break; 5333 case "M": 5334 month = getName("M", monthNamesShort, monthNames); 5335 break; 5336 case "y": 5337 year = getNumber("y"); 5338 break; 5339 case "@": 5340 date = new Date(getNumber("@")); 5341 year = date.getFullYear(); 5342 month = date.getMonth() + 1; 5343 day = date.getDate(); 5344 break; 5345 case "!": 5346 date = new Date((getNumber("!") - this._ticksTo1970) / 10000); 5347 year = date.getFullYear(); 5348 month = date.getMonth() + 1; 5349 day = date.getDate(); 5350 break; 5351 case "'": 5352 if (lookAhead("'")){ 5353 checkLiteral(); 5354 } else { 5355 literal = true; 5356 } 5357 break; 5358 default: 5359 checkLiteral(); 5360 } 5361 } 5362 } 5363 5364 if (iValue < value.length){ 5365 extra = value.substr(iValue); 5366 if (!/^\s+/.test(extra)) { 5367 throw "Extra/unparsed characters found in date: " + extra; 5368 } 5369 } 5370 5371 if (year === -1) { 5372 year = new Date().getFullYear(); 5373 } else if (year < 100) { 5374 year += new Date().getFullYear() - new Date().getFullYear() % 100 + 5375 (year <= shortYearCutoff ? 0 : -100); 5376 } 5377 5378 if (doy > -1) { 5379 month = 1; 5380 day = doy; 5381 do { 5382 dim = this._getDaysInMonth(year, month - 1); 5383 if (day <= dim) { 5384 break; 5385 } 5386 month++; 5387 day -= dim; 5388 } while (true); 5389 } 5390 5391 date = this._daylightSavingAdjust(new Date(year, month - 1, day)); 5392 if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) { 5393 throw "Invalid date"; // E.g. 31/02/00 5394 } 5395 return date; 5396 }, 5397 5398 /* Standard date formats. */ 5399 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601) 5400 COOKIE: "D, dd M yy", 5401 ISO_8601: "yy-mm-dd", 5402 RFC_822: "D, d M y", 5403 RFC_850: "DD, dd-M-y", 5404 RFC_1036: "D, d M y", 5405 RFC_1123: "D, d M yy", 5406 RFC_2822: "D, d M yy", 5407 RSS: "D, d M y", // RFC 822 5408 TICKS: "!", 5409 TIMESTAMP: "@", 5410 W3C: "yy-mm-dd", // ISO 8601 5411 5412 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + 5413 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000), 5414 5415 /* Format a date object into a string value. 5416 * The format can be combinations of the following: 5417 * d - day of month (no leading zero) 5418 * dd - day of month (two digit) 5419 * o - day of year (no leading zeros) 5420 * oo - day of year (three digit) 5421 * D - day name short 5422 * DD - day name long 5423 * m - month of year (no leading zero) 5424 * mm - month of year (two digit) 5425 * M - month name short 5426 * MM - month name long 5427 * y - year (two digit) 5428 * yy - year (four digit) 5429 * @ - Unix timestamp (ms since 01/01/1970) 5430 * ! - Windows ticks (100ns since 01/01/0001) 5431 * "..." - literal text 5432 * '' - single quote 5433 * 5434 * @param format string - the desired format of the date 5435 * @param date Date - the date value to format 5436 * @param settings Object - attributes include: 5437 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 5438 * dayNames string[7] - names of the days from Sunday (optional) 5439 * monthNamesShort string[12] - abbreviated names of the months (optional) 5440 * monthNames string[12] - names of the months (optional) 5441 * @return string - the date in the above format 5442 */ 5443 formatDate: function (format, date, settings) { 5444 if (!date) { 5445 return ""; 5446 } 5447 5448 var iFormat, 5449 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, 5450 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, 5451 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, 5452 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, 5453 // Check whether a format character is doubled 5454 lookAhead = function(match) { 5455 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 5456 if (matches) { 5457 iFormat++; 5458 } 5459 return matches; 5460 }, 5461 // Format a number, with leading zero if necessary 5462 formatNumber = function(match, value, len) { 5463 var num = "" + value; 5464 if (lookAhead(match)) { 5465 while (num.length < len) { 5466 num = "0" + num; 5467 } 5468 } 5469 return num; 5470 }, 5471 // Format a name, short or long as requested 5472 formatName = function(match, value, shortNames, longNames) { 5473 return (lookAhead(match) ? longNames[value] : shortNames[value]); 5474 }, 5475 output = "", 5476 literal = false; 5477 5478 if (date) { 5479 for (iFormat = 0; iFormat < format.length; iFormat++) { 5480 if (literal) { 5481 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 5482 literal = false; 5483 } else { 5484 output += format.charAt(iFormat); 5485 } 5486 } else { 5487 switch (format.charAt(iFormat)) { 5488 case "d": 5489 output += formatNumber("d", date.getDate(), 2); 5490 break; 5491 case "D": 5492 output += formatName("D", date.getDay(), dayNamesShort, dayNames); 5493 break; 5494 case "o": 5495 output += formatNumber("o", 5496 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); 5497 break; 5498 case "m": 5499 output += formatNumber("m", date.getMonth() + 1, 2); 5500 break; 5501 case "M": 5502 output += formatName("M", date.getMonth(), monthNamesShort, monthNames); 5503 break; 5504 case "y": 5505 output += (lookAhead("y") ? date.getFullYear() : 5506 (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100); 5507 break; 5508 case "@": 5509 output += date.getTime(); 5510 break; 5511 case "!": 5512 output += date.getTime() * 10000 + this._ticksTo1970; 5513 break; 5514 case "'": 5515 if (lookAhead("'")) { 5516 output += "'"; 5517 } else { 5518 literal = true; 5519 } 5520 break; 5521 default: 5522 output += format.charAt(iFormat); 5523 } 5524 } 5525 } 5526 } 5527 return output; 5528 }, 5529 5530 /* Extract all possible characters from the date format. */ 5531 _possibleChars: function (format) { 5532 var iFormat, 5533 chars = "", 5534 literal = false, 5535 // Check whether a format character is doubled 5536 lookAhead = function(match) { 5537 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 5538 if (matches) { 5539 iFormat++; 5540 } 5541 return matches; 5542 }; 5543 5544 for (iFormat = 0; iFormat < format.length; iFormat++) { 5545 if (literal) { 5546 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 5547 literal = false; 5548 } else { 5549 chars += format.charAt(iFormat); 5550 } 5551 } else { 5552 switch (format.charAt(iFormat)) { 5553 case "d": case "m": case "y": case "@": 5554 chars += "0123456789"; 5555 break; 5556 case "D": case "M": 5557 return null; // Accept anything 5558 case "'": 5559 if (lookAhead("'")) { 5560 chars += "'"; 5561 } else { 5562 literal = true; 5563 } 5564 break; 5565 default: 5566 chars += format.charAt(iFormat); 5567 } 5568 } 5569 } 5570 return chars; 5571 }, 5572 5573 /* Get a setting value, defaulting if necessary. */ 5574 _get: function(inst, name) { 5575 return inst.settings[name] !== undefined ? 5576 inst.settings[name] : this._defaults[name]; 5577 }, 5578 5579 /* Parse existing date and initialise date picker. */ 5580 _setDateFromField: function(inst, noDefault) { 5581 if (inst.input.val() === inst.lastVal) { 5582 return; 5583 } 5584 5585 var dateFormat = this._get(inst, "dateFormat"), 5586 dates = inst.lastVal = inst.input ? inst.input.val() : null, 5587 defaultDate = this._getDefaultDate(inst), 5588 date = defaultDate, 5589 settings = this._getFormatConfig(inst); 5590 5591 try { 5592 date = this.parseDate(dateFormat, dates, settings) || defaultDate; 5593 } catch (event) { 5594 dates = (noDefault ? "" : dates); 5595 } 5596 inst.selectedDay = date.getDate(); 5597 inst.drawMonth = inst.selectedMonth = date.getMonth(); 5598 inst.drawYear = inst.selectedYear = date.getFullYear(); 5599 inst.currentDay = (dates ? date.getDate() : 0); 5600 inst.currentMonth = (dates ? date.getMonth() : 0); 5601 inst.currentYear = (dates ? date.getFullYear() : 0); 5602 this._adjustInstDate(inst); 5603 }, 5604 5605 /* Retrieve the default date shown on opening. */ 5606 _getDefaultDate: function(inst) { 5607 return this._restrictMinMax(inst, 5608 this._determineDate(inst, this._get(inst, "defaultDate"), new Date())); 5609 }, 5610 5611 /* A date may be specified as an exact value or a relative one. */ 5612 _determineDate: function(inst, date, defaultDate) { 5613 var offsetNumeric = function(offset) { 5614 var date = new Date(); 5615 date.setDate(date.getDate() + offset); 5616 return date; 5617 }, 5618 offsetString = function(offset) { 5619 try { 5620 return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), 5621 offset, $.datepicker._getFormatConfig(inst)); 5622 } 5623 catch (e) { 5624 // Ignore 5625 } 5626 5627 var date = (offset.toLowerCase().match(/^c/) ? 5628 $.datepicker._getDate(inst) : null) || new Date(), 5629 year = date.getFullYear(), 5630 month = date.getMonth(), 5631 day = date.getDate(), 5632 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g, 5633 matches = pattern.exec(offset); 5634 5635 while (matches) { 5636 switch (matches[2] || "d") { 5637 case "d" : case "D" : 5638 day += parseInt(matches[1],10); break; 5639 case "w" : case "W" : 5640 day += parseInt(matches[1],10) * 7; break; 5641 case "m" : case "M" : 5642 month += parseInt(matches[1],10); 5643 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); 5644 break; 5645 case "y": case "Y" : 5646 year += parseInt(matches[1],10); 5647 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); 5648 break; 5649 } 5650 matches = pattern.exec(offset); 5651 } 5652 return new Date(year, month, day); 5653 }, 5654 newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) : 5655 (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime())))); 5656 5657 newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate); 5658 if (newDate) { 5659 newDate.setHours(0); 5660 newDate.setMinutes(0); 5661 newDate.setSeconds(0); 5662 newDate.setMilliseconds(0); 5663 } 5664 return this._daylightSavingAdjust(newDate); 5665 }, 5666 5667 /* Handle switch to/from daylight saving. 5668 * Hours may be non-zero on daylight saving cut-over: 5669 * > 12 when midnight changeover, but then cannot generate 5670 * midnight datetime, so jump to 1AM, otherwise reset. 5671 * @param date (Date) the date to check 5672 * @return (Date) the corrected date 5673 */ 5674 _daylightSavingAdjust: function(date) { 5675 if (!date) { 5676 return null; 5677 } 5678 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); 5679 return date; 5680 }, 5681 5682 /* Set the date(s) directly. */ 5683 _setDate: function(inst, date, noChange) { 5684 var clear = !date, 5685 origMonth = inst.selectedMonth, 5686 origYear = inst.selectedYear, 5687 newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date())); 5688 5689 inst.selectedDay = inst.currentDay = newDate.getDate(); 5690 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); 5691 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); 5692 if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) { 5693 this._notifyChange(inst); 5694 } 5695 this._adjustInstDate(inst); 5696 if (inst.input) { 5697 inst.input.val(clear ? "" : this._formatDate(inst)); 5698 } 5699 }, 5700 5701 /* Retrieve the date(s) directly. */ 5702 _getDate: function(inst) { 5703 var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null : 5704 this._daylightSavingAdjust(new Date( 5705 inst.currentYear, inst.currentMonth, inst.currentDay))); 5706 return startDate; 5707 }, 5708 5709 /* Attach the onxxx handlers. These are declared statically so 5710 * they work with static code transformers like Caja. 5711 */ 5712 _attachHandlers: function(inst) { 5713 var stepMonths = this._get(inst, "stepMonths"), 5714 id = "#" + inst.id.replace( /\\\\/g, "\\" ); 5715 inst.dpDiv.find("[data-handler]").map(function () { 5716 var handler = { 5717 prev: function () { 5718 $.datepicker._adjustDate(id, -stepMonths, "M"); 5719 }, 5720 next: function () { 5721 $.datepicker._adjustDate(id, +stepMonths, "M"); 5722 }, 5723 hide: function () { 5724 $.datepicker._hideDatepicker(); 5725 }, 5726 today: function () { 5727 $.datepicker._gotoToday(id); 5728 }, 5729 selectDay: function () { 5730 $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this); 5731 return false; 5732 }, 5733 selectMonth: function () { 5734 $.datepicker._selectMonthYear(id, this, "M"); 5735 return false; 5736 }, 5737 selectYear: function () { 5738 $.datepicker._selectMonthYear(id, this, "Y"); 5739 return false; 5740 } 5741 }; 5742 $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]); 5743 }); 5744 }, 5745 5746 /* Generate the HTML for the current state of the date picker. */ 5747 _generateHTML: function(inst) { 5748 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate, 5749 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin, 5750 monthNames, monthNamesShort, beforeShowDay, showOtherMonths, 5751 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate, 5752 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows, 5753 printDate, dRow, tbody, daySettings, otherMonth, unselectable, 5754 tempDate = new Date(), 5755 today = this._daylightSavingAdjust( 5756 new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time 5757 isRTL = this._get(inst, "isRTL"), 5758 showButtonPanel = this._get(inst, "showButtonPanel"), 5759 hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"), 5760 navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"), 5761 numMonths = this._getNumberOfMonths(inst), 5762 showCurrentAtPos = this._get(inst, "showCurrentAtPos"), 5763 stepMonths = this._get(inst, "stepMonths"), 5764 isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1), 5765 currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) : 5766 new Date(inst.currentYear, inst.currentMonth, inst.currentDay))), 5767 minDate = this._getMinMaxDate(inst, "min"),
vendor: 4,276 bytes, lines 5768-5848
5768 maxDate = this._getMinMaxDate(inst, "max"), 5769 drawMonth = inst.drawMonth - showCurrentAtPos, 5770 drawYear = inst.drawYear; 5771 5772 if (drawMonth < 0) { 5773 drawMonth += 12; 5774 drawYear--; 5775 } 5776 if (maxDate) { 5777 maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), 5778 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate())); 5779 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); 5780 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { 5781 drawMonth--; 5782 if (drawMonth < 0) { 5783 drawMonth = 11; 5784 drawYear--; 5785 } 5786 } 5787 } 5788 inst.drawMonth = drawMonth; 5789 inst.drawYear = drawYear; 5790 5791 prevText = this._get(inst, "prevText"); 5792 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, 5793 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), 5794 this._getFormatConfig(inst))); 5795 5796 prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? 5797 "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" + 5798 " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" : 5799 (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+ prevText +"'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>")); 5800 5801 nextText = this._get(inst, "nextText"); 5802 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, 5803 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), 5804 this._getFormatConfig(inst))); 5805 5806 next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ? 5807 "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" + 5808 " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" : 5809 (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+ nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>")); 5810 5811 currentText = this._get(inst, "currentText"); 5812 gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today); 5813 currentText = (!navigationAsDateFormat ? currentText : 5814 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); 5815 5816 controls = (!inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" + 5817 this._get(inst, "closeText") + "</button>" : ""); 5818 5819 buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") + 5820 (this._isInRange(inst, gotoDate) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" + 5821 ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : ""; 5822 5823 firstDay = parseInt(this._get(inst, "firstDay"),10); 5824 firstDay = (isNaN(firstDay) ? 0 : firstDay); 5825 5826 showWeek = this._get(inst, "showWeek"); 5827 dayNames = this._get(inst, "dayNames"); 5828 dayNamesMin = this._get(inst, "dayNamesMin"); 5829 monthNames = this._get(inst, "monthNames"); 5830 monthNamesShort = this._get(inst, "monthNamesShort"); 5831 beforeShowDay = this._get(inst, "beforeShowDay"); 5832 showOtherMonths = this._get(inst, "showOtherMonths"); 5833 selectOtherMonths = this._get(inst, "selectOtherMonths"); 5834 defaultDate = this._getDefaultDate(inst); 5835 html = ""; 5836 dow; 5837 for (row = 0; row < numMonths[0]; row++) { 5838 group = ""; 5839 this.maxRows = 4; 5840 for (col = 0; col < numMonths[1]; col++) { 5841 selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); 5842 cornerClass = " ui-corner-all"; 5843 calender = ""; 5844 if (isMultiMonth) { 5845 calender += "<div class='ui-datepicker-group"; 5846 if (numMonths[1] > 1) { 5847 switch (col) { 5848 case 0: calender += " ui-datepicker-group-first";
vendor: 5,473 bytes, lines 5849-5926
5849 cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break; 5850 case numMonths[1]-1: calender += " ui-datepicker-group-last"; 5851 cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break; 5852 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break; 5853 } 5854 } 5855 calender += "'>"; 5856 } 5857 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" + 5858 (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") + 5859 (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") + 5860 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, 5861 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers 5862 "</div><table class='ui-datepicker-calendar'><thead>" + 5863 "<tr>"; 5864 thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : ""); 5865 for (dow = 0; dow < 7; dow++) { // days of the week 5866 day = (dow + firstDay) % 7; 5867 thead += "<th" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" + 5868 "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>"; 5869 } 5870 calender += thead + "</tr></thead><tbody>"; 5871 daysInMonth = this._getDaysInMonth(drawYear, drawMonth); 5872 if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) { 5873 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); 5874 } 5875 leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; 5876 curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate 5877 numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043) 5878 this.maxRows = numRows; 5879 printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); 5880 for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows 5881 calender += "<tr>"; 5882 tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" + 5883 this._get(inst, "calculateWeek")(printDate) + "</td>"); 5884 for (dow = 0; dow < 7; dow++) { // create date picker days 5885 daySettings = (beforeShowDay ? 5886 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]); 5887 otherMonth = (printDate.getMonth() !== drawMonth); 5888 unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] || 5889 (minDate && printDate < minDate) || (maxDate && printDate > maxDate); 5890 tbody += "<td class='" + 5891 ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends 5892 (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months 5893 ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key 5894 (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ? 5895 // or defaultDate is current printedDate and defaultDate is selectedDate 5896 " " + this._dayOverClass : "") + // highlight selected day 5897 (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days 5898 (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates 5899 (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day 5900 (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different) 5901 ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "'") + "'" : "") + // cell title 5902 (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions 5903 (otherMonth && !showOtherMonths ? " " : // display for other months 5904 (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" + 5905 (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") + 5906 (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day 5907 (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months 5908 "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date 5909 printDate.setDate(printDate.getDate() + 1); 5910 printDate = this._daylightSavingAdjust(printDate); 5911 } 5912 calender += tbody + "</tr>"; 5913 } 5914 drawMonth++; 5915 if (drawMonth > 11) { 5916 drawMonth = 0; 5917 drawYear++; 5918 } 5919 calender += "</tbody></table>" + (isMultiMonth ? "</div>" + 5920 ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : ""); 5921 group += calender; 5922 } 5923 html += group; 5924 } 5925 html += buttonPanel; 5926 inst._keyEvent = false;
vendor: 4,246 bytes, lines 5927-6029
5927 return html; 5928 }, 5929 5930 /* Generate the month and year header. */ 5931 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, 5932 secondary, monthNames, monthNamesShort) { 5933 5934 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear, 5935 changeMonth = this._get(inst, "changeMonth"), 5936 changeYear = this._get(inst, "changeYear"), 5937 showMonthAfterYear = this._get(inst, "showMonthAfterYear"), 5938 html = "<div class='ui-datepicker-title'>", 5939 monthHtml = ""; 5940 5941 // month selection 5942 if (secondary || !changeMonth) { 5943 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>"; 5944 } else { 5945 inMinYear = (minDate && minDate.getFullYear() === drawYear); 5946 inMaxYear = (maxDate && maxDate.getFullYear() === drawYear); 5947 monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>"; 5948 for ( month = 0; month < 12; month++) { 5949 if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) { 5950 monthHtml += "<option value='" + month + "'" + 5951 (month === drawMonth ? " selected='selected'" : "") + 5952 ">" + monthNamesShort[month] + "</option>"; 5953 } 5954 } 5955 monthHtml += "</select>"; 5956 } 5957 5958 if (!showMonthAfterYear) { 5959 html += monthHtml + (secondary || !(changeMonth && changeYear) ? " " : ""); 5960 } 5961 5962 // year selection 5963 if ( !inst.yearshtml ) { 5964 inst.yearshtml = ""; 5965 if (secondary || !changeYear) { 5966 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>"; 5967 } else { 5968 // determine range of years to display 5969 years = this._get(inst, "yearRange").split(":"); 5970 thisYear = new Date().getFullYear(); 5971 determineYear = function(value) { 5972 var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) : 5973 (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) : 5974 parseInt(value, 10))); 5975 return (isNaN(year) ? thisYear : year); 5976 }; 5977 year = determineYear(years[0]); 5978 endYear = Math.max(year, determineYear(years[1] || "")); 5979 year = (minDate ? Math.max(year, minDate.getFullYear()) : year); 5980 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); 5981 inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>"; 5982 for (; year <= endYear; year++) { 5983 inst.yearshtml += "<option value='" + year + "'" + 5984 (year === drawYear ? " selected='selected'" : "") + 5985 ">" + year + "</option>"; 5986 } 5987 inst.yearshtml += "</select>"; 5988 5989 html += inst.yearshtml; 5990 inst.yearshtml = null; 5991 } 5992 } 5993 5994 html += this._get(inst, "yearSuffix"); 5995 if (showMonthAfterYear) { 5996 html += (secondary || !(changeMonth && changeYear) ? " " : "") + monthHtml; 5997 } 5998 html += "</div>"; // Close datepicker_header 5999 return html; 6000 }, 6001 6002 /* Adjust one of the date sub-fields. */ 6003 _adjustInstDate: function(inst, offset, period) { 6004 var year = inst.drawYear + (period === "Y" ? offset : 0), 6005 month = inst.drawMonth + (period === "M" ? offset : 0), 6006 day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0), 6007 date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day))); 6008 6009 inst.selectedDay = date.getDate(); 6010 inst.drawMonth = inst.selectedMonth = date.getMonth(); 6011 inst.drawYear = inst.selectedYear = date.getFullYear(); 6012 if (period === "M" || period === "Y") { 6013 this._notifyChange(inst); 6014 } 6015 }, 6016 6017 /* Ensure a date is within any min/max bounds. */ 6018 _restrictMinMax: function(inst, date) { 6019 var minDate = this._getMinMaxDate(inst, "min"), 6020 maxDate = this._getMinMaxDate(inst, "max"), 6021 newDate = (minDate && date < minDate ? minDate : date); 6022 return (maxDate && newDate > maxDate ? maxDate : newDate); 6023 }, 6024 6025 /* Notify change of month/year. */ 6026 _notifyChange: function(inst) { 6027 var onChange = this._get(inst, "onChangeMonthYear"); 6028 if (onChange) { 6029 onChange.apply((inst.input ? inst.input[0] : null),
vendor: 6,498 bytes, lines 6030-6199
6030 [inst.selectedYear, inst.selectedMonth + 1, inst]); 6031 } 6032 }, 6033 6034 /* Determine the number of months to show. */ 6035 _getNumberOfMonths: function(inst) { 6036 var numMonths = this._get(inst, "numberOfMonths"); 6037 return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths)); 6038 }, 6039 6040 /* Determine the current maximum date - ensure no time components are set. */ 6041 _getMinMaxDate: function(inst, minMax) { 6042 return this._determineDate(inst, this._get(inst, minMax + "Date"), null); 6043 }, 6044 6045 /* Find the number of days in a given month. */ 6046 _getDaysInMonth: function(year, month) { 6047 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); 6048 }, 6049 6050 /* Find the day of the week of the first of a month. */ 6051 _getFirstDayOfMonth: function(year, month) { 6052 return new Date(year, month, 1).getDay(); 6053 }, 6054 6055 /* Determines if we should allow a "next/prev" month display change. */ 6056 _canAdjustMonth: function(inst, offset, curYear, curMonth) { 6057 var numMonths = this._getNumberOfMonths(inst), 6058 date = this._daylightSavingAdjust(new Date(curYear, 6059 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); 6060 6061 if (offset < 0) { 6062 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); 6063 } 6064 return this._isInRange(inst, date); 6065 }, 6066 6067 /* Is the given date in the accepted range? */ 6068 _isInRange: function(inst, date) { 6069 var yearSplit, currentYear, 6070 minDate = this._getMinMaxDate(inst, "min"), 6071 maxDate = this._getMinMaxDate(inst, "max"), 6072 minYear = null, 6073 maxYear = null, 6074 years = this._get(inst, "yearRange"); 6075 if (years){ 6076 yearSplit = years.split(":"); 6077 currentYear = new Date().getFullYear(); 6078 minYear = parseInt(yearSplit[0], 10); 6079 maxYear = parseInt(yearSplit[1], 10); 6080 if ( yearSplit[0].match(/[+\-].*/) ) { 6081 minYear += currentYear; 6082 } 6083 if ( yearSplit[1].match(/[+\-].*/) ) { 6084 maxYear += currentYear; 6085 } 6086 } 6087 6088 return ((!minDate || date.getTime() >= minDate.getTime()) && 6089 (!maxDate || date.getTime() <= maxDate.getTime()) && 6090 (!minYear || date.getFullYear() >= minYear) && 6091 (!maxYear || date.getFullYear() <= maxYear)); 6092 }, 6093 6094 /* Provide the configuration settings for formatting/parsing. */ 6095 _getFormatConfig: function(inst) { 6096 var shortYearCutoff = this._get(inst, "shortYearCutoff"); 6097 shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff : 6098 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); 6099 return {shortYearCutoff: shortYearCutoff, 6100 dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"), 6101 monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")}; 6102 }, 6103 6104 /* Format the given date for display. */ 6105 _formatDate: function(inst, day, month, year) { 6106 if (!day) { 6107 inst.currentDay = inst.selectedDay; 6108 inst.currentMonth = inst.selectedMonth; 6109 inst.currentYear = inst.selectedYear; 6110 } 6111 var date = (day ? (typeof day === "object" ? day : 6112 this._daylightSavingAdjust(new Date(year, month, day))) : 6113 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); 6114 return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst)); 6115 } 6116}); 6117 6118/* 6119 * Bind hover events for datepicker elements. 6120 * Done via delegate so the binding only occurs once in the lifetime of the parent div. 6121 * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. 6122 */ 6123function bindHover(dpDiv) { 6124 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a"; 6125 return dpDiv.delegate(selector, "mouseout", function() { 6126 $(this).removeClass("ui-state-hover"); 6127 if (this.className.indexOf("ui-datepicker-prev") !== -1) { 6128 $(this).removeClass("ui-datepicker-prev-hover"); 6129 } 6130 if (this.className.indexOf("ui-datepicker-next") !== -1) { 6131 $(this).removeClass("ui-datepicker-next-hover"); 6132 } 6133 }) 6134 .delegate(selector, "mouseover", function(){ 6135 if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) { 6136 $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"); 6137 $(this).addClass("ui-state-hover"); 6138 if (this.className.indexOf("ui-datepicker-prev") !== -1) { 6139 $(this).addClass("ui-datepicker-prev-hover"); 6140 } 6141 if (this.className.indexOf("ui-datepicker-next") !== -1) { 6142 $(this).addClass("ui-datepicker-next-hover"); 6143 } 6144 } 6145 }); 6146} 6147 6148/* jQuery extend now ignores nulls! */ 6149function extendRemove(target, props) { 6150 $.extend(target, props); 6151 for (var name in props) { 6152 if (props[name] == null) { 6153 target[name] = props[name]; 6154 } 6155 } 6156 return target; 6157} 6158 6159/* Invoke the datepicker functionality. 6160 @param options string - a command, optionally followed by additional parameters or 6161 Object - settings for attaching new datepicker functionality 6162 @return jQuery object */ 6163$.fn.datepicker = function(options){ 6164 6165 /* Verify an empty collection wasn't passed - Fixes #6976 */ 6166 if ( !this.length ) { 6167 return this; 6168 } 6169 6170 /* Initialise the date picker. */ 6171 if (!$.datepicker.initialized) { 6172 $(document).mousedown($.datepicker._checkExternalClick); 6173 $.datepicker.initialized = true; 6174 } 6175 6176 /* Append datepicker main container to body if not exist. */ 6177 if ($("#"+$.datepicker._mainDivId).length === 0) { 6178 $("body").append($.datepicker.dpDiv); 6179 } 6180 6181 var otherArgs = Array.prototype.slice.call(arguments, 1); 6182 if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) { 6183 return $.datepicker["_" + options + "Datepicker"]. 6184 apply($.datepicker, [this[0]].concat(otherArgs)); 6185 } 6186 if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") { 6187 return $.datepicker["_" + options + "Datepicker"]. 6188 apply($.datepicker, [this[0]].concat(otherArgs)); 6189 } 6190 return this.each(function() { 6191 typeof options === "string" ? 6192 $.datepicker["_" + options + "Datepicker"]. 6193 apply($.datepicker, [this].concat(otherArgs)) : 6194 $.datepicker._attachDatepicker(this, options); 6195 }); 6196}; 6197 6198$.datepicker = new Datepicker(); // singleton instance 6199$.datepicker.initialized = false;
vendor: 19,925 bytes, lines 6200-6928
6200$.datepicker.uuid = new Date().getTime(); 6201$.datepicker.version = "1.10.4"; 6202 6203})( _4ORMAT.$ ); 6204(function( $, undefined ) { 6205 6206var sizeRelatedOptions = { 6207 buttons: true, 6208 height: true, 6209 maxHeight: true, 6210 maxWidth: true, 6211 minHeight: true, 6212 minWidth: true, 6213 width: true 6214 }, 6215 resizableRelatedOptions = { 6216 maxHeight: true, 6217 maxWidth: true, 6218 minHeight: true, 6219 minWidth: true 6220 }; 6221 6222$.widget( "ui.dialog", { 6223 version: "1.10.4", 6224 options: { 6225 appendTo: "body", 6226 autoOpen: true, 6227 buttons: [], 6228 closeOnEscape: true, 6229 closeText: "close", 6230 dialogClass: "", 6231 draggable: true, 6232 hide: null, 6233 height: "auto", 6234 maxHeight: null, 6235 maxWidth: null, 6236 minHeight: 150, 6237 minWidth: 150, 6238 modal: false, 6239 position: { 6240 my: "center", 6241 at: "center", 6242 of: window, 6243 collision: "fit", 6244 // Ensure the titlebar is always visible 6245 using: function( pos ) { 6246 var topOffset = $( this ).css( pos ).offset().top; 6247 if ( topOffset < 0 ) { 6248 $( this ).css( "top", pos.top - topOffset ); 6249 } 6250 } 6251 }, 6252 resizable: true, 6253 show: null, 6254 title: null, 6255 width: 300, 6256 6257 // callbacks 6258 beforeClose: null, 6259 close: null, 6260 drag: null, 6261 dragStart: null, 6262 dragStop: null, 6263 focus: null, 6264 open: null, 6265 resize: null, 6266 resizeStart: null, 6267 resizeStop: null 6268 }, 6269 6270 _create: function() { 6271 this.originalCss = { 6272 display: this.element[0].style.display, 6273 width: this.element[0].style.width, 6274 minHeight: this.element[0].style.minHeight, 6275 maxHeight: this.element[0].style.maxHeight, 6276 height: this.element[0].style.height 6277 }; 6278 this.originalPosition = { 6279 parent: this.element.parent(), 6280 index: this.element.parent().children().index( this.element ) 6281 }; 6282 this.originalTitle = this.element.attr("title"); 6283 this.options.title = this.options.title || this.originalTitle; 6284 6285 this._createWrapper(); 6286 6287 this.element 6288 .show() 6289 .removeAttr("title") 6290 .addClass("ui-dialog-content ui-widget-content") 6291 .appendTo( this.uiDialog ); 6292 6293 this._createTitlebar(); 6294 this._createButtonPane(); 6295 6296 if ( this.options.draggable && $.fn.draggable ) { 6297 this._makeDraggable(); 6298 } 6299 if ( this.options.resizable && $.fn.resizable ) { 6300 this._makeResizable(); 6301 } 6302 6303 this._isOpen = false; 6304 }, 6305 6306 _init: function() { 6307 if ( this.options.autoOpen ) { 6308 this.open(); 6309 } 6310 }, 6311 6312 _appendTo: function() { 6313 var element = this.options.appendTo; 6314 if ( element && (element.jquery || element.nodeType) ) { 6315 return $( element ); 6316 } 6317 return this.document.find( element || "body" ).eq( 0 ); 6318 }, 6319 6320 _destroy: function() { 6321 var next, 6322 originalPosition = this.originalPosition; 6323 6324 this._destroyOverlay(); 6325 6326 this.element 6327 .removeUniqueId() 6328 .removeClass("ui-dialog-content ui-widget-content") 6329 .css( this.originalCss ) 6330 // Without detaching first, the following becomes really slow 6331 .detach(); 6332 6333 this.uiDialog.stop( true, true ).remove(); 6334 6335 if ( this.originalTitle ) { 6336 this.element.attr( "title", this.originalTitle ); 6337 } 6338 6339 next = originalPosition.parent.children().eq( originalPosition.index ); 6340 // Don't try to place the dialog next to itself (#8613) 6341 if ( next.length && next[0] !== this.element[0] ) { 6342 next.before( this.element ); 6343 } else { 6344 originalPosition.parent.append( this.element ); 6345 } 6346 }, 6347 6348 widget: function() { 6349 return this.uiDialog; 6350 }, 6351 6352 disable: $.noop, 6353 enable: $.noop, 6354 6355 close: function( event ) { 6356 var activeElement, 6357 that = this; 6358 6359 if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) { 6360 return; 6361 } 6362 6363 this._isOpen = false; 6364 this._destroyOverlay(); 6365 6366 if ( !this.opener.filter(":focusable").focus().length ) { 6367 6368 // support: IE9 6369 // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe> 6370 try { 6371 activeElement = this.document[ 0 ].activeElement; 6372 6373 // Support: IE9, IE10 6374 // If the <body> is blurred, IE will switch windows, see #4520 6375 if ( activeElement && activeElement.nodeName.toLowerCase() !== "body" ) { 6376 6377 // Hiding a focused element doesn't trigger blur in WebKit 6378 // so in case we have nothing to focus on, explicitly blur the active element 6379 // https://bugs.webkit.org/show_bug.cgi?id=47182 6380 $( activeElement ).blur(); 6381 } 6382 } catch ( error ) {} 6383 } 6384 6385 this._hide( this.uiDialog, this.options.hide, function() { 6386 that._trigger( "close", event ); 6387 }); 6388 }, 6389 6390 isOpen: function() { 6391 return this._isOpen; 6392 }, 6393 6394 moveToTop: function() { 6395 this._moveToTop(); 6396 }, 6397 6398 _moveToTop: function( event, silent ) { 6399 var moved = !!this.uiDialog.nextAll(":visible").insertBefore( this.uiDialog ).length; 6400 if ( moved && !silent ) { 6401 this._trigger( "focus", event ); 6402 } 6403 return moved; 6404 }, 6405 6406 open: function() { 6407 var that = this; 6408 if ( this._isOpen ) { 6409 if ( this._moveToTop() ) { 6410 this._focusTabbable(); 6411 } 6412 return; 6413 } 6414 6415 this._isOpen = true; 6416 this.opener = $( this.document[0].activeElement ); 6417 6418 this._size(); 6419 this._position(); 6420 this._createOverlay(); 6421 this._moveToTop( null, true ); 6422 this._show( this.uiDialog, this.options.show, function() { 6423 that._focusTabbable(); 6424 that._trigger("focus"); 6425 }); 6426 6427 this._trigger("open"); 6428 }, 6429 6430 _focusTabbable: function() { 6431 // Set focus to the first match: 6432 // 1. First element inside the dialog matching [autofocus] 6433 // 2. Tabbable element inside the content element 6434 // 3. Tabbable element inside the buttonpane 6435 // 4. The close button 6436 // 5. The dialog itself 6437 var hasFocus = this.element.find("[autofocus]"); 6438 if ( !hasFocus.length ) { 6439 hasFocus = this.element.find(":tabbable"); 6440 } 6441 if ( !hasFocus.length ) { 6442 hasFocus = this.uiDialogButtonPane.find(":tabbable"); 6443 } 6444 if ( !hasFocus.length ) { 6445 hasFocus = this.uiDialogTitlebarClose.filter(":tabbable"); 6446 } 6447 if ( !hasFocus.length ) { 6448 hasFocus = this.uiDialog; 6449 } 6450 hasFocus.eq( 0 ).focus(); 6451 }, 6452 6453 _keepFocus: function( event ) { 6454 function checkFocus() { 6455 var activeElement = this.document[0].activeElement, 6456 isActive = this.uiDialog[0] === activeElement || 6457 $.contains( this.uiDialog[0], activeElement ); 6458 if ( !isActive ) { 6459 this._focusTabbable(); 6460 } 6461 } 6462 event.preventDefault(); 6463 checkFocus.call( this ); 6464 // support: IE 6465 // IE <= 8 doesn't prevent moving focus even with event.preventDefault() 6466 // so we check again later 6467 this._delay( checkFocus ); 6468 }, 6469 6470 _createWrapper: function() { 6471 this.uiDialog = $("<div>") 6472 .addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " + 6473 this.options.dialogClass ) 6474 .hide() 6475 .attr({ 6476 // Setting tabIndex makes the div focusable 6477 tabIndex: -1, 6478 role: "dialog" 6479 }) 6480 .appendTo( this._appendTo() ); 6481 6482 this._on( this.uiDialog, { 6483 keydown: function( event ) { 6484 if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && 6485 event.keyCode === $.ui.keyCode.ESCAPE ) { 6486 event.preventDefault(); 6487 this.close( event ); 6488 return; 6489 } 6490 6491 // prevent tabbing out of dialogs 6492 if ( event.keyCode !== $.ui.keyCode.TAB ) { 6493 return; 6494 } 6495 var tabbables = this.uiDialog.find(":tabbable"), 6496 first = tabbables.filter(":first"), 6497 last = tabbables.filter(":last"); 6498 6499 if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) { 6500 first.focus( 1 ); 6501 event.preventDefault(); 6502 } else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) { 6503 last.focus( 1 ); 6504 event.preventDefault(); 6505 } 6506 }, 6507 mousedown: function( event ) { 6508 if ( this._moveToTop( event ) ) { 6509 this._focusTabbable(); 6510 } 6511 } 6512 }); 6513 6514 // We assume that any existing aria-describedby attribute means 6515 // that the dialog content is marked up properly 6516 // otherwise we brute force the content as the description 6517 if ( !this.element.find("[aria-describedby]").length ) { 6518 this.uiDialog.attr({ 6519 "aria-describedby": this.element.uniqueId().attr("id") 6520 }); 6521 } 6522 }, 6523 6524 _createTitlebar: function() { 6525 var uiDialogTitle; 6526 6527 this.uiDialogTitlebar = $("<div>") 6528 .addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix") 6529 .prependTo( this.uiDialog ); 6530 this._on( this.uiDialogTitlebar, { 6531 mousedown: function( event ) { 6532 // Don't prevent click on close button (#8838) 6533 // Focusing a dialog that is partially scrolled out of view 6534 // causes the browser to scroll it into view, preventing the click event 6535 if ( !$( event.target ).closest(".ui-dialog-titlebar-close") ) { 6536 // Dialog isn't getting focus when dragging (#8063) 6537 this.uiDialog.focus(); 6538 } 6539 } 6540 }); 6541 6542 // support: IE 6543 // Use type="button" to prevent enter keypresses in textboxes from closing the 6544 // dialog in IE (#9312) 6545 this.uiDialogTitlebarClose = $( "<button type='button'></button>" ) 6546 .button({ 6547 label: this.options.closeText, 6548 icons: { 6549 primary: "ui-icon-closethick" 6550 }, 6551 text: false 6552 }) 6553 .addClass("ui-dialog-titlebar-close") 6554 .appendTo( this.uiDialogTitlebar ); 6555 this._on( this.uiDialogTitlebarClose, { 6556 click: function( event ) { 6557 event.preventDefault(); 6558 this.close( event ); 6559 } 6560 }); 6561 6562 uiDialogTitle = $("<span>") 6563 .uniqueId() 6564 .addClass("ui-dialog-title") 6565 .prependTo( this.uiDialogTitlebar ); 6566 this._title( uiDialogTitle ); 6567 6568 this.uiDialog.attr({ 6569 "aria-labelledby": uiDialogTitle.attr("id") 6570 }); 6571 }, 6572 6573 _title: function( title ) { 6574 if ( !this.options.title ) { 6575 title.html(" "); 6576 } 6577 title.text( this.options.title ); 6578 }, 6579 6580 _createButtonPane: function() { 6581 this.uiDialogButtonPane = $("<div>") 6582 .addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"); 6583 6584 this.uiButtonSet = $("<div>") 6585 .addClass("ui-dialog-buttonset") 6586 .appendTo( this.uiDialogButtonPane ); 6587 6588 this._createButtons(); 6589 }, 6590 6591 _createButtons: function() { 6592 var that = this, 6593 buttons = this.options.buttons; 6594 6595 // if we already have a button pane, remove it 6596 this.uiDialogButtonPane.remove(); 6597 this.uiButtonSet.empty(); 6598 6599 if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) { 6600 this.uiDialog.removeClass("ui-dialog-buttons"); 6601 return; 6602 } 6603 6604 $.each( buttons, function( name, props ) { 6605 var click, buttonOptions; 6606 props = $.isFunction( props ) ? 6607 { click: props, text: name } : 6608 props; 6609 // Default to a non-submitting button 6610 props = $.extend( { type: "button" }, props ); 6611 // Change the context for the click callback to be the main element 6612 click = props.click; 6613 props.click = function() { 6614 click.apply( that.element[0], arguments ); 6615 }; 6616 buttonOptions = { 6617 icons: props.icons, 6618 text: props.showText 6619 }; 6620 delete props.icons; 6621 delete props.showText; 6622 $( "<button></button>", props ) 6623 .button( buttonOptions ) 6624 .appendTo( that.uiButtonSet ); 6625 }); 6626 this.uiDialog.addClass("ui-dialog-buttons"); 6627 this.uiDialogButtonPane.appendTo( this.uiDialog ); 6628 }, 6629 6630 _makeDraggable: function() { 6631 var that = this, 6632 options = this.options; 6633 6634 function filteredUi( ui ) { 6635 return { 6636 position: ui.position, 6637 offset: ui.offset 6638 }; 6639 } 6640 6641 this.uiDialog.draggable({ 6642 cancel: ".ui-dialog-content, .ui-dialog-titlebar-close", 6643 handle: ".ui-dialog-titlebar", 6644 containment: "document", 6645 start: function( event, ui ) { 6646 $( this ).addClass("ui-dialog-dragging"); 6647 that._blockFrames(); 6648 that._trigger( "dragStart", event, filteredUi( ui ) ); 6649 }, 6650 drag: function( event, ui ) { 6651 that._trigger( "drag", event, filteredUi( ui ) ); 6652 }, 6653 stop: function( event, ui ) { 6654 options.position = [ 6655 ui.position.left - that.document.scrollLeft(), 6656 ui.position.top - that.document.scrollTop() 6657 ]; 6658 $( this ).removeClass("ui-dialog-dragging"); 6659 that._unblockFrames(); 6660 that._trigger( "dragStop", event, filteredUi( ui ) ); 6661 } 6662 }); 6663 }, 6664 6665 _makeResizable: function() { 6666 var that = this, 6667 options = this.options, 6668 handles = options.resizable, 6669 // .ui-resizable has position: relative defined in the stylesheet 6670 // but dialogs have to use absolute or fixed positioning 6671 position = this.uiDialog.css("position"), 6672 resizeHandles = typeof handles === "string" ? 6673 handles : 6674 "n,e,s,w,se,sw,ne,nw"; 6675 6676 function filteredUi( ui ) { 6677 return { 6678 originalPosition: ui.originalPosition, 6679 originalSize: ui.originalSize, 6680 position: ui.position, 6681 size: ui.size 6682 }; 6683 } 6684 6685 this.uiDialog.resizable({ 6686 cancel: ".ui-dialog-content", 6687 containment: "document", 6688 alsoResize: this.element, 6689 maxWidth: options.maxWidth, 6690 maxHeight: options.maxHeight, 6691 minWidth: options.minWidth, 6692 minHeight: this._minHeight(), 6693 handles: resizeHandles, 6694 start: function( event, ui ) { 6695 $( this ).addClass("ui-dialog-resizing"); 6696 that._blockFrames(); 6697 that._trigger( "resizeStart", event, filteredUi( ui ) ); 6698 }, 6699 resize: function( event, ui ) { 6700 that._trigger( "resize", event, filteredUi( ui ) ); 6701 }, 6702 stop: function( event, ui ) { 6703 options.height = $( this ).height(); 6704 options.width = $( this ).width(); 6705 $( this ).removeClass("ui-dialog-resizing"); 6706 that._unblockFrames(); 6707 that._trigger( "resizeStop", event, filteredUi( ui ) ); 6708 } 6709 }) 6710 .css( "position", position ); 6711 }, 6712 6713 _minHeight: function() { 6714 var options = this.options; 6715 6716 return options.height === "auto" ? 6717 options.minHeight : 6718 Math.min( options.minHeight, options.height ); 6719 }, 6720 6721 _position: function() { 6722 // Need to show the dialog to get the actual offset in the position plugin 6723 var isVisible = this.uiDialog.is(":visible"); 6724 if ( !isVisible ) { 6725 this.uiDialog.show(); 6726 } 6727 this.uiDialog.position( this.options.position ); 6728 if ( !isVisible ) { 6729 this.uiDialog.hide(); 6730 } 6731 }, 6732 6733 _setOptions: function( options ) { 6734 var that = this, 6735 resize = false, 6736 resizableOptions = {}; 6737 6738 $.each( options, function( key, value ) { 6739 that._setOption( key, value ); 6740 6741 if ( key in sizeRelatedOptions ) { 6742 resize = true; 6743 } 6744 if ( key in resizableRelatedOptions ) { 6745 resizableOptions[ key ] = value; 6746 } 6747 }); 6748 6749 if ( resize ) { 6750 this._size(); 6751 this._position(); 6752 } 6753 if ( this.uiDialog.is(":data(ui-resizable)") ) { 6754 this.uiDialog.resizable( "option", resizableOptions ); 6755 } 6756 }, 6757 6758 _setOption: function( key, value ) { 6759 var isDraggable, isResizable, 6760 uiDialog = this.uiDialog; 6761 6762 if ( key === "dialogClass" ) { 6763 uiDialog 6764 .removeClass( this.options.dialogClass ) 6765 .addClass( value ); 6766 } 6767 6768 if ( key === "disabled" ) { 6769 return; 6770 } 6771 6772 this._super( key, value ); 6773 6774 if ( key === "appendTo" ) { 6775 this.uiDialog.appendTo( this._appendTo() ); 6776 } 6777 6778 if ( key === "buttons" ) { 6779 this._createButtons(); 6780 } 6781 6782 if ( key === "closeText" ) { 6783 this.uiDialogTitlebarClose.button({ 6784 // Ensure that we always pass a string 6785 label: "" + value 6786 }); 6787 } 6788 6789 if ( key === "draggable" ) { 6790 isDraggable = uiDialog.is(":data(ui-draggable)"); 6791 if ( isDraggable && !value ) { 6792 uiDialog.draggable("destroy"); 6793 } 6794 6795 if ( !isDraggable && value ) { 6796 this._makeDraggable(); 6797 } 6798 } 6799 6800 if ( key === "position" ) { 6801 this._position(); 6802 } 6803 6804 if ( key === "resizable" ) { 6805 // currently resizable, becoming non-resizable 6806 isResizable = uiDialog.is(":data(ui-resizable)"); 6807 if ( isResizable && !value ) { 6808 uiDialog.resizable("destroy"); 6809 } 6810 6811 // currently resizable, changing handles 6812 if ( isResizable && typeof value === "string" ) { 6813 uiDialog.resizable( "option", "handles", value ); 6814 } 6815 6816 // currently non-resizable, becoming resizable 6817 if ( !isResizable && value !== false ) { 6818 this._makeResizable(); 6819 } 6820 } 6821 6822 if ( key === "title" ) { 6823 this._title( this.uiDialogTitlebar.find(".ui-dialog-title") ); 6824 } 6825 }, 6826 6827 _size: function() { 6828 // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content 6829 // divs will both have width and height set, so we need to reset them 6830 var nonContentHeight, minContentHeight, maxContentHeight, 6831 options = this.options; 6832 6833 // Reset content sizing 6834 this.element.show().css({ 6835 width: "auto", 6836 minHeight: 0, 6837 maxHeight: "none", 6838 height: 0 6839 }); 6840 6841 if ( options.minWidth > options.width ) { 6842 options.width = options.minWidth; 6843 } 6844 6845 // reset wrapper sizing 6846 // determine the height of all the non-content elements 6847 nonContentHeight = this.uiDialog.css({ 6848 height: "auto", 6849 width: options.width 6850 }) 6851 .outerHeight(); 6852 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); 6853 maxContentHeight = typeof options.maxHeight === "number" ? 6854 Math.max( 0, options.maxHeight - nonContentHeight ) : 6855 "none"; 6856 6857 if ( options.height === "auto" ) { 6858 this.element.css({ 6859 minHeight: minContentHeight, 6860 maxHeight: maxContentHeight, 6861 height: "auto" 6862 }); 6863 } else { 6864 this.element.height( Math.max( 0, options.height - nonContentHeight ) ); 6865 } 6866 6867 if (this.uiDialog.is(":data(ui-resizable)") ) { 6868 this.uiDialog.resizable( "option", "minHeight", this._minHeight() ); 6869 } 6870 }, 6871 6872 _blockFrames: function() { 6873 this.iframeBlocks = this.document.find( "iframe" ).map(function() { 6874 var iframe = $( this ); 6875 6876 return $( "<div>" ) 6877 .css({ 6878 position: "absolute", 6879 width: iframe.outerWidth(), 6880 height: iframe.outerHeight() 6881 }) 6882 .appendTo( iframe.parent() ) 6883 .offset( iframe.offset() )[0]; 6884 }); 6885 }, 6886 6887 _unblockFrames: function() { 6888 if ( this.iframeBlocks ) { 6889 this.iframeBlocks.remove(); 6890 delete this.iframeBlocks; 6891 } 6892 }, 6893 6894 _allowInteraction: function( event ) { 6895 if ( $( event.target ).closest(".ui-dialog").length ) { 6896 return true; 6897 } 6898 6899 // TODO: Remove hack when datepicker implements 6900 // the .ui-front logic (#8989) 6901 return !!$( event.target ).closest(".ui-datepicker").length; 6902 }, 6903 6904 _createOverlay: function() { 6905 if ( !this.options.modal ) { 6906 return; 6907 } 6908 6909 var that = this, 6910 widgetFullName = this.widgetFullName; 6911 if ( !$.ui.dialog.overlayInstances ) { 6912 // Prevent use of anchors and inputs. 6913 // We use a delay in case the overlay is created from an 6914 // event that we're going to be cancelling. (#2804) 6915 this._delay(function() { 6916 // Handle .dialog().dialog("close") (#4065) 6917 if ( $.ui.dialog.overlayInstances ) { 6918 this.document.bind( "focusin.dialog", function( event ) { 6919 if ( !that._allowInteraction( event ) ) { 6920 event.preventDefault(); 6921 $(".ui-dialog:visible:last .ui-dialog-content") 6922 .data( widgetFullName )._focusTabbable(); 6923 } 6924 }); 6925 } 6926 }); 6927 } 6928
6929 this.overlay = $("<div>") 6930 .addClass("ui-widget-overlay ui-front") 6931 .appendTo( this._appendTo() ); 6932 this._on( this.overlay, { 6933 mousedown: "_keepFocus" 6934 }); 6935 $.ui.dialog.overlayInstances++; 6936 }, 6937 6938 _destroyOverlay: function() { 6939 if ( !this.options.modal ) { 6940 return; 6941 } 6942 6943 if ( this.overlay ) { 6944 $.ui.dialog.overlayInstances--; 6945 6946 if ( !$.ui.dialog.overlayInstances ) { 6947 this.document.unbind( "focusin.dialog" ); 6948 } 6949 this.overlay.remove(); 6950 this.overlay = null; 6951 } 6952 } 6953}); 6954 6955$.ui.dialog.overlayInstances = 0; 6956 6957// DEPRECATED 6958if ( $.uiBackCompat !== false ) { 6959 // position option with array notation 6960 // just override with old implementation 6961 $.widget( "ui.dialog", $.ui.dialog, { 6962 _position: function() { 6963 var position = this.options.position, 6964 myAt = [], 6965 offset = [ 0, 0 ], 6966 isVisible; 6967 6968 if ( position ) { 6969 if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) { 6970 myAt = position.split ? position.split(" ") : [ position[0], position[1] ]; 6971 if ( myAt.length === 1 ) { 6972 myAt[1] = myAt[0]; 6973 } 6974 6975 $.each( [ "left", "top" ], function( i, offsetPosition ) { 6976 if ( +myAt[ i ] === myAt[ i ] ) { 6977 offset[ i ] = myAt[ i ]; 6978 myAt[ i ] = offsetPosition; 6979 } 6980 }); 6981 6982 position = { 6983 my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " + 6984 myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]), 6985 at: myAt.join(" ") 6986 }; 6987 } 6988 6989 position = $.extend( {}, $.ui.dialog.prototype.options.position, position ); 6990 } else { 6991 position = $.ui.dialog.prototype.options.position; 6992 } 6993 6994 // need to show the dialog to get the actual offset in the position plugin 6995 isVisible = this.uiDialog.is(":visible"); 6996 if ( !isVisible ) { 6997 this.uiDialog.show(); 6998 } 6999 this.uiDialog.position( position ); 7000 if ( !isVisible ) { 7001 this.uiDialog.hide(); 7002 } 7003 } 7004 }); 7005} 7006 7007}( _4ORMAT.$ ) ); 7008(function( $, undefined ) { 7009 7010$.widget("ui.draggable", $.ui.mouse, { 7011 version: "1.10.4", 7012 widgetEventPrefix: "drag", 7013 options: { 7014 addClasses: true, 7015 appendTo: "parent", 7016 axis: false, 7017 connectToSortable: false, 7018 containment: false, 7019 cursor: "auto", 7020 cursorAt: false, 7021 grid: false, 7022 handle: false, 7023 helper: "original", 7024 iframeFix: false, 7025 opacity: false, 7026 refreshPositions: false, 7027 revert: false, 7028 revertDuration: 500, 7029 scope: "default", 7030 scroll: true, 7031 scrollSensitivity: 20, 7032 scrollSpeed: 20, 7033 snap: false, 7034 snapMode: "both", 7035 snapTolerance: 20, 7036 stack: false, 7037 zIndex: false, 7038 7039 // callbacks 7040 drag: null, 7041 start: null, 7042 stop: null 7043 }, 7044 _create: function() { 7045 7046 if (this.options.helper === "original" && !(/^(?:r|a|f)/).test(this.element.css("position"))) { 7047 this.element[0].style.position = "relative"; 7048 } 7049 if (this.options.addClasses){ 7050 this.element.addClass("ui-draggable"); 7051 } 7052 if (this.options.disabled){ 7053 this.element.addClass("ui-draggable-disabled"); 7054 } 7055 7056 this._mouseInit(); 7057 7058 }, 7059 7060 _destroy: function() { 7061 this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" ); 7062 this._mouseDestroy(); 7063 }, 7064 7065 _mouseCapture: function(event) { 7066 7067 var o = this.options; 7068 7069 // among others, prevent a drag on a resizable-handle 7070 if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) { 7071 return false; 7072 } 7073 7074 //Quit if we're not on a valid handle 7075 this.handle = this._getHandle(event); 7076 if (!this.handle) { 7077 return false; 7078 } 7079 7080 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() { 7081 $("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>") 7082 .css({ 7083 width: this.offsetWidth+"px", height: this.offsetHeight+"px", 7084 position: "absolute", opacity: "0.001", zIndex: 1000 7085 }) 7086 .css($(this).offset()) 7087 .appendTo("body"); 7088 }); 7089 7090 return true; 7091 7092 }, 7093 7094 _mouseStart: function(event) { 7095 7096 var o = this.options; 7097 7098 //Create and append the visible helper 7099 this.helper = this._createHelper(event); 7100 7101 this.helper.addClass("ui-draggable-dragging"); 7102 7103 //Cache the helper size 7104 this._cacheHelperProportions(); 7105 7106 //If ddmanager is used for droppables, set the global draggable 7107 if($.ui.ddmanager) { 7108 $.ui.ddmanager.current = this; 7109 } 7110 7111 /* 7112 * - Position generation - 7113 * This block generates everything position related - it's the core of draggables. 7114 */ 7115 7116 //Cache the margins of the original element 7117 this._cacheMargins(); 7118 7119 //Store the helper's css position 7120 this.cssPosition = this.helper.css( "position" ); 7121 this.scrollParent = this.helper.scrollParent(); 7122 this.offsetParent = this.helper.offsetParent(); 7123 this.offsetParentCssPosition = this.offsetParent.css( "position" ); 7124 7125 //The element's absolute position on the page minus margins 7126 this.offset = this.positionAbs = this.element.offset(); 7127 this.offset = { 7128 top: this.offset.top - this.margins.top, 7129 left: this.offset.left - this.margins.left 7130 }; 7131 7132 //Reset scroll cache 7133 this.offset.scroll = false;
vendor: 27,184 bytes, lines 7134-7862
7134 7135 $.extend(this.offset, { 7136 click: { //Where the click happened, relative to the element 7137 left: event.pageX - this.offset.left, 7138 top: event.pageY - this.offset.top 7139 }, 7140 parent: this._getParentOffset(), 7141 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper 7142 }); 7143 7144 //Generate the original position 7145 this.originalPosition = this.position = this._generatePosition(event); 7146 this.originalPageX = event.pageX; 7147 this.originalPageY = event.pageY; 7148 7149 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 7150 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); 7151 7152 //Set a containment if given in the options 7153 this._setContainment(); 7154 7155 //Trigger event + callbacks 7156 if(this._trigger("start", event) === false) { 7157 this._clear(); 7158 return false; 7159 } 7160 7161 //Recache the helper size 7162 this._cacheHelperProportions(); 7163 7164 //Prepare the droppable offsets 7165 if ($.ui.ddmanager && !o.dropBehaviour) { 7166 $.ui.ddmanager.prepareOffsets(this, event); 7167 } 7168 7169 7170 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position 7171 7172 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) 7173 if ( $.ui.ddmanager ) { 7174 $.ui.ddmanager.dragStart(this, event); 7175 } 7176 7177 return true; 7178 }, 7179 7180 _mouseDrag: function(event, noPropagation) { 7181 // reset any necessary cached properties (see #5009) 7182 if ( this.offsetParentCssPosition === "fixed" ) { 7183 this.offset.parent = this._getParentOffset(); 7184 } 7185 7186 //Compute the helpers position 7187 this.position = this._generatePosition(event); 7188 this.positionAbs = this._convertPositionTo("absolute"); 7189 7190 //Call plugins and callbacks and use the resulting position if something is returned 7191 if (!noPropagation) { 7192 var ui = this._uiHash(); 7193 if(this._trigger("drag", event, ui) === false) { 7194 this._mouseUp({}); 7195 return false; 7196 } 7197 this.position = ui.position; 7198 } 7199 7200 if(!this.options.axis || this.options.axis !== "y") { 7201 this.helper[0].style.left = this.position.left+"px"; 7202 } 7203 if(!this.options.axis || this.options.axis !== "x") { 7204 this.helper[0].style.top = this.position.top+"px"; 7205 } 7206 if($.ui.ddmanager) { 7207 $.ui.ddmanager.drag(this, event); 7208 } 7209 7210 return false; 7211 }, 7212 7213 _mouseStop: function(event) { 7214 7215 //If we are using droppables, inform the manager about the drop 7216 var that = this, 7217 dropped = false; 7218 if ($.ui.ddmanager && !this.options.dropBehaviour) { 7219 dropped = $.ui.ddmanager.drop(this, event); 7220 } 7221 7222 //if a drop comes from outside (a sortable) 7223 if(this.dropped) { 7224 dropped = this.dropped; 7225 this.dropped = false; 7226 } 7227 7228 //if the original element is no longer in the DOM don't bother to continue (see #8269) 7229 if ( this.options.helper === "original" && !$.contains( this.element[ 0 ].ownerDocument, this.element[ 0 ] ) ) { 7230 return false; 7231 } 7232 7233 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))) { 7234 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { 7235 if(that._trigger("stop", event) !== false) { 7236 that._clear(); 7237 } 7238 }); 7239 } else { 7240 if(this._trigger("stop", event) !== false) { 7241 this._clear(); 7242 } 7243 } 7244 7245 return false; 7246 }, 7247 7248 _mouseUp: function(event) { 7249 //Remove frame helpers 7250 $("div.ui-draggable-iframeFix").each(function() { 7251 this.parentNode.removeChild(this); 7252 }); 7253 7254 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) 7255 if( $.ui.ddmanager ) { 7256 $.ui.ddmanager.dragStop(this, event); 7257 } 7258 7259 return $.ui.mouse.prototype._mouseUp.call(this, event); 7260 }, 7261 7262 cancel: function() { 7263 7264 if(this.helper.is(".ui-draggable-dragging")) { 7265 this._mouseUp({}); 7266 } else { 7267 this._clear(); 7268 } 7269 7270 return this; 7271 7272 }, 7273 7274 _getHandle: function(event) { 7275 return this.options.handle ? 7276 !!$( event.target ).closest( this.element.find( this.options.handle ) ).length : 7277 true; 7278 }, 7279 7280 _createHelper: function(event) { 7281 7282 var o = this.options, 7283 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element); 7284 7285 if(!helper.parents("body").length) { 7286 helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo)); 7287 } 7288 7289 if(helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) { 7290 helper.css("position", "absolute"); 7291 } 7292 7293 return helper; 7294 7295 }, 7296 7297 _adjustOffsetFromHelper: function(obj) { 7298 if (typeof obj === "string") { 7299 obj = obj.split(" "); 7300 } 7301 if ($.isArray(obj)) { 7302 obj = {left: +obj[0], top: +obj[1] || 0}; 7303 } 7304 if ("left" in obj) { 7305 this.offset.click.left = obj.left + this.margins.left; 7306 } 7307 if ("right" in obj) { 7308 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 7309 } 7310 if ("top" in obj) { 7311 this.offset.click.top = obj.top + this.margins.top; 7312 } 7313 if ("bottom" in obj) { 7314 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 7315 } 7316 }, 7317 7318 _getParentOffset: function() { 7319 7320 //Get the offsetParent and cache its position 7321 var po = this.offsetParent.offset(); 7322 7323 // This is a special case where we need to modify a offset calculated on start, since the following happened: 7324 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent 7325 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that 7326 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag 7327 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { 7328 po.left += this.scrollParent.scrollLeft(); 7329 po.top += this.scrollParent.scrollTop(); 7330 } 7331 7332 //This needs to be actually done for all browsers, since pageX/pageY includes this information 7333 //Ugly IE fix 7334 if((this.offsetParent[0] === document.body) || 7335 (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) { 7336 po = { top: 0, left: 0 }; 7337 } 7338 7339 return { 7340 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), 7341 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) 7342 }; 7343 7344 }, 7345 7346 _getRelativeOffset: function() { 7347 7348 if(this.cssPosition === "relative") { 7349 var p = this.element.position(); 7350 return { 7351 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), 7352 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() 7353 }; 7354 } else { 7355 return { top: 0, left: 0 }; 7356 } 7357 7358 }, 7359 7360 _cacheMargins: function() { 7361 this.margins = { 7362 left: (parseInt(this.element.css("marginLeft"),10) || 0), 7363 top: (parseInt(this.element.css("marginTop"),10) || 0), 7364 right: (parseInt(this.element.css("marginRight"),10) || 0), 7365 bottom: (parseInt(this.element.css("marginBottom"),10) || 0) 7366 }; 7367 }, 7368 7369 _cacheHelperProportions: function() { 7370 this.helperProportions = { 7371 width: this.helper.outerWidth(), 7372 height: this.helper.outerHeight() 7373 }; 7374 }, 7375 7376 _setContainment: function() { 7377 7378 var over, c, ce, 7379 o = this.options; 7380 7381 if ( !o.containment ) { 7382 this.containment = null; 7383 return; 7384 } 7385 7386 if ( o.containment === "window" ) { 7387 this.containment = [ 7388 $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left, 7389 $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top, 7390 $( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left, 7391 $( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top 7392 ]; 7393 return; 7394 } 7395 7396 if ( o.containment === "document") { 7397 this.containment = [ 7398 0, 7399 0, 7400 $( document ).width() - this.helperProportions.width - this.margins.left, 7401 ( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top 7402 ]; 7403 return; 7404 } 7405 7406 if ( o.containment.constructor === Array ) { 7407 this.containment = o.containment; 7408 return; 7409 } 7410 7411 if ( o.containment === "parent" ) { 7412 o.containment = this.helper[ 0 ].parentNode; 7413 } 7414 7415 c = $( o.containment ); 7416 ce = c[ 0 ]; 7417 7418 if( !ce ) { 7419 return; 7420 } 7421 7422 over = c.css( "overflow" ) !== "hidden"; 7423 7424 this.containment = [ 7425 ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ), 7426 ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ) , 7427 ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) - this.helperProportions.width - this.margins.left - this.margins.right, 7428 ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) - this.helperProportions.height - this.margins.top - this.margins.bottom 7429 ]; 7430 this.relative_container = c; 7431 }, 7432 7433 _convertPositionTo: function(d, pos) { 7434 7435 if(!pos) { 7436 pos = this.position; 7437 } 7438 7439 var mod = d === "absolute" ? 1 : -1, 7440 scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent; 7441 7442 //Cache the scroll 7443 if (!this.offset.scroll) { 7444 this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()}; 7445 } 7446 7447 return { 7448 top: ( 7449 pos.top + // The absolute mouse position 7450 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent 7451 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) 7452 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top ) * mod ) 7453 ), 7454 left: ( 7455 pos.left + // The absolute mouse position 7456 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent 7457 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) 7458 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left ) * mod ) 7459 ) 7460 }; 7461 7462 }, 7463 7464 _generatePosition: function(event) { 7465 7466 var containment, co, top, left, 7467 o = this.options, 7468 scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent, 7469 pageX = event.pageX, 7470 pageY = event.pageY; 7471 7472 //Cache the scroll 7473 if (!this.offset.scroll) { 7474 this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()}; 7475 } 7476 7477 /* 7478 * - Position constraining - 7479 * Constrain the position to a mix of grid, containment. 7480 */ 7481 7482 // If we are not dragging yet, we won't check for options 7483 if ( this.originalPosition ) { 7484 if ( this.containment ) { 7485 if ( this.relative_container ){ 7486 co = this.relative_container.offset(); 7487 containment = [ 7488 this.containment[ 0 ] + co.left, 7489 this.containment[ 1 ] + co.top, 7490 this.containment[ 2 ] + co.left, 7491 this.containment[ 3 ] + co.top 7492 ]; 7493 } 7494 else { 7495 containment = this.containment; 7496 } 7497 7498 if(event.pageX - this.offset.click.left < containment[0]) { 7499 pageX = containment[0] + this.offset.click.left; 7500 } 7501 if(event.pageY - this.offset.click.top < containment[1]) { 7502 pageY = containment[1] + this.offset.click.top; 7503 } 7504 if(event.pageX - this.offset.click.left > containment[2]) { 7505 pageX = containment[2] + this.offset.click.left; 7506 } 7507 if(event.pageY - this.offset.click.top > containment[3]) { 7508 pageY = containment[3] + this.offset.click.top; 7509 } 7510 } 7511 7512 if(o.grid) { 7513 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) 7514 top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; 7515 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; 7516 7517 left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; 7518 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; 7519 } 7520 7521 } 7522 7523 return { 7524 top: ( 7525 pageY - // The absolute mouse position 7526 this.offset.click.top - // Click offset (relative to the element) 7527 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent 7528 this.offset.parent.top + // The offsetParent's offset without borders (offset + border) 7529 ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top ) 7530 ), 7531 left: ( 7532 pageX - // The absolute mouse position 7533 this.offset.click.left - // Click offset (relative to the element) 7534 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent 7535 this.offset.parent.left + // The offsetParent's offset without borders (offset + border) 7536 ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left ) 7537 ) 7538 }; 7539 7540 }, 7541 7542 _clear: function() { 7543 this.helper.removeClass("ui-draggable-dragging"); 7544 if(this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) { 7545 this.helper.remove(); 7546 } 7547 this.helper = null; 7548 this.cancelHelperRemoval = false; 7549 }, 7550 7551 // From now on bulk stuff - mainly helpers 7552 7553 _trigger: function(type, event, ui) { 7554 ui = ui || this._uiHash(); 7555 $.ui.plugin.call(this, type, [event, ui]); 7556 //The absolute position has to be recalculated after plugins 7557 if(type === "drag") { 7558 this.positionAbs = this._convertPositionTo("absolute"); 7559 } 7560 return $.Widget.prototype._trigger.call(this, type, event, ui); 7561 }, 7562 7563 plugins: {}, 7564 7565 _uiHash: function() { 7566 return { 7567 helper: this.helper, 7568 position: this.position, 7569 originalPosition: this.originalPosition, 7570 offset: this.positionAbs 7571 }; 7572 } 7573 7574}); 7575 7576$.ui.plugin.add("draggable", "connectToSortable", { 7577 start: function(event, ui) { 7578 7579 var inst = $(this).data("ui-draggable"), o = inst.options, 7580 uiSortable = $.extend({}, ui, { item: inst.element }); 7581 inst.sortables = []; 7582 $(o.connectToSortable).each(function() { 7583 var sortable = $.data(this, "ui-sortable"); 7584 if (sortable && !sortable.options.disabled) { 7585 inst.sortables.push({ 7586 instance: sortable, 7587 shouldRevert: sortable.options.revert 7588 }); 7589 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). 7590 sortable._trigger("activate", event, uiSortable); 7591 } 7592 }); 7593 7594 }, 7595 stop: function(event, ui) { 7596 7597 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper 7598 var inst = $(this).data("ui-draggable"), 7599 uiSortable = $.extend({}, ui, { item: inst.element }); 7600 7601 $.each(inst.sortables, function() { 7602 if(this.instance.isOver) { 7603 7604 this.instance.isOver = 0; 7605 7606 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance 7607 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work) 7608 7609 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: "valid/invalid" 7610 if(this.shouldRevert) { 7611 this.instance.options.revert = this.shouldRevert; 7612 } 7613 7614 //Trigger the stop of the sortable 7615 this.instance._mouseStop(event); 7616 7617 this.instance.options.helper = this.instance.options._helper; 7618 7619 //If the helper has been the original item, restore properties in the sortable 7620 if(inst.options.helper === "original") { 7621 this.instance.currentItem.css({ top: "auto", left: "auto" }); 7622 } 7623 7624 } else { 7625 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance 7626 this.instance._trigger("deactivate", event, uiSortable); 7627 } 7628 7629 }); 7630 7631 }, 7632 drag: function(event, ui) { 7633 7634 var inst = $(this).data("ui-draggable"), that = this; 7635 7636 $.each(inst.sortables, function() { 7637 7638 var innermostIntersecting = false, 7639 thisSortable = this; 7640 7641 //Copy over some variables to allow calling the sortable's native _intersectsWith 7642 this.instance.positionAbs = inst.positionAbs; 7643 this.instance.helperProportions = inst.helperProportions; 7644 this.instance.offset.click = inst.offset.click; 7645 7646 if(this.instance._intersectsWith(this.instance.containerCache)) { 7647 innermostIntersecting = true; 7648 $.each(inst.sortables, function () { 7649 this.instance.positionAbs = inst.positionAbs; 7650 this.instance.helperProportions = inst.helperProportions; 7651 this.instance.offset.click = inst.offset.click; 7652 if (this !== thisSortable && 7653 this.instance._intersectsWith(this.instance.containerCache) && 7654 $.contains(thisSortable.instance.element[0], this.instance.element[0]) 7655 ) { 7656 innermostIntersecting = false; 7657 } 7658 return innermostIntersecting; 7659 }); 7660 } 7661 7662 7663 if(innermostIntersecting) { 7664 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once 7665 if(!this.instance.isOver) { 7666 7667 this.instance.isOver = 1; 7668 //Now we fake the start of dragging for the sortable instance, 7669 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem 7670 //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) 7671 this.instance.currentItem = $(that).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", true); 7672 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it 7673 this.instance.options.helper = function() { return ui.helper[0]; }; 7674 7675 event.target = this.instance.currentItem[0]; 7676 this.instance._mouseCapture(event, true); 7677 this.instance._mouseStart(event, true, true); 7678 7679 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes 7680 this.instance.offset.click.top = inst.offset.click.top; 7681 this.instance.offset.click.left = inst.offset.click.left; 7682 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left; 7683 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top; 7684 7685 inst._trigger("toSortable", event); 7686 inst.dropped = this.instance.element; //draggable revert needs that 7687 //hack so receive/update callbacks work (mostly) 7688 inst.currentItem = inst.element; 7689 this.instance.fromOutside = inst; 7690 7691 } 7692 7693 //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 7694 if(this.instance.currentItem) { 7695 this.instance._mouseDrag(event); 7696 } 7697 7698 } else { 7699 7700 //If it doesn't intersect with the sortable, and it intersected before, 7701 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval 7702 if(this.instance.isOver) { 7703 7704 this.instance.isOver = 0; 7705 this.instance.cancelHelperRemoval = true; 7706 7707 //Prevent reverting on this forced stop 7708 this.instance.options.revert = false; 7709 7710 // The out event needs to be triggered independently 7711 this.instance._trigger("out", event, this.instance._uiHash(this.instance)); 7712 7713 this.instance._mouseStop(event, true); 7714 this.instance.options.helper = this.instance.options._helper; 7715 7716 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size 7717 this.instance.currentItem.remove(); 7718 if(this.instance.placeholder) { 7719 this.instance.placeholder.remove(); 7720 } 7721 7722 inst._trigger("fromSortable", event); 7723 inst.dropped = false; //draggable revert needs that 7724 } 7725 7726 } 7727 7728 }); 7729 7730 } 7731}); 7732 7733$.ui.plugin.add("draggable", "cursor", { 7734 start: function() { 7735 var t = $("body"), o = $(this).data("ui-draggable").options; 7736 if (t.css("cursor")) { 7737 o._cursor = t.css("cursor"); 7738 } 7739 t.css("cursor", o.cursor); 7740 }, 7741 stop: function() { 7742 var o = $(this).data("ui-draggable").options; 7743 if (o._cursor) { 7744 $("body").css("cursor", o._cursor); 7745 } 7746 } 7747}); 7748 7749$.ui.plugin.add("draggable", "opacity", { 7750 start: function(event, ui) { 7751 var t = $(ui.helper), o = $(this).data("ui-draggable").options; 7752 if(t.css("opacity")) { 7753 o._opacity = t.css("opacity"); 7754 } 7755 t.css("opacity", o.opacity); 7756 }, 7757 stop: function(event, ui) { 7758 var o = $(this).data("ui-draggable").options; 7759 if(o._opacity) { 7760 $(ui.helper).css("opacity", o._opacity); 7761 } 7762 } 7763}); 7764 7765$.ui.plugin.add("draggable", "scroll", { 7766 start: function() { 7767 var i = $(this).data("ui-draggable"); 7768 if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") { 7769 i.overflowOffset = i.scrollParent.offset(); 7770 } 7771 }, 7772 drag: function( event ) { 7773 7774 var i = $(this).data("ui-draggable"), o = i.options, scrolled = false; 7775 7776 if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") { 7777 7778 if(!o.axis || o.axis !== "x") { 7779 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) { 7780 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed; 7781 } else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) { 7782 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed; 7783 } 7784 } 7785 7786 if(!o.axis || o.axis !== "y") { 7787 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) { 7788 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed; 7789 } else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) { 7790 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed; 7791 } 7792 } 7793 7794 } else { 7795 7796 if(!o.axis || o.axis !== "x") { 7797 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) { 7798 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); 7799 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { 7800 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); 7801 } 7802 } 7803 7804 if(!o.axis || o.axis !== "y") { 7805 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { 7806 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); 7807 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { 7808 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); 7809 } 7810 } 7811 7812 } 7813 7814 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { 7815 $.ui.ddmanager.prepareOffsets(i, event); 7816 } 7817 7818 } 7819}); 7820 7821$.ui.plugin.add("draggable", "snap", { 7822 start: function() { 7823 7824 var i = $(this).data("ui-draggable"), 7825 o = i.options; 7826 7827 i.snapElements = []; 7828 7829 $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() { 7830 var $t = $(this), 7831 $o = $t.offset(); 7832 if(this !== i.element[0]) { 7833 i.snapElements.push({ 7834 item: this, 7835 width: $t.outerWidth(), height: $t.outerHeight(), 7836 top: $o.top, left: $o.left 7837 }); 7838 } 7839 }); 7840 7841 }, 7842 drag: function(event, ui) { 7843 7844 var ts, bs, ls, rs, l, r, t, b, i, first, 7845 inst = $(this).data("ui-draggable"), 7846 o = inst.options, 7847 d = o.snapTolerance, 7848 x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, 7849 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; 7850 7851 for (i = inst.snapElements.length - 1; i >= 0; i--){ 7852 7853 l = inst.snapElements[i].left; 7854 r = l + inst.snapElements[i].width; 7855 t = inst.snapElements[i].top; 7856 b = t + inst.snapElements[i].height; 7857 7858 if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) { 7859 if(inst.snapElements[i].snapping) { 7860 (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); 7861 } 7862 inst.snapElements[i].snapping = false;
7863 continue; 7864 } 7865 7866 if(o.snapMode !== "inner") { 7867 ts = Math.abs(t - y2) <= d; 7868 bs = Math.abs(b - y1) <= d; 7869 ls = Math.abs(l - x2) <= d; 7870 rs = Math.abs(r - x1) <= d; 7871 if(ts) { 7872 ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top; 7873 } 7874 if(bs) { 7875 ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top; 7876 } 7877 if(ls) { 7878 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left; 7879 } 7880 if(rs) { 7881 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left; 7882 } 7883 } 7884 7885 first = (ts || bs || ls || rs); 7886 7887 if(o.snapMode !== "outer") { 7888 ts = Math.abs(t - y1) <= d; 7889 bs = Math.abs(b - y2) <= d; 7890 ls = Math.abs(l - x1) <= d; 7891 rs = Math.abs(r - x2) <= d; 7892 if(ts) { 7893 ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top; 7894 } 7895 if(bs) { 7896 ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top; 7897 } 7898 if(ls) { 7899 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left; 7900 } 7901 if(rs) { 7902 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left; 7903 } 7904 } 7905 7906 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) { 7907 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); 7908 } 7909 inst.snapElements[i].snapping = (ts || bs || ls || rs || first); 7910 7911 } 7912 7913 } 7914}); 7915 7916$.ui.plugin.add("draggable", "stack", { 7917 start: function() { 7918 var min, 7919 o = this.data("ui-draggable").options, 7920 group = $.makeArray($(o.stack)).sort(function(a,b) { 7921 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0); 7922 }); 7923 7924 if (!group.length) { return; } 7925 7926 min = parseInt($(group[0]).css("zIndex"), 10) || 0; 7927 $(group).each(function(i) { 7928 $(this).css("zIndex", min + i); 7929 }); 7930 this.css("zIndex", (min + group.length)); 7931 } 7932}); 7933 7934$.ui.plugin.add("draggable", "zIndex", { 7935 start: function(event, ui) { 7936 var t = $(ui.helper), o = $(this).data("ui-draggable").options; 7937 if(t.css("zIndex")) { 7938 o._zIndex = t.css("zIndex"); 7939 } 7940 t.css("zIndex", o.zIndex); 7941 }, 7942 stop: function(event, ui) { 7943 var o = $(this).data("ui-draggable").options; 7944 if(o._zIndex) { 7945 $(ui.helper).css("zIndex", o._zIndex); 7946 } 7947 } 7948}); 7949 7950})( _4ORMAT.$ ); 7951(function( $, undefined ) { 7952 7953function isOverAxis( x, reference, size ) { 7954 return ( x > reference ) && ( x < ( reference + size ) ); 7955} 7956 7957$.widget("ui.droppable", { 7958 version: "1.10.4", 7959 widgetEventPrefix: "drop", 7960 options: { 7961 accept: "*", 7962 activeClass: false, 7963 addClasses: true, 7964 greedy: false, 7965 hoverClass: false, 7966 scope: "default", 7967 tolerance: "intersect", 7968 7969 // callbacks 7970 activate: null, 7971 deactivate: null, 7972 drop: null, 7973 out: null, 7974 over: null 7975 }, 7976 _create: function() { 7977 7978 var proportions, 7979 o = this.options, 7980 accept = o.accept; 7981 7982 this.isover = false; 7983 this.isout = true; 7984 7985 this.accept = $.isFunction(accept) ? accept : function(d) { 7986 return d.is(accept); 7987 }; 7988 7989 this.proportions = function( /* valueToWrite */ ) { 7990 if ( arguments.length ) { 7991 // Store the droppable's proportions 7992 proportions = arguments[ 0 ]; 7993 } else { 7994 // Retrieve or derive the droppable's proportions 7995 return proportions ? 7996 proportions : 7997 proportions = { 7998 width: this.element[ 0 ].offsetWidth, 7999 height: this.element[ 0 ].offsetHeight 8000 }; 8001 } 8002 }; 8003 8004 // Add the reference and positions to the manager 8005 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || []; 8006 $.ui.ddmanager.droppables[o.scope].push(this); 8007 8008 (o.addClasses && this.element.addClass("ui-droppable")); 8009 8010 }, 8011 8012 _destroy: function() { 8013 var i = 0, 8014 drop = $.ui.ddmanager.droppables[this.options.scope]; 8015 8016 for ( ; i < drop.length; i++ ) { 8017 if ( drop[i] === this ) { 8018 drop.splice(i, 1); 8019 } 8020 } 8021 8022 this.element.removeClass("ui-droppable ui-droppable-disabled"); 8023 }, 8024 8025 _setOption: function(key, value) { 8026 8027 if(key === "accept") { 8028 this.accept = $.isFunction(value) ? value : function(d) { 8029 return d.is(value); 8030 }; 8031 } 8032 $.Widget.prototype._setOption.apply(this, arguments); 8033 }, 8034 8035 _activate: function(event) { 8036 var draggable = $.ui.ddmanager.current; 8037 if(this.options.activeClass) { 8038 this.element.addClass(this.options.activeClass); 8039 } 8040 if(draggable){ 8041 this._trigger("activate", event, this.ui(draggable)); 8042 } 8043 }, 8044 8045 _deactivate: function(event) { 8046 var draggable = $.ui.ddmanager.current; 8047 if(this.options.activeClass) { 8048 this.element.removeClass(this.options.activeClass); 8049 } 8050 if(draggable){ 8051 this._trigger("deactivate", event, this.ui(draggable)); 8052 } 8053 }, 8054 8055 _over: function(event) { 8056 8057 var draggable = $.ui.ddmanager.current; 8058 8059 // Bail if draggable and droppable are same element 8060 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { 8061 return; 8062 } 8063 8064 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 8065 if(this.options.hoverClass) { 8066 this.element.addClass(this.options.hoverClass); 8067 } 8068 this._trigger("over", event, this.ui(draggable)); 8069 } 8070 8071 }, 8072 8073 _out: function(event) { 8074 8075 var draggable = $.ui.ddmanager.current; 8076 8077 // Bail if draggable and droppable are same element 8078 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { 8079 return; 8080 } 8081 8082 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 8083 if(this.options.hoverClass) { 8084 this.element.removeClass(this.options.hoverClass); 8085 } 8086 this._trigger("out", event, this.ui(draggable)); 8087 } 8088 8089 }, 8090 8091 _drop: function(event,custom) { 8092 8093 var draggable = custom || $.ui.ddmanager.current, 8094 childrenIntersection = false;
vendor: 67,515 bytes, lines 8095-10558
8095 8096 // Bail if draggable and droppable are same element 8097 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { 8098 return false; 8099 } 8100 8101 this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function() { 8102 var inst = $.data(this, "ui-droppable"); 8103 if( 8104 inst.options.greedy && 8105 !inst.options.disabled && 8106 inst.options.scope === draggable.options.scope && 8107 inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) && 8108 $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance) 8109 ) { childrenIntersection = true; return false; } 8110 }); 8111 if(childrenIntersection) { 8112 return false; 8113 } 8114 8115 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 8116 if(this.options.activeClass) { 8117 this.element.removeClass(this.options.activeClass); 8118 } 8119 if(this.options.hoverClass) { 8120 this.element.removeClass(this.options.hoverClass); 8121 } 8122 this._trigger("drop", event, this.ui(draggable)); 8123 return this.element; 8124 } 8125 8126 return false; 8127 8128 }, 8129 8130 ui: function(c) { 8131 return { 8132 draggable: (c.currentItem || c.element), 8133 helper: c.helper, 8134 position: c.position, 8135 offset: c.positionAbs 8136 }; 8137 } 8138 8139}); 8140 8141$.ui.intersect = function(draggable, droppable, toleranceMode) { 8142 8143 if (!droppable.offset) { 8144 return false; 8145 } 8146 8147 var draggableLeft, draggableTop, 8148 x1 = (draggable.positionAbs || draggable.position.absolute).left, 8149 y1 = (draggable.positionAbs || draggable.position.absolute).top, 8150 x2 = x1 + draggable.helperProportions.width, 8151 y2 = y1 + draggable.helperProportions.height, 8152 l = droppable.offset.left, 8153 t = droppable.offset.top, 8154 r = l + droppable.proportions().width, 8155 b = t + droppable.proportions().height; 8156 8157 switch (toleranceMode) { 8158 case "fit": 8159 return (l <= x1 && x2 <= r && t <= y1 && y2 <= b); 8160 case "intersect": 8161 return (l < x1 + (draggable.helperProportions.width / 2) && // Right Half 8162 x2 - (draggable.helperProportions.width / 2) < r && // Left Half 8163 t < y1 + (draggable.helperProportions.height / 2) && // Bottom Half 8164 y2 - (draggable.helperProportions.height / 2) < b ); // Top Half 8165 case "pointer": 8166 draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left); 8167 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top); 8168 return isOverAxis( draggableTop, t, droppable.proportions().height ) && isOverAxis( draggableLeft, l, droppable.proportions().width ); 8169 case "touch": 8170 return ( 8171 (y1 >= t && y1 <= b) || // Top edge touching 8172 (y2 >= t && y2 <= b) || // Bottom edge touching 8173 (y1 < t && y2 > b) // Surrounded vertically 8174 ) && ( 8175 (x1 >= l && x1 <= r) || // Left edge touching 8176 (x2 >= l && x2 <= r) || // Right edge touching 8177 (x1 < l && x2 > r) // Surrounded horizontally 8178 ); 8179 default: 8180 return false; 8181 } 8182 8183}; 8184 8185/* 8186 This manager tracks offsets of draggables and droppables 8187*/ 8188$.ui.ddmanager = { 8189 current: null, 8190 droppables: { "default": [] }, 8191 prepareOffsets: function(t, event) { 8192 8193 var i, j, 8194 m = $.ui.ddmanager.droppables[t.options.scope] || [], 8195 type = event ? event.type : null, // workaround for #2317 8196 list = (t.currentItem || t.element).find(":data(ui-droppable)").addBack(); 8197 8198 droppablesLoop: for (i = 0; i < m.length; i++) { 8199 8200 //No disabled and non-accepted 8201 if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) { 8202 continue; 8203 } 8204 8205 // Filter out elements in the current dragged item 8206 for (j=0; j < list.length; j++) { 8207 if(list[j] === m[i].element[0]) { 8208 m[i].proportions().height = 0; 8209 continue droppablesLoop; 8210 } 8211 } 8212 8213 m[i].visible = m[i].element.css("display") !== "none"; 8214 if(!m[i].visible) { 8215 continue; 8216 } 8217 8218 //Activate the droppable if used directly from draggables 8219 if(type === "mousedown") { 8220 m[i]._activate.call(m[i], event); 8221 } 8222 8223 m[ i ].offset = m[ i ].element.offset(); 8224 m[ i ].proportions({ width: m[ i ].element[ 0 ].offsetWidth, height: m[ i ].element[ 0 ].offsetHeight }); 8225 8226 } 8227 8228 }, 8229 drop: function(draggable, event) { 8230 8231 var dropped = false; 8232 // Create a copy of the droppables in case the list changes during the drop (#9116) 8233 $.each(($.ui.ddmanager.droppables[draggable.options.scope] || []).slice(), function() { 8234 8235 if(!this.options) { 8236 return; 8237 } 8238 if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) { 8239 dropped = this._drop.call(this, event) || dropped; 8240 } 8241 8242 if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 8243 this.isout = true; 8244 this.isover = false; 8245 this._deactivate.call(this, event); 8246 } 8247 8248 }); 8249 return dropped; 8250 8251 }, 8252 dragStart: function( draggable, event ) { 8253 //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003) 8254 draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() { 8255 if( !draggable.options.refreshPositions ) { 8256 $.ui.ddmanager.prepareOffsets( draggable, event ); 8257 } 8258 }); 8259 }, 8260 drag: function(draggable, event) { 8261 8262 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. 8263 if(draggable.options.refreshPositions) { 8264 $.ui.ddmanager.prepareOffsets(draggable, event); 8265 } 8266 8267 //Run through all droppables and check their positions based on specific tolerance options 8268 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { 8269 8270 if(this.options.disabled || this.greedyChild || !this.visible) { 8271 return; 8272 } 8273 8274 var parentInstance, scope, parent, 8275 intersects = $.ui.intersect(draggable, this, this.options.tolerance), 8276 c = !intersects && this.isover ? "isout" : (intersects && !this.isover ? "isover" : null); 8277 if(!c) { 8278 return; 8279 } 8280 8281 if (this.options.greedy) { 8282 // find droppable parents with same scope 8283 scope = this.options.scope; 8284 parent = this.element.parents(":data(ui-droppable)").filter(function () { 8285 return $.data(this, "ui-droppable").options.scope === scope; 8286 }); 8287 8288 if (parent.length) { 8289 parentInstance = $.data(parent[0], "ui-droppable"); 8290 parentInstance.greedyChild = (c === "isover"); 8291 } 8292 } 8293 8294 // we just moved into a greedy child 8295 if (parentInstance && c === "isover") { 8296 parentInstance.isover = false; 8297 parentInstance.isout = true; 8298 parentInstance._out.call(parentInstance, event); 8299 } 8300 8301 this[c] = true; 8302 this[c === "isout" ? "isover" : "isout"] = false; 8303 this[c === "isover" ? "_over" : "_out"].call(this, event); 8304 8305 // we just moved out of a greedy child 8306 if (parentInstance && c === "isout") { 8307 parentInstance.isout = false; 8308 parentInstance.isover = true; 8309 parentInstance._over.call(parentInstance, event); 8310 } 8311 }); 8312 8313 }, 8314 dragStop: function( draggable, event ) { 8315 draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" ); 8316 //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003) 8317 if( !draggable.options.refreshPositions ) { 8318 $.ui.ddmanager.prepareOffsets( draggable, event ); 8319 } 8320 } 8321}; 8322 8323})( _4ORMAT.$ ); 8324(function($, undefined) { 8325 8326var dataSpace = "ui-effects-"; 8327 8328$.effects = { 8329 effect: {} 8330}; 8331 8332/*! 8333 * jQuery Color Animations v2.1.2 8334 * https://github.com/jquery/jquery-color 8335 * 8336 * Copyright 2013 jQuery Foundation and other contributors 8337 * Released under the MIT license. 8338 * http://jquery.org/license 8339 * 8340 * Date: Wed Jan 16 08:47:09 2013 -0600 8341 */ 8342(function( jQuery, undefined ) { 8343 8344 var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", 8345 8346 // plusequals test for += 100 -= 100 8347 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, 8348 // a set of RE's that can match strings and generate color tuples. 8349 stringParsers = [{ 8350 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 8351 parse: function( execResult ) { 8352 return [ 8353 execResult[ 1 ], 8354 execResult[ 2 ], 8355 execResult[ 3 ], 8356 execResult[ 4 ] 8357 ]; 8358 } 8359 }, { 8360 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 8361 parse: function( execResult ) { 8362 return [ 8363 execResult[ 1 ] * 2.55, 8364 execResult[ 2 ] * 2.55, 8365 execResult[ 3 ] * 2.55, 8366 execResult[ 4 ] 8367 ]; 8368 } 8369 }, { 8370 // this regex ignores A-F because it's compared against an already lowercased string 8371 re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/, 8372 parse: function( execResult ) { 8373 return [ 8374 parseInt( execResult[ 1 ], 16 ), 8375 parseInt( execResult[ 2 ], 16 ), 8376 parseInt( execResult[ 3 ], 16 ) 8377 ]; 8378 } 8379 }, { 8380 // this regex ignores A-F because it's compared against an already lowercased string 8381 re: /#([a-f0-9])([a-f0-9])([a-f0-9])/, 8382 parse: function( execResult ) { 8383 return [ 8384 parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), 8385 parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), 8386 parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ) 8387 ]; 8388 } 8389 }, { 8390 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 8391 space: "hsla", 8392 parse: function( execResult ) { 8393 return [ 8394 execResult[ 1 ], 8395 execResult[ 2 ] / 100, 8396 execResult[ 3 ] / 100, 8397 execResult[ 4 ] 8398 ]; 8399 } 8400 }], 8401 8402 // jQuery.Color( ) 8403 color = jQuery.Color = function( color, green, blue, alpha ) { 8404 return new jQuery.Color.fn.parse( color, green, blue, alpha ); 8405 }, 8406 spaces = { 8407 rgba: { 8408 props: { 8409 red: { 8410 idx: 0, 8411 type: "byte" 8412 }, 8413 green: { 8414 idx: 1, 8415 type: "byte" 8416 }, 8417 blue: { 8418 idx: 2, 8419 type: "byte" 8420 } 8421 } 8422 }, 8423 8424 hsla: { 8425 props: { 8426 hue: { 8427 idx: 0, 8428 type: "degrees" 8429 }, 8430 saturation: { 8431 idx: 1, 8432 type: "percent" 8433 }, 8434 lightness: { 8435 idx: 2, 8436 type: "percent" 8437 } 8438 } 8439 } 8440 }, 8441 propTypes = { 8442 "byte": { 8443 floor: true, 8444 max: 255 8445 }, 8446 "percent": { 8447 max: 1 8448 }, 8449 "degrees": { 8450 mod: 360, 8451 floor: true 8452 } 8453 }, 8454 support = color.support = {}, 8455 8456 // element for support tests 8457 supportElem = jQuery( "<p>" )[ 0 ], 8458 8459 // colors = jQuery.Color.names 8460 colors, 8461 8462 // local aliases of functions called often 8463 each = jQuery.each; 8464 8465// determine rgba support immediately 8466supportElem.style.cssText = "background-color:rgba(1,1,1,.5)"; 8467support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1; 8468 8469// define cache name and alpha properties 8470// for rgba and hsla spaces 8471each( spaces, function( spaceName, space ) { 8472 space.cache = "_" + spaceName; 8473 space.props.alpha = { 8474 idx: 3, 8475 type: "percent", 8476 def: 1 8477 }; 8478}); 8479 8480function clamp( value, prop, allowEmpty ) { 8481 var type = propTypes[ prop.type ] || {}; 8482 8483 if ( value == null ) { 8484 return (allowEmpty || !prop.def) ? null : prop.def; 8485 } 8486 8487 // ~~ is an short way of doing floor for positive numbers 8488 value = type.floor ? ~~value : parseFloat( value ); 8489 8490 // IE will pass in empty strings as value for alpha, 8491 // which will hit this case 8492 if ( isNaN( value ) ) { 8493 return prop.def; 8494 } 8495 8496 if ( type.mod ) { 8497 // we add mod before modding to make sure that negatives values 8498 // get converted properly: -10 -> 350 8499 return (value + type.mod) % type.mod; 8500 } 8501 8502 // for now all property types without mod have min and max 8503 return 0 > value ? 0 : type.max < value ? type.max : value; 8504} 8505 8506function stringParse( string ) { 8507 var inst = color(), 8508 rgba = inst._rgba = []; 8509 8510 string = string.toLowerCase(); 8511 8512 each( stringParsers, function( i, parser ) { 8513 var parsed, 8514 match = parser.re.exec( string ), 8515 values = match && parser.parse( match ), 8516 spaceName = parser.space || "rgba"; 8517 8518 if ( values ) { 8519 parsed = inst[ spaceName ]( values ); 8520 8521 // if this was an rgba parse the assignment might happen twice 8522 // oh well.... 8523 inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ]; 8524 rgba = inst._rgba = parsed._rgba; 8525 8526 // exit each( stringParsers ) here because we matched 8527 return false; 8528 } 8529 }); 8530 8531 // Found a stringParser that handled it 8532 if ( rgba.length ) { 8533 8534 // if this came from a parsed string, force "transparent" when alpha is 0 8535 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) 8536 if ( rgba.join() === "0,0,0,0" ) { 8537 jQuery.extend( rgba, colors.transparent ); 8538 } 8539 return inst; 8540 } 8541 8542 // named colors 8543 return colors[ string ]; 8544} 8545 8546color.fn = jQuery.extend( color.prototype, { 8547 parse: function( red, green, blue, alpha ) { 8548 if ( red === undefined ) { 8549 this._rgba = [ null, null, null, null ]; 8550 return this; 8551 } 8552 if ( red.jquery || red.nodeType ) { 8553 red = jQuery( red ).css( green ); 8554 green = undefined; 8555 } 8556 8557 var inst = this, 8558 type = jQuery.type( red ), 8559 rgba = this._rgba = []; 8560 8561 // more than 1 argument specified - assume ( red, green, blue, alpha ) 8562 if ( green !== undefined ) { 8563 red = [ red, green, blue, alpha ]; 8564 type = "array"; 8565 } 8566 8567 if ( type === "string" ) { 8568 return this.parse( stringParse( red ) || colors._default ); 8569 } 8570 8571 if ( type === "array" ) { 8572 each( spaces.rgba.props, function( key, prop ) { 8573 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop ); 8574 }); 8575 return this; 8576 } 8577 8578 if ( type === "object" ) { 8579 if ( red instanceof color ) { 8580 each( spaces, function( spaceName, space ) { 8581 if ( red[ space.cache ] ) { 8582 inst[ space.cache ] = red[ space.cache ].slice(); 8583 } 8584 }); 8585 } else { 8586 each( spaces, function( spaceName, space ) { 8587 var cache = space.cache; 8588 each( space.props, function( key, prop ) { 8589 8590 // if the cache doesn't exist, and we know how to convert 8591 if ( !inst[ cache ] && space.to ) { 8592 8593 // if the value was null, we don't need to copy it 8594 // if the key was alpha, we don't need to copy it either 8595 if ( key === "alpha" || red[ key ] == null ) { 8596 return; 8597 } 8598 inst[ cache ] = space.to( inst._rgba ); 8599 } 8600 8601 // this is the only case where we allow nulls for ALL properties. 8602 // call clamp with alwaysAllowEmpty 8603 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true ); 8604 }); 8605 8606 // everything defined but alpha? 8607 if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) { 8608 // use the default of 1 8609 inst[ cache ][ 3 ] = 1; 8610 if ( space.from ) { 8611 inst._rgba = space.from( inst[ cache ] ); 8612 } 8613 } 8614 }); 8615 } 8616 return this; 8617 } 8618 }, 8619 is: function( compare ) { 8620 var is = color( compare ), 8621 same = true, 8622 inst = this; 8623 8624 each( spaces, function( _, space ) { 8625 var localCache, 8626 isCache = is[ space.cache ]; 8627 if (isCache) { 8628 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || []; 8629 each( space.props, function( _, prop ) { 8630 if ( isCache[ prop.idx ] != null ) { 8631 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] ); 8632 return same; 8633 } 8634 }); 8635 } 8636 return same; 8637 }); 8638 return same; 8639 }, 8640 _space: function() { 8641 var used = [], 8642 inst = this; 8643 each( spaces, function( spaceName, space ) { 8644 if ( inst[ space.cache ] ) { 8645 used.push( spaceName ); 8646 } 8647 }); 8648 return used.pop(); 8649 }, 8650 transition: function( other, distance ) { 8651 var end = color( other ), 8652 spaceName = end._space(), 8653 space = spaces[ spaceName ], 8654 startColor = this.alpha() === 0 ? color( "transparent" ) : this, 8655 start = startColor[ space.cache ] || space.to( startColor._rgba ), 8656 result = start.slice(); 8657 8658 end = end[ space.cache ]; 8659 each( space.props, function( key, prop ) { 8660 var index = prop.idx, 8661 startValue = start[ index ], 8662 endValue = end[ index ], 8663 type = propTypes[ prop.type ] || {}; 8664 8665 // if null, don't override start value 8666 if ( endValue === null ) { 8667 return; 8668 } 8669 // if null - use end 8670 if ( startValue === null ) { 8671 result[ index ] = endValue; 8672 } else { 8673 if ( type.mod ) { 8674 if ( endValue - startValue > type.mod / 2 ) { 8675 startValue += type.mod; 8676 } else if ( startValue - endValue > type.mod / 2 ) { 8677 startValue -= type.mod; 8678 } 8679 } 8680 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop ); 8681 } 8682 }); 8683 return this[ spaceName ]( result ); 8684 }, 8685 blend: function( opaque ) { 8686 // if we are already opaque - return ourself 8687 if ( this._rgba[ 3 ] === 1 ) { 8688 return this; 8689 } 8690 8691 var rgb = this._rgba.slice(), 8692 a = rgb.pop(), 8693 blend = color( opaque )._rgba; 8694 8695 return color( jQuery.map( rgb, function( v, i ) { 8696 return ( 1 - a ) * blend[ i ] + a * v; 8697 })); 8698 }, 8699 toRgbaString: function() { 8700 var prefix = "rgba(", 8701 rgba = jQuery.map( this._rgba, function( v, i ) { 8702 return v == null ? ( i > 2 ? 1 : 0 ) : v; 8703 }); 8704 8705 if ( rgba[ 3 ] === 1 ) { 8706 rgba.pop(); 8707 prefix = "rgb("; 8708 } 8709 8710 return prefix + rgba.join() + ")"; 8711 }, 8712 toHslaString: function() { 8713 var prefix = "hsla(", 8714 hsla = jQuery.map( this.hsla(), function( v, i ) { 8715 if ( v == null ) { 8716 v = i > 2 ? 1 : 0; 8717 } 8718 8719 // catch 1 and 2 8720 if ( i && i < 3 ) { 8721 v = Math.round( v * 100 ) + "%"; 8722 } 8723 return v; 8724 }); 8725 8726 if ( hsla[ 3 ] === 1 ) { 8727 hsla.pop(); 8728 prefix = "hsl("; 8729 } 8730 return prefix + hsla.join() + ")"; 8731 }, 8732 toHexString: function( includeAlpha ) { 8733 var rgba = this._rgba.slice(), 8734 alpha = rgba.pop(); 8735 8736 if ( includeAlpha ) { 8737 rgba.push( ~~( alpha * 255 ) ); 8738 } 8739 8740 return "#" + jQuery.map( rgba, function( v ) { 8741 8742 // default to 0 when nulls exist 8743 v = ( v || 0 ).toString( 16 ); 8744 return v.length === 1 ? "0" + v : v; 8745 }).join(""); 8746 }, 8747 toString: function() { 8748 return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString(); 8749 } 8750}); 8751color.fn.parse.prototype = color.fn; 8752 8753// hsla conversions adapted from: 8754// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021 8755 8756function hue2rgb( p, q, h ) { 8757 h = ( h + 1 ) % 1; 8758 if ( h * 6 < 1 ) { 8759 return p + (q - p) * h * 6; 8760 } 8761 if ( h * 2 < 1) { 8762 return q; 8763 } 8764 if ( h * 3 < 2 ) { 8765 return p + (q - p) * ((2/3) - h) * 6; 8766 } 8767 return p; 8768} 8769 8770spaces.hsla.to = function ( rgba ) { 8771 if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) { 8772 return [ null, null, null, rgba[ 3 ] ]; 8773 } 8774 var r = rgba[ 0 ] / 255, 8775 g = rgba[ 1 ] / 255, 8776 b = rgba[ 2 ] / 255, 8777 a = rgba[ 3 ], 8778 max = Math.max( r, g, b ), 8779 min = Math.min( r, g, b ), 8780 diff = max - min, 8781 add = max + min, 8782 l = add * 0.5, 8783 h, s; 8784 8785 if ( min === max ) { 8786 h = 0; 8787 } else if ( r === max ) { 8788 h = ( 60 * ( g - b ) / diff ) + 360; 8789 } else if ( g === max ) { 8790 h = ( 60 * ( b - r ) / diff ) + 120; 8791 } else { 8792 h = ( 60 * ( r - g ) / diff ) + 240; 8793 } 8794 8795 // chroma (diff) == 0 means greyscale which, by definition, saturation = 0% 8796 // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add) 8797 if ( diff === 0 ) { 8798 s = 0; 8799 } else if ( l <= 0.5 ) { 8800 s = diff / add; 8801 } else { 8802 s = diff / ( 2 - add ); 8803 } 8804 return [ Math.round(h) % 360, s, l, a == null ? 1 : a ]; 8805}; 8806 8807spaces.hsla.from = function ( hsla ) { 8808 if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) { 8809 return [ null, null, null, hsla[ 3 ] ]; 8810 } 8811 var h = hsla[ 0 ] / 360, 8812 s = hsla[ 1 ], 8813 l = hsla[ 2 ], 8814 a = hsla[ 3 ], 8815 q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, 8816 p = 2 * l - q; 8817 8818 return [ 8819 Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), 8820 Math.round( hue2rgb( p, q, h ) * 255 ), 8821 Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ), 8822 a 8823 ]; 8824}; 8825 8826 8827each( spaces, function( spaceName, space ) { 8828 var props = space.props, 8829 cache = space.cache, 8830 to = space.to, 8831 from = space.from; 8832 8833 // makes rgba() and hsla() 8834 color.fn[ spaceName ] = function( value ) { 8835 8836 // generate a cache for this space if it doesn't exist 8837 if ( to && !this[ cache ] ) { 8838 this[ cache ] = to( this._rgba ); 8839 } 8840 if ( value === undefined ) { 8841 return this[ cache ].slice(); 8842 } 8843 8844 var ret, 8845 type = jQuery.type( value ), 8846 arr = ( type === "array" || type === "object" ) ? value : arguments, 8847 local = this[ cache ].slice(); 8848 8849 each( props, function( key, prop ) { 8850 var val = arr[ type === "object" ? key : prop.idx ]; 8851 if ( val == null ) { 8852 val = local[ prop.idx ]; 8853 } 8854 local[ prop.idx ] = clamp( val, prop ); 8855 }); 8856 8857 if ( from ) { 8858 ret = color( from( local ) ); 8859 ret[ cache ] = local; 8860 return ret; 8861 } else { 8862 return color( local ); 8863 } 8864 }; 8865 8866 // makes red() green() blue() alpha() hue() saturation() lightness() 8867 each( props, function( key, prop ) { 8868 // alpha is included in more than one space 8869 if ( color.fn[ key ] ) { 8870 return; 8871 } 8872 color.fn[ key ] = function( value ) { 8873 var vtype = jQuery.type( value ), 8874 fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ), 8875 local = this[ fn ](), 8876 cur = local[ prop.idx ], 8877 match; 8878 8879 if ( vtype === "undefined" ) { 8880 return cur; 8881 } 8882 8883 if ( vtype === "function" ) { 8884 value = value.call( this, cur ); 8885 vtype = jQuery.type( value ); 8886 } 8887 if ( value == null && prop.empty ) { 8888 return this; 8889 } 8890 if ( vtype === "string" ) { 8891 match = rplusequals.exec( value ); 8892 if ( match ) { 8893 value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 ); 8894 } 8895 } 8896 local[ prop.idx ] = value; 8897 return this[ fn ]( local ); 8898 }; 8899 }); 8900}); 8901 8902// add cssHook and .fx.step function for each named hook. 8903// accept a space separated string of properties 8904color.hook = function( hook ) { 8905 var hooks = hook.split( " " ); 8906 each( hooks, function( i, hook ) { 8907 jQuery.cssHooks[ hook ] = { 8908 set: function( elem, value ) { 8909 var parsed, curElem, 8910 backgroundColor = ""; 8911 8912 if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) { 8913 value = color( parsed || value ); 8914 if ( !support.rgba && value._rgba[ 3 ] !== 1 ) { 8915 curElem = hook === "backgroundColor" ? elem.parentNode : elem; 8916 while ( 8917 (backgroundColor === "" || backgroundColor === "transparent") && 8918 curElem && curElem.style 8919 ) { 8920 try { 8921 backgroundColor = jQuery.css( curElem, "backgroundColor" ); 8922 curElem = curElem.parentNode; 8923 } catch ( e ) { 8924 } 8925 } 8926 8927 value = value.blend( backgroundColor && backgroundColor !== "transparent" ? 8928 backgroundColor : 8929 "_default" ); 8930 } 8931 8932 value = value.toRgbaString(); 8933 } 8934 try { 8935 elem.style[ hook ] = value; 8936 } catch( e ) { 8937 // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit' 8938 } 8939 } 8940 }; 8941 jQuery.fx.step[ hook ] = function( fx ) { 8942 if ( !fx.colorInit ) { 8943 fx.start = color( fx.elem, hook ); 8944 fx.end = color( fx.end ); 8945 fx.colorInit = true; 8946 } 8947 jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); 8948 }; 8949 }); 8950 8951}; 8952 8953color.hook( stepHooks ); 8954 8955jQuery.cssHooks.borderColor = { 8956 expand: function( value ) { 8957 var expanded = {}; 8958 8959 each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) { 8960 expanded[ "border" + part + "Color" ] = value; 8961 }); 8962 return expanded; 8963 } 8964}; 8965 8966// Basic color names only. 8967// Usage of any of the other color names requires adding yourself or including 8968// jquery.color.svg-names.js. 8969colors = jQuery.Color.names = { 8970 // 4.1. Basic color keywords 8971 aqua: "#00ffff", 8972 black: "#000000", 8973 blue: "#0000ff", 8974 fuchsia: "#ff00ff", 8975 gray: "#808080", 8976 green: "#008000", 8977 lime: "#00ff00", 8978 maroon: "#800000", 8979 navy: "#000080", 8980 olive: "#808000", 8981 purple: "#800080", 8982 red: "#ff0000", 8983 silver: "#c0c0c0", 8984 teal: "#008080", 8985 white: "#ffffff", 8986 yellow: "#ffff00", 8987 8988 // 4.2.3. "transparent" color keyword 8989 transparent: [ null, null, null, 0 ], 8990 8991 _default: "#ffffff" 8992}; 8993 8994})( _4ORMAT.$ ); 8995 8996 8997/******************************************************************************/ 8998/****************************** CLASS ANIMATIONS ******************************/ 8999/******************************************************************************/ 9000(function() { 9001 9002var classAnimationActions = [ "add", "remove", "toggle" ], 9003 shorthandStyles = { 9004 border: 1, 9005 borderBottom: 1, 9006 borderColor: 1, 9007 borderLeft: 1, 9008 borderRight: 1, 9009 borderTop: 1, 9010 borderWidth: 1, 9011 margin: 1, 9012 padding: 1 9013 }; 9014 9015$.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) { 9016 $.fx.step[ prop ] = function( fx ) { 9017 if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) { 9018 jQuery.style( fx.elem, prop, fx.end ); 9019 fx.setAttr = true; 9020 } 9021 }; 9022}); 9023 9024function getElementStyles( elem ) { 9025 var key, len, 9026 style = elem.ownerDocument.defaultView ? 9027 elem.ownerDocument.defaultView.getComputedStyle( elem, null ) : 9028 elem.currentStyle, 9029 styles = {}; 9030 9031 if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) { 9032 len = style.length; 9033 while ( len-- ) { 9034 key = style[ len ]; 9035 if ( typeof style[ key ] === "string" ) { 9036 styles[ $.camelCase( key ) ] = style[ key ]; 9037 } 9038 } 9039 // support: Opera, IE <9 9040 } else { 9041 for ( key in style ) { 9042 if ( typeof style[ key ] === "string" ) { 9043 styles[ key ] = style[ key ]; 9044 } 9045 } 9046 } 9047 9048 return styles; 9049} 9050 9051 9052function styleDifference( oldStyle, newStyle ) { 9053 var diff = {}, 9054 name, value; 9055 9056 for ( name in newStyle ) { 9057 value = newStyle[ name ]; 9058 if ( oldStyle[ name ] !== value ) { 9059 if ( !shorthandStyles[ name ] ) { 9060 if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) { 9061 diff[ name ] = value; 9062 } 9063 } 9064 } 9065 } 9066 9067 return diff; 9068} 9069 9070// support: jQuery <1.8 9071if ( !$.fn.addBack ) { 9072 $.fn.addBack = function( selector ) { 9073 return this.add( selector == null ? 9074 this.prevObject : this.prevObject.filter( selector ) 9075 ); 9076 }; 9077} 9078 9079$.effects.animateClass = function( value, duration, easing, callback ) { 9080 var o = $.speed( duration, easing, callback ); 9081 9082 return this.queue( function() { 9083 var animated = $( this ), 9084 baseClass = animated.attr( "class" ) || "", 9085 applyClassChange, 9086 allAnimations = o.children ? animated.find( "*" ).addBack() : animated; 9087 9088 // map the animated objects to store the original styles. 9089 allAnimations = allAnimations.map(function() { 9090 var el = $( this ); 9091 return { 9092 el: el, 9093 start: getElementStyles( this ) 9094 }; 9095 }); 9096 9097 // apply class change 9098 applyClassChange = function() { 9099 $.each( classAnimationActions, function(i, action) { 9100 if ( value[ action ] ) { 9101 animated[ action + "Class" ]( value[ action ] ); 9102 } 9103 }); 9104 }; 9105 applyClassChange(); 9106 9107 // map all animated objects again - calculate new styles and diff 9108 allAnimations = allAnimations.map(function() { 9109 this.end = getElementStyles( this.el[ 0 ] ); 9110 this.diff = styleDifference( this.start, this.end ); 9111 return this; 9112 }); 9113 9114 // apply original class 9115 animated.attr( "class", baseClass ); 9116 9117 // map all animated objects again - this time collecting a promise 9118 allAnimations = allAnimations.map(function() { 9119 var styleInfo = this, 9120 dfd = $.Deferred(), 9121 opts = $.extend({}, o, { 9122 queue: false, 9123 complete: function() { 9124 dfd.resolve( styleInfo ); 9125 } 9126 }); 9127 9128 this.el.animate( this.diff, opts ); 9129 return dfd.promise(); 9130 }); 9131 9132 // once all animations have completed: 9133 $.when.apply( $, allAnimations.get() ).done(function() { 9134 9135 // set the final class 9136 applyClassChange(); 9137 9138 // for each animated element, 9139 // clear all css properties that were animated 9140 $.each( arguments, function() { 9141 var el = this.el; 9142 $.each( this.diff, function(key) { 9143 el.css( key, "" ); 9144 }); 9145 }); 9146 9147 // this is guarnteed to be there if you use jQuery.speed() 9148 // it also handles dequeuing the next anim... 9149 o.complete.call( animated[ 0 ] ); 9150 }); 9151 }); 9152}; 9153 9154$.fn.extend({ 9155 addClass: (function( orig ) { 9156 return function( classNames, speed, easing, callback ) { 9157 return speed ? 9158 $.effects.animateClass.call( this, 9159 { add: classNames }, speed, easing, callback ) : 9160 orig.apply( this, arguments ); 9161 }; 9162 })( $.fn.addClass ), 9163 9164 removeClass: (function( orig ) { 9165 return function( classNames, speed, easing, callback ) { 9166 return arguments.length > 1 ? 9167 $.effects.animateClass.call( this, 9168 { remove: classNames }, speed, easing, callback ) : 9169 orig.apply( this, arguments ); 9170 }; 9171 })( $.fn.removeClass ), 9172 9173 toggleClass: (function( orig ) { 9174 return function( classNames, force, speed, easing, callback ) { 9175 if ( typeof force === "boolean" || force === undefined ) { 9176 if ( !speed ) { 9177 // without speed parameter 9178 return orig.apply( this, arguments ); 9179 } else { 9180 return $.effects.animateClass.call( this, 9181 (force ? { add: classNames } : { remove: classNames }), 9182 speed, easing, callback ); 9183 } 9184 } else { 9185 // without force parameter 9186 return $.effects.animateClass.call( this, 9187 { toggle: classNames }, force, speed, easing ); 9188 } 9189 }; 9190 })( $.fn.toggleClass ), 9191 9192 switchClass: function( remove, add, speed, easing, callback) { 9193 return $.effects.animateClass.call( this, { 9194 add: add, 9195 remove: remove 9196 }, speed, easing, callback ); 9197 } 9198}); 9199 9200})(); 9201 9202/******************************************************************************/ 9203/*********************************** EFFECTS **********************************/ 9204/******************************************************************************/ 9205 9206(function() { 9207 9208$.extend( $.effects, { 9209 version: "1.10.4", 9210 9211 // Saves a set of properties in a data storage 9212 save: function( element, set ) { 9213 for( var i=0; i < set.length; i++ ) { 9214 if ( set[ i ] !== null ) { 9215 element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] ); 9216 } 9217 } 9218 }, 9219 9220 // Restores a set of previously saved properties from a data storage 9221 restore: function( element, set ) { 9222 var val, i; 9223 for( i=0; i < set.length; i++ ) { 9224 if ( set[ i ] !== null ) { 9225 val = element.data( dataSpace + set[ i ] ); 9226 // support: jQuery 1.6.2 9227 // http://bugs.jquery.com/ticket/9917 9228 // jQuery 1.6.2 incorrectly returns undefined for any falsy value. 9229 // We can't differentiate between "" and 0 here, so we just assume 9230 // empty string since it's likely to be a more common value... 9231 if ( val === undefined ) { 9232 val = ""; 9233 } 9234 element.css( set[ i ], val ); 9235 } 9236 } 9237 }, 9238 9239 setMode: function( el, mode ) { 9240 if (mode === "toggle") { 9241 mode = el.is( ":hidden" ) ? "show" : "hide"; 9242 } 9243 return mode; 9244 }, 9245 9246 // Translates a [top,left] array into a baseline value 9247 // this should be a little more flexible in the future to handle a string & hash 9248 getBaseline: function( origin, original ) { 9249 var y, x; 9250 switch ( origin[ 0 ] ) { 9251 case "top": y = 0; break; 9252 case "middle": y = 0.5; break; 9253 case "bottom": y = 1; break; 9254 default: y = origin[ 0 ] / original.height; 9255 } 9256 switch ( origin[ 1 ] ) { 9257 case "left": x = 0; break; 9258 case "center": x = 0.5; break; 9259 case "right": x = 1; break; 9260 default: x = origin[ 1 ] / original.width; 9261 } 9262 return { 9263 x: x, 9264 y: y 9265 }; 9266 }, 9267 9268 // Wraps the element around a wrapper that copies position properties 9269 createWrapper: function( element ) { 9270 9271 // if the element is already wrapped, return it 9272 if ( element.parent().is( ".ui-effects-wrapper" )) { 9273 return element.parent(); 9274 } 9275 9276 // wrap the element 9277 var props = { 9278 width: element.outerWidth(true), 9279 height: element.outerHeight(true), 9280 "float": element.css( "float" ) 9281 }, 9282 wrapper = $( "<div></div>" ) 9283 .addClass( "ui-effects-wrapper" ) 9284 .css({ 9285 fontSize: "100%", 9286 background: "transparent", 9287 border: "none", 9288 margin: 0, 9289 padding: 0 9290 }), 9291 // Store the size in case width/height are defined in % - Fixes #5245 9292 size = { 9293 width: element.width(), 9294 height: element.height() 9295 }, 9296 active = document.activeElement; 9297 9298 // support: Firefox 9299 // Firefox incorrectly exposes anonymous content 9300 // https://bugzilla.mozilla.org/show_bug.cgi?id=561664 9301 try { 9302 active.id; 9303 } catch( e ) { 9304 active = document.body; 9305 } 9306 9307 element.wrap( wrapper ); 9308 9309 // Fixes #7595 - Elements lose focus when wrapped. 9310 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 9311 $( active ).focus(); 9312 } 9313 9314 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element 9315 9316 // transfer positioning properties to the wrapper 9317 if ( element.css( "position" ) === "static" ) { 9318 wrapper.css({ position: "relative" }); 9319 element.css({ position: "relative" }); 9320 } else { 9321 $.extend( props, { 9322 position: element.css( "position" ), 9323 zIndex: element.css( "z-index" ) 9324 }); 9325 $.each([ "top", "left", "bottom", "right" ], function(i, pos) { 9326 props[ pos ] = element.css( pos ); 9327 if ( isNaN( parseInt( props[ pos ], 10 ) ) ) { 9328 props[ pos ] = "auto"; 9329 } 9330 }); 9331 element.css({ 9332 position: "relative", 9333 top: 0, 9334 left: 0, 9335 right: "auto", 9336 bottom: "auto" 9337 }); 9338 } 9339 element.css(size); 9340 9341 return wrapper.css( props ).show(); 9342 }, 9343 9344 removeWrapper: function( element ) { 9345 var active = document.activeElement; 9346 9347 if ( element.parent().is( ".ui-effects-wrapper" ) ) { 9348 element.parent().replaceWith( element ); 9349 9350 // Fixes #7595 - Elements lose focus when wrapped. 9351 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 9352 $( active ).focus(); 9353 } 9354 } 9355 9356 9357 return element; 9358 }, 9359 9360 setTransition: function( element, list, factor, value ) { 9361 value = value || {}; 9362 $.each( list, function( i, x ) { 9363 var unit = element.cssUnit( x ); 9364 if ( unit[ 0 ] > 0 ) { 9365 value[ x ] = unit[ 0 ] * factor + unit[ 1 ]; 9366 } 9367 }); 9368 return value; 9369 } 9370}); 9371 9372// return an effect options object for the given parameters: 9373function _normalizeArguments( effect, options, speed, callback ) { 9374 9375 // allow passing all options as the first parameter 9376 if ( $.isPlainObject( effect ) ) { 9377 options = effect; 9378 effect = effect.effect; 9379 } 9380 9381 // convert to an object 9382 effect = { effect: effect }; 9383 9384 // catch (effect, null, ...) 9385 if ( options == null ) { 9386 options = {}; 9387 } 9388 9389 // catch (effect, callback) 9390 if ( $.isFunction( options ) ) { 9391 callback = options; 9392 speed = null; 9393 options = {}; 9394 } 9395 9396 // catch (effect, speed, ?) 9397 if ( typeof options === "number" || $.fx.speeds[ options ] ) { 9398 callback = speed; 9399 speed = options; 9400 options = {}; 9401 } 9402 9403 // catch (effect, options, callback) 9404 if ( $.isFunction( speed ) ) { 9405 callback = speed; 9406 speed = null; 9407 } 9408 9409 // add options to effect 9410 if ( options ) { 9411 $.extend( effect, options ); 9412 } 9413 9414 speed = speed || options.duration; 9415 effect.duration = $.fx.off ? 0 : 9416 typeof speed === "number" ? speed : 9417 speed in $.fx.speeds ? $.fx.speeds[ speed ] : 9418 $.fx.speeds._default; 9419 9420 effect.complete = callback || options.complete; 9421 9422 return effect; 9423} 9424 9425function standardAnimationOption( option ) { 9426 // Valid standard speeds (nothing, number, named speed) 9427 if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) { 9428 return true; 9429 } 9430 9431 // Invalid strings - treat as "normal" speed 9432 if ( typeof option === "string" && !$.effects.effect[ option ] ) { 9433 return true; 9434 } 9435 9436 // Complete callback 9437 if ( $.isFunction( option ) ) { 9438 return true; 9439 } 9440 9441 // Options hash (but not naming an effect) 9442 if ( typeof option === "object" && !option.effect ) { 9443 return true; 9444 } 9445 9446 // Didn't match any standard API 9447 return false; 9448} 9449 9450$.fn.extend({ 9451 effect: function( /* effect, options, speed, callback */ ) { 9452 var args = _normalizeArguments.apply( this, arguments ), 9453 mode = args.mode, 9454 queue = args.queue, 9455 effectMethod = $.effects.effect[ args.effect ]; 9456 9457 if ( $.fx.off || !effectMethod ) { 9458 // delegate to the original method (e.g., .show()) if possible 9459 if ( mode ) { 9460 return this[ mode ]( args.duration, args.complete ); 9461 } else { 9462 return this.each( function() { 9463 if ( args.complete ) { 9464 args.complete.call( this ); 9465 } 9466 }); 9467 } 9468 } 9469 9470 function run( next ) { 9471 var elem = $( this ), 9472 complete = args.complete, 9473 mode = args.mode; 9474 9475 function done() { 9476 if ( $.isFunction( complete ) ) { 9477 complete.call( elem[0] ); 9478 } 9479 if ( $.isFunction( next ) ) { 9480 next(); 9481 } 9482 } 9483 9484 // If the element already has the correct final state, delegate to 9485 // the core methods so the internal tracking of "olddisplay" works. 9486 if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) { 9487 elem[ mode ](); 9488 done(); 9489 } else { 9490 effectMethod.call( elem[0], args, done ); 9491 } 9492 } 9493 9494 return queue === false ? this.each( run ) : this.queue( queue || "fx", run ); 9495 }, 9496 9497 show: (function( orig ) { 9498 return function( option ) { 9499 if ( standardAnimationOption( option ) ) { 9500 return orig.apply( this, arguments ); 9501 } else { 9502 var args = _normalizeArguments.apply( this, arguments ); 9503 args.mode = "show"; 9504 return this.effect.call( this, args ); 9505 } 9506 }; 9507 })( $.fn.show ), 9508 9509 hide: (function( orig ) { 9510 return function( option ) { 9511 if ( standardAnimationOption( option ) ) { 9512 return orig.apply( this, arguments ); 9513 } else { 9514 var args = _normalizeArguments.apply( this, arguments ); 9515 args.mode = "hide"; 9516 return this.effect.call( this, args ); 9517 } 9518 }; 9519 })( $.fn.hide ), 9520 9521 toggle: (function( orig ) { 9522 return function( option ) { 9523 if ( standardAnimationOption( option ) || typeof option === "boolean" ) { 9524 return orig.apply( this, arguments ); 9525 } else { 9526 var args = _normalizeArguments.apply( this, arguments ); 9527 args.mode = "toggle"; 9528 return this.effect.call( this, args ); 9529 } 9530 }; 9531 })( $.fn.toggle ), 9532 9533 // helper functions 9534 cssUnit: function(key) { 9535 var style = this.css( key ), 9536 val = []; 9537 9538 $.each( [ "em", "px", "%", "pt" ], function( i, unit ) { 9539 if ( style.indexOf( unit ) > 0 ) { 9540 val = [ parseFloat( style ), unit ]; 9541 } 9542 }); 9543 return val; 9544 } 9545}); 9546 9547})(); 9548 9549/******************************************************************************/ 9550/*********************************** EASING ***********************************/ 9551/******************************************************************************/ 9552 9553(function() { 9554 9555// based on easing equations from Robert Penner (http://www.robertpenner.com/easing) 9556 9557var baseEasings = {}; 9558 9559$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) { 9560 baseEasings[ name ] = function( p ) { 9561 return Math.pow( p, i + 2 ); 9562 }; 9563}); 9564 9565$.extend( baseEasings, { 9566 Sine: function ( p ) { 9567 return 1 - Math.cos( p * Math.PI / 2 ); 9568 }, 9569 Circ: function ( p ) { 9570 return 1 - Math.sqrt( 1 - p * p ); 9571 }, 9572 Elastic: function( p ) { 9573 return p === 0 || p === 1 ? p : 9574 -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 ); 9575 }, 9576 Back: function( p ) { 9577 return p * p * ( 3 * p - 2 ); 9578 }, 9579 Bounce: function ( p ) { 9580 var pow2, 9581 bounce = 4; 9582 9583 while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} 9584 return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); 9585 } 9586}); 9587 9588$.each( baseEasings, function( name, easeIn ) { 9589 $.easing[ "easeIn" + name ] = easeIn; 9590 $.easing[ "easeOut" + name ] = function( p ) { 9591 return 1 - easeIn( 1 - p ); 9592 }; 9593 $.easing[ "easeInOut" + name ] = function( p ) { 9594 return p < 0.5 ? 9595 easeIn( p * 2 ) / 2 : 9596 1 - easeIn( p * -2 + 2 ) / 2; 9597 }; 9598}); 9599 9600})(); 9601 9602})( _4ORMAT.$ ); 9603(function( $, undefined ) { 9604 9605var rvertical = /up|down|vertical/, 9606 rpositivemotion = /up|left|vertical|horizontal/; 9607 9608$.effects.effect.blind = function( o, done ) { 9609 // Create element 9610 var el = $( this ), 9611 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 9612 mode = $.effects.setMode( el, o.mode || "hide" ), 9613 direction = o.direction || "up", 9614 vertical = rvertical.test( direction ), 9615 ref = vertical ? "height" : "width", 9616 ref2 = vertical ? "top" : "left", 9617 motion = rpositivemotion.test( direction ), 9618 animation = {}, 9619 show = mode === "show", 9620 wrapper, distance, margin; 9621 9622 // if already wrapped, the wrapper's properties are my property. #6245 9623 if ( el.parent().is( ".ui-effects-wrapper" ) ) { 9624 $.effects.save( el.parent(), props ); 9625 } else { 9626 $.effects.save( el, props ); 9627 } 9628 el.show(); 9629 wrapper = $.effects.createWrapper( el ).css({ 9630 overflow: "hidden" 9631 }); 9632 9633 distance = wrapper[ ref ](); 9634 margin = parseFloat( wrapper.css( ref2 ) ) || 0; 9635 9636 animation[ ref ] = show ? distance : 0; 9637 if ( !motion ) { 9638 el 9639 .css( vertical ? "bottom" : "right", 0 ) 9640 .css( vertical ? "top" : "left", "auto" ) 9641 .css({ position: "absolute" }); 9642 9643 animation[ ref2 ] = show ? margin : distance + margin; 9644 } 9645 9646 // start at 0 if we are showing 9647 if ( show ) { 9648 wrapper.css( ref, 0 ); 9649 if ( ! motion ) { 9650 wrapper.css( ref2, margin + distance ); 9651 } 9652 } 9653 9654 // Animate 9655 wrapper.animate( animation, { 9656 duration: o.duration, 9657 easing: o.easing, 9658 queue: false, 9659 complete: function() { 9660 if ( mode === "hide" ) { 9661 el.hide(); 9662 } 9663 $.effects.restore( el, props ); 9664 $.effects.removeWrapper( el ); 9665 done(); 9666 } 9667 }); 9668 9669}; 9670 9671})( _4ORMAT.$ ); 9672(function( $, undefined ) { 9673 9674$.effects.effect.bounce = function( o, done ) { 9675 var el = $( this ), 9676 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 9677 9678 // defaults: 9679 mode = $.effects.setMode( el, o.mode || "effect" ), 9680 hide = mode === "hide", 9681 show = mode === "show", 9682 direction = o.direction || "up", 9683 distance = o.distance, 9684 times = o.times || 5, 9685 9686 // number of internal animations 9687 anims = times * 2 + ( show || hide ? 1 : 0 ), 9688 speed = o.duration / anims, 9689 easing = o.easing, 9690 9691 // utility: 9692 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 9693 motion = ( direction === "up" || direction === "left" ), 9694 i, 9695 upAnim, 9696 downAnim, 9697 9698 // we will need to re-assemble the queue to stack our animations in place 9699 queue = el.queue(), 9700 queuelen = queue.length; 9701 9702 // Avoid touching opacity to prevent clearType and PNG issues in IE 9703 if ( show || hide ) { 9704 props.push( "opacity" ); 9705 } 9706 9707 $.effects.save( el, props ); 9708 el.show(); 9709 $.effects.createWrapper( el ); // Create Wrapper 9710 9711 // default distance for the BIGGEST bounce is the outer Distance / 3 9712 if ( !distance ) { 9713 distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3; 9714 } 9715 9716 if ( show ) { 9717 downAnim = { opacity: 1 }; 9718 downAnim[ ref ] = 0; 9719 9720 // if we are showing, force opacity 0 and set the initial position 9721 // then do the "first" animation 9722 el.css( "opacity", 0 ) 9723 .css( ref, motion ? -distance * 2 : distance * 2 ) 9724 .animate( downAnim, speed, easing ); 9725 } 9726 9727 // start at the smallest distance if we are hiding 9728 if ( hide ) { 9729 distance = distance / Math.pow( 2, times - 1 ); 9730 } 9731 9732 downAnim = {}; 9733 downAnim[ ref ] = 0; 9734 // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here 9735 for ( i = 0; i < times; i++ ) { 9736 upAnim = {}; 9737 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; 9738 9739 el.animate( upAnim, speed, easing ) 9740 .animate( downAnim, speed, easing ); 9741 9742 distance = hide ? distance * 2 : distance / 2; 9743 } 9744 9745 // Last Bounce when Hiding 9746 if ( hide ) { 9747 upAnim = { opacity: 0 }; 9748 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; 9749 9750 el.animate( upAnim, speed, easing ); 9751 } 9752 9753 el.queue(function() { 9754 if ( hide ) { 9755 el.hide(); 9756 } 9757 $.effects.restore( el, props ); 9758 $.effects.removeWrapper( el ); 9759 done(); 9760 }); 9761 9762 // inject all the animations we just queued to be first in line (after "inprogress") 9763 if ( queuelen > 1) { 9764 queue.splice.apply( queue, 9765 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); 9766 } 9767 el.dequeue(); 9768 9769}; 9770 9771})( _4ORMAT.$ ); 9772(function( $, undefined ) { 9773 9774$.effects.effect.clip = function( o, done ) { 9775 // Create element 9776 var el = $( this ), 9777 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 9778 mode = $.effects.setMode( el, o.mode || "hide" ), 9779 show = mode === "show", 9780 direction = o.direction || "vertical", 9781 vert = direction === "vertical", 9782 size = vert ? "height" : "width", 9783 position = vert ? "top" : "left", 9784 animation = {}, 9785 wrapper, animate, distance; 9786 9787 // Save & Show 9788 $.effects.save( el, props ); 9789 el.show(); 9790 9791 // Create Wrapper 9792 wrapper = $.effects.createWrapper( el ).css({ 9793 overflow: "hidden" 9794 }); 9795 animate = ( el[0].tagName === "IMG" ) ? wrapper : el; 9796 distance = animate[ size ](); 9797 9798 // Shift 9799 if ( show ) { 9800 animate.css( size, 0 ); 9801 animate.css( position, distance / 2 ); 9802 } 9803 9804 // Create Animation Object: 9805 animation[ size ] = show ? distance : 0; 9806 animation[ position ] = show ? 0 : distance / 2; 9807 9808 // Animate 9809 animate.animate( animation, { 9810 queue: false, 9811 duration: o.duration, 9812 easing: o.easing, 9813 complete: function() { 9814 if ( !show ) { 9815 el.hide(); 9816 } 9817 $.effects.restore( el, props ); 9818 $.effects.removeWrapper( el ); 9819 done(); 9820 } 9821 }); 9822 9823}; 9824 9825})( _4ORMAT.$ ); 9826(function( $, undefined ) { 9827 9828$.effects.effect.drop = function( o, done ) { 9829 9830 var el = $( this ), 9831 props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ], 9832 mode = $.effects.setMode( el, o.mode || "hide" ), 9833 show = mode === "show", 9834 direction = o.direction || "left", 9835 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 9836 motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg", 9837 animation = { 9838 opacity: show ? 1 : 0 9839 }, 9840 distance; 9841 9842 // Adjust 9843 $.effects.save( el, props ); 9844 el.show(); 9845 $.effects.createWrapper( el ); 9846 9847 distance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2; 9848 9849 if ( show ) { 9850 el 9851 .css( "opacity", 0 ) 9852 .css( ref, motion === "pos" ? -distance : distance ); 9853 } 9854 9855 // Animation 9856 animation[ ref ] = ( show ? 9857 ( motion === "pos" ? "+=" : "-=" ) : 9858 ( motion === "pos" ? "-=" : "+=" ) ) + 9859 distance; 9860 9861 // Animate 9862 el.animate( animation, { 9863 queue: false, 9864 duration: o.duration, 9865 easing: o.easing, 9866 complete: function() { 9867 if ( mode === "hide" ) { 9868 el.hide(); 9869 } 9870 $.effects.restore( el, props ); 9871 $.effects.removeWrapper( el ); 9872 done(); 9873 } 9874 }); 9875}; 9876 9877})( _4ORMAT.$ ); 9878(function( $, undefined ) { 9879 9880$.effects.effect.explode = function( o, done ) { 9881 9882 var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3, 9883 cells = rows, 9884 el = $( this ), 9885 mode = $.effects.setMode( el, o.mode || "hide" ), 9886 show = mode === "show", 9887 9888 // show and then visibility:hidden the element before calculating offset 9889 offset = el.show().css( "visibility", "hidden" ).offset(), 9890 9891 // width and height of a piece 9892 width = Math.ceil( el.outerWidth() / cells ), 9893 height = Math.ceil( el.outerHeight() / rows ), 9894 pieces = [], 9895 9896 // loop 9897 i, j, left, top, mx, my; 9898 9899 // children animate complete: 9900 function childComplete() { 9901 pieces.push( this ); 9902 if ( pieces.length === rows * cells ) { 9903 animComplete(); 9904 } 9905 } 9906 9907 // clone the element for each row and cell. 9908 for( i = 0; i < rows ; i++ ) { // ===> 9909 top = offset.top + i * height; 9910 my = i - ( rows - 1 ) / 2 ; 9911 9912 for( j = 0; j < cells ; j++ ) { // ||| 9913 left = offset.left + j * width; 9914 mx = j - ( cells - 1 ) / 2 ; 9915 9916 // Create a clone of the now hidden main element that will be absolute positioned 9917 // within a wrapper div off the -left and -top equal to size of our pieces 9918 el 9919 .clone() 9920 .appendTo( "body" ) 9921 .wrap( "<div></div>" ) 9922 .css({ 9923 position: "absolute", 9924 visibility: "visible", 9925 left: -j * width, 9926 top: -i * height 9927 }) 9928 9929 // select the wrapper - make it overflow: hidden and absolute positioned based on 9930 // where the original was located +left and +top equal to the size of pieces 9931 .parent() 9932 .addClass( "ui-effects-explode" ) 9933 .css({ 9934 position: "absolute", 9935 overflow: "hidden", 9936 width: width, 9937 height: height, 9938 left: left + ( show ? mx * width : 0 ), 9939 top: top + ( show ? my * height : 0 ), 9940 opacity: show ? 0 : 1 9941 }).animate({ 9942 left: left + ( show ? 0 : mx * width ), 9943 top: top + ( show ? 0 : my * height ), 9944 opacity: show ? 1 : 0 9945 }, o.duration || 500, o.easing, childComplete ); 9946 } 9947 } 9948 9949 function animComplete() { 9950 el.css({ 9951 visibility: "visible" 9952 }); 9953 $( pieces ).remove(); 9954 if ( !show ) { 9955 el.hide(); 9956 } 9957 done(); 9958 } 9959}; 9960 9961})( _4ORMAT.$ ); 9962(function( $, undefined ) { 9963 9964$.effects.effect.fade = function( o, done ) { 9965 var el = $( this ), 9966 mode = $.effects.setMode( el, o.mode || "toggle" ); 9967 9968 el.animate({ 9969 opacity: mode 9970 }, { 9971 queue: false, 9972 duration: o.duration, 9973 easing: o.easing, 9974 complete: done 9975 }); 9976}; 9977 9978})( _4ORMAT.$ ); 9979(function( $, undefined ) { 9980 9981$.effects.effect.fold = function( o, done ) { 9982 9983 // Create element 9984 var el = $( this ), 9985 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 9986 mode = $.effects.setMode( el, o.mode || "hide" ), 9987 show = mode === "show", 9988 hide = mode === "hide", 9989 size = o.size || 15, 9990 percent = /([0-9]+)%/.exec( size ), 9991 horizFirst = !!o.horizFirst, 9992 widthFirst = show !== horizFirst, 9993 ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ], 9994 duration = o.duration / 2, 9995 wrapper, distance, 9996 animation1 = {}, 9997 animation2 = {}; 9998 9999 $.effects.save( el, props ); 10000 el.show(); 10001 10002 // Create Wrapper 10003 wrapper = $.effects.createWrapper( el ).css({ 10004 overflow: "hidden" 10005 }); 10006 distance = widthFirst ? 10007 [ wrapper.width(), wrapper.height() ] : 10008 [ wrapper.height(), wrapper.width() ]; 10009 10010 if ( percent ) { 10011 size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ]; 10012 } 10013 if ( show ) { 10014 wrapper.css( horizFirst ? { 10015 height: 0, 10016 width: size 10017 } : { 10018 height: size, 10019 width: 0 10020 }); 10021 } 10022 10023 // Animation 10024 animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size; 10025 animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0; 10026 10027 // Animate 10028 wrapper 10029 .animate( animation1, duration, o.easing ) 10030 .animate( animation2, duration, o.easing, function() { 10031 if ( hide ) { 10032 el.hide(); 10033 } 10034 $.effects.restore( el, props ); 10035 $.effects.removeWrapper( el ); 10036 done(); 10037 }); 10038 10039}; 10040 10041})( _4ORMAT.$ ); 10042(function( $, undefined ) { 10043 10044$.effects.effect.highlight = function( o, done ) { 10045 var elem = $( this ), 10046 props = [ "backgroundImage", "backgroundColor", "opacity" ], 10047 mode = $.effects.setMode( elem, o.mode || "show" ), 10048 animation = { 10049 backgroundColor: elem.css( "backgroundColor" ) 10050 }; 10051 10052 if (mode === "hide") { 10053 animation.opacity = 0; 10054 } 10055 10056 $.effects.save( elem, props ); 10057 10058 elem 10059 .show() 10060 .css({ 10061 backgroundImage: "none", 10062 backgroundColor: o.color || "#ffff99" 10063 }) 10064 .animate( animation, { 10065 queue: false, 10066 duration: o.duration, 10067 easing: o.easing, 10068 complete: function() { 10069 if ( mode === "hide" ) { 10070 elem.hide(); 10071 } 10072 $.effects.restore( elem, props ); 10073 done(); 10074 } 10075 }); 10076}; 10077 10078})( _4ORMAT.$ ); 10079(function( $, undefined ) { 10080 10081$.effects.effect.pulsate = function( o, done ) { 10082 var elem = $( this ), 10083 mode = $.effects.setMode( elem, o.mode || "show" ), 10084 show = mode === "show", 10085 hide = mode === "hide", 10086 showhide = ( show || mode === "hide" ), 10087 10088 // showing or hiding leaves of the "last" animation 10089 anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ), 10090 duration = o.duration / anims, 10091 animateTo = 0, 10092 queue = elem.queue(), 10093 queuelen = queue.length, 10094 i; 10095 10096 if ( show || !elem.is(":visible")) { 10097 elem.css( "opacity", 0 ).show(); 10098 animateTo = 1; 10099 } 10100 10101 // anims - 1 opacity "toggles" 10102 for ( i = 1; i < anims; i++ ) { 10103 elem.animate({ 10104 opacity: animateTo 10105 }, duration, o.easing ); 10106 animateTo = 1 - animateTo; 10107 } 10108 10109 elem.animate({ 10110 opacity: animateTo 10111 }, duration, o.easing); 10112 10113 elem.queue(function() { 10114 if ( hide ) { 10115 elem.hide(); 10116 } 10117 done(); 10118 }); 10119 10120 // We just queued up "anims" animations, we need to put them next in the queue 10121 if ( queuelen > 1 ) { 10122 queue.splice.apply( queue, 10123 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); 10124 } 10125 elem.dequeue(); 10126}; 10127 10128})( _4ORMAT.$ ); 10129(function( $, undefined ) { 10130 10131$.effects.effect.puff = function( o, done ) { 10132 var elem = $( this ), 10133 mode = $.effects.setMode( elem, o.mode || "hide" ), 10134 hide = mode === "hide", 10135 percent = parseInt( o.percent, 10 ) || 150, 10136 factor = percent / 100, 10137 original = { 10138 height: elem.height(), 10139 width: elem.width(), 10140 outerHeight: elem.outerHeight(), 10141 outerWidth: elem.outerWidth() 10142 }; 10143 10144 $.extend( o, { 10145 effect: "scale", 10146 queue: false, 10147 fade: true, 10148 mode: mode, 10149 complete: done, 10150 percent: hide ? percent : 100, 10151 from: hide ? 10152 original : 10153 { 10154 height: original.height * factor, 10155 width: original.width * factor, 10156 outerHeight: original.outerHeight * factor, 10157 outerWidth: original.outerWidth * factor 10158 } 10159 }); 10160 10161 elem.effect( o ); 10162}; 10163 10164$.effects.effect.scale = function( o, done ) { 10165 10166 // Create element 10167 var el = $( this ), 10168 options = $.extend( true, {}, o ), 10169 mode = $.effects.setMode( el, o.mode || "effect" ), 10170 percent = parseInt( o.percent, 10 ) || 10171 ( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ), 10172 direction = o.direction || "both", 10173 origin = o.origin, 10174 original = { 10175 height: el.height(), 10176 width: el.width(), 10177 outerHeight: el.outerHeight(), 10178 outerWidth: el.outerWidth() 10179 }, 10180 factor = { 10181 y: direction !== "horizontal" ? (percent / 100) : 1, 10182 x: direction !== "vertical" ? (percent / 100) : 1 10183 }; 10184 10185 // We are going to pass this effect to the size effect: 10186 options.effect = "size"; 10187 options.queue = false; 10188 options.complete = done; 10189 10190 // Set default origin and restore for show/hide 10191 if ( mode !== "effect" ) { 10192 options.origin = origin || ["middle","center"]; 10193 options.restore = true; 10194 } 10195 10196 options.from = o.from || ( mode === "show" ? { 10197 height: 0, 10198 width: 0, 10199 outerHeight: 0, 10200 outerWidth: 0 10201 } : original ); 10202 options.to = { 10203 height: original.height * factor.y, 10204 width: original.width * factor.x, 10205 outerHeight: original.outerHeight * factor.y, 10206 outerWidth: original.outerWidth * factor.x 10207 }; 10208 10209 // Fade option to support puff 10210 if ( options.fade ) { 10211 if ( mode === "show" ) { 10212 options.from.opacity = 0; 10213 options.to.opacity = 1; 10214 } 10215 if ( mode === "hide" ) { 10216 options.from.opacity = 1; 10217 options.to.opacity = 0; 10218 } 10219 } 10220 10221 // Animate 10222 el.effect( options ); 10223 10224}; 10225 10226$.effects.effect.size = function( o, done ) { 10227 10228 // Create element 10229 var original, baseline, factor, 10230 el = $( this ), 10231 props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ], 10232 10233 // Always restore 10234 props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ], 10235 10236 // Copy for children 10237 props2 = [ "width", "height", "overflow" ], 10238 cProps = [ "fontSize" ], 10239 vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ], 10240 hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ], 10241 10242 // Set options 10243 mode = $.effects.setMode( el, o.mode || "effect" ), 10244 restore = o.restore || mode !== "effect", 10245 scale = o.scale || "both", 10246 origin = o.origin || [ "middle", "center" ], 10247 position = el.css( "position" ), 10248 props = restore ? props0 : props1, 10249 zero = { 10250 height: 0, 10251 width: 0, 10252 outerHeight: 0, 10253 outerWidth: 0 10254 }; 10255 10256 if ( mode === "show" ) { 10257 el.show(); 10258 } 10259 original = { 10260 height: el.height(), 10261 width: el.width(), 10262 outerHeight: el.outerHeight(), 10263 outerWidth: el.outerWidth() 10264 }; 10265 10266 if ( o.mode === "toggle" && mode === "show" ) { 10267 el.from = o.to || zero; 10268 el.to = o.from || original; 10269 } else { 10270 el.from = o.from || ( mode === "show" ? zero : original ); 10271 el.to = o.to || ( mode === "hide" ? zero : original ); 10272 } 10273 10274 // Set scaling factor 10275 factor = { 10276 from: { 10277 y: el.from.height / original.height, 10278 x: el.from.width / original.width 10279 }, 10280 to: { 10281 y: el.to.height / original.height, 10282 x: el.to.width / original.width 10283 } 10284 }; 10285 10286 // Scale the css box 10287 if ( scale === "box" || scale === "both" ) { 10288 10289 // Vertical props scaling 10290 if ( factor.from.y !== factor.to.y ) { 10291 props = props.concat( vProps ); 10292 el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from ); 10293 el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to ); 10294 } 10295 10296 // Horizontal props scaling 10297 if ( factor.from.x !== factor.to.x ) { 10298 props = props.concat( hProps ); 10299 el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from ); 10300 el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to ); 10301 } 10302 } 10303 10304 // Scale the content 10305 if ( scale === "content" || scale === "both" ) { 10306 10307 // Vertical props scaling 10308 if ( factor.from.y !== factor.to.y ) { 10309 props = props.concat( cProps ).concat( props2 ); 10310 el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from ); 10311 el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to ); 10312 } 10313 } 10314 10315 $.effects.save( el, props ); 10316 el.show(); 10317 $.effects.createWrapper( el ); 10318 el.css( "overflow", "hidden" ).css( el.from ); 10319 10320 // Adjust 10321 if (origin) { // Calculate baseline shifts 10322 baseline = $.effects.getBaseline( origin, original ); 10323 el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y; 10324 el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x; 10325 el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y; 10326 el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x; 10327 } 10328 el.css( el.from ); // set top & left 10329 10330 // Animate 10331 if ( scale === "content" || scale === "both" ) { // Scale the children 10332 10333 // Add margins/font-size 10334 vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps); 10335 hProps = hProps.concat([ "marginLeft", "marginRight" ]); 10336 props2 = props0.concat(vProps).concat(hProps); 10337 10338 el.find( "*[width]" ).each( function(){ 10339 var child = $( this ), 10340 c_original = { 10341 height: child.height(), 10342 width: child.width(), 10343 outerHeight: child.outerHeight(), 10344 outerWidth: child.outerWidth() 10345 }; 10346 if (restore) { 10347 $.effects.save(child, props2); 10348 } 10349 10350 child.from = { 10351 height: c_original.height * factor.from.y, 10352 width: c_original.width * factor.from.x, 10353 outerHeight: c_original.outerHeight * factor.from.y, 10354 outerWidth: c_original.outerWidth * factor.from.x 10355 }; 10356 child.to = { 10357 height: c_original.height * factor.to.y, 10358 width: c_original.width * factor.to.x, 10359 outerHeight: c_original.height * factor.to.y, 10360 outerWidth: c_original.width * factor.to.x 10361 }; 10362 10363 // Vertical props scaling 10364 if ( factor.from.y !== factor.to.y ) { 10365 child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from ); 10366 child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to ); 10367 } 10368 10369 // Horizontal props scaling 10370 if ( factor.from.x !== factor.to.x ) { 10371 child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from ); 10372 child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to ); 10373 } 10374 10375 // Animate children 10376 child.css( child.from ); 10377 child.animate( child.to, o.duration, o.easing, function() { 10378 10379 // Restore children 10380 if ( restore ) { 10381 $.effects.restore( child, props2 ); 10382 } 10383 }); 10384 }); 10385 } 10386 10387 // Animate 10388 el.animate( el.to, { 10389 queue: false, 10390 duration: o.duration, 10391 easing: o.easing, 10392 complete: function() { 10393 if ( el.to.opacity === 0 ) { 10394 el.css( "opacity", el.from.opacity ); 10395 } 10396 if( mode === "hide" ) { 10397 el.hide(); 10398 } 10399 $.effects.restore( el, props ); 10400 if ( !restore ) { 10401 10402 // we need to calculate our new positioning based on the scaling 10403 if ( position === "static" ) { 10404 el.css({ 10405 position: "relative", 10406 top: el.to.top, 10407 left: el.to.left 10408 }); 10409 } else { 10410 $.each([ "top", "left" ], function( idx, pos ) { 10411 el.css( pos, function( _, str ) { 10412 var val = parseInt( str, 10 ), 10413 toRef = idx ? el.to.left : el.to.top; 10414 10415 // if original was "auto", recalculate the new value from wrapper 10416 if ( str === "auto" ) { 10417 return toRef + "px"; 10418 } 10419 10420 return val + toRef + "px"; 10421 }); 10422 }); 10423 } 10424 } 10425 10426 $.effects.removeWrapper( el ); 10427 done(); 10428 } 10429 }); 10430 10431}; 10432 10433})( _4ORMAT.$ ); 10434(function( $, undefined ) { 10435 10436$.effects.effect.shake = function( o, done ) { 10437 10438 var el = $( this ), 10439 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 10440 mode = $.effects.setMode( el, o.mode || "effect" ), 10441 direction = o.direction || "left", 10442 distance = o.distance || 20, 10443 times = o.times || 3, 10444 anims = times * 2 + 1, 10445 speed = Math.round(o.duration/anims), 10446 ref = (direction === "up" || direction === "down") ? "top" : "left", 10447 positiveMotion = (direction === "up" || direction === "left"), 10448 animation = {}, 10449 animation1 = {}, 10450 animation2 = {}, 10451 i, 10452 10453 // we will need to re-assemble the queue to stack our animations in place 10454 queue = el.queue(), 10455 queuelen = queue.length; 10456 10457 $.effects.save( el, props ); 10458 el.show(); 10459 $.effects.createWrapper( el ); 10460 10461 // Animation 10462 animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance; 10463 animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2; 10464 animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2; 10465 10466 // Animate 10467 el.animate( animation, speed, o.easing ); 10468 10469 // Shakes 10470 for ( i = 1; i < times; i++ ) { 10471 el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing ); 10472 } 10473 el 10474 .animate( animation1, speed, o.easing ) 10475 .animate( animation, speed / 2, o.easing ) 10476 .queue(function() { 10477 if ( mode === "hide" ) { 10478 el.hide(); 10479 } 10480 $.effects.restore( el, props ); 10481 $.effects.removeWrapper( el ); 10482 done(); 10483 }); 10484 10485 // inject all the animations we just queued to be first in line (after "inprogress") 10486 if ( queuelen > 1) { 10487 queue.splice.apply( queue, 10488 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); 10489 } 10490 el.dequeue(); 10491 10492}; 10493 10494})( _4ORMAT.$ ); 10495(function( $, undefined ) { 10496 10497$.effects.effect.slide = function( o, done ) { 10498 10499 // Create element 10500 var el = $( this ), 10501 props = [ "position", "top", "bottom", "left", "right", "width", "height" ], 10502 mode = $.effects.setMode( el, o.mode || "show" ), 10503 show = mode === "show", 10504 direction = o.direction || "left", 10505 ref = (direction === "up" || direction === "down") ? "top" : "left", 10506 positiveMotion = (direction === "up" || direction === "left"), 10507 distance, 10508 animation = {}; 10509 10510 // Adjust 10511 $.effects.save( el, props ); 10512 el.show(); 10513 distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ); 10514 10515 $.effects.createWrapper( el ).css({ 10516 overflow: "hidden" 10517 }); 10518 10519 if ( show ) { 10520 el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance ); 10521 } 10522 10523 // Animation 10524 animation[ ref ] = ( show ? 10525 ( positiveMotion ? "+=" : "-=") : 10526 ( positiveMotion ? "-=" : "+=")) + 10527 distance; 10528 10529 // Animate 10530 el.animate( animation, { 10531 queue: false, 10532 duration: o.duration, 10533 easing: o.easing, 10534 complete: function() { 10535 if ( mode === "hide" ) { 10536 el.hide(); 10537 } 10538 $.effects.restore( el, props ); 10539 $.effects.removeWrapper( el ); 10540 done(); 10541 } 10542 }); 10543}; 10544 10545})( _4ORMAT.$ ); 10546(function( $, undefined ) { 10547 10548$.effects.effect.transfer = function( o, done ) { 10549 var elem = $( this ), 10550 target = $( o.to ), 10551 targetFixed = target.css( "position" ) === "fixed", 10552 body = $("body"), 10553 fixTop = targetFixed ? body.scrollTop() : 0, 10554 fixLeft = targetFixed ? body.scrollLeft() : 0, 10555 endPosition = target.offset(), 10556 animation = { 10557 top: endPosition.top - fixTop , 10558 left: endPosition.left - fixLeft ,
10559 height: target.innerHeight(), 10560 width: target.innerWidth() 10561 }, 10562 startPosition = elem.offset(), 10563 transfer = $( "<div class='ui-effects-transfer'></div>" ) 10564 .appendTo( document.body ) 10565 .addClass( o.className ) 10566 .css({ 10567 top: startPosition.top - fixTop , 10568 left: startPosition.left - fixLeft , 10569 height: elem.innerHeight(), 10570 width: elem.innerWidth(), 10571 position: targetFixed ? "fixed" : "absolute" 10572 }) 10573 .animate( animation, o.duration, o.easing, function() { 10574 transfer.remove(); 10575 done(); 10576 }); 10577}; 10578 10579})( _4ORMAT.$ ); 10580(function( $, undefined ) { 10581 10582$.widget( "ui.menu", { 10583 version: "1.10.4", 10584 defaultElement: "<ul>", 10585 delay: 300, 10586 options: { 10587 icons: { 10588 submenu: "ui-icon-carat-1-e" 10589 }, 10590 menus: "ul", 10591 position: { 10592 my: "left top", 10593 at: "right top" 10594 }, 10595 role: "menu", 10596 10597 // callbacks 10598 blur: null, 10599 focus: null, 10600 select: null 10601 }, 10602 10603 _create: function() { 10604 this.activeMenu = this.element; 10605 // flag used to prevent firing of the click handler 10606 // as the event bubbles up through nested menus 10607 this.mouseHandled = false; 10608 this.element 10609 .uniqueId() 10610 .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) 10611 .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length ) 10612 .attr({ 10613 role: this.options.role, 10614 tabIndex: 0 10615 }) 10616 // need to catch all clicks on disabled menu 10617 // not possible through _on 10618 .bind( "click" + this.eventNamespace, $.proxy(function( event ) { 10619 if ( this.options.disabled ) { 10620 event.preventDefault(); 10621 } 10622 }, this )); 10623 10624 if ( this.options.disabled ) { 10625 this.element 10626 .addClass( "ui-state-disabled" ) 10627 .attr( "aria-disabled", "true" ); 10628 } 10629 10630 this._on({ 10631 // Prevent focus from sticking to links inside menu after clicking 10632 // them (focus should always stay on UL during navigation). 10633 "mousedown .ui-menu-item > a": function( event ) { 10634 event.preventDefault(); 10635 }, 10636 "click .ui-state-disabled > a": function( event ) { 10637 event.preventDefault(); 10638 }, 10639 "click .ui-menu-item:has(a)": function( event ) { 10640 var target = $( event.target ).closest( ".ui-menu-item" ); 10641 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) { 10642 this.select( event ); 10643 10644 // Only set the mouseHandled flag if the event will bubble, see #9469. 10645 if ( !event.isPropagationStopped() ) { 10646 this.mouseHandled = true; 10647 } 10648 10649 // Open submenu on click 10650 if ( target.has( ".ui-menu" ).length ) { 10651 this.expand( event ); 10652 } else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) { 10653 10654 // Redirect focus to the menu 10655 this.element.trigger( "focus", [ true ] ); 10656 10657 // If the active item is on the top level, let it stay active. 10658 // Otherwise, blur the active item since it is no longer visible. 10659 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) { 10660 clearTimeout( this.timer ); 10661 } 10662 } 10663 } 10664 }, 10665 "mouseenter .ui-menu-item": function( event ) { 10666 var target = $( event.currentTarget ); 10667 // Remove ui-state-active class from siblings of the newly focused menu item 10668 // to avoid a jump caused by adjacent elements both having a class with a border 10669 target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" ); 10670 this.focus( event, target ); 10671 }, 10672 mouseleave: "collapseAll", 10673 "mouseleave .ui-menu": "collapseAll", 10674 focus: function( event, keepActiveItem ) { 10675 // If there's already an active item, keep it active 10676 // If not, activate the first item 10677 var item = this.active || this.element.children( ".ui-menu-item" ).eq( 0 ); 10678 10679 if ( !keepActiveItem ) { 10680 this.focus( event, item ); 10681 } 10682 }, 10683 blur: function( event ) { 10684 this._delay(function() { 10685 if ( !$.contains( this.element[0], this.document[0].activeElement ) ) { 10686 this.collapseAll( event ); 10687 } 10688 }); 10689 }, 10690 keydown: "_keydown" 10691 }); 10692 10693 this.refresh(); 10694
vendor: 38,527 bytes, lines 10695-12019
10695 // Clicks outside of a menu collapse any open menus 10696 this._on( this.document, { 10697 click: function( event ) { 10698 if ( !$( event.target ).closest( ".ui-menu" ).length ) { 10699 this.collapseAll( event ); 10700 } 10701 10702 // Reset the mouseHandled flag 10703 this.mouseHandled = false; 10704 } 10705 }); 10706 }, 10707 10708 _destroy: function() { 10709 // Destroy (sub)menus 10710 this.element 10711 .removeAttr( "aria-activedescendant" ) 10712 .find( ".ui-menu" ).addBack() 10713 .removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons" ) 10714 .removeAttr( "role" ) 10715 .removeAttr( "tabIndex" ) 10716 .removeAttr( "aria-labelledby" ) 10717 .removeAttr( "aria-expanded" ) 10718 .removeAttr( "aria-hidden" ) 10719 .removeAttr( "aria-disabled" ) 10720 .removeUniqueId() 10721 .show(); 10722 10723 // Destroy menu items 10724 this.element.find( ".ui-menu-item" ) 10725 .removeClass( "ui-menu-item" ) 10726 .removeAttr( "role" ) 10727 .removeAttr( "aria-disabled" ) 10728 .children( "a" ) 10729 .removeUniqueId() 10730 .removeClass( "ui-corner-all ui-state-hover" ) 10731 .removeAttr( "tabIndex" ) 10732 .removeAttr( "role" ) 10733 .removeAttr( "aria-haspopup" ) 10734 .children().each( function() { 10735 var elem = $( this ); 10736 if ( elem.data( "ui-menu-submenu-carat" ) ) { 10737 elem.remove(); 10738 } 10739 }); 10740 10741 // Destroy menu dividers 10742 this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" ); 10743 }, 10744 10745 _keydown: function( event ) { 10746 var match, prev, character, skip, regex, 10747 preventDefault = true; 10748 10749 function escape( value ) { 10750 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ); 10751 } 10752 10753 switch ( event.keyCode ) { 10754 case $.ui.keyCode.PAGE_UP: 10755 this.previousPage( event ); 10756 break; 10757 case $.ui.keyCode.PAGE_DOWN: 10758 this.nextPage( event ); 10759 break; 10760 case $.ui.keyCode.HOME: 10761 this._move( "first", "first", event ); 10762 break; 10763 case $.ui.keyCode.END: 10764 this._move( "last", "last", event ); 10765 break; 10766 case $.ui.keyCode.UP: 10767 this.previous( event ); 10768 break; 10769 case $.ui.keyCode.DOWN: 10770 this.next( event ); 10771 break; 10772 case $.ui.keyCode.LEFT: 10773 this.collapse( event ); 10774 break; 10775 case $.ui.keyCode.RIGHT: 10776 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { 10777 this.expand( event ); 10778 } 10779 break; 10780 case $.ui.keyCode.ENTER: 10781 case $.ui.keyCode.SPACE: 10782 this._activate( event ); 10783 break; 10784 case $.ui.keyCode.ESCAPE: 10785 this.collapse( event ); 10786 break; 10787 default: 10788 preventDefault = false; 10789 prev = this.previousFilter || ""; 10790 character = String.fromCharCode( event.keyCode ); 10791 skip = false; 10792 10793 clearTimeout( this.filterTimer ); 10794 10795 if ( character === prev ) { 10796 skip = true; 10797 } else { 10798 character = prev + character; 10799 } 10800 10801 regex = new RegExp( "^" + escape( character ), "i" ); 10802 match = this.activeMenu.children( ".ui-menu-item" ).filter(function() { 10803 return regex.test( $( this ).children( "a" ).text() ); 10804 }); 10805 match = skip && match.index( this.active.next() ) !== -1 ? 10806 this.active.nextAll( ".ui-menu-item" ) : 10807 match; 10808 10809 // If no matches on the current filter, reset to the last character pressed 10810 // to move down the menu to the first item that starts with that character 10811 if ( !match.length ) { 10812 character = String.fromCharCode( event.keyCode ); 10813 regex = new RegExp( "^" + escape( character ), "i" ); 10814 match = this.activeMenu.children( ".ui-menu-item" ).filter(function() { 10815 return regex.test( $( this ).children( "a" ).text() ); 10816 }); 10817 } 10818 10819 if ( match.length ) { 10820 this.focus( event, match ); 10821 if ( match.length > 1 ) { 10822 this.previousFilter = character; 10823 this.filterTimer = this._delay(function() { 10824 delete this.previousFilter; 10825 }, 1000 ); 10826 } else { 10827 delete this.previousFilter; 10828 } 10829 } else { 10830 delete this.previousFilter; 10831 } 10832 } 10833 10834 if ( preventDefault ) { 10835 event.preventDefault(); 10836 } 10837 }, 10838 10839 _activate: function( event ) { 10840 if ( !this.active.is( ".ui-state-disabled" ) ) { 10841 if ( this.active.children( "a[aria-haspopup='true']" ).length ) { 10842 this.expand( event ); 10843 } else { 10844 this.select( event ); 10845 } 10846 } 10847 }, 10848 10849 refresh: function() { 10850 var menus, 10851 icon = this.options.icons.submenu, 10852 submenus = this.element.find( this.options.menus ); 10853 10854 this.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length ); 10855 10856 // Initialize nested menus 10857 submenus.filter( ":not(.ui-menu)" ) 10858 .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) 10859 .hide() 10860 .attr({ 10861 role: this.options.role, 10862 "aria-hidden": "true", 10863 "aria-expanded": "false" 10864 }) 10865 .each(function() { 10866 var menu = $( this ), 10867 item = menu.prev( "a" ), 10868 submenuCarat = $( "<span>" ) 10869 .addClass( "ui-menu-icon ui-icon " + icon ) 10870 .data( "ui-menu-submenu-carat", true ); 10871 10872 item 10873 .attr( "aria-haspopup", "true" ) 10874 .prepend( submenuCarat ); 10875 menu.attr( "aria-labelledby", item.attr( "id" ) ); 10876 }); 10877 10878 menus = submenus.add( this.element ); 10879 10880 // Don't refresh list items that are already adapted 10881 menus.children( ":not(.ui-menu-item):has(a)" ) 10882 .addClass( "ui-menu-item" ) 10883 .attr( "role", "presentation" ) 10884 .children( "a" ) 10885 .uniqueId() 10886 .addClass( "ui-corner-all" ) 10887 .attr({ 10888 tabIndex: -1, 10889 role: this._itemRole() 10890 }); 10891 10892 // Initialize unlinked menu-items containing spaces and/or dashes only as dividers 10893 menus.children( ":not(.ui-menu-item)" ).each(function() { 10894 var item = $( this ); 10895 // hyphen, em dash, en dash 10896 if ( !/[^\-\u2014\u2013\s]/.test( item.text() ) ) { 10897 item.addClass( "ui-widget-content ui-menu-divider" ); 10898 } 10899 }); 10900 10901 // Add aria-disabled attribute to any disabled menu item 10902 menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" ); 10903 10904 // If the active item has been removed, blur the menu 10905 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { 10906 this.blur(); 10907 } 10908 }, 10909 10910 _itemRole: function() { 10911 return { 10912 menu: "menuitem", 10913 listbox: "option" 10914 }[ this.options.role ]; 10915 }, 10916 10917 _setOption: function( key, value ) { 10918 if ( key === "icons" ) { 10919 this.element.find( ".ui-menu-icon" ) 10920 .removeClass( this.options.icons.submenu ) 10921 .addClass( value.submenu ); 10922 } 10923 this._super( key, value ); 10924 }, 10925 10926 focus: function( event, item ) { 10927 var nested, focused; 10928 this.blur( event, event && event.type === "focus" ); 10929 10930 this._scrollIntoView( item ); 10931 10932 this.active = item.first(); 10933 focused = this.active.children( "a" ).addClass( "ui-state-focus" ); 10934 // Only update aria-activedescendant if there's a role 10935 // otherwise we assume focus is managed elsewhere 10936 if ( this.options.role ) { 10937 this.element.attr( "aria-activedescendant", focused.attr( "id" ) ); 10938 } 10939 10940 // Highlight active parent menu item, if any 10941 this.active 10942 .parent() 10943 .closest( ".ui-menu-item" ) 10944 .children( "a:first" ) 10945 .addClass( "ui-state-active" ); 10946 10947 if ( event && event.type === "keydown" ) { 10948 this._close(); 10949 } else { 10950 this.timer = this._delay(function() { 10951 this._close(); 10952 }, this.delay ); 10953 } 10954 10955 nested = item.children( ".ui-menu" ); 10956 if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) { 10957 this._startOpening(nested); 10958 } 10959 this.activeMenu = item.parent(); 10960 10961 this._trigger( "focus", event, { item: item } ); 10962 }, 10963 10964 _scrollIntoView: function( item ) { 10965 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; 10966 if ( this._hasScroll() ) { 10967 borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0; 10968 paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0; 10969 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop; 10970 scroll = this.activeMenu.scrollTop(); 10971 elementHeight = this.activeMenu.height(); 10972 itemHeight = item.height(); 10973 10974 if ( offset < 0 ) { 10975 this.activeMenu.scrollTop( scroll + offset ); 10976 } else if ( offset + itemHeight > elementHeight ) { 10977 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight ); 10978 } 10979 } 10980 }, 10981 10982 blur: function( event, fromFocus ) { 10983 if ( !fromFocus ) { 10984 clearTimeout( this.timer ); 10985 } 10986 10987 if ( !this.active ) { 10988 return; 10989 } 10990 10991 this.active.children( "a" ).removeClass( "ui-state-focus" ); 10992 this.active = null; 10993 10994 this._trigger( "blur", event, { item: this.active } ); 10995 }, 10996 10997 _startOpening: function( submenu ) { 10998 clearTimeout( this.timer ); 10999 11000 // Don't open if already open fixes a Firefox bug that caused a .5 pixel 11001 // shift in the submenu position when mousing over the carat icon 11002 if ( submenu.attr( "aria-hidden" ) !== "true" ) { 11003 return; 11004 } 11005 11006 this.timer = this._delay(function() { 11007 this._close(); 11008 this._open( submenu ); 11009 }, this.delay ); 11010 }, 11011 11012 _open: function( submenu ) { 11013 var position = $.extend({ 11014 of: this.active 11015 }, this.options.position ); 11016 11017 clearTimeout( this.timer ); 11018 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) ) 11019 .hide() 11020 .attr( "aria-hidden", "true" ); 11021 11022 submenu 11023 .show() 11024 .removeAttr( "aria-hidden" ) 11025 .attr( "aria-expanded", "true" ) 11026 .position( position ); 11027 }, 11028 11029 collapseAll: function( event, all ) { 11030 clearTimeout( this.timer ); 11031 this.timer = this._delay(function() { 11032 // If we were passed an event, look for the submenu that contains the event 11033 var currentMenu = all ? this.element : 11034 $( event && event.target ).closest( this.element.find( ".ui-menu" ) ); 11035 11036 // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway 11037 if ( !currentMenu.length ) { 11038 currentMenu = this.element; 11039 } 11040 11041 this._close( currentMenu ); 11042 11043 this.blur( event ); 11044 this.activeMenu = currentMenu; 11045 }, this.delay ); 11046 }, 11047 11048 // With no arguments, closes the currently active menu - if nothing is active 11049 // it closes all menus. If passed an argument, it will search for menus BELOW 11050 _close: function( startMenu ) { 11051 if ( !startMenu ) { 11052 startMenu = this.active ? this.active.parent() : this.element; 11053 } 11054 11055 startMenu 11056 .find( ".ui-menu" ) 11057 .hide() 11058 .attr( "aria-hidden", "true" ) 11059 .attr( "aria-expanded", "false" ) 11060 .end() 11061 .find( "a.ui-state-active" ) 11062 .removeClass( "ui-state-active" ); 11063 }, 11064 11065 collapse: function( event ) { 11066 var newItem = this.active && 11067 this.active.parent().closest( ".ui-menu-item", this.element ); 11068 if ( newItem && newItem.length ) { 11069 this._close(); 11070 this.focus( event, newItem ); 11071 } 11072 }, 11073 11074 expand: function( event ) { 11075 var newItem = this.active && 11076 this.active 11077 .children( ".ui-menu " ) 11078 .children( ".ui-menu-item" ) 11079 .first(); 11080 11081 if ( newItem && newItem.length ) { 11082 this._open( newItem.parent() ); 11083 11084 // Delay so Firefox will not hide activedescendant change in expanding submenu from AT 11085 this._delay(function() { 11086 this.focus( event, newItem ); 11087 }); 11088 } 11089 }, 11090 11091 next: function( event ) { 11092 this._move( "next", "first", event ); 11093 }, 11094 11095 previous: function( event ) { 11096 this._move( "prev", "last", event ); 11097 }, 11098 11099 isFirstItem: function() { 11100 return this.active && !this.active.prevAll( ".ui-menu-item" ).length; 11101 }, 11102 11103 isLastItem: function() { 11104 return this.active && !this.active.nextAll( ".ui-menu-item" ).length; 11105 }, 11106 11107 _move: function( direction, filter, event ) { 11108 var next; 11109 if ( this.active ) { 11110 if ( direction === "first" || direction === "last" ) { 11111 next = this.active 11112 [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ) 11113 .eq( -1 ); 11114 } else { 11115 next = this.active 11116 [ direction + "All" ]( ".ui-menu-item" ) 11117 .eq( 0 ); 11118 } 11119 } 11120 if ( !next || !next.length || !this.active ) { 11121 next = this.activeMenu.children( ".ui-menu-item" )[ filter ](); 11122 } 11123 11124 this.focus( event, next ); 11125 }, 11126 11127 nextPage: function( event ) { 11128 var item, base, height; 11129 11130 if ( !this.active ) { 11131 this.next( event ); 11132 return; 11133 } 11134 if ( this.isLastItem() ) { 11135 return; 11136 } 11137 if ( this._hasScroll() ) { 11138 base = this.active.offset().top; 11139 height = this.element.height(); 11140 this.active.nextAll( ".ui-menu-item" ).each(function() { 11141 item = $( this ); 11142 return item.offset().top - base - height < 0; 11143 }); 11144 11145 this.focus( event, item ); 11146 } else { 11147 this.focus( event, this.activeMenu.children( ".ui-menu-item" ) 11148 [ !this.active ? "first" : "last" ]() ); 11149 } 11150 }, 11151 11152 previousPage: function( event ) { 11153 var item, base, height; 11154 if ( !this.active ) { 11155 this.next( event ); 11156 return; 11157 } 11158 if ( this.isFirstItem() ) { 11159 return; 11160 } 11161 if ( this._hasScroll() ) { 11162 base = this.active.offset().top; 11163 height = this.element.height(); 11164 this.active.prevAll( ".ui-menu-item" ).each(function() { 11165 item = $( this ); 11166 return item.offset().top - base + height > 0; 11167 }); 11168 11169 this.focus( event, item ); 11170 } else { 11171 this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() ); 11172 } 11173 }, 11174 11175 _hasScroll: function() { 11176 return this.element.outerHeight() < this.element.prop( "scrollHeight" ); 11177 }, 11178 11179 select: function( event ) { 11180 // TODO: It should never be possible to not have an active item at this 11181 // point, but the tests don't trigger mouseenter before click. 11182 this.active = this.active || $( event.target ).closest( ".ui-menu-item" ); 11183 var ui = { item: this.active }; 11184 if ( !this.active.has( ".ui-menu" ).length ) { 11185 this.collapseAll( event, true ); 11186 } 11187 this._trigger( "select", event, ui ); 11188 } 11189}); 11190 11191}( _4ORMAT.$ )); 11192(function( $, undefined ) { 11193 11194$.widget( "ui.progressbar", { 11195 version: "1.10.4", 11196 options: { 11197 max: 100, 11198 value: 0, 11199 11200 change: null, 11201 complete: null 11202 }, 11203 11204 min: 0, 11205 11206 _create: function() { 11207 // Constrain initial value 11208 this.oldValue = this.options.value = this._constrainedValue(); 11209 11210 this.element 11211 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) 11212 .attr({ 11213 // Only set static values, aria-valuenow and aria-valuemax are 11214 // set inside _refreshValue() 11215 role: "progressbar", 11216 "aria-valuemin": this.min 11217 }); 11218 11219 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" ) 11220 .appendTo( this.element ); 11221 11222 this._refreshValue(); 11223 }, 11224 11225 _destroy: function() { 11226 this.element 11227 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) 11228 .removeAttr( "role" ) 11229 .removeAttr( "aria-valuemin" ) 11230 .removeAttr( "aria-valuemax" ) 11231 .removeAttr( "aria-valuenow" ); 11232 11233 this.valueDiv.remove(); 11234 }, 11235 11236 value: function( newValue ) { 11237 if ( newValue === undefined ) { 11238 return this.options.value; 11239 } 11240 11241 this.options.value = this._constrainedValue( newValue ); 11242 this._refreshValue(); 11243 }, 11244 11245 _constrainedValue: function( newValue ) { 11246 if ( newValue === undefined ) { 11247 newValue = this.options.value; 11248 } 11249 11250 this.indeterminate = newValue === false; 11251 11252 // sanitize value 11253 if ( typeof newValue !== "number" ) { 11254 newValue = 0; 11255 } 11256 11257 return this.indeterminate ? false : 11258 Math.min( this.options.max, Math.max( this.min, newValue ) ); 11259 }, 11260 11261 _setOptions: function( options ) { 11262 // Ensure "value" option is set after other values (like max) 11263 var value = options.value; 11264 delete options.value; 11265 11266 this._super( options ); 11267 11268 this.options.value = this._constrainedValue( value ); 11269 this._refreshValue(); 11270 }, 11271 11272 _setOption: function( key, value ) { 11273 if ( key === "max" ) { 11274 // Don't allow a max less than min 11275 value = Math.max( this.min, value ); 11276 } 11277 11278 this._super( key, value ); 11279 }, 11280 11281 _percentage: function() { 11282 return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min ); 11283 }, 11284 11285 _refreshValue: function() { 11286 var value = this.options.value, 11287 percentage = this._percentage(); 11288 11289 this.valueDiv 11290 .toggle( this.indeterminate || value > this.min ) 11291 .toggleClass( "ui-corner-right", value === this.options.max ) 11292 .width( percentage.toFixed(0) + "%" ); 11293 11294 this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate ); 11295 11296 if ( this.indeterminate ) { 11297 this.element.removeAttr( "aria-valuenow" ); 11298 if ( !this.overlayDiv ) { 11299 this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv ); 11300 } 11301 } else { 11302 this.element.attr({ 11303 "aria-valuemax": this.options.max, 11304 "aria-valuenow": value 11305 }); 11306 if ( this.overlayDiv ) { 11307 this.overlayDiv.remove(); 11308 this.overlayDiv = null; 11309 } 11310 } 11311 11312 if ( this.oldValue !== value ) { 11313 this.oldValue = value; 11314 this._trigger( "change" ); 11315 } 11316 if ( value === this.options.max ) { 11317 this._trigger( "complete" ); 11318 } 11319 } 11320}); 11321 11322})( _4ORMAT.$ ); 11323(function( $, undefined ) { 11324 11325function num(v) { 11326 return parseInt(v, 10) || 0; 11327} 11328 11329function isNumber(value) { 11330 return !isNaN(parseInt(value, 10)); 11331} 11332 11333$.widget("ui.resizable", $.ui.mouse, { 11334 version: "1.10.4", 11335 widgetEventPrefix: "resize", 11336 options: { 11337 alsoResize: false, 11338 animate: false, 11339 animateDuration: "slow", 11340 animateEasing: "swing", 11341 aspectRatio: false, 11342 autoHide: false, 11343 containment: false, 11344 ghost: false, 11345 grid: false, 11346 handles: "e,s,se", 11347 helper: false, 11348 maxHeight: null, 11349 maxWidth: null, 11350 minHeight: 10, 11351 minWidth: 10, 11352 // See #7960 11353 zIndex: 90, 11354 11355 // callbacks 11356 resize: null, 11357 start: null, 11358 stop: null 11359 }, 11360 _create: function() { 11361 11362 var n, i, handle, axis, hname, 11363 that = this, 11364 o = this.options; 11365 this.element.addClass("ui-resizable"); 11366 11367 $.extend(this, { 11368 _aspectRatio: !!(o.aspectRatio), 11369 aspectRatio: o.aspectRatio, 11370 originalElement: this.element, 11371 _proportionallyResizeElements: [], 11372 _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null 11373 }); 11374 11375 //Wrap the element if it cannot hold child nodes 11376 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) { 11377 11378 //Create a wrapper element and set the wrapper to the new current internal element 11379 this.element.wrap( 11380 $("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({ 11381 position: this.element.css("position"), 11382 width: this.element.outerWidth(), 11383 height: this.element.outerHeight(), 11384 top: this.element.css("top"), 11385 left: this.element.css("left") 11386 }) 11387 ); 11388 11389 //Overwrite the original this.element 11390 this.element = this.element.parent().data( 11391 "ui-resizable", this.element.data("ui-resizable") 11392 ); 11393 11394 this.elementIsWrapper = true; 11395 11396 //Move margins to the wrapper 11397 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") }); 11398 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0}); 11399 11400 //Prevent Safari textarea resize 11401 this.originalResizeStyle = this.originalElement.css("resize"); 11402 this.originalElement.css("resize", "none"); 11403 11404 //Push the actual element to our proportionallyResize internal array 11405 this._proportionallyResizeElements.push(this.originalElement.css({ position: "static", zoom: 1, display: "block" })); 11406 11407 // avoid IE jump (hard set the margin) 11408 this.originalElement.css({ margin: this.originalElement.css("margin") }); 11409 11410 // fix handlers offset 11411 this._proportionallyResize(); 11412 11413 } 11414 11415 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" }); 11416 if(this.handles.constructor === String) { 11417 11418 if ( this.handles === "all") { 11419 this.handles = "n,e,s,w,se,sw,ne,nw"; 11420 } 11421 11422 n = this.handles.split(","); 11423 this.handles = {}; 11424 11425 for(i = 0; i < n.length; i++) { 11426 11427 handle = $.trim(n[i]); 11428 hname = "ui-resizable-"+handle; 11429 axis = $("<div class='ui-resizable-handle " + hname + "'></div>"); 11430 11431 // Apply zIndex to all handles - see #7960 11432 axis.css({ zIndex: o.zIndex }); 11433 11434 //TODO : What's going on here? 11435 if ("se" === handle) { 11436 axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se"); 11437 } 11438 11439 //Insert into internal handles object and append to element 11440 this.handles[handle] = ".ui-resizable-"+handle; 11441 this.element.append(axis); 11442 } 11443 11444 } 11445 11446 this._renderAxis = function(target) { 11447 11448 var i, axis, padPos, padWrapper; 11449 11450 target = target || this.element; 11451 11452 for(i in this.handles) { 11453 11454 if(this.handles[i].constructor === String) { 11455 this.handles[i] = $(this.handles[i], this.element).show(); 11456 } 11457 11458 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls) 11459 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) { 11460 11461 axis = $(this.handles[i], this.element); 11462 11463 //Checking the correct pad and border 11464 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); 11465 11466 //The padding type i have to apply... 11467 padPos = [ "padding", 11468 /ne|nw|n/.test(i) ? "Top" : 11469 /se|sw|s/.test(i) ? "Bottom" : 11470 /^e$/.test(i) ? "Right" : "Left" ].join(""); 11471 11472 target.css(padPos, padWrapper); 11473 11474 this._proportionallyResize(); 11475 11476 } 11477 11478 //TODO: What's that good for? There's not anything to be executed left 11479 if(!$(this.handles[i]).length) { 11480 continue; 11481 } 11482 } 11483 }; 11484 11485 //TODO: make renderAxis a prototype function 11486 this._renderAxis(this.element); 11487 11488 this._handles = $(".ui-resizable-handle", this.element) 11489 .disableSelection(); 11490 11491 //Matching axis name 11492 this._handles.mouseover(function() { 11493 if (!that.resizing) { 11494 if (this.className) { 11495 axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); 11496 } 11497 //Axis, default = se 11498 that.axis = axis && axis[1] ? axis[1] : "se"; 11499 } 11500 }); 11501 11502 //If we want to auto hide the elements 11503 if (o.autoHide) { 11504 this._handles.hide(); 11505 $(this.element) 11506 .addClass("ui-resizable-autohide") 11507 .mouseenter(function() { 11508 if (o.disabled) { 11509 return; 11510 } 11511 $(this).removeClass("ui-resizable-autohide"); 11512 that._handles.show(); 11513 }) 11514 .mouseleave(function(){ 11515 if (o.disabled) { 11516 return; 11517 } 11518 if (!that.resizing) { 11519 $(this).addClass("ui-resizable-autohide"); 11520 that._handles.hide(); 11521 } 11522 }); 11523 } 11524 11525 //Initialize the mouse interaction 11526 this._mouseInit(); 11527 11528 }, 11529 11530 _destroy: function() { 11531 11532 this._mouseDestroy(); 11533 11534 var wrapper, 11535 _destroy = function(exp) { 11536 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing") 11537 .removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove(); 11538 }; 11539 11540 //TODO: Unwrap at same DOM position 11541 if (this.elementIsWrapper) { 11542 _destroy(this.element); 11543 wrapper = this.element; 11544 this.originalElement.css({ 11545 position: wrapper.css("position"), 11546 width: wrapper.outerWidth(), 11547 height: wrapper.outerHeight(), 11548 top: wrapper.css("top"), 11549 left: wrapper.css("left") 11550 }).insertAfter( wrapper ); 11551 wrapper.remove(); 11552 } 11553 11554 this.originalElement.css("resize", this.originalResizeStyle); 11555 _destroy(this.originalElement); 11556 11557 return this; 11558 }, 11559 11560 _mouseCapture: function(event) { 11561 var i, handle, 11562 capture = false; 11563 11564 for (i in this.handles) { 11565 handle = $(this.handles[i])[0]; 11566 if (handle === event.target || $.contains(handle, event.target)) { 11567 capture = true; 11568 } 11569 } 11570 11571 return !this.options.disabled && capture; 11572 }, 11573 11574 _mouseStart: function(event) { 11575 11576 var curleft, curtop, cursor, 11577 o = this.options, 11578 iniPos = this.element.position(), 11579 el = this.element; 11580 11581 this.resizing = true; 11582 11583 // bugfix for http://dev.jquery.com/ticket/1749 11584 if ( (/absolute/).test( el.css("position") ) ) { 11585 el.css({ position: "absolute", top: el.css("top"), left: el.css("left") }); 11586 } else if (el.is(".ui-draggable")) { 11587 el.css({ position: "absolute", top: iniPos.top, left: iniPos.left }); 11588 } 11589 11590 this._renderProxy(); 11591 11592 curleft = num(this.helper.css("left")); 11593 curtop = num(this.helper.css("top")); 11594 11595 if (o.containment) { 11596 curleft += $(o.containment).scrollLeft() || 0; 11597 curtop += $(o.containment).scrollTop() || 0; 11598 } 11599 11600 //Store needed variables 11601 this.offset = this.helper.offset(); 11602 this.position = { left: curleft, top: curtop }; 11603 this.size = this._helper ? { width: this.helper.width(), height: this.helper.height() } : { width: el.width(), height: el.height() }; 11604 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; 11605 this.originalPosition = { left: curleft, top: curtop }; 11606 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() }; 11607 this.originalMousePosition = { left: event.pageX, top: event.pageY }; 11608 11609 //Aspect Ratio 11610 this.aspectRatio = (typeof o.aspectRatio === "number") ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1); 11611 11612 cursor = $(".ui-resizable-" + this.axis).css("cursor"); 11613 $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor); 11614 11615 el.addClass("ui-resizable-resizing"); 11616 this._propagate("start", event); 11617 return true; 11618 }, 11619 11620 _mouseDrag: function(event) { 11621 11622 //Increase performance, avoid regex 11623 var data, 11624 el = this.helper, props = {}, 11625 smp = this.originalMousePosition, 11626 a = this.axis, 11627 prevTop = this.position.top, 11628 prevLeft = this.position.left, 11629 prevWidth = this.size.width, 11630 prevHeight = this.size.height, 11631 dx = (event.pageX-smp.left)||0, 11632 dy = (event.pageY-smp.top)||0, 11633 trigger = this._change[a]; 11634 11635 if (!trigger) { 11636 return false; 11637 } 11638 11639 // Calculate the attrs that will be change 11640 data = trigger.apply(this, [event, dx, dy]); 11641 11642 // Put this in the mouseDrag handler since the user can start pressing shift while resizing 11643 this._updateVirtualBoundaries(event.shiftKey); 11644 if (this._aspectRatio || event.shiftKey) { 11645 data = this._updateRatio(data, event); 11646 } 11647 11648 data = this._respectSize(data, event); 11649 11650 this._updateCache(data); 11651 11652 // plugins callbacks need to be called first 11653 this._propagate("resize", event); 11654 11655 if (this.position.top !== prevTop) { 11656 props.top = this.position.top + "px"; 11657 } 11658 if (this.position.left !== prevLeft) { 11659 props.left = this.position.left + "px"; 11660 } 11661 if (this.size.width !== prevWidth) { 11662 props.width = this.size.width + "px"; 11663 } 11664 if (this.size.height !== prevHeight) { 11665 props.height = this.size.height + "px"; 11666 } 11667 el.css(props); 11668 11669 if (!this._helper && this._proportionallyResizeElements.length) { 11670 this._proportionallyResize(); 11671 } 11672 11673 // Call the user callback if the element was resized 11674 if ( ! $.isEmptyObject(props) ) { 11675 this._trigger("resize", event, this.ui()); 11676 } 11677 11678 return false; 11679 }, 11680 11681 _mouseStop: function(event) { 11682 11683 this.resizing = false; 11684 var pr, ista, soffseth, soffsetw, s, left, top, 11685 o = this.options, that = this; 11686 11687 if(this._helper) { 11688 11689 pr = this._proportionallyResizeElements; 11690 ista = pr.length && (/textarea/i).test(pr[0].nodeName); 11691 soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height; 11692 soffsetw = ista ? 0 : that.sizeDiff.width; 11693 11694 s = { width: (that.helper.width() - soffsetw), height: (that.helper.height() - soffseth) }; 11695 left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null; 11696 top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null; 11697 11698 if (!o.animate) { 11699 this.element.css($.extend(s, { top: top, left: left })); 11700 } 11701 11702 that.helper.height(that.size.height); 11703 that.helper.width(that.size.width); 11704 11705 if (this._helper && !o.animate) { 11706 this._proportionallyResize(); 11707 } 11708 } 11709 11710 $("body").css("cursor", "auto"); 11711 11712 this.element.removeClass("ui-resizable-resizing"); 11713 11714 this._propagate("stop", event); 11715 11716 if (this._helper) { 11717 this.helper.remove(); 11718 } 11719 11720 return false; 11721 11722 }, 11723 11724 _updateVirtualBoundaries: function(forceAspectRatio) { 11725 var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b, 11726 o = this.options; 11727 11728 b = { 11729 minWidth: isNumber(o.minWidth) ? o.minWidth : 0, 11730 maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity, 11731 minHeight: isNumber(o.minHeight) ? o.minHeight : 0, 11732 maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity 11733 }; 11734 11735 if(this._aspectRatio || forceAspectRatio) { 11736 // We want to create an enclosing box whose aspect ration is the requested one 11737 // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension 11738 pMinWidth = b.minHeight * this.aspectRatio; 11739 pMinHeight = b.minWidth / this.aspectRatio; 11740 pMaxWidth = b.maxHeight * this.aspectRatio; 11741 pMaxHeight = b.maxWidth / this.aspectRatio; 11742 11743 if(pMinWidth > b.minWidth) { 11744 b.minWidth = pMinWidth; 11745 } 11746 if(pMinHeight > b.minHeight) { 11747 b.minHeight = pMinHeight; 11748 } 11749 if(pMaxWidth < b.maxWidth) { 11750 b.maxWidth = pMaxWidth; 11751 } 11752 if(pMaxHeight < b.maxHeight) { 11753 b.maxHeight = pMaxHeight; 11754 } 11755 } 11756 this._vBoundaries = b; 11757 }, 11758 11759 _updateCache: function(data) { 11760 this.offset = this.helper.offset(); 11761 if (isNumber(data.left)) { 11762 this.position.left = data.left; 11763 } 11764 if (isNumber(data.top)) { 11765 this.position.top = data.top; 11766 } 11767 if (isNumber(data.height)) { 11768 this.size.height = data.height; 11769 } 11770 if (isNumber(data.width)) { 11771 this.size.width = data.width; 11772 } 11773 }, 11774 11775 _updateRatio: function( data ) { 11776 11777 var cpos = this.position, 11778 csize = this.size, 11779 a = this.axis; 11780 11781 if (isNumber(data.height)) { 11782 data.width = (data.height * this.aspectRatio); 11783 } else if (isNumber(data.width)) { 11784 data.height = (data.width / this.aspectRatio); 11785 } 11786 11787 if (a === "sw") { 11788 data.left = cpos.left + (csize.width - data.width); 11789 data.top = null; 11790 } 11791 if (a === "nw") { 11792 data.top = cpos.top + (csize.height - data.height); 11793 data.left = cpos.left + (csize.width - data.width); 11794 } 11795 11796 return data; 11797 }, 11798 11799 _respectSize: function( data ) { 11800 11801 var o = this._vBoundaries, 11802 a = this.axis, 11803 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), 11804 isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height), 11805 dw = this.originalPosition.left + this.originalSize.width, 11806 dh = this.position.top + this.size.height, 11807 cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); 11808 if (isminw) { 11809 data.width = o.minWidth; 11810 } 11811 if (isminh) { 11812 data.height = o.minHeight; 11813 } 11814 if (ismaxw) { 11815 data.width = o.maxWidth; 11816 } 11817 if (ismaxh) { 11818 data.height = o.maxHeight; 11819 } 11820 11821 if (isminw && cw) { 11822 data.left = dw - o.minWidth; 11823 } 11824 if (ismaxw && cw) { 11825 data.left = dw - o.maxWidth; 11826 } 11827 if (isminh && ch) { 11828 data.top = dh - o.minHeight; 11829 } 11830 if (ismaxh && ch) { 11831 data.top = dh - o.maxHeight; 11832 } 11833 11834 // fixing jump error on top/left - bug #2330 11835 if (!data.width && !data.height && !data.left && data.top) { 11836 data.top = null; 11837 } else if (!data.width && !data.height && !data.top && data.left) { 11838 data.left = null; 11839 } 11840 11841 return data; 11842 }, 11843 11844 _proportionallyResize: function() { 11845 11846 if (!this._proportionallyResizeElements.length) { 11847 return; 11848 } 11849 11850 var i, j, borders, paddings, prel, 11851 element = this.helper || this.element; 11852 11853 for ( i=0; i < this._proportionallyResizeElements.length; i++) { 11854 11855 prel = this._proportionallyResizeElements[i]; 11856 11857 if (!this.borderDif) { 11858 this.borderDif = []; 11859 borders = [prel.css("borderTopWidth"), prel.css("borderRightWidth"), prel.css("borderBottomWidth"), prel.css("borderLeftWidth")]; 11860 paddings = [prel.css("paddingTop"), prel.css("paddingRight"), prel.css("paddingBottom"), prel.css("paddingLeft")]; 11861 11862 for ( j = 0; j < borders.length; j++ ) { 11863 this.borderDif[ j ] = ( parseInt( borders[ j ], 10 ) || 0 ) + ( parseInt( paddings[ j ], 10 ) || 0 ); 11864 } 11865 } 11866 11867 prel.css({ 11868 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0, 11869 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0 11870 }); 11871 11872 } 11873 11874 }, 11875 11876 _renderProxy: function() { 11877 11878 var el = this.element, o = this.options; 11879 this.elementOffset = el.offset(); 11880 11881 if(this._helper) { 11882 11883 this.helper = this.helper || $("<div style='overflow:hidden;'></div>"); 11884 11885 this.helper.addClass(this._helper).css({ 11886 width: this.element.outerWidth() - 1, 11887 height: this.element.outerHeight() - 1, 11888 position: "absolute", 11889 left: this.elementOffset.left +"px", 11890 top: this.elementOffset.top +"px", 11891 zIndex: ++o.zIndex //TODO: Don't modify option 11892 }); 11893 11894 this.helper 11895 .appendTo("body") 11896 .disableSelection(); 11897 11898 } else { 11899 this.helper = this.element; 11900 } 11901 11902 }, 11903 11904 _change: { 11905 e: function(event, dx) { 11906 return { width: this.originalSize.width + dx }; 11907 }, 11908 w: function(event, dx) { 11909 var cs = this.originalSize, sp = this.originalPosition; 11910 return { left: sp.left + dx, width: cs.width - dx }; 11911 }, 11912 n: function(event, dx, dy) { 11913 var cs = this.originalSize, sp = this.originalPosition; 11914 return { top: sp.top + dy, height: cs.height - dy }; 11915 }, 11916 s: function(event, dx, dy) { 11917 return { height: this.originalSize.height + dy }; 11918 }, 11919 se: function(event, dx, dy) { 11920 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); 11921 }, 11922 sw: function(event, dx, dy) { 11923 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); 11924 }, 11925 ne: function(event, dx, dy) { 11926 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); 11927 }, 11928 nw: function(event, dx, dy) { 11929 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); 11930 } 11931 }, 11932 11933 _propagate: function(n, event) { 11934 $.ui.plugin.call(this, n, [event, this.ui()]); 11935 (n !== "resize" && this._trigger(n, event, this.ui())); 11936 }, 11937 11938 plugins: {}, 11939 11940 ui: function() { 11941 return { 11942 originalElement: this.originalElement, 11943 element: this.element, 11944 helper: this.helper, 11945 position: this.position, 11946 size: this.size, 11947 originalSize: this.originalSize, 11948 originalPosition: this.originalPosition 11949 }; 11950 } 11951 11952}); 11953 11954/* 11955 * Resizable Extensions 11956 */ 11957 11958$.ui.plugin.add("resizable", "animate", { 11959 11960 stop: function( event ) { 11961 var that = $(this).data("ui-resizable"), 11962 o = that.options, 11963 pr = that._proportionallyResizeElements, 11964 ista = pr.length && (/textarea/i).test(pr[0].nodeName), 11965 soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height, 11966 soffsetw = ista ? 0 : that.sizeDiff.width, 11967 style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) }, 11968 left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null, 11969 top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null; 11970 11971 that.element.animate( 11972 $.extend(style, top && left ? { top: top, left: left } : {}), { 11973 duration: o.animateDuration, 11974 easing: o.animateEasing, 11975 step: function() { 11976 11977 var data = { 11978 width: parseInt(that.element.css("width"), 10), 11979 height: parseInt(that.element.css("height"), 10), 11980 top: parseInt(that.element.css("top"), 10), 11981 left: parseInt(that.element.css("left"), 10) 11982 }; 11983 11984 if (pr && pr.length) { 11985 $(pr[0]).css({ width: data.width, height: data.height }); 11986 } 11987 11988 // propagating resize, and updating values for each animation step 11989 that._updateCache(data); 11990 that._propagate("resize", event); 11991 11992 } 11993 } 11994 ); 11995 } 11996 11997}); 11998 11999$.ui.plugin.add("resizable", "containment", { 12000 12001 start: function() { 12002 var element, p, co, ch, cw, width, height, 12003 that = $(this).data("ui-resizable"), 12004 o = that.options, 12005 el = that.element, 12006 oc = o.containment, 12007 ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc; 12008 12009 if (!ce) { 12010 return; 12011 } 12012 12013 that.containerElement = $(ce); 12014 12015 if (/document/.test(oc) || oc === document) { 12016 that.containerOffset = { left: 0, top: 0 }; 12017 that.containerPosition = { left: 0, top: 0 }; 12018 12019 that.parentData = {
12020 element: $(document), left: 0, top: 0, 12021 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight 12022 }; 12023 } 12024 12025 // i'm a node, so compute top, left, right, bottom 12026 else { 12027 element = $(ce); 12028 p = []; 12029 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); }); 12030 12031 that.containerOffset = element.offset(); 12032 that.containerPosition = element.position(); 12033 that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) }; 12034 12035 co = that.containerOffset; 12036 ch = that.containerSize.height; 12037 cw = that.containerSize.width; 12038 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ); 12039 height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch); 12040 12041 that.parentData = { 12042 element: ce, left: co.left, top: co.top, width: width, height: height 12043 }; 12044 } 12045 }, 12046 12047 resize: function( event ) { 12048 var woset, hoset, isParent, isOffsetRelative, 12049 that = $(this).data("ui-resizable"), 12050 o = that.options, 12051 co = that.containerOffset, cp = that.position, 12052 pRatio = that._aspectRatio || event.shiftKey, 12053 cop = { top:0, left:0 }, ce = that.containerElement; 12054 12055 if (ce[0] !== document && (/static/).test(ce.css("position"))) { 12056 cop = co; 12057 } 12058 12059 if (cp.left < (that._helper ? co.left : 0)) { 12060 that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left)); 12061 if (pRatio) { 12062 that.size.height = that.size.width / that.aspectRatio; 12063 } 12064 that.position.left = o.helper ? co.left : 0; 12065 } 12066 12067 if (cp.top < (that._helper ? co.top : 0)) { 12068 that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top); 12069 if (pRatio) { 12070 that.size.width = that.size.height * that.aspectRatio; 12071 } 12072 that.position.top = that._helper ? co.top : 0; 12073 } 12074 12075 that.offset.left = that.parentData.left+that.position.left; 12076 that.offset.top = that.parentData.top+that.position.top; 12077 12078 woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width ); 12079 hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height ); 12080 12081 isParent = that.containerElement.get(0) === that.element.parent().get(0); 12082 isOffsetRelative = /relative|absolute/.test(that.containerElement.css("position")); 12083 12084 if ( isParent && isOffsetRelative ) { 12085 woset -= Math.abs( that.parentData.left ); 12086 } 12087 12088 if (woset + that.size.width >= that.parentData.width) { 12089 that.size.width = that.parentData.width - woset; 12090 if (pRatio) { 12091 that.size.height = that.size.width / that.aspectRatio; 12092 } 12093 } 12094 12095 if (hoset + that.size.height >= that.parentData.height) { 12096 that.size.height = that.parentData.height - hoset; 12097 if (pRatio) { 12098 that.size.width = that.size.height * that.aspectRatio; 12099 } 12100 } 12101 }, 12102 12103 stop: function(){ 12104 var that = $(this).data("ui-resizable"), 12105 o = that.options, 12106 co = that.containerOffset, 12107 cop = that.containerPosition, 12108 ce = that.containerElement, 12109 helper = $(that.helper), 12110 ho = helper.offset(), 12111 w = helper.outerWidth() - that.sizeDiff.width, 12112 h = helper.outerHeight() - that.sizeDiff.height; 12113 12114 if (that._helper && !o.animate && (/relative/).test(ce.css("position"))) { 12115 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); 12116 } 12117 12118 if (that._helper && !o.animate && (/static/).test(ce.css("position"))) { 12119 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); 12120 } 12121 12122 } 12123}); 12124 12125$.ui.plugin.add("resizable", "alsoResize", { 12126 12127 start: function () { 12128 var that = $(this).data("ui-resizable"), 12129 o = that.options, 12130 _store = function (exp) { 12131 $(exp).each(function() { 12132 var el = $(this); 12133 el.data("ui-resizable-alsoresize", { 12134 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), 12135 left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10) 12136 }); 12137 }); 12138 }; 12139
vendor: 56,170 bytes, lines 12140-13986
12140 if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) { 12141 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); } 12142 else { $.each(o.alsoResize, function (exp) { _store(exp); }); } 12143 }else{ 12144 _store(o.alsoResize); 12145 } 12146 }, 12147 12148 resize: function (event, ui) { 12149 var that = $(this).data("ui-resizable"), 12150 o = that.options, 12151 os = that.originalSize, 12152 op = that.originalPosition, 12153 delta = { 12154 height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0, 12155 top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0 12156 }, 12157 12158 _alsoResize = function (exp, c) { 12159 $(exp).each(function() { 12160 var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {}, 12161 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ["width", "height"] : ["width", "height", "top", "left"]; 12162 12163 $.each(css, function (i, prop) { 12164 var sum = (start[prop]||0) + (delta[prop]||0); 12165 if (sum && sum >= 0) { 12166 style[prop] = sum || null; 12167 } 12168 }); 12169 12170 el.css(style); 12171 }); 12172 }; 12173 12174 if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) { 12175 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); }); 12176 }else{ 12177 _alsoResize(o.alsoResize); 12178 } 12179 }, 12180 12181 stop: function () { 12182 $(this).removeData("resizable-alsoresize"); 12183 } 12184}); 12185 12186$.ui.plugin.add("resizable", "ghost", { 12187 12188 start: function() { 12189 12190 var that = $(this).data("ui-resizable"), o = that.options, cs = that.size; 12191 12192 that.ghost = that.originalElement.clone(); 12193 that.ghost 12194 .css({ opacity: 0.25, display: "block", position: "relative", height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }) 12195 .addClass("ui-resizable-ghost") 12196 .addClass(typeof o.ghost === "string" ? o.ghost : ""); 12197 12198 that.ghost.appendTo(that.helper); 12199 12200 }, 12201 12202 resize: function(){ 12203 var that = $(this).data("ui-resizable"); 12204 if (that.ghost) { 12205 that.ghost.css({ position: "relative", height: that.size.height, width: that.size.width }); 12206 } 12207 }, 12208 12209 stop: function() { 12210 var that = $(this).data("ui-resizable"); 12211 if (that.ghost && that.helper) { 12212 that.helper.get(0).removeChild(that.ghost.get(0)); 12213 } 12214 } 12215 12216}); 12217 12218$.ui.plugin.add("resizable", "grid", { 12219 12220 resize: function() { 12221 var that = $(this).data("ui-resizable"), 12222 o = that.options, 12223 cs = that.size, 12224 os = that.originalSize, 12225 op = that.originalPosition, 12226 a = that.axis, 12227 grid = typeof o.grid === "number" ? [o.grid, o.grid] : o.grid, 12228 gridX = (grid[0]||1), 12229 gridY = (grid[1]||1), 12230 ox = Math.round((cs.width - os.width) / gridX) * gridX, 12231 oy = Math.round((cs.height - os.height) / gridY) * gridY, 12232 newWidth = os.width + ox, 12233 newHeight = os.height + oy, 12234 isMaxWidth = o.maxWidth && (o.maxWidth < newWidth), 12235 isMaxHeight = o.maxHeight && (o.maxHeight < newHeight), 12236 isMinWidth = o.minWidth && (o.minWidth > newWidth), 12237 isMinHeight = o.minHeight && (o.minHeight > newHeight); 12238 12239 o.grid = grid; 12240 12241 if (isMinWidth) { 12242 newWidth = newWidth + gridX; 12243 } 12244 if (isMinHeight) { 12245 newHeight = newHeight + gridY; 12246 } 12247 if (isMaxWidth) { 12248 newWidth = newWidth - gridX; 12249 } 12250 if (isMaxHeight) { 12251 newHeight = newHeight - gridY; 12252 } 12253 12254 if (/^(se|s|e)$/.test(a)) { 12255 that.size.width = newWidth; 12256 that.size.height = newHeight; 12257 } else if (/^(ne)$/.test(a)) { 12258 that.size.width = newWidth; 12259 that.size.height = newHeight; 12260 that.position.top = op.top - oy; 12261 } else if (/^(sw)$/.test(a)) { 12262 that.size.width = newWidth; 12263 that.size.height = newHeight; 12264 that.position.left = op.left - ox; 12265 } else { 12266 if ( newHeight - gridY > 0 ) { 12267 that.size.height = newHeight; 12268 that.position.top = op.top - oy; 12269 } else { 12270 that.size.height = gridY; 12271 that.position.top = op.top + os.height - gridY; 12272 } 12273 if ( newWidth - gridX > 0 ) { 12274 that.size.width = newWidth; 12275 that.position.left = op.left - ox; 12276 } else { 12277 that.size.width = gridX; 12278 that.position.left = op.left + os.width - gridX; 12279 } 12280 } 12281 } 12282 12283}); 12284 12285})( _4ORMAT.$ ); 12286(function( $, undefined ) { 12287 12288$.widget("ui.selectable", $.ui.mouse, { 12289 version: "1.10.4", 12290 options: { 12291 appendTo: "body", 12292 autoRefresh: true, 12293 distance: 0, 12294 filter: "*", 12295 tolerance: "touch", 12296 12297 // callbacks 12298 selected: null, 12299 selecting: null, 12300 start: null, 12301 stop: null, 12302 unselected: null, 12303 unselecting: null 12304 }, 12305 _create: function() { 12306 var selectees, 12307 that = this; 12308 12309 this.element.addClass("ui-selectable"); 12310 12311 this.dragged = false; 12312 12313 // cache selectee children based on filter 12314 this.refresh = function() { 12315 selectees = $(that.options.filter, that.element[0]); 12316 selectees.addClass("ui-selectee"); 12317 selectees.each(function() { 12318 var $this = $(this), 12319 pos = $this.offset(); 12320 $.data(this, "selectable-item", { 12321 element: this, 12322 $element: $this, 12323 left: pos.left, 12324 top: pos.top, 12325 right: pos.left + $this.outerWidth(), 12326 bottom: pos.top + $this.outerHeight(), 12327 startselected: false, 12328 selected: $this.hasClass("ui-selected"), 12329 selecting: $this.hasClass("ui-selecting"), 12330 unselecting: $this.hasClass("ui-unselecting") 12331 }); 12332 }); 12333 }; 12334 this.refresh(); 12335 12336 this.selectees = selectees.addClass("ui-selectee"); 12337 12338 this._mouseInit(); 12339 12340 this.helper = $("<div class='ui-selectable-helper'></div>"); 12341 }, 12342 12343 _destroy: function() { 12344 this.selectees 12345 .removeClass("ui-selectee") 12346 .removeData("selectable-item"); 12347 this.element 12348 .removeClass("ui-selectable ui-selectable-disabled"); 12349 this._mouseDestroy(); 12350 }, 12351 12352 _mouseStart: function(event) { 12353 var that = this, 12354 options = this.options; 12355 12356 this.opos = [event.pageX, event.pageY]; 12357 12358 if (this.options.disabled) { 12359 return; 12360 } 12361 12362 this.selectees = $(options.filter, this.element[0]); 12363 12364 this._trigger("start", event); 12365 12366 $(options.appendTo).append(this.helper); 12367 // position helper (lasso) 12368 this.helper.css({ 12369 "left": event.pageX, 12370 "top": event.pageY, 12371 "width": 0, 12372 "height": 0 12373 }); 12374 12375 if (options.autoRefresh) { 12376 this.refresh(); 12377 } 12378 12379 this.selectees.filter(".ui-selected").each(function() { 12380 var selectee = $.data(this, "selectable-item"); 12381 selectee.startselected = true; 12382 if (!event.metaKey && !event.ctrlKey) { 12383 selectee.$element.removeClass("ui-selected"); 12384 selectee.selected = false; 12385 selectee.$element.addClass("ui-unselecting"); 12386 selectee.unselecting = true; 12387 // selectable UNSELECTING callback 12388 that._trigger("unselecting", event, { 12389 unselecting: selectee.element 12390 }); 12391 } 12392 }); 12393 12394 $(event.target).parents().addBack().each(function() { 12395 var doSelect, 12396 selectee = $.data(this, "selectable-item"); 12397 if (selectee) { 12398 doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected"); 12399 selectee.$element 12400 .removeClass(doSelect ? "ui-unselecting" : "ui-selected") 12401 .addClass(doSelect ? "ui-selecting" : "ui-unselecting"); 12402 selectee.unselecting = !doSelect; 12403 selectee.selecting = doSelect; 12404 selectee.selected = doSelect; 12405 // selectable (UN)SELECTING callback 12406 if (doSelect) { 12407 that._trigger("selecting", event, { 12408 selecting: selectee.element 12409 }); 12410 } else { 12411 that._trigger("unselecting", event, { 12412 unselecting: selectee.element 12413 }); 12414 } 12415 return false; 12416 } 12417 }); 12418 12419 }, 12420 12421 _mouseDrag: function(event) { 12422 12423 this.dragged = true; 12424 12425 if (this.options.disabled) { 12426 return; 12427 } 12428 12429 var tmp, 12430 that = this, 12431 options = this.options, 12432 x1 = this.opos[0], 12433 y1 = this.opos[1], 12434 x2 = event.pageX, 12435 y2 = event.pageY; 12436 12437 if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; } 12438 if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; } 12439 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1}); 12440 12441 this.selectees.each(function() { 12442 var selectee = $.data(this, "selectable-item"), 12443 hit = false; 12444 12445 //prevent helper from being selected if appendTo: selectable 12446 if (!selectee || selectee.element === that.element[0]) { 12447 return; 12448 } 12449 12450 if (options.tolerance === "touch") { 12451 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) ); 12452 } else if (options.tolerance === "fit") { 12453 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2); 12454 } 12455 12456 if (hit) { 12457 // SELECT 12458 if (selectee.selected) { 12459 selectee.$element.removeClass("ui-selected"); 12460 selectee.selected = false; 12461 } 12462 if (selectee.unselecting) { 12463 selectee.$element.removeClass("ui-unselecting"); 12464 selectee.unselecting = false; 12465 } 12466 if (!selectee.selecting) { 12467 selectee.$element.addClass("ui-selecting"); 12468 selectee.selecting = true; 12469 // selectable SELECTING callback 12470 that._trigger("selecting", event, { 12471 selecting: selectee.element 12472 }); 12473 } 12474 } else { 12475 // UNSELECT 12476 if (selectee.selecting) { 12477 if ((event.metaKey || event.ctrlKey) && selectee.startselected) { 12478 selectee.$element.removeClass("ui-selecting"); 12479 selectee.selecting = false; 12480 selectee.$element.addClass("ui-selected"); 12481 selectee.selected = true; 12482 } else { 12483 selectee.$element.removeClass("ui-selecting"); 12484 selectee.selecting = false; 12485 if (selectee.startselected) { 12486 selectee.$element.addClass("ui-unselecting"); 12487 selectee.unselecting = true; 12488 } 12489 // selectable UNSELECTING callback 12490 that._trigger("unselecting", event, { 12491 unselecting: selectee.element 12492 }); 12493 } 12494 } 12495 if (selectee.selected) { 12496 if (!event.metaKey && !event.ctrlKey && !selectee.startselected) { 12497 selectee.$element.removeClass("ui-selected"); 12498 selectee.selected = false; 12499 12500 selectee.$element.addClass("ui-unselecting"); 12501 selectee.unselecting = true; 12502 // selectable UNSELECTING callback 12503 that._trigger("unselecting", event, { 12504 unselecting: selectee.element 12505 }); 12506 } 12507 } 12508 } 12509 }); 12510 12511 return false; 12512 }, 12513 12514 _mouseStop: function(event) { 12515 var that = this; 12516 12517 this.dragged = false; 12518 12519 $(".ui-unselecting", this.element[0]).each(function() { 12520 var selectee = $.data(this, "selectable-item"); 12521 selectee.$element.removeClass("ui-unselecting"); 12522 selectee.unselecting = false; 12523 selectee.startselected = false; 12524 that._trigger("unselected", event, { 12525 unselected: selectee.element 12526 }); 12527 }); 12528 $(".ui-selecting", this.element[0]).each(function() { 12529 var selectee = $.data(this, "selectable-item"); 12530 selectee.$element.removeClass("ui-selecting").addClass("ui-selected"); 12531 selectee.selecting = false; 12532 selectee.selected = true; 12533 selectee.startselected = true; 12534 that._trigger("selected", event, { 12535 selected: selectee.element 12536 }); 12537 }); 12538 this._trigger("stop", event); 12539 12540 this.helper.remove(); 12541 12542 return false; 12543 } 12544 12545}); 12546 12547})( _4ORMAT.$ ); 12548(function( $, undefined ) { 12549 12550// number of pages in a slider 12551// (how many times can you page up/down to go through the whole range) 12552var numPages = 5; 12553 12554$.widget( "ui.slider", $.ui.mouse, { 12555 version: "1.10.4", 12556 widgetEventPrefix: "slide", 12557 12558 options: { 12559 animate: false, 12560 distance: 0, 12561 max: 100, 12562 min: 0, 12563 orientation: "horizontal", 12564 range: false, 12565 step: 1, 12566 value: 0, 12567 values: null, 12568 12569 // callbacks 12570 change: null, 12571 slide: null, 12572 start: null, 12573 stop: null 12574 }, 12575 12576 _create: function() { 12577 this._keySliding = false; 12578 this._mouseSliding = false; 12579 this._animateOff = true; 12580 this._handleIndex = null; 12581 this._detectOrientation(); 12582 this._mouseInit(); 12583 12584 this.element 12585 .addClass( "ui-slider" + 12586 " ui-slider-" + this.orientation + 12587 " ui-widget" + 12588 " ui-widget-content" + 12589 " ui-corner-all"); 12590 12591 this._refresh(); 12592 this._setOption( "disabled", this.options.disabled ); 12593 12594 this._animateOff = false; 12595 }, 12596 12597 _refresh: function() { 12598 this._createRange(); 12599 this._createHandles(); 12600 this._setupEvents(); 12601 this._refreshValue(); 12602 }, 12603 12604 _createHandles: function() { 12605 var i, handleCount, 12606 options = this.options, 12607 existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ), 12608 handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>", 12609 handles = []; 12610 12611 handleCount = ( options.values && options.values.length ) || 1; 12612 12613 if ( existingHandles.length > handleCount ) { 12614 existingHandles.slice( handleCount ).remove(); 12615 existingHandles = existingHandles.slice( 0, handleCount ); 12616 } 12617 12618 for ( i = existingHandles.length; i < handleCount; i++ ) { 12619 handles.push( handle ); 12620 } 12621 12622 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) ); 12623 12624 this.handle = this.handles.eq( 0 ); 12625 12626 this.handles.each(function( i ) { 12627 $( this ).data( "ui-slider-handle-index", i ); 12628 }); 12629 }, 12630 12631 _createRange: function() { 12632 var options = this.options, 12633 classes = ""; 12634 12635 if ( options.range ) { 12636 if ( options.range === true ) { 12637 if ( !options.values ) { 12638 options.values = [ this._valueMin(), this._valueMin() ]; 12639 } else if ( options.values.length && options.values.length !== 2 ) { 12640 options.values = [ options.values[0], options.values[0] ]; 12641 } else if ( $.isArray( options.values ) ) { 12642 options.values = options.values.slice(0); 12643 } 12644 } 12645 12646 if ( !this.range || !this.range.length ) { 12647 this.range = $( "<div></div>" ) 12648 .appendTo( this.element ); 12649 12650 classes = "ui-slider-range" + 12651 // note: this isn't the most fittingly semantic framework class for this element, 12652 // but worked best visually with a variety of themes 12653 " ui-widget-header ui-corner-all"; 12654 } else { 12655 this.range.removeClass( "ui-slider-range-min ui-slider-range-max" ) 12656 // Handle range switching from true to min/max 12657 .css({ 12658 "left": "", 12659 "bottom": "" 12660 }); 12661 } 12662 12663 this.range.addClass( classes + 12664 ( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) ); 12665 } else { 12666 if ( this.range ) { 12667 this.range.remove(); 12668 } 12669 this.range = null; 12670 } 12671 }, 12672 12673 _setupEvents: function() { 12674 var elements = this.handles.add( this.range ).filter( "a" ); 12675 this._off( elements ); 12676 this._on( elements, this._handleEvents ); 12677 this._hoverable( elements ); 12678 this._focusable( elements ); 12679 }, 12680 12681 _destroy: function() { 12682 this.handles.remove(); 12683 if ( this.range ) { 12684 this.range.remove(); 12685 } 12686 12687 this.element 12688 .removeClass( "ui-slider" + 12689 " ui-slider-horizontal" + 12690 " ui-slider-vertical" + 12691 " ui-widget" + 12692 " ui-widget-content" + 12693 " ui-corner-all" ); 12694 12695 this._mouseDestroy(); 12696 }, 12697 12698 _mouseCapture: function( event ) { 12699 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle, 12700 that = this, 12701 o = this.options; 12702 12703 if ( o.disabled ) { 12704 return false; 12705 } 12706 12707 this.elementSize = { 12708 width: this.element.outerWidth(), 12709 height: this.element.outerHeight() 12710 }; 12711 this.elementOffset = this.element.offset(); 12712 12713 position = { x: event.pageX, y: event.pageY }; 12714 normValue = this._normValueFromMouse( position ); 12715 distance = this._valueMax() - this._valueMin() + 1; 12716 this.handles.each(function( i ) { 12717 var thisDistance = Math.abs( normValue - that.values(i) ); 12718 if (( distance > thisDistance ) || 12719 ( distance === thisDistance && 12720 (i === that._lastChangedValue || that.values(i) === o.min ))) { 12721 distance = thisDistance; 12722 closestHandle = $( this ); 12723 index = i; 12724 } 12725 }); 12726 12727 allowed = this._start( event, index ); 12728 if ( allowed === false ) { 12729 return false; 12730 } 12731 this._mouseSliding = true; 12732 12733 this._handleIndex = index; 12734 12735 closestHandle 12736 .addClass( "ui-state-active" ) 12737 .focus(); 12738 12739 offset = closestHandle.offset(); 12740 mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" ); 12741 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { 12742 left: event.pageX - offset.left - ( closestHandle.width() / 2 ), 12743 top: event.pageY - offset.top - 12744 ( closestHandle.height() / 2 ) - 12745 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) - 12746 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) + 12747 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0) 12748 }; 12749 12750 if ( !this.handles.hasClass( "ui-state-hover" ) ) { 12751 this._slide( event, index, normValue ); 12752 } 12753 this._animateOff = true; 12754 return true; 12755 }, 12756 12757 _mouseStart: function() { 12758 return true; 12759 }, 12760 12761 _mouseDrag: function( event ) { 12762 var position = { x: event.pageX, y: event.pageY }, 12763 normValue = this._normValueFromMouse( position ); 12764 12765 this._slide( event, this._handleIndex, normValue ); 12766 12767 return false; 12768 }, 12769 12770 _mouseStop: function( event ) { 12771 this.handles.removeClass( "ui-state-active" ); 12772 this._mouseSliding = false; 12773 12774 this._stop( event, this._handleIndex ); 12775 this._change( event, this._handleIndex ); 12776 12777 this._handleIndex = null; 12778 this._clickOffset = null; 12779 this._animateOff = false; 12780 12781 return false; 12782 }, 12783 12784 _detectOrientation: function() { 12785 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; 12786 }, 12787 12788 _normValueFromMouse: function( position ) { 12789 var pixelTotal, 12790 pixelMouse, 12791 percentMouse, 12792 valueTotal, 12793 valueMouse; 12794 12795 if ( this.orientation === "horizontal" ) { 12796 pixelTotal = this.elementSize.width; 12797 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 ); 12798 } else { 12799 pixelTotal = this.elementSize.height; 12800 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 ); 12801 } 12802 12803 percentMouse = ( pixelMouse / pixelTotal ); 12804 if ( percentMouse > 1 ) { 12805 percentMouse = 1; 12806 } 12807 if ( percentMouse < 0 ) { 12808 percentMouse = 0; 12809 } 12810 if ( this.orientation === "vertical" ) { 12811 percentMouse = 1 - percentMouse; 12812 } 12813 12814 valueTotal = this._valueMax() - this._valueMin(); 12815 valueMouse = this._valueMin() + percentMouse * valueTotal; 12816 12817 return this._trimAlignValue( valueMouse ); 12818 }, 12819 12820 _start: function( event, index ) { 12821 var uiHash = { 12822 handle: this.handles[ index ], 12823 value: this.value() 12824 }; 12825 if ( this.options.values && this.options.values.length ) { 12826 uiHash.value = this.values( index ); 12827 uiHash.values = this.values(); 12828 } 12829 return this._trigger( "start", event, uiHash ); 12830 }, 12831 12832 _slide: function( event, index, newVal ) { 12833 var otherVal, 12834 newValues, 12835 allowed; 12836 12837 if ( this.options.values && this.options.values.length ) { 12838 otherVal = this.values( index ? 0 : 1 ); 12839 12840 if ( ( this.options.values.length === 2 && this.options.range === true ) && 12841 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) ) 12842 ) { 12843 newVal = otherVal; 12844 } 12845 12846 if ( newVal !== this.values( index ) ) { 12847 newValues = this.values(); 12848 newValues[ index ] = newVal; 12849 // A slide can be canceled by returning false from the slide callback 12850 allowed = this._trigger( "slide", event, { 12851 handle: this.handles[ index ], 12852 value: newVal, 12853 values: newValues 12854 } ); 12855 otherVal = this.values( index ? 0 : 1 ); 12856 if ( allowed !== false ) { 12857 this.values( index, newVal ); 12858 } 12859 } 12860 } else { 12861 if ( newVal !== this.value() ) { 12862 // A slide can be canceled by returning false from the slide callback 12863 allowed = this._trigger( "slide", event, { 12864 handle: this.handles[ index ], 12865 value: newVal 12866 } ); 12867 if ( allowed !== false ) { 12868 this.value( newVal ); 12869 } 12870 } 12871 } 12872 }, 12873 12874 _stop: function( event, index ) { 12875 var uiHash = { 12876 handle: this.handles[ index ], 12877 value: this.value() 12878 }; 12879 if ( this.options.values && this.options.values.length ) { 12880 uiHash.value = this.values( index ); 12881 uiHash.values = this.values(); 12882 } 12883 12884 this._trigger( "stop", event, uiHash ); 12885 }, 12886 12887 _change: function( event, index ) { 12888 if ( !this._keySliding && !this._mouseSliding ) { 12889 var uiHash = { 12890 handle: this.handles[ index ], 12891 value: this.value() 12892 }; 12893 if ( this.options.values && this.options.values.length ) { 12894 uiHash.value = this.values( index ); 12895 uiHash.values = this.values(); 12896 } 12897 12898 //store the last changed value index for reference when handles overlap 12899 this._lastChangedValue = index; 12900 12901 this._trigger( "change", event, uiHash ); 12902 } 12903 }, 12904 12905 value: function( newValue ) { 12906 if ( arguments.length ) { 12907 this.options.value = this._trimAlignValue( newValue ); 12908 this._refreshValue(); 12909 this._change( null, 0 ); 12910 return; 12911 } 12912 12913 return this._value(); 12914 }, 12915 12916 values: function( index, newValue ) { 12917 var vals, 12918 newValues, 12919 i; 12920 12921 if ( arguments.length > 1 ) { 12922 this.options.values[ index ] = this._trimAlignValue( newValue ); 12923 this._refreshValue(); 12924 this._change( null, index ); 12925 return; 12926 } 12927 12928 if ( arguments.length ) { 12929 if ( $.isArray( arguments[ 0 ] ) ) { 12930 vals = this.options.values; 12931 newValues = arguments[ 0 ]; 12932 for ( i = 0; i < vals.length; i += 1 ) { 12933 vals[ i ] = this._trimAlignValue( newValues[ i ] ); 12934 this._change( null, i ); 12935 } 12936 this._refreshValue(); 12937 } else { 12938 if ( this.options.values && this.options.values.length ) { 12939 return this._values( index ); 12940 } else { 12941 return this.value(); 12942 } 12943 } 12944 } else { 12945 return this._values(); 12946 } 12947 }, 12948 12949 _setOption: function( key, value ) { 12950 var i, 12951 valsLength = 0; 12952 12953 if ( key === "range" && this.options.range === true ) { 12954 if ( value === "min" ) { 12955 this.options.value = this._values( 0 ); 12956 this.options.values = null; 12957 } else if ( value === "max" ) { 12958 this.options.value = this._values( this.options.values.length-1 ); 12959 this.options.values = null; 12960 } 12961 } 12962 12963 if ( $.isArray( this.options.values ) ) { 12964 valsLength = this.options.values.length; 12965 } 12966 12967 $.Widget.prototype._setOption.apply( this, arguments ); 12968 12969 switch ( key ) { 12970 case "orientation": 12971 this._detectOrientation(); 12972 this.element 12973 .removeClass( "ui-slider-horizontal ui-slider-vertical" ) 12974 .addClass( "ui-slider-" + this.orientation ); 12975 this._refreshValue(); 12976 break; 12977 case "value": 12978 this._animateOff = true; 12979 this._refreshValue(); 12980 this._change( null, 0 ); 12981 this._animateOff = false; 12982 break; 12983 case "values": 12984 this._animateOff = true; 12985 this._refreshValue(); 12986 for ( i = 0; i < valsLength; i += 1 ) { 12987 this._change( null, i ); 12988 } 12989 this._animateOff = false; 12990 break; 12991 case "min": 12992 case "max": 12993 this._animateOff = true; 12994 this._refreshValue(); 12995 this._animateOff = false; 12996 break; 12997 case "range": 12998 this._animateOff = true; 12999 this._refresh(); 13000 this._animateOff = false; 13001 break; 13002 } 13003 }, 13004 13005 //internal value getter 13006 // _value() returns value trimmed by min and max, aligned by step 13007 _value: function() { 13008 var val = this.options.value; 13009 val = this._trimAlignValue( val ); 13010 13011 return val; 13012 }, 13013 13014 //internal values getter 13015 // _values() returns array of values trimmed by min and max, aligned by step 13016 // _values( index ) returns single value trimmed by min and max, aligned by step 13017 _values: function( index ) { 13018 var val, 13019 vals, 13020 i; 13021 13022 if ( arguments.length ) { 13023 val = this.options.values[ index ]; 13024 val = this._trimAlignValue( val ); 13025 13026 return val; 13027 } else if ( this.options.values && this.options.values.length ) { 13028 // .slice() creates a copy of the array 13029 // this copy gets trimmed by min and max and then returned 13030 vals = this.options.values.slice(); 13031 for ( i = 0; i < vals.length; i+= 1) { 13032 vals[ i ] = this._trimAlignValue( vals[ i ] ); 13033 } 13034 13035 return vals; 13036 } else { 13037 return []; 13038 } 13039 }, 13040 13041 // returns the step-aligned value that val is closest to, between (inclusive) min and max 13042 _trimAlignValue: function( val ) { 13043 if ( val <= this._valueMin() ) { 13044 return this._valueMin(); 13045 } 13046 if ( val >= this._valueMax() ) { 13047 return this._valueMax(); 13048 } 13049 var step = ( this.options.step > 0 ) ? this.options.step : 1, 13050 valModStep = (val - this._valueMin()) % step, 13051 alignValue = val - valModStep; 13052 13053 if ( Math.abs(valModStep) * 2 >= step ) { 13054 alignValue += ( valModStep > 0 ) ? step : ( -step ); 13055 } 13056 13057 // Since JavaScript has problems with large floats, round 13058 // the final value to 5 digits after the decimal point (see #4124) 13059 return parseFloat( alignValue.toFixed(5) ); 13060 }, 13061 13062 _valueMin: function() { 13063 return this.options.min; 13064 }, 13065 13066 _valueMax: function() { 13067 return this.options.max; 13068 }, 13069 13070 _refreshValue: function() { 13071 var lastValPercent, valPercent, value, valueMin, valueMax, 13072 oRange = this.options.range, 13073 o = this.options, 13074 that = this, 13075 animate = ( !this._animateOff ) ? o.animate : false, 13076 _set = {}; 13077 13078 if ( this.options.values && this.options.values.length ) { 13079 this.handles.each(function( i ) { 13080 valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100; 13081 _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 13082 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 13083 if ( that.options.range === true ) { 13084 if ( that.orientation === "horizontal" ) { 13085 if ( i === 0 ) { 13086 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate ); 13087 } 13088 if ( i === 1 ) { 13089 that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); 13090 } 13091 } else { 13092 if ( i === 0 ) { 13093 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate ); 13094 } 13095 if ( i === 1 ) { 13096 that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); 13097 } 13098 } 13099 } 13100 lastValPercent = valPercent; 13101 }); 13102 } else { 13103 value = this.value(); 13104 valueMin = this._valueMin(); 13105 valueMax = this._valueMax(); 13106 valPercent = ( valueMax !== valueMin ) ? 13107 ( value - valueMin ) / ( valueMax - valueMin ) * 100 : 13108 0; 13109 _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 13110 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 13111 13112 if ( oRange === "min" && this.orientation === "horizontal" ) { 13113 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate ); 13114 } 13115 if ( oRange === "max" && this.orientation === "horizontal" ) { 13116 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); 13117 } 13118 if ( oRange === "min" && this.orientation === "vertical" ) { 13119 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate ); 13120 } 13121 if ( oRange === "max" && this.orientation === "vertical" ) { 13122 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); 13123 } 13124 } 13125 }, 13126 13127 _handleEvents: { 13128 keydown: function( event ) { 13129 var allowed, curVal, newVal, step, 13130 index = $( event.target ).data( "ui-slider-handle-index" ); 13131 13132 switch ( event.keyCode ) { 13133 case $.ui.keyCode.HOME: 13134 case $.ui.keyCode.END: 13135 case $.ui.keyCode.PAGE_UP: 13136 case $.ui.keyCode.PAGE_DOWN: 13137 case $.ui.keyCode.UP: 13138 case $.ui.keyCode.RIGHT: 13139 case $.ui.keyCode.DOWN: 13140 case $.ui.keyCode.LEFT: 13141 event.preventDefault(); 13142 if ( !this._keySliding ) { 13143 this._keySliding = true; 13144 $( event.target ).addClass( "ui-state-active" ); 13145 allowed = this._start( event, index ); 13146 if ( allowed === false ) { 13147 return; 13148 } 13149 } 13150 break; 13151 } 13152 13153 step = this.options.step; 13154 if ( this.options.values && this.options.values.length ) { 13155 curVal = newVal = this.values( index ); 13156 } else { 13157 curVal = newVal = this.value(); 13158 } 13159 13160 switch ( event.keyCode ) { 13161 case $.ui.keyCode.HOME: 13162 newVal = this._valueMin(); 13163 break; 13164 case $.ui.keyCode.END: 13165 newVal = this._valueMax(); 13166 break; 13167 case $.ui.keyCode.PAGE_UP: 13168 newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) ); 13169 break; 13170 case $.ui.keyCode.PAGE_DOWN: 13171 newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) ); 13172 break; 13173 case $.ui.keyCode.UP: 13174 case $.ui.keyCode.RIGHT: 13175 if ( curVal === this._valueMax() ) { 13176 return; 13177 } 13178 newVal = this._trimAlignValue( curVal + step ); 13179 break; 13180 case $.ui.keyCode.DOWN: 13181 case $.ui.keyCode.LEFT: 13182 if ( curVal === this._valueMin() ) { 13183 return; 13184 } 13185 newVal = this._trimAlignValue( curVal - step ); 13186 break; 13187 } 13188 13189 this._slide( event, index, newVal ); 13190 }, 13191 click: function( event ) { 13192 event.preventDefault(); 13193 }, 13194 keyup: function( event ) { 13195 var index = $( event.target ).data( "ui-slider-handle-index" ); 13196 13197 if ( this._keySliding ) { 13198 this._keySliding = false; 13199 this._stop( event, index ); 13200 this._change( event, index ); 13201 $( event.target ).removeClass( "ui-state-active" ); 13202 } 13203 } 13204 } 13205 13206}); 13207 13208}( _4ORMAT.$ )); 13209(function( $, undefined ) { 13210 13211function isOverAxis( x, reference, size ) { 13212 return ( x > reference ) && ( x < ( reference + size ) ); 13213} 13214 13215function isFloating(item) { 13216 return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display")); 13217} 13218 13219$.widget("ui.sortable", $.ui.mouse, { 13220 version: "1.10.4", 13221 widgetEventPrefix: "sort", 13222 ready: false, 13223 options: { 13224 appendTo: "parent", 13225 axis: false, 13226 connectWith: false, 13227 containment: false, 13228 cursor: "auto", 13229 cursorAt: false, 13230 dropOnEmpty: true, 13231 forcePlaceholderSize: false, 13232 forceHelperSize: false, 13233 grid: false, 13234 handle: false, 13235 helper: "original", 13236 items: "> *", 13237 opacity: false, 13238 placeholder: false, 13239 revert: false, 13240 scroll: true, 13241 scrollSensitivity: 20, 13242 scrollSpeed: 20, 13243 scope: "default", 13244 tolerance: "intersect", 13245 zIndex: 1000, 13246 13247 // callbacks 13248 activate: null, 13249 beforeStop: null, 13250 change: null, 13251 deactivate: null, 13252 out: null, 13253 over: null, 13254 receive: null, 13255 remove: null, 13256 sort: null, 13257 start: null, 13258 stop: null, 13259 update: null 13260 }, 13261 _create: function() { 13262 13263 var o = this.options; 13264 this.containerCache = {}; 13265 this.element.addClass("ui-sortable"); 13266 13267 //Get the items 13268 this.refresh(); 13269 13270 //Let's determine if the items are being displayed horizontally 13271 this.floating = this.items.length ? o.axis === "x" || isFloating(this.items[0].item) : false; 13272 13273 //Let's determine the parent's offset 13274 this.offset = this.element.offset(); 13275 13276 //Initialize mouse events for interaction 13277 this._mouseInit(); 13278 13279 //We're ready to go 13280 this.ready = true; 13281 13282 }, 13283 13284 _destroy: function() { 13285 this.element 13286 .removeClass("ui-sortable ui-sortable-disabled"); 13287 this._mouseDestroy(); 13288 13289 for ( var i = this.items.length - 1; i >= 0; i-- ) { 13290 this.items[i].item.removeData(this.widgetName + "-item"); 13291 } 13292 13293 return this; 13294 }, 13295 13296 _setOption: function(key, value){ 13297 if ( key === "disabled" ) { 13298 this.options[ key ] = value; 13299 13300 this.widget().toggleClass( "ui-sortable-disabled", !!value ); 13301 } else { 13302 // Don't call widget base _setOption for disable as it adds ui-state-disabled class 13303 $.Widget.prototype._setOption.apply(this, arguments); 13304 } 13305 }, 13306 13307 _mouseCapture: function(event, overrideHandle) { 13308 var currentItem = null, 13309 validHandle = false, 13310 that = this; 13311 13312 if (this.reverting) { 13313 return false; 13314 } 13315 13316 if(this.options.disabled || this.options.type === "static") { 13317 return false; 13318 } 13319 13320 //We have to refresh the items data once first 13321 this._refreshItems(event); 13322 13323 //Find out if the clicked node (or one of its parents) is a actual item in this.items 13324 $(event.target).parents().each(function() { 13325 if($.data(this, that.widgetName + "-item") === that) { 13326 currentItem = $(this); 13327 return false; 13328 } 13329 }); 13330 if($.data(event.target, that.widgetName + "-item") === that) { 13331 currentItem = $(event.target); 13332 } 13333 13334 if(!currentItem) { 13335 return false; 13336 } 13337 if(this.options.handle && !overrideHandle) { 13338 $(this.options.handle, currentItem).find("*").addBack().each(function() { 13339 if(this === event.target) { 13340 validHandle = true; 13341 } 13342 }); 13343 if(!validHandle) { 13344 return false; 13345 } 13346 } 13347 13348 this.currentItem = currentItem; 13349 this._removeCurrentsFromItems(); 13350 return true; 13351 13352 }, 13353 13354 _mouseStart: function(event, overrideHandle, noActivation) { 13355 13356 var i, body, 13357 o = this.options; 13358 13359 this.currentContainer = this; 13360 13361 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture 13362 this.refreshPositions(); 13363 13364 //Create and append the visible helper 13365 this.helper = this._createHelper(event); 13366 13367 //Cache the helper size 13368 this._cacheHelperProportions(); 13369 13370 /* 13371 * - Position generation - 13372 * This block generates everything position related - it's the core of draggables. 13373 */ 13374 13375 //Cache the margins of the original element 13376 this._cacheMargins(); 13377 13378 //Get the next scrolling parent 13379 this.scrollParent = this.helper.scrollParent(); 13380 13381 //The element's absolute position on the page minus margins 13382 this.offset = this.currentItem.offset(); 13383 this.offset = { 13384 top: this.offset.top - this.margins.top, 13385 left: this.offset.left - this.margins.left 13386 }; 13387 13388 $.extend(this.offset, { 13389 click: { //Where the click happened, relative to the element 13390 left: event.pageX - this.offset.left, 13391 top: event.pageY - this.offset.top 13392 }, 13393 parent: this._getParentOffset(), 13394 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper 13395 }); 13396 13397 // Only after we got the offset, we can change the helper's position to absolute 13398 // TODO: Still need to figure out a way to make relative sorting possible 13399 this.helper.css("position", "absolute"); 13400 this.cssPosition = this.helper.css("position"); 13401 13402 //Generate the original position 13403 this.originalPosition = this._generatePosition(event); 13404 this.originalPageX = event.pageX; 13405 this.originalPageY = event.pageY; 13406 13407 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 13408 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); 13409 13410 //Cache the former DOM position 13411 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; 13412 13413 //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 13414 if(this.helper[0] !== this.currentItem[0]) { 13415 this.currentItem.hide(); 13416 } 13417 13418 //Create the placeholder 13419 this._createPlaceholder(); 13420 13421 //Set a containment if given in the options 13422 if(o.containment) { 13423 this._setContainment(); 13424 } 13425 13426 if( o.cursor && o.cursor !== "auto" ) { // cursor option 13427 body = this.document.find( "body" ); 13428 13429 // support: IE 13430 this.storedCursor = body.css( "cursor" ); 13431 body.css( "cursor", o.cursor ); 13432 13433 this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body ); 13434 } 13435 13436 if(o.opacity) { // opacity option 13437 if (this.helper.css("opacity")) { 13438 this._storedOpacity = this.helper.css("opacity"); 13439 } 13440 this.helper.css("opacity", o.opacity); 13441 } 13442 13443 if(o.zIndex) { // zIndex option 13444 if (this.helper.css("zIndex")) { 13445 this._storedZIndex = this.helper.css("zIndex"); 13446 } 13447 this.helper.css("zIndex", o.zIndex); 13448 } 13449 13450 //Prepare scrolling 13451 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { 13452 this.overflowOffset = this.scrollParent.offset(); 13453 } 13454 13455 //Call callbacks 13456 this._trigger("start", event, this._uiHash()); 13457 13458 //Recache the helper size 13459 if(!this._preserveHelperProportions) { 13460 this._cacheHelperProportions(); 13461 } 13462 13463 13464 //Post "activate" events to possible containers 13465 if( !noActivation ) { 13466 for ( i = this.containers.length - 1; i >= 0; i-- ) { 13467 this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) ); 13468 } 13469 } 13470 13471 //Prepare possible droppables 13472 if($.ui.ddmanager) { 13473 $.ui.ddmanager.current = this; 13474 } 13475 13476 if ($.ui.ddmanager && !o.dropBehaviour) { 13477 $.ui.ddmanager.prepareOffsets(this, event); 13478 } 13479 13480 this.dragging = true; 13481 13482 this.helper.addClass("ui-sortable-helper"); 13483 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position 13484 return true; 13485 13486 }, 13487 13488 _mouseDrag: function(event) { 13489 var i, item, itemElement, intersection, 13490 o = this.options, 13491 scrolled = false; 13492 13493 //Compute the helpers position 13494 this.position = this._generatePosition(event); 13495 this.positionAbs = this._convertPositionTo("absolute"); 13496 13497 if (!this.lastPositionAbs) { 13498 this.lastPositionAbs = this.positionAbs; 13499 } 13500 13501 //Do scrolling 13502 if(this.options.scroll) { 13503 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { 13504 13505 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) { 13506 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; 13507 } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) { 13508 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; 13509 } 13510 13511 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) { 13512 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; 13513 } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) { 13514 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; 13515 } 13516 13517 } else { 13518 13519 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) { 13520 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); 13521 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { 13522 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); 13523 } 13524 13525 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { 13526 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); 13527 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { 13528 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); 13529 } 13530 13531 } 13532 13533 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { 13534 $.ui.ddmanager.prepareOffsets(this, event); 13535 } 13536 } 13537 13538 //Regenerate the absolute position used for position checks 13539 this.positionAbs = this._convertPositionTo("absolute"); 13540 13541 //Set the helper position 13542 if(!this.options.axis || this.options.axis !== "y") { 13543 this.helper[0].style.left = this.position.left+"px"; 13544 } 13545 if(!this.options.axis || this.options.axis !== "x") { 13546 this.helper[0].style.top = this.position.top+"px"; 13547 } 13548 13549 //Rearrange 13550 for (i = this.items.length - 1; i >= 0; i--) { 13551 13552 //Cache variables and intersection, continue if no intersection 13553 item = this.items[i]; 13554 itemElement = item.item[0]; 13555 intersection = this._intersectsWithPointer(item); 13556 if (!intersection) { 13557 continue; 13558 } 13559 13560 // Only put the placeholder inside the current Container, skip all 13561 // items from other containers. This works because when moving 13562 // an item from one container to another the 13563 // currentContainer is switched before the placeholder is moved. 13564 // 13565 // Without this, moving items in "sub-sortables" can cause 13566 // the placeholder to jitter beetween the outer and inner container. 13567 if (item.instance !== this.currentContainer) { 13568 continue; 13569 } 13570 13571 // cannot intersect with itself 13572 // no useless actions that have been done before 13573 // no action if the item moved is the parent of the item checked 13574 if (itemElement !== this.currentItem[0] && 13575 this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement && 13576 !$.contains(this.placeholder[0], itemElement) && 13577 (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true) 13578 ) { 13579 13580 this.direction = intersection === 1 ? "down" : "up"; 13581 13582 if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) { 13583 this._rearrange(event, item); 13584 } else { 13585 break; 13586 } 13587 13588 this._trigger("change", event, this._uiHash()); 13589 break; 13590 } 13591 } 13592 13593 //Post events to containers 13594 this._contactContainers(event); 13595 13596 //Interconnect with droppables 13597 if($.ui.ddmanager) { 13598 $.ui.ddmanager.drag(this, event); 13599 } 13600 13601 //Call callbacks 13602 this._trigger("sort", event, this._uiHash()); 13603 13604 this.lastPositionAbs = this.positionAbs; 13605 return false; 13606 13607 }, 13608 13609 _mouseStop: function(event, noPropagation) { 13610 13611 if(!event) { 13612 return; 13613 } 13614 13615 //If we are using droppables, inform the manager about the drop 13616 if ($.ui.ddmanager && !this.options.dropBehaviour) { 13617 $.ui.ddmanager.drop(this, event); 13618 } 13619 13620 if(this.options.revert) { 13621 var that = this, 13622 cur = this.placeholder.offset(), 13623 axis = this.options.axis, 13624 animation = {}; 13625 13626 if ( !axis || axis === "x" ) { 13627 animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft); 13628 } 13629 if ( !axis || axis === "y" ) { 13630 animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop); 13631 } 13632 this.reverting = true; 13633 $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() { 13634 that._clear(event); 13635 }); 13636 } else { 13637 this._clear(event, noPropagation); 13638 } 13639 13640 return false; 13641 13642 }, 13643 13644 cancel: function() { 13645 13646 if(this.dragging) { 13647 13648 this._mouseUp({ target: null }); 13649 13650 if(this.options.helper === "original") { 13651 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); 13652 } else { 13653 this.currentItem.show(); 13654 } 13655 13656 //Post deactivating events to containers 13657 for (var i = this.containers.length - 1; i >= 0; i--){ 13658 this.containers[i]._trigger("deactivate", null, this._uiHash(this)); 13659 if(this.containers[i].containerCache.over) { 13660 this.containers[i]._trigger("out", null, this._uiHash(this)); 13661 this.containers[i].containerCache.over = 0; 13662 } 13663 } 13664 13665 } 13666 13667 if (this.placeholder) { 13668 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! 13669 if(this.placeholder[0].parentNode) { 13670 this.placeholder[0].parentNode.removeChild(this.placeholder[0]); 13671 } 13672 if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) { 13673 this.helper.remove(); 13674 } 13675 13676 $.extend(this, { 13677 helper: null, 13678 dragging: false, 13679 reverting: false, 13680 _noFinalSort: null 13681 }); 13682 13683 if(this.domPosition.prev) { 13684 $(this.domPosition.prev).after(this.currentItem); 13685 } else { 13686 $(this.domPosition.parent).prepend(this.currentItem); 13687 } 13688 } 13689 13690 return this; 13691 13692 }, 13693 13694 serialize: function(o) { 13695 13696 var items = this._getItemsAsjQuery(o && o.connected), 13697 str = []; 13698 o = o || {}; 13699 13700 $(items).each(function() { 13701 var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/)); 13702 if (res) { 13703 str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2])); 13704 } 13705 }); 13706 13707 if(!str.length && o.key) { 13708 str.push(o.key + "="); 13709 } 13710 13711 return str.join("&"); 13712 13713 }, 13714 13715 toArray: function(o) { 13716 13717 var items = this._getItemsAsjQuery(o && o.connected), 13718 ret = []; 13719 13720 o = o || {}; 13721 13722 items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); }); 13723 return ret; 13724 13725 }, 13726 13727 /* Be careful with the following core functions */ 13728 _intersectsWith: function(item) { 13729 13730 var x1 = this.positionAbs.left, 13731 x2 = x1 + this.helperProportions.width, 13732 y1 = this.positionAbs.top, 13733 y2 = y1 + this.helperProportions.height, 13734 l = item.left, 13735 r = l + item.width, 13736 t = item.top, 13737 b = t + item.height, 13738 dyClick = this.offset.click.top, 13739 dxClick = this.offset.click.left, 13740 isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ), 13741 isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ), 13742 isOverElement = isOverElementHeight && isOverElementWidth; 13743 13744 if ( this.options.tolerance === "pointer" || 13745 this.options.forcePointerForContainers || 13746 (this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"]) 13747 ) { 13748 return isOverElement; 13749 } else { 13750 13751 return (l < x1 + (this.helperProportions.width / 2) && // Right Half 13752 x2 - (this.helperProportions.width / 2) < r && // Left Half 13753 t < y1 + (this.helperProportions.height / 2) && // Bottom Half 13754 y2 - (this.helperProportions.height / 2) < b ); // Top Half 13755 13756 } 13757 }, 13758 13759 _intersectsWithPointer: function(item) { 13760 13761 var isOverElementHeight = (this.options.axis === "x") || isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), 13762 isOverElementWidth = (this.options.axis === "y") || isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), 13763 isOverElement = isOverElementHeight && isOverElementWidth, 13764 verticalDirection = this._getDragVerticalDirection(), 13765 horizontalDirection = this._getDragHorizontalDirection(); 13766 13767 if (!isOverElement) { 13768 return false; 13769 } 13770 13771 return this.floating ? 13772 ( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 ) 13773 : ( verticalDirection && (verticalDirection === "down" ? 2 : 1) ); 13774 13775 }, 13776 13777 _intersectsWithSides: function(item) { 13778 13779 var isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), 13780 isOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width), 13781 verticalDirection = this._getDragVerticalDirection(), 13782 horizontalDirection = this._getDragHorizontalDirection(); 13783 13784 if (this.floating && horizontalDirection) { 13785 return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf)); 13786 } else { 13787 return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf)); 13788 } 13789 13790 }, 13791 13792 _getDragVerticalDirection: function() { 13793 var delta = this.positionAbs.top - this.lastPositionAbs.top; 13794 return delta !== 0 && (delta > 0 ? "down" : "up"); 13795 }, 13796 13797 _getDragHorizontalDirection: function() { 13798 var delta = this.positionAbs.left - this.lastPositionAbs.left; 13799 return delta !== 0 && (delta > 0 ? "right" : "left"); 13800 }, 13801 13802 refresh: function(event) { 13803 this._refreshItems(event); 13804 this.refreshPositions(); 13805 return this; 13806 }, 13807 13808 _connectWith: function() { 13809 var options = this.options; 13810 return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith; 13811 }, 13812 13813 _getItemsAsjQuery: function(connected) { 13814 13815 var i, j, cur, inst, 13816 items = [], 13817 queries = [], 13818 connectWith = this._connectWith(); 13819 13820 if(connectWith && connected) { 13821 for (i = connectWith.length - 1; i >= 0; i--){ 13822 cur = $(connectWith[i]); 13823 for ( j = cur.length - 1; j >= 0; j--){ 13824 inst = $.data(cur[j], this.widgetFullName); 13825 if(inst && inst !== this && !inst.options.disabled) { 13826 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]); 13827 } 13828 } 13829 } 13830 } 13831 13832 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]); 13833 13834 function addItems() { 13835 items.push( this ); 13836 } 13837 for (i = queries.length - 1; i >= 0; i--){ 13838 queries[i][0].each( addItems ); 13839 } 13840 13841 return $(items); 13842 13843 }, 13844 13845 _removeCurrentsFromItems: function() { 13846 13847 var list = this.currentItem.find(":data(" + this.widgetName + "-item)"); 13848 13849 this.items = $.grep(this.items, function (item) { 13850 for (var j=0; j < list.length; j++) { 13851 if(list[j] === item.item[0]) { 13852 return false; 13853 } 13854 } 13855 return true; 13856 }); 13857 13858 }, 13859 13860 _refreshItems: function(event) { 13861 13862 this.items = []; 13863 this.containers = [this]; 13864 13865 var i, j, cur, inst, targetData, _queries, item, queriesLength, 13866 items = this.items, 13867 queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]], 13868 connectWith = this._connectWith(); 13869 13870 if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down 13871 for (i = connectWith.length - 1; i >= 0; i--){ 13872 cur = $(connectWith[i]); 13873 for (j = cur.length - 1; j >= 0; j--){ 13874 inst = $.data(cur[j], this.widgetFullName); 13875 if(inst && inst !== this && !inst.options.disabled) { 13876 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); 13877 this.containers.push(inst); 13878 } 13879 } 13880 } 13881 } 13882 13883 for (i = queries.length - 1; i >= 0; i--) { 13884 targetData = queries[i][1]; 13885 _queries = queries[i][0]; 13886 13887 for (j=0, queriesLength = _queries.length; j < queriesLength; j++) { 13888 item = $(_queries[j]); 13889 13890 item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager) 13891 13892 items.push({ 13893 item: item, 13894 instance: targetData, 13895 width: 0, height: 0, 13896 left: 0, top: 0 13897 }); 13898 } 13899 } 13900 13901 }, 13902 13903 refreshPositions: function(fast) { 13904 13905 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change 13906 if(this.offsetParent && this.helper) { 13907 this.offset.parent = this._getParentOffset(); 13908 } 13909 13910 var i, item, t, p; 13911 13912 for (i = this.items.length - 1; i >= 0; i--){ 13913 item = this.items[i]; 13914 13915 //We ignore calculating positions of all connected containers when we're not over them 13916 if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) { 13917 continue; 13918 } 13919 13920 t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; 13921 13922 if (!fast) { 13923 item.width = t.outerWidth(); 13924 item.height = t.outerHeight(); 13925 } 13926 13927 p = t.offset(); 13928 item.left = p.left; 13929 item.top = p.top; 13930 } 13931 13932 if(this.options.custom && this.options.custom.refreshContainers) { 13933 this.options.custom.refreshContainers.call(this); 13934 } else { 13935 for (i = this.containers.length - 1; i >= 0; i--){ 13936 p = this.containers[i].element.offset(); 13937 this.containers[i].containerCache.left = p.left; 13938 this.containers[i].containerCache.top = p.top; 13939 this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); 13940 this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); 13941 } 13942 } 13943 13944 return this; 13945 }, 13946 13947 _createPlaceholder: function(that) { 13948 that = that || this; 13949 var className, 13950 o = that.options; 13951 13952 if(!o.placeholder || o.placeholder.constructor === String) { 13953 className = o.placeholder; 13954 o.placeholder = { 13955 element: function() { 13956 13957 var nodeName = that.currentItem[0].nodeName.toLowerCase(), 13958 element = $( "<" + nodeName + ">", that.document[0] ) 13959 .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder") 13960 .removeClass("ui-sortable-helper"); 13961 13962 if ( nodeName === "tr" ) { 13963 that.currentItem.children().each(function() { 13964 $( "<td> </td>", that.document[0] ) 13965 .attr( "colspan", $( this ).attr( "colspan" ) || 1 ) 13966 .appendTo( element ); 13967 }); 13968 } else if ( nodeName === "img" ) { 13969 element.attr( "src", that.currentItem.attr( "src" ) ); 13970 } 13971 13972 if ( !className ) { 13973 element.css( "visibility", "hidden" ); 13974 } 13975 13976 return element; 13977 }, 13978 update: function(container, p) { 13979 13980 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that 13981 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified 13982 if(className && !o.forcePlaceholderSize) { 13983 return; 13984 } 13985 13986 //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
13987 if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); } 13988 if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); } 13989 } 13990 }; 13991 } 13992 13993 //Create the placeholder 13994 that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem)); 13995 13996 //Append it after the actual current item 13997 that.currentItem.after(that.placeholder); 13998 13999 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) 14000 o.placeholder.update(that, that.placeholder); 14001 14002 }, 14003 14004 _contactContainers: function(event) { 14005 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, base, cur, nearBottom, floating, 14006 innermostContainer = null, 14007 innermostIndex = null; 14008 14009 // get innermost container that intersects with item 14010 for (i = this.containers.length - 1; i >= 0; i--) { 14011 14012 // never consider a container that's located within the item itself 14013 if($.contains(this.currentItem[0], this.containers[i].element[0])) { 14014 continue; 14015 } 14016 14017 if(this._intersectsWith(this.containers[i].containerCache)) { 14018 14019 // if we've already found a container and it's more "inner" than this, then continue 14020 if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) { 14021 continue; 14022 } 14023 14024 innermostContainer = this.containers[i]; 14025 innermostIndex = i; 14026 14027 } else { 14028 // container doesn't intersect. trigger "out" event if necessary 14029 if(this.containers[i].containerCache.over) { 14030 this.containers[i]._trigger("out", event, this._uiHash(this)); 14031 this.containers[i].containerCache.over = 0; 14032 } 14033 } 14034 14035 } 14036 14037 // if no intersecting containers found, return 14038 if(!innermostContainer) { 14039 return; 14040 } 14041 14042 // move the item into the container if it's not there already 14043 if(this.containers.length === 1) { 14044 if (!this.containers[innermostIndex].containerCache.over) { 14045 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 14046 this.containers[innermostIndex].containerCache.over = 1; 14047 } 14048 } else { 14049 14050 //When entering a new container, we will find the item with the least distance and append our item near it 14051 dist = 10000; 14052 itemWithLeastDistance = null; 14053 floating = innermostContainer.floating || isFloating(this.currentItem); 14054 posProperty = floating ? "left" : "top"; 14055 sizeProperty = floating ? "width" : "height"; 14056 base = this.positionAbs[posProperty] + this.offset.click[posProperty]; 14057 for (j = this.items.length - 1; j >= 0; j--) { 14058 if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) { 14059 continue; 14060 } 14061 if(this.items[j].item[0] === this.currentItem[0]) { 14062 continue; 14063 } 14064 if (floating && !isOverAxis(this.positionAbs.top + this.offset.click.top, this.items[j].top, this.items[j].height)) { 14065 continue; 14066 } 14067 cur = this.items[j].item.offset()[posProperty]; 14068 nearBottom = false; 14069 if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){ 14070 nearBottom = true; 14071 cur += this.items[j][sizeProperty]; 14072 } 14073 14074 if(Math.abs(cur - base) < dist) { 14075 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; 14076 this.direction = nearBottom ? "up": "down"; 14077 } 14078 } 14079 14080 //Check if dropOnEmpty is enabled 14081 if(!itemWithLeastDistance && !this.options.dropOnEmpty) { 14082 return; 14083 } 14084 14085 if(this.currentContainer === this.containers[innermostIndex]) { 14086 return; 14087 } 14088 14089 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 14090 this._trigger("change", event, this._uiHash()); 14091 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 14092 this.currentContainer = this.containers[innermostIndex]; 14093 14094 //Update the placeholder 14095 this.options.placeholder.update(this.currentContainer, this.placeholder); 14096 14097 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 14098 this.containers[innermostIndex].containerCache.over = 1; 14099 } 14100 14101 14102 }, 14103 14104 _createHelper: function(event) { 14105 14106 var o = this.options, 14107 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem); 14108 14109 //Add the helper to the DOM if that didn't happen already 14110 if(!helper.parents("body").length) { 14111 $(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); 14112 } 14113 14114 if(helper[0] === this.currentItem[0]) { 14115 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
vendor: 23,930 bytes, lines 14115-14790
14115: this.currentItem.css("left") }; 14116 } 14117 14118 if(!helper[0].style.width || o.forceHelperSize) { 14119 helper.width(this.currentItem.width()); 14120 } 14121 if(!helper[0].style.height || o.forceHelperSize) { 14122 helper.height(this.currentItem.height()); 14123 } 14124 14125 return helper; 14126 14127 }, 14128 14129 _adjustOffsetFromHelper: function(obj) { 14130 if (typeof obj === "string") { 14131 obj = obj.split(" "); 14132 } 14133 if ($.isArray(obj)) { 14134 obj = {left: +obj[0], top: +obj[1] || 0}; 14135 } 14136 if ("left" in obj) { 14137 this.offset.click.left = obj.left + this.margins.left; 14138 } 14139 if ("right" in obj) { 14140 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 14141 } 14142 if ("top" in obj) { 14143 this.offset.click.top = obj.top + this.margins.top; 14144 } 14145 if ("bottom" in obj) { 14146 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 14147 } 14148 }, 14149 14150 _getParentOffset: function() { 14151 14152 14153 //Get the offsetParent and cache its position 14154 this.offsetParent = this.helper.offsetParent(); 14155 var po = this.offsetParent.offset(); 14156 14157 // This is a special case where we need to modify a offset calculated on start, since the following happened: 14158 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent 14159 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that 14160 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag 14161 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { 14162 po.left += this.scrollParent.scrollLeft(); 14163 po.top += this.scrollParent.scrollTop(); 14164 } 14165 14166 // This needs to be actually done for all browsers, since pageX/pageY includes this information 14167 // with an ugly IE fix 14168 if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) { 14169 po = { top: 0, left: 0 }; 14170 } 14171 14172 return { 14173 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), 14174 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) 14175 }; 14176 14177 }, 14178 14179 _getRelativeOffset: function() { 14180 14181 if(this.cssPosition === "relative") { 14182 var p = this.currentItem.position(); 14183 return { 14184 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), 14185 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() 14186 }; 14187 } else { 14188 return { top: 0, left: 0 }; 14189 } 14190 14191 }, 14192 14193 _cacheMargins: function() { 14194 this.margins = { 14195 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0), 14196 top: (parseInt(this.currentItem.css("marginTop"),10) || 0) 14197 }; 14198 }, 14199 14200 _cacheHelperProportions: function() { 14201 this.helperProportions = { 14202 width: this.helper.outerWidth(), 14203 height: this.helper.outerHeight() 14204 }; 14205 }, 14206 14207 _setContainment: function() { 14208 14209 var ce, co, over, 14210 o = this.options; 14211 if(o.containment === "parent") { 14212 o.containment = this.helper[0].parentNode; 14213 } 14214 if(o.containment === "document" || o.containment === "window") { 14215 this.containment = [ 14216 0 - this.offset.relative.left - this.offset.parent.left, 14217 0 - this.offset.relative.top - this.offset.parent.top, 14218 $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left, 14219 ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top 14220 ]; 14221 } 14222 14223 if(!(/^(document|window|parent)$/).test(o.containment)) { 14224 ce = $(o.containment)[0]; 14225 co = $(o.containment).offset(); 14226 over = ($(ce).css("overflow") !== "hidden"); 14227 14228 this.containment = [ 14229 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, 14230 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, 14231 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, 14232 co.top+(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 14233 ]; 14234 } 14235 14236 }, 14237 14238 _convertPositionTo: function(d, pos) { 14239 14240 if(!pos) { 14241 pos = this.position; 14242 } 14243 var mod = d === "absolute" ? 1 : -1, 14244 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, 14245 scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); 14246 14247 return { 14248 top: ( 14249 pos.top + // The absolute mouse position 14250 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent 14251 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) 14252 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) 14253 ), 14254 left: ( 14255 pos.left + // The absolute mouse position 14256 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent 14257 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) 14258 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) 14259 ) 14260 }; 14261 14262 }, 14263 14264 _generatePosition: function(event) { 14265 14266 var top, left, 14267 o = this.options, 14268 pageX = event.pageX, 14269 pageY = event.pageY, 14270 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); 14271 14272 // This is another very weird special case that only happens for relative elements: 14273 // 1. If the css position is relative 14274 // 2. and the scroll parent is the document or similar to the offset parent 14275 // we have to refresh the relative offset during the scroll so there are no jumps 14276 if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) { 14277 this.offset.relative = this._getRelativeOffset(); 14278 } 14279 14280 /* 14281 * - Position constraining - 14282 * Constrain the position to a mix of grid, containment. 14283 */ 14284 14285 if(this.originalPosition) { //If we are not dragging yet, we won't check for options 14286 14287 if(this.containment) { 14288 if(event.pageX - this.offset.click.left < this.containment[0]) { 14289 pageX = this.containment[0] + this.offset.click.left; 14290 } 14291 if(event.pageY - this.offset.click.top < this.containment[1]) { 14292 pageY = this.containment[1] + this.offset.click.top; 14293 } 14294 if(event.pageX - this.offset.click.left > this.containment[2]) { 14295 pageX = this.containment[2] + this.offset.click.left; 14296 } 14297 if(event.pageY - this.offset.click.top > this.containment[3]) { 14298 pageY = this.containment[3] + this.offset.click.top; 14299 } 14300 } 14301 14302 if(o.grid) { 14303 top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; 14304 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; 14305 14306 left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; 14307 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; 14308 } 14309 14310 } 14311 14312 return { 14313 top: ( 14314 pageY - // The absolute mouse position 14315 this.offset.click.top - // Click offset (relative to the element) 14316 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent 14317 this.offset.parent.top + // The offsetParent's offset without borders (offset + border) 14318 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) 14319 ), 14320 left: ( 14321 pageX - // The absolute mouse position 14322 this.offset.click.left - // Click offset (relative to the element) 14323 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent 14324 this.offset.parent.left + // The offsetParent's offset without borders (offset + border) 14325 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) 14326 ) 14327 }; 14328 14329 }, 14330 14331 _rearrange: function(event, i, a, hardRefresh) { 14332 14333 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)); 14334 14335 //Various things done here to improve the performance: 14336 // 1. we create a setTimeout, that calls refreshPositions 14337 // 2. on the instance, we have a counter variable, that get's higher after every append 14338 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same 14339 // 4. this lets only the last addition to the timeout stack through 14340 this.counter = this.counter ? ++this.counter : 1; 14341 var counter = this.counter; 14342 14343 this._delay(function() { 14344 if(counter === this.counter) { 14345 this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove 14346 } 14347 }); 14348 14349 }, 14350 14351 _clear: function(event, noPropagation) { 14352 14353 this.reverting = false; 14354 // We delay all events that have to be triggered to after the point where the placeholder has been removed and 14355 // everything else normalized again 14356 var i, 14357 delayedTriggers = []; 14358 14359 // We first have to update the dom position of the actual currentItem 14360 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) 14361 if(!this._noFinalSort && this.currentItem.parent().length) { 14362 this.placeholder.before(this.currentItem); 14363 } 14364 this._noFinalSort = null; 14365 14366 if(this.helper[0] === this.currentItem[0]) { 14367 for(i in this._storedCSS) { 14368 if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") { 14369 this._storedCSS[i] = ""; 14370 } 14371 } 14372 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); 14373 } else { 14374 this.currentItem.show(); 14375 } 14376 14377 if(this.fromOutside && !noPropagation) { 14378 delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); }); 14379 } 14380 if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) { 14381 delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed 14382 } 14383 14384 // Check if the items Container has Changed and trigger appropriate 14385 // events. 14386 if (this !== this.currentContainer) { 14387 if(!noPropagation) { 14388 delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); }); 14389 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); 14390 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); 14391 } 14392 } 14393 14394 14395 //Post events to containers 14396 function delayEvent( type, instance, container ) { 14397 return function( event ) { 14398 container._trigger( type, event, instance._uiHash( instance ) ); 14399 }; 14400 } 14401 for (i = this.containers.length - 1; i >= 0; i--){ 14402 if (!noPropagation) { 14403 delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) ); 14404 } 14405 if(this.containers[i].containerCache.over) { 14406 delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) ); 14407 this.containers[i].containerCache.over = 0; 14408 } 14409 } 14410 14411 //Do what was originally in plugins 14412 if ( this.storedCursor ) { 14413 this.document.find( "body" ).css( "cursor", this.storedCursor ); 14414 this.storedStylesheet.remove(); 14415 } 14416 if(this._storedOpacity) { 14417 this.helper.css("opacity", this._storedOpacity); 14418 } 14419 if(this._storedZIndex) { 14420 this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex); 14421 } 14422 14423 this.dragging = false; 14424 if(this.cancelHelperRemoval) { 14425 if(!noPropagation) { 14426 this._trigger("beforeStop", event, this._uiHash()); 14427 for (i=0; i < delayedTriggers.length; i++) { 14428 delayedTriggers[i].call(this, event); 14429 } //Trigger all delayed events 14430 this._trigger("stop", event, this._uiHash()); 14431 } 14432 14433 this.fromOutside = false; 14434 return false; 14435 } 14436 14437 if(!noPropagation) { 14438 this._trigger("beforeStop", event, this._uiHash()); 14439 } 14440 14441 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! 14442 this.placeholder[0].parentNode.removeChild(this.placeholder[0]); 14443 14444 if(this.helper[0] !== this.currentItem[0]) { 14445 this.helper.remove(); 14446 } 14447 this.helper = null; 14448 14449 if(!noPropagation) { 14450 for (i=0; i < delayedTriggers.length; i++) { 14451 delayedTriggers[i].call(this, event); 14452 } //Trigger all delayed events 14453 this._trigger("stop", event, this._uiHash()); 14454 } 14455 14456 this.fromOutside = false; 14457 return true; 14458 14459 }, 14460 14461 _trigger: function() { 14462 if ($.Widget.prototype._trigger.apply(this, arguments) === false) { 14463 this.cancel(); 14464 } 14465 }, 14466 14467 _uiHash: function(_inst) { 14468 var inst = _inst || this; 14469 return { 14470 helper: inst.helper, 14471 placeholder: inst.placeholder || $([]), 14472 position: inst.position, 14473 originalPosition: inst.originalPosition, 14474 offset: inst.positionAbs, 14475 item: inst.currentItem, 14476 sender: _inst ? _inst.element : null 14477 }; 14478 } 14479 14480}); 14481 14482})( _4ORMAT.$ ); 14483(function( $ ) { 14484 14485function modifier( fn ) { 14486 return function() { 14487 var previous = this.element.val(); 14488 fn.apply( this, arguments ); 14489 this._refresh(); 14490 if ( previous !== this.element.val() ) { 14491 this._trigger( "change" ); 14492 } 14493 }; 14494} 14495 14496$.widget( "ui.spinner", { 14497 version: "1.10.4", 14498 defaultElement: "<input>", 14499 widgetEventPrefix: "spin", 14500 options: { 14501 culture: null, 14502 icons: { 14503 down: "ui-icon-triangle-1-s", 14504 up: "ui-icon-triangle-1-n" 14505 }, 14506 incremental: true, 14507 max: null, 14508 min: null, 14509 numberFormat: null, 14510 page: 10, 14511 step: 1, 14512 14513 change: null, 14514 spin: null, 14515 start: null, 14516 stop: null 14517 }, 14518 14519 _create: function() { 14520 // handle string values that need to be parsed 14521 this._setOption( "max", this.options.max ); 14522 this._setOption( "min", this.options.min ); 14523 this._setOption( "step", this.options.step ); 14524 14525 // Only format if there is a value, prevents the field from being marked 14526 // as invalid in Firefox, see #9573. 14527 if ( this.value() !== "" ) { 14528 // Format the value, but don't constrain. 14529 this._value( this.element.val(), true ); 14530 } 14531 14532 this._draw(); 14533 this._on( this._events ); 14534 this._refresh(); 14535 14536 // turning off autocomplete prevents the browser from remembering the 14537 // value when navigating through history, so we re-enable autocomplete 14538 // if the page is unloaded before the widget is destroyed. #7790 14539 this._on( this.window, { 14540 beforeunload: function() { 14541 this.element.removeAttr( "autocomplete" ); 14542 } 14543 }); 14544 }, 14545 14546 _getCreateOptions: function() { 14547 var options = {}, 14548 element = this.element; 14549 14550 $.each( [ "min", "max", "step" ], function( i, option ) { 14551 var value = element.attr( option ); 14552 if ( value !== undefined && value.length ) { 14553 options[ option ] = value; 14554 } 14555 }); 14556 14557 return options; 14558 }, 14559 14560 _events: { 14561 keydown: function( event ) { 14562 if ( this._start( event ) && this._keydown( event ) ) { 14563 event.preventDefault(); 14564 } 14565 }, 14566 keyup: "_stop", 14567 focus: function() { 14568 this.previous = this.element.val(); 14569 }, 14570 blur: function( event ) { 14571 if ( this.cancelBlur ) { 14572 delete this.cancelBlur; 14573 return; 14574 } 14575 14576 this._stop(); 14577 this._refresh(); 14578 if ( this.previous !== this.element.val() ) { 14579 this._trigger( "change", event ); 14580 } 14581 }, 14582 mousewheel: function( event, delta ) { 14583 if ( !delta ) { 14584 return; 14585 } 14586 if ( !this.spinning && !this._start( event ) ) { 14587 return false; 14588 } 14589 14590 this._spin( (delta > 0 ? 1 : -1) * this.options.step, event ); 14591 clearTimeout( this.mousewheelTimer ); 14592 this.mousewheelTimer = this._delay(function() { 14593 if ( this.spinning ) { 14594 this._stop( event ); 14595 } 14596 }, 100 ); 14597 event.preventDefault(); 14598 }, 14599 "mousedown .ui-spinner-button": function( event ) { 14600 var previous; 14601 14602 // We never want the buttons to have focus; whenever the user is 14603 // interacting with the spinner, the focus should be on the input. 14604 // If the input is focused then this.previous is properly set from 14605 // when the input first received focus. If the input is not focused 14606 // then we need to set this.previous based on the value before spinning. 14607 previous = this.element[0] === this.document[0].activeElement ? 14608 this.previous : this.element.val(); 14609 function checkFocus() { 14610 var isActive = this.element[0] === this.document[0].activeElement; 14611 if ( !isActive ) { 14612 this.element.focus(); 14613 this.previous = previous; 14614 // support: IE 14615 // IE sets focus asynchronously, so we need to check if focus 14616 // moved off of the input because the user clicked on the button. 14617 this._delay(function() { 14618 this.previous = previous; 14619 }); 14620 } 14621 } 14622 14623 // ensure focus is on (or stays on) the text field 14624 event.preventDefault(); 14625 checkFocus.call( this ); 14626 14627 // support: IE 14628 // IE doesn't prevent moving focus even with event.preventDefault() 14629 // so we set a flag to know when we should ignore the blur event 14630 // and check (again) if focus moved off of the input. 14631 this.cancelBlur = true; 14632 this._delay(function() { 14633 delete this.cancelBlur; 14634 checkFocus.call( this ); 14635 }); 14636 14637 if ( this._start( event ) === false ) { 14638 return; 14639 } 14640 14641 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); 14642 }, 14643 "mouseup .ui-spinner-button": "_stop", 14644 "mouseenter .ui-spinner-button": function( event ) { 14645 // button will add ui-state-active if mouse was down while mouseleave and kept down 14646 if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) { 14647 return; 14648 } 14649 14650 if ( this._start( event ) === false ) { 14651 return false; 14652 } 14653 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); 14654 }, 14655 // TODO: do we really want to consider this a stop? 14656 // shouldn't we just stop the repeater and wait until mouseup before 14657 // we trigger the stop event? 14658 "mouseleave .ui-spinner-button": "_stop" 14659 }, 14660 14661 _draw: function() { 14662 var uiSpinner = this.uiSpinner = this.element 14663 .addClass( "ui-spinner-input" ) 14664 .attr( "autocomplete", "off" ) 14665 .wrap( this._uiSpinnerHtml() ) 14666 .parent() 14667 // add buttons 14668 .append( this._buttonHtml() ); 14669 14670 this.element.attr( "role", "spinbutton" ); 14671 14672 // button bindings 14673 this.buttons = uiSpinner.find( ".ui-spinner-button" ) 14674 .attr( "tabIndex", -1 ) 14675 .button() 14676 .removeClass( "ui-corner-all" ); 14677 14678 // IE 6 doesn't understand height: 50% for the buttons 14679 // unless the wrapper has an explicit height 14680 if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) && 14681 uiSpinner.height() > 0 ) { 14682 uiSpinner.height( uiSpinner.height() ); 14683 } 14684 14685 // disable spinner if element was already disabled 14686 if ( this.options.disabled ) { 14687 this.disable(); 14688 } 14689 }, 14690 14691 _keydown: function( event ) { 14692 var options = this.options, 14693 keyCode = $.ui.keyCode; 14694 14695 switch ( event.keyCode ) { 14696 case keyCode.UP: 14697 this._repeat( null, 1, event ); 14698 return true; 14699 case keyCode.DOWN: 14700 this._repeat( null, -1, event ); 14701 return true; 14702 case keyCode.PAGE_UP: 14703 this._repeat( null, options.page, event ); 14704 return true; 14705 case keyCode.PAGE_DOWN: 14706 this._repeat( null, -options.page, event ); 14707 return true; 14708 } 14709 14710 return false; 14711 }, 14712 14713 _uiSpinnerHtml: function() { 14714 return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"; 14715 }, 14716 14717 _buttonHtml: function() { 14718 return "" + 14719 "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" + 14720 "<span class='ui-icon " + this.options.icons.up + "'>▲</span>" + 14721 "</a>" + 14722 "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" + 14723 "<span class='ui-icon " + this.options.icons.down + "'>▼</span>" + 14724 "</a>"; 14725 }, 14726 14727 _start: function( event ) { 14728 if ( !this.spinning && this._trigger( "start", event ) === false ) { 14729 return false; 14730 } 14731 14732 if ( !this.counter ) { 14733 this.counter = 1; 14734 } 14735 this.spinning = true; 14736 return true; 14737 }, 14738 14739 _repeat: function( i, steps, event ) { 14740 i = i || 500; 14741 14742 clearTimeout( this.timer ); 14743 this.timer = this._delay(function() { 14744 this._repeat( 40, steps, event ); 14745 }, i ); 14746 14747 this._spin( steps * this.options.step, event ); 14748 }, 14749 14750 _spin: function( step, event ) { 14751 var value = this.value() || 0; 14752 14753 if ( !this.counter ) { 14754 this.counter = 1; 14755 } 14756 14757 value = this._adjustValue( value + step * this._increment( this.counter ) ); 14758 14759 if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) { 14760 this._value( value ); 14761 this.counter++; 14762 } 14763 }, 14764 14765 _increment: function( i ) { 14766 var incremental = this.options.incremental; 14767 14768 if ( incremental ) { 14769 return $.isFunction( incremental ) ? 14770 incremental( i ) : 14771 Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 ); 14772 } 14773 14774 return 1; 14775 }, 14776 14777 _precision: function() { 14778 var precision = this._precisionOf( this.options.step ); 14779 if ( this.options.min !== null ) { 14780 precision = Math.max( precision, this._precisionOf( this.options.min ) ); 14781 } 14782 return precision; 14783 }, 14784 14785 _precisionOf: function( num ) { 14786 var str = num.toString(), 14787 decimal = str.indexOf( "." ); 14788 return decimal === -1 ? 0 : str.length - decimal - 1; 14789 }, 14790
14791 _adjustValue: function( value ) { 14792 var base, aboveMin, 14793 options = this.options; 14794 14795 // make sure we're at a valid step 14796 // - find out where we are relative to the base (min or 0) 14797 base = options.min !== null ? options.min : 0; 14798 aboveMin = value - base; 14799 // - round to the nearest step 14800 aboveMin = Math.round(aboveMin / options.step) * options.step; 14801 // - rounding is based on 0, so adjust back to our base 14802 value = base + aboveMin; 14803 14804 // fix precision from bad JS floating point math 14805 value = parseFloat( value.toFixed( this._precision() ) ); 14806 14807 // clamp the value 14808 if ( options.max !== null && value > options.max) { 14809 return options.max; 14810 } 14811 if ( options.min !== null && value < options.min ) { 14812 return options.min; 14813 } 14814 14815 return value; 14816 }, 14817 14818 _stop: function( event ) { 14819 if ( !this.spinning ) { 14820 return; 14821 } 14822 14823 clearTimeout( this.timer ); 14824 clearTimeout( this.mousewheelTimer ); 14825 this.counter = 0; 14826 this.spinning = false; 14827 this._trigger( "stop", event ); 14828 }, 14829 14830 _setOption: function( key, value ) { 14831 if ( key === "culture" || key === "numberFormat" ) { 14832 var prevValue = this._parse( this.element.val() ); 14833 this.options[ key ] = value; 14834 this.element.val( this._format( prevValue ) ); 14835 return; 14836 } 14837 14838 if ( key === "max" || key === "min" || key === "step" ) { 14839 if ( typeof value === "string" ) { 14840 value = this._parse( value ); 14841 } 14842 } 14843 if ( key === "icons" ) { 14844 this.buttons.first().find( ".ui-icon" ) 14845 .removeClass( this.options.icons.up ) 14846 .addClass( value.up ); 14847 this.buttons.last().find( ".ui-icon" ) 14848 .removeClass( this.options.icons.down ) 14849 .addClass( value.down ); 14850 } 14851 14852 this._super( key, value ); 14853 14854 if ( key === "disabled" ) { 14855 if ( value ) { 14856 this.element.prop( "disabled", true ); 14857 this.buttons.button( "disable" ); 14858 } else { 14859 this.element.prop( "disabled", false ); 14860 this.buttons.button( "enable" ); 14861 } 14862 } 14863 }, 14864 14865 _setOptions: modifier(function( options ) { 14866 this._super( options ); 14867 this._value( this.element.val() ); 14868 }), 14869 14870 _parse: function( val ) { 14871 if ( typeof val === "string" && val !== "" ) { 14872 val = window.Globalize && this.options.numberFormat ? 14873 Globalize.parseFloat( val, 10, this.options.culture ) : +val; 14874 } 14875 return val === "" || isNaN( val ) ? null : val; 14876 }, 14877 14878 _format: function( value ) { 14879 if ( value === "" ) { 14880 return ""; 14881 } 14882 return window.Globalize && this.options.numberFormat ? 14883 Globalize.format( value, this.options.numberFormat, this.options.culture ) : 14884 value; 14885 }, 14886 14887 _refresh: function() { 14888 this.element.attr({ 14889 "aria-valuemin": this.options.min, 14890 "aria-valuemax": this.options.max, 14891 // TODO: what should we do with values that can't be parsed? 14892 "aria-valuenow": this._parse( this.element.val() ) 14893 }); 14894 }, 14895 14896 // update the value without triggering change 14897 _value: function( value, allowAny ) { 14898 var parsed; 14899 if ( value !== "" ) { 14900 parsed = this._parse( value ); 14901 if ( parsed !== null ) { 14902 if ( !allowAny ) { 14903 parsed = this._adjustValue( parsed ); 14904 } 14905 value = this._format( parsed ); 14906 } 14907 } 14908 this.element.val( value ); 14909 this._refresh(); 14910 }, 14911 14912 _destroy: function() { 14913 this.element 14914 .removeClass( "ui-spinner-input" ) 14915 .prop( "disabled", false ) 14916 .removeAttr( "autocomplete" ) 14917 .removeAttr( "role" ) 14918 .removeAttr( "aria-valuemin" ) 14919 .removeAttr( "aria-valuemax" ) 14920 .removeAttr( "aria-valuenow" ); 14921 this.uiSpinner.replaceWith( this.element ); 14922 }, 14923 14924 stepUp: modifier(function( steps ) { 14925 this._stepUp( steps ); 14926 }), 14927 _stepUp: function( steps ) { 14928 if ( this._start() ) { 14929 this._spin( (steps || 1) * this.options.step ); 14930 this._stop(); 14931 } 14932 }, 14933 14934 stepDown: modifier(function( steps ) { 14935 this._stepDown( steps ); 14936 }), 14937 _stepDown: function( steps ) { 14938 if ( this._start() ) { 14939 this._spin( (steps || 1) * -this.options.step ); 14940 this._stop(); 14941 } 14942 }, 14943 14944 pageUp: modifier(function( pages ) { 14945 this._stepUp( (pages || 1) * this.options.page ); 14946 }), 14947 14948 pageDown: modifier(function( pages ) { 14949 this._stepDown( (pages || 1) * this.options.page ); 14950 }), 14951 14952 value: function( newVal ) { 14953 if ( !arguments.length ) { 14954 return this._parse( this.element.val() ); 14955 } 14956 modifier( this._value ).call( this, newVal ); 14957 }, 14958 14959 widget: function() { 14960 return this.uiSpinner; 14961 } 14962}); 14963 14964}( _4ORMAT.$ ) ); 14965(function( $, undefined ) { 14966 14967var tabId = 0, 14968 rhash = /#.*$/; 14969 14970function getNextTabId() { 14971 return ++tabId; 14972} 14973 14974function isLocal( anchor ) { 14975 // support: IE7 14976 // IE7 doesn't normalize the href property when set via script (#9317) 14977 anchor = anchor.cloneNode( false ); 14978 14979 return anchor.hash.length > 1 && 14980 decodeURIComponent( anchor.href.replace( rhash, "" ) ) === 14981 decodeURIComponent( location.href.replace( rhash, "" ) ); 14982} 14983 14984$.widget( "ui.tabs", { 14985 version: "1.10.4", 14986 delay: 300, 14987 options: { 14988 active: null, 14989 collapsible: false, 14990 event: "click", 14991 heightStyle: "content", 14992 hide: null, 14993 show: null, 14994 14995 // callbacks 14996 activate: null, 14997 beforeActivate: null, 14998 beforeLoad: null, 14999 load: null 15000 }, 15001 15002 _create: function() { 15003 var that = this, 15004 options = this.options; 15005 15006 this.running = false;
vendor: 29,620 bytes, lines 15007-16024
15007 15008 this.element 15009 .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ) 15010 .toggleClass( "ui-tabs-collapsible", options.collapsible ) 15011 // Prevent users from focusing disabled tabs via click 15012 .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) { 15013 if ( $( this ).is( ".ui-state-disabled" ) ) { 15014 event.preventDefault(); 15015 } 15016 }) 15017 // support: IE <9 15018 // Preventing the default action in mousedown doesn't prevent IE 15019 // from focusing the element, so if the anchor gets focused, blur. 15020 // We don't have to worry about focusing the previously focused 15021 // element since clicking on a non-focusable element should focus 15022 // the body anyway. 15023 .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() { 15024 if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) { 15025 this.blur(); 15026 } 15027 }); 15028 15029 this._processTabs(); 15030 options.active = this._initialActive(); 15031 15032 // Take disabling tabs via class attribute from HTML 15033 // into account and update option properly. 15034 if ( $.isArray( options.disabled ) ) { 15035 options.disabled = $.unique( options.disabled.concat( 15036 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) { 15037 return that.tabs.index( li ); 15038 }) 15039 ) ).sort(); 15040 } 15041 15042 // check for length avoids error when initializing empty list 15043 if ( this.options.active !== false && this.anchors.length ) { 15044 this.active = this._findActive( options.active ); 15045 } else { 15046 this.active = $(); 15047 } 15048 15049 this._refresh(); 15050 15051 if ( this.active.length ) { 15052 this.load( options.active ); 15053 } 15054 }, 15055 15056 _initialActive: function() { 15057 var active = this.options.active, 15058 collapsible = this.options.collapsible, 15059 locationHash = location.hash.substring( 1 ); 15060 15061 if ( active === null ) { 15062 // check the fragment identifier in the URL 15063 if ( locationHash ) { 15064 this.tabs.each(function( i, tab ) { 15065 if ( $( tab ).attr( "aria-controls" ) === locationHash ) { 15066 active = i; 15067 return false; 15068 } 15069 }); 15070 } 15071 15072 // check for a tab marked active via a class 15073 if ( active === null ) { 15074 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) ); 15075 } 15076 15077 // no active tab, set to false 15078 if ( active === null || active === -1 ) { 15079 active = this.tabs.length ? 0 : false; 15080 } 15081 } 15082 15083 // handle numbers: negative, out of range 15084 if ( active !== false ) { 15085 active = this.tabs.index( this.tabs.eq( active ) ); 15086 if ( active === -1 ) { 15087 active = collapsible ? false : 0; 15088 } 15089 } 15090 15091 // don't allow collapsible: false and active: false 15092 if ( !collapsible && active === false && this.anchors.length ) { 15093 active = 0; 15094 } 15095 15096 return active; 15097 }, 15098 15099 _getCreateEventData: function() { 15100 return { 15101 tab: this.active, 15102 panel: !this.active.length ? $() : this._getPanelForTab( this.active ) 15103 }; 15104 }, 15105 15106 _tabKeydown: function( event ) { 15107 var focusedTab = $( this.document[0].activeElement ).closest( "li" ), 15108 selectedIndex = this.tabs.index( focusedTab ), 15109 goingForward = true; 15110 15111 if ( this._handlePageNav( event ) ) { 15112 return; 15113 } 15114 15115 switch ( event.keyCode ) { 15116 case $.ui.keyCode.RIGHT: 15117 case $.ui.keyCode.DOWN: 15118 selectedIndex++; 15119 break; 15120 case $.ui.keyCode.UP: 15121 case $.ui.keyCode.LEFT: 15122 goingForward = false; 15123 selectedIndex--; 15124 break; 15125 case $.ui.keyCode.END: 15126 selectedIndex = this.anchors.length - 1; 15127 break; 15128 case $.ui.keyCode.HOME: 15129 selectedIndex = 0; 15130 break; 15131 case $.ui.keyCode.SPACE: 15132 // Activate only, no collapsing 15133 event.preventDefault(); 15134 clearTimeout( this.activating ); 15135 this._activate( selectedIndex ); 15136 return; 15137 case $.ui.keyCode.ENTER: 15138 // Toggle (cancel delayed activation, allow collapsing) 15139 event.preventDefault(); 15140 clearTimeout( this.activating ); 15141 // Determine if we should collapse or activate 15142 this._activate( selectedIndex === this.options.active ? false : selectedIndex ); 15143 return; 15144 default: 15145 return; 15146 } 15147 15148 // Focus the appropriate tab, based on which key was pressed 15149 event.preventDefault(); 15150 clearTimeout( this.activating ); 15151 selectedIndex = this._focusNextTab( selectedIndex, goingForward ); 15152 15153 // Navigating with control key will prevent automatic activation 15154 if ( !event.ctrlKey ) { 15155 // Update aria-selected immediately so that AT think the tab is already selected. 15156 // Otherwise AT may confuse the user by stating that they need to activate the tab, 15157 // but the tab will already be activated by the time the announcement finishes. 15158 focusedTab.attr( "aria-selected", "false" ); 15159 this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" ); 15160 15161 this.activating = this._delay(function() { 15162 this.option( "active", selectedIndex ); 15163 }, this.delay ); 15164 } 15165 }, 15166 15167 _panelKeydown: function( event ) { 15168 if ( this._handlePageNav( event ) ) { 15169 return; 15170 } 15171 15172 // Ctrl+up moves focus to the current tab 15173 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) { 15174 event.preventDefault(); 15175 this.active.focus(); 15176 } 15177 }, 15178 15179 // Alt+page up/down moves focus to the previous/next tab (and activates) 15180 _handlePageNav: function( event ) { 15181 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) { 15182 this._activate( this._focusNextTab( this.options.active - 1, false ) ); 15183 return true; 15184 } 15185 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) { 15186 this._activate( this._focusNextTab( this.options.active + 1, true ) ); 15187 return true; 15188 } 15189 }, 15190 15191 _findNextTab: function( index, goingForward ) { 15192 var lastTabIndex = this.tabs.length - 1; 15193 15194 function constrain() { 15195 if ( index > lastTabIndex ) { 15196 index = 0; 15197 } 15198 if ( index < 0 ) { 15199 index = lastTabIndex; 15200 } 15201 return index; 15202 } 15203 15204 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) { 15205 index = goingForward ? index + 1 : index - 1; 15206 } 15207 15208 return index; 15209 }, 15210 15211 _focusNextTab: function( index, goingForward ) { 15212 index = this._findNextTab( index, goingForward ); 15213 this.tabs.eq( index ).focus(); 15214 return index; 15215 }, 15216 15217 _setOption: function( key, value ) { 15218 if ( key === "active" ) { 15219 // _activate() will handle invalid values and update this.options 15220 this._activate( value ); 15221 return; 15222 } 15223 15224 if ( key === "disabled" ) { 15225 // don't use the widget factory's disabled handling 15226 this._setupDisabled( value ); 15227 return; 15228 } 15229 15230 this._super( key, value); 15231 15232 if ( key === "collapsible" ) { 15233 this.element.toggleClass( "ui-tabs-collapsible", value ); 15234 // Setting collapsible: false while collapsed; open first panel 15235 if ( !value && this.options.active === false ) { 15236 this._activate( 0 ); 15237 } 15238 } 15239 15240 if ( key === "event" ) { 15241 this._setupEvents( value ); 15242 } 15243 15244 if ( key === "heightStyle" ) { 15245 this._setupHeightStyle( value ); 15246 } 15247 }, 15248 15249 _tabId: function( tab ) { 15250 return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId(); 15251 }, 15252 15253 _sanitizeSelector: function( hash ) { 15254 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : ""; 15255 }, 15256 15257 refresh: function() { 15258 var options = this.options, 15259 lis = this.tablist.children( ":has(a[href])" ); 15260 15261 // get disabled tabs from class attribute from HTML 15262 // this will get converted to a boolean if needed in _refresh() 15263 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) { 15264 return lis.index( tab ); 15265 }); 15266 15267 this._processTabs(); 15268 15269 // was collapsed or no tabs 15270 if ( options.active === false || !this.anchors.length ) { 15271 options.active = false; 15272 this.active = $(); 15273 // was active, but active tab is gone 15274 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) { 15275 // all remaining tabs are disabled 15276 if ( this.tabs.length === options.disabled.length ) { 15277 options.active = false; 15278 this.active = $(); 15279 // activate previous tab 15280 } else { 15281 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) ); 15282 } 15283 // was active, active tab still exists 15284 } else { 15285 // make sure active index is correct 15286 options.active = this.tabs.index( this.active ); 15287 } 15288 15289 this._refresh(); 15290 }, 15291 15292 _refresh: function() { 15293 this._setupDisabled( this.options.disabled ); 15294 this._setupEvents( this.options.event ); 15295 this._setupHeightStyle( this.options.heightStyle ); 15296 15297 this.tabs.not( this.active ).attr({ 15298 "aria-selected": "false", 15299 tabIndex: -1 15300 }); 15301 this.panels.not( this._getPanelForTab( this.active ) ) 15302 .hide() 15303 .attr({ 15304 "aria-expanded": "false", 15305 "aria-hidden": "true" 15306 }); 15307 15308 // Make sure one tab is in the tab order 15309 if ( !this.active.length ) { 15310 this.tabs.eq( 0 ).attr( "tabIndex", 0 ); 15311 } else { 15312 this.active 15313 .addClass( "ui-tabs-active ui-state-active" ) 15314 .attr({ 15315 "aria-selected": "true", 15316 tabIndex: 0 15317 }); 15318 this._getPanelForTab( this.active ) 15319 .show() 15320 .attr({ 15321 "aria-expanded": "true", 15322 "aria-hidden": "false" 15323 }); 15324 } 15325 }, 15326 15327 _processTabs: function() { 15328 var that = this; 15329 15330 this.tablist = this._getList() 15331 .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) 15332 .attr( "role", "tablist" ); 15333 15334 this.tabs = this.tablist.find( "> li:has(a[href])" ) 15335 .addClass( "ui-state-default ui-corner-top" ) 15336 .attr({ 15337 role: "tab", 15338 tabIndex: -1 15339 }); 15340 15341 this.anchors = this.tabs.map(function() { 15342 return $( "a", this )[ 0 ]; 15343 }) 15344 .addClass( "ui-tabs-anchor" ) 15345 .attr({ 15346 role: "presentation", 15347 tabIndex: -1 15348 }); 15349 15350 this.panels = $(); 15351 15352 this.anchors.each(function( i, anchor ) { 15353 var selector, panel, panelId, 15354 anchorId = $( anchor ).uniqueId().attr( "id" ), 15355 tab = $( anchor ).closest( "li" ), 15356 originalAriaControls = tab.attr( "aria-controls" ); 15357 15358 // inline tab 15359 if ( isLocal( anchor ) ) { 15360 selector = anchor.hash; 15361 panel = that.element.find( that._sanitizeSelector( selector ) ); 15362 // remote tab 15363 } else { 15364 panelId = that._tabId( tab ); 15365 selector = "#" + panelId; 15366 panel = that.element.find( selector ); 15367 if ( !panel.length ) { 15368 panel = that._createPanel( panelId ); 15369 panel.insertAfter( that.panels[ i - 1 ] || that.tablist ); 15370 } 15371 panel.attr( "aria-live", "polite" ); 15372 } 15373 15374 if ( panel.length) { 15375 that.panels = that.panels.add( panel ); 15376 } 15377 if ( originalAriaControls ) { 15378 tab.data( "ui-tabs-aria-controls", originalAriaControls ); 15379 } 15380 tab.attr({ 15381 "aria-controls": selector.substring( 1 ), 15382 "aria-labelledby": anchorId 15383 }); 15384 panel.attr( "aria-labelledby", anchorId ); 15385 }); 15386 15387 this.panels 15388 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) 15389 .attr( "role", "tabpanel" ); 15390 }, 15391 15392 // allow overriding how to find the list for rare usage scenarios (#7715) 15393 _getList: function() { 15394 return this.tablist || this.element.find( "ol,ul" ).eq( 0 ); 15395 }, 15396 15397 _createPanel: function( id ) { 15398 return $( "<div>" ) 15399 .attr( "id", id ) 15400 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) 15401 .data( "ui-tabs-destroy", true ); 15402 }, 15403 15404 _setupDisabled: function( disabled ) { 15405 if ( $.isArray( disabled ) ) { 15406 if ( !disabled.length ) { 15407 disabled = false; 15408 } else if ( disabled.length === this.anchors.length ) { 15409 disabled = true; 15410 } 15411 } 15412 15413 // disable tabs 15414 for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) { 15415 if ( disabled === true || $.inArray( i, disabled ) !== -1 ) { 15416 $( li ) 15417 .addClass( "ui-state-disabled" ) 15418 .attr( "aria-disabled", "true" ); 15419 } else { 15420 $( li ) 15421 .removeClass( "ui-state-disabled" ) 15422 .removeAttr( "aria-disabled" ); 15423 } 15424 } 15425 15426 this.options.disabled = disabled; 15427 }, 15428 15429 _setupEvents: function( event ) { 15430 var events = { 15431 click: function( event ) { 15432 event.preventDefault(); 15433 } 15434 }; 15435 if ( event ) { 15436 $.each( event.split(" "), function( index, eventName ) { 15437 events[ eventName ] = "_eventHandler"; 15438 }); 15439 } 15440 15441 this._off( this.anchors.add( this.tabs ).add( this.panels ) ); 15442 this._on( this.anchors, events ); 15443 this._on( this.tabs, { keydown: "_tabKeydown" } ); 15444 this._on( this.panels, { keydown: "_panelKeydown" } ); 15445 15446 this._focusable( this.tabs ); 15447 this._hoverable( this.tabs ); 15448 }, 15449 15450 _setupHeightStyle: function( heightStyle ) { 15451 var maxHeight, 15452 parent = this.element.parent(); 15453 15454 if ( heightStyle === "fill" ) { 15455 maxHeight = parent.height(); 15456 maxHeight -= this.element.outerHeight() - this.element.height(); 15457 15458 this.element.siblings( ":visible" ).each(function() { 15459 var elem = $( this ), 15460 position = elem.css( "position" ); 15461 15462 if ( position === "absolute" || position === "fixed" ) { 15463 return; 15464 } 15465 maxHeight -= elem.outerHeight( true ); 15466 }); 15467 15468 this.element.children().not( this.panels ).each(function() { 15469 maxHeight -= $( this ).outerHeight( true ); 15470 }); 15471 15472 this.panels.each(function() { 15473 $( this ).height( Math.max( 0, maxHeight - 15474 $( this ).innerHeight() + $( this ).height() ) ); 15475 }) 15476 .css( "overflow", "auto" ); 15477 } else if ( heightStyle === "auto" ) { 15478 maxHeight = 0; 15479 this.panels.each(function() { 15480 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); 15481 }).height( maxHeight ); 15482 } 15483 }, 15484 15485 _eventHandler: function( event ) { 15486 var options = this.options, 15487 active = this.active, 15488 anchor = $( event.currentTarget ), 15489 tab = anchor.closest( "li" ), 15490 clickedIsActive = tab[ 0 ] === active[ 0 ], 15491 collapsing = clickedIsActive && options.collapsible, 15492 toShow = collapsing ? $() : this._getPanelForTab( tab ), 15493 toHide = !active.length ? $() : this._getPanelForTab( active ), 15494 eventData = { 15495 oldTab: active, 15496 oldPanel: toHide, 15497 newTab: collapsing ? $() : tab, 15498 newPanel: toShow 15499 }; 15500 15501 event.preventDefault(); 15502 15503 if ( tab.hasClass( "ui-state-disabled" ) || 15504 // tab is already loading 15505 tab.hasClass( "ui-tabs-loading" ) || 15506 // can't switch durning an animation 15507 this.running || 15508 // click on active header, but not collapsible 15509 ( clickedIsActive && !options.collapsible ) || 15510 // allow canceling activation 15511 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 15512 return; 15513 } 15514 15515 options.active = collapsing ? false : this.tabs.index( tab ); 15516 15517 this.active = clickedIsActive ? $() : tab; 15518 if ( this.xhr ) { 15519 this.xhr.abort(); 15520 } 15521 15522 if ( !toHide.length && !toShow.length ) { 15523 $.error( "jQuery UI Tabs: Mismatching fragment identifier." ); 15524 } 15525 15526 if ( toShow.length ) { 15527 this.load( this.tabs.index( tab ), event ); 15528 } 15529 this._toggle( event, eventData ); 15530 }, 15531 15532 // handles show/hide for selecting tabs 15533 _toggle: function( event, eventData ) { 15534 var that = this, 15535 toShow = eventData.newPanel, 15536 toHide = eventData.oldPanel; 15537 15538 this.running = true; 15539 15540 function complete() { 15541 that.running = false; 15542 that._trigger( "activate", event, eventData ); 15543 } 15544 15545 function show() { 15546 eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" ); 15547 15548 if ( toShow.length && that.options.show ) { 15549 that._show( toShow, that.options.show, complete ); 15550 } else { 15551 toShow.show(); 15552 complete(); 15553 } 15554 } 15555 15556 // start out by hiding, then showing, then completing 15557 if ( toHide.length && this.options.hide ) { 15558 this._hide( toHide, this.options.hide, function() { 15559 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); 15560 show(); 15561 }); 15562 } else { 15563 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); 15564 toHide.hide(); 15565 show(); 15566 } 15567 15568 toHide.attr({ 15569 "aria-expanded": "false", 15570 "aria-hidden": "true" 15571 }); 15572 eventData.oldTab.attr( "aria-selected", "false" ); 15573 // If we're switching tabs, remove the old tab from the tab order. 15574 // If we're opening from collapsed state, remove the previous tab from the tab order. 15575 // If we're collapsing, then keep the collapsing tab in the tab order. 15576 if ( toShow.length && toHide.length ) { 15577 eventData.oldTab.attr( "tabIndex", -1 ); 15578 } else if ( toShow.length ) { 15579 this.tabs.filter(function() { 15580 return $( this ).attr( "tabIndex" ) === 0; 15581 }) 15582 .attr( "tabIndex", -1 ); 15583 } 15584 15585 toShow.attr({ 15586 "aria-expanded": "true", 15587 "aria-hidden": "false" 15588 }); 15589 eventData.newTab.attr({ 15590 "aria-selected": "true", 15591 tabIndex: 0 15592 }); 15593 }, 15594 15595 _activate: function( index ) { 15596 var anchor, 15597 active = this._findActive( index ); 15598 15599 // trying to activate the already active panel 15600 if ( active[ 0 ] === this.active[ 0 ] ) { 15601 return; 15602 } 15603 15604 // trying to collapse, simulate a click on the current active header 15605 if ( !active.length ) { 15606 active = this.active; 15607 } 15608 15609 anchor = active.find( ".ui-tabs-anchor" )[ 0 ]; 15610 this._eventHandler({ 15611 target: anchor, 15612 currentTarget: anchor, 15613 preventDefault: $.noop 15614 }); 15615 }, 15616 15617 _findActive: function( index ) { 15618 return index === false ? $() : this.tabs.eq( index ); 15619 }, 15620 15621 _getIndex: function( index ) { 15622 // meta-function to give users option to provide a href string instead of a numerical index. 15623 if ( typeof index === "string" ) { 15624 index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) ); 15625 } 15626 15627 return index; 15628 }, 15629 15630 _destroy: function() { 15631 if ( this.xhr ) { 15632 this.xhr.abort(); 15633 } 15634 15635 this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" ); 15636 15637 this.tablist 15638 .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) 15639 .removeAttr( "role" ); 15640 15641 this.anchors 15642 .removeClass( "ui-tabs-anchor" ) 15643 .removeAttr( "role" ) 15644 .removeAttr( "tabIndex" ) 15645 .removeUniqueId(); 15646 15647 this.tabs.add( this.panels ).each(function() { 15648 if ( $.data( this, "ui-tabs-destroy" ) ) { 15649 $( this ).remove(); 15650 } else { 15651 $( this ) 15652 .removeClass( "ui-state-default ui-state-active ui-state-disabled " + 15653 "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" ) 15654 .removeAttr( "tabIndex" ) 15655 .removeAttr( "aria-live" ) 15656 .removeAttr( "aria-busy" ) 15657 .removeAttr( "aria-selected" ) 15658 .removeAttr( "aria-labelledby" ) 15659 .removeAttr( "aria-hidden" ) 15660 .removeAttr( "aria-expanded" ) 15661 .removeAttr( "role" ); 15662 } 15663 }); 15664 15665 this.tabs.each(function() { 15666 var li = $( this ), 15667 prev = li.data( "ui-tabs-aria-controls" ); 15668 if ( prev ) { 15669 li 15670 .attr( "aria-controls", prev ) 15671 .removeData( "ui-tabs-aria-controls" ); 15672 } else { 15673 li.removeAttr( "aria-controls" ); 15674 } 15675 }); 15676 15677 this.panels.show(); 15678 15679 if ( this.options.heightStyle !== "content" ) { 15680 this.panels.css( "height", "" ); 15681 } 15682 }, 15683 15684 enable: function( index ) { 15685 var disabled = this.options.disabled; 15686 if ( disabled === false ) { 15687 return; 15688 } 15689 15690 if ( index === undefined ) { 15691 disabled = false; 15692 } else { 15693 index = this._getIndex( index ); 15694 if ( $.isArray( disabled ) ) { 15695 disabled = $.map( disabled, function( num ) { 15696 return num !== index ? num : null; 15697 }); 15698 } else { 15699 disabled = $.map( this.tabs, function( li, num ) { 15700 return num !== index ? num : null; 15701 }); 15702 } 15703 } 15704 this._setupDisabled( disabled ); 15705 }, 15706 15707 disable: function( index ) { 15708 var disabled = this.options.disabled; 15709 if ( disabled === true ) { 15710 return; 15711 } 15712 15713 if ( index === undefined ) { 15714 disabled = true; 15715 } else { 15716 index = this._getIndex( index ); 15717 if ( $.inArray( index, disabled ) !== -1 ) { 15718 return; 15719 } 15720 if ( $.isArray( disabled ) ) { 15721 disabled = $.merge( [ index ], disabled ).sort(); 15722 } else { 15723 disabled = [ index ]; 15724 } 15725 } 15726 this._setupDisabled( disabled ); 15727 }, 15728 15729 load: function( index, event ) { 15730 index = this._getIndex( index ); 15731 var that = this, 15732 tab = this.tabs.eq( index ), 15733 anchor = tab.find( ".ui-tabs-anchor" ), 15734 panel = this._getPanelForTab( tab ), 15735 eventData = { 15736 tab: tab, 15737 panel: panel 15738 }; 15739 15740 // not remote 15741 if ( isLocal( anchor[ 0 ] ) ) { 15742 return; 15743 } 15744 15745 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) ); 15746 15747 // support: jQuery <1.8 15748 // jQuery <1.8 returns false if the request is canceled in beforeSend, 15749 // but as of 1.8, $.ajax() always returns a jqXHR object. 15750 if ( this.xhr && this.xhr.statusText !== "canceled" ) { 15751 tab.addClass( "ui-tabs-loading" ); 15752 panel.attr( "aria-busy", "true" ); 15753 15754 this.xhr 15755 .success(function( response ) { 15756 // support: jQuery <1.8 15757 // http://bugs.jquery.com/ticket/11778 15758 setTimeout(function() { 15759 panel.html( response ); 15760 that._trigger( "load", event, eventData ); 15761 }, 1 ); 15762 }) 15763 .complete(function( jqXHR, status ) { 15764 // support: jQuery <1.8 15765 // http://bugs.jquery.com/ticket/11778 15766 setTimeout(function() { 15767 if ( status === "abort" ) { 15768 that.panels.stop( false, true ); 15769 } 15770 15771 tab.removeClass( "ui-tabs-loading" ); 15772 panel.removeAttr( "aria-busy" ); 15773 15774 if ( jqXHR === that.xhr ) { 15775 delete that.xhr; 15776 } 15777 }, 1 ); 15778 }); 15779 } 15780 }, 15781 15782 _ajaxSettings: function( anchor, event, eventData ) { 15783 var that = this; 15784 return { 15785 url: anchor.attr( "href" ), 15786 beforeSend: function( jqXHR, settings ) { 15787 return that._trigger( "beforeLoad", event, 15788 $.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) ); 15789 } 15790 }; 15791 }, 15792 15793 _getPanelForTab: function( tab ) { 15794 var id = $( tab ).attr( "aria-controls" ); 15795 return this.element.find( this._sanitizeSelector( "#" + id ) ); 15796 } 15797}); 15798 15799})( _4ORMAT.$ ); 15800(function( $ ) { 15801 15802var increments = 0; 15803 15804function addDescribedBy( elem, id ) { 15805 var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ); 15806 describedby.push( id ); 15807 elem 15808 .data( "ui-tooltip-id", id ) 15809 .attr( "aria-describedby", $.trim( describedby.join( " " ) ) ); 15810} 15811 15812function removeDescribedBy( elem ) { 15813 var id = elem.data( "ui-tooltip-id" ), 15814 describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ), 15815 index = $.inArray( id, describedby ); 15816 if ( index !== -1 ) { 15817 describedby.splice( index, 1 ); 15818 } 15819 15820 elem.removeData( "ui-tooltip-id" ); 15821 describedby = $.trim( describedby.join( " " ) ); 15822 if ( describedby ) { 15823 elem.attr( "aria-describedby", describedby ); 15824 } else { 15825 elem.removeAttr( "aria-describedby" ); 15826 } 15827} 15828 15829$.widget( "ui.tooltip", { 15830 version: "1.10.4", 15831 options: { 15832 content: function() { 15833 // support: IE<9, Opera in jQuery <1.7 15834 // .text() can't accept undefined, so coerce to a string 15835 var title = $( this ).attr( "title" ) || ""; 15836 // Escape title, since we're going from an attribute to raw HTML 15837 return $( "<a>" ).text( title ).html(); 15838 }, 15839 hide: true, 15840 // Disabled elements have inconsistent behavior across browsers (#8661) 15841 items: "[title]:not([disabled])", 15842 position: { 15843 my: "left top+15", 15844 at: "left bottom", 15845 collision: "flipfit flip" 15846 }, 15847 show: true, 15848 tooltipClass: null, 15849 track: false, 15850 15851 // callbacks 15852 close: null, 15853 open: null 15854 }, 15855 15856 _create: function() { 15857 this._on({ 15858 mouseover: "open", 15859 focusin: "open" 15860 }); 15861 15862 // IDs of generated tooltips, needed for destroy 15863 this.tooltips = {}; 15864 // IDs of parent tooltips where we removed the title attribute 15865 this.parents = {}; 15866 15867 if ( this.options.disabled ) { 15868 this._disable(); 15869 } 15870 }, 15871 15872 _setOption: function( key, value ) { 15873 var that = this; 15874 15875 if ( key === "disabled" ) { 15876 this[ value ? "_disable" : "_enable" ](); 15877 this.options[ key ] = value; 15878 // disable element style changes 15879 return; 15880 } 15881 15882 this._super( key, value ); 15883 15884 if ( key === "content" ) { 15885 $.each( this.tooltips, function( id, element ) { 15886 that._updateContent( element ); 15887 }); 15888 } 15889 }, 15890 15891 _disable: function() { 15892 var that = this; 15893 15894 // close open tooltips 15895 $.each( this.tooltips, function( id, element ) { 15896 var event = $.Event( "blur" ); 15897 event.target = event.currentTarget = element[0]; 15898 that.close( event, true ); 15899 }); 15900 15901 // remove title attributes to prevent native tooltips 15902 this.element.find( this.options.items ).addBack().each(function() { 15903 var element = $( this ); 15904 if ( element.is( "[title]" ) ) { 15905 element 15906 .data( "ui-tooltip-title", element.attr( "title" ) ) 15907 .attr( "title", "" ); 15908 } 15909 }); 15910 }, 15911 15912 _enable: function() { 15913 // restore title attributes 15914 this.element.find( this.options.items ).addBack().each(function() { 15915 var element = $( this ); 15916 if ( element.data( "ui-tooltip-title" ) ) { 15917 element.attr( "title", element.data( "ui-tooltip-title" ) ); 15918 } 15919 }); 15920 }, 15921 15922 open: function( event ) { 15923 var that = this, 15924 target = $( event ? event.target : this.element ) 15925 // we need closest here due to mouseover bubbling, 15926 // but always pointing at the same event target 15927 .closest( this.options.items ); 15928 15929 // No element to show a tooltip for or the tooltip is already open 15930 if ( !target.length || target.data( "ui-tooltip-id" ) ) { 15931 return; 15932 } 15933 15934 if ( target.attr( "title" ) ) { 15935 target.data( "ui-tooltip-title", target.attr( "title" ) ); 15936 } 15937 15938 target.data( "ui-tooltip-open", true ); 15939 15940 // kill parent tooltips, custom or native, for hover 15941 if ( event && event.type === "mouseover" ) { 15942 target.parents().each(function() { 15943 var parent = $( this ), 15944 blurEvent; 15945 if ( parent.data( "ui-tooltip-open" ) ) { 15946 blurEvent = $.Event( "blur" ); 15947 blurEvent.target = blurEvent.currentTarget = this; 15948 that.close( blurEvent, true ); 15949 } 15950 if ( parent.attr( "title" ) ) { 15951 parent.uniqueId(); 15952 that.parents[ this.id ] = { 15953 element: this, 15954 title: parent.attr( "title" ) 15955 }; 15956 parent.attr( "title", "" ); 15957 } 15958 }); 15959 } 15960 15961 this._updateContent( target, event ); 15962 }, 15963 15964 _updateContent: function( target, event ) { 15965 var content, 15966 contentOption = this.options.content, 15967 that = this, 15968 eventType = event ? event.type : null; 15969 15970 if ( typeof contentOption === "string" ) { 15971 return this._open( event, target, contentOption ); 15972 } 15973 15974 content = contentOption.call( target[0], function( response ) { 15975 // ignore async response if tooltip was closed already 15976 if ( !target.data( "ui-tooltip-open" ) ) { 15977 return; 15978 } 15979 // IE may instantly serve a cached response for ajax requests 15980 // delay this call to _open so the other call to _open runs first 15981 that._delay(function() { 15982 // jQuery creates a special event for focusin when it doesn't 15983 // exist natively. To improve performance, the native event 15984 // object is reused and the type is changed. Therefore, we can't 15985 // rely on the type being correct after the event finished 15986 // bubbling, so we set it back to the previous value. (#8740) 15987 if ( event ) { 15988 event.type = eventType; 15989 } 15990 this._open( event, target, response ); 15991 }); 15992 }); 15993 if ( content ) { 15994 this._open( event, target, content ); 15995 } 15996 }, 15997 15998 _open: function( event, target, content ) { 15999 var tooltip, events, delayedShow, 16000 positionOption = $.extend( {}, this.options.position ); 16001 16002 if ( !content ) { 16003 return; 16004 } 16005 16006 // Content can be updated multiple times. If the tooltip already 16007 // exists, then just update the content and bail. 16008 tooltip = this._find( target ); 16009 if ( tooltip.length ) { 16010 tooltip.find( ".ui-tooltip-content" ).html( content ); 16011 return; 16012 } 16013 16014 // if we have a title, clear it to prevent the native tooltip 16015 // we have to check first to avoid defining a title if none exists 16016 // (we don't want to cause an element to start matching [title]) 16017 // 16018 // We use removeAttr only for key events, to allow IE to export the correct 16019 // accessible attributes. For mouse events, set to empty string to avoid 16020 // native tooltip showing up (happens only when removing inside mouseover). 16021 if ( target.is( "[title]" ) ) { 16022 if ( event && event.type === "mouseover" ) { 16023 target.attr( "title", "" ); 16024 } else {
16025 target.removeAttr( "title" ); 16026 } 16027 } 16028 16029 tooltip = this._tooltip( target ); 16030 addDescribedBy( target, tooltip.attr( "id" ) ); 16031 tooltip.find( ".ui-tooltip-content" ).html( content ); 16032 16033 function position( event ) { 16034 positionOption.of = event; 16035 if ( tooltip.is( ":hidden" ) ) { 16036 return; 16037 } 16038 tooltip.position( positionOption ); 16039 } 16040 if ( this.options.track && event && /^mouse/.test( event.type ) ) { 16041 this._on( this.document, { 16042 mousemove: position 16043 }); 16044 // trigger once to override element-relative positioning 16045 position( event ); 16046 } else { 16047 tooltip.position( $.extend({ 16048 of: target 16049 }, this.options.position ) ); 16050 } 16051 16052 tooltip.hide(); 16053 16054 this._show( tooltip, this.options.show ); 16055 // Handle tracking tooltips that are shown with a delay (#8644). As soon 16056 // as the tooltip is visible, position the tooltip using the most recent 16057 // event. 16058 if ( this.options.show && this.options.show.delay ) { 16059 delayedShow = this.delayedShow = setInterval(function() { 16060 if ( tooltip.is( ":visible" ) ) { 16061 position( positionOption.of ); 16062 clearInterval( delayedShow ); 16063 } 16064 }, $.fx.interval ); 16065 } 16066 16067 this._trigger( "open", event, { tooltip: tooltip } ); 16068 16069 events = { 16070 keyup: function( event ) { 16071 if ( event.keyCode === $.ui.keyCode.ESCAPE ) { 16072 var fakeEvent = $.Event(event); 16073 fakeEvent.currentTarget = target[0]; 16074 this.close( fakeEvent, true ); 16075 } 16076 }, 16077 remove: function() { 16078 this._removeTooltip( tooltip ); 16079 } 16080 }; 16081 if ( !event || event.type === "mouseover" ) { 16082 events.mouseleave = "close"; 16083 } 16084 if ( !event || event.type === "focusin" ) { 16085 events.focusout = "close"; 16086 } 16087 this._on( true, target, events ); 16088 }, 16089 16090 close: function( event ) { 16091 var that = this, 16092 target = $( event ? event.currentTarget : this.element ), 16093 tooltip = this._find( target ); 16094 16095 // disabling closes the tooltip, so we need to track when we're closing 16096 // to avoid an infinite loop in case the tooltip becomes disabled on close 16097 if ( this.closing ) { 16098 return; 16099 } 16100 16101 // Clear the interval for delayed tracking tooltips 16102 clearInterval( this.delayedShow ); 16103 16104 // only set title if we had one before (see comment in _open()) 16105 if ( target.data( "ui-tooltip-title" ) ) { 16106 target.attr( "title", target.data( "ui-tooltip-title" ) ); 16107 } 16108 16109 removeDescribedBy( target ); 16110 16111 tooltip.stop( true ); 16112 this._hide( tooltip, this.options.hide, function() { 16113 that._removeTooltip( $( this ) ); 16114 }); 16115 16116 target.removeData( "ui-tooltip-open" ); 16117 this._off( target, "mouseleave focusout keyup" ); 16118 // Remove 'remove' binding only on delegated targets 16119 if ( target[0] !== this.element[0] ) { 16120 this._off( target, "remove" ); 16121 } 16122 this._off( this.document, "mousemove" ); 16123 16124 if ( event && event.type === "mouseleave" ) { 16125 $.each( this.parents, function( id, parent ) { 16126 $( parent.element ).attr( "title", parent.title ); 16127 delete that.parents[ id ]; 16128 }); 16129 } 16130 16131 this.closing = true; 16132 this._trigger( "close", event, { tooltip: tooltip } ); 16133 this.closing = false; 16134 }, 16135 16136 _tooltip: function( element ) { 16137 var id = "ui-tooltip-" + increments++, 16138 tooltip = $( "<div>" ) 16139 .attr({ 16140 id: id, 16141 role: "tooltip" 16142 }) 16143 .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " + 16144 ( this.options.tooltipClass || "" ) ); 16145 $( "<div>" ) 16146 .addClass( "ui-tooltip-content" ) 16147 .appendTo( tooltip ); 16148 tooltip.appendTo( this.document[0].body ); 16149 this.tooltips[ id ] = element; 16150 return tooltip; 16151 }, 16152 16153 _find: function( target ) { 16154 var id = target.data( "ui-tooltip-id" ); 16155 return id ? $( "#" + id ) : $(); 16156 }, 16157 16158 _removeTooltip: function( tooltip ) { 16159 tooltip.remove(); 16160 delete this.tooltips[ tooltip.attr( "id" ) ]; 16161 }, 16162 16163 _destroy: function() { 16164 var that = this; 16165 16166 // close open tooltips 16167 $.each( this.tooltips, function( id, element ) { 16168 // Delegate to close method to handle common cleanup 16169 var event = $.Event( "blur" ); 16170 event.target = event.currentTarget = element[0]; 16171 that.close( event, true ); 16172 16173 // Remove immediately; destroying an open tooltip doesn't use the 16174 // hide animation 16175 $( "#" + id ).remove(); 16176 16177 // Restore the title 16178 if ( element.data( "ui-tooltip-title" ) ) { 16179 element.attr( "title", element.data( "ui-tooltip-title" ) ); 16180 element.removeData( "ui-tooltip-title" ); 16181 } 16182 }); 16183 } 16184}); 16185 16186}( _4ORMAT.$ ) ); 16187/* =========================================================== 16188 * bootstrap-tooltip.js v2.1.1 16189 * http://twitter.github.com/bootstrap/javascript.html#tooltips 16190 * Inspired by the original jQuery.tipsy by Jason Frame 16191 * =========================================================== 16192 * Copyright 2012 Twitter, Inc. 16193 * 16194 * Licensed under the Apache License, Version 2.0 (the "License");
16195 * you may not use this file except in compliance with the License. 16196 * You may obtain a copy of the License at 16197 * 16198 * http://www.apache.org/licenses/LICENSE-2.0 16199 * 16200 * Unless required by applicable law or agreed to in writing, software 16201 * distributed under the License is distributed on an "AS IS" BASIS, 16202 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16203 * See the License for the specific language governing permissions and 16204 * limitations under the License. 16205 * ========================================================== */ 16206 16207 16208 16209!function ($) { 16210 16211 "use strict"; // jshint ;_; 16212 16213 16214 /* TOOLTIP PUBLIC CLASS DEFINITION 16215 * =============================== */ 16216 16217 var Tooltip = function (element, options) { 16218 this.init('tooltip', element, options) 16219 } 16220 16221 Tooltip.prototype = { 16222 16223 constructor: Tooltip 16224 16225 , init: function (type, element, options) { 16226 var eventIn 16227 , eventOut 16228 16229 this.type = type 16230 this.$element = $(element) 16231 this.options = this.getOptions(options) 16232 this.enabled = true 16233 16234 if (this.options.trigger == 'click') { 16235 this.$element.live('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) 16236 } else if (this.options.trigger != 'manual') { 16237 eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus' 16238 eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur' 16239 this.$element.live(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) 16240 this.$element.live(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) 16241 } 16242 16243 this.options.selector ? 16244 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : 16245 this.fixTitle() 16246 } 16247 16248 , getOptions: function (options) { 16249 options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data()) 16250 16251 if (options.delay && typeof options.delay == 'number') { 16252 options.delay = { 16253 show: options.delay 16254 , hide: options.delay 16255 } 16256 } 16257 16258 return options 16259 } 16260 16261 , enter: function (e) { 16262 var self = $(e.currentTarget)[this.type](this._options).data(this.type) 16263 16264 if (!self.options.delay || !self.options.delay.show) return self.show() 16265 16266 clearTimeout(this.timeout) 16267 self.hoverState = 'in' 16268 this.timeout = setTimeout(function() { 16269 if (self.hoverState == 'in') self.show() 16270 }, self.options.delay.show) 16271 } 16272 16273 , leave: function (e) { 16274 var self = $(e.currentTarget)[this.type](this._options).data(this.type) 16275 16276 if (this.timeout) clearTimeout(this.timeout) 16277 if (!self.options.delay || !self.options.delay.hide) return self.hide() 16278 16279 self.hoverState = 'out' 16280 this.timeout = setTimeout(function() { 16281 if (self.hoverState == 'out') self.hide() 16282 }, self.options.delay.hide) 16283 } 16284 16285 , show: function () { 16286 var $tip 16287 , inside 16288 , pos 16289 , actualWidth 16290 , actualHeight 16291 , placement 16292 , tp 16293 16294 if (this.hasContent() && this.enabled) { 16295 $tip = this.tip() 16296 this.setContent() 16297 16298 if (this.options.animation) { 16299 $tip.addClass('fade') 16300 } 16301 16302 placement = typeof this.options.placement == 'function' ? 16303 this.options.placement.call(this, $tip[0], this.$element[0]) : 16304 this.options.placement 16305 16306 inside = /in/.test(placement) 16307 16308 $tip 16309 .remove() 16310 .css({ top: 0, left: 0, display: 'block' }) 16311 .appendTo(inside ? this.$element : document.body) 16312 16313 pos = this.getPosition(inside) 16314 16315 actualWidth = $tip[0].offsetWidth 16316 actualHeight = $tip[0].offsetHeight 16317 16318 switch (inside ? placement.split(' ')[1] : placement) { 16319 case 'bottom': 16320 tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2} 16321 break 16322 case 'top': 16323 tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2} 16324 break 16325 case 'left': 16326 tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth} 16327 break 16328 case 'right': 16329 tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width} 16330 break 16331 } 16332 16333 $tip 16334 .css(tp) 16335 .addClass(placement) 16336 .addClass('in') 16337 } 16338 } 16339 16340 , setContent: function () { 16341 var $tip = this.tip() 16342 , title = this.getTitle() 16343 16344 $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) 16345 $tip.removeClass('fade in top bottom left right') 16346 } 16347 16348 , hide: function () { 16349 var that = this 16350 , $tip = this.tip() 16351 16352 $tip.removeClass('in') 16353 16354 function removeWithAnimation() { 16355 var timeout = setTimeout(function () { 16356 $tip.unbind($.support.transition.end).remove() 16357 }, 500) 16358 16359 $tip.one($.support.transition.end, function () { 16360 clearTimeout(timeout) 16361 $tip.remove() 16362 }) 16363 } 16364 16365 $.support.transition && this.$tip.hasClass('fade') ? 16366 removeWithAnimation() : 16367 $tip.remove() 16368 16369 return this 16370 } 16371 16372 , fixTitle: function () { 16373 var $e = this.$element 16374 if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { 16375 $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title') 16376 } 16377 } 16378 16379 , hasContent: function () { 16380 return this.getTitle() 16381 } 16382 16383 , getPosition: function (inside) { 16384 return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), { 16385 width: this.$element[0].offsetWidth 16386 , height: this.$element[0].offsetHeight 16387 }) 16388 } 16389 16390 , getTitle: function () { 16391 var title 16392 , $e = this.$element 16393 , o = this.options 16394 16395 title = $e.attr('data-original-title') 16396 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) 16397 16398 return title 16399 } 16400 16401 , tip: function () { 16402 return this.$tip = this.$tip || $(this.options.template) 16403 } 16404 16405 , validate: function () { 16406 if (!this.$element[0].parentNode) { 16407 this.hide() 16408 this.$element = null 16409 this.options = null 16410 } 16411 } 16412 16413 , enable: function () { 16414 this.enabled = true 16415 } 16416 16417 , disable: function () { 16418 this.enabled = false 16419 } 16420 16421 , toggleEnabled: function () { 16422 this.enabled = !this.enabled 16423 } 16424 16425 , toggle: function () { 16426 this[this.tip().hasClass('in') ? 'hide' : 'show']() 16427 } 16428 16429 , destroy: function () { 16430 this.hide().$element.unbind('.' + this.type).removeData(this.type) 16431 } 16432 16433 } 16434 16435 16436 /* TOOLTIP PLUGIN DEFINITION 16437 * ========================= */ 16438 16439 $.fn.tooltip = function ( option ) { 16440 return this.each(function () { 16441 var $this = $(this) 16442 , data = $this.data('tooltip') 16443 , options = typeof option == 'object' && option 16444 if (!data) $this.data('tooltip', (data = new Tooltip(this, options))) 16445 if (typeof option == 'string') data[option]() 16446 }) 16447 } 16448 16449 $.fn.tooltip.Constructor = Tooltip 16450 16451 $.fn.tooltip.defaults = { 16452 animation: true 16453 , placement: 'top' 16454 , selector: false 16455 , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>' 16456 , trigger: 'hover' 16457 , title: '' 16458 , delay: 0 16459 , html: true 16460 } 16461 16462}(typeof(_4ORMAT) === 'object' ? _4ORMAT.jQuery : window.jQuery); 16463(function(){ 16464 var $ = this.jQuery, 16465 that = null; 16466 16467 /** 16468 * Create and show a new modal message. 16469 * @constructor 16470 * @param {(string|Object)} options - Either a string that will be the modal message text or an options object. 16471 * @param {Object} options.target_el - jQuery collection of the element in which the modal message will be placed. 16472 * For example: 16473 * $('body') 16474 * @param {string} options.title - The text shown as the modal message's title. 16475 * For example: 16476 * "My Title" 16477 */ 16478 this.ModalMessage = function(options) { 16479 16480 // Options can take just a string or an object of values 16481 16482 // Object accepts following values: 16483 // { 16484 // target_el : $('body'), 16485 // title : "My Title", 16486 // html : "<p>String of html.</p>", 16487 // text : "String of text.", 16488 // modal_class : 'small/medium/large', 16489 // prevent_close : true, 16490 // enter_button : 'button', 16491 // buttons : { 16492 // 'button' : { 16493 // text : 'My Button', 16494 // classes : 'class1 class2 class3', 16495 // icon : 'check', 16496 // action : function() { 16497 // alert('callback'); 16498 // } 16499 // }, 16500 // 'close' : { text : 'Close' } 16501 // }, 16502 // on_create_callback : function() {} // called after modal is appended to DOM 16503 // before_close_callback : function(modal) {} // called before modal is closed (via 'X' button or modal.close_modal) 16504 // after_close_callback : function(modal) {} // called after modal is closed (via 'X' button or modal.close_modal) 16505 // } 16506 16507 // Instantiation syntax: 16508 // var modal = new ModalMessage({ options }); 16509 16510 // Notes: 16511 16512 // - Accepts an object passed to target to append the modal. 16513 // - If html and text is passed as args the text will not show. 16514 // - Creating a button 'close' automatically gets the close event bound. 16515 // - If no buttons are created a close button will be added, if at least one 16516 // button is created then close will not automatically be added. 16517 // - Button icons pull from ss-icon library. 16518 // - Buttons can be assigned functions through the action option callback. 16519 // - Specify 'prevent_close' as true if user shouldn't be able to close the modal. 16520 // - enter_button determines which button gets a click invoked when users presses enter button 16521 16522 16523 var html = '', 16524 modal_class = 'small', 16525 target_el = $('body'); 16526 16527 that = this; 16528 16529 this.anim_speed = 300; 16530 this.options = options; 16531 16532 if(options.modal_class) { modal_class = options.modal_class; } 16533 16534 if (typeof(options) === 'string') { options = {text: options}; } 16535 16536 if (options.buttons === undefined && options.prevent_close !== true) { 16537 options.buttons = { 16538 close: { 16539 text: 'Close', 16540 classes: 'btn_default' 16541 } 16542 }; 16543 } 16544 16545 // Wrapper and Overlay for popup 16546 16547 html += '<div class="_4ORMAT_overlay"></div><div class="ModalMessage generated ' + modal_class + '">'; 16548 16549 // Body content gets inserted here. If html isn't provided we assume that 16550 // title and/or text is provided and populate the popup with this instead. 16551 16552 if(options.title) { 16553 html += '<div id="modalMessage_header">'; 16554 16555 if(options.prevent_close !== true) { 16556 html += '<a href="javascript:void(0)" class="ss-icon close">close</a>'; 16557 } 16558 16559 html += '<div id="modalMessage_header_title">' + options.title + '</div>'; 16560 html += '</div>'; 16561 } else { 16562 if(options.prevent_close !== true) { 16563 html += '<a href="javascript:void(0)" class="ss-icon close">close</a>'; 16564 } 16565 } 16566 16567 html += '<div class="msg">'; 16568 16569 if(options.html) { 16570 html += options.html; 16571 } else if(options.text) { 16572 html += '<p>' + options.text + '</p>'; 16573 } 16574 16575 html += '</div>'; 16576 16577 // Construct buttons 16578 16579 if(options.buttons) { 16580 html += '<p class="center">'; 16581 16582 // for each button add it with the classes and names 16583 16584 $.each(options.buttons, function(i, v) { 16585 var text = '', 16586 classes = ''; 16587 16588 if(v.text) { text = v.text; } 16589 if(v.classes) { classes = ' ' + v.classes; } 16590 16591 html += '<a href="javascript:void(0)" class="' + i + classes +'">'; 16592 16593 if(v.icon) { 16594 html += '<span class="ss-icon">' + v.icon + '</span> '; 16595 } 16596 16597 html += text + '</a>'; 16598 }); 16599 16600 html += '</p>'; 16601 } 16602 16603 html += '</div>'; 16604 16605 // Append html to dom. 16606 16607 if(typeof(options.target_el) === 'object') { 16608 target_el = options.target_el; 16609 } 16610 16611 target_el.append(html); 16612 16613 if(typeof(options.on_create_callback) === 'function') { 16614 options.on_create_callback(); 16615 } 16616 16617 // Animate after appended. 16618 16619 setTimeout(function() { 16620 $('.ModalMessage').addClass('show'); 16621 $('._4ORMAT_overlay').addClass('show'); 16622 }, 1); 16623 16624 // Bind button actions 16625 16626 if(options.buttons) { 16627 $.each(options.buttons, function(i, v) { 16628 if(typeof(v.action) === 'function') { 16629 $('.ModalMessage').delegate('.' + i, 'click.modal', v.action); 16630 } 16631 }); 16632 } 16633 16634 $(document).unbind('keydown.modal').bind('keydown.modal', function(e) { 16635 if(e.which == 13) { 16636 if(! options.enter_button) { options.enter_button = 'close'; } 16637 $('.ModalMessage .' + options.enter_button).trigger('click'); 16638 } 16639 }); 16640 16641 // Bind close event 16642 16643 if(options.prevent_close !== true) { 16644 $('html').delegate('.ModalMessage .close, ._4ORMAT_overlay', 'click.modal_close', this.close_modal); 16645 } 16646 }; 16647 16648 // helper functions 16649 16650 this.ModalMessage.prototype.close_modal = function() { 16651 if (typeof(that.options.before_close_callback) === 'function') { 16652 that.options.before_close_callback(that); 16653 } 16654 16655 $('.ModalMessage').removeClass('show'); 16656 $('._4ORMAT_overlay').removeClass('show'); 16657 16658 if(that.options.prevent_close !== true) { 16659 $('html').undelegate('.ModalMessage .close, ._4ORMAT_overlay', 'click.modal_close'); 16660 } 16661 16662 if(that.options.buttons) { 16663 $.each(that.options.buttons, function(i, v) { 16664 if(typeof(v.action) === 'function') { 16665 $('.ModalMessage').undelegate('.' + i, 'click.modal'); 16666 } 16667 }); 16668 } 16669 16670 $(document).unbind('keydown.modal'); 16671 16672 setTimeout(function() { 16673 $('.ModalMessage.generated').remove(); 16674 $('._4ORMAT_overlay').remove(); 16675 if (typeof(that.options.after_close_callback) === 'function') { 16676 that.options.after_close_callback(that); 16677 } 16678 }, that.anim_speed); 16679 }; 16680}).call(typeof(_4ORMAT) === 'object' ? _4ORMAT : window); 16681 16682 16683 16684 16685 16686// Public facing javascript for content pages 16687// It's included in the content iframe when the page is flagged to be 16688// rendered in 'edit mode' 16689(function() { 16690 var $ = this.$; 16691 var ModalMessage = _4ORMAT.ModalMessage; 16692 16693 var ContactForm = {}; 16694 this.ContactForm = ContactForm; 16695 16696 var formSubmitTextValues = {}; 16697 16698 function beginFormInit() { 16699 if (typeof _4ORMAT.contact_forms === "object") { 16700 $(".email_form[data-editable-type='contact-form']").each(function(_i, form) { 16701 var $form = $(form); 16702 16703 if ($form.data("contactFormType") !== "mailing-list") { 16704 ContactForm.initForm($form); 16705 } 16706 }); 16707 } 16708 } 16709 16710 ContactForm.initForm = function(form) { 16711 if (_4ORMAT_DATA && !_4ORMAT_DATA.page.content_editable && !_4ORMAT_DATA.preview) { 16712 $.ajax("/public_heartbeat").fail(function() { 16713 form.find("input, textarea").prop("disabled", true); 16714 form.find("input[type=submit]").attr("originalValue", form.find("input[type=submit]").val()); 16715 form.find("input[type=submit]").val("Form is unavailable, please try again later"); 16716 }); 16717 } 16718 16719 ContactForm.addValidations(form); 16720 16721 // fixme - $(window).resize doesnt work but window.onresize does 16722 window.onresize = function() { 16723 $("div.tooltip").remove(); 16724 }; 16725 }; 16726 16727 // validation rules by data-validate type 16728 ContactForm.validationRules = { 16729 email: { email: true, required: true },
16730 name: { maxlength: 255 }, 16731 body: { required: true, maxlength: 65535 }, 16732 }; 16733 16734 // messages to display to the user when validating 16735 ContactForm.validationMessages = { 16736 email: { 16737 required: "Email address is required.", 16738 email: "Email address is not valid.", 16739 }, 16740 name: { 16741 maxlength: "Field length must not exceed 255 characters.", 16742 }, 16743 body: { 16744 required: "Message must not be blank.", 16745 maxlength: "Message length must not exceed 65,535 characters.", 16746 }, 16747 }; 16748 16749 // add validations to the form 16750 ContactForm.addValidations = function(form) { 16751 var rules = {}; 16752 var messages = {}; 16753 var name; 16754 var type; 16755 16756 // A simple system that is specifically not the HTML5 validation spec so 16757 // that we don't have two validations going on. 16758 // 16759 // <input> - no validation 16760 // <input data-validate='required'> - validated presence 16761 // <input data-validate='email'> - validates presence and email format 16762 form.find("*[data-validate]").each(function(i, node) { 16763 node = $(node); 16764 type = node.data("validate"); 16765 name = node.attr("name"); 16766 16767 rules[name] = ContactForm.validationRules[type]; 16768 messages[name] = ContactForm.validationMessages[type]; 16769 }); 16770 16771 // Validations currently disabled in editor mode. Rendering the tooltips is 16772 // broken because of the page position of the iframe. 16773 if (!_4ORMAT_DATA.page.content_editable) { 16774 form.validate({ 16775 rules: rules, 16776 messages: messages, 16777 errorElement: "p", 16778 errorClass: "invalid", 16779 errorPlacement: ContactForm.errorPlacement, 16780 unhighlight: ContactForm.unhighlight, 16781 submitHandler: ContactForm.submitHandler, 16782 }); 16783 } 16784 }; 16785 16786 // callback that places validation error on the page 16787 ContactForm.errorPlacement = function(error, element) { 16788 $(element) 16789 .tooltip("destroy") 16790 .attr("title", $(error).text()); 16791 $(element) 16792 .tooltip({ 16793 html: false, 16794 placement: "bottom", 16795 trigger: "manual", 16796 }) 16797 .tooltip("show"); 16798 }; 16799 16800 // callback that unhighlights a previously highlighted field 16801 ContactForm.unhighlight = function(element) { 16802 $(element).tooltip("destroy"); 16803 }; 16804 ContactForm.submitHandler = function(form) { 16805 if (_4ORMAT_DATA.page.content_editable) { 16806 ContactForm.previewSubmit(); 16807 } else { 16808 ContactForm.saveSubmitValue(form); 16809 ContactForm.disableSubmit(form); 16810 $.ajax({ 16811 url: $(form).attr("action"), 16812 data: $(form).serialize(), 16813 type: "POST", 16814 context: form, 16815 }) 16816 .done(ContactForm.sendSuccess) 16817 .done(function() { 16818 $(this) 16819 .find("textarea") 16820 .val(""); 16821 }) 16822 .fail(ContactForm.sendError); 16823 } 16824 return false; // required to prevent the form from submitting? 16825 }; 16826 16827 ContactForm.disableSubmit = function(form) { 16828 $(form) 16829 .find("input[type=submit]") 16830 .attr("disabled", "disabled") 16831 .val("Sending..."); 16832 }; 16833 16834 ContactForm.saveSubmitValue = function(form) { 16835 var formSubmitValue = $(form) 16836 .find("input[type=submit]") 16837 .val(); 16838 formSubmitTextValues[$(form).attr("id")] = formSubmitValue; 16839 }; 16840 16841 ContactForm.previewSubmit = function() { 16842 new ModalMessage({ 16843 title: "Note", 16844 text: "When this button is clicked by visitors to your site, it will send you this form in an email.", 16845 }); 16846 }; 16847 16848 ContactForm.sendSuccess = function() { 16849 var formId = $(this).attr("id"); 16850 16851 $(this).trigger("reset"); 16852 16853 $(this) 16854 .find("input[type=submit]") 16855 .attr("disabled", "disabled") 16856 .addClass("f_form_send_success") 16857 .val("Message Sent"); 16858 16859 var that = this; 16860 var resetFormTimeout = 2000; 16861 setTimeout(function() { 16862 $(that) 16863 .find("input[type=submit]") 16864 .removeAttr("disabled") 16865 .val(formSubmitTextValues[formId]); 16866 }, resetFormTimeout); 16867 16868 $(this) 16869 .find("fieldset") 16870 .removeClass("_4ORMAT_module_input_active"); 16871 }; 16872 16873 ContactForm.sendError = function() { 16874 var formId = $(this).attr("id"); 16875 $(this) 16876 .find("input[type=submit]") 16877 .removeAttr("disabled") 16878 .val(formSubmitTextValues[formId]); 16879 16880 new ModalMessage({ 16881 title: "Warning", 16882 text: "We could not deliver your message. Please try again later.", 16883 modal_class: "warning small", 16884 }); 16885 }; 16886 16887 beginFormInit(); 16888}.call(_4ORMAT));
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.