diff options
Diffstat (limited to 'ui/widgets')
-rw-r--r-- | ui/widgets/accordion.js | 6 | ||||
-rw-r--r-- | ui/widgets/autocomplete.js | 47 | ||||
-rw-r--r-- | ui/widgets/button.js | 605 | ||||
-rw-r--r-- | ui/widgets/checkboxradio.js | 277 | ||||
-rw-r--r-- | ui/widgets/controlgroup.js | 251 | ||||
-rw-r--r-- | ui/widgets/dialog.js | 27 | ||||
-rw-r--r-- | ui/widgets/draggable.js | 6 | ||||
-rw-r--r-- | ui/widgets/menu.js | 6 | ||||
-rw-r--r-- | ui/widgets/mouse.js | 16 | ||||
-rw-r--r-- | ui/widgets/progressbar.js | 6 | ||||
-rw-r--r-- | ui/widgets/resizable.js | 33 | ||||
-rw-r--r-- | ui/widgets/selectable.js | 2 | ||||
-rw-r--r-- | ui/widgets/selectmenu.js | 24 | ||||
-rw-r--r-- | ui/widgets/slider.js | 6 | ||||
-rw-r--r-- | ui/widgets/sortable.js | 2 | ||||
-rw-r--r-- | ui/widgets/spinner.js | 40 | ||||
-rw-r--r-- | ui/widgets/tabs.js | 6 | ||||
-rw-r--r-- | ui/widgets/tooltip.js | 9 |
18 files changed, 937 insertions, 432 deletions
diff --git a/ui/widgets/accordion.js b/ui/widgets/accordion.js index 360ac1700..14b3f7303 100644 --- a/ui/widgets/accordion.js +++ b/ui/widgets/accordion.js @@ -12,9 +12,9 @@ //>>description: Displays collapsible content panels for presenting information in a limited amount of space. //>>docs: http://api.jqueryui.com/accordion/ //>>demos: http://jqueryui.com/accordion/ -//>>css.structure: ../themes/base/core.css -//>>css.structure: ../themes/base/accordion.css -//>>css.theme: ../themes/base/theme.css +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/accordion.css +//>>css.theme: ../../themes/base/theme.css ( function( factory ) { if ( typeof define === "function" && define.amd ) { diff --git a/ui/widgets/autocomplete.js b/ui/widgets/autocomplete.js index 4067f871f..060d8e94f 100644 --- a/ui/widgets/autocomplete.js +++ b/ui/widgets/autocomplete.js @@ -12,9 +12,9 @@ //>>description: Lists suggested words as the user is typing. //>>docs: http://api.jqueryui.com/autocomplete/ //>>demos: http://jqueryui.com/autocomplete/ -//>>css.structure: ../themes/base/core.css -//>>css.structure: ../themes/base/autocomplete.css -//>>css.theme: ../themes/base/theme.css +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/autocomplete.css +//>>css.theme: ../../themes/base/theme.css ( function( factory ) { if ( typeof define === "function" && define.amd ) { @@ -245,24 +245,6 @@ $.widget( "ui.autocomplete", { this.element.trigger( "focus" ); } } ); - - // 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 - // the user clicks somewhere outside of the autocomplete - var menuElement = this.menu.element[ 0 ]; - if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { - this._delay( function() { - var that = this; - this.document.one( "mousedown", function( event ) { - if ( event.target !== that.element[ 0 ] && - event.target !== menuElement && - !$.contains( menuElement, event.target ) ) { - that.close(); - } - } ); - } ); - } }, menufocus: function( event, ui ) { var label, item; @@ -368,6 +350,20 @@ $.widget( "ui.autocomplete", { } }, + _isEventTargetInWidget: function( event ) { + var menuElement = this.menu.element[ 0 ]; + + return event.target === this.element[ 0 ] || + event.target === menuElement || + $.contains( menuElement, event.target ); + }, + + _closeOnClickOutside: function( event ) { + if ( !this._isEventTargetInWidget( event ) ) { + this.close(); + } + }, + _appendTo: function() { var element = this.options.appendTo; @@ -496,6 +492,10 @@ $.widget( "ui.autocomplete", { }, _close: function( event ) { + + // Remove the handler that closes the menu on outside clicks + this._off( this.document, "mousedown" ); + if ( this.menu.element.is( ":visible" ) ) { this.menu.element.hide(); this.menu.blur(); @@ -546,6 +546,11 @@ $.widget( "ui.autocomplete", { if ( this.options.autoFocus ) { this.menu.next(); } + + // Listen for interactions outside of the widget (#6642) + this._on( this.document, { + mousedown: "_closeOnClickOutside" + } ); }, _resizeMenu: function() { diff --git a/ui/widgets/button.js b/ui/widgets/button.js index 94fc75331..50da9f9e2 100644 --- a/ui/widgets/button.js +++ b/ui/widgets/button.js @@ -12,9 +12,9 @@ //>>description: Enhances a form with themeable buttons. //>>docs: http://api.jqueryui.com/button/ //>>demos: http://jqueryui.com/button/ -//>>css.structure: ../themes/base/core.css -//>>css.structure: ../themes/base/button.css -//>>css.theme: ../themes/base/theme.css +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/button.css +//>>css.theme: ../../themes/base/theme.css ( function( factory ) { if ( typeof define === "function" && define.amd ) { @@ -22,10 +22,13 @@ // AMD. Register as an anonymous module. define( [ "jquery", - "../data", + + // These are only for backcompat + // TODO: Remove after 1.12 + "./controlgroup", + "./checkboxradio", + "../keycode", - "../labels", - "../version", "../widget" ], factory ); } else { @@ -35,391 +38,349 @@ } }( function( $ ) { -var lastActive, - baseClasses = "ui-button ui-widget ui-state-default ui-corner-all", - 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", - formResetHandler = function() { - var form = $( this ); - setTimeout( function() { - form.find( ":ui-button" ).button( "refresh" ); - }, 1 ); - }, - radioGroup = function( radio ) { - var name = radio.name, - form = radio.form, - radios = $( [] ); - if ( name ) { - name = name.replace( /'/g, "\\'" ); - if ( form ) { - radios = $( form ).find( "[name='" + name + "'][type=radio]" ); - } else { - radios = $( "[name='" + name + "'][type=radio]", radio.ownerDocument ) - .filter( function() { - return !this.form; - } ); - } - } - return radios; - }; - $.widget( "ui.button", { version: "@VERSION", defaultElement: "<button>", options: { + classes: { + "ui-button": "ui-corner-all" + }, disabled: null, - text: true, + icon: null, + iconPosition: "beginning", label: null, - icons: { - primary: null, - secondary: null - } + showLabel: true }, - _create: function() { - this.element.closest( "form" ) - .off( "reset" + this.eventNamespace ) - .on( "reset" + this.eventNamespace, formResetHandler ); - if ( typeof this.options.disabled !== "boolean" ) { - this.options.disabled = !!this.element.prop( "disabled" ); - } else { - this.element.prop( "disabled", this.options.disabled ); - } + _getCreateOptions: function() { + var disabled, - this._determineButtonType(); - this.hasTitle = !!this.buttonElement.attr( "title" ); + // This is to support cases like in jQuery Mobile where the base widget does have + // an implementation of _getCreateOptions + options = this._super() || {}; - var that = this, - options = this.options, - toggleButton = this.type === "checkbox" || this.type === "radio", - activeClass = !toggleButton ? "ui-state-active" : ""; + this.isInput = this.element.is( "input" ); - if ( options.label === null ) { - options.label = ( this.type === "input" ? this.buttonElement.val() : this.buttonElement.html() ); + disabled = this.element[ 0 ].disabled; + if ( disabled != null ) { + options.disabled = disabled; } - this._hoverable( this.buttonElement ); + this.originalLabel = this.isInput ? this.element.val() : this.element.html(); + if ( this.originalLabel ) { + options.label = this.originalLabel; + } - this.buttonElement - .addClass( baseClasses ) - .attr( "role", "button" ) - .on( "mouseenter" + this.eventNamespace, function() { - if ( options.disabled ) { - return; - } - if ( this === lastActive ) { - $( this ).addClass( "ui-state-active" ); - } - } ) - .on( "mouseleave" + this.eventNamespace, function() { - if ( options.disabled ) { - return; - } - $( this ).removeClass( activeClass ); - } ) - .on( "click" + this.eventNamespace, function( event ) { - if ( options.disabled ) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - } ); + return options; + }, - // Can't use _focusable() because the element that receives focus - // and the element that gets the ui-state-focus class are different - this._on( { - focus: function() { - this.buttonElement.addClass( "ui-state-focus" ); - }, - blur: function() { - this.buttonElement.removeClass( "ui-state-focus" ); - } - } ); + _create: function() { + if ( !this.option.showLabel & !this.options.icon ) { + this.options.showLabel = true; + } - if ( toggleButton ) { - this.element.on( "change" + this.eventNamespace, function() { - that.refresh(); - } ); + // We have to check the option again here even though we did in _getCreateOptions, + // because null may have been passed on init which would override what was set in + // _getCreateOptions + if ( this.options.disabled == null ) { + this.options.disabled = this.element[ 0 ].disabled || false; } - if ( this.type === "checkbox" ) { - this.buttonElement.on( "click" + this.eventNamespace, function() { - if ( options.disabled ) { - return false; - } - } ); - } else if ( this.type === "radio" ) { - this.buttonElement.on( "click" + this.eventNamespace, function() { - if ( options.disabled ) { - return false; - } - $( this ).addClass( "ui-state-active" ); - that.buttonElement.attr( "aria-pressed", "true" ); - - var radio = that.element[ 0 ]; - radioGroup( radio ) - .not( radio ) - .map( function() { - return $( this ).button( "widget" )[ 0 ]; - } ) - .removeClass( "ui-state-active" ) - .attr( "aria-pressed", "false" ); - } ); - } else { - this.buttonElement - .on( "mousedown" + this.eventNamespace, function() { - if ( options.disabled ) { - return false; - } - $( this ).addClass( "ui-state-active" ); - lastActive = this; - that.document.one( "mouseup", function() { - lastActive = null; - } ); - } ) - .on( "mouseup" + this.eventNamespace, function() { - if ( options.disabled ) { - return false; - } - $( this ).removeClass( "ui-state-active" ); - } ) - .on( "keydown" + this.eventNamespace, function( event ) { - if ( options.disabled ) { - return false; - } - if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) { - $( this ).addClass( "ui-state-active" ); - } - } ) + this.hasTitle = !!this.element.attr( "title" ); - // see #8559, we bind to blur here in case the button element loses - // focus between keydown and keyup, it would be left in an "active" state - .on( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() { - $( this ).removeClass( "ui-state-active" ); - } ); + // Check to see if the label needs to be set or if its already correct + if ( this.options.label && this.options.label !== this.originalLabel ) { + if ( this.isInput ) { + this.element.val( this.options.label ); + } else { + this.element.html( this.options.label ); + } + } + this._addClass( "ui-button", "ui-widget" ); + this._setOption( "disabled", this.options.disabled ); + this._enhance(); - if ( this.buttonElement.is( "a" ) ) { - this.buttonElement.on( "keyup", function( event ) { + if ( this.element.is( "a" ) ) { + this._on( { + "keyup": function( event ) { if ( event.keyCode === $.ui.keyCode.SPACE ) { - - // TODO pass through original event correctly (just as 2nd argument doesn't work) - $( this ).trigger( "click" ); + event.preventDefault(); + + // Support: PhantomJS <= 1.9, IE 8 Only + // If a native click is available use it so we actually cause navigation + // otherwise just trigger a click event + if ( this.element[ 0 ].click ) { + this.element[ 0 ].click(); + } else { + this.element.trigger( "click" ); + } } - } ); - } + } + } ); + } + }, + + _enhance: function() { + if ( !this.element.is( "button" ) ) { + this.element.attr( "role", "button" ); } - this._setOption( "disabled", options.disabled ); - this._resetButton(); + if ( this.options.icon ) { + this._updateIcon( "icon", this.options.icon ); + this._updateTooltip(); + } }, - _determineButtonType: function() { - var ancestor, labelSelector, checked; + _updateTooltip: function() { + this.title = this.element.attr( "title" ); - if ( this.element.is( "[type=checkbox]" ) ) { - this.type = "checkbox"; - } else if ( this.element.is( "[type=radio]" ) ) { - this.type = "radio"; - } else if ( this.element.is( "input" ) ) { - this.type = "input"; - } else { - this.type = "button"; + if ( !this.options.showLabel && !this.title ) { + this.element.attr( "title", this.options.label ); } + }, - if ( this.type === "checkbox" || this.type === "radio" ) { - - // we don't search against the document in case the element - // is disconnected from the DOM - ancestor = this.element.parents().last(); - labelSelector = "label[for='" + this.element.attr( "id" ) + "']"; - this.buttonElement = ancestor.find( labelSelector ); - if ( !this.buttonElement.length ) { - ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings(); - this.buttonElement = ancestor.filter( labelSelector ); - if ( !this.buttonElement.length ) { - this.buttonElement = ancestor.find( labelSelector ); - } + _updateIcon: function( option, value ) { + var icon = option !== "iconPosition", + position = icon ? this.options.iconPosition : value, + displayBlock = position === "top" || position === "bottom"; + + // Create icon + if ( !this.icon ) { + this.icon = $( "<span>" ); + + this._addClass( this.icon, "ui-button-icon", "ui-icon" ); + + if ( !this.options.showLabel ) { + this._addClass( "ui-button-icon-only" ); } - this.element.addClass( "ui-helper-hidden-accessible" ); + } else if ( icon ) { - checked = this.element.is( ":checked" ); - if ( checked ) { - this.buttonElement.addClass( "ui-state-active" ); + // If we are updating the icon remove the old icon class + this._removeClass( this.icon, null, this.options.icon ); + } + + // If we are updating the icon add the new icon class + if ( icon ) { + this._addClass( this.icon, null, value ); + } + + this._attachIcon( position ); + + // If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove + // the iconSpace if there is one. + if ( displayBlock ) { + this._addClass( this.icon, null, "ui-widget-icon-block" ); + if ( this.iconSpace ) { + this.iconSpace.remove(); } - this.buttonElement.prop( "aria-pressed", checked ); } else { - this.buttonElement = this.element; - } - }, - widget: function() { - return this.buttonElement; + // Position is beginning or end so remove the ui-widget-icon-block class and add the + // space if it does not exist + if ( !this.iconSpace ) { + this.iconSpace = $( "<span> </span>" ); + this._addClass( this.iconSpace, "ui-button-icon-space" ); + } + this._removeClass( this.icon, null, "ui-wiget-icon-block" ); + this._attachIconSpace( position ); + } }, _destroy: function() { - this.element - .removeClass( "ui-helper-hidden-accessible" ); - this.buttonElement - .removeClass( baseClasses + " ui-state-active " + typeClasses ) - .removeAttr( "role aria-pressed" ) - .html( this.buttonElement.find( ".ui-button-text" ).html() ); + this.element.removeAttr( "role" ); + if ( this.icon ) { + this.icon.remove(); + } + if ( this.iconSpace ) { + this.iconSpace.remove(); + } if ( !this.hasTitle ) { - this.buttonElement.removeAttr( "title" ); + this.element.removeAttr( "title" ); } }, - _setOption: function( key, value ) { - this._super( key, value ); - if ( key === "disabled" ) { - this.widget().toggleClass( "ui-state-disabled", !!value ); - this.element.prop( "disabled", !!value ); - if ( value ) { - if ( this.type === "checkbox" || this.type === "radio" ) { - this.buttonElement.removeClass( "ui-state-focus" ); - } else { - this.buttonElement.removeClass( "ui-state-focus ui-state-active" ); - } - } - return; - } - this._resetButton(); + _attachIconSpace: function( iconPosition ) { + this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace ); }, - refresh: function() { + _attachIcon: function( iconPosition ) { + this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon ); + }, - //See #8237 & #8828 - var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" ); + _setOptions: function( options ) { + var newShowLabel = options.showLabel === undefined ? + this.options.showLabel : + options.showLabel, + newIcon = options.icon === undefined ? this.options.icon : options.icon; - if ( isDisabled !== this.options.disabled ) { - this._setOption( "disabled", isDisabled ); - } - if ( this.type === "radio" ) { - radioGroup( this.element[ 0 ] ).each( function() { - if ( $( this ).is( ":checked" ) ) { - $( this ).button( "widget" ) - .addClass( "ui-state-active" ) - .attr( "aria-pressed", "true" ); - } else { - $( this ).button( "widget" ) - .removeClass( "ui-state-active" ) - .attr( "aria-pressed", "false" ); - } - } ); - } else if ( this.type === "checkbox" ) { - if ( this.element.is( ":checked" ) ) { - this.buttonElement - .addClass( "ui-state-active" ) - .attr( "aria-pressed", "true" ); - } else { - this.buttonElement - .removeClass( "ui-state-active" ) - .attr( "aria-pressed", "false" ); - } + if ( !newShowLabel && !newIcon ) { + options.showLabel = true; } + this._super( options ); }, - _resetButton: function() { - if ( this.type === "input" ) { - if ( this.options.label ) { - this.element.val( this.options.label ); + _setOption: function( key, value ) { + if ( key === "icon" ) { + if ( value ) { + this._updateIcon( key, value ); + } else if ( this.icon ) { + this.icon.remove(); + if ( this.iconSpace ) { + this.iconSpace.remove(); + } } - return; } - var buttonElement = this.buttonElement.removeClass( typeClasses ), - buttonText = $( "<span></span>", this.document[ 0 ] ) - .addClass( "ui-button-text" ) - .html( this.options.label ) - .appendTo( buttonElement.empty() ) - .text(), - icons = this.options.icons, - multipleIcons = icons.primary && icons.secondary, - buttonClasses = []; - - if ( icons.primary || icons.secondary ) { - if ( this.options.text ) { - buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) ); - } - if ( icons.primary ) { - buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" ); - } + if ( key === "iconPosition" ) { + this._updateIcon( key, value ); + } - if ( icons.secondary ) { - buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" ); - } + // Make sure we can't end up with a button that has neither text nor icon + if ( key === "showLabel" ) { + this._toggleClass( "ui-button-icon-only", null, !value ); + this._updateTooltip(); + } - if ( !this.options.text ) { - buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" ); + if ( key === "label" ) { + if ( this.isInput ) { + this.element.val( value ); + } else { - if ( !this.hasTitle ) { - buttonElement.attr( "title", $.trim( buttonText ) ); + // If there is an icon, append it, else nothing then append the value + // this avoids removal of the icon when setting label text + this.element.html( value ); + if ( this.icon ) { + this._attachIcon( this.options.iconPosition ); + this._attachIconSpace( this.options.iconPosition ); } } - } else { - buttonClasses.push( "ui-button-text-only" ); } - buttonElement.addClass( buttonClasses.join( " " ) ); - } -} ); - -$.widget( "ui.buttonset", { - version: "@VERSION", - options: { - items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)" - }, - _create: function() { - this.element.addClass( "ui-buttonset" ); - }, - - _init: function() { - this.refresh(); - }, + this._super( key, value ); - _setOption: function( key, value ) { if ( key === "disabled" ) { - this.buttons.button( "option", key, value ); + this._toggleClass( null, "ui-state-disabled", value ); + this.element[ 0 ].disabled = value; + if ( value ) { + this.element.blur(); + } } - - this._super( key, value ); }, refresh: function() { - var rtl = this.element.css( "direction" ) === "rtl", - allButtons = this.element.find( this.options.items ), - existingButtons = allButtons.filter( ":ui-button" ); - - // Initialize new buttons - allButtons.not( ":ui-button" ).button(); - - // Refresh existing buttons - existingButtons.button( "refresh" ); - - this.buttons = allButtons - .map( function() { - return $( this ).button( "widget" )[ 0 ]; - } ) - .removeClass( "ui-corner-all ui-corner-left ui-corner-right" ) - .filter( ":first" ) - .addClass( rtl ? "ui-corner-right" : "ui-corner-left" ) - .end() - .filter( ":last" ) - .addClass( rtl ? "ui-corner-left" : "ui-corner-right" ) - .end() - .end(); - }, - _destroy: function() { - this.element.removeClass( "ui-buttonset" ); - this.buttons - .map( function() { - return $( this ).button( "widget" )[ 0 ]; - } ) - .removeClass( "ui-corner-left ui-corner-right" ) - .end() - .button( "destroy" ); + // Make sure to only check disabled if its an element that supports this otherwise + // check for the disabled class to determine state + var isDisabled = this.element.is( "input, button" ) ? + this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" ); + + if ( isDisabled !== this.options.disabled ) { + this._setOptions( { disabled: isDisabled } ); + } + + this._updateTooltip(); } } ); +// DEPRECATED +if ( $.uiBackCompat !== false ) { + + // Text and Icons options + $.widget( "ui.button", $.ui.button, { + options: { + text: true, + icons: { + primary: null, + secondary: null + } + }, + + _create: function() { + if ( this.options.showLabel && !this.options.text ) { + this.options.showLabel = this.options.text; + } + if ( !this.options.showLabel && this.options.text ) { + this.options.text = this.options.showLabel; + } + if ( !this.options.icon && ( this.options.icons.primary || + this.options.icons.secondary ) ) { + if ( this.options.icons.primary ) { + this.options.icon = this.options.icons.primary; + } else { + this.options.icon = this.options.icons.secondary; + this.options.iconPosition = "end"; + } + } else if ( this.options.icon ) { + this.options.icons.primary = this.options.icon; + } + this._super(); + }, + + _setOption: function( key, value ) { + if ( key === "text" ) { + this._super( "showLabel", value ); + return; + } + if ( key === "showLabel" ) { + this.options.text = value; + } + if ( key === "icon" ) { + this.options.icons.primary = value; + } + if ( key === "icons" ) { + if ( value.primary ) { + this._super( "icon", value.primary ); + this._super( "iconPosition", "beginning" ); + } else if ( value.secondary ) { + this._super( "icon", value.secondary ); + this._super( "iconPosition", "end" ); + } + } + this._superApply( arguments ); + } + } ); + + $.fn.button = ( function( orig ) { + return function() { + if ( !this.length || ( this.length && this[ 0 ].tagName !== "INPUT" ) || + ( this.length && this[ 0 ].tagName === "INPUT" && ( + this.attr( "type" ) !== "checkbox" && this.attr( "type" ) !== "radio" + ) ) ) { + return orig.apply( this, arguments ); + } + if ( !$.ui.checkboxradio ) { + $.error( "Checkboxradio widget missing" ); + } + if ( arguments.length === 0 ) { + return this.checkboxradio( { + "icon": false + } ); + } + return this.checkboxradio.apply( this, arguments ); + }; + } )( $.fn.button ); + + $.fn.buttonset = function() { + if ( !$.ui.controlgroup ) { + $.error( "Controlgroup widget missing" ); + } + if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) { + return this.controlgroup.apply( this, + [ arguments[ 0 ], "items.button", arguments[ 2 ] ] ); + } + if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) { + return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] ); + } + if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) { + arguments[ 0 ].items = { + button: arguments[ 0 ].items + }; + } + return this.controlgroup.apply( this, arguments ); + }; +} + return $.ui.button; } ) ); diff --git a/ui/widgets/checkboxradio.js b/ui/widgets/checkboxradio.js new file mode 100644 index 000000000..107749201 --- /dev/null +++ b/ui/widgets/checkboxradio.js @@ -0,0 +1,277 @@ +/*! + * jQuery UI Checkboxradio @VERSION + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Checkboxradio +//>>group: Widgets +//>>description: Enhances a form with multiple themeable checkboxes or radio buttons. +//>>docs: http://api.jqueryui.com/checkboxradio/ +//>>demos: http://jqueryui.com/checkboxradio/ +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/button.css +//>>css.structure: ../../themes/base/checkboxradio.css +//>>css.theme: ../../themes/base/theme.css + +( function( factory ) { + if ( typeof define === "function" && define.amd ) { + + // AMD. Register as an anonymous module. + define( [ + "jquery", + "../escape-selector", + "../form-reset-mixin", + "../labels", + "../widget" + ], factory ); + } else { + + // Browser globals + factory( jQuery ); + } +}( function( $ ) { + +$.widget( "ui.checkboxradio", [ $.ui.formResetMixin, { + version: "@VERSION", + options: { + disabled: null, + label: null, + icon: true, + classes: { + "ui-checkboxradio-label": "ui-corner-all", + "ui-checkboxradio-icon": "ui-corner-all" + } + }, + + _getCreateOptions: function() { + var disabled, labels; + var that = this; + var options = this._super() || {}; + + // We read the type here, because it makes more sense to throw a element type error first, + // rather then the error for lack of a label. Often if its the wrong type, it + // won't have a label (e.g. calling on a div, btn, etc) + this._readType(); + + labels = this.element.labels(); + + // If there are multiple labels, use the last one + this.label = $( labels[ labels.length - 1 ] ); + if ( !this.label.length ) { + $.error( "No label found for checkboxradio widget" ); + } + + this.originalLabel = ""; + + // We need to get the label text but this may also need to make sure it does not contain the + // input itself. + this.label.contents().not( this.element ).each( function() { + + // The label contents could be text, html, or a mix. We concat each element to get a string + // representation of the label, without the input as part of it. + that.originalLabel += this.nodeType === 3 ? $( this ).text() : this.outerHTML; + } ); + + // Set the label option if we found label text + if ( this.originalLabel ) { + options.label = this.originalLabel; + } + + disabled = this.element[ 0 ].disabled; + if ( disabled != null ) { + options.disabled = disabled; + } + return options; + }, + + _create: function() { + var checked = this.element[ 0 ].checked; + + this._bindFormResetHandler(); + + if ( this.options.disabled == null ) { + this.options.disabled = this.element[ 0 ].disabled; + } + + this._setOption( "disabled", this.options.disabled ); + this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" ); + this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" ); + + if ( this.type === "radio" ) { + this._addClass( this.label, "ui-checkboxradio-radio-label" ); + } + + if ( this.options.label && this.options.label !== this.originalLabel ) { + this._updateLabel(); + } else if ( this.originalLabel ) { + this.options.label = this.originalLabel; + } + + this._enhance(); + + if ( checked ) { + this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" ); + this._addClass( this.icon, null, "ui-state-hover" ); + } + + this._on( { + change: "_toggleClasses", + focus: function() { + this._addClass( this.label, null, "ui-state-focus ui-visual-focus" ); + }, + blur: function() { + this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" ); + } + } ); + }, + + _readType: function() { + var nodeName = this.element[ 0 ].nodeName.toLowerCase(); + this.type = this.element[ 0 ].type; + if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) { + $.error( "Can't create checkboxradio on element.nodeName=" + nodeName + + " and element.type=" + this.type ); + } + }, + + // Support jQuery Mobile enhanced option + _enhance: function() { + this._updateIcon( this.element[ 0 ].checked ); + }, + + widget: function() { + return this.label; + }, + + _getRadioGroup: function() { + var group; + var name = this.element[ 0 ].name; + var nameSelector = "input[name='" + $.ui.escapeSelector( name ) + "']"; + + if ( !name ) { + return $( [] ); + } + + if ( this.form.length ) { + group = $( this.form[ 0 ].elements ).filter( nameSelector ); + } else { + + // Not inside a form, check all inputs that also are not inside a form + group = $( nameSelector ).filter( function() { + return $( this ).form().length === 0; + } ); + } + + return group.not( this.element ); + }, + + _toggleClasses: function() { + var checked = this.element[ 0 ].checked; + this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked ); + + if ( this.options.icon && this.type === "checkbox" ) { + + // We add ui-state-highlight to change the icon color + this._toggleClass( this.icon, null, "ui-icon-check ui-state-highlight", checked ) + ._toggleClass( this.icon, null, "ui-icon-blank", !checked ); + } + if ( this.type === "radio" ) { + this._getRadioGroup() + .each( function() { + var instance = $( this ).checkboxradio( "instance" ); + + if ( instance ) { + instance._removeClass( instance.label, + "ui-checkboxradio-checked", "ui-state-active" ); + } + } ); + } + }, + + _destroy: function() { + this._unbindFormResetHandler(); + + if ( this.icon ) { + this.icon.remove(); + this.iconSpace.remove(); + } + }, + + _setOption: function( key, value ) { + + // We don't allow the value to be set to nothing + if ( key === "label" && !value ) { + return; + } + + this._super( key, value ); + + if ( key === "disabled" ) { + this._toggleClass( this.label, null, "ui-state-disabled", value ); + this.element[ 0 ].disabled = value; + + // Don't refresh when setting disabled + return; + } + this.refresh(); + }, + + _updateIcon: function( checked ) { + var toAdd = "ui-icon ui-icon-background "; + + if ( this.options.icon ) { + if ( !this.icon ) { + this.icon = $( "<span>" ); + this.iconSpace = $( "<span> </span>" ); + this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" ); + } + + if ( this.type === "checkbox" ) { + toAdd += checked ? "ui-icon-check ui-state-highlight" : "ui-icon-blank"; + this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" ); + } else { + toAdd += "ui-icon-blank"; + } + this._addClass( this.icon, "ui-checkboxradio-icon", toAdd ); + if ( !checked ) { + this._removeClass( this.icon, null, "ui-icon-check ui-state-highlight" ); + } + this.icon.prependTo( this.label ).after( this.iconSpace ); + } else if ( this.icon !== undefined ) { + this.icon.remove(); + this.iconSpace.remove(); + delete this.icon; + } + }, + + _updateLabel: function() { + + // Remove the contents of the label ( minus the icon, icon space, and input ) + this.label.contents().not( this.element.add( this.icon ).add( this.iconSpace ) ).remove(); + this.label.append( this.options.label ); + }, + + refresh: function() { + var checked = this.element[ 0 ].checked, + isDisabled = this.element[ 0 ].disabled; + + this._updateIcon( checked ); + this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked ); + if ( this.options.label !== null ) { + this._updateLabel(); + } + + if ( isDisabled !== this.options.disabled ) { + this._setOptions( { "disabled": isDisabled } ); + } + } + +} ] ); + +return $.ui.checkboxradio; + +} ) ); diff --git a/ui/widgets/controlgroup.js b/ui/widgets/controlgroup.js new file mode 100644 index 000000000..ceb78c7c3 --- /dev/null +++ b/ui/widgets/controlgroup.js @@ -0,0 +1,251 @@ +/*! + * jQuery UI Controlgroup @VERSION + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Controlgroup +//>>group: Widgets +//>>description: Visually groups form control widgets +//>>docs: http://api.jqueryui.com/controlgroup/ +//>>demos: http://jqueryui.com/controlgroup/ +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/controlgroup.css +//>>css.theme: ../../themes/base/theme.css + +( function( factory ) { + if ( typeof define === "function" && define.amd ) { + + // AMD. Register as an anonymous module. + define( [ + "jquery", + "../widget" + ], factory ); + } else { + + // Browser globals + factory( jQuery ); + } +}( function( $ ) { + +return $.widget( "ui.controlgroup", { + version: "@VERSION", + defaultElement: "<div>", + options: { + direction: "horizontal", + disabled: null, + onlyVisible: true, + items: { + "button": "input[type=button], input[type=submit], input[type=reset], button, a", + "controlgroupLabel": ".ui-controlgroup-label", + "checkboxradio": "input[type='checkbox'], input[type='radio']", + "selectmenu": "select", + "spinner": ".ui-spinner-input" + } + }, + + _create: function() { + this._enhance(); + }, + + // To support the enhanced option in jQuery Mobile, we isolate DOM manipulation + _enhance: function() { + this.element.attr( "role", "toolbar" ); + this.refresh(); + }, + + _destroy: function() { + this._callChildMethod( "destroy" ); + this.childWidgets.removeData( "ui-controlgroup-data" ); + this.element.removeAttr( "role" ); + if ( this.options.items.controlgroupLabel ) { + this.element + .find( this.options.items.controlgroupLabel ) + .find( ".ui-controlgroup-label-contents" ) + .contents().unwrap(); + } + }, + + _initWidgets: function() { + var that = this, + childWidgets = []; + + // First we iterate over each of the items options + $.each( this.options.items, function( widget, selector ) { + var labels; + var options = {}; + + // Make sure the widget has a selector set + if ( !selector ) { + return; + } + + if ( widget === "controlgroupLabel" ) { + labels = that.element.find( selector ); + labels.each( function() { + $( this ).contents().wrapAll( "<span class='ui-controlgroup-label-contents'></span>" ); + } ); + that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" ); + childWidgets = childWidgets.concat( labels.get() ); + return; + } + + // Make sure the widget actually exists + if ( !$.fn[ widget ] ) { + return; + } + + // We assume everything is in the middle to start because we can't determine + // first / last elements until all enhancments are done. + if ( that[ "_" + widget + "Options" ] ) { + options = that[ "_" + widget + "Options" ]( "middle" ); + } + + // Find instances of this widget inside controlgroup and init them + that.element + .find( selector )[ widget ]( options ) + .each( function() { + var element = $( this ); + + // Store an instance of the controlgroup to be able to reference + // from the outermost element for changing options and refresh + var widgetElement = element[ widget ]( "widget" ); + $.data( widgetElement[ 0 ], "ui-controlgroup-data", + element[ widget ]( "instance" ) ); + + childWidgets.push( widgetElement[ 0 ] ); + } ); + } ); + + this.childWidgets = $( $.unique( childWidgets ) ); + this._addClass( this.childWidgets, "ui-controlgroup-item" ); + }, + + _callChildMethod: function( method ) { + this.childWidgets.each( function() { + var element = $( this ), + data = element.data( "ui-controlgroup-data" ); + if ( data && data[ method ] ) { + data[ method ](); + } + } ); + }, + + _updateCornerClass: function( element, position ) { + var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right"; + var add = this._buildSimpleOptions( position, "label" ).classes.label; + + this._removeClass( element, null, remove ); + this._addClass( element, null, add ); + }, + + _buildSimpleOptions: function( position, key ) { + var direction = this.options.direction === "vertical"; + var result = { + classes: {} + }; + result.classes[ key ] = { + "middle": null, + "first": "ui-corner-" + ( direction ? "top" : "left" ), + "last": "ui-corner-" + ( direction ? "bottom" : "right" ) + }[ position ]; + + return result; + }, + + _spinnerOptions: function( position ) { + var options = this._buildSimpleOptions( position, "ui-spinner" ); + + options.classes[ "ui-spinner-up" ] = ""; + options.classes[ "ui-spinner-down" ] = ""; + + return options; + }, + + _buttonOptions: function( position ) { + return this._buildSimpleOptions( position, "ui-button" ); + }, + + _checkboxradioOptions: function( position ) { + return this._buildSimpleOptions( position, "ui-checkboxradio-label" ); + }, + + _selectmenuOptions: function( position ) { + var direction = this.options.direction === "vertical"; + return { + width: direction ? "auto" : false, + classes: { + middle: { + "ui-selectmenu-button-open": null, + "ui-selectmenu-button-closed": null + }, + first: { + "ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ), + "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" ) + }, + last: { + "ui-selectmenu-button-open": direction ? null : "ui-corner-tr", + "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" ) + } + + }[ position ] + }; + }, + + _setOption: function( key, value ) { + if ( key === "direction" ) { + this._removeClass( "ui-controlgroup-" + this.options.direction ); + } + + this._super( key, value ); + if ( key === "disabled" ) { + this._callChildMethod( value ? "disable" : "enable" ); + return; + } + + this.refresh(); + }, + + refresh: function() { + var children, + that = this; + + this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction ); + + if ( this.options.direction === "horizontal" ) { + this._addClass( null, "ui-helper-clearfix" ); + } + this._initWidgets(); + + children = this.childWidgets; + + // We filter here because we need to track all childWidgets not just the visible ones + if ( this.options.onlyVisible ) { + children = children.filter( ":visible" ); + } + + if ( children.length ) { + + // We do this last because we need to make sure all enhancment is done + // before determining first and last + $.each( [ "first", "last" ], function( index, value ) { + var instance = children[ value ]().data( "ui-controlgroup-data" ); + + if ( instance && that[ "_" + instance.widgetName + "Options" ] ) { + instance.element[ instance.widgetName ]( + that[ "_" + instance.widgetName + "Options" ]( value ) + ); + } else { + that._updateCornerClass( children[ value ](), value ); + } + } ); + + // Finally call the refresh method on each of the child widgets. + this._callChildMethod( "refresh" ); + } + } +} ); +} ) ); diff --git a/ui/widgets/dialog.js b/ui/widgets/dialog.js index 6070014c9..c3ca95ed3 100644 --- a/ui/widgets/dialog.js +++ b/ui/widgets/dialog.js @@ -12,9 +12,9 @@ //>>description: Displays customizable dialog windows. //>>docs: http://api.jqueryui.com/dialog/ //>>demos: http://jqueryui.com/dialog/ -//>>css.structure: ../themes/base/core.css -//>>css.structure: ../themes/base/dialog.css -//>>css.theme: ../themes/base/theme.css +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/dialog.css +//>>css.theme: ../../themes/base/theme.css ( function( factory ) { if ( typeof define === "function" && define.amd ) { @@ -426,11 +426,9 @@ $.widget( "ui.dialog", { // dialog in IE (#9312) this.uiDialogTitlebarClose = $( "<button type='button'></button>" ) .button( { - label: this.options.closeText, - icons: { - primary: "ui-icon-closethick" - }, - text: false + label: $( "<a>" ).text( this.options.closeText ).html(), + icon: "ui-icon-closethick", + showLabel: false } ) .appendTo( this.uiDialogTitlebar ); @@ -498,12 +496,15 @@ $.widget( "ui.dialog", { // Change the context for the click callback to be the main element click = props.click; buttonOptions = { - icons: props.icons, - text: props.showText + icon: props.icon, + iconPosition: props.iconPosition, + showLabel: props.showLabel }; - delete props.icons; - delete props.showText; + delete props.click; + delete props.icon; + delete props.iconPosition; + delete props.showLabel; $( "<button></button>", props ) .button( buttonOptions ) @@ -714,7 +715,7 @@ $.widget( "ui.dialog", { this.uiDialogTitlebarClose.button( { // Ensure that we always pass a string - label: "" + value + label: $( "<a>" ).text( "" + this.options.closeText ).html() } ); } diff --git a/ui/widgets/draggable.js b/ui/widgets/draggable.js index f61c38ce0..7da09b7ec 100644 --- a/ui/widgets/draggable.js +++ b/ui/widgets/draggable.js @@ -12,7 +12,7 @@ //>>description: Enables dragging functionality for any element. //>>docs: http://api.jqueryui.com/draggable/ //>>demos: http://jqueryui.com/draggable/ -//>>css.structure: ../themes/base/draggable.css +//>>css.structure: ../../themes/base/draggable.css ( function( factory ) { if ( typeof define === "function" && define.amd ) { @@ -255,7 +255,7 @@ $.widget( "ui.draggable", $.ui.mouse, { if ( !noPropagation ) { var ui = this._uiHash(); if ( this._trigger( "drag", event, ui ) === false ) { - this._mouseUp( {} ); + this._mouseUp( new $.Event( "mouseup", event ) ); return false; } this.position = ui.position; @@ -322,7 +322,7 @@ $.widget( "ui.draggable", $.ui.mouse, { cancel: function() { if ( this.helper.is( ".ui-draggable-dragging" ) ) { - this._mouseUp( {} ); + this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) ); } else { this._clear(); } diff --git a/ui/widgets/menu.js b/ui/widgets/menu.js index d42d65bac..e7b13e7c9 100644 --- a/ui/widgets/menu.js +++ b/ui/widgets/menu.js @@ -12,9 +12,9 @@ //>>description: Creates nestable menus. //>>docs: http://api.jqueryui.com/menu/ //>>demos: http://jqueryui.com/menu/ -//>>css.structure: ../themes/base/core.css -//>>css.structure: ../themes/base/menu.css -//>>css.theme: ../themes/base/theme.css +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/menu.css +//>>css.theme: ../../themes/base/theme.css ( function( factory ) { if ( typeof define === "function" && define.amd ) { diff --git a/ui/widgets/mouse.js b/ui/widgets/mouse.js index 938d0f4b7..c14aebe53 100644 --- a/ui/widgets/mouse.js +++ b/ui/widgets/mouse.js @@ -8,7 +8,7 @@ */ //>>label: Mouse -//>>group: UI Core +//>>group: Widgets //>>description: Abstracts mouse-based interactions to assist in creating certain widgets. //>>docs: http://api.jqueryui.com/mouse/ @@ -146,7 +146,16 @@ return $.widget( "ui.mouse", { // Iframe mouseup check - mouseup occurred in another document } else if ( !event.which ) { - return this._mouseUp( event ); + + // Support: Safari <=8 - 9 + // Safari sets which to 0 if you press any of the following keys + // during a drag (#14461) + if ( event.originalEvent.altKey || event.originalEvent.ctrlKey || + event.originalEvent.metaKey || event.originalEvent.shiftKey ) { + this.ignoreMissingWhich = true; + } else if ( !this.ignoreMissingWhich ) { + return this._mouseUp( event ); + } } } @@ -188,8 +197,9 @@ return $.widget( "ui.mouse", { delete this._mouseDelayTimer; } + this.ignoreMissingWhich = false; mouseHandled = false; - return false; + event.preventDefault(); }, _mouseDistanceMet: function( event ) { diff --git a/ui/widgets/progressbar.js b/ui/widgets/progressbar.js index 7e2695994..6afba892e 100644 --- a/ui/widgets/progressbar.js +++ b/ui/widgets/progressbar.js @@ -12,9 +12,9 @@ //>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators. //>>docs: http://api.jqueryui.com/progressbar/ //>>demos: http://jqueryui.com/progressbar/ -//>>css.structure: ../themes/base/core.css -//>>css.structure: ../themes/base/progressbar.css -//>>css.theme: ../themes/base/theme.css +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/progressbar.css +//>>css.theme: ../../themes/base/theme.css ( function( factory ) { if ( typeof define === "function" && define.amd ) { diff --git a/ui/widgets/resizable.js b/ui/widgets/resizable.js index 74e664c43..88ad41180 100644 --- a/ui/widgets/resizable.js +++ b/ui/widgets/resizable.js @@ -12,9 +12,9 @@ //>>description: Enables resize functionality for any element. //>>docs: http://api.jqueryui.com/resizable/ //>>demos: http://jqueryui.com/resizable/ -//>>css.structure: ../themes/base/core.css -//>>css.structure: ../themes/base/resizable.css -//>>css.theme: ../themes/base/theme.css +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/resizable.css +//>>css.theme: ../../themes/base/theme.css ( function( factory ) { if ( typeof define === "function" && define.amd ) { @@ -99,7 +99,7 @@ $.widget( "ui.resizable", $.ui.mouse, { _create: function() { - var n, i, handle, axis, hname, + var n, i, handle, axis, hname, margins, that = this, o = this.options; this._addClass( "ui-resizable" ); @@ -131,18 +131,15 @@ $.widget( "ui.resizable", $.ui.mouse, { this.elementIsWrapper = true; - this.element.css( { - marginLeft: this.originalElement.css( "marginLeft" ), + margins = { marginTop: this.originalElement.css( "marginTop" ), marginRight: this.originalElement.css( "marginRight" ), - marginBottom: this.originalElement.css( "marginBottom" ) - } ); - this.originalElement.css( { - marginLeft: 0, - marginTop: 0, - marginRight: 0, - marginBottom: 0 - } ); + marginBottom: this.originalElement.css( "marginBottom" ), + marginLeft: this.originalElement.css( "marginLeft" ) + }; + + this.element.css( margins ); + this.originalElement.css( "margin", 0 ); // support: Safari // Prevent Safari textarea resize @@ -157,7 +154,7 @@ $.widget( "ui.resizable", $.ui.mouse, { // Support: IE9 // avoid IE jump (hard set the margin) - this.originalElement.css( { margin: this.originalElement.css( "margin" ) } ); + this.originalElement.css( margins ); this._proportionallyResize(); } @@ -690,8 +687,8 @@ $.widget( "ui.resizable", $.ui.mouse, { this._addClass( this.helper, this._helper ); this.helper.css( { - width: this.element.outerWidth() - 1, - height: this.element.outerHeight() - 1, + width: this.element.outerWidth(), + height: this.element.outerHeight(), position: "absolute", left: this.elementOffset.left + "px", top: this.elementOffset.top + "px", @@ -1035,7 +1032,7 @@ $.ui.plugin.add( "resizable", "alsoResize", { }, stop: function() { - $( this ).removeData( "resizable-alsoresize" ); + $( this ).removeData( "ui-resizable-alsoresize" ); } } ); diff --git a/ui/widgets/selectable.js b/ui/widgets/selectable.js index 152729d7c..f3f144a81 100644 --- a/ui/widgets/selectable.js +++ b/ui/widgets/selectable.js @@ -12,7 +12,7 @@ //>>description: Allows groups of elements to be selected with the mouse. //>>docs: http://api.jqueryui.com/selectable/ //>>demos: http://jqueryui.com/selectable/ -//>>css.structure: ../themes/base/selectable.css +//>>css.structure: ../../themes/base/selectable.css ( function( factory ) { if ( typeof define === "function" && define.amd ) { diff --git a/ui/widgets/selectmenu.js b/ui/widgets/selectmenu.js index 30d8c71af..b251f04f1 100644 --- a/ui/widgets/selectmenu.js +++ b/ui/widgets/selectmenu.js @@ -12,9 +12,9 @@ //>>description: Duplicates and extends the functionality of a native HTML select element, allowing it to be customizable in behavior and appearance far beyond the limitations of a native select. //>>docs: http://api.jqueryui.com/selectmenu/ //>>demos: http://jqueryui.com/selectmenu/ -//>>css.structure: ../themes/base/core.css -//>>css.structure: ../themes/base/selectmenu.css -//>>css.theme: ../themes/base/theme.css +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css +//>>css.theme: ../../themes/base/theme.css ( function( factory ) { if ( typeof define === "function" && define.amd ) { @@ -24,6 +24,7 @@ "jquery", "./menu", "../escape-selector", + "../form-reset-mixin", "../keycode", "../labels", "../position", @@ -38,7 +39,7 @@ } }( function( $ ) { -return $.widget( "ui.selectmenu", { +return $.widget( "ui.selectmenu", [ $.ui.formResetMixin, { version: "@VERSION", defaultElement: "<select>", options: { @@ -76,13 +77,14 @@ return $.widget( "ui.selectmenu", { this._drawButton(); this._drawMenu(); + this._bindFormResetHandler(); this._rendered = false; this.menuItems = $(); }, _drawButton: function() { - var icon, + var icon, space, that = this, item = this._parseOption( this.element.find( "option:selected" ), @@ -115,10 +117,13 @@ return $.widget( "ui.selectmenu", { .insertAfter( this.element ); this._addClass( this.button, "ui-selectmenu-button ui-selectmenu-button-closed", - "ui-widget ui-state-default" ); + "ui-button ui-widget" ); icon = $( "<span>" ).prependTo( this.button ); + space = $( "<span> </span>" ); + this._addClass( space, "ui-selectmenu-icon-space" ); this._addClass( icon, null, "ui-icon " + this.options.icons.button ); + icon.after( space ); this.buttonItem = this._renderButtonItem( item ) .appendTo( this.button ); @@ -136,8 +141,6 @@ return $.widget( "ui.selectmenu", { that._refreshMenu(); } } ); - this._hoverable( this.button ); - this._focusable( this.button ); }, _drawMenu: function() { @@ -606,7 +609,7 @@ return $.widget( "ui.selectmenu", { // we always remove classes first and add them second, otherwise if both classes have the // same theme class, it will be removed after we add it. this._removeClass( this.button, "ui-selectmenu-button-" + - ( this.isOpen ? "closed" : "open" ) ) + ( this.isOpen ? "closed" : "open" ) ) ._addClass( this.button, "ui-selectmenu-button-" + ( this.isOpen ? "open" : "closed" ) ) ._toggleClass( this.menuWrap, "ui-selectmenu-open", null, this.isOpen ); @@ -674,12 +677,13 @@ return $.widget( "ui.selectmenu", { }, _destroy: function() { + this._unbindFormResetHandler(); this.menuWrap.remove(); this.button.remove(); this.element.show(); this.element.removeUniqueId(); this.labels.attr( "for", this.ids.element ); } -} ); +} ] ); } ) ); diff --git a/ui/widgets/slider.js b/ui/widgets/slider.js index 8b8a7292a..a2da892c4 100644 --- a/ui/widgets/slider.js +++ b/ui/widgets/slider.js @@ -12,9 +12,9 @@ //>>description: Displays a flexible slider with ranges and accessibility via keyboard. //>>docs: http://api.jqueryui.com/slider/ //>>demos: http://jqueryui.com/slider/ -//>>css.structure: ../themes/base/core.css -//>>css.structure: ../themes/base/slider.css -//>>css.theme: ../themes/base/theme.css +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/slider.css +//>>css.theme: ../../themes/base/theme.css ( function( factory ) { if ( typeof define === "function" && define.amd ) { diff --git a/ui/widgets/sortable.js b/ui/widgets/sortable.js index 423bb81f8..8920ed967 100644 --- a/ui/widgets/sortable.js +++ b/ui/widgets/sortable.js @@ -12,7 +12,7 @@ //>>description: Enables items in a list to be sorted using the mouse. //>>docs: http://api.jqueryui.com/sortable/ //>>demos: http://jqueryui.com/sortable/ -//>>css.structure: ../themes/base/sortable.css +//>>css.structure: ../../themes/base/sortable.css ( function( factory ) { if ( typeof define === "function" && define.amd ) { diff --git a/ui/widgets/spinner.js b/ui/widgets/spinner.js index f79b2baed..e875f10ad 100644 --- a/ui/widgets/spinner.js +++ b/ui/widgets/spinner.js @@ -12,9 +12,9 @@ //>>description: Displays buttons to easily input numbers via the keyboard or mouse. //>>docs: http://api.jqueryui.com/spinner/ //>>demos: http://jqueryui.com/spinner/ -//>>css.structure: ../themes/base/core.css -//>>css.structure: ../themes/base/spinner.css -//>>css.theme: ../themes/base/theme.css +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/spinner.css +//>>css.theme: ../../themes/base/theme.css ( function( factory ) { if ( typeof define === "function" && define.amd ) { @@ -230,12 +230,7 @@ $.widget( "ui.spinner", { // Add buttons .append( - "<a>" + - "<span>▲</span>" + - "</a>" + - "<a>" + - "<span>▼</span>" + - "</a>" + "<a></a><a></a>" ); }, @@ -250,17 +245,26 @@ $.widget( "ui.spinner", { // Button bindings this.buttons = this.uiSpinner.children( "a" ) .attr( "tabIndex", -1 ) - .button(); + .attr( "aria-hidden", true ) + .button( { + classes: { + "ui-button": "" + } + } ); // TODO: Right now button does not support classes this is already updated in button PR this._removeClass( this.buttons, "ui-corner-all" ); this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" ); this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" ); - this._addClass( this.buttons.first().find( ".ui-button-text span" ), null, - "ui-icon " + this.options.icons.up ); - this._addClass( this.buttons.last().find( ".ui-button-text span" ), null, - "ui-icon " + this.options.icons.down ); + this.buttons.first().button( { + "icon": this.options.icons.up, + "showLabel": false + } ); + this.buttons.last().button( { + "icon": this.options.icons.down, + "showLabel": false + } ); // IE 6 doesn't understand height: 50% for the buttons // unless the wrapper has an explicit height @@ -559,13 +563,7 @@ if ( $.uiBackCompat !== false ) { }, _buttonHtml: function() { - return "" + - "<a>" + - "<span>▲</span>" + - "</a>" + - "<a>" + - "<span>▼</span>" + - "</a>"; + return "<a></a><a></a>"; } } ); } diff --git a/ui/widgets/tabs.js b/ui/widgets/tabs.js index baece431d..a35386541 100644 --- a/ui/widgets/tabs.js +++ b/ui/widgets/tabs.js @@ -12,9 +12,9 @@ //>>description: Transforms a set of container elements into a tab structure. //>>docs: http://api.jqueryui.com/tabs/ //>>demos: http://jqueryui.com/tabs/ -//>>css.structure: ../themes/base/core.css -//>>css.structure: ../themes/base/tabs.css -//>>css.theme: ../themes/base/theme.css +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/tabs.css +//>>css.theme: ../../themes/base/theme.css ( function( factory ) { if ( typeof define === "function" && define.amd ) { diff --git a/ui/widgets/tooltip.js b/ui/widgets/tooltip.js index daf783a98..94021092a 100644 --- a/ui/widgets/tooltip.js +++ b/ui/widgets/tooltip.js @@ -12,9 +12,9 @@ //>>description: Shows additional information for any element on hover or focus. //>>docs: http://api.jqueryui.com/tooltip/ //>>demos: http://jqueryui.com/tooltip/ -//>>css.structure: ../themes/base/core.css -//>>css.structure: ../themes/base/tooltip.css -//>>css.theme: ../themes/base/theme.css +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/tooltip.css +//>>css.theme: ../../themes/base/theme.css ( function( factory ) { if ( typeof define === "function" && define.amd ) { @@ -318,7 +318,8 @@ $.widget( "ui.tooltip", { // Handle tracking tooltips that are shown with a delay (#8644). As soon // as the tooltip is visible, position the tooltip using the most recent // event. - if ( this.options.show && this.options.show.delay ) { + // Adds the check to add the timers only when both delay and track options are set (#14682) + if ( this.options.track && this.options.show && this.options.show.delay ) { delayedShow = this.delayedShow = setInterval( function() { if ( tooltip.is( ":visible" ) ) { position( positionOption.of ); |