diff options
Diffstat (limited to 'ui')
-rw-r--r-- | ui/i18n/jquery.ui.datepicker-he.js | 4 | ||||
-rw-r--r-- | ui/i18n/jquery.ui.datepicker-hi.js | 23 | ||||
-rw-r--r-- | ui/i18n/jquery.ui.datepicker-km.js | 23 | ||||
-rw-r--r-- | ui/jquery.effects.core.js | 252 | ||||
-rw-r--r-- | ui/jquery.ui.accordion.js | 330 | ||||
-rw-r--r-- | ui/jquery.ui.autocomplete.js | 41 | ||||
-rw-r--r-- | ui/jquery.ui.button.js | 16 | ||||
-rw-r--r-- | ui/jquery.ui.core.js | 24 | ||||
-rw-r--r-- | ui/jquery.ui.datepicker.js | 9 | ||||
-rw-r--r-- | ui/jquery.ui.draggable.js | 10 | ||||
-rw-r--r-- | ui/jquery.ui.menu.js | 69 | ||||
-rw-r--r-- | ui/jquery.ui.mouse.js | 16 | ||||
-rw-r--r-- | ui/jquery.ui.position.js | 10 | ||||
-rw-r--r-- | ui/jquery.ui.resizable.js | 36 | ||||
-rw-r--r-- | ui/jquery.ui.slider.js | 8 | ||||
-rw-r--r-- | ui/jquery.ui.sortable.js | 2 | ||||
-rw-r--r-- | ui/jquery.ui.tabs.js | 262 | ||||
-rw-r--r-- | ui/jquery.ui.tooltip.js | 12 | ||||
-rw-r--r-- | ui/jquery.ui.widget.js | 76 |
19 files changed, 518 insertions, 705 deletions
diff --git a/ui/i18n/jquery.ui.datepicker-he.js b/ui/i18n/jquery.ui.datepicker-he.js index 58ea8c6d8..b9e8deec5 100644 --- a/ui/i18n/jquery.ui.datepicker-he.js +++ b/ui/i18n/jquery.ui.datepicker-he.js @@ -8,8 +8,8 @@ jQuery(function($){ currentText: 'היום', monthNames: ['ינואר','פברואר','מרץ','אפריל','מאי','יוני', 'יולי','אוגוסט','ספטמבר','אוקטובר','נובמבר','דצמבר'], - monthNamesShort: ['1','2','3','4','5','6', - '7','8','9','10','11','12'], + monthNamesShort: ['ינו','פבר','מרץ','אפר','מאי','יוני', + 'יולי','אוג','ספט','אוק','נוב','דצמ'], dayNames: ['ראשון','שני','שלישי','רביעי','חמישי','שישי','שבת'], dayNamesShort: ['א\'','ב\'','ג\'','ד\'','ה\'','ו\'','שבת'], dayNamesMin: ['א\'','ב\'','ג\'','ד\'','ה\'','ו\'','שבת'], diff --git a/ui/i18n/jquery.ui.datepicker-hi.js b/ui/i18n/jquery.ui.datepicker-hi.js new file mode 100644 index 000000000..d75e98ead --- /dev/null +++ b/ui/i18n/jquery.ui.datepicker-hi.js @@ -0,0 +1,23 @@ +/* Hindi initialisation for the jQuery UI date picker plugin. */ +/* Written by Michael Dawart. */ +jQuery(function($){ + $.datepicker.regional['hi'] = { + closeText: 'होकर', + prevText: 'अगला', + nextText: 'नेक्स्ट', + currentText: 'आज', + monthNames: ['जनवरी ','फरवरी','मार्च','अप्रेल','मै','जून', + 'जूलाई','अगस्त ','सितम्बर','आक्टोबर','नवम्बर','दिसम्बर'], + monthNamesShort: ['जन', 'फर', 'मार्च', 'अप्रेल', 'मै', 'जून', + 'जूलाई', 'अग', 'सित', 'आक्ट', 'नव', 'िद'], + dayNames: ['रविवासर', 'सोमवासर', 'मंगलवासर', 'बुधवासर', 'गुरुवासर', 'शुक्रवासर', 'शनिवासर'], + dayNamesShort: ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरु', 'शुक्र', 'शनि'], + dayNamesMin: ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरु', 'शुक्र', 'शनि'], + weekHeader: 'हफ्ता', + dateFormat: 'mm/dd/yy', + firstDay: 1, + isRTL: false, + showMonthAfterYear: false, + yearSuffix: ''}; + $.datepicker.setDefaults($.datepicker.regional['hi']); +}); diff --git a/ui/i18n/jquery.ui.datepicker-km.js b/ui/i18n/jquery.ui.datepicker-km.js new file mode 100644 index 000000000..f9c4e3a02 --- /dev/null +++ b/ui/i18n/jquery.ui.datepicker-km.js @@ -0,0 +1,23 @@ +/* Khmer initialisation for the jQuery calendar extension. */ +/* Written by Chandara Om (chandara.teacher@gmail.com). */ +jQuery(function($){ + $.datepicker.regional['km'] = { + closeText: 'ធ្វើរួច', + prevText: 'មុន', + nextText: 'បន្ទាប់', + currentText: 'ថ្ងៃនេះ', + monthNames: ['មករា','កុម្ភៈ','មីនា','មេសា','ឧសភា','មិថុនា', + 'កក្កដា','សីហា','កញ្ញា','តុលា','វិច្ឆិកា','ធ្នូ'], + monthNamesShort: ['មករា','កុម្ភៈ','មីនា','មេសា','ឧសភា','មិថុនា', + 'កក្កដា','សីហា','កញ្ញា','តុលា','វិច្ឆិកា','ធ្នូ'], + dayNames: ['អាទិត្យ', 'ចន្ទ', 'អង្គារ', 'ពុធ', 'ព្រហស្បតិ៍', 'សុក្រ', 'សៅរ៍'], + dayNamesShort: ['អា', 'ច', 'អ', 'ពុ', 'ព្រហ', 'សុ', 'សៅ'], + dayNamesMin: ['អា', 'ច', 'អ', 'ពុ', 'ព្រហ', 'សុ', 'សៅ'], + weekHeader: 'សប្ដាហ៍', + dateFormat: 'dd-mm-yy', + firstDay: 1, + isRTL: false, + showMonthAfterYear: false, + yearSuffix: ''}; + $.datepicker.setDefaults($.datepicker.regional['km']); +}); diff --git a/ui/jquery.effects.core.js b/ui/jquery.effects.core.js index 233b4f96d..b28e4c4ee 100644 --- a/ui/jquery.effects.core.js +++ b/ui/jquery.effects.core.js @@ -77,7 +77,7 @@ function getColor(elem, attr) { var color; do { - color = $.curCSS(elem, attr); + color = $.css(elem, attr); // Keep going until we find an element that has color, or we hit the body if ( color != "" && color !== "transparent" || $.nodeName(elem, "body") ) @@ -662,229 +662,49 @@ $.fn.extend({ /*********************************** EASING ***********************************/ /******************************************************************************/ -/* - * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ - * - * Uses the built in easing capabilities added In jQuery 1.1 - * to offer multiple easing options - * - * TERMS OF USE - jQuery Easing - * - * Open source under the BSD License. - * - * Copyright 2008 George McGinley Smith - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * Neither the name of the author nor the names of contributors may be used to endorse - * or promote products derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ +// based on easing equations from Robert Penner (http://www.robertpenner.com/easing) -// t: current time, b: begInnIng value, c: change In value, d: duration -$.easing.jswing = $.easing.swing; +var baseEasings = {}; -$.extend( $.easing, { - def: "easeOutQuad", - swing: function ( x, t, b, c, d ) { - return $.easing[ $.easing.def ]( x, t, b, c, d ); - }, - easeInQuad: function ( x, t, b, c, d ) { - return c * ( t /= d ) * t + b; - }, - easeOutQuad: function ( x, t, b, c, d ) { - return -c * ( t /= d ) * ( t - 2 ) + b; - }, - easeInOutQuad: function ( x, t, b, c, d ) { - if ( ( t /= d / 2 ) < 1 ) return c / 2 * t * t + b; - return -c / 2 * ( ( --t ) * ( t-2 ) - 1) + b; - }, - easeInCubic: function ( x, t, b, c, d ) { - return c * ( t /= d ) * t * t + b; - }, - easeOutCubic: function ( x, t, b, c, d ) { - return c * ( ( t = t / d - 1 ) * t * t + 1 ) + b; - }, - easeInOutCubic: function ( x, t, b, c, d ) { - if ( ( t /= d / 2 ) < 1 ) return c / 2 * t * t * t + b; - return c / 2 * ( ( t -= 2 ) * t * t + 2) + b; - }, - easeInQuart: function ( x, t, b, c, d ) { - return c * ( t /= d ) * t * t * t + b; - }, - easeOutQuart: function ( x, t, b, c, d ) { - return -c * ( ( t = t / d - 1 ) * t * t * t - 1) + b; - }, - easeInOutQuart: function ( x, t, b, c, d ) { - if ( (t /= d / 2 ) < 1 ) return c / 2 * t * t * t * t + b; - return -c / 2 * ( ( t -= 2 ) * t * t * t - 2) + b; - }, - easeInQuint: function ( x, t, b, c, d ) { - return c * ( t /= d ) * t * t * t * t + b; - }, - easeOutQuint: function ( x, t, b, c, d ) { - return c * ( ( t = t / d - 1 ) * t * t * t * t + 1) + b; - }, - easeInOutQuint: function ( x, t, b, c, d ) { - if ( ( t /= d / 2 ) < 1 ) return c / 2 * t * t * t * t * t + b; - return c / 2 * ( ( t -= 2 ) * t * t * t * t + 2) + b; - }, - easeInSine: function ( x, t, b, c, d ) { - return -c * Math.cos( t / d * ( Math.PI / 2 ) ) + c + b; - }, - easeOutSine: function ( x, t, b, c, d ) { - return c * Math.sin( t / d * ( Math.PI /2 ) ) + b; - }, - easeInOutSine: function ( x, t, b, c, d ) { - return -c / 2 * ( Math.cos( Math.PI * t / d ) - 1 ) + b; - }, - easeInExpo: function ( x, t, b, c, d ) { - return ( t==0 ) ? b : c * Math.pow( 2, 10 * ( t / d - 1) ) + b; - }, - easeOutExpo: function ( x, t, b, c, d ) { - return ( t==d ) ? b + c : c * ( -Math.pow( 2, -10 * t / d) + 1) + b; - }, - easeInOutExpo: function ( x, t, b, c, d ) { - if ( t==0 ) return b; - if ( t==d ) return b + c; - if ( ( t /= d / 2) < 1) return c / 2 * Math.pow( 2, 10 * (t - 1) ) + b; - return c / 2 * ( -Math.pow( 2, -10 * --t ) + 2 ) + b; - }, - easeInCirc: function ( x, t, b, c, d ) { - return -c * ( Math.sqrt( 1 - ( t /= d ) * t ) - 1 ) + b; - }, - easeOutCirc: function ( x, t, b, c, d ) { - return c * Math.sqrt( 1 - ( t = t / d - 1 ) * t ) + b; - }, - easeInOutCirc: function ( x, t, b, c, d ) { - if ( ( t /= d / 2) < 1 ) return -c / 2 * ( Math.sqrt( 1 - t * t ) - 1 ) + b; - return c / 2 * ( Math.sqrt( 1 - ( t -= 2 ) * t ) + 1 ) + b; - }, - easeInElastic: function ( x, t, b, c, d ) { - var s = 1.70158, - p = d * 0.3, - a = c; - if ( t == 0 ) return b; - if ( ( t /= d ) == 1 ) return b+c; - if ( a < Math.abs( c ) ) { - a = c; - s = p / 4; - } else { - s = p / ( 2 * Math.PI ) * Math.asin( c / a ); - } - return - ( a * Math.pow( 2, 10 * ( t -= 1 ) ) * Math.sin( ( t * d - s) * ( 2 * Math.PI ) / p ) ) + b; - }, - easeOutElastic: function ( x, t, b, c, d ) { - var s = 1.70158, - p = d * 0.3, - a = c; - if ( t == 0 ) return b; - if ( ( t /= d ) == 1 ) return b+c; - if ( a < Math.abs( c ) ) { - a = c; - s = p / 4; - } else { - s = p / ( 2 * Math.PI ) * Math.asin( c / a ); - } - return a * Math.pow( 2, -10 * t ) * Math.sin( ( t * d - s ) * ( 2 * Math.PI ) / p ) + c + b; - }, - easeInOutElastic: function ( x, t, b, c, d ) { - var s = 1.70158, - p = d * ( 0.3 * 1.5 ), - a = c; - if ( t == 0 ) return b; - if ( ( t /= d / 2 ) == 2 ) return b+c; - if ( a < Math.abs( c ) ) { - a = c; - s = p / 4; - } else { - s = p / ( 2 * Math.PI ) * Math.asin( c / a ); - } - if ( t < 1 ) return -.5 * ( a * Math.pow( 2, 10 * ( t -= 1 ) ) * Math.sin( ( t * d - s ) * ( 2 * Math.PI ) / p ) ) + b; - return a * Math.pow( 2, -10 * ( t -= 1 ) ) * Math.sin( ( t * d - s ) * ( 2 * Math.PI ) / p ) *.5 + c + b; - }, - easeInBack: function ( x, t, b, c, d, s ) { - if ( s == undefined ) s = 1.70158; - return c * ( t /= d ) * t * ( ( s+1 ) * t - s ) + b; - }, - easeOutBack: function ( x, t, b, c, d, s ) { - if ( s == undefined ) s = 1.70158; - return c * ( ( t = t / d - 1 ) * t * ( ( s + 1 ) * t + s) + 1) + b; +$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) { + baseEasings[ name ] = function( p ) { + return Math.pow( p, i + 2 ); + }; +}); + +$.extend( baseEasings, { + Sine: function ( p ) { + return 1 - Math.cos( p * Math.PI / 2 ); }, - easeInOutBack: function ( x, t, b, c, d, s ) { - if ( s == undefined ) s = 1.70158; - if ( ( t /= d / 2 ) < 1 ) return c / 2 * ( t * t * ( ( ( s *= 1.525 ) + 1 ) * t - s ) ) + b; - return c / 2 * ( ( t -= 2 ) * t * ( ( ( s *= 1.525 ) + 1 ) * t + s) + 2) + b; + Circ: function ( p ) { + return 1 - Math.sqrt( 1 - p * p ); }, - easeInBounce: function ( x, t, b, c, d ) { - return c - $.easing.easeOutBounce( x, d - t, 0, c, d ) + b; + Elastic: function( p ) { + return p === 0 || p === 1 ? p : + -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 ); }, - easeOutBounce: function ( x, t, b, c, d ) { - if ( ( t /= d ) < ( 1 / 2.75 ) ) { - return c * ( 7.5625 * t * t ) + b; - } else if ( t < ( 2 / 2.75 ) ) { - return c * ( 7.5625 * ( t -= ( 1.5 / 2.75 ) ) * t + .75 ) + b; - } else if ( t < ( 2.5 / 2.75 ) ) { - return c * ( 7.5625 * ( t -= ( 2.25/ 2.75 ) ) * t + .9375 ) + b; - } else { - return c * ( 7.5625 * ( t -= ( 2.625 / 2.75 ) ) * t + .984375 ) + b; - } + Back: function( p ) { + return p * p * ( 3 * p - 2 ); }, - easeInOutBounce: function ( x, t, b, c, d ) { - if ( t < d / 2 ) return $.easing.easeInBounce( x, t * 2, 0, c, d ) * .5 + b; - return $.easing.easeOutBounce( x, t * 2 - d, 0, c, d ) * .5 + c * .5 + b; + Bounce: function ( p ) { + var pow2, + bounce = 4; + + while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} + return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); } }); -/* - * - * TERMS OF USE - EASING EQUATIONS - * - * Open source under the BSD License. - * - * Copyright 2001 Robert Penner - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * Neither the name of the author nor the names of contributors may be used to endorse - * or promote products derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ +$.each( baseEasings, function( name, easeIn ) { + $.easing[ "easeIn" + name ] = easeIn; + $.easing[ "easeOut" + name ] = function( p ) { + return 1 - easeIn( 1 - p ); + }; + $.easing[ "easeInOut" + name ] = function( p ) { + return p < .5 ? + easeIn( p * 2 ) / 2 : + easeIn( p * -2 + 2 ) / -2 + 1; + }; +}); })(jQuery); diff --git a/ui/jquery.ui.accordion.js b/ui/jquery.ui.accordion.js index 127099d59..8731c17ca 100644 --- a/ui/jquery.ui.accordion.js +++ b/ui/jquery.ui.accordion.js @@ -13,12 +13,11 @@ */ (function( $, undefined ) { -// TODO: use ui-accordion-header-active class and fix styling $.widget( "ui.accordion", { version: "@VERSION", options: { active: 0, - animated: "slide", + animate: {}, collapsible: false, event: "click", header: "> li > :first-child,> :not(li):even", @@ -34,19 +33,18 @@ $.widget( "ui.accordion", { }, _create: function() { - var self = this, - options = self.options; + var options = this.options; - self.lastToggle = {}; - self.element.addClass( "ui-accordion ui-widget ui-helper-reset" ); + this.prevShow = this.prevHide = $(); + this.element.addClass( "ui-accordion ui-widget ui-helper-reset" ); - self.headers = self.element.find( options.header ) + this.headers = this.element.find( options.header ) .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" ); - self._hoverable( self.headers ); - self._focusable( self.headers ); - self.headers.find( ":first-child" ).addClass( "ui-accordion-heading" ); + this._hoverable( this.headers ); + this._focusable( this.headers ); + this.headers.find( ":first-child" ).addClass( "ui-accordion-heading" ); - self.headers.next() + this.headers.next() .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ); // don't allow collapsible: false and active: false @@ -57,26 +55,27 @@ $.widget( "ui.accordion", { if ( options.active < 0 ) { options.active += this.headers.length; } - self.active = self._findActive( options.active ) - .addClass( "ui-state-default ui-state-active" ) + this.active = this._findActive( options.active ) + .addClass( "ui-accordion-header-active ui-state-active" ) .toggleClass( "ui-corner-all" ) .toggleClass( "ui-corner-top" ); - self.active.next().addClass( "ui-accordion-content-active" ); + this.active.next().addClass( "ui-accordion-content-active" ); - self._createIcons(); - self.refresh(); + this._createIcons(); + this.originalHeight = this.element[0].style.height; + this.refresh(); // ARIA - self.element.attr( "role", "tablist" ); + this.element.attr( "role", "tablist" ); - self.headers + this.headers .attr( "role", "tab" ) - .bind( "keydown.accordion", $.proxy( self, "_keydown" ) ) + .bind( "keydown.accordion", $.proxy( this, "_keydown" ) ) .next() .attr( "role", "tabpanel" ); - self.headers - .not( self.active ) + this.headers + .not( this.active ) .attr({ "aria-expanded": "false", "aria-selected": "false", @@ -86,10 +85,10 @@ $.widget( "ui.accordion", { .hide(); // make sure at least one header is in the tab order - if ( !self.active.length ) { - self.headers.eq( 0 ).attr( "tabIndex", 0 ); + if ( !this.active.length ) { + this.headers.eq( 0 ).attr( "tabIndex", 0 ); } else { - self.active.attr({ + this.active.attr({ "aria-expanded": "true", "aria-selected": "true", tabIndex: 0 @@ -98,12 +97,19 @@ $.widget( "ui.accordion", { // only need links in tab order for Safari if ( !$.browser.safari ) { - self.headers.find( "a" ).attr( "tabIndex", -1 ); + this.headers.find( "a" ).attr( "tabIndex", -1 ); } this._setupEvents( options.event ); }, + _getCreateEventData: function() { + return { + header: this.active, + content: !this.active.length ? $() : this.active.next() + }; + }, + _createIcons: function() { var icons = this.options.icons; if ( icons ) { @@ -113,13 +119,15 @@ $.widget( "ui.accordion", { this.active.children( ".ui-accordion-header-icon" ) .removeClass( icons.header ) .addClass( icons.activeHeader ); - this.element.addClass( "ui-accordion-icons" ); + this.headers.addClass( "ui-accordion-icons" ); } }, _destroyIcons: function() { - this.headers.children( ".ui-accordion-header-icon" ).remove(); - this.element.removeClass( "ui-accordion-icons" ); + this.headers + .removeClass( "ui-accordion-icons" ) + .children( ".ui-accordion-header-icon" ) + .remove(); }, _destroy: function() { @@ -131,7 +139,7 @@ $.widget( "ui.accordion", { // clean up headers this.headers .unbind( ".accordion" ) - .removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" ) + .removeClass( "ui-accordion-header ui-accordion-header-active ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" ) .removeAttr( "role" ) .removeAttr( "aria-expanded" ) .removeAttr( "aria-selected" ) @@ -149,6 +157,7 @@ $.widget( "ui.accordion", { .removeAttr( "role" ) .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" ); if ( this.options.heightStyle !== "content" ) { + this.element.css( "height", this.originalHeight ); contents.css( "height", "" ); } }, @@ -222,12 +231,12 @@ $.widget( "ui.accordion", { }, refresh: function() { - var options = this.options, + var heightStyle = this.options.heightStyle, parent = this.element.parent(), maxHeight, overflow; - if ( options.heightStyle === "fill" ) { + if ( heightStyle === "fill" ) { // IE 6 treats height like minHeight, so we need to turn off overflow // in order to get a reliable height // we use the minHeight support test because we assume that only @@ -260,7 +269,7 @@ $.widget( "ui.accordion", { $( this ).innerHeight() + $( this ).height() ) ); }) .css( "overflow", "auto" ); - } else if ( options.heightStyle === "auto" ) { + } else if ( heightStyle === "auto" ) { maxHeight = 0; this.headers.next() .each(function() { @@ -269,7 +278,9 @@ $.widget( "ui.accordion", { .height( maxHeight ); } - return this; + if ( heightStyle !== "content" ) { + this.element.height( this.element.height() ); + } }, _activate: function( index ) { @@ -335,15 +346,15 @@ $.widget( "ui.accordion", { // switch classes active - .removeClass( "ui-state-active ui-corner-top" ) - .addClass( "ui-state-default ui-corner-all" ) + .removeClass( "ui-accordion-header-active ui-state-active ui-corner-top" ) + .addClass( "ui-corner-all" ) .children( ".ui-accordion-header-icon" ) .removeClass( options.icons.activeHeader ) .addClass( options.icons.header ); if ( !clickedIsActive ) { clicked - .removeClass( "ui-state-default ui-corner-all" ) - .addClass( "ui-state-active ui-corner-top" ) + .removeClass( "ui-corner-all" ) + .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ) .children( ".ui-accordion-header-icon" ) .removeClass( options.icons.header ) .addClass( options.icons.activeHeader ); @@ -354,41 +365,20 @@ $.widget( "ui.accordion", { }, _toggle: function( data ) { - var self = this, - options = self.options, - toShow = data.newContent, - toHide = data.oldContent; - - function complete() { - self._completed( data ); - } + var toShow = data.newContent, + toHide = this.prevShow.length ? this.prevShow : data.oldContent; - if ( options.animated ) { - var animations = $.ui.accordion.animations, - animation = options.animated, - additional; - - if ( !animations[ animation ] ) { - additional = { - easing: $.easing[ animation ] ? animation : "slide", - duration: 700 - }; - animation = "slide"; - } + // handle activating a panel during the animation for another activation + this.prevShow.add( this.prevHide ).stop( true, true ); + this.prevShow = toShow; + this.prevHide = toHide; - animations[ animation ]({ - widget: self, - toShow: toShow, - toHide: toHide, - prevShow: self.lastToggle.toShow, - prevHide: self.lastToggle.toHide, - complete: complete, - down: toShow.length && ( !toHide.length || ( toShow.index() < toHide.index() ) ) - }, additional ); + if ( this.options.animate ) { + this._animate( toShow, toHide, data ); } else { toHide.hide(); toShow.show(); - complete(); + this._completed( data ); } // TODO assert that the blur and focus triggers are really necessary, remove otherwise @@ -408,17 +398,51 @@ $.widget( "ui.accordion", { .focus(); }, + _animate: function( toShow, toHide, data ) { + var total, easing, duration, + that = this, + down = toShow.length && + ( !toHide.length || ( toShow.index() < toHide.index() ) ), + animate = this.options.animate || {}, + options = down && animate.down || animate, + complete = function() { + toShow.removeData( "accordionHeight" ); + that._completed( data ); + }; + + if ( typeof options === "number" ) { + duration = options; + } + if ( typeof options === "string" ) { + easing = options; + } + // fall back from options to animation in case of partial down settings + easing = easing || options.easing || animate.easing; + duration = duration || options.duration || animate.duration; + + if ( !toHide.size() ) { + return toShow.animate( showProps, duration, easing, complete ); + } + if ( !toShow.size() ) { + return toHide.animate( hideProps, duration, easing, complete ); + } + + total = toShow.show().outerHeight(); + toHide.animate( hideProps, duration, easing ); + toShow + .hide() + .data( "accordionHeight", { + total: total, + toHide: toHide + }) + .animate( this.options.heightStyle === "content" ? showProps : showPropsAdjust, + duration, easing, complete ); + }, + _completed: function( data ) { var toShow = data.newContent, toHide = data.oldContent; - if ( this.options.heightStyle === "content" ) { - toShow.add( toHide ).css({ - height: "", - overflow: "" - }); - } - // other classes are removed before the animation; this one needs to stay until completed toHide.removeClass( "ui-accordion-content-active" ); // Work around for rendering bug in IE (#5421) @@ -430,113 +454,19 @@ $.widget( "ui.accordion", { } }); -$.extend( $.ui.accordion, { - animations: { - slide: function( options, additions ) { - if ( options.prevShow || options.prevHide ) { - options.prevHide.stop( true, true ); - options.toHide = options.prevShow; - } - - var showOverflow = options.toShow.css( "overflow" ), - hideOverflow = options.toHide.css( "overflow" ), - percentDone = 0, - showProps = {}, - hideProps = {}, - fxAttrs = [ "height", "paddingTop", "paddingBottom" ], - originalWidth; - options = $.extend({ - easing: "swing", - duration: 300 - }, options, additions ); - - options.widget.lastToggle = options; - - if ( !options.toHide.size() ) { - originalWidth = options.toShow[0].style.width; - options.toShow - .show() - .width( options.toShow.width() ) - .hide() - .animate({ - height: "show", - paddingTop: "show", - paddingBottom: "show" - }, { - duration: options.duration, - easing: options.easing, - complete: function() { - options.toShow.width( originalWidth ); - options.complete(); - } - }); - return; - } - if ( !options.toShow.size() ) { - options.toHide.animate({ - height: "hide", - paddingTop: "hide", - paddingBottom: "hide" - }, options ); - return; - } - // fix width before calculating height of hidden element - var s = options.toShow; - originalWidth = s[0].style.width; - s.width( s.parent().width() - - parseFloat( s.css( "paddingLeft" ) ) - - parseFloat( s.css( "paddingRight" ) ) - - ( parseFloat( s.css( "borderLeftWidth" ) ) || 0 ) - - ( parseFloat( s.css( "borderRightWidth" ) ) || 0 ) ); - - $.each( fxAttrs, function( i, prop ) { - hideProps[ prop ] = "hide"; - - var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ ), - // work around bug when a panel has no height - #7335 - propVal = prop === "height" && parts[ 1 ] === "0" ? 1 : parts[ 1 ]; - showProps[ prop ] = { - value: propVal, - unit: parts[ 2 ] || "px" - }; - }); - options.toShow.css({ height: 0, overflow: "hidden" }).show(); - options.toHide - .filter( ":hidden" ) - .each( options.complete ) - .end() - .filter( ":visible" ) - .animate( hideProps, { - step: function( now, settings ) { - if ( settings.prop == "height" || settings.prop == "paddingTop" || settings.prop == "paddingBottom" ) { - percentDone = ( settings.end - settings.start === 0 ) ? 0 : - ( settings.now - settings.start ) / ( settings.end - settings.start ); - } - - options.toShow[ 0 ].style[ settings.prop ] = - ( percentDone * showProps[ settings.prop ].value ) - + showProps[ settings.prop ].unit; - }, - duration: options.duration, - easing: options.easing, - complete: function() { - options.toShow.css({ - width: originalWidth, - overflow: showOverflow - }); - options.toHide.css( "overflow", hideOverflow ); - options.complete(); - } - }); - }, - bounceslide: function( options ) { - this.slide( options, { - easing: options.down ? "easeOutBounce" : "swing", - duration: options.down ? 1000 : 200 - }); - } - } -}); +$.fx.step.accordionHeight = function( fx ) { + var elem = $( fx.elem ), + data = elem.data( "accordionHeight" ); + elem.height( data.total - elem.outerHeight() - data.toHide.outerHeight() + elem.height() ); +}; +var hideProps = {}, + showProps = {}, + showPropsAdjust = {}; +hideProps.height = hideProps.paddingTop = hideProps.paddingBottom = + hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide"; +showProps.height = showProps.paddingTop = showProps.paddingBottom = + showProps.borderTopWidth = showProps.borderBottomWidth = "show"; +$.extend( showPropsAdjust, showProps, { accordionHeight: "show" } ); @@ -554,7 +484,7 @@ if ( $.uiBackCompat !== false ) { var _create = prototype._create; prototype._create = function() { if ( this.options.navigation ) { - var self = this, + var that = this, headers = this.element.find( this.options.header ), content = headers.next(), current = headers.add( content ) @@ -564,7 +494,7 @@ if ( $.uiBackCompat !== false ) { if ( current ) { headers.add( content ).each( function( index ) { if ( $.contains( this, current ) ) { - self.options.active = Math.floor( index / 2 ); + that.options.active = Math.floor( index / 2 ); return false; } }); @@ -680,6 +610,40 @@ if ( $.uiBackCompat !== false ) { return ret; }; }( jQuery, jQuery.ui.accordion.prototype ) ); + + // animated option + // NOTE: this only provides support for "slide", "bounceslide", and easings + // not the full $.ui.accordion.animations API + (function( $, prototype ) { + $.extend( prototype.options, { + animate: null, + animated: "slide" + }); + + var _create = prototype._create; + prototype._create = function() { + var options = this.options; + if ( options.animate === null ) { + if ( !options.animated ) { + options.animate = false; + } else if ( options.animated === "slide" ) { + options.animate = 300; + } else if ( options.animated === "bounceslide" ) { + options.animate = { + duration: 200, + down: { + easing: "easeOutBounce", + duration: 1000 + } + } + } else { + options.animate = options.animated; + } + } + + _create.call( this ); + }; + }( jQuery, jQuery.ui.accordion.prototype ) ); } })( jQuery ); diff --git a/ui/jquery.ui.autocomplete.js b/ui/jquery.ui.autocomplete.js index c054ba2dd..e261b9147 100644 --- a/ui/jquery.ui.autocomplete.js +++ b/ui/jquery.ui.autocomplete.js @@ -176,13 +176,14 @@ $.widget( "ui.autocomplete", { return; } + if ( self.cancelBlur ) { + delete self.cancelBlur; + return; + } + clearTimeout( self.searching ); - self.cancelSearch = true; - // clicks on the menu (or a button to trigger a search) will cause a blur event - self.closing = setTimeout(function() { - self.close( event ); - self._change( event ); - }, 150 ); + self.close( event ); + self._change( event ); }); this._initSource(); this.response = function() { @@ -193,6 +194,16 @@ $.widget( "ui.autocomplete", { .appendTo( this.document.find( this.options.appendTo || "body" )[0] ) // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown) .mousedown(function( event ) { + // prevent moving focus out of the text field + event.preventDefault(); + + // IE doesn't prevent moving focus even with event.preventDefault() + // so we set a flag to know when we should ignore the blur event + self.cancelBlur = true; + setTimeout(function() { + delete self.cancelBlur; + }, 1 ); + // clicking on the scrollbar causes focus to shift to the body // but we can't detect a mouseup or a click immediately afterward // so we have to track the next mousedown and close the menu if @@ -209,11 +220,6 @@ $.widget( "ui.autocomplete", { }); }, 1 ); } - - // use another timeout to make sure the blur-event-handler on the input was already triggered - setTimeout(function() { - clearTimeout( self.closing ); - }, 13); }) .menu({ // custom key handling for now @@ -316,7 +322,9 @@ $.widget( "ui.autocomplete", { url: url, data: request, dataType: "json", - autocompleteRequest: ++requestIndex, + context: { + autocompleteRequest: ++requestIndex + }, success: function( data, status ) { if ( this.autocompleteRequest === requestIndex ) { response( data ); @@ -356,7 +364,6 @@ $.widget( "ui.autocomplete", { return this.close( event ); } - clearTimeout( this.closing ); if ( this._trigger( "search", event ) === false ) { return; } @@ -381,7 +388,8 @@ $.widget( "ui.autocomplete", { this._suggest( content ); this._trigger( "open" ); } else { - this.close(); + // use ._close() instead of .close() so we don't cancel future searches + this._close(); } this.pending--; if ( !this.pending ) { @@ -390,6 +398,11 @@ $.widget( "ui.autocomplete", { }, close: function( event ) { + this.cancelSearch = true; + this._close( event ); + }, + + _close: function( event ) { clearTimeout( this.closing ); if ( this.menu.element.is(":visible") ) { this.menu.element.hide(); diff --git a/ui/jquery.ui.button.js b/ui/jquery.ui.button.js index 1c3cf2c64..25f1668a5 100644 --- a/ui/jquery.ui.button.js +++ b/ui/jquery.ui.button.js @@ -66,7 +66,7 @@ $.widget( "ui.button", { this._determineButtonType(); this.hasTitle = !!this.buttonElement.attr( "title" ); - var self = this, + var that = this, options = this.options, toggleButton = this.type === "checkbox" || this.type === "radio", hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ), @@ -104,10 +104,10 @@ $.widget( "ui.button", { this.element .bind( "focus.button", function() { // no need to check disabled, focus won't be triggered anyway - self.buttonElement.addClass( focusClass ); + that.buttonElement.addClass( focusClass ); }) .bind( "blur.button", function() { - self.buttonElement.removeClass( focusClass ); + that.buttonElement.removeClass( focusClass ); }); if ( toggleButton ) { @@ -115,7 +115,7 @@ $.widget( "ui.button", { if ( clickDragged ) { return; } - self.refresh(); + that.refresh(); }); // if mouse moves between mousedown and mouseup (drag) set clickDragged flag // prevents issue where button state changes but checkbox/radio checked state @@ -145,7 +145,7 @@ $.widget( "ui.button", { return false; } $( this ).toggleClass( "ui-state-active" ); - self.buttonElement.attr( "aria-pressed", self.element[0].checked ); + that.buttonElement.attr( "aria-pressed", that.element[0].checked ); }); } else if ( this.type === "radio" ) { this.buttonElement.bind( "click.button", function() { @@ -153,9 +153,9 @@ $.widget( "ui.button", { return false; } $( this ).addClass( "ui-state-active" ); - self.buttonElement.attr( "aria-pressed", "true" ); + that.buttonElement.attr( "aria-pressed", "true" ); - var radio = self.element[ 0 ]; + var radio = that.element[ 0 ]; radioGroup( radio ) .not( radio ) .map(function() { @@ -172,7 +172,7 @@ $.widget( "ui.button", { } $( this ).addClass( "ui-state-active" ); lastActive = this; - self.document.one( "mouseup", function() { + that.document.one( "mouseup", function() { lastActive = null; }); }) diff --git a/ui/jquery.ui.core.js b/ui/jquery.ui.core.js index d777d6d49..5f0414ec8 100644 --- a/ui/jquery.ui.core.js +++ b/ui/jquery.ui.core.js @@ -21,23 +21,15 @@ $.extend( $.ui, { version: "@VERSION", keyCode: { - ALT: 18, BACKSPACE: 8, - CAPS_LOCK: 20, COMMA: 188, - COMMAND: 91, - COMMAND_LEFT: 91, // COMMAND - COMMAND_RIGHT: 93, - CONTROL: 17, DELETE: 46, DOWN: 40, END: 35, ENTER: 13, ESCAPE: 27, HOME: 36, - INSERT: 45, LEFT: 37, - MENU: 93, // COMMAND_RIGHT NUMPAD_ADD: 107, NUMPAD_DECIMAL: 110, NUMPAD_DIVIDE: 111, @@ -48,11 +40,9 @@ $.extend( $.ui, { PAGE_UP: 33, PERIOD: 190, RIGHT: 39, - SHIFT: 16, SPACE: 32, TAB: 9, - UP: 38, - WINDOWS: 91 // COMMAND + UP: 38 } }); @@ -77,11 +67,11 @@ $.fn.extend({ var scrollParent; if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) { scrollParent = this.parents().filter(function() { - return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); + return (/(relative|absolute|fixed)/).test($.css(this,'position')) && (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x')); }).eq(0); } else { scrollParent = this.parents().filter(function() { - return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); + return (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x')); }).eq(0); } @@ -141,12 +131,12 @@ $.each( [ "Width", "Height" ], function( i, name ) { function reduce( elem, size, border, margin ) { $.each( side, function() { - size -= parseFloat( $.curCSS( elem, "padding" + this, true ) ) || 0; + size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; if ( border ) { - size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true ) ) || 0; + size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; } if ( margin ) { - size -= parseFloat( $.curCSS( elem, "margin" + this, true ) ) || 0; + size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; } }); return size; @@ -197,7 +187,7 @@ function focusable( element, isTabIndexNotNaN ) { function visible( element ) { return !$( element ).parents().andSelf().filter(function() { - return $.curCSS( this, "visibility" ) === "hidden" || + return $.css( this, "visibility" ) === "hidden" || $.expr.filters.hidden( this ); }).length; } diff --git a/ui/jquery.ui.datepicker.js b/ui/jquery.ui.datepicker.js index 5915d4027..07aeeadd0 100644 --- a/ui/jquery.ui.datepicker.js +++ b/ui/jquery.ui.datepicker.js @@ -711,8 +711,7 @@ $.extend(Datepicker.prototype, { /* Generate the date picker content. */ _updateDatepicker: function(inst) { - var self = this; - self.maxRows = 4; //Reset the max number of rows being displayed (see #7043) + this.maxRows = 4; //Reset the max number of rows being displayed (see #7043) var borders = $.datepicker._getBorders(inst.dpDiv); instActive = inst; // for delegate hover events inst.dpDiv.empty().append(this._generateHTML(inst)); @@ -802,10 +801,10 @@ $.extend(Datepicker.prototype, { if (this._datepickerShowing) { var showAnim = this._get(inst, 'showAnim'); var duration = this._get(inst, 'duration'); - var self = this; + var that = this; var postProcess = function() { $.datepicker._tidyDialog(inst); - self._curInst = null; + that._curInst = null; }; // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed @@ -849,7 +848,7 @@ $.extend(Datepicker.prototype, { if ( ( ( $target[0].id != $.datepicker._mainDivId && $target.parents('#' + $.datepicker._mainDivId).length == 0 && !$target.hasClass($.datepicker.markerClassName) && - !$target.hasClass($.datepicker._triggerClass) && + !$target.closest("." + $.datepicker._triggerClass).length && $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) || ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst != inst ) ) $.datepicker._hideDatepicker(); diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 92dd13c0d..ccc1fe81b 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -212,10 +212,10 @@ $.widget("ui.draggable", $.ui.mouse, { return false; 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))) { - var self = this; + var that = this; $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { - if(self._trigger("stop", event) !== false) { - self._clear(); + if(that._trigger("stop", event) !== false) { + that._clear(); } }); } else { @@ -558,7 +558,7 @@ $.ui.plugin.add("draggable", "connectToSortable", { }, drag: function(event, ui) { - var inst = $(this).data("draggable"), self = this; + var inst = $(this).data("draggable"), that = this; var checkPos = function(o) { var dyClick = this.offset.click.top, dxClick = this.offset.click.left; @@ -585,7 +585,7 @@ $.ui.plugin.add("draggable", "connectToSortable", { //Now we fake the start of dragging for the sortable instance, //by cloning the list group item, appending it to the sortable and using it as inst.currentItem //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) - this.instance.currentItem = $(self).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true); + this.instance.currentItem = $(that).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true); this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it this.instance.options.helper = function() { return ui.helper[0]; }; diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index 83ea3c3c0..42829c2a1 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -45,6 +45,9 @@ $.widget( "ui.menu", { event.preventDefault(); } }, this)); + if ( this.options.disabled ) { + this.element.addClass( "ui-state-disabled" ); + } this._bind({ // Prevent focus from sticking to links inside menu after clicking // them (focus should always stay on UL during navigation). @@ -53,13 +56,16 @@ $.widget( "ui.menu", { }, "click .ui-menu-item:has(a)": function( event ) { event.stopImmediatePropagation(); - this.select( event ); - // Redirect focus to the menu with a delay for firefox - this._delay( function() { - if ( !this.element.is(":focus") ) { - this.element.focus(); - } - }, 20); + //Don't select disabled menu items + if ( !$( event.target ).closest( ".ui-menu-item" ).is( ".ui-state-disabled" ) ) { + this.select( event ); + // Redirect focus to the menu with a delay for firefox + this._delay( function() { + if ( !this.element.is(":focus") ) { + this.element.focus(); + } + }, 20); + } }, "mouseover .ui-menu-item": function( event ) { event.stopImmediatePropagation(); @@ -71,7 +77,7 @@ $.widget( "ui.menu", { "mouseleave": "collapseAll", "mouseleave .ui-menu": "collapseAll", "focus": function( event ) { - var firstItem = this.element.children( ".ui-menu-item" ).eq( 0 ); + var firstItem = this.element.children( ".ui-menu-item" ).not( ".ui-state-disabled" ).eq( 0 ); if ( this._hasScroll() && !this.active ) { var menu = this.element; menu.children().each( function() { @@ -280,8 +286,8 @@ $.widget( "ui.menu", { this.blur( event ); if ( this._hasScroll() ) { - var borderTop = parseFloat( $.curCSS( this.activeMenu[0], "borderTopWidth", true ) ) || 0, - paddingTop = parseFloat( $.curCSS( this.activeMenu[0], "paddingTop", true ) ) || 0, + var borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0, + paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0, offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop, scroll = this.activeMenu.scrollTop(), elementHeight = this.activeMenu.height(), @@ -411,7 +417,7 @@ $.widget( "ui.menu", { }, expand: function( event ) { - var newItem = this.active && this.active.children( ".ui-menu " ).children( ".ui-menu-item" ).first(); + var newItem = this.active && this.active.children( ".ui-menu " ).children( ".ui-menu-item" ).not( ".ui-state-disabled" ).first(); if ( newItem && newItem.length ) { this._open( newItem.parent() ); @@ -424,11 +430,11 @@ $.widget( "ui.menu", { } }, - next: function(event) { + next: function( event ) { this._move( "next", "first", event ); }, - previous: function(event) { + previous: function( event ) { this._move( "prev", "last", event ); }, @@ -441,28 +447,27 @@ $.widget( "ui.menu", { }, _move: function( direction, filter, event ) { - if ( !this.active ) { - this.focus( event, this.activeMenu.children( ".ui-menu-item" )[ filter ]() ); - return; - } - var next; - if ( direction === "first" || direction === "last" ) { - next = this.active[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ).eq( -1 ); - } else { - next = this.active[ direction + "All" ]( ".ui-menu-item" ).eq( 0 ); + if ( this.active ) { + if ( direction === "first" || direction === "last" ) { + next = this.active[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ).not( ".ui-state-disabled" ).eq( -1 ); + } else { + next = this.active[ direction + "All" ]( ".ui-menu-item" ).not( ".ui-state-disabled" ).eq( 0 ); + } + } + if ( !next || !next.length || !this.active ) { + next = this.activeMenu.children( ".ui-menu-item" )[ filter ](); } - if ( next.length ) { - this.focus( event, next ); - } else { - this.focus( event, this.activeMenu.children( ".ui-menu-item" )[ filter ]() ); + this.focus( event, next ); + if ( next.is( ".ui-state-disabled" ) ) { + this._move( direction, filter, event ); } }, nextPage: function( event ) { if ( !this.active ) { - this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() ); + this._move( "next", "first", event ); return; } if ( this.isLastItem() ) { @@ -472,21 +477,21 @@ $.widget( "ui.menu", { var base = this.active.offset().top, height = this.element.height(), result; - this.active.nextAll( ".ui-menu-item" ).each( function() { + this.active.nextAll( ".ui-menu-item" ).not( ".ui-state-disabled" ).each( function() { result = $( this ); return $( this ).offset().top - base - height < 0; }); this.focus( event, result ); } else { - this.focus( event, this.activeMenu.children( ".ui-menu-item" ) + this.focus( event, this.activeMenu.children( ".ui-menu-item" ).not( ".ui-state-disabled" ) [ !this.active ? "first" : "last" ]() ); } }, previousPage: function( event ) { if ( !this.active ) { - this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() ); + this._move( "next", "first", event ); return; } if ( this.isFirstItem() ) { @@ -496,14 +501,14 @@ $.widget( "ui.menu", { var base = this.active.offset().top, height = this.element.height(), result; - this.active.prevAll( ".ui-menu-item" ).each( function() { + this.active.prevAll( ".ui-menu-item" ).not( ".ui-state-disabled" ).each( function() { result = $( this ); return $(this).offset().top - base + height > 0; }); this.focus( event, result ); } else { - this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() ); + this.focus( event, this.activeMenu.children( ".ui-menu-item" ).not( ".ui-state-disabled" ).first() ); } }, diff --git a/ui/jquery.ui.mouse.js b/ui/jquery.ui.mouse.js index 888fbedfe..b1826aa23 100644 --- a/ui/jquery.ui.mouse.js +++ b/ui/jquery.ui.mouse.js @@ -25,15 +25,15 @@ $.widget("ui.mouse", { delay: 0 }, _mouseInit: function() { - var self = this; + var that = this; this.element .bind('mousedown.'+this.widgetName, function(event) { - return self._mouseDown(event); + return that._mouseDown(event); }) .bind('click.'+this.widgetName, function(event) { - if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) { - $.removeData(event.target, self.widgetName + '.preventClickEvent'); + if (true === $.data(event.target, that.widgetName + '.preventClickEvent')) { + $.removeData(event.target, that.widgetName + '.preventClickEvent'); event.stopImmediatePropagation(); return false; } @@ -57,7 +57,7 @@ $.widget("ui.mouse", { this._mouseDownEvent = event; - var self = this, + var that = this, btnIsLeft = (event.which == 1), // event.target.nodeName works around a bug in IE 8 with // disabled inputs (#7620) @@ -69,7 +69,7 @@ $.widget("ui.mouse", { this.mouseDelayMet = !this.options.delay; if (!this.mouseDelayMet) { this._mouseDelayTimer = setTimeout(function() { - self.mouseDelayMet = true; + that.mouseDelayMet = true; }, this.options.delay); } @@ -88,10 +88,10 @@ $.widget("ui.mouse", { // these delegates are required to keep context this._mouseMoveDelegate = function(event) { - return self._mouseMove(event); + return that._mouseMove(event); }; this._mouseUpDelegate = function(event) { - return self._mouseUp(event); + return that._mouseUp(event); }; $(document) .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate) diff --git a/ui/jquery.ui.position.js b/ui/jquery.ui.position.js index 00976bf79..b8bb2c883 100644 --- a/ui/jquery.ui.position.js +++ b/ui/jquery.ui.position.js @@ -152,13 +152,13 @@ $.fn.position = function( options ) { var elem = $( this ), elemWidth = elem.outerWidth(), elemHeight = elem.outerHeight(), - marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0, - marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0, + marginLeft = parseInt( $.css( this, "marginLeft" ) ) || 0, + marginTop = parseInt( $.css( this, "marginTop" ) ) || 0, scrollInfo = $.position.getScrollInfo( within ), collisionWidth = elemWidth + marginLeft + - ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ) + scrollInfo.width, + ( parseInt( $.css( this, "marginRight" ) ) || 0 ) + scrollInfo.width, collisionHeight = elemHeight + marginTop + - ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ) + scrollInfo.height, + ( parseInt( $.css( this, "marginBottom" ) ) || 0 ) + scrollInfo.height, position = $.extend( {}, basePosition ), myOffset = [ parseInt( offsets.my[ 0 ], 10 ) * @@ -414,7 +414,7 @@ $.ui.position = { // fraction support test (function () { - var testElement, testElementParent, testElementStyle, offsetLeft, i + var testElement, testElementParent, testElementStyle, offsetLeft, i, body = document.getElementsByTagName( "body" )[ 0 ], div = document.createElement( "div" ); diff --git a/ui/jquery.ui.resizable.js b/ui/jquery.ui.resizable.js index baca11f83..d1745a0c7 100644 --- a/ui/jquery.ui.resizable.js +++ b/ui/jquery.ui.resizable.js @@ -51,10 +51,6 @@ $.widget("ui.resizable", $.ui.mouse, { //Wrap the element if it cannot hold child nodes if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) { - //Opera fix for relative positioning - if (/relative/.test(this.element.css('position')) && $.browser.opera) - this.element.css({ position: 'relative', top: 'auto', left: 'auto' }); - //Create a wrapper element and set the wrapper to the new current internal element this.element.wrap( $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({ @@ -248,10 +244,6 @@ $.widget("ui.resizable", $.ui.mouse, { el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left }); } - //Opera fixing relative position - if ($.browser.opera && (/relative/).test(el.css('position'))) - el.css({ position: 'relative', top: 'auto', left: 'auto' }); - this._renderProxy(); var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top')); @@ -563,8 +555,7 @@ $.ui.plugin.add("resizable", "alsoResize", { var el = $(this); el.data("resizable-alsoresize", { width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), - left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10), - position: el.css('position') // to reset Opera on stop() + left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10) }); }); }; @@ -596,12 +587,6 @@ $.ui.plugin.add("resizable", "alsoResize", { style[prop] = sum || null; }); - // Opera fixing relative position - if ($.browser.opera && /relative/.test(el.css('position'))) { - self._revertToRelativePosition = true; - el.css({ position: 'absolute', top: 'auto', left: 'auto' }); - } - el.css(style); }); }; @@ -614,25 +599,6 @@ $.ui.plugin.add("resizable", "alsoResize", { }, stop: function (event, ui) { - var self = $(this).data("resizable"), o = self.options; - - var _reset = function (exp) { - $(exp).each(function() { - var el = $(this); - // reset position for Opera - no need to verify it was changed - el.css({ position: el.data("resizable-alsoresize").position }); - }); - }; - - if (self._revertToRelativePosition) { - self._revertToRelativePosition = false; - if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) { - $.each(o.alsoResize, function (exp) { _reset(exp); }); - }else{ - _reset(o.alsoResize); - } - } - $(this).removeData("resizable-alsoresize"); } }); diff --git a/ui/jquery.ui.slider.js b/ui/jquery.ui.slider.js index 9c5d21ffb..aff9093ba 100644 --- a/ui/jquery.ui.slider.js +++ b/ui/jquery.ui.slider.js @@ -115,8 +115,7 @@ $.widget( "ui.slider", $.ui.mouse, { this.handles .keydown(function( event ) { - var ret = true, - index = $( this ).data( "index.ui-slider-handle" ), + var index = $( this ).data( "index.ui-slider-handle" ), allowed, curVal, newVal, @@ -135,7 +134,7 @@ $.widget( "ui.slider", $.ui.mouse, { case $.ui.keyCode.RIGHT: case $.ui.keyCode.DOWN: case $.ui.keyCode.LEFT: - ret = false; + event.preventDefault(); if ( !self._keySliding ) { self._keySliding = true; $( this ).addClass( "ui-state-active" ); @@ -184,9 +183,6 @@ $.widget( "ui.slider", $.ui.mouse, { } self._slide( event, index, newVal ); - - return ret; - }) .keyup(function( event ) { var index = $( this ).data( "index.ui-slider-handle" ); diff --git a/ui/jquery.ui.sortable.js b/ui/jquery.ui.sortable.js index 600569451..d5796a3f0 100644 --- a/ui/jquery.ui.sortable.js +++ b/ui/jquery.ui.sortable.js @@ -65,7 +65,7 @@ $.widget("ui.sortable", $.ui.mouse, { }, - destroy: function() { + _destroy: function() { this.element .removeClass("ui-sortable ui-sortable-disabled"); this._mouseDestroy(); diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index 7a701405c..6e5cde07e 100644 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -596,86 +596,79 @@ if ( $.uiBackCompat !== false ) { }; // url method - (function( $, prototype ) { - prototype.url = function( index, url ) { + $.widget( "ui.tabs", $.ui.tabs, { + url: function( index, url ) { this.anchors.eq( index ).attr( "href", url ); - }; - }( jQuery, jQuery.ui.tabs.prototype ) ); + } + }); // ajaxOptions and cache options - (function( $, prototype ) { - $.extend( prototype.options, { + $.widget( "ui.tabs", $.ui.tabs, { + options: { ajaxOptions: null, cache: false - }); - - var _create = prototype._create, - _setOption = prototype._setOption, - _destroy = prototype._destroy, - oldurl = prototype.url || $.noop; + }, - $.extend( prototype, { - _create: function() { - _create.call( this ); + _create: function() { + this._super(); - var self = this; + var self = this; - this.element.bind( "tabsbeforeload.tabs", function( event, ui ) { - // tab is already cached - if ( $.data( ui.tab[ 0 ], "cache.tabs" ) ) { - event.preventDefault(); - return; - } - - $.extend( ui.ajaxSettings, self.options.ajaxOptions, { - error: function( xhr, s, e ) { - try { - // Passing index avoid a race condition when this method is - // called after the user has selected another tab. - // Pass the anchor that initiated this request allows - // loadError to manipulate the tab content panel via $(a.hash) - self.options.ajaxOptions.error( xhr, s, ui.tab.closest( "li" ).index(), ui.tab[ 0 ] ); - } - catch ( e ) {} - } - }); + this.element.bind( "tabsbeforeload.tabs", function( event, ui ) { + // tab is already cached + if ( $.data( ui.tab[ 0 ], "cache.tabs" ) ) { + event.preventDefault(); + return; + } - ui.jqXHR.success(function() { - if ( self.options.cache ) { - $.data( ui.tab[ 0 ], "cache.tabs", true ); + $.extend( ui.ajaxSettings, self.options.ajaxOptions, { + error: function( xhr, s, e ) { + try { + // Passing index avoid a race condition when this method is + // called after the user has selected another tab. + // Pass the anchor that initiated this request allows + // loadError to manipulate the tab content panel via $(a.hash) + self.options.ajaxOptions.error( xhr, s, ui.tab.closest( "li" ).index(), ui.tab[ 0 ] ); } - }); + catch ( e ) {} + } }); - }, - _setOption: function( key, value ) { - // reset cache if switching from cached to not cached - if ( key === "cache" && value === false ) { - this.anchors.removeData( "cache.tabs" ); - } - _setOption.apply( this, arguments ); - }, + ui.jqXHR.success(function() { + if ( self.options.cache ) { + $.data( ui.tab[ 0 ], "cache.tabs", true ); + } + }); + }); + }, - _destroy: function() { + _setOption: function( key, value ) { + // reset cache if switching from cached to not cached + if ( key === "cache" && value === false ) { this.anchors.removeData( "cache.tabs" ); - _destroy.call( this ); - }, - - url: function( index, url ){ - this.anchors.eq( index ).removeData( "cache.tabs" ); - oldurl.apply( this, arguments ); } - }); - }( jQuery, jQuery.ui.tabs.prototype ) ); + this._super( key, value ); + }, + + _destroy: function() { + this.anchors.removeData( "cache.tabs" ); + this._super(); + }, + + url: function( index, url ){ + this.anchors.eq( index ).removeData( "cache.tabs" ); + this._superApply( arguments ); + } + }); // abort method - (function( $, prototype ) { - prototype.abort = function() { + $.widget( "ui.tabs", $.ui.tabs, { + abort: function() { if ( this.xhr ) { this.xhr.abort(); } - }; - }( jQuery, jQuery.ui.tabs.prototype ) ); + } + }); // spinner $.widget( "ui.tabs", $.ui.tabs, { @@ -702,16 +695,13 @@ if ( $.uiBackCompat !== false ) { }); // enable/disable events - (function( $, prototype ) { - $.extend( prototype.options, { + $.widget( "ui.tabs", $.ui.tabs, { + options: { enable: null, disable: null - }); - - var enable = prototype.enable, - disable = prototype.disable; + }, - prototype.enable = function( index ) { + enable: function( index ) { var options = this.options, trigger; @@ -720,14 +710,14 @@ if ( $.uiBackCompat !== false ) { trigger = true; } - enable.apply( this, arguments ); + this._superApply( arguments ); if ( trigger ) { this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); } - }; + }, - prototype.disable = function( index ) { + disable: function( index ) { var options = this.options, trigger; @@ -736,23 +726,23 @@ if ( $.uiBackCompat !== false ) { trigger = true; } - disable.apply( this, arguments ); + this._superApply( arguments ); if ( trigger ) { this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); } - }; - }( jQuery, jQuery.ui.tabs.prototype ) ); + } + }); // add/remove methods and events - (function( $, prototype ) { - $.extend( prototype.options, { + $.widget( "ui.tabs", $.ui.tabs, { + options: { add: null, remove: null, tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>" - }); + }, - prototype.add = function( url, label, index ) { + add: function( url, label, index ) { if ( index === undefined ) { index = this.anchors.length; } @@ -803,9 +793,9 @@ if ( $.uiBackCompat !== false ) { this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); return this; - }; + }, - prototype.remove = function( index ) { + remove: function( index ) { index = this._getIndex( index ); var options = this.options, tab = this.lis.eq( index ).remove(), @@ -832,125 +822,117 @@ if ( $.uiBackCompat !== false ) { this._trigger( "remove", null, this._ui( tab.find( "a" )[ 0 ], panel[ 0 ] ) ); return this; - }; - }( jQuery, jQuery.ui.tabs.prototype ) ); + } + }); // length method - (function( $, prototype ) { - prototype.length = function() { + $.widget( "ui.tabs", $.ui.tabs, { + length: function() { return this.anchors.length; - }; - }( jQuery, jQuery.ui.tabs.prototype ) ); + } + }); // panel ids (idPrefix option + title attribute) - (function( $, prototype ) { - $.extend( prototype.options, { + $.widget( "ui.tabs", $.ui.tabs, { + options: { idPrefix: "ui-tabs-" - }); + }, - var _tabId = prototype._tabId; - prototype._tabId = function( a ) { + _tabId: function( a ) { return $( a ).attr( "aria-controls" ) || a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) || this.options.idPrefix + getNextTabId(); - }; - }( jQuery, jQuery.ui.tabs.prototype ) ); + } + }); // _createPanel method - (function( $, prototype ) { - $.extend( prototype.options, { + $.widget( "ui.tabs", $.ui.tabs, { + options: { panelTemplate: "<div></div>" - }); + }, - var _createPanel = prototype._createPanel; - prototype._createPanel = function( id ) { + _createPanel: function( id ) { return $( this.options.panelTemplate ) - .attr( "id", id ) - .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) - .data( "destroy.tabs", true ); - }; - }( jQuery, jQuery.ui.tabs.prototype ) ); + .attr( "id", id ) + .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) + .data( "destroy.tabs", true ); + } + }); // selected option - (function( $, prototype ) { - var _create = prototype._create, - _setOption = prototype._setOption, - _eventHandler = prototype._eventHandler; - - prototype._create = function() { + $.widget( "ui.tabs", $.ui.tabs, { + _create: function() { var options = this.options; if ( options.active === null && options.selected !== undefined ) { options.active = options.selected === -1 ? false : options.selected; } - _create.call( this ); + this._super(); options.selected = options.active; if ( options.selected === false ) { options.selected = -1; } - }; + }, - prototype._setOption = function( key, value ) { + _setOption: function( key, value ) { if ( key !== "selected" ) { - return _setOption.apply( this, arguments ); + return this._super( key, value ); } var options = this.options; - _setOption.call( this, "active", value === -1 ? false : value ); + this._super( "active", value === -1 ? false : value ); options.selected = options.active; if ( options.selected === false ) { options.selected = -1; } - }; + }, - prototype._eventHandler = function( event ) { - _eventHandler.apply( this, arguments ); + _eventHandler: function( event ) { + this._superApply( arguments ); this.options.selected = this.options.active; if ( this.options.selected === false ) { this.options.selected = -1; } - }; - }( jQuery, jQuery.ui.tabs.prototype ) ); + } + }); // show and select event - (function( $, prototype ) { - $.extend( prototype.options, { + $.widget( "ui.tabs", $.ui.tabs, { + options: { show: null, select: null - }); - var _create = prototype._create, - _trigger = prototype._trigger; - - prototype._create = function() { - _create.call( this ); + }, + _create: function() { + this._super(); if ( this.options.active !== false ) { this._trigger( "show", null, this._ui( this.active[ 0 ], this._getPanelForTab( this.active )[ 0 ] ) ); } - }; - prototype._trigger = function( type, event, data ) { - var ret = _trigger.apply( this, arguments ); + }, + _trigger: function( type, event, data ) { + var ret = this._superApply( arguments ); if ( !ret ) { return false; } if ( type === "beforeActivate" && data.newTab.length ) { - ret = _trigger.call( this, "select", event, { + ret = this._super( "select", event, { tab: data.newTab[ 0], panel: data.newPanel[ 0 ], index: data.newTab.closest( "li" ).index() }); } else if ( type === "activate" && data.newTab.length ) { - ret = _trigger.call( this, "show", event, { + ret = this._super( "show", event, { tab: data.newTab[ 0 ], panel: data.newPanel[ 0 ], index: data.newTab.closest( "li" ).index() }); } - }; - }( jQuery, jQuery.ui.tabs.prototype ) ); + return ret; + } + }); // select method - (function( $, prototype ) { - prototype.select = function( index ) { + $.widget( "ui.tabs", $.ui.tabs, { + select: function( index ) { index = this._getIndex( index ); if ( index === -1 ) { if ( this.options.collapsible && this.options.selected !== -1 ) { @@ -960,14 +942,12 @@ if ( $.uiBackCompat !== false ) { } } this.anchors.eq( index ).trigger( this.options.event + ".tabs" ); - }; - }( jQuery, jQuery.ui.tabs.prototype ) ); + } + }); // cookie option var listId = 0; - function getNextListId() { - return ++listId; - } + $.widget( "ui.tabs", $.ui.tabs, { options: { cookie: null // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true } @@ -986,7 +966,7 @@ if ( $.uiBackCompat !== false ) { }, _cookie: function( active ) { var cookie = [ this.cookie || - ( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() ) ]; + ( this.cookie = this.options.cookie.name || "ui-tabs-" + ++listId ) ]; if ( arguments.length ) { cookie.push( active === false ? -1 : active ); cookie.push( this.options.cookie ); diff --git a/ui/jquery.ui.tooltip.js b/ui/jquery.ui.tooltip.js index a006f3bf7..cb23e9a4d 100644 --- a/ui/jquery.ui.tooltip.js +++ b/ui/jquery.ui.tooltip.js @@ -103,7 +103,13 @@ $.widget( "ui.tooltip", { target.data( "tooltip-title", target.attr( "title" ) ); } + target.data( "tooltip-open", true ); + content = this.options.content.call( target[0], function( response ) { + // ignore async response if tooltip was closed already + if ( !target.data( "tooltip-open" ) ) { + return; + } // IE may instantly serve a cached response for ajax requests // delay this call to _open so the other call to _open runs first setTimeout(function() { @@ -123,7 +129,10 @@ $.widget( "ui.tooltip", { // if we have a title, clear it to prevent the native tooltip // we have to check first to avoid defining a title if none exists // (we don't want to cause an element to start matching [title]) - // TODO: document why we don't use .removeAttr() + + // We don't use removeAttr as that causes the native tooltip to show + // up in IE (9 and below, didn't yet test 10). Happens only when removing + // inside the mouseover handler. if ( target.is( "[title]" ) ) { target.attr( "title", "" ); } @@ -183,6 +192,7 @@ $.widget( "ui.tooltip", { delete that.tooltips[ this.id ]; }); + target.removeData( "tooltip-open" ); target.unbind( "mouseleave.tooltip blur.tooltip keyup.tooltip" ); this._trigger( "close", event, { tooltip: tooltip } ); diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index ad03e6f44..2d48ae26d 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -23,8 +23,9 @@ $.cleanData = function( elems ) { }; $.widget = function( name, base, prototype ) { - var namespace = name.split( "." )[ 0 ], - fullName; + var fullName, existingConstructor, constructor, basePrototype, + namespace = name.split( "." )[ 0 ]; + name = name.split( "." )[ 1 ]; fullName = namespace + "-" + name; @@ -39,12 +40,11 @@ $.widget = function( name, base, prototype ) { }; $[ namespace ] = $[ namespace ] || {}; - // create the constructor using $.extend() so we can carry over any - // static properties stored on the existing constructor (if there is one) - $[ namespace ][ name ] = $.extend( function( options, element ) { + existingConstructor = $[ namespace ][ name ]; + constructor = $[ namespace ][ name ] = function( options, element ) { // allow instantiation without "new" keyword if ( !this._createWidget ) { - return new $[ namespace ][ name ]( options, element ); + return new constructor( options, element ); } // allow instantiation without initializing for simple inheritance @@ -52,9 +52,19 @@ $.widget = function( name, base, prototype ) { if ( arguments.length ) { this._createWidget( options, element ); } - }, $[ namespace ][ name ], { version: prototype.version } ); + }; + // extend with the existing constructor to carry over any static properties + $.extend( constructor, existingConstructor, { + version: prototype.version, + // copy the object used to create the prototype in case we need to + // redefine the widget later + _proto: $.extend( {}, prototype ), + // track widgets that inherit from this widget in case this widget is + // redefined after a widget inherits from it + _childConstructors: [] + }); - var basePrototype = new base(); + basePrototype = new base(); // we need to make the options hash a property directly on the new instance // otherwise we'll modify the options hash on the prototype that we're // inheriting from @@ -83,17 +93,41 @@ $.widget = function( name, base, prototype ) { return returnValue; }; - }()); + })(); } }); - $[ namespace ][ name ].prototype = $.widget.extend( basePrototype, { + constructor.prototype = $.widget.extend( basePrototype, { + // TODO: remove support for widgetEventPrefix + // always use the name + a colon as the prefix, e.g., draggable:start + // don't prefix for widgets that aren't DOM-based + widgetEventPrefix: name + }, prototype, { + constructor: constructor, namespace: namespace, widgetName: name, - widgetEventPrefix: name, widgetBaseClass: fullName - }, prototype ); + }); - $.widget.bridge( name, $[ namespace ][ name ] ); + // If this widget is being redefined then we need to find all widgets that + // are inheriting from it and redefine all of them so that they inherit from + // the new version of this widget. We're essentially trying to replace one + // level in the prototype chain. + if ( existingConstructor ) { + $.each( existingConstructor._childConstructors, function( i, child ) { + var childPrototype = child.prototype; + + // redefine the child widget using the same prototype that was + // originally used, but inherit from the new version of the base + $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); + }); + // remove the list of existing child constructors from the old constructor + // so the old child constructors can be garbage collected + delete existingConstructor._childConstructors; + } else { + base._childConstructors.push( constructor ); + } + + $.widget.bridge( name, constructor ); }; $.widget.extend = function( target ) { @@ -148,7 +182,7 @@ $.widget.bridge = function( name, object ) { if ( instance ) { instance.option( options || {} )._init(); } else { - object( options, this ); + new object( options, this ); } }); } @@ -157,18 +191,8 @@ $.widget.bridge = function( name, object ) { }; }; -$.Widget = function( options, element ) { - // allow instantiation without "new" keyword - if ( !this._createWidget ) { - return new $[ namespace ][ name ]( options, element ); - } - - // allow instantiation without initializing for simple inheritance - // must use "new" keyword (the code above always passes args) - if ( arguments.length ) { - this._createWidget( options, element ); - } -}; +$.Widget = function( options, element ) {}; +$.Widget._childConstructors = []; $.Widget.prototype = { widgetName: "widget", |