diff --git a/README.md b/README.md index 5c7d79a13..9a0d7c5c5 100644 --- a/README.md +++ b/README.md @@ -7,3 +7,20 @@ If you want to use jQuery UI, go to [jqueryui.com](http://jqueryui.com) to get s If you are interested in helping developing jQuery UI, you are in the right place. To discuss development with team members and the community, visit the [Developing jQuery UI Forum](http://forum.jquery.com/developing-jquery-ui). + +For commiters +--- +When looking at pull requests, first check for [proper commit messages](http://wiki.jqueryui.com/w/page/12137724/Bug-Fixing-Guide). + +Unless everything is fine and you can merge directly via GitHub's interface, fetch the remote first: + + git remote add [username] [his-fork.git] -f + +If you want just one commit and edit the commit message: + + git cherry-pick -e [sha-of-commit] + +If it should go to the stable brach, cherry-pick it to stable: + + git checkout 1-8-stable + git cherry-pick -x [sha-of-commit] diff --git a/demos/autocomplete/combobox.html b/demos/autocomplete/combobox.html index ded809e1e..5fb3ffef9 100644 --- a/demos/autocomplete/combobox.html +++ b/demos/autocomplete/combobox.html @@ -16,7 +16,7 @@ + + @@ -279,6 +281,8 @@
Datepicker
Dialog
Menu
+
Menubar
+
Popup
Progressbar
Slider
Spinner
diff --git a/demos/menu/contextmenu.html b/demos/menu/contextmenu.html index 0fb98c140..115f15b24 100644 --- a/demos/menu/contextmenu.html +++ b/demos/menu/contextmenu.html @@ -3,44 +3,28 @@ jQuery UI Menu - Contextmenu demo - - - - - - - - - + + + + + + + + +
+
Log: -
+
+
+ +
+ +

TODO

+ +
+ diff --git a/demos/menubar/index.html b/demos/menubar/index.html new file mode 100644 index 000000000..3eebda2d0 --- /dev/null +++ b/demos/menubar/index.html @@ -0,0 +1,16 @@ + + + + + jQuery UI Menubar Demos + + + +
+

Examples

+ +
+ + diff --git a/demos/popup/default.html b/demos/popup/default.html new file mode 100644 index 000000000..71b3c8dd2 --- /dev/null +++ b/demos/popup/default.html @@ -0,0 +1,83 @@ + + + + jQuery UI Popup - Default demo + + + + + + + + + + + + + + +
+ Log In +
+
+
+ + +
+
+ + +
+
+ +
+
+
+
+ +
+ +

A link to a login form that opens as a popup. [Not quite functional, focus handling needs to get better]

+ +
+ + + + diff --git a/demos/popup/index.html b/demos/popup/index.html new file mode 100644 index 000000000..e69365c98 --- /dev/null +++ b/demos/popup/index.html @@ -0,0 +1,18 @@ + + + + + jQuery UI Popup Demos + + + +
+

Examples

+ +
+ + diff --git a/demos/popup/popup-menu-table.html b/demos/popup/popup-menu-table.html new file mode 100644 index 000000000..a06a38434 --- /dev/null +++ b/demos/popup/popup-menu-table.html @@ -0,0 +1,108 @@ + + + + jQuery UI Popup - Menu as Popup in table demo + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameRelease YearAverage Rating
Red Hot Chili Peppers: Funky Monks19933.6 + +
Rod Stewart: Storyteller 1984-199119913.1
Stevie Ray Vaughan and Double Trouble: Live at the El Mocambo 198319913.9
Spike and Mike's Sick & Twisted Festival of Animation19972.6
+ +
+
+ + +
+ +

Poup menu in a table. Works okay standalone, not so much in the scrolling demo view. For that to work better, position() would have to take the closest scrolled parent into account for collision detection.

+ +
+ + + + diff --git a/demos/popup/popup-menu.html b/demos/popup/popup-menu.html new file mode 100644 index 000000000..7152d85bc --- /dev/null +++ b/demos/popup/popup-menu.html @@ -0,0 +1,98 @@ + + + + jQuery UI Popup - Popup Menu + + + + + + + + + + + + + + +
+ + + + + +
+
+ + + +
+
+ +
+
+ + +
+ +

Make the popup a menu (or the menu a popup) and you get context menus.

+ +
+ + + + diff --git a/demos/resizable/constrain-area.html b/demos/resizable/constrain-area.html index a7003352c..33539f940 100644 --- a/demos/resizable/constrain-area.html +++ b/demos/resizable/constrain-area.html @@ -10,7 +10,7 @@ - + @@ -65,23 +98,23 @@ - +
- + +
- diff --git a/tests/unit/autocomplete/autocomplete_events.js b/tests/unit/autocomplete/autocomplete_events.js index 35103d89b..eb009064c 100644 --- a/tests/unit/autocomplete/autocomplete_events.js +++ b/tests/unit/autocomplete/autocomplete_events.js @@ -203,4 +203,20 @@ test("cancel select", function() { }, 50); }); +test("blur without selection", function() { + expect(1); + var ac = $("#autocomplete").autocomplete({ + delay: 0, + source: data + }); + stop(); + ac.val("j").keydown(); + setTimeout(function() { + $( ".ui-menu-item" ).first().simulate("mouseover"); + ac.simulate("keydown", { keyCode: $.ui.keyCode.TAB }); + same( ac.val(), "j" ); + start(); + }, 50); +}); + })(jQuery); diff --git a/tests/unit/datepicker/datepicker.html b/tests/unit/datepicker/datepicker.html index 76082e780..fa346c6c9 100644 --- a/tests/unit/datepicker/datepicker.html +++ b/tests/unit/datepicker/datepicker.html @@ -12,6 +12,7 @@ + diff --git a/tests/unit/datepicker/datepicker_core.js b/tests/unit/datepicker/datepicker_core.js index 78f78ce38..badb837ed 100644 --- a/tests/unit/datepicker/datepicker_core.js +++ b/tests/unit/datepicker/datepicker_core.js @@ -116,8 +116,16 @@ test('baseStructure', function() { ok(child.is('div.ui-datepicker-group') && child.is('div.ui-datepicker-group-last'), 'Structure multi [2] - second month division'); child = dp.children(':eq(2)'); ok(child.is('div.ui-datepicker-row-break'), 'Structure multi [2] - row break'); + ok(dp.is('.ui-datepicker-multi-2'), 'Structure multi [2] - multi-2'); inp.datepicker('hide').datepicker('destroy'); + // Multi-month 3 + inp = init('#inp', {numberOfMonths: 3}); + inp.focus(); + ok(dp.is('.ui-datepicker-multi-3'), 'Structure multi [3] - multi-3'); + ok(! dp.is('.ui-datepicker-multi-2'), 'Structure multi [3] - Trac #6704'); + inp.datepicker('hide').datepicker('destroy'); + // Multi-month [2, 2] inp = init('#inp', {numberOfMonths: [2, 2]}); inp.focus(); diff --git a/tests/unit/datepicker/datepicker_options.js b/tests/unit/datepicker/datepicker_options.js index 4f1e9a164..a10d1ea45 100644 --- a/tests/unit/datepicker/datepicker_options.js +++ b/tests/unit/datepicker/datepicker_options.js @@ -827,6 +827,10 @@ test('parseDate', function() { equalsDate($.datepicker.parseDate('\'jour\' d \'de\' MM (\'\'DD\'\'), yy', 'jour 9 de Avril (\'Lundi\'), 2001', settings), new Date(2001, 4 - 1, 9), 'Parse date \'jour\' d \'de\' MM (\'\'DD\'\'), yy with settings'); + + var zh = $.datepicker.regional['zh-CN']; + equalsDate($.datepicker.parseDate('yy M d', '2011 十一 22', zh), + new Date(2011, 11 - 1, 22), 'Parse date yy M d with zh-CN'); }); test('parseDateErrors', function() { diff --git a/tests/unit/tabs/spinner.gif b/tests/unit/tabs/spinner.gif deleted file mode 100644 index 822747576..000000000 Binary files a/tests/unit/tabs/spinner.gif and /dev/null differ diff --git a/tests/unit/tabs/tabs.html b/tests/unit/tabs/tabs.html index 565a0b427..34ec28bc4 100644 --- a/tests/unit/tabs/tabs.html +++ b/tests/unit/tabs/tabs.html @@ -24,7 +24,6 @@ - - - - - - - - - - - - - - - - - - - -
- Log: -
-
- - - - - - diff --git a/tests/visual/menu/menubar.js b/tests/visual/menu/menubar.js deleted file mode 100644 index cc3258d4a..000000000 --- a/tests/visual/menu/menubar.js +++ /dev/null @@ -1,234 +0,0 @@ -/* - * jQuery UI menubar - * - * backported from Michael Lang's fork: http://www.nexul.com/prototypes/toolbar/demo.html - */ -(function($) { - -// TODO take non-menubar buttons into account -$.widget("ui.menubar", { - options: { - buttons: false, - menuIcon: false - }, - _create: function() { - var self = this; - var items = this.items = this.element.children("li") - .addClass("ui-menubar-item") - .attr("role", "presentation") - .children("button, a"); - items.slice(1).attr("tabIndex", -1); - var o = this.options; - - this.element.addClass('ui-menubar ui-widget-header ui-helper-clearfix').attr("role", "menubar"); - this._focusable(items); - this._hoverable(items); - items.next("ul").each(function(i, elm) { - $(elm).menu({ - select: function(event, ui) { - ui.item.parents("ul.ui-menu:last").hide(); - self._trigger( "select", event, ui ); - self._close(); - $(event.target).prev().focus(); - } - }).hide() - .attr("aria-hidden", "true") - .attr("aria-expanded", "false") - .keydown(function(event) { - var menu = $(this); - if (menu.is(":hidden")) - return; - switch (event.keyCode) { - case $.ui.keyCode.LEFT: - self._left(event); - event.preventDefault(); - break; - case $.ui.keyCode.RIGHT: - self._right(event); - event.preventDefault(); - break; - }; - }) - }); - items.each(function() { - var input = $(this), - menu = input.next("ul"); - - input.bind("click focus mouseenter", function(event) { - // ignore triggered focus event - if (event.type == "focus" && !event.originalEvent) { - return; - } - event.preventDefault(); - if (event.type == "click" && menu.is(":visible") && self.active && self.active[0] == menu[0]) { - self._close(); - return; - } - if ((self.open && event.type == "mouseenter") || event.type == "click") { - self._open(event, menu); - } - }) - .bind( "keydown", function( event ) { - switch ( event.keyCode ) { - case $.ui.keyCode.SPACE: - case $.ui.keyCode.UP: - case $.ui.keyCode.DOWN: - self._open( event, $( this ).next() ); - event.preventDefault(); - break; - case $.ui.keyCode.LEFT: - self._prev( event, $( this ) ); - event.preventDefault(); - break; - case $.ui.keyCode.RIGHT: - self._next( event, $( this ) ); - event.preventDefault(); - break; - } - }) - .addClass("ui-button ui-widget ui-button-text-only ui-menubar-link") - .attr("role", "menuitem") - .attr("aria-haspopup", "true") - .wrapInner(""); - - if (o.menuIcon) { - input.addClass("ui-state-default").append(""); - input.removeClass("ui-button-text-only").addClass("ui-button-text-icon-secondary"); - } - - if (!o.buttons) { - input.addClass('ui-menubar-link').removeClass('ui-state-default'); - }; - - }); - self._bind({ - keydown: function(event) { - if (event.keyCode == $.ui.keyCode.ESCAPE) { - if (self.active && self.active.menu("left", event) !== true) { - var active = self.active; - self.active.blur(); - self._close( event ); - active.prev().focus(); - } - } - }, - focusout : function( event ) { - self.closeTimer = setTimeout(function() { - self._close( event ); - }, 100); - }, - focusin :function( event ) { - clearTimeout(self.closeTimer); - } - }); - }, - - _destroy : function() { - var items = this.element.children("li") - .removeClass("ui-menubar-item") - .removeAttr("role", "presentation") - .children("button, a"); - - this.element.removeClass('ui-menubar ui-widget-header ui-helper-clearfix').removeAttr("role", "menubar").unbind(".menubar");; - items.unbind("focusin focusout click focus mouseenter keydown"); - - items - .removeClass("ui-button ui-widget ui-button-text-only ui-menubar-link ui-state-default") - .removeAttr("role", "menuitem") - .removeAttr("aria-haspopup", "true") - .children("span.ui-button-text").each(function(i, e) { - var item = $(this); - item.parent().html(item.html()); - }) - .end() - .children(".ui-icon").remove(); - - $(document).unbind(".menubar"); - - this.element.find(":ui-menu").menu("destroy") - .show() - .removeAttr("aria-hidden", "true") - .removeAttr("aria-expanded", "false") - .removeAttr("tabindex") - .unbind("keydown", "blur") - ; - }, - - _close: function() { - if (!this.active || !this.active.length) - return; - this.active.menu("closeAll").hide().attr("aria-hidden", "true").attr("aria-expanded", "false"); - this.active.prev().removeClass("ui-state-active").removeAttr("tabIndex"); - this.active = null; - this.open = false; - }, - - _open: function(event, menu) { - // on a single-button menubar, ignore reopening the same menu - if (this.active && this.active[0] == menu[0]) { - return; - } - // almost the same as _close above, but don't remove tabIndex - if (this.active) { - this.active.menu("closeAll").hide().attr("aria-hidden", "true").attr("aria-expanded", "false"); - this.active.prev().removeClass("ui-state-active"); - } - // set tabIndex -1 to have the button skipped on shift-tab when menu is open (it gets focus) - var button = menu.prev().addClass("ui-state-active").attr("tabIndex", -1); - this.active = menu.show().position({ - my: "left top", - at: "left bottom", - of: button - }) - .removeAttr("aria-hidden").attr("aria-expanded", "true") - .menu("focus", event, menu.children("li").first()) - .focus() - .focusin() - ; - this.open = true; - }, - - _prev: function( event, button ) { - button.attr("tabIndex", -1); - var prev = button.parent().prevAll("li").children( ".ui-button" ).eq( 0 ); - if (prev.length) { - prev.removeAttr("tabIndex")[0].focus(); - } else { - var lastItem = this.element.children("li:last").children(".ui-button:last"); - lastItem.removeAttr("tabIndex")[0].focus(); - } - }, - - _next: function( event, button ) { - button.attr("tabIndex", -1); - var next = button.parent().nextAll("li").children( ".ui-button" ).eq( 0 ); - if (next.length) { - next.removeAttr("tabIndex")[0].focus(); - } else { - var firstItem = this.element.children("li:first").children(".ui-button:first"); - firstItem.removeAttr("tabIndex")[0].focus(); - } - }, - - _left: function(event) { - var prev = this.active.parent().prevAll("li:eq(0)").children( ".ui-menu" ).eq( 0 ); - if (prev.length) { - this._open(event, prev); - } else { - var lastItem = this.element.children("li:last").children(".ui-menu:first"); - this._open(event, lastItem); - } - }, - - _right: function(event) { - var next = this.active.parent().nextAll("li:eq(0)").children( ".ui-menu" ).eq( 0 ); - if (next.length) { - this._open(event, next); - } else { - var firstItem = this.element.children("li:first").children(".ui-menu:first"); - this._open(event, firstItem); - } - } -}); - -}(jQuery)); diff --git a/tests/visual/menu/popup.html b/tests/visual/menu/popup.html deleted file mode 100644 index 271002a20..000000000 --- a/tests/visual/menu/popup.html +++ /dev/null @@ -1,176 +0,0 @@ - - - - Visual Test for Popup Utility - - - - - - - - - - - - - - - -
- Project members -
- some form controls in here -
-
- - - - - -
-
- - -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameRelease YearAverage Rating
Red Hot Chili Peppers: Funky Monks19933.6 - -
Rod Stewart: Storyteller 1984-199119913.1
Stevie Ray Vaughan and Double Trouble: Live at the El Mocambo 198319913.9
Spike and Mike's Sick & Twisted Festival of Animation19972.6
- -
- Log: -
-
- - - diff --git a/tests/visual/menu/popup.js b/tests/visual/menu/popup.js deleted file mode 100644 index f57cba699..000000000 --- a/tests/visual/menu/popup.js +++ /dev/null @@ -1,124 +0,0 @@ -/* - * jQuery UI popup utility - */ -(function($) { - -var idIncrement = 0; - -$.widget( "ui.popup", { - options: { - position: { - my: "left top", - at: "left bottom" - } - }, - _create: function() { - if ( !this.options.trigger ) { - this.options.trigger = this.element.prev(); - } - - if ( !this.element.attr( "id" ) ) { - this.element.attr( "id", "ui-popup-" + idIncrement++ ); - this.generatedId = true; - } - - if ( !this.element.attr( "role" ) ) { - // TODO alternatives to tooltip are dialog and menu, all three aren't generic popups - this.element.attr( "role", "tooltip" ); - this.generatedRole = true; - } - - this.options.trigger - .attr( "aria-haspopup", true ) - .attr( "aria-owns", this.element.attr( "id" ) ); - - this.element - .addClass("ui-popup") - this._close(); - - this._bind(this.options.trigger, { - click: function( event ) { - event.preventDefault(); - var that = this; - setTimeout(function() { - that._open( event ); - }, 1); - } - }); - - this._bind(this.element, { - blur: "_close" - }); - - this._bind({ - keyup: function( event ) { - if (event.keyCode == $.ui.keyCode.ESCAPE && this.element.is( ":visible" )) { - this._close( event ); - this.options.trigger.focus(); - } - } - }); - - this._bind(document, { - click: function( event ) { - if (this.open && !$(event.target).closest(".ui-popup").length) { - this._close( event ); - } - } - }) - }, - - _destroy: function() { - this.element - .show() - .removeClass( "ui-popup" ) - .removeAttr( "aria-hidden" ) - .removeAttr( "aria-expanded" ); - - this.options.trigger - .removeAttr( "aria-haspopup" ) - .removeAttr( "aria-owns" ); - - if ( this.generatedId ) { - this.element.removeAttr( "id" ); - } - if ( this.generatedRole ) { - this.element.removeAttr( "role" ); - } - }, - - _open: function( event ) { - var position = $.extend( {}, { - of: this.options.trigger - }, this.options.position ); - - this.element - .show() - .attr( "aria-hidden", false ) - .attr( "aria-expanded", true ) - .position( position ) - .focus(); - - // take trigger out of tab order to allow shift-tab to skip trigger - this.options.trigger.attr("tabindex", -1); - - this.open = true; - this._trigger( "open", event ); - }, - - _close: function( event ) { - this.element - .hide() - .attr( "aria-hidden", true ) - .attr( "aria-expanded", false ); - - this.options.trigger.attr("tabindex", 0); - - this.open = false; - this._trigger( "close", event ); - } - - -}); - -}(jQuery)); diff --git a/ui/i18n/jquery.ui.datepicker-af.js b/ui/i18n/jquery.ui.datepicker-af.js index 43fbf6cd8..0922ef7a1 100644 --- a/ui/i18n/jquery.ui.datepicker-af.js +++ b/ui/i18n/jquery.ui.datepicker-af.js @@ -1,4 +1,4 @@ -/* Afrikaans initialisation for the jQuery UI date picker plugin. */ +/* Afrikaans initialisation for the jQuery UI date picker plugin. */ /* Written by Renier Pretorius. */ jQuery(function($){ $.datepicker.regional['af'] = { diff --git a/ui/i18n/jquery.ui.datepicker-ar.js b/ui/i18n/jquery.ui.datepicker-ar.js index db5773558..f24b3ff5a 100644 --- a/ui/i18n/jquery.ui.datepicker-ar.js +++ b/ui/i18n/jquery.ui.datepicker-ar.js @@ -1,4 +1,4 @@ -/* Arabic Translation for jQuery UI date picker plugin. */ +/* Arabic Translation for jQuery UI date picker plugin. */ /* Khaled Alhourani -- me@khaledalhourani.com */ /* NOTE: monthNames are the original months names and they are the Arabic names, not the new months name فبراير - يناير and there isn't any Arabic roots for these months */ jQuery(function($){ diff --git a/ui/i18n/jquery.ui.datepicker-az.js b/ui/i18n/jquery.ui.datepicker-az.js index 0f60a7e1d..1101c8b91 100644 --- a/ui/i18n/jquery.ui.datepicker-az.js +++ b/ui/i18n/jquery.ui.datepicker-az.js @@ -1,4 +1,4 @@ -/* Azerbaijani (UTF-8) initialisation for the jQuery UI date picker plugin. */ +/* Azerbaijani (UTF-8) initialisation for the jQuery UI date picker plugin. */ /* Written by Jamil Najafov (necefov33@gmail.com). */ jQuery(function($) { $.datepicker.regional['az'] = { diff --git a/ui/i18n/jquery.ui.datepicker-bg.js b/ui/i18n/jquery.ui.datepicker-bg.js index ae850ef80..4e0ee2f50 100644 --- a/ui/i18n/jquery.ui.datepicker-bg.js +++ b/ui/i18n/jquery.ui.datepicker-bg.js @@ -1,4 +1,4 @@ -/* Bulgarian initialisation for the jQuery UI date picker plugin. */ +/* Bulgarian initialisation for the jQuery UI date picker plugin. */ /* Written by Stoyan Kyosev (http://svest.org). */ jQuery(function($){ $.datepicker.regional['bg'] = { diff --git a/ui/i18n/jquery.ui.datepicker-bs.js b/ui/i18n/jquery.ui.datepicker-bs.js index 7be269ab2..d64573755 100644 --- a/ui/i18n/jquery.ui.datepicker-bs.js +++ b/ui/i18n/jquery.ui.datepicker-bs.js @@ -1,4 +1,4 @@ -/* Bosnian i18n for the jQuery UI date picker plugin. */ +/* Bosnian i18n for the jQuery UI date picker plugin. */ /* Written by Kenan Konjo. */ jQuery(function($){ $.datepicker.regional['bs'] = { diff --git a/ui/i18n/jquery.ui.datepicker-cs.js b/ui/i18n/jquery.ui.datepicker-cs.js index 115b8c0e1..bf56baf01 100644 --- a/ui/i18n/jquery.ui.datepicker-cs.js +++ b/ui/i18n/jquery.ui.datepicker-cs.js @@ -1,4 +1,4 @@ -/* Czech initialisation for the jQuery UI date picker plugin. */ +/* Czech initialisation for the jQuery UI date picker plugin. */ /* Written by Tomas Muller (tomas@tomas-muller.net). */ jQuery(function($){ $.datepicker.regional['cs'] = { diff --git a/ui/i18n/jquery.ui.datepicker-da.js b/ui/i18n/jquery.ui.datepicker-da.js index 6d2ddee59..fb2d3356d 100644 --- a/ui/i18n/jquery.ui.datepicker-da.js +++ b/ui/i18n/jquery.ui.datepicker-da.js @@ -1,4 +1,4 @@ -/* Danish initialisation for the jQuery UI date picker plugin. */ +/* Danish initialisation for the jQuery UI date picker plugin. */ /* Written by Jan Christensen ( deletestuff@gmail.com). */ jQuery(function($){ $.datepicker.regional['da'] = { diff --git a/ui/i18n/jquery.ui.datepicker-de.js b/ui/i18n/jquery.ui.datepicker-de.js index 56203ed7a..52d6c82ce 100644 --- a/ui/i18n/jquery.ui.datepicker-de.js +++ b/ui/i18n/jquery.ui.datepicker-de.js @@ -1,4 +1,4 @@ -/* German initialisation for the jQuery UI date picker plugin. */ +/* German initialisation for the jQuery UI date picker plugin. */ /* Written by Milian Wolff (mail@milianw.de). */ jQuery(function($){ $.datepicker.regional['de'] = { diff --git a/ui/i18n/jquery.ui.datepicker-el.js b/ui/i18n/jquery.ui.datepicker-el.js index 9542769d9..6d775f995 100644 --- a/ui/i18n/jquery.ui.datepicker-el.js +++ b/ui/i18n/jquery.ui.datepicker-el.js @@ -1,4 +1,4 @@ -/* Greek (el) initialisation for the jQuery UI date picker plugin. */ +/* Greek (el) initialisation for the jQuery UI date picker plugin. */ /* Written by Alex Cicovic (http://www.alexcicovic.com) */ jQuery(function($){ $.datepicker.regional['el'] = { diff --git a/ui/i18n/jquery.ui.datepicker-en-GB.js b/ui/i18n/jquery.ui.datepicker-en-GB.js index aac7b6195..16a096e75 100644 --- a/ui/i18n/jquery.ui.datepicker-en-GB.js +++ b/ui/i18n/jquery.ui.datepicker-en-GB.js @@ -1,4 +1,4 @@ -/* English/UK initialisation for the jQuery UI date picker plugin. */ +/* English/UK initialisation for the jQuery UI date picker plugin. */ /* Written by Stuart. */ jQuery(function($){ $.datepicker.regional['en-GB'] = { diff --git a/ui/i18n/jquery.ui.datepicker-eo.js b/ui/i18n/jquery.ui.datepicker-eo.js index 7201a2c9f..39e44fc57 100644 --- a/ui/i18n/jquery.ui.datepicker-eo.js +++ b/ui/i18n/jquery.ui.datepicker-eo.js @@ -1,4 +1,4 @@ -/* Esperanto initialisation for the jQuery UI date picker plugin. */ +/* Esperanto initialisation for the jQuery UI date picker plugin. */ /* Written by Olivier M. (olivierweb@ifrance.com). */ jQuery(function($){ $.datepicker.regional['eo'] = { diff --git a/ui/i18n/jquery.ui.datepicker-et.js b/ui/i18n/jquery.ui.datepicker-et.js index f97311f31..92f81f637 100644 --- a/ui/i18n/jquery.ui.datepicker-et.js +++ b/ui/i18n/jquery.ui.datepicker-et.js @@ -1,4 +1,4 @@ -/* Estonian initialisation for the jQuery UI date picker plugin. */ +/* Estonian initialisation for the jQuery UI date picker plugin. */ /* Written by Mart Sõmermaa (mrts.pydev at gmail com). */ jQuery(function($){ $.datepicker.regional['et'] = { diff --git a/ui/i18n/jquery.ui.datepicker-eu.js b/ui/i18n/jquery.ui.datepicker-eu.js index 5eaace880..4c40eebec 100644 --- a/ui/i18n/jquery.ui.datepicker-eu.js +++ b/ui/i18n/jquery.ui.datepicker-eu.js @@ -1,4 +1,4 @@ -/* Euskarako oinarria 'UI date picker' jquery-ko extentsioarentzat */ +/* Euskarako oinarria 'UI date picker' jquery-ko extentsioarentzat */ /* Karrikas-ek itzulia (karrikas@karrikas.com) */ jQuery(function($){ $.datepicker.regional['eu'] = { diff --git a/ui/i18n/jquery.ui.datepicker-fa.js b/ui/i18n/jquery.ui.datepicker-fa.js index c3252a548..1d7fbd23c 100644 --- a/ui/i18n/jquery.ui.datepicker-fa.js +++ b/ui/i18n/jquery.ui.datepicker-fa.js @@ -1,4 +1,4 @@ -/* Persian (Farsi) Translation for the jQuery UI date picker plugin. */ +/* Persian (Farsi) Translation for the jQuery UI date picker plugin. */ /* Javad Mowlanezhad -- jmowla@gmail.com */ /* Jalali calendar should supported soon! (Its implemented but I have to test it) */ jQuery(function($) { diff --git a/ui/i18n/jquery.ui.datepicker-fo.js b/ui/i18n/jquery.ui.datepicker-fo.js index 2548df836..9c848a04b 100644 --- a/ui/i18n/jquery.ui.datepicker-fo.js +++ b/ui/i18n/jquery.ui.datepicker-fo.js @@ -1,4 +1,4 @@ -/* Faroese initialisation for the jQuery UI date picker plugin */ +/* Faroese initialisation for the jQuery UI date picker plugin */ /* Written by Sverri Mohr Olsen, sverrimo@gmail.com */ jQuery(function($){ $.datepicker.regional['fo'] = { diff --git a/ui/i18n/jquery.ui.datepicker-fr-CH.js b/ui/i18n/jquery.ui.datepicker-fr-CH.js index 04f9b033e..fec03a042 100644 --- a/ui/i18n/jquery.ui.datepicker-fr-CH.js +++ b/ui/i18n/jquery.ui.datepicker-fr-CH.js @@ -1,4 +1,4 @@ -/* Swiss-French initialisation for the jQuery UI date picker plugin. */ +/* Swiss-French initialisation for the jQuery UI date picker plugin. */ /* Written Martin Voelkle (martin.voelkle@e-tc.ch). */ jQuery(function($){ $.datepicker.regional['fr-CH'] = { diff --git a/ui/i18n/jquery.ui.datepicker-fr.js b/ui/i18n/jquery.ui.datepicker-fr.js index 74ea1c231..7e793639f 100644 --- a/ui/i18n/jquery.ui.datepicker-fr.js +++ b/ui/i18n/jquery.ui.datepicker-fr.js @@ -1,4 +1,4 @@ -/* French initialisation for the jQuery UI date picker plugin. */ +/* French initialisation for the jQuery UI date picker plugin. */ /* Written by Keith Wood (kbwood{at}iinet.com.au), Stéphane Nahmani (sholby@sholby.net), Stéphane Raimbault */ diff --git a/ui/i18n/jquery.ui.datepicker-he.js b/ui/i18n/jquery.ui.datepicker-he.js index 429a11c2c..58ea8c6d8 100644 --- a/ui/i18n/jquery.ui.datepicker-he.js +++ b/ui/i18n/jquery.ui.datepicker-he.js @@ -1,4 +1,4 @@ -/* Hebrew initialisation for the UI Datepicker extension. */ +/* Hebrew initialisation for the UI Datepicker extension. */ /* Written by Amir Hardon (ahardon at gmail dot com). */ jQuery(function($){ $.datepicker.regional['he'] = { diff --git a/ui/i18n/jquery.ui.datepicker-hr.js b/ui/i18n/jquery.ui.datepicker-hr.js index 61b7fccb1..6bc5aade1 100644 --- a/ui/i18n/jquery.ui.datepicker-hr.js +++ b/ui/i18n/jquery.ui.datepicker-hr.js @@ -1,4 +1,4 @@ -/* Croatian i18n for the jQuery UI date picker plugin. */ +/* Croatian i18n for the jQuery UI date picker plugin. */ /* Written by Vjekoslav Nesek. */ jQuery(function($){ $.datepicker.regional['hr'] = { diff --git a/ui/i18n/jquery.ui.datepicker-ja.js b/ui/i18n/jquery.ui.datepicker-ja.js index ab9243bbd..afd298315 100644 --- a/ui/i18n/jquery.ui.datepicker-ja.js +++ b/ui/i18n/jquery.ui.datepicker-ja.js @@ -1,4 +1,4 @@ -/* Japanese initialisation for the jQuery UI date picker plugin. */ +/* Japanese initialisation for the jQuery UI date picker plugin. */ /* Written by Kentaro SATO (kentaro@ranvis.com). */ jQuery(function($){ $.datepicker.regional['ja'] = { diff --git a/ui/i18n/jquery.ui.datepicker-ml.js b/ui/i18n/jquery.ui.datepicker-ml.js index 753dba411..1e3432c0a 100644 --- a/ui/i18n/jquery.ui.datepicker-ml.js +++ b/ui/i18n/jquery.ui.datepicker-ml.js @@ -1,4 +1,4 @@ -/* Malayalam (UTF-8) initialisation for the jQuery UI date picker plugin. */ +/* Malayalam (UTF-8) initialisation for the jQuery UI date picker plugin. */ /* Written by Saji Nediyanchath (saji89@gmail.com). */ jQuery(function($){ $.datepicker.regional['ml'] = { diff --git a/ui/i18n/jquery.ui.datepicker-nl.js b/ui/i18n/jquery.ui.datepicker-nl.js index 40be2cfa4..09634088b 100644 --- a/ui/i18n/jquery.ui.datepicker-nl.js +++ b/ui/i18n/jquery.ui.datepicker-nl.js @@ -1,4 +1,4 @@ -/* Dutch (UTF-8) initialisation for the jQuery UI date picker plugin. */ +/* Dutch (UTF-8) initialisation for the jQuery UI date picker plugin. */ /* Written by Mathias Bynens */ jQuery(function($){ $.datepicker.regional.nl = { diff --git a/ui/i18n/jquery.ui.datepicker-ro.js b/ui/i18n/jquery.ui.datepicker-ro.js index 9016b6712..a988270d7 100644 --- a/ui/i18n/jquery.ui.datepicker-ro.js +++ b/ui/i18n/jquery.ui.datepicker-ro.js @@ -1,4 +1,4 @@ -/* Romanian initialisation for the jQuery UI date picker plugin. +/* Romanian initialisation for the jQuery UI date picker plugin. * * Written by Edmond L. (ll_edmond@walla.com) * and Ionut G. Stan (ionut.g.stan@gmail.com) diff --git a/ui/i18n/jquery.ui.datepicker-sq.js b/ui/i18n/jquery.ui.datepicker-sq.js index 52f8eee0c..d6086a789 100644 --- a/ui/i18n/jquery.ui.datepicker-sq.js +++ b/ui/i18n/jquery.ui.datepicker-sq.js @@ -1,4 +1,4 @@ -/* Albanian initialisation for the jQuery UI date picker plugin. */ +/* Albanian initialisation for the jQuery UI date picker plugin. */ /* Written by Flakron Bytyqi (flakron@gmail.com). */ jQuery(function($){ $.datepicker.regional['sq'] = { diff --git a/ui/i18n/jquery.ui.datepicker-sr-SR.js b/ui/i18n/jquery.ui.datepicker-sr-SR.js index 57ee8f24a..6d5d04211 100644 --- a/ui/i18n/jquery.ui.datepicker-sr-SR.js +++ b/ui/i18n/jquery.ui.datepicker-sr-SR.js @@ -1,4 +1,4 @@ -/* Serbian i18n for the jQuery UI date picker plugin. */ +/* Serbian i18n for the jQuery UI date picker plugin. */ /* Written by Dejan Dimić. */ jQuery(function($){ $.datepicker.regional['sr-SR'] = { diff --git a/ui/i18n/jquery.ui.datepicker-sr.js b/ui/i18n/jquery.ui.datepicker-sr.js index 543dd0feb..d4e1d9af0 100644 --- a/ui/i18n/jquery.ui.datepicker-sr.js +++ b/ui/i18n/jquery.ui.datepicker-sr.js @@ -1,4 +1,4 @@ -/* Serbian i18n for the jQuery UI date picker plugin. */ +/* Serbian i18n for the jQuery UI date picker plugin. */ /* Written by Dejan Dimić. */ jQuery(function($){ $.datepicker.regional['sr'] = { diff --git a/ui/i18n/jquery.ui.datepicker-sv.js b/ui/i18n/jquery.ui.datepicker-sv.js index 05aab3308..173689b2a 100644 --- a/ui/i18n/jquery.ui.datepicker-sv.js +++ b/ui/i18n/jquery.ui.datepicker-sv.js @@ -1,4 +1,4 @@ -/* Swedish initialisation for the jQuery UI date picker plugin. */ +/* Swedish initialisation for the jQuery UI date picker plugin. */ /* Written by Anders Ekdahl ( anders@nomadiz.se). */ jQuery(function($){ $.datepicker.regional['sv'] = { diff --git a/ui/i18n/jquery.ui.datepicker-ta.js b/ui/i18n/jquery.ui.datepicker-ta.js index 91116d387..40431ed8e 100644 --- a/ui/i18n/jquery.ui.datepicker-ta.js +++ b/ui/i18n/jquery.ui.datepicker-ta.js @@ -1,4 +1,4 @@ -/* Tamil (UTF-8) initialisation for the jQuery UI date picker plugin. */ +/* Tamil (UTF-8) initialisation for the jQuery UI date picker plugin. */ /* Written by S A Sureshkumar (saskumar@live.com). */ jQuery(function($){ $.datepicker.regional['ta'] = { diff --git a/ui/i18n/jquery.ui.datepicker-th.js b/ui/i18n/jquery.ui.datepicker-th.js index f2122fc9f..d57541f64 100644 --- a/ui/i18n/jquery.ui.datepicker-th.js +++ b/ui/i18n/jquery.ui.datepicker-th.js @@ -1,4 +1,4 @@ -/* Thai initialisation for the jQuery UI date picker plugin. */ +/* Thai initialisation for the jQuery UI date picker plugin. */ /* Written by pipo (pipo@sixhead.com). */ jQuery(function($){ $.datepicker.regional['th'] = { diff --git a/ui/i18n/jquery.ui.datepicker-vi.js b/ui/i18n/jquery.ui.datepicker-vi.js index 3ecf36197..b49e7eb13 100644 --- a/ui/i18n/jquery.ui.datepicker-vi.js +++ b/ui/i18n/jquery.ui.datepicker-vi.js @@ -1,4 +1,4 @@ -/* Vietnamese initialisation for the jQuery UI date picker plugin. */ +/* Vietnamese initialisation for the jQuery UI date picker plugin. */ /* Translated by Le Thanh Huy (lthanhhuy@cit.ctu.edu.vn). */ jQuery(function($){ $.datepicker.regional['vi'] = { diff --git a/ui/i18n/jquery.ui.datepicker-zh-TW.js b/ui/i18n/jquery.ui.datepicker-zh-TW.js index 3c58ea92d..19702a65c 100644 --- a/ui/i18n/jquery.ui.datepicker-zh-TW.js +++ b/ui/i18n/jquery.ui.datepicker-zh-TW.js @@ -1,4 +1,4 @@ -/* Chinese initialisation for the jQuery UI date picker plugin. */ +/* Chinese initialisation for the jQuery UI date picker plugin. */ /* Written by Ressol (ressol@gmail.com). */ jQuery(function($){ $.datepicker.regional['zh-TW'] = { diff --git a/ui/jquery.effects.bounce.js b/ui/jquery.effects.bounce.js index 1ffd5ed5a..bb386a4f4 100644 --- a/ui/jquery.effects.bounce.js +++ b/ui/jquery.effects.bounce.js @@ -23,7 +23,7 @@ $.effects.effect.bounce = function(o) { hide = mode === "hide", show = mode === "show", direction = o.direction || "up", - distance = o.distance || 20, + distance = o.distance, times = o.times || 5, // number of internal animations @@ -53,7 +53,7 @@ $.effects.effect.bounce = function(o) { // default distance for the BIGGEST bounce is the outer Distance / 3 if ( !distance ) { - distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]({ margin:true }) / 3; + distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3; } if ( show ) { @@ -69,7 +69,7 @@ $.effects.effect.bounce = function(o) { // start at the smallest distance if we are hiding if ( hide ) { - distance = distance / ( ( times - 1 ) * 2 ); + distance = distance / Math.pow( 2, times - 1 ); } downAnim = {}; diff --git a/ui/jquery.effects.pulsate.js b/ui/jquery.effects.pulsate.js index 30c346abd..54c5c10af 100644 --- a/ui/jquery.effects.pulsate.js +++ b/ui/jquery.effects.pulsate.js @@ -18,9 +18,10 @@ $.effects.effect.pulsate = function( o ) { mode = $.effects.setMode( elem, o.mode || "show" ), show = mode === "show", hide = mode === "hide", + showhide = ( show || mode === "hide" ), // showing or hiding leaves of the "last" animation - anims = ( ( o.times || 5 ) * 2 ) - ( show || hide ? 1 : 0 ), + anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ), duration = o.duration / anims, animateTo = 0, queue = elem.queue(), @@ -32,7 +33,8 @@ $.effects.effect.pulsate = function( o ) { animateTo = 1; } - for ( i = 0; i < anims - 1; i++ ) { + // anims - 1 opacity "toggles" + for ( i = 1; i < anims; i++ ) { elem.animate({ opacity: animateTo }, duration, o.easing ); diff --git a/ui/jquery.ui.autocomplete.js b/ui/jquery.ui.autocomplete.js index 526eb3869..b3d7598c1 100644 --- a/ui/jquery.ui.autocomplete.js +++ b/ui/jquery.ui.autocomplete.js @@ -62,6 +62,7 @@ $.widget( "ui.autocomplete", { }) .bind( "keydown.autocomplete", function( event ) { if ( self.options.disabled || self.element.attr( "readonly" ) ) { + suppressKeyPress = true; return; } @@ -69,17 +70,21 @@ $.widget( "ui.autocomplete", { var keyCode = $.ui.keyCode; switch( event.keyCode ) { case keyCode.PAGE_UP: + suppressKeyPress = true; self._move( "previousPage", event ); break; case keyCode.PAGE_DOWN: + suppressKeyPress = true; self._move( "nextPage", event ); break; case keyCode.UP: + suppressKeyPress = true; self._move( "previous", event ); // prevent moving cursor to beginning of text field in some browsers event.preventDefault(); break; case keyCode.DOWN: + suppressKeyPress = true; self._move( "next", event ); // prevent moving cursor to end of text field in some browsers event.preventDefault(); @@ -121,7 +126,29 @@ $.widget( "ui.autocomplete", { if ( suppressKeyPress ) { suppressKeyPress = false; event.preventDefault(); + return; } + + // replicate some key handlers to allow them to repeat in Firefox and Opera + var keyCode = $.ui.keyCode; + switch( event.keyCode ) { + case keyCode.PAGE_UP: + self._move( "previousPage", event ); + break; + case keyCode.PAGE_DOWN: + self._move( "nextPage", event ); + break; + case keyCode.UP: + self._move( "previous", event ); + // prevent moving cursor to beginning of text field in some browsers + event.preventDefault(); + break; + case keyCode.DOWN: + self._move( "next", event ); + // prevent moving cursor to end of text field in some browsers + event.preventDefault(); + break; + } }) .bind( "focus.autocomplete", function() { if ( self.options.disabled ) { @@ -338,6 +365,7 @@ $.widget( "ui.autocomplete", { this.menu.element.hide(); this.menu.blur(); this._trigger( "close", event ); + this.menu.isNewMenu = true; } }, diff --git a/ui/jquery.ui.button.js b/ui/jquery.ui.button.js index 5777d4753..031ac2091 100644 --- a/ui/jquery.ui.button.js +++ b/ui/jquery.ui.button.js @@ -103,6 +103,11 @@ $.widget( "ui.button", { }) .bind( "blur.button", function() { $( this ).removeClass( focusClass ); + }) + .bind( "click.button", function( event ) { + if ( options.disabled ) { + event.stopImmediatePropagation(); + } }); if ( toggleButton ) { diff --git a/ui/jquery.ui.datepicker.js b/ui/jquery.ui.datepicker.js index 3437d0bda..12323672a 100644 --- a/ui/jquery.ui.datepicker.js +++ b/ui/jquery.ui.datepicker.js @@ -648,7 +648,6 @@ $.extend(Datepicker.prototype, { var showAnim = $.datepicker._get(inst, 'showAnim'); var duration = $.datepicker._get(inst, 'duration'); var postProcess = function() { - $.datepicker._datepickerShowing = true; var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only if( !! cover.length ){ var borders = $.datepicker._getBorders(inst.dpDiv); @@ -657,6 +656,7 @@ $.extend(Datepicker.prototype, { } }; inst.dpDiv.zIndex($(input).zIndex()+1); + $.datepicker._datepickerShowing = true; // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) @@ -685,10 +685,9 @@ $.extend(Datepicker.prototype, { var numMonths = this._getNumberOfMonths(inst); var cols = numMonths[1]; var width = 17; + inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width(''); if (cols > 1) inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em'); - else - inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width(''); inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') + 'Class']('ui-datepicker-multi'); inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') + @@ -996,14 +995,24 @@ $.extend(Datepicker.prototype, { }; // Extract a name from the string value and convert to an index var getName = function(match, shortNames, longNames) { - var names = (lookAhead(match) ? longNames : shortNames); - for (var i = 0; i < names.length; i++) { - if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) { - iValue += names[i].length; - return i + 1; + var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) { + return [ [k, v] ]; + }).sort(function (a, b) { + return -(a[1].length - b[1].length); + }); + var index = -1; + $.each(names, function (i, pair) { + var name = pair[1]; + if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) { + index = pair[0]; + iValue += name.length; + return false; } - } - throw 'Unknown name at position ' + iValue; + }); + if (index != -1) + return index + 1; + else + throw 'Unknown name at position ' + iValue; }; // Confirm that a literal character matches the string value var checkLiteral = function() { diff --git a/ui/jquery.ui.dialog.js b/ui/jquery.ui.dialog.js index 8423d1164..2138a9a58 100644 --- a/ui/jquery.ui.dialog.js +++ b/ui/jquery.ui.dialog.js @@ -281,7 +281,7 @@ $.widget("ui.dialog", { options = self.options, uiDialog = self.uiDialog; - self.overlay = options.modal ? new $.ui.dialog.overlay( self ) : null; + self.overlay = options.modal ? new $.ui.dialog.overlay( self ) : null; self._size(); self._position( options.position ); uiDialog.show( options.show ); diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index 0841018af..3cc25062c 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -18,6 +18,7 @@ var idIncrement = 0; $.widget("ui.menu", { defaultElement: "
    ", delay: 150, + isNewMenu: true, options: { position: { my: "left top", @@ -54,7 +55,8 @@ $.widget("ui.menu", { self.select( event ); }) .bind( "mouseover.menu", function( event ) { - if ( self.options.disabled ) { + if ( self.options.disabled || self.isNewMenu ) { + self.isNewMenu = false; return; } var target = $( event.target ).closest( ".ui-menu-item" ); diff --git a/ui/jquery.ui.menubar.js b/ui/jquery.ui.menubar.js new file mode 100644 index 000000000..2879d079c --- /dev/null +++ b/ui/jquery.ui.menubar.js @@ -0,0 +1,272 @@ +/* + * jQuery UI Menubar @VERSION + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Menubar + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.position.js + * jquery.ui.menu.js + */ +(function( $ ) { + +// TODO when mixing clicking menus and keyboard navigation, focus handling is broken +// there has to be just one item that has tabindex +$.widget( "ui.menubar", { + options: { + buttons: false, + menuIcon: false + }, + _create: function() { + var that = this; + var items = this.items = this.element.children( "li" ) + .addClass( "ui-menubar-item" ) + .attr( "role", "presentation" ) + .children( "button, a" ); + // let only the first item receive focus + items.slice(1).attr( "tabIndex", -1 ); + + this.element + .addClass( "ui-menubar ui-widget-header ui-helper-clearfix" ) + .attr( "role", "menubar" ); + this._focusable( items ); + this._hoverable( items ); + items.next( "ul" ) + .menu({ + select: function( event, ui ) { + ui.item.parents( "ul.ui-menu:last" ).hide(); + that._trigger( "select", event, ui ); + that._close(); + // TODO what is this targetting? there's probably a better way to access it + $(event.target).prev().focus(); + } + }) + .hide() + .attr( "aria-hidden", "true" ) + .attr( "aria-expanded", "false" ) + .bind( "keydown.menubar", function( event ) { + var menu = $( this ); + if ( menu.is( ":hidden" ) ) + return; + switch ( event.keyCode ) { + case $.ui.keyCode.LEFT: + that._left( event ); + event.preventDefault(); + break; + case $.ui.keyCode.RIGHT: + that._right( event ); + event.preventDefault(); + break; + }; + }); + items.each(function() { + var input = $(this), + // TODO menu var is only used on two places, doesn't quite justify the .each + menu = input.next( "ul" ); + + input.bind( "click.menubar focus.menubar mouseenter.menubar", function( event ) { + // ignore triggered focus event + if ( event.type == "focus" && !event.originalEvent ) { + return; + } + event.preventDefault(); + // TODO can we simplify or extractthis check? especially the last two expressions + // there's a similar active[0] == menu[0] check in _open + if ( event.type == "click" && menu.is( ":visible" ) && that.active && that.active[0] == menu[0] ) { + that._close(); + return; + } + if ( ( that.open && event.type == "mouseenter" ) || event.type == "click" ) { + that._open( event, menu ); + } + }) + .bind( "keydown", function( event ) { + switch ( event.keyCode ) { + case $.ui.keyCode.SPACE: + case $.ui.keyCode.UP: + case $.ui.keyCode.DOWN: + that._open( event, $( this ).next() ); + event.preventDefault(); + break; + case $.ui.keyCode.LEFT: + that._prev( event, $( this ) ); + event.preventDefault(); + break; + case $.ui.keyCode.RIGHT: + that._next( event, $( this ) ); + event.preventDefault(); + break; + } + }) + .addClass( "ui-button ui-widget ui-button-text-only ui-menubar-link" ) + .attr( "role", "menuitem" ) + .attr( "aria-haspopup", "true" ) + .wrapInner( "" ); + + // TODO review if these options are a good choice, maybe they can be merged + if ( that.options.menuIcon ) { + input.addClass( "ui-state-default" ).append( "" ); + input.removeClass( "ui-button-text-only" ).addClass( "ui-button-text-icon-secondary" ); + } + + if ( !that.options.buttons ) { + // TODO ui-menubar-link is added above, not needed here? + input.addClass( "ui-menubar-link" ).removeClass( "ui-state-default" ); + }; + + }); + that._bind( { + keydown: function( event ) { + if ( event.keyCode == $.ui.keyCode.ESCAPE && that.active && that.active.menu( "left", event ) !== true ) { + var active = that.active; + that.active.blur(); + that._close( event ); + active.prev().focus(); + } + }, + focusin: function( event ) { + clearTimeout( that.closeTimer ); + }, + focusout: function( event ) { + that.closeTimer = setTimeout( function() { + that._close( event ); + }, 100); + } + }); + }, + + _destroy : function() { + var items = this.element.children( "li" ) + .removeClass( "ui-menubar-item" ) + .removeAttr( "role", "presentation" ) + .children( "button, a" ); + + this.element + .removeClass( "ui-menubar ui-widget-header ui-helper-clearfix" ) + .removeAttr( "role", "menubar" ) + .unbind( ".menubar" ); + + items + .unbind( ".menubar" ) + .removeClass( "ui-button ui-widget ui-button-text-only ui-menubar-link ui-state-default" ) + .removeAttr( "role", "menuitem" ) + .removeAttr( "aria-haspopup", "true" ) + // TODO unwrap? + .children( "span.ui-button-text" ).each(function( i, e ) { + var item = $( this ); + item.parent().html( item.html() ); + }) + .end() + .children( ".ui-icon" ).remove(); + + this.element.find( ":ui-menu" ) + .menu( "destroy" ) + .show() + .removeAttr( "aria-hidden", "true" ) + .removeAttr( "aria-expanded", "false" ) + .removeAttr( "tabindex" ) + .unbind( ".menubar" ); + }, + + _close: function() { + if ( !this.active || !this.active.length ) + return; + this.active + .menu( "closeAll" ) + .hide() + .attr( "aria-hidden", "true" ) + .attr( "aria-expanded", "false" ); + this.active + .prev() + .removeClass( "ui-state-active" ) + .removeAttr( "tabIndex" ); + this.active = null; + this.open = false; + }, + + _open: function( event, menu ) { + // on a single-button menubar, ignore reopening the same menu + if ( this.active && this.active[0] == menu[0] ) { + return; + } + // TODO refactor, almost the same as _close above, but don't remove tabIndex + if ( this.active ) { + this.active + .menu( "closeAll" ) + .hide() + .attr( "aria-hidden", "true" ) + .attr( "aria-expanded", "false" ); + this.active + .prev() + .removeClass( "ui-state-active" ); + } + // set tabIndex -1 to have the button skipped on shift-tab when menu is open (it gets focus) + var button = menu.prev().addClass( "ui-state-active" ).attr( "tabIndex", -1 ); + this.active = menu + .show() + .position( { + my: "left top", + at: "left bottom", + of: button + }) + .removeAttr( "aria-hidden" ) + .attr( "aria-expanded", "true" ) + .menu("focus", event, menu.children( "li" ).first() ) + // TODO need a comment here why both events are triggered + .focus() + .focusin(); + this.open = true; + }, + + // TODO refactor this and the next three methods + _prev: function( event, button ) { + button.attr( "tabIndex", -1 ); + var prev = button.parent().prevAll( "li" ).children( ".ui-button" ).eq( 0 ); + if ( prev.length ) { + prev.removeAttr( "tabIndex" )[0].focus(); + } else { + var lastItem = this.element.children( "li:last" ).children( ".ui-button:last" ); + lastItem.removeAttr( "tabIndex" )[0].focus(); + } + }, + + _next: function( event, button ) { + button.attr( "tabIndex", -1 ); + var next = button.parent().nextAll( "li" ).children( ".ui-button" ).eq( 0 ); + if ( next.length ) { + next.removeAttr( "tabIndex")[0].focus(); + } else { + var firstItem = this.element.children( "li:first" ).children( ".ui-button:first" ); + firstItem.removeAttr( "tabIndex" )[0].focus(); + } + }, + + // TODO rename to parent + _left: function( event ) { + var prev = this.active.parent().prevAll( "li:eq(0)" ).children( ".ui-menu" ).eq( 0 ); + if ( prev.length ) { + this._open( event, prev ); + } else { + var lastItem = this.element.children( "li:last" ).children( ".ui-menu:first" ); + this._open( event, lastItem ); + } + }, + + // TODO rename to child (or something like that) + _right: function( event ) { + var next = this.active.parent().nextAll( "li:eq(0)" ).children( ".ui-menu" ).eq( 0 ); + if ( next.length ) { + this._open( event, next ); + } else { + var firstItem = this.element.children( "li:first" ).children( ".ui-menu:first" ); + this._open( event, firstItem ); + } + } +}); + +}( jQuery )); diff --git a/ui/jquery.ui.mouse.js b/ui/jquery.ui.mouse.js index bfe4a7578..0bd38db85 100644 --- a/ui/jquery.ui.mouse.js +++ b/ui/jquery.ui.mouse.js @@ -12,6 +12,11 @@ */ (function( $, undefined ) { +var mouseHandled = false; +$(document).mousedown(function(e) { + mouseHandled = false; +}); + $.widget("ui.mouse", { options: { cancel: ':input,option', @@ -44,9 +49,7 @@ $.widget("ui.mouse", { _mouseDown: function(event) { // don't let more than one widget handle mouseStart - // TODO: figure out why we have to use originalEvent - event.originalEvent = event.originalEvent || {}; - if (event.originalEvent.mouseHandled) { return; } + if(mouseHandled) {return}; // we may have missed mouseup (out of window) (this._mouseStarted && this._mouseUp(event)); @@ -92,7 +95,8 @@ $.widget("ui.mouse", { .bind('mouseup.'+this.widgetName, this._mouseUpDelegate); event.preventDefault(); - event.originalEvent.mouseHandled = true; + + mouseHandled = true; return true; }, diff --git a/ui/jquery.ui.popup.js b/ui/jquery.ui.popup.js new file mode 100644 index 000000000..10361a35c --- /dev/null +++ b/ui/jquery.ui.popup.js @@ -0,0 +1,174 @@ +/* + * jQuery UI Popup @VERSION + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Popup + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.position.js + */ +(function($) { + +var idIncrement = 0; + +$.widget( "ui.popup", { + options: { + position: { + my: "left top", + at: "left bottom" + } + }, + _create: function() { + if ( !this.options.trigger ) { + this.options.trigger = this.element.prev(); + } + + if ( !this.element.attr( "id" ) ) { + this.element.attr( "id", "ui-popup-" + idIncrement++ ); + this.generatedId = true; + } + + if ( !this.element.attr( "role" ) ) { + // TODO alternatives to tooltip are dialog and menu, all three aren't generic popups + this.element.attr( "role", "tooltip" ); + this.generatedRole = true; + } + + this.options.trigger + .attr( "aria-haspopup", true ) + .attr( "aria-owns", this.element.attr( "id" ) ); + + this.element + .addClass("ui-popup") + this.close(); + + this._bind(this.options.trigger, { + keydown: function( event ) { + // prevent space-to-open to scroll the page, only hapens for anchor ui.button + if ( this.options.trigger.is( "a:ui-button" ) && event.keyCode == $.ui.keyCode.SPACE) { + event.preventDefault() + } + // TODO handle SPACE to open popup? only when not handled by ui.button + if ( event.keyCode == $.ui.keyCode.SPACE && this.options.trigger.is("a:not(:ui-button)") ) { + this.options.trigger.trigger( "click", event ); + } + // translate keydown to click + // opens popup and let's tooltip hide itself + if ( event.keyCode == $.ui.keyCode.DOWN ) { + // prevent scrolling + event.preventDefault(); + this.options.trigger.trigger( "click", event ); + } + }, + click: function( event ) { + event.preventDefault(); + if (this.isOpen) { + // let it propagate to close + return; + } + var that = this; + clearTimeout( this.closeTimer ); + setTimeout(function() { + that.open( event ); + }, 1); + } + }); + + this._bind(this.element, { + // TODO use focusout so that element itself doesn't need to be focussable + blur: function( event ) { + var that = this; + // use a timer to allow click to clear it and letting that + // handle the closing instead of opening again + that.closeTimer = setTimeout( function() { + that.close( event ); + }, 100); + } + }); + + this._bind({ + // TODO only triggerd on element if it can receive focus + // bind to document instead? + // either element itself or a child should be focusable + keyup: function( event ) { + if (event.keyCode == $.ui.keyCode.ESCAPE && this.element.is( ":visible" )) { + this.close( event ); + // TODO move this to close()? would allow menu.select to call popup.close, and get focus back to trigger + this.options.trigger.focus(); + } + } + }); + + this._bind(document, { + click: function( event ) { + if (this.isOpen && !$(event.target).closest(".ui-popup").length) { + this.close( event ); + } + } + }) + }, + + _destroy: function() { + this.element + .show() + .removeClass( "ui-popup" ) + .removeAttr( "aria-hidden" ) + .removeAttr( "aria-expanded" ); + + this.options.trigger + .removeAttr( "aria-haspopup" ) + .removeAttr( "aria-owns" ); + + if ( this.generatedId ) { + this.element.removeAttr( "id" ); + } + if ( this.generatedRole ) { + this.element.removeAttr( "role" ); + } + }, + + open: function( event ) { + var position = $.extend( {}, { + of: this.options.trigger + }, this.options.position ); + + this.element + .show() + .attr( "aria-hidden", false ) + .attr( "aria-expanded", true ) + .position( position ) + // TODO find a focussable child, otherwise put focus on element, add tabIndex=0 if not focussable + .focus(); + + if (this.element.is(":ui-menu")) { + this.element.menu("focus", event, this.element.children( "li" ).first() ); + } + + // take trigger out of tab order to allow shift-tab to skip trigger + this.options.trigger.attr("tabindex", -1); + + this.isOpen = true; + this._trigger( "open", event ); + }, + + close: function( event ) { + this.element + .hide() + .attr( "aria-hidden", true ) + .attr( "aria-expanded", false ); + + this.options.trigger.attr("tabindex", 0); + + this.isOpen = false; + this._trigger( "close", event ); + } + + +}); + +}(jQuery)); diff --git a/ui/jquery.ui.resizable.js b/ui/jquery.ui.resizable.js index 1e1706a9d..e0579ef84 100644 --- a/ui/jquery.ui.resizable.js +++ b/ui/jquery.ui.resizable.js @@ -176,10 +176,12 @@ $.widget("ui.resizable", $.ui.mouse, { $(this.element) .addClass("ui-resizable-autohide") .hover(function() { + if (o.disabled) return; $(this).removeClass("ui-resizable-autohide"); self._handles.show(); }, function(){ + if (o.disabled) return; if (!self.resizing) { $(this).addClass("ui-resizable-autohide"); self._handles.hide(); diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js old mode 100755 new mode 100644 index 58c181670..cce50d3e7 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -108,15 +108,7 @@ $.widget( "ui.tabs", { var panel = that._getPanelForTab( this.active ); panel.show(); - this.lis.eq( options.active ).addClass( "ui-tabs-active ui-state-active" ); - - // TODO: we need to remove this or add it to accordion - // seems to be expected behavior that the activate callback is fired - that.element.queue( "tabs", function() { - that._trigger( "activate", null, that._ui( that.active[ 0 ], panel[ 0 ] ) ); - }); - this.load( options.active ); } else { this.active = $(); @@ -161,14 +153,6 @@ $.widget( "ui.tabs", { return hash ? hash.replace( /:/g, "\\:" ) : ""; }, - _ui: function( tab, panel ) { - return { - tab: tab, - panel: panel, - index: this.anchors.index( tab ) - }; - }, - refresh: function() { var self = this, options = this.options, @@ -621,6 +605,7 @@ $.widget( "ui.tabs", { this.xhr .success(function( response ) { panel.html( response ); + self._trigger( "load", event, eventData ); }) .complete(function( jqXHR, status ) { if ( status === "abort" ) { @@ -631,13 +616,11 @@ $.widget( "ui.tabs", { // "tabs" queue must not contain more than two elements, // which are the callbacks for the latest clicked tab... self.element.queue( "tabs", self.element.queue( "tabs" ).splice( -2, 2 ) ); - - delete this.xhr; } self.lis.eq( index ).removeClass( "ui-tabs-loading" ); - self._trigger( "load", event, eventData ); + delete self.xhr; }); } @@ -660,6 +643,15 @@ $.extend( $.ui.tabs, { // DEPRECATED if ( $.uiBackCompat !== false ) { + // helper method for a lot of the back compat extensions + $.ui.tabs.prototype._ui = function( tab, panel ) { + return { + tab: tab, + panel: panel, + index: this.anchors.index( tab ) + }; + }; + // url method (function( $, prototype ) { prototype.url = function( index, url ) { @@ -705,7 +697,7 @@ if ( $.uiBackCompat !== false ) { } }); - ui.jqXHR.success( function() { + ui.jqXHR.success(function() { if ( self.options.cache ) { $.data( ui.tab[ 0 ], "cache.tabs", true ); } @@ -743,34 +735,28 @@ if ( $.uiBackCompat !== false ) { }( jQuery, jQuery.ui.tabs.prototype ) ); // spinner - (function( $, prototype ) { - $.extend( prototype.options, { + $.widget( "ui.tabs", $.ui.tabs, { + options: { spinner: "Loading…" - }); - - var _create = prototype._create; - prototype._create = function() { - _create.call( this ); - var self = this; - - this.element.bind( "tabsbeforeload", function( event, ui ) { - if ( self.options.spinner ) { - var span = $( "span", ui.tab ); - if ( span.length ) { - span.data( "label.tabs", span.html() ).html( self.options.spinner ); + }, + _create: function() { + this._super( "_create" ); + this._bind({ + tabsbeforeload: function( event, ui ) { + if ( !this.options.spinner ) { + return; } + + var span = ui.tab.find( "span" ), + html = span.html(); + span.html( this.options.spinner ); + ui.jqXHR.complete(function() { + span.html( html ); + }); } - ui.jqXHR.complete( function() { - if ( self.options.spinner ) { - var span = $( "span", ui.tab ); - if ( span.length ) { - span.html( span.data( "label.tabs" ) ).removeData( "label.tabs" ); - } - } - }); }); - }; - }( jQuery, jQuery.ui.tabs.prototype ) ); + } + }); // enable/disable events (function( $, prototype ) { @@ -975,21 +961,33 @@ if ( $.uiBackCompat !== false ) { show: null, select: null }); - var _trigger = prototype._trigger; + var _create = prototype._create, + _trigger = prototype._trigger; + prototype._create = function() { + _create.call( this ); + 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 ); if ( !ret ) { return false; } - if ( type === "beforeActivate" ) { + if ( type === "beforeActivate" && data.newTab.length ) { ret = _trigger.call( this, "select", event, { tab: data.newTab[ 0], panel: data.newPanel[ 0 ], index: data.newTab.closest( "li" ).index() }); - } else if ( type === "activate" ) { - ret = _trigger.call( this, "show", event, data ); + } else if ( type === "activate" && data.newTab.length ) { + ret = _trigger.call( this, "show", event, { + tab: data.newTab[ 0 ], + panel: data.newPanel[ 0 ], + index: data.newTab.closest( "li" ).index() + }); } }; }( jQuery, jQuery.ui.tabs.prototype ) ); @@ -1010,57 +1008,50 @@ if ( $.uiBackCompat !== false ) { }( jQuery, jQuery.ui.tabs.prototype ) ); // cookie option - (function( $, prototype ) { - $.extend( prototype.options, { + $.widget( "ui.tabs", $.ui.tabs, { + options: { cookie: null // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true } - }); - - var _create = prototype._create, - _refresh = prototype._refresh, - _eventHandler = prototype._eventHandler, - _destroy = prototype._destroy; - - prototype._create = function() { - var o = this.options; - if ( o.active === undefined ) { - if ( typeof o.active !== "number" && o.cookie ) { - o.active = parseInt( this._cookie(), 10 ); + }, + _create: function() { + var options = this.options, + active; + if ( options.active == null && options.cookie ) { + active = parseInt( this._cookie(), 10 ); + if ( active === -1 ) { + active = false; } + options.active = active; } - _create.call( this ); - }; - - prototype._cookie = function() { - var cookie = this.cookie || - ( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() ); - return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) ); - }; - - prototype._refresh = function() { - _refresh.call( this ); - - // set or update cookie after init and add/remove respectively + this._super( "_create" ); + }, + _cookie: function( active ) { + var cookie = [ this.cookie || + ( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() ) ]; + if ( arguments.length ) { + cookie.push( active === false ? -1 : active ); + cookie.push( this.options.cookie ); + } + return $.cookie.apply( null, cookie ); + }, + _refresh: function() { + this._super( "_refresh" ); if ( this.options.cookie ) { this._cookie( this.options.active, this.options.cookie ); } - }; - - prototype._eventHandler = function( event ) { - _eventHandler.apply( this, arguments ); - + }, + _eventHandler: function( event ) { + this._superApply( "_eventHandler", arguments ); if ( this.options.cookie ) { this._cookie( this.options.active, this.options.cookie ); } - }; - - prototype._destroy = function() { - _destroy.call( this ); - + }, + _destroy: function() { + this._super( "_destroy" ); if ( this.options.cookie ) { this._cookie( null, this.options.cookie ); } - }; - }( jQuery, jQuery.ui.tabs.prototype ) ); + } + }); } })( jQuery ); diff --git a/ui/jquery.ui.tooltip.js b/ui/jquery.ui.tooltip.js index 20638cba5..a8a44f1c0 100644 --- a/ui/jquery.ui.tooltip.js +++ b/ui/jquery.ui.tooltip.js @@ -96,7 +96,8 @@ $.widget("ui.tooltip", { this._bind( target, { mouseleave: "close", - blur: "close" + blur: "close", + click: "close" }); },