From bd3a348776bf50da53d17f1574efd5538ce9de4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Fri, 12 Oct 2012 20:26:47 -0400 Subject: [PATCH 001/151] Tooltip: Change the default items selector to exclude disabled elements. Fixes #8661 - Tooltip doesn't hide on disabled anchor element [IE only]. --- tests/unit/tooltip/tooltip_common.js | 2 +- ui/jquery.ui.tooltip.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/unit/tooltip/tooltip_common.js b/tests/unit/tooltip/tooltip_common.js index 6d503aecd3..a4958ca9a8 100644 --- a/tests/unit/tooltip/tooltip_common.js +++ b/tests/unit/tooltip/tooltip_common.js @@ -3,7 +3,7 @@ TestHelpers.commonWidgetTests( "tooltip", { content: function() {}, disabled: false, hide: true, - items: "[title]", + items: "[title]:not([disabled])", position: { my: "left+15 center", at: "right center", diff --git a/ui/jquery.ui.tooltip.js b/ui/jquery.ui.tooltip.js index 980b43868e..0f69e898f1 100644 --- a/ui/jquery.ui.tooltip.js +++ b/ui/jquery.ui.tooltip.js @@ -49,7 +49,8 @@ $.widget( "ui.tooltip", { return $( this ).attr( "title" ); }, hide: true, - items: "[title]", + // Disabled elements have inconsistent behavior across browsers (#8661) + items: "[title]:not([disabled])", position: { my: "left+15 center", at: "right center", From 025266e00270d155f45550b6838ddd6f4a44470b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Sat, 13 Oct 2012 14:50:51 -0400 Subject: [PATCH 002/151] Resizable: Use .insertAfter() instead of .after() to avoid recursively destroying. Fixes #8662 - Infinite loop - new to jQuery UI 1.9.0. --- ui/jquery.ui.resizable.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/ui/jquery.ui.resizable.js b/ui/jquery.ui.resizable.js index cc82b8b927..c1fd676d97 100644 --- a/ui/jquery.ui.resizable.js +++ b/ui/jquery.ui.resizable.js @@ -204,15 +204,14 @@ $.widget("ui.resizable", $.ui.mouse, { if (this.elementIsWrapper) { _destroy(this.element); var wrapper = this.element; - wrapper.after( - this.originalElement.css({ - position: wrapper.css('position'), - width: wrapper.outerWidth(), - height: wrapper.outerHeight(), - top: wrapper.css('top'), - left: wrapper.css('left') - }) - ).remove(); + this.originalElement.css({ + position: wrapper.css('position'), + width: wrapper.outerWidth(), + height: wrapper.outerHeight(), + top: wrapper.css('top'), + left: wrapper.css('left') + }).insertAfter( wrapper ); + wrapper.remove(); } this.originalElement.css('resize', this.originalResizeStyle); From 112185ec8ddb7f0849fa40e7b1409e28153555f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Zaefferer?= Date: Fri, 12 Oct 2012 10:36:56 +0200 Subject: [PATCH 003/151] Spinner: Remove ui-state- classes from spinner, along with the background:none TR override. Fixes #8654 - Spinner background-color --- themes/base/jquery.ui.spinner.css | 1 - ui/jquery.ui.spinner.js | 5 +---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/themes/base/jquery.ui.spinner.css b/themes/base/jquery.ui.spinner.css index 94b73fa056..fd2a449af9 100644 --- a/themes/base/jquery.ui.spinner.css +++ b/themes/base/jquery.ui.spinner.css @@ -17,7 +17,6 @@ .ui-spinner-down { bottom: 0; } /* TR overrides */ -span.ui-spinner { background: none; } .ui-spinner .ui-icon-triangle-1-s { /* need to fix icons sprite */ background-position:-65px -16px; diff --git a/ui/jquery.ui.spinner.js b/ui/jquery.ui.spinner.js index 23cce18efb..406eefb915 100644 --- a/ui/jquery.ui.spinner.js +++ b/ui/jquery.ui.spinner.js @@ -94,7 +94,6 @@ $.widget( "ui.spinner", { }, keyup: "_stop", focus: function() { - this.uiSpinner.addClass( "ui-state-active" ); this.previous = this.element.val(); }, blur: function( event ) { @@ -104,7 +103,6 @@ $.widget( "ui.spinner", { } this._refresh(); - this.uiSpinner.removeClass( "ui-state-active" ); if ( this.previous !== this.element.val() ) { this._trigger( "change", event ); } @@ -196,7 +194,6 @@ $.widget( "ui.spinner", { .parent() // add buttons .append( this._buttonHtml() ); - this._hoverable( uiSpinner ); this.element.attr( "role", "spinbutton" ); @@ -242,7 +239,7 @@ $.widget( "ui.spinner", { }, _uiSpinnerHtml: function() { - return ""; + return ""; }, _buttonHtml: function() { From 1a696678878f48748912b4c9d5df6da91c760b98 Mon Sep 17 00:00:00 2001 From: Dale Kocian Date: Tue, 16 Oct 2012 09:17:21 -0400 Subject: [PATCH 004/151] Dialog: Added mousedown event handler on dialog title to focus. Fixed #8063 - Dialog: Escape closes incorrect dialog. --- ui/jquery.ui.dialog.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui/jquery.ui.dialog.js b/ui/jquery.ui.dialog.js index 8593fff854..d83059ade0 100644 --- a/ui/jquery.ui.dialog.js +++ b/ui/jquery.ui.dialog.js @@ -119,6 +119,10 @@ $.widget("ui.dialog", { uiDialogTitlebar = ( this.uiDialogTitlebar = $( "
" ) ) .addClass( "ui-dialog-titlebar ui-widget-header " + "ui-corner-all ui-helper-clearfix" ) + .bind( "mousedown", function() { + // Dialog isn't getting focus when dragging (#8063) + uiDialog.focus(); + }) .prependTo( uiDialog ), uiDialogTitlebarClose = $( "" ) From 8ce35198daf261370e2962f4c429bf4fa998b2df Mon Sep 17 00:00:00 2001 From: David Petersen Date: Tue, 16 Oct 2012 12:16:13 -0400 Subject: [PATCH 005/151] Tabs: Remove anchor clone in isLocal. Fixed #8653 - Tabs are not working inside iframe in IE6/7. --- ui/jquery.ui.tabs.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index 7d38fb46ea..0d7f85fbca 100644 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -22,9 +22,6 @@ function getNextTabId() { } function isLocal( anchor ) { - // clone the node to work around IE 6 not normalizing the href property - // if it's manually set, i.e., a.href = "#foo" kills the normalization - anchor = anchor.cloneNode( false ); return anchor.hash.length > 1 && anchor.href.replace( rhash, "" ) === location.href.replace( rhash, "" ); } From 5e24a1ce4b337830b37511305a6ddefe797fd40c Mon Sep 17 00:00:00 2001 From: TJ VanToll Date: Tue, 16 Oct 2012 13:20:55 -0400 Subject: [PATCH 006/151] Button: Check for ui-state-disabled during refresh. Fixes #8237 - Button: Anchor tags cannot be disabled within buttonset. --- tests/unit/button/button_tickets.js | 8 ++++++++ ui/jquery.ui.button.js | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/unit/button/button_tickets.js b/tests/unit/button/button_tickets.js index 846ca7ef45..eb70181ec0 100644 --- a/tests/unit/button/button_tickets.js +++ b/tests/unit/button/button_tickets.js @@ -61,4 +61,12 @@ test( "#7534 - Button label selector works for ids with \":\"", function() { ok( group.find( "label" ).is( ".ui-button" ), "Found an id with a :" ); }); +test( "#8237 - Anchor tags lose disabled state when refreshed", function() { + expect( 1 ); + var element = $( "" ).appendTo( "#qunit-fixture" ); + + element.button({ disabled: true }).button( "refresh" ); + ok( element.button( "option", "disabled" ), "Anchor button should remain disabled after refresh" ); +}); + })( jQuery ); diff --git a/ui/jquery.ui.button.js b/ui/jquery.ui.button.js index 5ae5264888..f253464df6 100644 --- a/ui/jquery.ui.button.js +++ b/ui/jquery.ui.button.js @@ -282,7 +282,7 @@ $.widget( "ui.button", { }, refresh: function() { - var isDisabled = this.element.is( ":disabled" ); + var isDisabled = this.element.is( ":disabled" ) || this.element.hasClass( "ui-button-disabled" ); if ( isDisabled !== this.options.disabled ) { this._setOption( "disabled", isDisabled ); } From f37008eeb11eb12571cb65b1010a7e5d367064ac Mon Sep 17 00:00:00 2001 From: David Petersen Date: Tue, 16 Oct 2012 13:42:05 -0400 Subject: [PATCH 007/151] Slider: Update UI when min or max option changes. Fixes #7477 - Setting min/max options does not update view. --- ui/jquery.ui.slider.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ui/jquery.ui.slider.js b/ui/jquery.ui.slider.js index f24982878d..ab8287e7bf 100644 --- a/ui/jquery.ui.slider.js +++ b/ui/jquery.ui.slider.js @@ -509,6 +509,12 @@ $.widget( "ui.slider", $.ui.mouse, { } this._animateOff = false; break; + case "min": + case "max": + this._animateOff = true; + this._refreshValue(); + this._animateOff = false; + break; } }, From dda1925d0f8d19b4baffa20259674dcef85e8bab Mon Sep 17 00:00:00 2001 From: David Petersen Date: Tue, 16 Oct 2012 14:07:10 -0400 Subject: [PATCH 008/151] Slider: Count the handles after setting up a range. Fixes #7922 - Slider with range doesn't work if values are not set. --- ui/jquery.ui.slider.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ui/jquery.ui.slider.js b/ui/jquery.ui.slider.js index ab8287e7bf..eb0f7fc15c 100644 --- a/ui/jquery.ui.slider.js +++ b/ui/jquery.ui.slider.js @@ -36,11 +36,10 @@ $.widget( "ui.slider", $.ui.mouse, { }, _create: function() { - var i, + var i, handleCount, o = this.options, existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ), handle = "", - handleCount = ( o.values && o.values.length ) || 1, handles = []; this._keySliding = false; @@ -79,6 +78,8 @@ $.widget( "ui.slider", $.ui.mouse, { ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) ); } + handleCount = ( o.values && o.values.length ) || 1; + for ( i = existingHandles.length; i < handleCount; i++ ) { handles.push( handle ); } From 35dc9307fc2ce5d2016e8848fdc578829867f97e Mon Sep 17 00:00:00 2001 From: David Petersen Date: Wed, 17 Oct 2012 09:28:51 -0400 Subject: [PATCH 009/151] Dialog: Use _hide() to make sure close event gets triggered. Fixes #8684 - jQuery dialog with hide options does not trigger close event. --- tests/unit/dialog/dialog_events.js | 21 +++++++++++++++++++-- ui/jquery.ui.dialog.js | 2 +- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/tests/unit/dialog/dialog_events.js b/tests/unit/dialog/dialog_events.js index 85afa5a3b9..515bebdc19 100644 --- a/tests/unit/dialog/dialog_events.js +++ b/tests/unit/dialog/dialog_events.js @@ -195,8 +195,8 @@ test("resizeStop", function() { el.remove(); }); -test("close", function() { - expect(7); +asyncTest("close", function() { + expect(14); el = $('
').dialog({ close: function(ev, ui) { @@ -212,6 +212,23 @@ test("close", function() { }); el.dialog('close'); el.remove(); + + // Close event with an effect + el = $('
').dialog({ + hide: 10, + close: function(ev, ui) { + ok(true, '.dialog("close") fires close callback'); + equal(this, el[0], "context of callback"); + equal(ev.type, 'dialogclose', 'event type in callback'); + deepEqual(ui, {}, 'ui hash in callback'); + start(); + } + }).bind('dialogclose', function(ev, ui) { + ok(true, '.dialog("close") fires dialogclose event'); + equal(this, el[0], 'context of event'); + deepEqual(ui, {}, 'ui hash in event'); + }); + el.dialog('close'); }); test("beforeClose", function() { diff --git a/ui/jquery.ui.dialog.js b/ui/jquery.ui.dialog.js index d83059ade0..e234464ad9 100644 --- a/ui/jquery.ui.dialog.js +++ b/ui/jquery.ui.dialog.js @@ -251,7 +251,7 @@ $.widget("ui.dialog", { } if ( this.options.hide ) { - this.uiDialog.hide( this.options.hide, function() { + this._hide( this.uiDialog, this.options.hide, function() { that._trigger( "close", event ); }); } else { From 390510c7059d98d68cfe082530051c476ee08be4 Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Wed, 17 Oct 2012 12:34:13 -0400 Subject: [PATCH 010/151] Build: Include ui/.jshintrc. Fixes #8687 - .jshintrc files not copied to dist. --- grunt.js | 1 + 1 file changed, 1 insertion(+) diff --git a/grunt.js b/grunt.js index 08647a7a12..1430fc5250 100644 --- a/grunt.js +++ b/grunt.js @@ -161,6 +161,7 @@ grunt.initConfig({ "package.json", "*.jquery.json", "ui/**/*", + "ui/.jshintrc", "demos/**/*", "themes/**/*", "external/**/*", From c2802d7aa05e6dc7731806a35d9f0057405a22c7 Mon Sep 17 00:00:00 2001 From: David Petersen Date: Wed, 17 Oct 2012 11:35:27 -0400 Subject: [PATCH 011/151] Accordion: handle active: null. Fixes #8694: 1.9 Accordion - active: null allows panels to be collapsible. --- tests/unit/accordion/accordion_options.js | 9 +++++++++ ui/jquery.ui.accordion.js | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/unit/accordion/accordion_options.js b/tests/unit/accordion/accordion_options.js index 5d950e1acd..8f0d0637fa 100644 --- a/tests/unit/accordion/accordion_options.js +++ b/tests/unit/accordion/accordion_options.js @@ -13,6 +13,15 @@ test( "{ active: default }", function() { state( element, 1, 0, 0 ); }); +test( "{ active: null }", function() { + expect( 2 ); + var element = $( "#list1" ).accordion({ + active: null + }); + equal( element.accordion( "option", "active" ), 0 ); + state( element, 1, 0, 0 ); +}); + test( "{ active: false }", function() { expect( 7 ); var element = $( "#list1" ).accordion({ diff --git a/ui/jquery.ui.accordion.js b/ui/jquery.ui.accordion.js index 48e880a057..ff07a8e937 100644 --- a/ui/jquery.ui.accordion.js +++ b/ui/jquery.ui.accordion.js @@ -59,8 +59,8 @@ $.widget( "ui.accordion", { .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ) .hide(); - // don't allow collapsible: false and active: false - if ( !options.collapsible && options.active === false ) { + // don't allow collapsible: false and active: false / null + if ( !options.collapsible && ( !options.active || typeof options.active !== "number" ) ) { options.active = 0; } // handle negative values From 5bd5ef15f9f7d1820334abd52aa5ee4b25c992ba Mon Sep 17 00:00:00 2001 From: Andrew Couch Date: Wed, 17 Oct 2012 22:04:36 -0700 Subject: [PATCH 012/151] Effect: fix typo in comment ft "optinos" => "options" --- ui/jquery.ui.effect.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/jquery.ui.effect.js b/ui/jquery.ui.effect.js index d5d3067838..65108e7ba4 100644 --- a/ui/jquery.ui.effect.js +++ b/ui/jquery.ui.effect.js @@ -1045,7 +1045,7 @@ $.extend( $.effects, { // return an effect options object for the given parameters: function _normalizeArguments( effect, options, speed, callback ) { - // allow passing all optinos as the first parameter + // allow passing all options as the first parameter if ( $.isPlainObject( effect ) ) { options = effect; effect = effect.effect; From 9d5f91ece2129801b4981b5befb588e8f215efd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Zaefferer?= Date: Fri, 19 Oct 2012 17:04:35 -0400 Subject: [PATCH 013/151] Tooltip: Comment why we need to use closest --- ui/jquery.ui.tooltip.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/jquery.ui.tooltip.js b/ui/jquery.ui.tooltip.js index 0f69e898f1..2323ae2434 100644 --- a/ui/jquery.ui.tooltip.js +++ b/ui/jquery.ui.tooltip.js @@ -127,7 +127,9 @@ $.widget( "ui.tooltip", { open: function( event ) { var target = $( event ? event.target : this.element ) - .closest( this.options.items ); + // we need closest here due to mouseover bubbling, + // but always pointing at the same event target + .closest( this.options.items ); // No element to show a tooltip for if ( !target.length ) { From 77a55f1291861b87d30011ac5fd948f6b38d2c60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Zaefferer?= Date: Fri, 19 Oct 2012 20:58:08 -0400 Subject: [PATCH 014/151] Tooltip: Fix nested tooltips (on hover) by closing parent tooltips and removing title attributes. Fixes #8700 - Overlapping tooltipped elements shows native tooltip for one of the elements --- tests/visual/tooltip/tooltip.html | 8 +++++-- ui/jquery.ui.tooltip.js | 38 +++++++++++++++++++++++++++---- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/tests/visual/tooltip/tooltip.html b/tests/visual/tooltip/tooltip.html index 56e5db10e7..8f9b2e8df0 100644 --- a/tests/visual/tooltip/tooltip.html +++ b/tests/visual/tooltip/tooltip.html @@ -140,10 +140,14 @@

Nested elements.

-
+
tooltipped - nested tooltipped + + nested tooltipped + third level +
+
Text in bold. diff --git a/ui/jquery.ui.tooltip.js b/ui/jquery.ui.tooltip.js index 2323ae2434..73321633bd 100644 --- a/ui/jquery.ui.tooltip.js +++ b/ui/jquery.ui.tooltip.js @@ -73,6 +73,8 @@ $.widget( "ui.tooltip", { // IDs of generated tooltips, needed for destroy this.tooltips = {}; + // IDs of parent tooltips where we removed the title attribute + this.parents = {}; }, _setOption: function( key, value ) { @@ -126,10 +128,11 @@ $.widget( "ui.tooltip", { }, open: function( event ) { - var target = $( event ? event.target : this.element ) - // we need closest here due to mouseover bubbling, - // but always pointing at the same event target - .closest( this.options.items ); + var that = this, + target = $( event ? event.target : this.element ) + // we need closest here due to mouseover bubbling, + // but always pointing at the same event target + .closest( this.options.items ); // No element to show a tooltip for if ( !target.length ) { @@ -154,6 +157,26 @@ $.widget( "ui.tooltip", { target.data( "tooltip-open", true ); + // kill parent tooltips, custom or native, for hover + if ( event && event.type === "mouseover" ) { + target.parents().each(function() { + var blurEvent; + if ( $( this ).data( "tooltip-open" ) ) { + blurEvent = $.Event( "blur" ); + blurEvent.target = blurEvent.currentTarget = this; + that.close( blurEvent, true ); + } + if ( this.title ) { + $( this ).uniqueId(); + that.parents[ this.id ] = { + element: this, + title: this.title + }; + this.title = ""; + } + }); + } + this._updateContent( target, event ); }, @@ -289,6 +312,13 @@ $.widget( "ui.tooltip", { this._off( target, "mouseleave focusout keyup" ); this._off( this.document, "mousemove" ); + if ( event && event.type === "mouseleave" ) { + $.each( this.parents, function( id, parent ) { + parent.element.title = parent.title; + delete that.parents[ id ]; + }); + } + this.closing = true; this._trigger( "close", event, { tooltip: tooltip } ); this.closing = false; From 6b48ef5eca67f389d7a58f3c8a263ceb82c8becb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Zaefferer?= Date: Fri, 19 Oct 2012 18:16:11 -0400 Subject: [PATCH 015/151] Tooltip: Only bind blur when opening via focus, mouseleave for mouseover. Remove the keep-open-on-focusout workaround. Now matching behaviour described in ARIA Authoring Practices. Fixes #8699 - Moving focus on click of a tooltipped element shows native tooltip in IE/Firefox on Windows --- tests/visual/tooltip/tooltip.html | 7 +++++++ ui/jquery.ui.tooltip.js | 25 ++++++++++--------------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/tests/visual/tooltip/tooltip.html b/tests/visual/tooltip/tooltip.html index 8f9b2e8df0..97fa99bb94 100644 --- a/tests/visual/tooltip/tooltip.html +++ b/tests/visual/tooltip/tooltip.html @@ -90,6 +90,10 @@ offset: "0 -5" } }); + + $( "#blurs-on-click" ).tooltip().click(function() { + $( "#focus-on-me" ).focus(); + }); }); @@ -154,6 +158,9 @@
+ + +

Play around with focusing and hovering of form elements.

diff --git a/ui/jquery.ui.tooltip.js b/ui/jquery.ui.tooltip.js index 73321633bd..b56d939e83 100644 --- a/ui/jquery.ui.tooltip.js +++ b/ui/jquery.ui.tooltip.js @@ -206,7 +206,7 @@ $.widget( "ui.tooltip", { }, _open: function( event, target, content ) { - var tooltip, positionOption; + var tooltip, positionOption, events; if ( !content ) { return; } @@ -261,9 +261,7 @@ $.widget( "ui.tooltip", { this._trigger( "open", event, { tooltip: tooltip } ); - this._on( target, { - mouseleave: "close", - focusout: "close", + events = { keyup: function( event ) { if ( event.keyCode === $.ui.keyCode.ESCAPE ) { var fakeEvent = $.Event(event); @@ -271,7 +269,14 @@ $.widget( "ui.tooltip", { this.close( fakeEvent, true ); } } - }); + }; + if ( !event || event.type === "mouseover" ) { + events.mouseleave = "close"; + } + if ( !event || event.type === "focusin" ) { + events.focusout = "close"; + } + this._on( target, events ); }, close: function( event, force ) { @@ -285,16 +290,6 @@ $.widget( "ui.tooltip", { return; } - // don't close if the element has focus - // this prevents the tooltip from closing if you hover while focused - // - // we have to check the event type because tabbing out of the document - // may leave the element as the activeElement - if ( !force && event && event.type !== "focusout" && - this.document[0].activeElement === target[0] ) { - return; - } - // only set title if we had one before (see comment in _open()) if ( target.data( "ui-tooltip-title" ) ) { target.attr( "title", target.data( "ui-tooltip-title" ) ); From 3b2d1e7736be99671af70aa3b775d67b917517e5 Mon Sep 17 00:00:00 2001 From: Andrew Couch Date: Mon, 15 Oct 2012 16:15:36 -0400 Subject: [PATCH 016/151] Tooltip: handle removal of elements with delegated tooltips. Fixed #8646 - Delegated tooltips don't close when the tooltipped element is removed --- tests/unit/tooltip/tooltip.html | 1 + tests/unit/tooltip/tooltip_core.js | 13 +++++++++++++ ui/jquery.ui.tooltip.js | 16 ++++++++++++++-- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/tests/unit/tooltip/tooltip.html b/tests/unit/tooltip/tooltip.html index f6e60b3673..2c9667ff50 100644 --- a/tests/unit/tooltip/tooltip.html +++ b/tests/unit/tooltip/tooltip.html @@ -43,6 +43,7 @@ aria-describedby span + baz
diff --git a/tests/unit/tooltip/tooltip_core.js b/tests/unit/tooltip/tooltip_core.js index 2b39253a27..06fb194cd7 100644 --- a/tests/unit/tooltip/tooltip_core.js +++ b/tests/unit/tooltip/tooltip_core.js @@ -44,4 +44,17 @@ test( "accessibility", function() { equal( element.attr( "title" ), "...", "title restored when closed" ); }); +test( "delegated removal", function() { + expect( 2 ); + + var container = $( "#contains-tooltipped" ).tooltip(), + element = $( "#contained-tooltipped" ); + + element.trigger( "mouseover" ); + equal( $( ".ui-tooltip" ).length, 1 ); + + container.empty(); + equal( $( ".ui-tooltip" ).length, 0 ); +}); + }( jQuery ) ); diff --git a/ui/jquery.ui.tooltip.js b/ui/jquery.ui.tooltip.js index b56d939e83..1be56c7ea3 100644 --- a/ui/jquery.ui.tooltip.js +++ b/ui/jquery.ui.tooltip.js @@ -207,6 +207,7 @@ $.widget( "ui.tooltip", { _open: function( event, target, content ) { var tooltip, positionOption, events; + if ( !content ) { return; } @@ -268,6 +269,9 @@ $.widget( "ui.tooltip", { fakeEvent.currentTarget = target[0]; this.close( fakeEvent, true ); } + }, + remove: function( event ) { + this._removeTooltip( tooltip ); } }; if ( !event || event.type === "mouseover" ) { @@ -299,12 +303,15 @@ $.widget( "ui.tooltip", { tooltip.stop( true ); this._hide( tooltip, this.options.hide, function() { - $( this ).remove(); - delete that.tooltips[ this.id ]; + that._removeTooltip( $( this ) ); }); target.removeData( "tooltip-open" ); this._off( target, "mouseleave focusout keyup" ); + // Remove 'remove' binding only on delegated targets + if ( target[0] !== this.element[0] ) { + this._off( target, "remove" ); + } this._off( this.document, "mousemove" ); if ( event && event.type === "mouseleave" ) { @@ -344,6 +351,11 @@ $.widget( "ui.tooltip", { return id ? $( "#" + id ) : $(); }, + _removeTooltip: function( tooltip ) { + tooltip.remove(); + delete this.tooltips[ tooltip.attr( "id" ) ]; + }, + _destroy: function() { var that = this; From 0b3e59f149054122d8948c29baa4bb174006d75e Mon Sep 17 00:00:00 2001 From: Andrew Couch Date: Tue, 16 Oct 2012 12:55:50 -0400 Subject: [PATCH 017/151] Tooltip: Do not attempt to position if tooltip is hidden. Fixed #8644 - Delayed tooltips set to track should reposition when being shown for the first time. --- tests/unit/tooltip/tooltip_options.js | 35 +++++++++++++++++++++++++++ tests/visual/tooltip/tooltip.html | 7 +++++- ui/jquery.ui.tooltip.js | 18 ++++++++++++-- 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/tests/unit/tooltip/tooltip_options.js b/tests/unit/tooltip/tooltip_options.js index db193e8fa5..e5046f4648 100644 --- a/tests/unit/tooltip/tooltip_options.js +++ b/tests/unit/tooltip/tooltip_options.js @@ -103,4 +103,39 @@ test( "tooltipClass", function() { ok( $( "#" + element.data( "ui-tooltip-id" ) ).hasClass( "custom" ) ); }); +test( "track + show delay", function() { + expect( 2 ); + var event, + leftVal = 314, + topVal = 159, + offsetVal = 26, + element = $( "#tooltipped1" ).tooltip({ + track: true, + show: { + delay: 1 + }, + position: { + my: "left+" + offsetVal + " top+" + offsetVal, + at: "right bottom" + } + }); + + event = $.Event( "mouseover" ); + event.target = $( "#tooltipped1" )[ 0 ]; + event.originalEvent = { type: "mouseover" }; + event.pageX = leftVal; + event.pageY = topVal; + element.trigger( event ); + + event = $.Event( "mousemove" ); + event.target = $( "#tooltipped1" )[ 0 ]; + event.originalEvent = { type: "mousemove" }; + event.pageX = leftVal; + event.pageY = topVal; + element.trigger( event ); + + equal( $( ".ui-tooltip" ).css( "left" ), leftVal + offsetVal + "px" ); + equal( $( ".ui-tooltip" ).css( "top" ), topVal + offsetVal + "px" ); +}); + }( jQuery ) ); diff --git a/tests/visual/tooltip/tooltip.html b/tests/visual/tooltip/tooltip.html index 97fa99bb94..598af0ee85 100644 --- a/tests/visual/tooltip/tooltip.html +++ b/tests/visual/tooltip/tooltip.html @@ -91,7 +91,12 @@ } }); - $( "#blurs-on-click" ).tooltip().click(function() { + $( "#blurs-on-click" ).tooltip({ + track: true, + show: { + delay: 500 + } + }).click(function() { $( "#focus-on-me" ).focus(); }); }); diff --git a/ui/jquery.ui.tooltip.js b/ui/jquery.ui.tooltip.js index 1be56c7ea3..a04b842893 100644 --- a/ui/jquery.ui.tooltip.js +++ b/ui/jquery.ui.tooltip.js @@ -206,7 +206,8 @@ $.widget( "ui.tooltip", { }, _open: function( event, target, content ) { - var tooltip, positionOption, events; + var tooltip, events, delayedShow, + positionOption = $.extend( {}, this.options.position ); if ( !content ) { return; @@ -241,10 +242,12 @@ $.widget( "ui.tooltip", { function position( event ) { positionOption.of = event; + if ( tooltip.is( ":hidden" ) ) { + return; + } tooltip.position( positionOption ); } if ( this.options.track && event && /^mouse/.test( event.originalEvent.type ) ) { - positionOption = $.extend( {}, this.options.position ); this._on( this.document, { mousemove: position }); @@ -259,6 +262,17 @@ $.widget( "ui.tooltip", { tooltip.hide(); this._show( tooltip, this.options.show ); + // 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 ) { + delayedShow = setInterval(function() { + if ( tooltip.is( ":visible" ) ) { + position( positionOption.of ); + clearInterval( delayedShow ); + } + }, $.fx.interval ); + } this._trigger( "open", event, { tooltip: tooltip } ); From 132e9f0c72d556a5c97911af8b321b04e75d72aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Zaefferer?= Date: Sun, 21 Oct 2012 13:07:43 -0400 Subject: [PATCH 018/151] Tooltip: Update events test to cover correct behaviour --- tests/unit/tooltip/tooltip_events.js | 38 +++++----------------------- 1 file changed, 6 insertions(+), 32 deletions(-) diff --git a/tests/unit/tooltip/tooltip_events.js b/tests/unit/tooltip/tooltip_events.js index fc5f1acc5c..de16471aed 100644 --- a/tests/unit/tooltip/tooltip_events.js +++ b/tests/unit/tooltip/tooltip_events.js @@ -26,14 +26,15 @@ test( "mouse events", function() { expect( 2 ); var element = $( "#tooltipped1" ).tooltip(); - element.one( "tooltipopen", function( event ) { + element.bind( "tooltipopen", function( event ) { deepEqual( event.originalEvent.type, "mouseover" ); }); element.trigger( "mouseover" ); - element.one( "tooltipclose", function( event ) { + element.bind( "tooltipclose", function( event ) { deepEqual( event.originalEvent.type, "mouseleave" ); }); + element.trigger( "focusout" ); element.trigger( "mouseleave" ); }); @@ -41,43 +42,16 @@ test( "focus events", function() { expect( 2 ); var element = $( "#tooltipped1" ).tooltip(); - element.one( "tooltipopen", function( event ) { + element.bind( "tooltipopen", function( event ) { deepEqual( event.originalEvent.type, "focusin" ); }); element.trigger( "focusin" ); - element.one( "tooltipclose", function( event ) { + element.bind( "tooltipclose", function( event ) { deepEqual( event.originalEvent.type, "focusout" ); }); + element.trigger( "mouseleave" ); element.trigger( "focusout" ); }); -asyncTest( "mixed events", function() { - expect( 2 ); - var element = $( "#tooltipped1" ).tooltip(); - - element.one( "tooltipopen", function( event ) { - deepEqual( event.originalEvent.type, "focusin" ); - }); - element.simulate( "focus" ); - - element.one( "tooltipopen", function() { - ok( false, "open triggered while already open" ); - }); - element.trigger( "mouseover" ); - - element.bind( "tooltipclose", function( event ) { - ok( false, "close triggered while still focused" ); - }); - element.trigger( "mouseleave" ); - element.unbind( "tooltipclose" ); - - // blurring is async in IE - element.one( "tooltipclose", function( event ) { - deepEqual( event.originalEvent.type, "focusout" ); - start(); - }); - element.simulate( "blur" ); -}); - }( jQuery ) ); From 78f781fccd2b757afa80e543a03f591ab029550d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Zaefferer?= Date: Sun, 21 Oct 2012 13:25:36 -0400 Subject: [PATCH 019/151] Tooltip: Unit test for nested tooltips --- tests/unit/tooltip/tooltip.html | 2 +- tests/unit/tooltip/tooltip_core.js | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/unit/tooltip/tooltip.html b/tests/unit/tooltip/tooltip.html index 2c9667ff50..ca5a1239ae 100644 --- a/tests/unit/tooltip/tooltip.html +++ b/tests/unit/tooltip/tooltip.html @@ -43,7 +43,7 @@ aria-describedby span - baz + baz
diff --git a/tests/unit/tooltip/tooltip_core.js b/tests/unit/tooltip/tooltip_core.js index 06fb194cd7..6e9bee2082 100644 --- a/tests/unit/tooltip/tooltip_core.js +++ b/tests/unit/tooltip/tooltip_core.js @@ -57,4 +57,20 @@ test( "delegated removal", function() { equal( $( ".ui-tooltip" ).length, 0 ); }); +test( "nested tooltips", function() { + expect( 2 ); + + var child = $( "#contained-tooltipped" ), + parent = $( "#contains-tooltipped" ).tooltip({ + show: null, + hide: null + }); + + parent.trigger( "mouseover" ); + equal( $( ".ui-tooltip:visible" ).text(), "parent" ); + + child.trigger( "mouseover" ); + equal( $( ".ui-tooltip" ).text(), "child" ); +}); + }( jQuery ) ); From eb392b30359e334a1777ed3a8bc1237ce09528a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Sun, 21 Oct 2012 15:54:19 -0400 Subject: [PATCH 020/151] Accordion: Fix back-compat for active option. --- ui/jquery.ui.accordion.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/jquery.ui.accordion.js b/ui/jquery.ui.accordion.js index ff07a8e937..a23d5e66d2 100644 --- a/ui/jquery.ui.accordion.js +++ b/ui/jquery.ui.accordion.js @@ -60,7 +60,7 @@ $.widget( "ui.accordion", { .hide(); // don't allow collapsible: false and active: false / null - if ( !options.collapsible && ( !options.active || typeof options.active !== "number" ) ) { + if ( !options.collapsible && (options.active === false || options.active == null) ) { options.active = 0; } // handle negative values From fd9b355a8e4f4a18b719905004a4ac346be691bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Sun, 21 Oct 2012 17:46:02 -0400 Subject: [PATCH 021/151] Grunt: Removed tooltip tests from qunit task. --- grunt.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grunt.js b/grunt.js index 1430fc5250..9e03c95fac 100644 --- a/grunt.js +++ b/grunt.js @@ -280,7 +280,7 @@ grunt.initConfig({ files: grunt.file.expandFiles( "tests/unit/**/*.html" ).filter(function( file ) { // disabling everything that doesn't (quite) work with PhantomJS for now // TODO except for all|index|test, try to include more as we go - return !( /(all|all-active|index|test|draggable|droppable|selectable|resizable|sortable|dialog|slider|datepicker|tabs|tabs_deprecated)\.html$/ ).test( file ); + return !( /(all|all-active|index|test|draggable|droppable|selectable|resizable|sortable|dialog|slider|datepicker|tabs|tabs_deprecated|tooltip)\.html$/ ).test( file ); }) }, lint: { From 8b76684a92d7340175284bb369426f0164673b0a Mon Sep 17 00:00:00 2001 From: Corey Frang Date: Sun, 21 Oct 2012 16:46:38 -0500 Subject: [PATCH 022/151] Effects: Allow 'null' for options - Fixes #8670 - null reference when using effects - Closes gh-783 --- tests/unit/effects/effects_core.js | 11 +++++++++++ ui/jquery.ui.effect.js | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/tests/unit/effects/effects_core.js b/tests/unit/effects/effects_core.js index 9b4787a575..c4e5c24f92 100644 --- a/tests/unit/effects/effects_core.js +++ b/tests/unit/effects/effects_core.js @@ -31,6 +31,17 @@ test( "Immediate Return Conditions", function() { equal( ++count, 3, "Both Functions worked properly" ); }); +asyncTest( "Parse of null for options", function() { + var hidden = $( "div.hidden" ), + count = 0; + expect( 1 ); + hidden.show( "blind", null, 1, function() { + equal( ++count, 1, "null for options still works" ); + start(); + }); +}); + + /* TODO: Disabled - Can't figure out why this is failing in IE 6/7 test( "createWrapper and removeWrapper retain focused elements (#7595)", function() { expect( 2 ); diff --git a/ui/jquery.ui.effect.js b/ui/jquery.ui.effect.js index 65108e7ba4..3fb428c1a1 100644 --- a/ui/jquery.ui.effect.js +++ b/ui/jquery.ui.effect.js @@ -1054,8 +1054,8 @@ function _normalizeArguments( effect, options, speed, callback ) { // convert to an object effect = { effect: effect }; - // catch (effect) - if ( options === undefined ) { + // catch (effect, null, ...) + if ( options == null ) { options = {}; } From eb4178f81910ec691f0bfe93d6002a76854bdde5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Sun, 21 Oct 2012 17:50:13 -0400 Subject: [PATCH 023/151] Fixed some jshint errors. --- ui/jquery.ui.effect.js | 2 +- ui/jquery.ui.tabs.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/jquery.ui.effect.js b/ui/jquery.ui.effect.js index 3fb428c1a1..8d875746e8 100644 --- a/ui/jquery.ui.effect.js +++ b/ui/jquery.ui.effect.js @@ -619,7 +619,7 @@ each( stepHooks, function( i, hook ) { } try { elem.style[ hook ] = value; - } catch( value ) { + } catch( error ) { // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit' } } diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index 0d7f85fbca..05456374d2 100644 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -895,16 +895,16 @@ if ( $.uiBackCompat !== false ) { _ajaxSettings: function( anchor, event, ui ) { var ajaxOptions = this.options.ajaxOptions; return $.extend( {}, ajaxOptions, { - error: function( xhr, s, e ) { + error: function( xhr, status ) { try { // Passing index avoid a race condition when this method is // called after the user has selected another tab. // Pass the anchor that initiated this request allows // loadError to manipulate the tab content panel via $(a.hash) ajaxOptions.error( - xhr, s, ui.tab.closest( "li" ).index(), ui.tab[ 0 ] ); + xhr, status, ui.tab.closest( "li" ).index(), ui.tab[ 0 ] ); } - catch ( e ) {} + catch ( error ) {} } }, this._superApply( arguments ) ); }, From fe1ecf97e01f6b9e6041ae324deafb69063d1c9c Mon Sep 17 00:00:00 2001 From: TJ VanToll Date: Tue, 16 Oct 2012 16:44:16 -0400 Subject: [PATCH 024/151] CSS: Apply opacity to absolutely positioned ui icons in IE8. Fixed #6059 - Button: Primary icon "enabled" when button is disabled. --- themes/base/jquery.ui.theme.css | 1 + 1 file changed, 1 insertion(+) diff --git a/themes/base/jquery.ui.theme.css b/themes/base/jquery.ui.theme.css index d70b9df903..bf8ef96338 100644 --- a/themes/base/jquery.ui.theme.css +++ b/themes/base/jquery.ui.theme.css @@ -41,6 +41,7 @@ .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } .ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } .ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } +.ui-state-disabled .ui-icon { filter:Alpha(Opacity=35); } /* For IE8 - See #6059 */ /* Icons ----------------------------------*/ From e629d9ae1acd5b36a35658a42cb553ad02efae66 Mon Sep 17 00:00:00 2001 From: Trey Hunner Date: Sun, 14 Oct 2012 16:09:42 -0700 Subject: [PATCH 025/151] Exempt external directory from .editorconfig rules --- .editorconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.editorconfig b/.editorconfig index c94db9a8ef..1ba4f5faac 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,3 +9,8 @@ end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true + +[external/**] +trim_trailing_whitespace = false +insert_final_newline = varies +end_of_line = varies From 0bcbfe714621ed181137387745a78d640924247b Mon Sep 17 00:00:00 2001 From: Trey Hunner Date: Sun, 14 Oct 2012 16:07:35 -0700 Subject: [PATCH 026/151] Replace mixed CRLF/LF line endings with LF --- jquery-1.8.2.js | 3328 ++++++++++++++++++++--------------------- tests/jquery-1.8.0.js | 2920 ++++++++++++++++++------------------ tests/jquery-1.8.1.js | 3058 ++++++++++++++++++------------------- tests/jquery-1.8.2.js | 3328 ++++++++++++++++++++--------------------- 4 files changed, 6317 insertions(+), 6317 deletions(-) diff --git a/jquery-1.8.2.js b/jquery-1.8.2.js index d4f3bb38cd..12c7797fdc 100644 --- a/jquery-1.8.2.js +++ b/jquery-1.8.2.js @@ -3665,1667 +3665,1667 @@ jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblcl jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; } }); -/*! - * Sizzle CSS Selector Engine - * Copyright 2012 jQuery Foundation and other contributors - * Released under the MIT license - * http://sizzlejs.com/ - */ -(function( window, undefined ) { - -var cachedruns, - assertGetIdNotName, - Expr, - getText, - isXML, - contains, - compile, - sortOrder, - hasDuplicate, - outermostContext, - - baseHasDuplicate = true, - strundefined = "undefined", - - expando = ( "sizcache" + Math.random() ).replace( ".", "" ), - - Token = String, - document = window.document, - docElem = document.documentElement, - dirruns = 0, - done = 0, - pop = [].pop, - push = [].push, - slice = [].slice, - // Use a stripped-down indexOf if a native one is unavailable - indexOf = [].indexOf || function( elem ) { - var i = 0, - len = this.length; - for ( ; i < len; i++ ) { - if ( this[i] === elem ) { - return i; - } - } - return -1; - }, - - // Augment a function for special use by Sizzle - markFunction = function( fn, value ) { - fn[ expando ] = value == null || value; - return fn; - }, - - createCache = function() { - var cache = {}, - keys = []; - - return markFunction(function( key, value ) { - // Only keep the most recent entries - if ( keys.push( key ) > Expr.cacheLength ) { - delete cache[ keys.shift() ]; - } - - return (cache[ key ] = value); - }, cache ); - }, - - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - - // Regex - - // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - // http://www.w3.org/TR/css3-syntax/#characters - characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+", - - // Loosely modeled on CSS identifier characters - // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors) - // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = characterEncoding.replace( "w", "w#" ), - - // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors - operators = "([*^$|!~]?=)", - attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + - "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", - - // Prefer arguments not in parens/brackets, - // then attribute selectors and non-pseudos (denoted by :), - // then anything else - // These preferences are here to reduce the number of selectors - // needing tokenize in the PSEUDO preFilter - pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)", - - // For matchExpr.POS and matchExpr.needsContext - pos = ":(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + - "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ), - rpseudo = new RegExp( pseudos ), - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/, - - rnot = /^:not/, - rsibling = /[\x20\t\r\n\f]*[+~]/, - rendsWithNot = /:not\($/, - - rheader = /h\d/i, - rinputs = /input|select|textarea|button/i, - - rbackslash = /\\(?!\\)/g, - - matchExpr = { - "ID": new RegExp( "^#(" + characterEncoding + ")" ), - "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), - "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ), - "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "POS": new RegExp( pos, "i" ), - "CHILD": new RegExp( "^:(only|nth|first|last)-child(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - // For use in libraries implementing .is() - "needsContext": new RegExp( "^" + whitespace + "*[>+~]|" + pos, "i" ) - }, - - // Support - - // Used for testing something on an element - assert = function( fn ) { - var div = document.createElement("div"); - - try { - return fn( div ); - } catch (e) { - return false; - } finally { - // release memory in IE - div = null; - } - }, - - // Check if getElementsByTagName("*") returns only elements - assertTagNameNoComments = assert(function( div ) { - div.appendChild( document.createComment("") ); - return !div.getElementsByTagName("*").length; - }), - - // Check if getAttribute returns normalized href attributes - assertHrefNotNormalized = assert(function( div ) { - div.innerHTML = ""; - return div.firstChild && typeof div.firstChild.getAttribute !== strundefined && - div.firstChild.getAttribute("href") === "#"; - }), - - // Check if attributes should be retrieved by attribute nodes - assertAttributes = assert(function( div ) { - div.innerHTML = ""; - var type = typeof div.lastChild.getAttribute("multiple"); - // IE8 returns a string for some attributes even when not present - return type !== "boolean" && type !== "string"; - }), - - // Check if getElementsByClassName can be trusted - assertUsableClassName = assert(function( div ) { - // Opera can't find a second classname (in 9.6) - div.innerHTML = ""; - if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) { - return false; - } - - // Safari 3.2 caches class attributes and doesn't catch changes - div.lastChild.className = "e"; - return div.getElementsByClassName("e").length === 2; - }), - - // Check if getElementById returns elements by name - // Check if getElementsByName privileges form controls or returns elements by ID - assertUsableName = assert(function( div ) { - // Inject content - div.id = expando + 0; - div.innerHTML = "
"; - docElem.insertBefore( div, docElem.firstChild ); - - // Test - var pass = document.getElementsByName && - // buggy browsers will return fewer than the correct 2 - document.getElementsByName( expando ).length === 2 + - // buggy browsers will return more than the correct 0 - document.getElementsByName( expando + 0 ).length; - assertGetIdNotName = !document.getElementById( expando ); - - // Cleanup - docElem.removeChild( div ); - - return pass; - }); - -// If slice is not available, provide a backup -try { - slice.call( docElem.childNodes, 0 )[0].nodeType; -} catch ( e ) { - slice = function( i ) { - var elem, - results = []; - for ( ; (elem = this[i]); i++ ) { - results.push( elem ); - } - return results; - }; -} - -function Sizzle( selector, context, results, seed ) { - results = results || []; - context = context || document; - var match, elem, xml, m, - nodeType = context.nodeType; - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - if ( nodeType !== 1 && nodeType !== 9 ) { - return []; - } - - xml = isXML( context ); - - if ( !xml && !seed ) { - if ( (match = rquickExpr.exec( selector )) ) { - // Speed-up: Sizzle("#ID") - if ( (m = match[1]) ) { - if ( nodeType === 9 ) { - elem = context.getElementById( m ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE, Opera, and Webkit return items - // by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - } else { - // Context is not a document - if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && - contains( context, elem ) && elem.id === m ) { - results.push( elem ); - return results; - } - } - - // Speed-up: Sizzle("TAG") - } else if ( match[2] ) { - push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) ); - return results; - - // Speed-up: Sizzle(".CLASS") - } else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) { - push.apply( results, slice.call(context.getElementsByClassName( m ), 0) ); - return results; - } - } - } - - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed, xml ); -} - -Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); -}; - -Sizzle.matchesSelector = function( elem, expr ) { - return Sizzle( expr, null, null, [ elem ] ).length > 0; -}; - -// Returns a function to use in pseudos for input types -function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; -} - -// Returns a function to use in pseudos for buttons -function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; -} - -// Returns a function to use in pseudos for positionals -function createPositionalPseudo( fn ) { - return markFunction(function( argument ) { - argument = +argument; - return markFunction(function( seed, matches ) { - var j, - matchIndexes = fn( [], seed.length, argument ), - i = matchIndexes.length; - - // Match elements found at the specified indexes - while ( i-- ) { - if ( seed[ (j = matchIndexes[i]) ] ) { - seed[j] = !(matches[j] = seed[j]); - } - } - }); - }); -} - -/** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if ( nodeType ) { - if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - // Use textContent for elements - // innerText usage removed for consistency of new lines (see #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - // Do not include comment or processing instruction nodes - } else { - - // If no nodeType, this is expected to be an array - for ( ; (node = elem[i]); i++ ) { - // Do not traverse comment nodes - ret += getText( node ); - } - } - return ret; -}; - -isXML = Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = elem && (elem.ownerDocument || elem).documentElement; - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -// Element contains another -contains = Sizzle.contains = docElem.contains ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) ); - } : - docElem.compareDocumentPosition ? - function( a, b ) { - return b && !!( a.compareDocumentPosition( b ) & 16 ); - } : - function( a, b ) { - while ( (b = b.parentNode) ) { - if ( b === a ) { - return true; - } - } - return false; - }; - -Sizzle.attr = function( elem, name ) { - var val, - xml = isXML( elem ); - - if ( !xml ) { - name = name.toLowerCase(); - } - if ( (val = Expr.attrHandle[ name ]) ) { - return val( elem ); - } - if ( xml || assertAttributes ) { - return elem.getAttribute( name ); - } - val = elem.getAttributeNode( name ); - return val ? - typeof elem[ name ] === "boolean" ? - elem[ name ] ? name : null : - val.specified ? val.value : null : - null; -}; - -Expr = Sizzle.selectors = { - - // Can be adjusted by the user - cacheLength: 50, - - createPseudo: markFunction, - - match: matchExpr, - - // IE6/7 return a modified href - attrHandle: assertHrefNotNormalized ? - {} : - { - "href": function( elem ) { - return elem.getAttribute( "href", 2 ); - }, - "type": function( elem ) { - return elem.getAttribute("type"); - } - }, - - find: { - "ID": assertGetIdNotName ? - function( id, context, xml ) { - if ( typeof context.getElementById !== strundefined && !xml ) { - var m = context.getElementById( id ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [m] : []; - } - } : - function( id, context, xml ) { - if ( typeof context.getElementById !== strundefined && !xml ) { - var m = context.getElementById( id ); - - return m ? - m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ? - [m] : - undefined : - []; - } - }, - - "TAG": assertTagNameNoComments ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== strundefined ) { - return context.getElementsByTagName( tag ); - } - } : - function( tag, context ) { - var results = context.getElementsByTagName( tag ); - - // Filter out possible comments - if ( tag === "*" ) { - var elem, - tmp = [], - i = 0; - - for ( ; (elem = results[i]); i++ ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } - - return tmp; - } - return results; - }, - - "NAME": assertUsableName && function( tag, context ) { - if ( typeof context.getElementsByName !== strundefined ) { - return context.getElementsByName( name ); - } - }, - - "CLASS": assertUsableClassName && function( className, context, xml ) { - if ( typeof context.getElementsByClassName !== strundefined && !xml ) { - return context.getElementsByClassName( className ); - } - } - }, - - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, - - preFilter: { - "ATTR": function( match ) { - match[1] = match[1].replace( rbackslash, "" ); - - // Move the given value to match[3] whether quoted or unquoted - match[3] = ( match[4] || match[5] || "" ).replace( rbackslash, "" ); - - if ( match[2] === "~=" ) { - match[3] = " " + match[3] + " "; - } - - return match.slice( 0, 4 ); - }, - - "CHILD": function( match ) { - /* matches from matchExpr["CHILD"] - 1 type (only|nth|...) - 2 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 3 xn-component of xn+y argument ([+-]?\d*n|) - 4 sign of xn-component - 5 x of xn-component - 6 sign of y-component - 7 y of y-component - */ - match[1] = match[1].toLowerCase(); - - if ( match[1] === "nth" ) { - // nth-child requires argument - if ( !match[2] ) { - Sizzle.error( match[0] ); - } - - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === "even" || match[2] === "odd" ) ); - match[4] = +( ( match[6] + match[7] ) || match[2] === "odd" ); - - // other types prohibit arguments - } else if ( match[2] ) { - Sizzle.error( match[0] ); - } - - return match; - }, - - "PSEUDO": function( match ) { - var unquoted, excess; - if ( matchExpr["CHILD"].test( match[0] ) ) { - return null; - } - - if ( match[3] ) { - match[2] = match[3]; - } else if ( (unquoted = match[4]) ) { - // Only check arguments that contain a pseudo - if ( rpseudo.test(unquoted) && - // Get excess from tokenize (recursively) - (excess = tokenize( unquoted, true )) && - // advance to the next closing parenthesis - (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { - - // excess is a negative index - unquoted = unquoted.slice( 0, excess ); - match[0] = match[0].slice( 0, excess ); - } - match[2] = unquoted; - } - - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice( 0, 3 ); - } - }, - - filter: { - "ID": assertGetIdNotName ? - function( id ) { - id = id.replace( rbackslash, "" ); - return function( elem ) { - return elem.getAttribute("id") === id; - }; - } : - function( id ) { - id = id.replace( rbackslash, "" ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); - return node && node.value === id; - }; - }, - - "TAG": function( nodeName ) { - if ( nodeName === "*" ) { - return function() { return true; }; - } - nodeName = nodeName.replace( rbackslash, "" ).toLowerCase(); - - return function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, - - "CLASS": function( className ) { - var pattern = classCache[ expando ][ className ]; - if ( !pattern ) { - pattern = classCache( className, new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)") ); - } - return function( elem ) { - return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" ); - }; - }, - - "ATTR": function( name, operator, check ) { - return function( elem, context ) { - var result = Sizzle.attr( elem, name ); - - if ( result == null ) { - return operator === "!="; - } - if ( !operator ) { - return true; - } - - result += ""; - - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf( check ) === 0 : - operator === "*=" ? check && result.indexOf( check ) > -1 : - operator === "$=" ? check && result.substr( result.length - check.length ) === check : - operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : - operator === "|=" ? result === check || result.substr( 0, check.length + 1 ) === check + "-" : - false; - }; - }, - - "CHILD": function( type, argument, first, last ) { - - if ( type === "nth" ) { - return function( elem ) { - var node, diff, - parent = elem.parentNode; - - if ( first === 1 && last === 0 ) { - return true; - } - - if ( parent ) { - diff = 0; - for ( node = parent.firstChild; node; node = node.nextSibling ) { - if ( node.nodeType === 1 ) { - diff++; - if ( elem === node ) { - break; - } - } - } - } - - // Incorporate the offset (or cast to NaN), then check against cycle size - diff -= last; - return diff === first || ( diff % first === 0 && diff / first >= 0 ); - }; - } - - return function( elem ) { - var node = elem; - - switch ( type ) { - case "only": - case "first": - while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - if ( type === "first" ) { - return true; - } - - node = elem; - - /* falls through */ - case "last": - while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - return true; - } - }; - }, - - "PSEUDO": function( pseudo, argument ) { - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - // Remember that setFilters inherits from pseudos - var args, - fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || - Sizzle.error( "unsupported pseudo: " + pseudo ); - - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if ( fn[ expando ] ) { - return fn( argument ); - } - - // But maintain support for old signatures - if ( fn.length > 1 ) { - args = [ pseudo, pseudo, "", argument ]; - return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction(function( seed, matches ) { - var idx, - matched = fn( seed, argument ), - i = matched.length; - while ( i-- ) { - idx = indexOf.call( seed, matched[i] ); - seed[ idx ] = !( matches[ idx ] = matched[i] ); - } - }) : - function( elem ) { - return fn( elem, 0, args ); - }; - } - - return fn; - } - }, - - pseudos: { - "not": markFunction(function( selector ) { - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var input = [], - results = [], - matcher = compile( selector.replace( rtrim, "$1" ) ); - - return matcher[ expando ] ? - markFunction(function( seed, matches, context, xml ) { - var elem, - unmatched = matcher( seed, null, xml, [] ), - i = seed.length; - - // Match elements unmatched by `matcher` - while ( i-- ) { - if ( (elem = unmatched[i]) ) { - seed[i] = !(matches[i] = elem); - } - } - }) : - function( elem, context, xml ) { - input[0] = elem; - matcher( input, null, xml, results ); - return !results.pop(); - }; - }), - - "has": markFunction(function( selector ) { - return function( elem ) { - return Sizzle( selector, elem ).length > 0; - }; - }), - - "contains": markFunction(function( text ) { - return function( elem ) { - return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; - }; - }), - - "enabled": function( elem ) { - return elem.disabled === false; - }, - - "disabled": function( elem ) { - return elem.disabled === true; - }, - - "checked": function( elem ) { - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); - }, - - "selected": function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - "parent": function( elem ) { - return !Expr.pseudos["empty"]( elem ); - }, - - "empty": function( elem ) { - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), - // not comment, processing instructions, or others - // Thanks to Diego Perini for the nodeName shortcut - // Greater than "@" means alpha characters (specifically not starting with "#" or "?") - var nodeType; - elem = elem.firstChild; - while ( elem ) { - if ( elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) { - return false; - } - elem = elem.nextSibling; - } - return true; - }, - - "header": function( elem ) { - return rheader.test( elem.nodeName ); - }, - - "text": function( elem ) { - var type, attr; - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) - // use getAttribute instead to test this case - return elem.nodeName.toLowerCase() === "input" && - (type = elem.type) === "text" && - ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type ); - }, - - // Input types - "radio": createInputPseudo("radio"), - "checkbox": createInputPseudo("checkbox"), - "file": createInputPseudo("file"), - "password": createInputPseudo("password"), - "image": createInputPseudo("image"), - - "submit": createButtonPseudo("submit"), - "reset": createButtonPseudo("reset"), - - "button": function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; - }, - - "input": function( elem ) { - return rinputs.test( elem.nodeName ); - }, - - "focus": function( elem ) { - var doc = elem.ownerDocument; - return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href); - }, - - "active": function( elem ) { - return elem === elem.ownerDocument.activeElement; - }, - - // Positional types - "first": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ 0 ]; - }), - - "last": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ length - 1 ]; - }), - - "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ argument < 0 ? argument + length : argument ]; - }), - - "even": createPositionalPseudo(function( matchIndexes, length, argument ) { - for ( var i = 0; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "odd": createPositionalPseudo(function( matchIndexes, length, argument ) { - for ( var i = 1; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { - for ( var i = argument < 0 ? argument + length : argument; --i >= 0; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { - for ( var i = argument < 0 ? argument + length : argument; ++i < length; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }) - } -}; - -function siblingCheck( a, b, ret ) { - if ( a === b ) { - return ret; - } - - var cur = a.nextSibling; - - while ( cur ) { - if ( cur === b ) { - return -1; - } - - cur = cur.nextSibling; - } - - return 1; -} - -sortOrder = docElem.compareDocumentPosition ? - function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - return ( !a.compareDocumentPosition || !b.compareDocumentPosition ? - a.compareDocumentPosition : - a.compareDocumentPosition(b) & 4 - ) ? -1 : 1; - } : - function( a, b ) { - // The nodes are identical, we can exit early - if ( a === b ) { - hasDuplicate = true; - return 0; - - // Fallback to using sourceIndex (in IE) if it's available on both nodes - } else if ( a.sourceIndex && b.sourceIndex ) { - return a.sourceIndex - b.sourceIndex; - } - - var al, bl, - ap = [], - bp = [], - aup = a.parentNode, - bup = b.parentNode, - cur = aup; - - // If the nodes are siblings (or identical) we can do a quick check - if ( aup === bup ) { - return siblingCheck( a, b ); - - // If no parents were found then the nodes are disconnected - } else if ( !aup ) { - return -1; - - } else if ( !bup ) { - return 1; - } - - // Otherwise they're somewhere else in the tree so we need - // to build up a full list of the parentNodes for comparison - while ( cur ) { - ap.unshift( cur ); - cur = cur.parentNode; - } - - cur = bup; - - while ( cur ) { - bp.unshift( cur ); - cur = cur.parentNode; - } - - al = ap.length; - bl = bp.length; - - // Start walking down the tree looking for a discrepancy - for ( var i = 0; i < al && i < bl; i++ ) { - if ( ap[i] !== bp[i] ) { - return siblingCheck( ap[i], bp[i] ); - } - } - - // We ended someplace up the tree so do a sibling check - return i === al ? - siblingCheck( a, bp[i], -1 ) : - siblingCheck( ap[i], b, 1 ); - }; - -// Always assume the presence of duplicates if sort doesn't -// pass them to our comparison function (as in Google Chrome). -[0, 0].sort( sortOrder ); -baseHasDuplicate = !hasDuplicate; - -// Document sorting and removing duplicates -Sizzle.uniqueSort = function( results ) { - var elem, - i = 1; - - hasDuplicate = baseHasDuplicate; - results.sort( sortOrder ); - - if ( hasDuplicate ) { - for ( ; (elem = results[i]); i++ ) { - if ( elem === results[ i - 1 ] ) { - results.splice( i--, 1 ); - } - } - } - - return results; -}; - -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; - -function tokenize( selector, parseOnly ) { - var matched, match, tokens, type, soFar, groups, preFilters, - cached = tokenCache[ expando ][ selector ]; - - if ( cached ) { - return parseOnly ? 0 : cached.slice( 0 ); - } - - soFar = selector; - groups = []; - preFilters = Expr.preFilter; - - while ( soFar ) { - - // Comma and first run - if ( !matched || (match = rcomma.exec( soFar )) ) { - if ( match ) { - soFar = soFar.slice( match[0].length ); - } - groups.push( tokens = [] ); - } - - matched = false; - - // Combinators - if ( (match = rcombinators.exec( soFar )) ) { - tokens.push( matched = new Token( match.shift() ) ); - soFar = soFar.slice( matched.length ); - - // Cast descendant combinators to space - matched.type = match[0].replace( rtrim, " " ); - } - - // Filters - for ( type in Expr.filter ) { - if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || - // The last two arguments here are (context, xml) for backCompat - (match = preFilters[ type ]( match, document, true ))) ) { - - tokens.push( matched = new Token( match.shift() ) ); - soFar = soFar.slice( matched.length ); - matched.type = type; - matched.matches = match; - } - } - - if ( !matched ) { - break; - } - } - - // Return the length of the invalid excess - // if we're just parsing - // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error( selector ) : - // Cache the tokens - tokenCache( selector, groups ).slice( 0 ); -} - -function addCombinator( matcher, combinator, base ) { - var dir = combinator.dir, - checkNonElements = base && combinator.dir === "parentNode", - doneName = done++; - - return combinator.first ? - // Check against closest ancestor/preceding element - function( elem, context, xml ) { - while ( (elem = elem[ dir ]) ) { - if ( checkNonElements || elem.nodeType === 1 ) { - return matcher( elem, context, xml ); - } - } - } : - - // Check against all ancestor/preceding elements - function( elem, context, xml ) { - // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching - if ( !xml ) { - var cache, - dirkey = dirruns + " " + doneName + " ", - cachedkey = dirkey + cachedruns; - while ( (elem = elem[ dir ]) ) { - if ( checkNonElements || elem.nodeType === 1 ) { - if ( (cache = elem[ expando ]) === cachedkey ) { - return elem.sizset; - } else if ( typeof cache === "string" && cache.indexOf(dirkey) === 0 ) { - if ( elem.sizset ) { - return elem; - } - } else { - elem[ expando ] = cachedkey; - if ( matcher( elem, context, xml ) ) { - elem.sizset = true; - return elem; - } - elem.sizset = false; - } - } - } - } else { - while ( (elem = elem[ dir ]) ) { - if ( checkNonElements || elem.nodeType === 1 ) { - if ( matcher( elem, context, xml ) ) { - return elem; - } - } - } - } - }; -} - -function elementMatcher( matchers ) { - return matchers.length > 1 ? - function( elem, context, xml ) { - var i = matchers.length; - while ( i-- ) { - if ( !matchers[i]( elem, context, xml ) ) { - return false; - } - } - return true; - } : - matchers[0]; -} - -function condense( unmatched, map, filter, context, xml ) { - var elem, - newUnmatched = [], - i = 0, - len = unmatched.length, - mapped = map != null; - - for ( ; i < len; i++ ) { - if ( (elem = unmatched[i]) ) { - if ( !filter || filter( elem, context, xml ) ) { - newUnmatched.push( elem ); - if ( mapped ) { - map.push( i ); - } - } - } - } - - return newUnmatched; -} - -function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { - if ( postFilter && !postFilter[ expando ] ) { - postFilter = setMatcher( postFilter ); - } - if ( postFinder && !postFinder[ expando ] ) { - postFinder = setMatcher( postFinder, postSelector ); - } - return markFunction(function( seed, results, context, xml ) { - // Positional selectors apply to seed elements, so it is invalid to follow them with relative ones - if ( seed && postFinder ) { - return; - } - - var i, elem, postFilterIn, - preMap = [], - postMap = [], - preexisting = results.length, - - // Get initial elements from seed or context - elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [], seed ), - - // Prefilter to get matcher input, preserving a map for seed-results synchronization - matcherIn = preFilter && ( seed || !selector ) ? - condense( elems, preMap, preFilter, context, xml ) : - elems, - - matcherOut = matcher ? - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || ( seed ? preFilter : preexisting || postFilter ) ? - - // ...intermediate processing is necessary - [] : - - // ...otherwise use results directly - results : - matcherIn; - - // Find primary matches - if ( matcher ) { - matcher( matcherIn, matcherOut, context, xml ); - } - - // Apply postFilter - if ( postFilter ) { - postFilterIn = condense( matcherOut, postMap ); - postFilter( postFilterIn, [], context, xml ); - - // Un-match failing elements by moving them back to matcherIn - i = postFilterIn.length; - while ( i-- ) { - if ( (elem = postFilterIn[i]) ) { - matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); - } - } - } - - // Keep seed and results synchronized - if ( seed ) { - // Ignore postFinder because it can't coexist with seed - i = preFilter && matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) ) { - seed[ preMap[i] ] = !(results[ preMap[i] ] = elem); - } - } - } else { - matcherOut = condense( - matcherOut === results ? - matcherOut.splice( preexisting, matcherOut.length ) : - matcherOut - ); - if ( postFinder ) { - postFinder( null, results, matcherOut, xml ); - } else { - push.apply( results, matcherOut ); - } - } - }); -} - -function matcherFromTokens( tokens ) { - var checkContext, matcher, j, - len = tokens.length, - leadingRelative = Expr.relative[ tokens[0].type ], - implicitRelative = leadingRelative || Expr.relative[" "], - i = leadingRelative ? 1 : 0, - - // The foundational matcher ensures that elements are reachable from top-level context(s) - matchContext = addCombinator( function( elem ) { - return elem === checkContext; - }, implicitRelative, true ), - matchAnyContext = addCombinator( function( elem ) { - return indexOf.call( checkContext, elem ) > -1; - }, implicitRelative, true ), - matchers = [ function( elem, context, xml ) { - return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - (checkContext = context).nodeType ? - matchContext( elem, context, xml ) : - matchAnyContext( elem, context, xml ) ); - } ]; - - for ( ; i < len; i++ ) { - if ( (matcher = Expr.relative[ tokens[i].type ]) ) { - matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; - } else { - // The concatenated values are (context, xml) for backCompat - matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); - - // Return special upon seeing a positional matcher - if ( matcher[ expando ] ) { - // Find the next relative operator (if any) for proper handling - j = ++i; - for ( ; j < len; j++ ) { - if ( Expr.relative[ tokens[j].type ] ) { - break; - } - } - return setMatcher( - i > 1 && elementMatcher( matchers ), - i > 1 && tokens.slice( 0, i - 1 ).join("").replace( rtrim, "$1" ), - matcher, - i < j && matcherFromTokens( tokens.slice( i, j ) ), - j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), - j < len && tokens.join("") - ); - } - matchers.push( matcher ); - } - } - - return elementMatcher( matchers ); -} - -function matcherFromGroupMatchers( elementMatchers, setMatchers ) { - var bySet = setMatchers.length > 0, - byElement = elementMatchers.length > 0, - superMatcher = function( seed, context, xml, results, expandContext ) { - var elem, j, matcher, - setMatched = [], - matchedCount = 0, - i = "0", - unmatched = seed && [], - outermost = expandContext != null, - contextBackup = outermostContext, - // We must always have either seed elements or context - elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), - // Nested matchers should use non-integer dirruns - dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.E); - - if ( outermost ) { - outermostContext = context !== document && context; - cachedruns = superMatcher.el; - } - - // Add elements passing elementMatchers directly to results - for ( ; (elem = elems[i]) != null; i++ ) { - if ( byElement && elem ) { - for ( j = 0; (matcher = elementMatchers[j]); j++ ) { - if ( matcher( elem, context, xml ) ) { - results.push( elem ); - break; - } - } - if ( outermost ) { - dirruns = dirrunsUnique; - cachedruns = ++superMatcher.el; - } - } - - // Track unmatched elements for set filters - if ( bySet ) { - // They will have gone through all possible matchers - if ( (elem = !matcher && elem) ) { - matchedCount--; - } - - // Lengthen the array for every element, matched or not - if ( seed ) { - unmatched.push( elem ); - } - } - } - - // Apply set filters to unmatched elements - matchedCount += i; - if ( bySet && i !== matchedCount ) { - for ( j = 0; (matcher = setMatchers[j]); j++ ) { - matcher( unmatched, setMatched, context, xml ); - } - - if ( seed ) { - // Reintegrate element matches to eliminate the need for sorting - if ( matchedCount > 0 ) { - while ( i-- ) { - if ( !(unmatched[i] || setMatched[i]) ) { - setMatched[i] = pop.call( results ); - } - } - } - - // Discard index placeholder values to get only actual matches - setMatched = condense( setMatched ); - } - - // Add matches to results - push.apply( results, setMatched ); - - // Seedless set matches succeeding multiple successful matchers stipulate sorting - if ( outermost && !seed && setMatched.length > 0 && - ( matchedCount + setMatchers.length ) > 1 ) { - - Sizzle.uniqueSort( results ); - } - } - - // Override manipulation of globals by nested matchers - if ( outermost ) { - dirruns = dirrunsUnique; - outermostContext = contextBackup; - } - - return unmatched; - }; - - superMatcher.el = 0; - return bySet ? - markFunction( superMatcher ) : - superMatcher; -} - -compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { - var i, - setMatchers = [], - elementMatchers = [], - cached = compilerCache[ expando ][ selector ]; - - if ( !cached ) { - // Generate a function of recursive functions that can be used to check each element - if ( !group ) { - group = tokenize( selector ); - } - i = group.length; - while ( i-- ) { - cached = matcherFromTokens( group[i] ); - if ( cached[ expando ] ) { - setMatchers.push( cached ); - } else { - elementMatchers.push( cached ); - } - } - - // Cache the compiled function - cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); - } - return cached; -}; - -function multipleContexts( selector, contexts, results, seed ) { - var i = 0, - len = contexts.length; - for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results, seed ); - } - return results; -} - -function select( selector, context, results, seed, xml ) { - var i, tokens, token, type, find, - match = tokenize( selector ), - j = match.length; - - if ( !seed ) { - // Try to minimize operations if there is only one group - if ( match.length === 1 ) { - - // Take a shortcut and set the context if the root selector is an ID - tokens = match[0] = match[0].slice( 0 ); - if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && - context.nodeType === 9 && !xml && - Expr.relative[ tokens[1].type ] ) { - - context = Expr.find["ID"]( token.matches[0].replace( rbackslash, "" ), context, xml )[0]; - if ( !context ) { - return results; - } - - selector = selector.slice( tokens.shift().length ); - } - - // Fetch a seed set for right-to-left matching - for ( i = matchExpr["POS"].test( selector ) ? -1 : tokens.length - 1; i >= 0; i-- ) { - token = tokens[i]; - - // Abort if we hit a combinator - if ( Expr.relative[ (type = token.type) ] ) { - break; - } - if ( (find = Expr.find[ type ]) ) { - // Search, expanding context for leading sibling combinators - if ( (seed = find( - token.matches[0].replace( rbackslash, "" ), - rsibling.test( tokens[0].type ) && context.parentNode || context, - xml - )) ) { - - // If seed is empty or no tokens remain, we can return early - tokens.splice( i, 1 ); - selector = seed.length && tokens.join(""); - if ( !selector ) { - push.apply( results, slice.call( seed, 0 ) ); - return results; - } - - break; - } - } - } - } - } - - // Compile and execute a filtering function - // Provide `match` to avoid retokenization if we modified the selector above - compile( selector, match )( - seed, - context, - xml, - results, - rsibling.test( selector ) - ); - return results; -} - -if ( document.querySelectorAll ) { - (function() { - var disconnectedMatch, - oldSelect = select, - rescape = /'|\\/g, - rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g, - - // qSa(:focus) reports false when true (Chrome 21), - // A support test would require too much code (would include document ready) - rbuggyQSA = [":focus"], - - // matchesSelector(:focus) reports false when true (Chrome 21), - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - // A support test would require too much code (would include document ready) - // just skip matchesSelector for :active - rbuggyMatches = [ ":active", ":focus" ], - matches = docElem.matchesSelector || - docElem.mozMatchesSelector || - docElem.webkitMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector; - - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert(function( div ) { - // Select is set to empty string on purpose - // This is to test IE's treatment of not explictly - // setting a boolean content attribute, - // since its presence should be enough - // http://bugs.jquery.com/ticket/12359 - div.innerHTML = ""; - - // IE8 - Some boolean attributes are not treated correctly - if ( !div.querySelectorAll("[selected]").length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" ); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here (do not put tests after this one) - if ( !div.querySelectorAll(":checked").length ) { - rbuggyQSA.push(":checked"); - } - }); - - assert(function( div ) { - - // Opera 10-12/IE9 - ^= $= *= and empty values - // Should not select anything - div.innerHTML = "

"; - if ( div.querySelectorAll("[test^='']").length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" ); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here (do not put tests after this one) - div.innerHTML = ""; - if ( !div.querySelectorAll(":enabled").length ) { - rbuggyQSA.push(":enabled", ":disabled"); - } - }); - - // rbuggyQSA always contains :focus, so no need for a length check - rbuggyQSA = /* rbuggyQSA.length && */ new RegExp( rbuggyQSA.join("|") ); - - select = function( selector, context, results, seed, xml ) { - // Only use querySelectorAll when not filtering, - // when this is not xml, - // and when no QSA bugs apply - if ( !seed && !xml && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { - var groups, i, - old = true, - nid = expando, - newContext = context, - newSelector = context.nodeType === 9 && selector; - - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - groups = tokenize( selector ); - - if ( (old = context.getAttribute("id")) ) { - nid = old.replace( rescape, "\\$&" ); - } else { - context.setAttribute( "id", nid ); - } - nid = "[id='" + nid + "'] "; - - i = groups.length; - while ( i-- ) { - groups[i] = nid + groups[i].join(""); - } - newContext = rsibling.test( selector ) && context.parentNode || context; - newSelector = groups.join(","); - } - - if ( newSelector ) { - try { - push.apply( results, slice.call( newContext.querySelectorAll( - newSelector - ), 0 ) ); - return results; - } catch(qsaError) { - } finally { - if ( !old ) { - context.removeAttribute("id"); - } - } - } - } - - return oldSelect( selector, context, results, seed, xml ); - }; - - if ( matches ) { - assert(function( div ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - disconnectedMatch = matches.call( div, "div" ); - - // This should fail with an exception - // Gecko does not error, returns false instead - try { - matches.call( div, "[test!='']:sizzle" ); - rbuggyMatches.push( "!=", pseudos ); - } catch ( e ) {} - }); - - // rbuggyMatches always contains :active and :focus, so no need for a length check - rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join("|") ); - - Sizzle.matchesSelector = function( elem, expr ) { - // Make sure that attribute selectors are quoted - expr = expr.replace( rattributeQuotes, "='$1']" ); - - // rbuggyMatches always contains :active, so no need for an existence check - if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && (!rbuggyQSA || !rbuggyQSA.test( expr )) ) { - try { - var ret = matches.call( elem, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { - return ret; - } - } catch(e) {} - } - - return Sizzle( expr, null, null, [ elem ] ).length > 0; - }; - } - })(); -} - -// Deprecated -Expr.pseudos["nth"] = Expr.pseudos["eq"]; - -// Back-compat -function setFilters() {} -Expr.filters = setFilters.prototype = Expr.pseudos; -Expr.setFilters = new setFilters(); - +/*! + * Sizzle CSS Selector Engine + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license + * http://sizzlejs.com/ + */ +(function( window, undefined ) { + +var cachedruns, + assertGetIdNotName, + Expr, + getText, + isXML, + contains, + compile, + sortOrder, + hasDuplicate, + outermostContext, + + baseHasDuplicate = true, + strundefined = "undefined", + + expando = ( "sizcache" + Math.random() ).replace( ".", "" ), + + Token = String, + document = window.document, + docElem = document.documentElement, + dirruns = 0, + done = 0, + pop = [].pop, + push = [].push, + slice = [].slice, + // Use a stripped-down indexOf if a native one is unavailable + indexOf = [].indexOf || function( elem ) { + var i = 0, + len = this.length; + for ( ; i < len; i++ ) { + if ( this[i] === elem ) { + return i; + } + } + return -1; + }, + + // Augment a function for special use by Sizzle + markFunction = function( fn, value ) { + fn[ expando ] = value == null || value; + return fn; + }, + + createCache = function() { + var cache = {}, + keys = []; + + return markFunction(function( key, value ) { + // Only keep the most recent entries + if ( keys.push( key ) > Expr.cacheLength ) { + delete cache[ keys.shift() ]; + } + + return (cache[ key ] = value); + }, cache ); + }, + + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + + // Regex + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors) + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors + operators = "([*^$|!~]?=)", + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + + "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", + + // Prefer arguments not in parens/brackets, + // then attribute selectors and non-pseudos (denoted by :), + // then anything else + // These preferences are here to reduce the number of selectors + // needing tokenize in the PSEUDO preFilter + pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)", + + // For matchExpr.POS and matchExpr.needsContext + pos = ":(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ), + rpseudo = new RegExp( pseudos ), + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/, + + rnot = /^:not/, + rsibling = /[\x20\t\r\n\f]*[+~]/, + rendsWithNot = /:not\($/, + + rheader = /h\d/i, + rinputs = /input|select|textarea|button/i, + + rbackslash = /\\(?!\\)/g, + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "POS": new RegExp( pos, "i" ), + "CHILD": new RegExp( "^:(only|nth|first|last)-child(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + // For use in libraries implementing .is() + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|" + pos, "i" ) + }, + + // Support + + // Used for testing something on an element + assert = function( fn ) { + var div = document.createElement("div"); + + try { + return fn( div ); + } catch (e) { + return false; + } finally { + // release memory in IE + div = null; + } + }, + + // Check if getElementsByTagName("*") returns only elements + assertTagNameNoComments = assert(function( div ) { + div.appendChild( document.createComment("") ); + return !div.getElementsByTagName("*").length; + }), + + // Check if getAttribute returns normalized href attributes + assertHrefNotNormalized = assert(function( div ) { + div.innerHTML = ""; + return div.firstChild && typeof div.firstChild.getAttribute !== strundefined && + div.firstChild.getAttribute("href") === "#"; + }), + + // Check if attributes should be retrieved by attribute nodes + assertAttributes = assert(function( div ) { + div.innerHTML = ""; + var type = typeof div.lastChild.getAttribute("multiple"); + // IE8 returns a string for some attributes even when not present + return type !== "boolean" && type !== "string"; + }), + + // Check if getElementsByClassName can be trusted + assertUsableClassName = assert(function( div ) { + // Opera can't find a second classname (in 9.6) + div.innerHTML = ""; + if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) { + return false; + } + + // Safari 3.2 caches class attributes and doesn't catch changes + div.lastChild.className = "e"; + return div.getElementsByClassName("e").length === 2; + }), + + // Check if getElementById returns elements by name + // Check if getElementsByName privileges form controls or returns elements by ID + assertUsableName = assert(function( div ) { + // Inject content + div.id = expando + 0; + div.innerHTML = "
"; + docElem.insertBefore( div, docElem.firstChild ); + + // Test + var pass = document.getElementsByName && + // buggy browsers will return fewer than the correct 2 + document.getElementsByName( expando ).length === 2 + + // buggy browsers will return more than the correct 0 + document.getElementsByName( expando + 0 ).length; + assertGetIdNotName = !document.getElementById( expando ); + + // Cleanup + docElem.removeChild( div ); + + return pass; + }); + +// If slice is not available, provide a backup +try { + slice.call( docElem.childNodes, 0 )[0].nodeType; +} catch ( e ) { + slice = function( i ) { + var elem, + results = []; + for ( ; (elem = this[i]); i++ ) { + results.push( elem ); + } + return results; + }; +} + +function Sizzle( selector, context, results, seed ) { + results = results || []; + context = context || document; + var match, elem, xml, m, + nodeType = context.nodeType; + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + if ( nodeType !== 1 && nodeType !== 9 ) { + return []; + } + + xml = isXML( context ); + + if ( !xml && !seed ) { + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) { + push.apply( results, slice.call(context.getElementsByClassName( m ), 0) ); + return results; + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed, xml ); +} + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + return Sizzle( expr, null, null, [ elem ] ).length > 0; +}; + +// Returns a function to use in pseudos for input types +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +// Returns a function to use in pseudos for buttons +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +// Returns a function to use in pseudos for positionals +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( nodeType ) { + if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (see #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + } else { + + // If no nodeType, this is expected to be an array + for ( ; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } + return ret; +}; + +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +// Element contains another +contains = Sizzle.contains = docElem.contains ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) ); + } : + docElem.compareDocumentPosition ? + function( a, b ) { + return b && !!( a.compareDocumentPosition( b ) & 16 ); + } : + function( a, b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + return false; + }; + +Sizzle.attr = function( elem, name ) { + var val, + xml = isXML( elem ); + + if ( !xml ) { + name = name.toLowerCase(); + } + if ( (val = Expr.attrHandle[ name ]) ) { + return val( elem ); + } + if ( xml || assertAttributes ) { + return elem.getAttribute( name ); + } + val = elem.getAttributeNode( name ); + return val ? + typeof elem[ name ] === "boolean" ? + elem[ name ] ? name : null : + val.specified ? val.value : null : + null; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + // IE6/7 return a modified href + attrHandle: assertHrefNotNormalized ? + {} : + { + "href": function( elem ) { + return elem.getAttribute( "href", 2 ); + }, + "type": function( elem ) { + return elem.getAttribute("type"); + } + }, + + find: { + "ID": assertGetIdNotName ? + function( id, context, xml ) { + if ( typeof context.getElementById !== strundefined && !xml ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + } : + function( id, context, xml ) { + if ( typeof context.getElementById !== strundefined && !xml ) { + var m = context.getElementById( id ); + + return m ? + m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ? + [m] : + undefined : + []; + } + }, + + "TAG": assertTagNameNoComments ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + var elem, + tmp = [], + i = 0; + + for ( ; (elem = results[i]); i++ ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }, + + "NAME": assertUsableName && function( tag, context ) { + if ( typeof context.getElementsByName !== strundefined ) { + return context.getElementsByName( name ); + } + }, + + "CLASS": assertUsableClassName && function( className, context, xml ) { + if ( typeof context.getElementsByClassName !== strundefined && !xml ) { + return context.getElementsByClassName( className ); + } + } + }, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( rbackslash, "" ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[4] || match[5] || "" ).replace( rbackslash, "" ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 3 xn-component of xn+y argument ([+-]?\d*n|) + 4 sign of xn-component + 5 x of xn-component + 6 sign of y-component + 7 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1] === "nth" ) { + // nth-child requires argument + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === "even" || match[2] === "odd" ) ); + match[4] = +( ( match[6] + match[7] ) || match[2] === "odd" ); + + // other types prohibit arguments + } else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var unquoted, excess; + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + if ( match[3] ) { + match[2] = match[3]; + } else if ( (unquoted = match[4]) ) { + // Only check arguments that contain a pseudo + if ( rpseudo.test(unquoted) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + unquoted = unquoted.slice( 0, excess ); + match[0] = match[0].slice( 0, excess ); + } + match[2] = unquoted; + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + "ID": assertGetIdNotName ? + function( id ) { + id = id.replace( rbackslash, "" ); + return function( elem ) { + return elem.getAttribute("id") === id; + }; + } : + function( id ) { + id = id.replace( rbackslash, "" ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === id; + }; + }, + + "TAG": function( nodeName ) { + if ( nodeName === "*" ) { + return function() { return true; }; + } + nodeName = nodeName.replace( rbackslash, "" ).toLowerCase(); + + return function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ expando ][ className ]; + if ( !pattern ) { + pattern = classCache( className, new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)") ); + } + return function( elem ) { + return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" ); + }; + }, + + "ATTR": function( name, operator, check ) { + return function( elem, context ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.substr( result.length - check.length ) === check : + operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.substr( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, argument, first, last ) { + + if ( type === "nth" ) { + return function( elem ) { + var node, diff, + parent = elem.parentNode; + + if ( first === 1 && last === 0 ) { + return true; + } + + if ( parent ) { + diff = 0; + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + diff++; + if ( elem === node ) { + break; + } + } + } + } + + // Incorporate the offset (or cast to NaN), then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + }; + } + + return function( elem ) { + var node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + /* falls through */ + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), + // not comment, processing instructions, or others + // Thanks to Diego Perini for the nodeName shortcut + // Greater than "@" means alpha characters (specifically not starting with "#" or "?") + var nodeType; + elem = elem.firstChild; + while ( elem ) { + if ( elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) { + return false; + } + elem = elem.nextSibling; + } + return true; + }, + + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "text": function( elem ) { + var type, attr; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && + (type = elem.type) === "text" && + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type ); + }, + + // Input types + "radio": createInputPseudo("radio"), + "checkbox": createInputPseudo("checkbox"), + "file": createInputPseudo("file"), + "password": createInputPseudo("password"), + "image": createInputPseudo("image"), + + "submit": createButtonPseudo("submit"), + "reset": createButtonPseudo("reset"), + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "focus": function( elem ) { + var doc = elem.ownerDocument; + return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href); + }, + + "active": function( elem ) { + return elem === elem.ownerDocument.activeElement; + }, + + // Positional types + "first": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length, argument ) { + for ( var i = 0; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length, argument ) { + for ( var i = 1; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + for ( var i = argument < 0 ? argument + length : argument; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + for ( var i = argument < 0 ? argument + length : argument; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +function siblingCheck( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; +} + +sortOrder = docElem.compareDocumentPosition ? + function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + return ( !a.compareDocumentPosition || !b.compareDocumentPosition ? + a.compareDocumentPosition : + a.compareDocumentPosition(b) & 4 + ) ? -1 : 1; + } : + function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + +// Always assume the presence of duplicates if sort doesn't +// pass them to our comparison function (as in Google Chrome). +[0, 0].sort( sortOrder ); +baseHasDuplicate = !hasDuplicate; + +// Document sorting and removing duplicates +Sizzle.uniqueSort = function( results ) { + var elem, + i = 1; + + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( ; (elem = results[i]); i++ ) { + if ( elem === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + + return results; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +function tokenize( selector, parseOnly ) { + var matched, match, tokens, type, soFar, groups, preFilters, + cached = tokenCache[ expando ][ selector ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + soFar = soFar.slice( match[0].length ); + } + groups.push( tokens = [] ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + tokens.push( matched = new Token( match.shift() ) ); + soFar = soFar.slice( matched.length ); + + // Cast descendant combinators to space + matched.type = match[0].replace( rtrim, " " ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + // The last two arguments here are (context, xml) for backCompat + (match = preFilters[ type ]( match, document, true ))) ) { + + tokens.push( matched = new Token( match.shift() ) ); + soFar = soFar.slice( matched.length ); + matched.type = type; + matched.matches = match; + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && combinator.dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( checkNonElements || elem.nodeType === 1 ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( !xml ) { + var cache, + dirkey = dirruns + " " + doneName + " ", + cachedkey = dirkey + cachedruns; + while ( (elem = elem[ dir ]) ) { + if ( checkNonElements || elem.nodeType === 1 ) { + if ( (cache = elem[ expando ]) === cachedkey ) { + return elem.sizset; + } else if ( typeof cache === "string" && cache.indexOf(dirkey) === 0 ) { + if ( elem.sizset ) { + return elem; + } + } else { + elem[ expando ] = cachedkey; + if ( matcher( elem, context, xml ) ) { + elem.sizset = true; + return elem; + } + elem.sizset = false; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( checkNonElements || elem.nodeType === 1 ) { + if ( matcher( elem, context, xml ) ) { + return elem; + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + // Positional selectors apply to seed elements, so it is invalid to follow them with relative ones + if ( seed && postFinder ) { + return; + } + + var i, elem, postFilterIn, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [], seed ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + postFilterIn = condense( matcherOut, postMap ); + postFilter( postFilterIn, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = postFilterIn.length; + while ( i-- ) { + if ( (elem = postFilterIn[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + // Keep seed and results synchronized + if ( seed ) { + // Ignore postFinder because it can't coexist with seed + i = preFilter && matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + seed[ preMap[i] ] = !(results[ preMap[i] ] = elem); + } + } + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + // The concatenated values are (context, xml) for backCompat + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && tokens.slice( 0, i - 1 ).join("").replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && tokens.join("") + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, expandContext ) { + var elem, j, matcher, + setMatched = [], + matchedCount = 0, + i = "0", + unmatched = seed && [], + outermost = expandContext != null, + contextBackup = outermostContext, + // We must always have either seed elements or context + elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), + // Nested matchers should use non-integer dirruns + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.E); + + if ( outermost ) { + outermostContext = context !== document && context; + cachedruns = superMatcher.el; + } + + // Add elements passing elementMatchers directly to results + for ( ; (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + for ( j = 0; (matcher = elementMatchers[j]); j++ ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + cachedruns = ++superMatcher.el; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + for ( j = 0; (matcher = setMatchers[j]); j++ ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + superMatcher.el = 0; + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ expando ][ selector ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !group ) { + group = tokenize( selector ); + } + i = group.length; + while ( i-- ) { + cached = matcherFromTokens( group[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + } + return cached; +}; + +function multipleContexts( selector, contexts, results, seed ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results, seed ); + } + return results; +} + +function select( selector, context, results, seed, xml ) { + var i, tokens, token, type, find, + match = tokenize( selector ), + j = match.length; + + if ( !seed ) { + // Try to minimize operations if there is only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + context.nodeType === 9 && !xml && + Expr.relative[ tokens[1].type ] ) { + + context = Expr.find["ID"]( token.matches[0].replace( rbackslash, "" ), context, xml )[0]; + if ( !context ) { + return results; + } + + selector = selector.slice( tokens.shift().length ); + } + + // Fetch a seed set for right-to-left matching + for ( i = matchExpr["POS"].test( selector ) ? -1 : tokens.length - 1; i >= 0; i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( rbackslash, "" ), + rsibling.test( tokens[0].type ) && context.parentNode || context, + xml + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && tokens.join(""); + if ( !selector ) { + push.apply( results, slice.call( seed, 0 ) ); + return results; + } + + break; + } + } + } + } + } + + // Compile and execute a filtering function + // Provide `match` to avoid retokenization if we modified the selector above + compile( selector, match )( + seed, + context, + xml, + results, + rsibling.test( selector ) + ); + return results; +} + +if ( document.querySelectorAll ) { + (function() { + var disconnectedMatch, + oldSelect = select, + rescape = /'|\\/g, + rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g, + + // qSa(:focus) reports false when true (Chrome 21), + // A support test would require too much code (would include document ready) + rbuggyQSA = [":focus"], + + // matchesSelector(:focus) reports false when true (Chrome 21), + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + // A support test would require too much code (would include document ready) + // just skip matchesSelector for :active + rbuggyMatches = [ ":active", ":focus" ], + matches = docElem.matchesSelector || + docElem.mozMatchesSelector || + docElem.webkitMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector; + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explictly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = ""; + + // IE8 - Some boolean attributes are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here (do not put tests after this one) + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + + // Opera 10-12/IE9 - ^= $= *= and empty values + // Should not select anything + div.innerHTML = "

"; + if ( div.querySelectorAll("[test^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here (do not put tests after this one) + div.innerHTML = ""; + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push(":enabled", ":disabled"); + } + }); + + // rbuggyQSA always contains :focus, so no need for a length check + rbuggyQSA = /* rbuggyQSA.length && */ new RegExp( rbuggyQSA.join("|") ); + + select = function( selector, context, results, seed, xml ) { + // Only use querySelectorAll when not filtering, + // when this is not xml, + // and when no QSA bugs apply + if ( !seed && !xml && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + var groups, i, + old = true, + nid = expando, + newContext = context, + newSelector = context.nodeType === 9 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + groups[i].join(""); + } + newContext = rsibling.test( selector ) && context.parentNode || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, slice.call( newContext.querySelectorAll( + newSelector + ), 0 ) ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + + return oldSelect( selector, context, results, seed, xml ); + }; + + if ( matches ) { + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + try { + matches.call( div, "[test!='']:sizzle" ); + rbuggyMatches.push( "!=", pseudos ); + } catch ( e ) {} + }); + + // rbuggyMatches always contains :active and :focus, so no need for a length check + rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join("|") ); + + Sizzle.matchesSelector = function( elem, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + // rbuggyMatches always contains :active, so no need for an existence check + if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && (!rbuggyQSA || !rbuggyQSA.test( expr )) ) { + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch(e) {} + } + + return Sizzle( expr, null, null, [ elem ] ).length > 0; + }; + } + })(); +} + +// Deprecated +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Back-compat +function setFilters() {} +Expr.filters = setFilters.prototype = Expr.pseudos; +Expr.setFilters = new setFilters(); + // Override sizzle attribute retrieval Sizzle.attr = jQuery.attr; jQuery.find = Sizzle; @@ -5335,9 +5335,9 @@ jQuery.unique = Sizzle.uniqueSort; jQuery.text = Sizzle.getText; jQuery.isXMLDoc = Sizzle.isXML; jQuery.contains = Sizzle.contains; - - -})( window ); + + +})( window ); var runtil = /Until$/, rparentsprev = /^(?:parents|prev(?:Until|All))/, isSimple = /^.[^:#\[\.,]*$/, diff --git a/tests/jquery-1.8.0.js b/tests/jquery-1.8.0.js index 0770682947..dfe5eb00a9 100644 --- a/tests/jquery-1.8.0.js +++ b/tests/jquery-1.8.0.js @@ -3668,1463 +3668,1463 @@ jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblcl jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; } }); -/*! - * Sizzle CSS Selector Engine - * Copyright 2012 jQuery Foundation and other contributors - * Released under the MIT license - * http://sizzlejs.com/ - */ -(function( window, undefined ) { - -var cachedruns, - dirruns, - sortOrder, - siblingCheck, - assertGetIdNotName, - - document = window.document, - docElem = document.documentElement, - - strundefined = "undefined", - hasDuplicate = false, - baseHasDuplicate = true, - done = 0, - slice = [].slice, - push = [].push, - - expando = ( "sizcache" + Math.random() ).replace( ".", "" ), - - // Regex - - // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - // http://www.w3.org/TR/css3-syntax/#characters - characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+", - - // Loosely modeled on CSS identifier characters - // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors) - // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = characterEncoding.replace( "w", "w#" ), - - // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors - operators = "([*^$|!~]?=)", - attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + - "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", - pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|((?:[^,]|\\\\,|(?:,(?=[^\\[]*\\]))|(?:,(?=[^\\(]*\\))))*))\\)|)", - pos = ":(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\)|)(?=[^-]|$)", - combinators = whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*", - groups = "(?=[^\\x20\\t\\r\\n\\f])(?:\\\\.|" + attributes + "|" + pseudos.replace( 2, 7 ) + "|[^\\\\(),])+", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), - - rcombinators = new RegExp( "^" + combinators ), - - // All simple (non-comma) selectors, excluding insignifant trailing whitespace - rgroups = new RegExp( groups + "?(?=" + whitespace + "*,|$)", "g" ), - - // A selector, or everything after leading whitespace - // Optionally followed in either case by a ")" for terminating sub-selectors - rselector = new RegExp( "^(?:(?!,)(?:(?:^|,)" + whitespace + "*" + groups + ")*?|" + whitespace + "*(.*?))(\\)|$)" ), - - // All combinators and selector components (attribute test, tag, pseudo, etc.), the latter appearing together when consecutive - rtokens = new RegExp( groups.slice( 19, -6 ) + "\\x20\\t\\r\\n\\f>+~])+|" + combinators, "g" ), - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/, - - rsibling = /[\x20\t\r\n\f]*[+~]/, - rendsWithNot = /:not\($/, - - rheader = /h\d/i, - rinputs = /input|select|textarea|button/i, - - rbackslash = /\\(?!\\)/g, - - matchExpr = { - "ID": new RegExp( "^#(" + characterEncoding + ")" ), - "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), - "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ), - "TAG": new RegExp( "^(" + characterEncoding.replace( "[-", "[-\\*" ) + ")" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "CHILD": new RegExp( "^:(only|nth|last|first)-child(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - "POS": new RegExp( pos, "ig" ), - // For use in libraries implementing .is() - "needsContext": new RegExp( "^" + whitespace + "*[>+~]|" + pos, "i" ) - }, - - classCache = {}, - cachedClasses = [], - compilerCache = {}, - cachedSelectors = [], - - // Mark a function for use in filtering - markFunction = function( fn ) { - fn.sizzleFilter = true; - return fn; - }, - - // Returns a function to use in pseudos for input types - createInputFunction = function( type ) { - return function( elem ) { - // Check the input's nodeName and type - return elem.nodeName.toLowerCase() === "input" && elem.type === type; - }; - }, - - // Returns a function to use in pseudos for buttons - createButtonFunction = function( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; - }, - - // Used for testing something on an element - assert = function( fn ) { - var pass = false, - div = document.createElement("div"); - try { - pass = fn( div ); - } catch (e) {} - // release memory in IE - div = null; - return pass; - }, - - // Check if attributes should be retrieved by attribute nodes - assertAttributes = assert(function( div ) { - div.innerHTML = ""; - var type = typeof div.lastChild.getAttribute("multiple"); - // IE8 returns a string for some attributes even when not present - return type !== "boolean" && type !== "string"; - }), - - // Check if getElementById returns elements by name - // Check if getElementsByName privileges form controls or returns elements by ID - assertUsableName = assert(function( div ) { - // Inject content - div.id = expando + 0; - div.innerHTML = "
"; - docElem.insertBefore( div, docElem.firstChild ); - - // Test - var pass = document.getElementsByName && - // buggy browsers will return fewer than the correct 2 - document.getElementsByName( expando ).length === - // buggy browsers will return more than the correct 0 - 2 + document.getElementsByName( expando + 0 ).length; - assertGetIdNotName = !document.getElementById( expando ); - - // Cleanup - docElem.removeChild( div ); - - return pass; - }), - - // Check if the browser returns only elements - // when doing getElementsByTagName("*") - assertTagNameNoComments = assert(function( div ) { - div.appendChild( document.createComment("") ); - return div.getElementsByTagName("*").length === 0; - }), - - // Check if getAttribute returns normalized href attributes - assertHrefNotNormalized = assert(function( div ) { - div.innerHTML = ""; - return div.firstChild && typeof div.firstChild.getAttribute !== strundefined && - div.firstChild.getAttribute("href") === "#"; - }), - - // Check if getElementsByClassName can be trusted - assertUsableClassName = assert(function( div ) { - // Opera can't find a second classname (in 9.6) - div.innerHTML = ""; - if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { - return false; - } - - // Safari caches class attributes, doesn't catch changes (in 3.2) - div.lastChild.className = "e"; - return div.getElementsByClassName("e").length !== 1; - }); - -var Sizzle = function( selector, context, results, seed ) { - results = results || []; - context = context || document; - var match, elem, xml, m, - nodeType = context.nodeType; - - if ( nodeType !== 1 && nodeType !== 9 ) { - return []; - } - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - xml = isXML( context ); - - if ( !xml && !seed ) { - if ( (match = rquickExpr.exec( selector )) ) { - // Speed-up: Sizzle("#ID") - if ( (m = match[1]) ) { - if ( nodeType === 9 ) { - elem = context.getElementById( m ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE, Opera, and Webkit return items - // by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - } else { - // Context is not a document - if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && - contains( context, elem ) && elem.id === m ) { - results.push( elem ); - return results; - } - } - - // Speed-up: Sizzle("TAG") - } else if ( match[2] ) { - push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) ); - return results; - - // Speed-up: Sizzle(".CLASS") - } else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) { - push.apply( results, slice.call(context.getElementsByClassName( m ), 0) ); - return results; - } - } - } - - // All others - return select( selector, context, results, seed, xml ); -}; - -var Expr = Sizzle.selectors = { - - // Can be adjusted by the user - cacheLength: 50, - - match: matchExpr, - - order: [ "ID", "TAG" ], - - attrHandle: {}, - - createPseudo: markFunction, - - find: { - "ID": assertGetIdNotName ? - function( id, context, xml ) { - if ( typeof context.getElementById !== strundefined && !xml ) { - var m = context.getElementById( id ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [m] : []; - } - } : - function( id, context, xml ) { - if ( typeof context.getElementById !== strundefined && !xml ) { - var m = context.getElementById( id ); - - return m ? - m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ? - [m] : - undefined : - []; - } - }, - - "TAG": assertTagNameNoComments ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== strundefined ) { - return context.getElementsByTagName( tag ); - } - } : - function( tag, context ) { - var results = context.getElementsByTagName( tag ); - - // Filter out possible comments - if ( tag === "*" ) { - var elem, - tmp = [], - i = 0; - - for ( ; (elem = results[i]); i++ ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } - - return tmp; - } - return results; - } - }, - - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, - - preFilter: { - "ATTR": function( match ) { - match[1] = match[1].replace( rbackslash, "" ); - - // Move the given value to match[3] whether quoted or unquoted - match[3] = ( match[4] || match[5] || "" ).replace( rbackslash, "" ); - - if ( match[2] === "~=" ) { - match[3] = " " + match[3] + " "; - } - - return match.slice( 0, 4 ); - }, - - "CHILD": function( match ) { - /* matches from matchExpr.CHILD - 1 type (only|nth|...) - 2 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 3 xn-component of xn+y argument ([+-]?\d*n|) - 4 sign of xn-component - 5 x of xn-component - 6 sign of y-component - 7 y of y-component - */ - match[1] = match[1].toLowerCase(); - - if ( match[1] === "nth" ) { - // nth-child requires argument - if ( !match[2] ) { - Sizzle.error( match[0] ); - } - - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === "even" || match[2] === "odd" ) ); - match[4] = +( ( match[6] + match[7] ) || match[2] === "odd" ); - - // other types prohibit arguments - } else if ( match[2] ) { - Sizzle.error( match[0] ); - } - - return match; - }, - - "PSEUDO": function( match ) { - var argument, - unquoted = match[4]; - - if ( matchExpr["CHILD"].test( match[0] ) ) { - return null; - } - - // Relinquish our claim on characters in `unquoted` from a closing parenthesis on - if ( unquoted && (argument = rselector.exec( unquoted )) && argument.pop() ) { - - match[0] = match[0].slice( 0, argument[0].length - unquoted.length - 1 ); - unquoted = argument[0].slice( 0, -1 ); - } - - // Quoted or unquoted, we have the full argument - // Return only captures needed by the pseudo filter method (type and argument) - match.splice( 2, 3, unquoted || match[3] ); - return match; - } - }, - - filter: { - "ID": assertGetIdNotName ? - function( id ) { - id = id.replace( rbackslash, "" ); - return function( elem ) { - return elem.getAttribute("id") === id; - }; - } : - function( id ) { - id = id.replace( rbackslash, "" ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); - return node && node.value === id; - }; - }, - - "TAG": function( nodeName ) { - if ( nodeName === "*" ) { - return function() { return true; }; - } - nodeName = nodeName.replace( rbackslash, "" ).toLowerCase(); - - return function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, - - "CLASS": function( className ) { - var pattern = classCache[ className ]; - if ( !pattern ) { - pattern = classCache[ className ] = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" ); - cachedClasses.push( className ); - // Avoid too large of a cache - if ( cachedClasses.length > Expr.cacheLength ) { - delete classCache[ cachedClasses.shift() ]; - } - } - return function( elem ) { - return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" ); - }; - }, - - "ATTR": function( name, operator, check ) { - if ( !operator ) { - return function( elem ) { - return Sizzle.attr( elem, name ) != null; - }; - } - - return function( elem ) { - var result = Sizzle.attr( elem, name ), - value = result + ""; - - if ( result == null ) { - return operator === "!="; - } - - switch ( operator ) { - case "=": - return value === check; - case "!=": - return value !== check; - case "^=": - return check && value.indexOf( check ) === 0; - case "*=": - return check && value.indexOf( check ) > -1; - case "$=": - return check && value.substr( value.length - check.length ) === check; - case "~=": - return ( " " + value + " " ).indexOf( check ) > -1; - case "|=": - return value === check || value.substr( 0, check.length + 1 ) === check + "-"; - } - }; - }, - - "CHILD": function( type, argument, first, last ) { - - if ( type === "nth" ) { - var doneName = done++; - - return function( elem ) { - var parent, diff, - count = 0, - node = elem; - - if ( first === 1 && last === 0 ) { - return true; - } - - parent = elem.parentNode; - - if ( parent && (parent[ expando ] !== doneName || !elem.sizset) ) { - for ( node = parent.firstChild; node; node = node.nextSibling ) { - if ( node.nodeType === 1 ) { - node.sizset = ++count; - if ( node === elem ) { - break; - } - } - } - - parent[ expando ] = doneName; - } - - diff = elem.sizset - last; - - if ( first === 0 ) { - return diff === 0; - - } else { - return ( diff % first === 0 && diff / first >= 0 ); - } - }; - } - - return function( elem ) { - var node = elem; - - switch ( type ) { - case "only": - case "first": - while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - if ( type === "first" ) { - return true; - } - - node = elem; - - /* falls through */ - case "last": - while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - return true; - } - }; - }, - - "PSEUDO": function( pseudo, argument, context, xml ) { - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - var fn = Expr.pseudos[ pseudo ] || Expr.pseudos[ pseudo.toLowerCase() ]; - - if ( !fn ) { - Sizzle.error( "unsupported pseudo: " + pseudo ); - } - - // The user may set fn.sizzleFilter to indicate - // that arguments are needed to create the filter function - // just as Sizzle does - if ( !fn.sizzleFilter ) { - return fn; - } - - return fn( argument, context, xml ); - } - }, - - pseudos: { - "not": markFunction(function( selector, context, xml ) { - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var matcher = compile( selector.replace( rtrim, "$1" ), context, xml ); - return function( elem ) { - return !matcher( elem ); - }; - }), - - "enabled": function( elem ) { - return elem.disabled === false; - }, - - "disabled": function( elem ) { - return elem.disabled === true; - }, - - "checked": function( elem ) { - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); - }, - - "selected": function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - "parent": function( elem ) { - return !Expr.pseudos["empty"]( elem ); - }, - - "empty": function( elem ) { - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), - // not comment, processing instructions, or others - // Thanks to Diego Perini for the nodeName shortcut - // Greater than "@" means alpha characters (specifically not starting with "#" or "?") - var nodeType; - elem = elem.firstChild; - while ( elem ) { - if ( elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) { - return false; - } - elem = elem.nextSibling; - } - return true; - }, - - "contains": markFunction(function( text ) { - return function( elem ) { - return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; - }; - }), - - "has": markFunction(function( selector ) { - return function( elem ) { - return Sizzle( selector, elem ).length > 0; - }; - }), - - "header": function( elem ) { - return rheader.test( elem.nodeName ); - }, - - "text": function( elem ) { - var type, attr; - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) - // use getAttribute instead to test this case - return elem.nodeName.toLowerCase() === "input" && - (type = elem.type) === "text" && - ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type ); - }, - - // Input types - "radio": createInputFunction("radio"), - "checkbox": createInputFunction("checkbox"), - "file": createInputFunction("file"), - "password": createInputFunction("password"), - "image": createInputFunction("image"), - - "submit": createButtonFunction("submit"), - "reset": createButtonFunction("reset"), - - "button": function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; - }, - - "input": function( elem ) { - return rinputs.test( elem.nodeName ); - }, - - "focus": function( elem ) { - var doc = elem.ownerDocument; - return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href); - }, - - "active": function( elem ) { - return elem === elem.ownerDocument.activeElement; - } - }, - - setFilters: { - "first": function( elements, argument, not ) { - return not ? elements.slice( 1 ) : [ elements[0] ]; - }, - - "last": function( elements, argument, not ) { - var elem = elements.pop(); - return not ? elements : [ elem ]; - }, - - "even": function( elements, argument, not ) { - var results = [], - i = not ? 1 : 0, - len = elements.length; - for ( ; i < len; i = i + 2 ) { - results.push( elements[i] ); - } - return results; - }, - - "odd": function( elements, argument, not ) { - var results = [], - i = not ? 0 : 1, - len = elements.length; - for ( ; i < len; i = i + 2 ) { - results.push( elements[i] ); - } - return results; - }, - - "lt": function( elements, argument, not ) { - return not ? elements.slice( +argument ) : elements.slice( 0, +argument ); - }, - - "gt": function( elements, argument, not ) { - return not ? elements.slice( 0, +argument + 1 ) : elements.slice( +argument + 1 ); - }, - - "eq": function( elements, argument, not ) { - var elem = elements.splice( +argument, 1 ); - return not ? elements : elem; - } - } -}; - -// Deprecated -Expr.setFilters["nth"] = Expr.setFilters["eq"]; - -// Back-compat -Expr.filters = Expr.pseudos; - -// IE6/7 return a modified href -if ( !assertHrefNotNormalized ) { - Expr.attrHandle = { - "href": function( elem ) { - return elem.getAttribute( "href", 2 ); - }, - "type": function( elem ) { - return elem.getAttribute("type"); - } - }; -} - -// Add getElementsByName if usable -if ( assertUsableName ) { - Expr.order.push("NAME"); - Expr.find["NAME"] = function( name, context ) { - if ( typeof context.getElementsByName !== strundefined ) { - return context.getElementsByName( name ); - } - }; -} - -// Add getElementsByClassName if usable -if ( assertUsableClassName ) { - Expr.order.splice( 1, 0, "CLASS" ); - Expr.find["CLASS"] = function( className, context, xml ) { - if ( typeof context.getElementsByClassName !== strundefined && !xml ) { - return context.getElementsByClassName( className ); - } - }; -} - -// If slice is not available, provide a backup -try { - slice.call( docElem.childNodes, 0 )[0].nodeType; -} catch ( e ) { - slice = function( i ) { - var elem, results = []; - for ( ; (elem = this[i]); i++ ) { - results.push( elem ); - } - return results; - }; -} - -var isXML = Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = elem && (elem.ownerDocument || elem).documentElement; - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -// Element contains another -var contains = Sizzle.contains = docElem.compareDocumentPosition ? - function( a, b ) { - return !!( a.compareDocumentPosition( b ) & 16 ); - } : - docElem.contains ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) ); - } : - function( a, b ) { - while ( (b = b.parentNode) ) { - if ( b === a ) { - return true; - } - } - return false; - }; - -/** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -var getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if ( nodeType ) { - if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - // Use textContent for elements - // innerText usage removed for consistency of new lines (see #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - // Do not include comment or processing instruction nodes - } else { - - // If no nodeType, this is expected to be an array - for ( ; (node = elem[i]); i++ ) { - // Do not traverse comment nodes - ret += getText( node ); - } - } - return ret; -}; - -Sizzle.attr = function( elem, name ) { - var attr, - xml = isXML( elem ); - - if ( !xml ) { - name = name.toLowerCase(); - } - if ( Expr.attrHandle[ name ] ) { - return Expr.attrHandle[ name ]( elem ); - } - if ( assertAttributes || xml ) { - return elem.getAttribute( name ); - } - attr = elem.getAttributeNode( name ); - return attr ? - typeof elem[ name ] === "boolean" ? - elem[ name ] ? name : null : - attr.specified ? attr.value : null : - null; -}; - -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; - -// Check if the JavaScript engine is using some sort of -// optimization where it does not always call our comparision -// function. If that is the case, discard the hasDuplicate value. -// Thus far that includes Google Chrome. -[0, 0].sort(function() { - return (baseHasDuplicate = 0); -}); - - -if ( docElem.compareDocumentPosition ) { - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - return ( !a.compareDocumentPosition || !b.compareDocumentPosition ? - a.compareDocumentPosition : - a.compareDocumentPosition(b) & 4 - ) ? -1 : 1; - }; - -} else { - sortOrder = function( a, b ) { - // The nodes are identical, we can exit early - if ( a === b ) { - hasDuplicate = true; - return 0; - - // Fallback to using sourceIndex (in IE) if it's available on both nodes - } else if ( a.sourceIndex && b.sourceIndex ) { - return a.sourceIndex - b.sourceIndex; - } - - var al, bl, - ap = [], - bp = [], - aup = a.parentNode, - bup = b.parentNode, - cur = aup; - - // If the nodes are siblings (or identical) we can do a quick check - if ( aup === bup ) { - return siblingCheck( a, b ); - - // If no parents were found then the nodes are disconnected - } else if ( !aup ) { - return -1; - - } else if ( !bup ) { - return 1; - } - - // Otherwise they're somewhere else in the tree so we need - // to build up a full list of the parentNodes for comparison - while ( cur ) { - ap.unshift( cur ); - cur = cur.parentNode; - } - - cur = bup; - - while ( cur ) { - bp.unshift( cur ); - cur = cur.parentNode; - } - - al = ap.length; - bl = bp.length; - - // Start walking down the tree looking for a discrepancy - for ( var i = 0; i < al && i < bl; i++ ) { - if ( ap[i] !== bp[i] ) { - return siblingCheck( ap[i], bp[i] ); - } - } - - // We ended someplace up the tree so do a sibling check - return i === al ? - siblingCheck( a, bp[i], -1 ) : - siblingCheck( ap[i], b, 1 ); - }; - - siblingCheck = function( a, b, ret ) { - if ( a === b ) { - return ret; - } - - var cur = a.nextSibling; - - while ( cur ) { - if ( cur === b ) { - return -1; - } - - cur = cur.nextSibling; - } - - return 1; - }; -} - -// Document sorting and removing duplicates -Sizzle.uniqueSort = function( results ) { - var elem, - i = 1; - - if ( sortOrder ) { - hasDuplicate = baseHasDuplicate; - results.sort( sortOrder ); - - if ( hasDuplicate ) { - for ( ; (elem = results[i]); i++ ) { - if ( elem === results[ i - 1 ] ) { - results.splice( i--, 1 ); - } - } - } - } - - return results; -}; - -function multipleContexts( selector, contexts, results, seed ) { - var i = 0, - len = contexts.length; - for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results, seed ); - } -} - -function handlePOSGroup( selector, posfilter, argument, contexts, seed, not ) { - var results, - fn = Expr.setFilters[ posfilter.toLowerCase() ]; - - if ( !fn ) { - Sizzle.error( posfilter ); - } - - if ( selector || !(results = seed) ) { - multipleContexts( selector || "*", contexts, (results = []), seed ); - } - - return results.length > 0 ? fn( results, argument, not ) : []; -} - -function handlePOS( selector, context, results, seed, groups ) { - var match, not, anchor, ret, elements, currentContexts, part, lastIndex, - i = 0, - len = groups.length, - rpos = matchExpr["POS"], - // This is generated here in case matchExpr["POS"] is extended - rposgroups = new RegExp( "^" + rpos.source + "(?!" + whitespace + ")", "i" ), - // This is for making sure non-participating - // matching groups are represented cross-browser (IE6-8) - setUndefined = function() { - var i = 1, - len = arguments.length - 2; - for ( ; i < len; i++ ) { - if ( arguments[i] === undefined ) { - match[i] = undefined; - } - } - }; - - for ( ; i < len; i++ ) { - // Reset regex index to 0 - rpos.exec(""); - selector = groups[i]; - ret = []; - anchor = 0; - elements = seed; - while ( (match = rpos.exec( selector )) ) { - lastIndex = rpos.lastIndex = match.index + match[0].length; - if ( lastIndex > anchor ) { - part = selector.slice( anchor, match.index ); - anchor = lastIndex; - currentContexts = [ context ]; - - if ( rcombinators.test(part) ) { - if ( elements ) { - currentContexts = elements; - } - elements = seed; - } - - if ( (not = rendsWithNot.test( part )) ) { - part = part.slice( 0, -5 ).replace( rcombinators, "$&*" ); - } - - if ( match.length > 1 ) { - match[0].replace( rposgroups, setUndefined ); - } - elements = handlePOSGroup( part, match[1], match[2], currentContexts, elements, not ); - } - } - - if ( elements ) { - ret = ret.concat( elements ); - - if ( (part = selector.slice( anchor )) && part !== ")" ) { - if ( rcombinators.test(part) ) { - multipleContexts( part, ret, results, seed ); - } else { - Sizzle( part, context, results, seed ? seed.concat(elements) : elements ); - } - } else { - push.apply( results, ret ); - } - } else { - Sizzle( selector, context, results, seed ); - } - } - - // Do not sort if this is a single filter - return len === 1 ? results : Sizzle.uniqueSort( results ); -} - -function tokenize( selector, context, xml ) { - var tokens, soFar, type, - groups = [], - i = 0, - - // Catch obvious selector issues: terminal ")"; nonempty fallback match - // rselector never fails to match *something* - match = rselector.exec( selector ), - matched = !match.pop() && !match.pop(), - selectorGroups = matched && selector.match( rgroups ) || [""], - - preFilters = Expr.preFilter, - filters = Expr.filter, - checkContext = !xml && context !== document; - - for ( ; (soFar = selectorGroups[i]) != null && matched; i++ ) { - groups.push( tokens = [] ); - - // Need to make sure we're within a narrower context if necessary - // Adding a descendant combinator will generate what is needed - if ( checkContext ) { - soFar = " " + soFar; - } - - while ( soFar ) { - matched = false; - - // Combinators - if ( (match = rcombinators.exec( soFar )) ) { - soFar = soFar.slice( match[0].length ); - - // Cast descendant combinators to space - matched = tokens.push({ part: match.pop().replace( rtrim, " " ), captures: match }); - } - - // Filters - for ( type in filters ) { - if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || - (match = preFilters[ type ]( match, context, xml )) ) ) { - - soFar = soFar.slice( match.shift().length ); - matched = tokens.push({ part: type, captures: match }); - } - } - - if ( !matched ) { - break; - } - } - } - - if ( !matched ) { - Sizzle.error( selector ); - } - - return groups; -} - -function addCombinator( matcher, combinator, context ) { - var dir = combinator.dir, - doneName = done++; - - if ( !matcher ) { - // If there is no matcher to check, check against the context - matcher = function( elem ) { - return elem === context; - }; - } - return combinator.first ? - function( elem, context ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 ) { - return matcher( elem, context ) && elem; - } - } - } : - function( elem, context ) { - var cache, - dirkey = doneName + "." + dirruns, - cachedkey = dirkey + "." + cachedruns; - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 ) { - if ( (cache = elem[ expando ]) === cachedkey ) { - return elem.sizset; - } else if ( typeof cache === "string" && cache.indexOf(dirkey) === 0 ) { - if ( elem.sizset ) { - return elem; - } - } else { - elem[ expando ] = cachedkey; - if ( matcher( elem, context ) ) { - elem.sizset = true; - return elem; - } - elem.sizset = false; - } - } - } - }; -} - -function addMatcher( higher, deeper ) { - return higher ? - function( elem, context ) { - var result = deeper( elem, context ); - return result && higher( result === true ? elem : result, context ); - } : - deeper; -} - -// ["TAG", ">", "ID", " ", "CLASS"] -function matcherFromTokens( tokens, context, xml ) { - var token, matcher, - i = 0; - - for ( ; (token = tokens[i]); i++ ) { - if ( Expr.relative[ token.part ] ) { - matcher = addCombinator( matcher, Expr.relative[ token.part ], context ); - } else { - token.captures.push( context, xml ); - matcher = addMatcher( matcher, Expr.filter[ token.part ].apply( null, token.captures ) ); - } - } - - return matcher; -} - -function matcherFromGroupMatchers( matchers ) { - return function( elem, context ) { - var matcher, - j = 0; - for ( ; (matcher = matchers[j]); j++ ) { - if ( matcher(elem, context) ) { - return true; - } - } - return false; - }; -} - -var compile = Sizzle.compile = function( selector, context, xml ) { - var tokens, group, i, - cached = compilerCache[ selector ]; - - // Return a cached group function if already generated (context dependent) - if ( cached && cached.context === context ) { - return cached; - } - - // Generate a function of recursive functions that can be used to check each element - group = tokenize( selector, context, xml ); - for ( i = 0; (tokens = group[i]); i++ ) { - group[i] = matcherFromTokens( tokens, context, xml ); - } - - // Cache the compiled function - cached = compilerCache[ selector ] = matcherFromGroupMatchers( group ); - cached.context = context; - cached.runs = cached.dirruns = 0; - cachedSelectors.push( selector ); - // Ensure only the most recent are cached - if ( cachedSelectors.length > Expr.cacheLength ) { - delete compilerCache[ cachedSelectors.shift() ]; - } - return cached; -}; - -Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); -}; - -Sizzle.matchesSelector = function( elem, expr ) { - return Sizzle( expr, null, null, [ elem ] ).length > 0; -}; - -var select = function( selector, context, results, seed, xml ) { - // Remove excessive whitespace - selector = selector.replace( rtrim, "$1" ); - var elements, matcher, i, len, elem, token, - type, findContext, notTokens, - match = selector.match( rgroups ), - tokens = selector.match( rtokens ), - contextNodeType = context.nodeType; - - // POS handling - if ( matchExpr["POS"].test(selector) ) { - return handlePOS( selector, context, results, seed, match ); - } - - if ( seed ) { - elements = slice.call( seed, 0 ); - - // To maintain document order, only narrow the - // set if there is one group - } else if ( match && match.length === 1 ) { - - // Take a shortcut and set the context if the root selector is an ID - if ( tokens.length > 1 && contextNodeType === 9 && !xml && - (match = matchExpr["ID"].exec( tokens[0] )) ) { - - context = Expr.find["ID"]( match[1], context, xml )[0]; - if ( !context ) { - return results; - } - - selector = selector.slice( tokens.shift().length ); - } - - findContext = ( (match = rsibling.exec( tokens[0] )) && !match.index && context.parentNode ) || context; - - // Get the last token, excluding :not - notTokens = tokens.pop(); - token = notTokens.split(":not")[0]; - - for ( i = 0, len = Expr.order.length; i < len; i++ ) { - type = Expr.order[i]; - - if ( (match = matchExpr[ type ].exec( token )) ) { - elements = Expr.find[ type ]( (match[1] || "").replace( rbackslash, "" ), findContext, xml ); - - if ( elements == null ) { - continue; - } - - if ( token === notTokens ) { - selector = selector.slice( 0, selector.length - notTokens.length ) + - token.replace( matchExpr[ type ], "" ); - - if ( !selector ) { - push.apply( results, slice.call(elements, 0) ); - } - } - break; - } - } - } - - // Only loop over the given elements once - // If selector is empty, we're already done - if ( selector ) { - matcher = compile( selector, context, xml ); - dirruns = matcher.dirruns++; - - if ( elements == null ) { - elements = Expr.find["TAG"]( "*", (rsibling.test( selector ) && context.parentNode) || context ); - } - for ( i = 0; (elem = elements[i]); i++ ) { - cachedruns = matcher.runs++; - if ( matcher(elem, context) ) { - results.push( elem ); - } - } - } - - return results; -}; - -if ( document.querySelectorAll ) { - (function() { - var disconnectedMatch, - oldSelect = select, - rescape = /'|\\/g, - rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g, - rbuggyQSA = [], - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - // A support test would require too much code (would include document ready) - // just skip matchesSelector for :active - rbuggyMatches = [":active"], - matches = docElem.matchesSelector || - docElem.mozMatchesSelector || - docElem.webkitMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector; - - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert(function( div ) { - div.innerHTML = ""; - - // IE8 - Some boolean attributes are not treated correctly - if ( !div.querySelectorAll("[selected]").length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" ); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here (do not put tests after this one) - if ( !div.querySelectorAll(":checked").length ) { - rbuggyQSA.push(":checked"); - } - }); - - assert(function( div ) { - - // Opera 10-12/IE9 - ^= $= *= and empty values - // Should not select anything - div.innerHTML = "

"; - if ( div.querySelectorAll("[test^='']").length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" ); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here (do not put tests after this one) - div.innerHTML = ""; - if ( !div.querySelectorAll(":enabled").length ) { - rbuggyQSA.push(":enabled", ":disabled"); - } - }); - - rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); - - select = function( selector, context, results, seed, xml ) { - // Only use querySelectorAll when not filtering, - // when this is not xml, - // and when no QSA bugs apply - if ( !seed && !xml && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { - if ( context.nodeType === 9 ) { - try { - push.apply( results, slice.call(context.querySelectorAll( selector ), 0) ); - return results; - } catch(qsaError) {} - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - var old = context.getAttribute("id"), - nid = old || expando, - newContext = rsibling.test( selector ) && context.parentNode || context; - - if ( old ) { - nid = nid.replace( rescape, "\\$&" ); - } else { - context.setAttribute( "id", nid ); - } - - try { - push.apply( results, slice.call( newContext.querySelectorAll( - selector.replace( rgroups, "[id='" + nid + "'] $&" ) - ), 0 ) ); - return results; - } catch(qsaError) { - } finally { - if ( !old ) { - context.removeAttribute("id"); - } - } - } - } - - return oldSelect( selector, context, results, seed, xml ); - }; - - if ( matches ) { - assert(function( div ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - disconnectedMatch = matches.call( div, "div" ); - - // This should fail with an exception - // Gecko does not error, returns false instead - try { - matches.call( div, "[test!='']:sizzle" ); - rbuggyMatches.push( Expr.match.PSEUDO ); - } catch ( e ) {} - }); - - // rbuggyMatches always contains :active, so no need for a length check - rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join("|") ); - - Sizzle.matchesSelector = function( elem, expr ) { - // Make sure that attribute selectors are quoted - expr = expr.replace( rattributeQuotes, "='$1']" ); - - // rbuggyMatches always contains :active, so no need for an existence check - if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && (!rbuggyQSA || !rbuggyQSA.test( expr )) ) { - try { - var ret = matches.call( elem, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { - return ret; - } - } catch(e) {} - } - - return Sizzle( expr, null, null, [ elem ] ).length > 0; - }; - } - })(); -} - +/*! + * Sizzle CSS Selector Engine + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license + * http://sizzlejs.com/ + */ +(function( window, undefined ) { + +var cachedruns, + dirruns, + sortOrder, + siblingCheck, + assertGetIdNotName, + + document = window.document, + docElem = document.documentElement, + + strundefined = "undefined", + hasDuplicate = false, + baseHasDuplicate = true, + done = 0, + slice = [].slice, + push = [].push, + + expando = ( "sizcache" + Math.random() ).replace( ".", "" ), + + // Regex + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors) + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors + operators = "([*^$|!~]?=)", + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + + "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", + pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|((?:[^,]|\\\\,|(?:,(?=[^\\[]*\\]))|(?:,(?=[^\\(]*\\))))*))\\)|)", + pos = ":(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\)|)(?=[^-]|$)", + combinators = whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*", + groups = "(?=[^\\x20\\t\\r\\n\\f])(?:\\\\.|" + attributes + "|" + pseudos.replace( 2, 7 ) + "|[^\\\\(),])+", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcombinators = new RegExp( "^" + combinators ), + + // All simple (non-comma) selectors, excluding insignifant trailing whitespace + rgroups = new RegExp( groups + "?(?=" + whitespace + "*,|$)", "g" ), + + // A selector, or everything after leading whitespace + // Optionally followed in either case by a ")" for terminating sub-selectors + rselector = new RegExp( "^(?:(?!,)(?:(?:^|,)" + whitespace + "*" + groups + ")*?|" + whitespace + "*(.*?))(\\)|$)" ), + + // All combinators and selector components (attribute test, tag, pseudo, etc.), the latter appearing together when consecutive + rtokens = new RegExp( groups.slice( 19, -6 ) + "\\x20\\t\\r\\n\\f>+~])+|" + combinators, "g" ), + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/, + + rsibling = /[\x20\t\r\n\f]*[+~]/, + rendsWithNot = /:not\($/, + + rheader = /h\d/i, + rinputs = /input|select|textarea|button/i, + + rbackslash = /\\(?!\\)/g, + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "[-", "[-\\*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|nth|last|first)-child(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "POS": new RegExp( pos, "ig" ), + // For use in libraries implementing .is() + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|" + pos, "i" ) + }, + + classCache = {}, + cachedClasses = [], + compilerCache = {}, + cachedSelectors = [], + + // Mark a function for use in filtering + markFunction = function( fn ) { + fn.sizzleFilter = true; + return fn; + }, + + // Returns a function to use in pseudos for input types + createInputFunction = function( type ) { + return function( elem ) { + // Check the input's nodeName and type + return elem.nodeName.toLowerCase() === "input" && elem.type === type; + }; + }, + + // Returns a function to use in pseudos for buttons + createButtonFunction = function( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; + }, + + // Used for testing something on an element + assert = function( fn ) { + var pass = false, + div = document.createElement("div"); + try { + pass = fn( div ); + } catch (e) {} + // release memory in IE + div = null; + return pass; + }, + + // Check if attributes should be retrieved by attribute nodes + assertAttributes = assert(function( div ) { + div.innerHTML = ""; + var type = typeof div.lastChild.getAttribute("multiple"); + // IE8 returns a string for some attributes even when not present + return type !== "boolean" && type !== "string"; + }), + + // Check if getElementById returns elements by name + // Check if getElementsByName privileges form controls or returns elements by ID + assertUsableName = assert(function( div ) { + // Inject content + div.id = expando + 0; + div.innerHTML = "
"; + docElem.insertBefore( div, docElem.firstChild ); + + // Test + var pass = document.getElementsByName && + // buggy browsers will return fewer than the correct 2 + document.getElementsByName( expando ).length === + // buggy browsers will return more than the correct 0 + 2 + document.getElementsByName( expando + 0 ).length; + assertGetIdNotName = !document.getElementById( expando ); + + // Cleanup + docElem.removeChild( div ); + + return pass; + }), + + // Check if the browser returns only elements + // when doing getElementsByTagName("*") + assertTagNameNoComments = assert(function( div ) { + div.appendChild( document.createComment("") ); + return div.getElementsByTagName("*").length === 0; + }), + + // Check if getAttribute returns normalized href attributes + assertHrefNotNormalized = assert(function( div ) { + div.innerHTML = ""; + return div.firstChild && typeof div.firstChild.getAttribute !== strundefined && + div.firstChild.getAttribute("href") === "#"; + }), + + // Check if getElementsByClassName can be trusted + assertUsableClassName = assert(function( div ) { + // Opera can't find a second classname (in 9.6) + div.innerHTML = ""; + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return false; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + return div.getElementsByClassName("e").length !== 1; + }); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + var match, elem, xml, m, + nodeType = context.nodeType; + + if ( nodeType !== 1 && nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + xml = isXML( context ); + + if ( !xml && !seed ) { + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) { + push.apply( results, slice.call(context.getElementsByClassName( m ), 0) ); + return results; + } + } + } + + // All others + return select( selector, context, results, seed, xml ); +}; + +var Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + match: matchExpr, + + order: [ "ID", "TAG" ], + + attrHandle: {}, + + createPseudo: markFunction, + + find: { + "ID": assertGetIdNotName ? + function( id, context, xml ) { + if ( typeof context.getElementById !== strundefined && !xml ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + } : + function( id, context, xml ) { + if ( typeof context.getElementById !== strundefined && !xml ) { + var m = context.getElementById( id ); + + return m ? + m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ? + [m] : + undefined : + []; + } + }, + + "TAG": assertTagNameNoComments ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + var elem, + tmp = [], + i = 0; + + for ( ; (elem = results[i]); i++ ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + } + }, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( rbackslash, "" ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[4] || match[5] || "" ).replace( rbackslash, "" ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr.CHILD + 1 type (only|nth|...) + 2 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 3 xn-component of xn+y argument ([+-]?\d*n|) + 4 sign of xn-component + 5 x of xn-component + 6 sign of y-component + 7 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1] === "nth" ) { + // nth-child requires argument + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === "even" || match[2] === "odd" ) ); + match[4] = +( ( match[6] + match[7] ) || match[2] === "odd" ); + + // other types prohibit arguments + } else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var argument, + unquoted = match[4]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Relinquish our claim on characters in `unquoted` from a closing parenthesis on + if ( unquoted && (argument = rselector.exec( unquoted )) && argument.pop() ) { + + match[0] = match[0].slice( 0, argument[0].length - unquoted.length - 1 ); + unquoted = argument[0].slice( 0, -1 ); + } + + // Quoted or unquoted, we have the full argument + // Return only captures needed by the pseudo filter method (type and argument) + match.splice( 2, 3, unquoted || match[3] ); + return match; + } + }, + + filter: { + "ID": assertGetIdNotName ? + function( id ) { + id = id.replace( rbackslash, "" ); + return function( elem ) { + return elem.getAttribute("id") === id; + }; + } : + function( id ) { + id = id.replace( rbackslash, "" ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === id; + }; + }, + + "TAG": function( nodeName ) { + if ( nodeName === "*" ) { + return function() { return true; }; + } + nodeName = nodeName.replace( rbackslash, "" ).toLowerCase(); + + return function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className ]; + if ( !pattern ) { + pattern = classCache[ className ] = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" ); + cachedClasses.push( className ); + // Avoid too large of a cache + if ( cachedClasses.length > Expr.cacheLength ) { + delete classCache[ cachedClasses.shift() ]; + } + } + return function( elem ) { + return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" ); + }; + }, + + "ATTR": function( name, operator, check ) { + if ( !operator ) { + return function( elem ) { + return Sizzle.attr( elem, name ) != null; + }; + } + + return function( elem ) { + var result = Sizzle.attr( elem, name ), + value = result + ""; + + if ( result == null ) { + return operator === "!="; + } + + switch ( operator ) { + case "=": + return value === check; + case "!=": + return value !== check; + case "^=": + return check && value.indexOf( check ) === 0; + case "*=": + return check && value.indexOf( check ) > -1; + case "$=": + return check && value.substr( value.length - check.length ) === check; + case "~=": + return ( " " + value + " " ).indexOf( check ) > -1; + case "|=": + return value === check || value.substr( 0, check.length + 1 ) === check + "-"; + } + }; + }, + + "CHILD": function( type, argument, first, last ) { + + if ( type === "nth" ) { + var doneName = done++; + + return function( elem ) { + var parent, diff, + count = 0, + node = elem; + + if ( first === 1 && last === 0 ) { + return true; + } + + parent = elem.parentNode; + + if ( parent && (parent[ expando ] !== doneName || !elem.sizset) ) { + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.sizset = ++count; + if ( node === elem ) { + break; + } + } + } + + parent[ expando ] = doneName; + } + + diff = elem.sizset - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + }; + } + + return function( elem ) { + var node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + /* falls through */ + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + } + }; + }, + + "PSEUDO": function( pseudo, argument, context, xml ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + var fn = Expr.pseudos[ pseudo ] || Expr.pseudos[ pseudo.toLowerCase() ]; + + if ( !fn ) { + Sizzle.error( "unsupported pseudo: " + pseudo ); + } + + // The user may set fn.sizzleFilter to indicate + // that arguments are needed to create the filter function + // just as Sizzle does + if ( !fn.sizzleFilter ) { + return fn; + } + + return fn( argument, context, xml ); + } + }, + + pseudos: { + "not": markFunction(function( selector, context, xml ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var matcher = compile( selector.replace( rtrim, "$1" ), context, xml ); + return function( elem ) { + return !matcher( elem ); + }; + }), + + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), + // not comment, processing instructions, or others + // Thanks to Diego Perini for the nodeName shortcut + // Greater than "@" means alpha characters (specifically not starting with "#" or "?") + var nodeType; + elem = elem.firstChild; + while ( elem ) { + if ( elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) { + return false; + } + elem = elem.nextSibling; + } + return true; + }, + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "text": function( elem ) { + var type, attr; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && + (type = elem.type) === "text" && + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type ); + }, + + // Input types + "radio": createInputFunction("radio"), + "checkbox": createInputFunction("checkbox"), + "file": createInputFunction("file"), + "password": createInputFunction("password"), + "image": createInputFunction("image"), + + "submit": createButtonFunction("submit"), + "reset": createButtonFunction("reset"), + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "focus": function( elem ) { + var doc = elem.ownerDocument; + return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href); + }, + + "active": function( elem ) { + return elem === elem.ownerDocument.activeElement; + } + }, + + setFilters: { + "first": function( elements, argument, not ) { + return not ? elements.slice( 1 ) : [ elements[0] ]; + }, + + "last": function( elements, argument, not ) { + var elem = elements.pop(); + return not ? elements : [ elem ]; + }, + + "even": function( elements, argument, not ) { + var results = [], + i = not ? 1 : 0, + len = elements.length; + for ( ; i < len; i = i + 2 ) { + results.push( elements[i] ); + } + return results; + }, + + "odd": function( elements, argument, not ) { + var results = [], + i = not ? 0 : 1, + len = elements.length; + for ( ; i < len; i = i + 2 ) { + results.push( elements[i] ); + } + return results; + }, + + "lt": function( elements, argument, not ) { + return not ? elements.slice( +argument ) : elements.slice( 0, +argument ); + }, + + "gt": function( elements, argument, not ) { + return not ? elements.slice( 0, +argument + 1 ) : elements.slice( +argument + 1 ); + }, + + "eq": function( elements, argument, not ) { + var elem = elements.splice( +argument, 1 ); + return not ? elements : elem; + } + } +}; + +// Deprecated +Expr.setFilters["nth"] = Expr.setFilters["eq"]; + +// Back-compat +Expr.filters = Expr.pseudos; + +// IE6/7 return a modified href +if ( !assertHrefNotNormalized ) { + Expr.attrHandle = { + "href": function( elem ) { + return elem.getAttribute( "href", 2 ); + }, + "type": function( elem ) { + return elem.getAttribute("type"); + } + }; +} + +// Add getElementsByName if usable +if ( assertUsableName ) { + Expr.order.push("NAME"); + Expr.find["NAME"] = function( name, context ) { + if ( typeof context.getElementsByName !== strundefined ) { + return context.getElementsByName( name ); + } + }; +} + +// Add getElementsByClassName if usable +if ( assertUsableClassName ) { + Expr.order.splice( 1, 0, "CLASS" ); + Expr.find["CLASS"] = function( className, context, xml ) { + if ( typeof context.getElementsByClassName !== strundefined && !xml ) { + return context.getElementsByClassName( className ); + } + }; +} + +// If slice is not available, provide a backup +try { + slice.call( docElem.childNodes, 0 )[0].nodeType; +} catch ( e ) { + slice = function( i ) { + var elem, results = []; + for ( ; (elem = this[i]); i++ ) { + results.push( elem ); + } + return results; + }; +} + +var isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +// Element contains another +var contains = Sizzle.contains = docElem.compareDocumentPosition ? + function( a, b ) { + return !!( a.compareDocumentPosition( b ) & 16 ); + } : + docElem.contains ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) ); + } : + function( a, b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + return false; + }; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +var getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( nodeType ) { + if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (see #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + } else { + + // If no nodeType, this is expected to be an array + for ( ; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } + return ret; +}; + +Sizzle.attr = function( elem, name ) { + var attr, + xml = isXML( elem ); + + if ( !xml ) { + name = name.toLowerCase(); + } + if ( Expr.attrHandle[ name ] ) { + return Expr.attrHandle[ name ]( elem ); + } + if ( assertAttributes || xml ) { + return elem.getAttribute( name ); + } + attr = elem.getAttributeNode( name ); + return attr ? + typeof elem[ name ] === "boolean" ? + elem[ name ] ? name : null : + attr.specified ? attr.value : null : + null; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +// Check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + return (baseHasDuplicate = 0); +}); + + +if ( docElem.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + return ( !a.compareDocumentPosition || !b.compareDocumentPosition ? + a.compareDocumentPosition : + a.compareDocumentPosition(b) & 4 + ) ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Document sorting and removing duplicates +Sizzle.uniqueSort = function( results ) { + var elem, + i = 1; + + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( ; (elem = results[i]); i++ ) { + if ( elem === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +function multipleContexts( selector, contexts, results, seed ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results, seed ); + } +} + +function handlePOSGroup( selector, posfilter, argument, contexts, seed, not ) { + var results, + fn = Expr.setFilters[ posfilter.toLowerCase() ]; + + if ( !fn ) { + Sizzle.error( posfilter ); + } + + if ( selector || !(results = seed) ) { + multipleContexts( selector || "*", contexts, (results = []), seed ); + } + + return results.length > 0 ? fn( results, argument, not ) : []; +} + +function handlePOS( selector, context, results, seed, groups ) { + var match, not, anchor, ret, elements, currentContexts, part, lastIndex, + i = 0, + len = groups.length, + rpos = matchExpr["POS"], + // This is generated here in case matchExpr["POS"] is extended + rposgroups = new RegExp( "^" + rpos.source + "(?!" + whitespace + ")", "i" ), + // This is for making sure non-participating + // matching groups are represented cross-browser (IE6-8) + setUndefined = function() { + var i = 1, + len = arguments.length - 2; + for ( ; i < len; i++ ) { + if ( arguments[i] === undefined ) { + match[i] = undefined; + } + } + }; + + for ( ; i < len; i++ ) { + // Reset regex index to 0 + rpos.exec(""); + selector = groups[i]; + ret = []; + anchor = 0; + elements = seed; + while ( (match = rpos.exec( selector )) ) { + lastIndex = rpos.lastIndex = match.index + match[0].length; + if ( lastIndex > anchor ) { + part = selector.slice( anchor, match.index ); + anchor = lastIndex; + currentContexts = [ context ]; + + if ( rcombinators.test(part) ) { + if ( elements ) { + currentContexts = elements; + } + elements = seed; + } + + if ( (not = rendsWithNot.test( part )) ) { + part = part.slice( 0, -5 ).replace( rcombinators, "$&*" ); + } + + if ( match.length > 1 ) { + match[0].replace( rposgroups, setUndefined ); + } + elements = handlePOSGroup( part, match[1], match[2], currentContexts, elements, not ); + } + } + + if ( elements ) { + ret = ret.concat( elements ); + + if ( (part = selector.slice( anchor )) && part !== ")" ) { + if ( rcombinators.test(part) ) { + multipleContexts( part, ret, results, seed ); + } else { + Sizzle( part, context, results, seed ? seed.concat(elements) : elements ); + } + } else { + push.apply( results, ret ); + } + } else { + Sizzle( selector, context, results, seed ); + } + } + + // Do not sort if this is a single filter + return len === 1 ? results : Sizzle.uniqueSort( results ); +} + +function tokenize( selector, context, xml ) { + var tokens, soFar, type, + groups = [], + i = 0, + + // Catch obvious selector issues: terminal ")"; nonempty fallback match + // rselector never fails to match *something* + match = rselector.exec( selector ), + matched = !match.pop() && !match.pop(), + selectorGroups = matched && selector.match( rgroups ) || [""], + + preFilters = Expr.preFilter, + filters = Expr.filter, + checkContext = !xml && context !== document; + + for ( ; (soFar = selectorGroups[i]) != null && matched; i++ ) { + groups.push( tokens = [] ); + + // Need to make sure we're within a narrower context if necessary + // Adding a descendant combinator will generate what is needed + if ( checkContext ) { + soFar = " " + soFar; + } + + while ( soFar ) { + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + soFar = soFar.slice( match[0].length ); + + // Cast descendant combinators to space + matched = tokens.push({ part: match.pop().replace( rtrim, " " ), captures: match }); + } + + // Filters + for ( type in filters ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match, context, xml )) ) ) { + + soFar = soFar.slice( match.shift().length ); + matched = tokens.push({ part: type, captures: match }); + } + } + + if ( !matched ) { + break; + } + } + } + + if ( !matched ) { + Sizzle.error( selector ); + } + + return groups; +} + +function addCombinator( matcher, combinator, context ) { + var dir = combinator.dir, + doneName = done++; + + if ( !matcher ) { + // If there is no matcher to check, check against the context + matcher = function( elem ) { + return elem === context; + }; + } + return combinator.first ? + function( elem, context ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 ) { + return matcher( elem, context ) && elem; + } + } + } : + function( elem, context ) { + var cache, + dirkey = doneName + "." + dirruns, + cachedkey = dirkey + "." + cachedruns; + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 ) { + if ( (cache = elem[ expando ]) === cachedkey ) { + return elem.sizset; + } else if ( typeof cache === "string" && cache.indexOf(dirkey) === 0 ) { + if ( elem.sizset ) { + return elem; + } + } else { + elem[ expando ] = cachedkey; + if ( matcher( elem, context ) ) { + elem.sizset = true; + return elem; + } + elem.sizset = false; + } + } + } + }; +} + +function addMatcher( higher, deeper ) { + return higher ? + function( elem, context ) { + var result = deeper( elem, context ); + return result && higher( result === true ? elem : result, context ); + } : + deeper; +} + +// ["TAG", ">", "ID", " ", "CLASS"] +function matcherFromTokens( tokens, context, xml ) { + var token, matcher, + i = 0; + + for ( ; (token = tokens[i]); i++ ) { + if ( Expr.relative[ token.part ] ) { + matcher = addCombinator( matcher, Expr.relative[ token.part ], context ); + } else { + token.captures.push( context, xml ); + matcher = addMatcher( matcher, Expr.filter[ token.part ].apply( null, token.captures ) ); + } + } + + return matcher; +} + +function matcherFromGroupMatchers( matchers ) { + return function( elem, context ) { + var matcher, + j = 0; + for ( ; (matcher = matchers[j]); j++ ) { + if ( matcher(elem, context) ) { + return true; + } + } + return false; + }; +} + +var compile = Sizzle.compile = function( selector, context, xml ) { + var tokens, group, i, + cached = compilerCache[ selector ]; + + // Return a cached group function if already generated (context dependent) + if ( cached && cached.context === context ) { + return cached; + } + + // Generate a function of recursive functions that can be used to check each element + group = tokenize( selector, context, xml ); + for ( i = 0; (tokens = group[i]); i++ ) { + group[i] = matcherFromTokens( tokens, context, xml ); + } + + // Cache the compiled function + cached = compilerCache[ selector ] = matcherFromGroupMatchers( group ); + cached.context = context; + cached.runs = cached.dirruns = 0; + cachedSelectors.push( selector ); + // Ensure only the most recent are cached + if ( cachedSelectors.length > Expr.cacheLength ) { + delete compilerCache[ cachedSelectors.shift() ]; + } + return cached; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + return Sizzle( expr, null, null, [ elem ] ).length > 0; +}; + +var select = function( selector, context, results, seed, xml ) { + // Remove excessive whitespace + selector = selector.replace( rtrim, "$1" ); + var elements, matcher, i, len, elem, token, + type, findContext, notTokens, + match = selector.match( rgroups ), + tokens = selector.match( rtokens ), + contextNodeType = context.nodeType; + + // POS handling + if ( matchExpr["POS"].test(selector) ) { + return handlePOS( selector, context, results, seed, match ); + } + + if ( seed ) { + elements = slice.call( seed, 0 ); + + // To maintain document order, only narrow the + // set if there is one group + } else if ( match && match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + if ( tokens.length > 1 && contextNodeType === 9 && !xml && + (match = matchExpr["ID"].exec( tokens[0] )) ) { + + context = Expr.find["ID"]( match[1], context, xml )[0]; + if ( !context ) { + return results; + } + + selector = selector.slice( tokens.shift().length ); + } + + findContext = ( (match = rsibling.exec( tokens[0] )) && !match.index && context.parentNode ) || context; + + // Get the last token, excluding :not + notTokens = tokens.pop(); + token = notTokens.split(":not")[0]; + + for ( i = 0, len = Expr.order.length; i < len; i++ ) { + type = Expr.order[i]; + + if ( (match = matchExpr[ type ].exec( token )) ) { + elements = Expr.find[ type ]( (match[1] || "").replace( rbackslash, "" ), findContext, xml ); + + if ( elements == null ) { + continue; + } + + if ( token === notTokens ) { + selector = selector.slice( 0, selector.length - notTokens.length ) + + token.replace( matchExpr[ type ], "" ); + + if ( !selector ) { + push.apply( results, slice.call(elements, 0) ); + } + } + break; + } + } + } + + // Only loop over the given elements once + // If selector is empty, we're already done + if ( selector ) { + matcher = compile( selector, context, xml ); + dirruns = matcher.dirruns++; + + if ( elements == null ) { + elements = Expr.find["TAG"]( "*", (rsibling.test( selector ) && context.parentNode) || context ); + } + for ( i = 0; (elem = elements[i]); i++ ) { + cachedruns = matcher.runs++; + if ( matcher(elem, context) ) { + results.push( elem ); + } + } + } + + return results; +}; + +if ( document.querySelectorAll ) { + (function() { + var disconnectedMatch, + oldSelect = select, + rescape = /'|\\/g, + rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g, + rbuggyQSA = [], + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + // A support test would require too much code (would include document ready) + // just skip matchesSelector for :active + rbuggyMatches = [":active"], + matches = docElem.matchesSelector || + docElem.mozMatchesSelector || + docElem.webkitMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector; + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + div.innerHTML = ""; + + // IE8 - Some boolean attributes are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here (do not put tests after this one) + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + + // Opera 10-12/IE9 - ^= $= *= and empty values + // Should not select anything + div.innerHTML = "

"; + if ( div.querySelectorAll("[test^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here (do not put tests after this one) + div.innerHTML = ""; + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push(":enabled", ":disabled"); + } + }); + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + + select = function( selector, context, results, seed, xml ) { + // Only use querySelectorAll when not filtering, + // when this is not xml, + // and when no QSA bugs apply + if ( !seed && !xml && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + if ( context.nodeType === 9 ) { + try { + push.apply( results, slice.call(context.querySelectorAll( selector ), 0) ); + return results; + } catch(qsaError) {} + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var old = context.getAttribute("id"), + nid = old || expando, + newContext = rsibling.test( selector ) && context.parentNode || context; + + if ( old ) { + nid = nid.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + + try { + push.apply( results, slice.call( newContext.querySelectorAll( + selector.replace( rgroups, "[id='" + nid + "'] $&" ) + ), 0 ) ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + + return oldSelect( selector, context, results, seed, xml ); + }; + + if ( matches ) { + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + try { + matches.call( div, "[test!='']:sizzle" ); + rbuggyMatches.push( Expr.match.PSEUDO ); + } catch ( e ) {} + }); + + // rbuggyMatches always contains :active, so no need for a length check + rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join("|") ); + + Sizzle.matchesSelector = function( elem, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + // rbuggyMatches always contains :active, so no need for an existence check + if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && (!rbuggyQSA || !rbuggyQSA.test( expr )) ) { + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch(e) {} + } + + return Sizzle( expr, null, null, [ elem ] ).length > 0; + }; + } + })(); +} + // Override sizzle attribute retrieval Sizzle.attr = jQuery.attr; jQuery.find = Sizzle; @@ -5134,9 +5134,9 @@ jQuery.unique = Sizzle.uniqueSort; jQuery.text = Sizzle.getText; jQuery.isXMLDoc = Sizzle.isXML; jQuery.contains = Sizzle.contains; - - -})( window ); + + +})( window ); var runtil = /Until$/, rparentsprev = /^(?:parents|prev(?:Until|All))/, isSimple = /^.[^:#\[\.,]*$/, diff --git a/tests/jquery-1.8.1.js b/tests/jquery-1.8.1.js index 973ef3d9a4..f6cb2a6fbd 100644 --- a/tests/jquery-1.8.1.js +++ b/tests/jquery-1.8.1.js @@ -3662,1532 +3662,1532 @@ jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblcl jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; } }); -/*! - * Sizzle CSS Selector Engine - * Copyright 2012 jQuery Foundation and other contributors - * Released under the MIT license - * http://sizzlejs.com/ - */ -(function( window, undefined ) { - -var dirruns, - cachedruns, - assertGetIdNotName, - Expr, - getText, - isXML, - contains, - compile, - sortOrder, - hasDuplicate, - - baseHasDuplicate = true, - strundefined = "undefined", - - expando = ( "sizcache" + Math.random() ).replace( ".", "" ), - - document = window.document, - docElem = document.documentElement, - done = 0, - slice = [].slice, - push = [].push, - - // Augment a function for special use by Sizzle - markFunction = function( fn, value ) { - fn[ expando ] = value || true; - return fn; - }, - - createCache = function() { - var cache = {}, - keys = []; - - return markFunction(function( key, value ) { - // Only keep the most recent entries - if ( keys.push( key ) > Expr.cacheLength ) { - delete cache[ keys.shift() ]; - } - - return (cache[ key ] = value); - }, cache ); - }, - - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - - // Regex - - // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - // http://www.w3.org/TR/css3-syntax/#characters - characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+", - - // Loosely modeled on CSS identifier characters - // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors) - // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = characterEncoding.replace( "w", "w#" ), - - // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors - operators = "([*^$|!~]?=)", - attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + - "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", - - // Prefer arguments not in parens/brackets, - // then attribute selectors and non-pseudos (denoted by :), - // then anything else - // These preferences are here to reduce the number of selectors - // needing tokenize in the PSEUDO preFilter - pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)", - - // For matchExpr.POS and matchExpr.needsContext - pos = ":(nth|eq|gt|lt|first|last|even|odd)(?:\\(((?:-\\d)?\\d*)\\)|)(?=[^-]|$)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ), - rpseudo = new RegExp( pseudos ), - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/, - - rnot = /^:not/, - rsibling = /[\x20\t\r\n\f]*[+~]/, - rendsWithNot = /:not\($/, - - rheader = /h\d/i, - rinputs = /input|select|textarea|button/i, - - rbackslash = /\\(?!\\)/g, - - matchExpr = { - "ID": new RegExp( "^#(" + characterEncoding + ")" ), - "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), - "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ), - "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "CHILD": new RegExp( "^:(only|nth|last|first)-child(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - "POS": new RegExp( pos, "ig" ), - // For use in libraries implementing .is() - "needsContext": new RegExp( "^" + whitespace + "*[>+~]|" + pos, "i" ) - }, - - // Support - - // Used for testing something on an element - assert = function( fn ) { - var div = document.createElement("div"); - - try { - return fn( div ); - } catch (e) { - return false; - } finally { - // release memory in IE - div = null; - } - }, - - // Check if getElementsByTagName("*") returns only elements - assertTagNameNoComments = assert(function( div ) { - div.appendChild( document.createComment("") ); - return !div.getElementsByTagName("*").length; - }), - - // Check if getAttribute returns normalized href attributes - assertHrefNotNormalized = assert(function( div ) { - div.innerHTML = ""; - return div.firstChild && typeof div.firstChild.getAttribute !== strundefined && - div.firstChild.getAttribute("href") === "#"; - }), - - // Check if attributes should be retrieved by attribute nodes - assertAttributes = assert(function( div ) { - div.innerHTML = ""; - var type = typeof div.lastChild.getAttribute("multiple"); - // IE8 returns a string for some attributes even when not present - return type !== "boolean" && type !== "string"; - }), - - // Check if getElementsByClassName can be trusted - assertUsableClassName = assert(function( div ) { - // Opera can't find a second classname (in 9.6) - div.innerHTML = ""; - if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) { - return false; - } - - // Safari 3.2 caches class attributes and doesn't catch changes - div.lastChild.className = "e"; - return div.getElementsByClassName("e").length === 2; - }), - - // Check if getElementById returns elements by name - // Check if getElementsByName privileges form controls or returns elements by ID - assertUsableName = assert(function( div ) { - // Inject content - div.id = expando + 0; - div.innerHTML = "
"; - docElem.insertBefore( div, docElem.firstChild ); - - // Test - var pass = document.getElementsByName && - // buggy browsers will return fewer than the correct 2 - document.getElementsByName( expando ).length === 2 + - // buggy browsers will return more than the correct 0 - document.getElementsByName( expando + 0 ).length; - assertGetIdNotName = !document.getElementById( expando ); - - // Cleanup - docElem.removeChild( div ); - - return pass; - }); - -// If slice is not available, provide a backup -try { - slice.call( docElem.childNodes, 0 )[0].nodeType; -} catch ( e ) { - slice = function( i ) { - var elem, results = []; - for ( ; (elem = this[i]); i++ ) { - results.push( elem ); - } - return results; - }; -} - -function Sizzle( selector, context, results, seed ) { - results = results || []; - context = context || document; - var match, elem, xml, m, - nodeType = context.nodeType; - - if ( nodeType !== 1 && nodeType !== 9 ) { - return []; - } - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - xml = isXML( context ); - - if ( !xml && !seed ) { - if ( (match = rquickExpr.exec( selector )) ) { - // Speed-up: Sizzle("#ID") - if ( (m = match[1]) ) { - if ( nodeType === 9 ) { - elem = context.getElementById( m ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE, Opera, and Webkit return items - // by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - } else { - // Context is not a document - if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && - contains( context, elem ) && elem.id === m ) { - results.push( elem ); - return results; - } - } - - // Speed-up: Sizzle("TAG") - } else if ( match[2] ) { - push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) ); - return results; - - // Speed-up: Sizzle(".CLASS") - } else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) { - push.apply( results, slice.call(context.getElementsByClassName( m ), 0) ); - return results; - } - } - } - - // All others - return select( selector, context, results, seed, xml ); -} - -Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); -}; - -Sizzle.matchesSelector = function( elem, expr ) { - return Sizzle( expr, null, null, [ elem ] ).length > 0; -}; - -// Returns a function to use in pseudos for input types -function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; -} - -// Returns a function to use in pseudos for buttons -function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; -} - -/** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if ( nodeType ) { - if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - // Use textContent for elements - // innerText usage removed for consistency of new lines (see #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - // Do not include comment or processing instruction nodes - } else { - - // If no nodeType, this is expected to be an array - for ( ; (node = elem[i]); i++ ) { - // Do not traverse comment nodes - ret += getText( node ); - } - } - return ret; -}; - -isXML = Sizzle.isXML = function isXML( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = elem && (elem.ownerDocument || elem).documentElement; - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -// Element contains another -contains = Sizzle.contains = docElem.contains ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) ); - } : - docElem.compareDocumentPosition ? - function( a, b ) { - return b && !!( a.compareDocumentPosition( b ) & 16 ); - } : - function( a, b ) { - while ( (b = b.parentNode) ) { - if ( b === a ) { - return true; - } - } - return false; - }; - -Sizzle.attr = function( elem, name ) { - var attr, - xml = isXML( elem ); - - if ( !xml ) { - name = name.toLowerCase(); - } - if ( Expr.attrHandle[ name ] ) { - return Expr.attrHandle[ name ]( elem ); - } - if ( assertAttributes || xml ) { - return elem.getAttribute( name ); - } - attr = elem.getAttributeNode( name ); - return attr ? - typeof elem[ name ] === "boolean" ? - elem[ name ] ? name : null : - attr.specified ? attr.value : null : - null; -}; - -Expr = Sizzle.selectors = { - - // Can be adjusted by the user - cacheLength: 50, - - createPseudo: markFunction, - - match: matchExpr, - - order: new RegExp( "ID|TAG" + - (assertUsableName ? "|NAME" : "") + - (assertUsableClassName ? "|CLASS" : "") - ), - - // IE6/7 return a modified href - attrHandle: assertHrefNotNormalized ? - {} : - { - "href": function( elem ) { - return elem.getAttribute( "href", 2 ); - }, - "type": function( elem ) { - return elem.getAttribute("type"); - } - }, - - find: { - "ID": assertGetIdNotName ? - function( id, context, xml ) { - if ( typeof context.getElementById !== strundefined && !xml ) { - var m = context.getElementById( id ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [m] : []; - } - } : - function( id, context, xml ) { - if ( typeof context.getElementById !== strundefined && !xml ) { - var m = context.getElementById( id ); - - return m ? - m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ? - [m] : - undefined : - []; - } - }, - - "TAG": assertTagNameNoComments ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== strundefined ) { - return context.getElementsByTagName( tag ); - } - } : - function( tag, context ) { - var results = context.getElementsByTagName( tag ); - - // Filter out possible comments - if ( tag === "*" ) { - var elem, - tmp = [], - i = 0; - - for ( ; (elem = results[i]); i++ ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } - - return tmp; - } - return results; - }, - - "NAME": function( tag, context ) { - if ( typeof context.getElementsByName !== strundefined ) { - return context.getElementsByName( name ); - } - }, - - "CLASS": function( className, context, xml ) { - if ( typeof context.getElementsByClassName !== strundefined && !xml ) { - return context.getElementsByClassName( className ); - } - } - }, - - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, - - preFilter: { - "ATTR": function( match ) { - match[1] = match[1].replace( rbackslash, "" ); - - // Move the given value to match[3] whether quoted or unquoted - match[3] = ( match[4] || match[5] || "" ).replace( rbackslash, "" ); - - if ( match[2] === "~=" ) { - match[3] = " " + match[3] + " "; - } - - return match.slice( 0, 4 ); - }, - - "CHILD": function( match ) { - /* matches from matchExpr.CHILD - 1 type (only|nth|...) - 2 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 3 xn-component of xn+y argument ([+-]?\d*n|) - 4 sign of xn-component - 5 x of xn-component - 6 sign of y-component - 7 y of y-component - */ - match[1] = match[1].toLowerCase(); - - if ( match[1] === "nth" ) { - // nth-child requires argument - if ( !match[2] ) { - Sizzle.error( match[0] ); - } - - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === "even" || match[2] === "odd" ) ); - match[4] = +( ( match[6] + match[7] ) || match[2] === "odd" ); - - // other types prohibit arguments - } else if ( match[2] ) { - Sizzle.error( match[0] ); - } - - return match; - }, - - "PSEUDO": function( match, context, xml ) { - var unquoted, excess; - if ( matchExpr["CHILD"].test( match[0] ) ) { - return null; - } - - if ( match[3] ) { - match[2] = match[3]; - } else if ( (unquoted = match[4]) ) { - // Only check arguments that contain a pseudo - if ( rpseudo.test(unquoted) && - // Get excess from tokenize (recursively) - (excess = tokenize( unquoted, context, xml, true )) && - // advance to the next closing parenthesis - (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { - - // excess is a negative index - unquoted = unquoted.slice( 0, excess ); - match[0] = match[0].slice( 0, excess ); - } - match[2] = unquoted; - } - - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice( 0, 3 ); - } - }, - - filter: { - "ID": assertGetIdNotName ? - function( id ) { - id = id.replace( rbackslash, "" ); - return function( elem ) { - return elem.getAttribute("id") === id; - }; - } : - function( id ) { - id = id.replace( rbackslash, "" ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); - return node && node.value === id; - }; - }, - - "TAG": function( nodeName ) { - if ( nodeName === "*" ) { - return function() { return true; }; - } - nodeName = nodeName.replace( rbackslash, "" ).toLowerCase(); - - return function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, - - "CLASS": function( className ) { - var pattern = classCache[ expando ][ className ]; - if ( !pattern ) { - pattern = classCache( className, new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)") ); - } - return function( elem ) { - return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" ); - }; - }, - - "ATTR": function( name, operator, check ) { - if ( !operator ) { - return function( elem ) { - return Sizzle.attr( elem, name ) != null; - }; - } - - return function( elem ) { - var result = Sizzle.attr( elem, name ), - value = result + ""; - - if ( result == null ) { - return operator === "!="; - } - - switch ( operator ) { - case "=": - return value === check; - case "!=": - return value !== check; - case "^=": - return check && value.indexOf( check ) === 0; - case "*=": - return check && value.indexOf( check ) > -1; - case "$=": - return check && value.substr( value.length - check.length ) === check; - case "~=": - return ( " " + value + " " ).indexOf( check ) > -1; - case "|=": - return value === check || value.substr( 0, check.length + 1 ) === check + "-"; - } - }; - }, - - "CHILD": function( type, argument, first, last ) { - - if ( type === "nth" ) { - var doneName = done++; - - return function( elem ) { - var parent, diff, - count = 0, - node = elem; - - if ( first === 1 && last === 0 ) { - return true; - } - - parent = elem.parentNode; - - if ( parent && (parent[ expando ] !== doneName || !elem.sizset) ) { - for ( node = parent.firstChild; node; node = node.nextSibling ) { - if ( node.nodeType === 1 ) { - node.sizset = ++count; - if ( node === elem ) { - break; - } - } - } - - parent[ expando ] = doneName; - } - - diff = elem.sizset - last; - - if ( first === 0 ) { - return diff === 0; - - } else { - return ( diff % first === 0 && diff / first >= 0 ); - } - }; - } - - return function( elem ) { - var node = elem; - - switch ( type ) { - case "only": - case "first": - while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - if ( type === "first" ) { - return true; - } - - node = elem; - - /* falls through */ - case "last": - while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - return true; - } - }; - }, - - "PSEUDO": function( pseudo, argument, context, xml ) { - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - var args, - fn = Expr.pseudos[ pseudo ] || Expr.pseudos[ pseudo.toLowerCase() ]; - - if ( !fn ) { - Sizzle.error( "unsupported pseudo: " + pseudo ); - } - - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if ( !fn[ expando ] ) { - if ( fn.length > 1 ) { - args = [ pseudo, pseudo, "", argument ]; - return function( elem ) { - return fn( elem, 0, args ); - }; - } - return fn; - } - - return fn( argument, context, xml ); - } - }, - - pseudos: { - "not": markFunction(function( selector, context, xml ) { - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var matcher = compile( selector.replace( rtrim, "$1" ), context, xml ); - return function( elem ) { - return !matcher( elem ); - }; - }), - - "enabled": function( elem ) { - return elem.disabled === false; - }, - - "disabled": function( elem ) { - return elem.disabled === true; - }, - - "checked": function( elem ) { - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); - }, - - "selected": function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - "parent": function( elem ) { - return !Expr.pseudos["empty"]( elem ); - }, - - "empty": function( elem ) { - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), - // not comment, processing instructions, or others - // Thanks to Diego Perini for the nodeName shortcut - // Greater than "@" means alpha characters (specifically not starting with "#" or "?") - var nodeType; - elem = elem.firstChild; - while ( elem ) { - if ( elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) { - return false; - } - elem = elem.nextSibling; - } - return true; - }, - - "contains": markFunction(function( text ) { - return function( elem ) { - return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; - }; - }), - - "has": markFunction(function( selector ) { - return function( elem ) { - return Sizzle( selector, elem ).length > 0; - }; - }), - - "header": function( elem ) { - return rheader.test( elem.nodeName ); - }, - - "text": function( elem ) { - var type, attr; - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) - // use getAttribute instead to test this case - return elem.nodeName.toLowerCase() === "input" && - (type = elem.type) === "text" && - ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type ); - }, - - // Input types - "radio": createInputPseudo("radio"), - "checkbox": createInputPseudo("checkbox"), - "file": createInputPseudo("file"), - "password": createInputPseudo("password"), - "image": createInputPseudo("image"), - - "submit": createButtonPseudo("submit"), - "reset": createButtonPseudo("reset"), - - "button": function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; - }, - - "input": function( elem ) { - return rinputs.test( elem.nodeName ); - }, - - "focus": function( elem ) { - var doc = elem.ownerDocument; - return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href); - }, - - "active": function( elem ) { - return elem === elem.ownerDocument.activeElement; - } - }, - - setFilters: { - "first": function( elements, argument, not ) { - return not ? elements.slice( 1 ) : [ elements[0] ]; - }, - - "last": function( elements, argument, not ) { - var elem = elements.pop(); - return not ? elements : [ elem ]; - }, - - "even": function( elements, argument, not ) { - var results = [], - i = not ? 1 : 0, - len = elements.length; - for ( ; i < len; i = i + 2 ) { - results.push( elements[i] ); - } - return results; - }, - - "odd": function( elements, argument, not ) { - var results = [], - i = not ? 0 : 1, - len = elements.length; - for ( ; i < len; i = i + 2 ) { - results.push( elements[i] ); - } - return results; - }, - - "lt": function( elements, argument, not ) { - return not ? elements.slice( +argument ) : elements.slice( 0, +argument ); - }, - - "gt": function( elements, argument, not ) { - return not ? elements.slice( 0, +argument + 1 ) : elements.slice( +argument + 1 ); - }, - - "eq": function( elements, argument, not ) { - var elem = elements.splice( +argument, 1 ); - return not ? elements : elem; - } - } -}; - -function siblingCheck( a, b, ret ) { - if ( a === b ) { - return ret; - } - - var cur = a.nextSibling; - - while ( cur ) { - if ( cur === b ) { - return -1; - } - - cur = cur.nextSibling; - } - - return 1; -} - -sortOrder = docElem.compareDocumentPosition ? - function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - return ( !a.compareDocumentPosition || !b.compareDocumentPosition ? - a.compareDocumentPosition : - a.compareDocumentPosition(b) & 4 - ) ? -1 : 1; - } : - function( a, b ) { - // The nodes are identical, we can exit early - if ( a === b ) { - hasDuplicate = true; - return 0; - - // Fallback to using sourceIndex (in IE) if it's available on both nodes - } else if ( a.sourceIndex && b.sourceIndex ) { - return a.sourceIndex - b.sourceIndex; - } - - var al, bl, - ap = [], - bp = [], - aup = a.parentNode, - bup = b.parentNode, - cur = aup; - - // If the nodes are siblings (or identical) we can do a quick check - if ( aup === bup ) { - return siblingCheck( a, b ); - - // If no parents were found then the nodes are disconnected - } else if ( !aup ) { - return -1; - - } else if ( !bup ) { - return 1; - } - - // Otherwise they're somewhere else in the tree so we need - // to build up a full list of the parentNodes for comparison - while ( cur ) { - ap.unshift( cur ); - cur = cur.parentNode; - } - - cur = bup; - - while ( cur ) { - bp.unshift( cur ); - cur = cur.parentNode; - } - - al = ap.length; - bl = bp.length; - - // Start walking down the tree looking for a discrepancy - for ( var i = 0; i < al && i < bl; i++ ) { - if ( ap[i] !== bp[i] ) { - return siblingCheck( ap[i], bp[i] ); - } - } - - // We ended someplace up the tree so do a sibling check - return i === al ? - siblingCheck( a, bp[i], -1 ) : - siblingCheck( ap[i], b, 1 ); - }; - -// Always assume the presence of duplicates if sort doesn't -// pass them to our comparison function (as in Google Chrome). -[0, 0].sort( sortOrder ); -baseHasDuplicate = !hasDuplicate; - -// Document sorting and removing duplicates -Sizzle.uniqueSort = function( results ) { - var elem, - i = 1; - - hasDuplicate = baseHasDuplicate; - results.sort( sortOrder ); - - if ( hasDuplicate ) { - for ( ; (elem = results[i]); i++ ) { - if ( elem === results[ i - 1 ] ) { - results.splice( i--, 1 ); - } - } - } - - return results; -}; - -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; - -function tokenize( selector, context, xml, parseOnly ) { - var matched, match, tokens, type, - soFar, groups, group, i, - preFilters, filters, - checkContext = !xml && context !== document, - // Token cache should maintain spaces - key = ( checkContext ? "" : "" ) + selector.replace( rtrim, "$1" ), - cached = tokenCache[ expando ][ key ]; - - if ( cached ) { - return parseOnly ? 0 : slice.call( cached, 0 ); - } - - soFar = selector; - groups = []; - i = 0; - preFilters = Expr.preFilter; - filters = Expr.filter; - - while ( soFar ) { - - // Comma and first run - if ( !matched || (match = rcomma.exec( soFar )) ) { - if ( match ) { - soFar = soFar.slice( match[0].length ); - tokens.selector = group; - } - groups.push( tokens = [] ); - group = ""; - - // Need to make sure we're within a narrower context if necessary - // Adding a descendant combinator will generate what is needed - if ( checkContext ) { - soFar = " " + soFar; - } - } - - matched = false; - - // Combinators - if ( (match = rcombinators.exec( soFar )) ) { - group += match[0]; - soFar = soFar.slice( match[0].length ); - - // Cast descendant combinators to space - matched = tokens.push({ - part: match.pop().replace( rtrim, " " ), - string: match[0], - captures: match - }); - } - - // Filters - for ( type in filters ) { - if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || - ( match = preFilters[ type ](match, context, xml) )) ) { - - group += match[0]; - soFar = soFar.slice( match[0].length ); - matched = tokens.push({ - part: type, - string: match.shift(), - captures: match - }); - } - } - - if ( !matched ) { - break; - } - } - - // Attach the full group as a selector - if ( group ) { - tokens.selector = group; - } - - // Return the length of the invalid excess - // if we're just parsing - // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error( selector ) : - // Cache the tokens - slice.call( tokenCache(key, groups), 0 ); -} - -function addCombinator( matcher, combinator, context, xml ) { - var dir = combinator.dir, - doneName = done++; - - if ( !matcher ) { - // If there is no matcher to check, check against the context - matcher = function( elem ) { - return elem === context; - }; - } - return combinator.first ? - function( elem ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 ) { - return matcher( elem ) && elem; - } - } - } : - xml ? - function( elem ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 ) { - if ( matcher( elem ) ) { - return elem; - } - } - } - } : - function( elem ) { - var cache, - dirkey = doneName + "." + dirruns, - cachedkey = dirkey + "." + cachedruns; - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 ) { - if ( (cache = elem[ expando ]) === cachedkey ) { - return elem.sizset; - } else if ( typeof cache === "string" && cache.indexOf(dirkey) === 0 ) { - if ( elem.sizset ) { - return elem; - } - } else { - elem[ expando ] = cachedkey; - if ( matcher( elem ) ) { - elem.sizset = true; - return elem; - } - elem.sizset = false; - } - } - } - }; -} - -function addMatcher( higher, deeper ) { - return higher ? - function( elem ) { - var result = deeper( elem ); - return result && higher( result === true ? elem : result ); - } : - deeper; -} - -// ["TAG", ">", "ID", " ", "CLASS"] -function matcherFromTokens( tokens, context, xml ) { - var token, matcher, - i = 0; - - for ( ; (token = tokens[i]); i++ ) { - if ( Expr.relative[ token.part ] ) { - matcher = addCombinator( matcher, Expr.relative[ token.part ], context, xml ); - } else { - matcher = addMatcher( matcher, Expr.filter[ token.part ].apply(null, token.captures.concat( context, xml )) ); - } - } - - return matcher; -} - -function matcherFromGroupMatchers( matchers ) { - return function( elem ) { - var matcher, - j = 0; - for ( ; (matcher = matchers[j]); j++ ) { - if ( matcher(elem) ) { - return true; - } - } - return false; - }; -} - -compile = Sizzle.compile = function( selector, context, xml ) { - var group, i, len, - cached = compilerCache[ expando ][ selector ]; - - // Return a cached group function if already generated (context dependent) - if ( cached && cached.context === context ) { - return cached; - } - - // Generate a function of recursive functions that can be used to check each element - group = tokenize( selector, context, xml ); - for ( i = 0, len = group.length; i < len; i++ ) { - group[i] = matcherFromTokens(group[i], context, xml); - } - - // Cache the compiled function - cached = compilerCache( selector, matcherFromGroupMatchers(group) ); - cached.context = context; - cached.runs = cached.dirruns = 0; - return cached; -}; - -function multipleContexts( selector, contexts, results, seed ) { - var i = 0, - len = contexts.length; - for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results, seed ); - } -} - -function handlePOSGroup( selector, posfilter, argument, contexts, seed, not ) { - var results, - fn = Expr.setFilters[ posfilter.toLowerCase() ]; - - if ( !fn ) { - Sizzle.error( posfilter ); - } - - if ( selector || !(results = seed) ) { - multipleContexts( selector || "*", contexts, (results = []), seed ); - } - - return results.length > 0 ? fn( results, argument, not ) : []; -} - -function handlePOS( groups, context, results, seed ) { - var group, part, j, groupLen, token, selector, - anchor, elements, match, matched, - lastIndex, currentContexts, not, - i = 0, - len = groups.length, - rpos = matchExpr["POS"], - // This is generated here in case matchExpr["POS"] is extended - rposgroups = new RegExp( "^" + rpos.source + "(?!" + whitespace + ")", "i" ), - // This is for making sure non-participating - // matching groups are represented cross-browser (IE6-8) - setUndefined = function() { - var i = 1, - len = arguments.length - 2; - for ( ; i < len; i++ ) { - if ( arguments[i] === undefined ) { - match[i] = undefined; - } - } - }; - - for ( ; i < len; i++ ) { - group = groups[i]; - part = ""; - elements = seed; - for ( j = 0, groupLen = group.length; j < groupLen; j++ ) { - token = group[j]; - selector = token.string; - if ( token.part === "PSEUDO" ) { - // Reset regex index to 0 - rpos.exec(""); - anchor = 0; - while ( (match = rpos.exec( selector )) ) { - matched = true; - lastIndex = rpos.lastIndex = match.index + match[0].length; - if ( lastIndex > anchor ) { - part += selector.slice( anchor, match.index ); - anchor = lastIndex; - currentContexts = [ context ]; - - if ( rcombinators.test(part) ) { - if ( elements ) { - currentContexts = elements; - } - elements = seed; - } - - if ( (not = rendsWithNot.test( part )) ) { - part = part.slice( 0, -5 ).replace( rcombinators, "$&*" ); - anchor++; - } - - if ( match.length > 1 ) { - match[0].replace( rposgroups, setUndefined ); - } - elements = handlePOSGroup( part, match[1], match[2], currentContexts, elements, not ); - } - part = ""; - } - - } - - if ( !matched ) { - part += selector; - } - matched = false; - } - - if ( part ) { - if ( rcombinators.test(part) ) { - multipleContexts( part, elements || [ context ], results, seed ); - } else { - Sizzle( part, context, results, seed ? seed.concat(elements) : elements ); - } - } else { - push.apply( results, elements ); - } - } - - // Do not sort if this is a single filter - return len === 1 ? results : Sizzle.uniqueSort( results ); -} - -function select( selector, context, results, seed, xml ) { - // Remove excessive whitespace - selector = selector.replace( rtrim, "$1" ); - var elements, matcher, cached, elem, - i, tokens, token, lastToken, findContext, type, - match = tokenize( selector, context, xml ), - contextNodeType = context.nodeType; - - // POS handling - if ( matchExpr["POS"].test(selector) ) { - return handlePOS( match, context, results, seed ); - } - - if ( seed ) { - elements = slice.call( seed, 0 ); - - // To maintain document order, only narrow the - // set if there is one group - } else if ( match.length === 1 ) { - - // Take a shortcut and set the context if the root selector is an ID - if ( (tokens = slice.call( match[0], 0 )).length > 2 && - (token = tokens[0]).part === "ID" && - contextNodeType === 9 && !xml && - Expr.relative[ tokens[1].part ] ) { - - context = Expr.find["ID"]( token.captures[0].replace( rbackslash, "" ), context, xml )[0]; - if ( !context ) { - return results; - } - - selector = selector.slice( tokens.shift().string.length ); - } - - findContext = ( (match = rsibling.exec( tokens[0].string )) && !match.index && context.parentNode ) || context; - - // Reduce the set if possible - lastToken = ""; - for ( i = tokens.length - 1; i >= 0; i-- ) { - token = tokens[i]; - type = token.part; - lastToken = token.string + lastToken; - if ( Expr.relative[ type ] ) { - break; - } - if ( Expr.order.test(type) ) { - elements = Expr.find[ type ]( token.captures[0].replace( rbackslash, "" ), findContext, xml ); - if ( elements == null ) { - continue; - } else { - selector = selector.slice( 0, selector.length - lastToken.length ) + - lastToken.replace( matchExpr[ type ], "" ); - - if ( !selector ) { - push.apply( results, slice.call(elements, 0) ); - } - - break; - } - } - } - } - - // Only loop over the given elements once - if ( selector ) { - matcher = compile( selector, context, xml ); - dirruns = matcher.dirruns++; - if ( elements == null ) { - elements = Expr.find["TAG"]( "*", (rsibling.test( selector ) && context.parentNode) || context ); - } - - for ( i = 0; (elem = elements[i]); i++ ) { - cachedruns = matcher.runs++; - if ( matcher(elem) ) { - results.push( elem ); - } - } - } - - return results; -} - -if ( document.querySelectorAll ) { - (function() { - var disconnectedMatch, - oldSelect = select, - rescape = /'|\\/g, - rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g, - rbuggyQSA = [], - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - // A support test would require too much code (would include document ready) - // just skip matchesSelector for :active - rbuggyMatches = [":active"], - matches = docElem.matchesSelector || - docElem.mozMatchesSelector || - docElem.webkitMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector; - - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert(function( div ) { - // Select is set to empty string on purpose - // This is to test IE's treatment of not explictly - // setting a boolean content attribute, - // since its presence should be enough - // http://bugs.jquery.com/ticket/12359 - div.innerHTML = ""; - - // IE8 - Some boolean attributes are not treated correctly - if ( !div.querySelectorAll("[selected]").length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" ); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here (do not put tests after this one) - if ( !div.querySelectorAll(":checked").length ) { - rbuggyQSA.push(":checked"); - } - }); - - assert(function( div ) { - - // Opera 10-12/IE9 - ^= $= *= and empty values - // Should not select anything - div.innerHTML = "

"; - if ( div.querySelectorAll("[test^='']").length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" ); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here (do not put tests after this one) - div.innerHTML = ""; - if ( !div.querySelectorAll(":enabled").length ) { - rbuggyQSA.push(":enabled", ":disabled"); - } - }); - - rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); - - select = function( selector, context, results, seed, xml ) { - // Only use querySelectorAll when not filtering, - // when this is not xml, - // and when no QSA bugs apply - if ( !seed && !xml && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { - if ( context.nodeType === 9 ) { - try { - push.apply( results, slice.call(context.querySelectorAll( selector ), 0) ); - return results; - } catch(qsaError) {} - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - var groups, i, len, - old = context.getAttribute("id"), - nid = old || expando, - newContext = rsibling.test( selector ) && context.parentNode || context; - - if ( old ) { - nid = nid.replace( rescape, "\\$&" ); - } else { - context.setAttribute( "id", nid ); - } - - groups = tokenize(selector, context, xml); - // Trailing space is unnecessary - // There is always a context check - nid = "[id='" + nid + "']"; - for ( i = 0, len = groups.length; i < len; i++ ) { - groups[i] = nid + groups[i].selector; - } - try { - push.apply( results, slice.call( newContext.querySelectorAll( - groups.join(",") - ), 0 ) ); - return results; - } catch(qsaError) { - } finally { - if ( !old ) { - context.removeAttribute("id"); - } - } - } - } - - return oldSelect( selector, context, results, seed, xml ); - }; - - if ( matches ) { - assert(function( div ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - disconnectedMatch = matches.call( div, "div" ); - - // This should fail with an exception - // Gecko does not error, returns false instead - try { - matches.call( div, "[test!='']:sizzle" ); - rbuggyMatches.push( matchExpr["PSEUDO"].source, matchExpr["POS"].source, "!=" ); - } catch ( e ) {} - }); - - // rbuggyMatches always contains :active, so no need for a length check - rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join("|") ); - - Sizzle.matchesSelector = function( elem, expr ) { - // Make sure that attribute selectors are quoted - expr = expr.replace( rattributeQuotes, "='$1']" ); - - // rbuggyMatches always contains :active, so no need for an existence check - if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && (!rbuggyQSA || !rbuggyQSA.test( expr )) ) { - try { - var ret = matches.call( elem, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { - return ret; - } - } catch(e) {} - } - - return Sizzle( expr, null, null, [ elem ] ).length > 0; - }; - } - })(); -} - -// Deprecated -Expr.setFilters["nth"] = Expr.setFilters["eq"]; - -// Back-compat -Expr.filters = Expr.pseudos; - +/*! + * Sizzle CSS Selector Engine + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license + * http://sizzlejs.com/ + */ +(function( window, undefined ) { + +var dirruns, + cachedruns, + assertGetIdNotName, + Expr, + getText, + isXML, + contains, + compile, + sortOrder, + hasDuplicate, + + baseHasDuplicate = true, + strundefined = "undefined", + + expando = ( "sizcache" + Math.random() ).replace( ".", "" ), + + document = window.document, + docElem = document.documentElement, + done = 0, + slice = [].slice, + push = [].push, + + // Augment a function for special use by Sizzle + markFunction = function( fn, value ) { + fn[ expando ] = value || true; + return fn; + }, + + createCache = function() { + var cache = {}, + keys = []; + + return markFunction(function( key, value ) { + // Only keep the most recent entries + if ( keys.push( key ) > Expr.cacheLength ) { + delete cache[ keys.shift() ]; + } + + return (cache[ key ] = value); + }, cache ); + }, + + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + + // Regex + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors) + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors + operators = "([*^$|!~]?=)", + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + + "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", + + // Prefer arguments not in parens/brackets, + // then attribute selectors and non-pseudos (denoted by :), + // then anything else + // These preferences are here to reduce the number of selectors + // needing tokenize in the PSEUDO preFilter + pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)", + + // For matchExpr.POS and matchExpr.needsContext + pos = ":(nth|eq|gt|lt|first|last|even|odd)(?:\\(((?:-\\d)?\\d*)\\)|)(?=[^-]|$)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ), + rpseudo = new RegExp( pseudos ), + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/, + + rnot = /^:not/, + rsibling = /[\x20\t\r\n\f]*[+~]/, + rendsWithNot = /:not\($/, + + rheader = /h\d/i, + rinputs = /input|select|textarea|button/i, + + rbackslash = /\\(?!\\)/g, + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|nth|last|first)-child(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "POS": new RegExp( pos, "ig" ), + // For use in libraries implementing .is() + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|" + pos, "i" ) + }, + + // Support + + // Used for testing something on an element + assert = function( fn ) { + var div = document.createElement("div"); + + try { + return fn( div ); + } catch (e) { + return false; + } finally { + // release memory in IE + div = null; + } + }, + + // Check if getElementsByTagName("*") returns only elements + assertTagNameNoComments = assert(function( div ) { + div.appendChild( document.createComment("") ); + return !div.getElementsByTagName("*").length; + }), + + // Check if getAttribute returns normalized href attributes + assertHrefNotNormalized = assert(function( div ) { + div.innerHTML = ""; + return div.firstChild && typeof div.firstChild.getAttribute !== strundefined && + div.firstChild.getAttribute("href") === "#"; + }), + + // Check if attributes should be retrieved by attribute nodes + assertAttributes = assert(function( div ) { + div.innerHTML = ""; + var type = typeof div.lastChild.getAttribute("multiple"); + // IE8 returns a string for some attributes even when not present + return type !== "boolean" && type !== "string"; + }), + + // Check if getElementsByClassName can be trusted + assertUsableClassName = assert(function( div ) { + // Opera can't find a second classname (in 9.6) + div.innerHTML = ""; + if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) { + return false; + } + + // Safari 3.2 caches class attributes and doesn't catch changes + div.lastChild.className = "e"; + return div.getElementsByClassName("e").length === 2; + }), + + // Check if getElementById returns elements by name + // Check if getElementsByName privileges form controls or returns elements by ID + assertUsableName = assert(function( div ) { + // Inject content + div.id = expando + 0; + div.innerHTML = "
"; + docElem.insertBefore( div, docElem.firstChild ); + + // Test + var pass = document.getElementsByName && + // buggy browsers will return fewer than the correct 2 + document.getElementsByName( expando ).length === 2 + + // buggy browsers will return more than the correct 0 + document.getElementsByName( expando + 0 ).length; + assertGetIdNotName = !document.getElementById( expando ); + + // Cleanup + docElem.removeChild( div ); + + return pass; + }); + +// If slice is not available, provide a backup +try { + slice.call( docElem.childNodes, 0 )[0].nodeType; +} catch ( e ) { + slice = function( i ) { + var elem, results = []; + for ( ; (elem = this[i]); i++ ) { + results.push( elem ); + } + return results; + }; +} + +function Sizzle( selector, context, results, seed ) { + results = results || []; + context = context || document; + var match, elem, xml, m, + nodeType = context.nodeType; + + if ( nodeType !== 1 && nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + xml = isXML( context ); + + if ( !xml && !seed ) { + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) { + push.apply( results, slice.call(context.getElementsByClassName( m ), 0) ); + return results; + } + } + } + + // All others + return select( selector, context, results, seed, xml ); +} + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + return Sizzle( expr, null, null, [ elem ] ).length > 0; +}; + +// Returns a function to use in pseudos for input types +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +// Returns a function to use in pseudos for buttons +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( nodeType ) { + if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (see #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + } else { + + // If no nodeType, this is expected to be an array + for ( ; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } + return ret; +}; + +isXML = Sizzle.isXML = function isXML( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +// Element contains another +contains = Sizzle.contains = docElem.contains ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) ); + } : + docElem.compareDocumentPosition ? + function( a, b ) { + return b && !!( a.compareDocumentPosition( b ) & 16 ); + } : + function( a, b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + return false; + }; + +Sizzle.attr = function( elem, name ) { + var attr, + xml = isXML( elem ); + + if ( !xml ) { + name = name.toLowerCase(); + } + if ( Expr.attrHandle[ name ] ) { + return Expr.attrHandle[ name ]( elem ); + } + if ( assertAttributes || xml ) { + return elem.getAttribute( name ); + } + attr = elem.getAttributeNode( name ); + return attr ? + typeof elem[ name ] === "boolean" ? + elem[ name ] ? name : null : + attr.specified ? attr.value : null : + null; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + order: new RegExp( "ID|TAG" + + (assertUsableName ? "|NAME" : "") + + (assertUsableClassName ? "|CLASS" : "") + ), + + // IE6/7 return a modified href + attrHandle: assertHrefNotNormalized ? + {} : + { + "href": function( elem ) { + return elem.getAttribute( "href", 2 ); + }, + "type": function( elem ) { + return elem.getAttribute("type"); + } + }, + + find: { + "ID": assertGetIdNotName ? + function( id, context, xml ) { + if ( typeof context.getElementById !== strundefined && !xml ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + } : + function( id, context, xml ) { + if ( typeof context.getElementById !== strundefined && !xml ) { + var m = context.getElementById( id ); + + return m ? + m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ? + [m] : + undefined : + []; + } + }, + + "TAG": assertTagNameNoComments ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + var elem, + tmp = [], + i = 0; + + for ( ; (elem = results[i]); i++ ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }, + + "NAME": function( tag, context ) { + if ( typeof context.getElementsByName !== strundefined ) { + return context.getElementsByName( name ); + } + }, + + "CLASS": function( className, context, xml ) { + if ( typeof context.getElementsByClassName !== strundefined && !xml ) { + return context.getElementsByClassName( className ); + } + } + }, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( rbackslash, "" ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[4] || match[5] || "" ).replace( rbackslash, "" ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr.CHILD + 1 type (only|nth|...) + 2 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 3 xn-component of xn+y argument ([+-]?\d*n|) + 4 sign of xn-component + 5 x of xn-component + 6 sign of y-component + 7 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1] === "nth" ) { + // nth-child requires argument + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === "even" || match[2] === "odd" ) ); + match[4] = +( ( match[6] + match[7] ) || match[2] === "odd" ); + + // other types prohibit arguments + } else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match, context, xml ) { + var unquoted, excess; + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + if ( match[3] ) { + match[2] = match[3]; + } else if ( (unquoted = match[4]) ) { + // Only check arguments that contain a pseudo + if ( rpseudo.test(unquoted) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, context, xml, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + unquoted = unquoted.slice( 0, excess ); + match[0] = match[0].slice( 0, excess ); + } + match[2] = unquoted; + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + "ID": assertGetIdNotName ? + function( id ) { + id = id.replace( rbackslash, "" ); + return function( elem ) { + return elem.getAttribute("id") === id; + }; + } : + function( id ) { + id = id.replace( rbackslash, "" ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === id; + }; + }, + + "TAG": function( nodeName ) { + if ( nodeName === "*" ) { + return function() { return true; }; + } + nodeName = nodeName.replace( rbackslash, "" ).toLowerCase(); + + return function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ expando ][ className ]; + if ( !pattern ) { + pattern = classCache( className, new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)") ); + } + return function( elem ) { + return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" ); + }; + }, + + "ATTR": function( name, operator, check ) { + if ( !operator ) { + return function( elem ) { + return Sizzle.attr( elem, name ) != null; + }; + } + + return function( elem ) { + var result = Sizzle.attr( elem, name ), + value = result + ""; + + if ( result == null ) { + return operator === "!="; + } + + switch ( operator ) { + case "=": + return value === check; + case "!=": + return value !== check; + case "^=": + return check && value.indexOf( check ) === 0; + case "*=": + return check && value.indexOf( check ) > -1; + case "$=": + return check && value.substr( value.length - check.length ) === check; + case "~=": + return ( " " + value + " " ).indexOf( check ) > -1; + case "|=": + return value === check || value.substr( 0, check.length + 1 ) === check + "-"; + } + }; + }, + + "CHILD": function( type, argument, first, last ) { + + if ( type === "nth" ) { + var doneName = done++; + + return function( elem ) { + var parent, diff, + count = 0, + node = elem; + + if ( first === 1 && last === 0 ) { + return true; + } + + parent = elem.parentNode; + + if ( parent && (parent[ expando ] !== doneName || !elem.sizset) ) { + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.sizset = ++count; + if ( node === elem ) { + break; + } + } + } + + parent[ expando ] = doneName; + } + + diff = elem.sizset - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + }; + } + + return function( elem ) { + var node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + /* falls through */ + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + } + }; + }, + + "PSEUDO": function( pseudo, argument, context, xml ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + var args, + fn = Expr.pseudos[ pseudo ] || Expr.pseudos[ pseudo.toLowerCase() ]; + + if ( !fn ) { + Sizzle.error( "unsupported pseudo: " + pseudo ); + } + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( !fn[ expando ] ) { + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return function( elem ) { + return fn( elem, 0, args ); + }; + } + return fn; + } + + return fn( argument, context, xml ); + } + }, + + pseudos: { + "not": markFunction(function( selector, context, xml ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var matcher = compile( selector.replace( rtrim, "$1" ), context, xml ); + return function( elem ) { + return !matcher( elem ); + }; + }), + + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), + // not comment, processing instructions, or others + // Thanks to Diego Perini for the nodeName shortcut + // Greater than "@" means alpha characters (specifically not starting with "#" or "?") + var nodeType; + elem = elem.firstChild; + while ( elem ) { + if ( elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) { + return false; + } + elem = elem.nextSibling; + } + return true; + }, + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "text": function( elem ) { + var type, attr; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && + (type = elem.type) === "text" && + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type ); + }, + + // Input types + "radio": createInputPseudo("radio"), + "checkbox": createInputPseudo("checkbox"), + "file": createInputPseudo("file"), + "password": createInputPseudo("password"), + "image": createInputPseudo("image"), + + "submit": createButtonPseudo("submit"), + "reset": createButtonPseudo("reset"), + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "focus": function( elem ) { + var doc = elem.ownerDocument; + return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href); + }, + + "active": function( elem ) { + return elem === elem.ownerDocument.activeElement; + } + }, + + setFilters: { + "first": function( elements, argument, not ) { + return not ? elements.slice( 1 ) : [ elements[0] ]; + }, + + "last": function( elements, argument, not ) { + var elem = elements.pop(); + return not ? elements : [ elem ]; + }, + + "even": function( elements, argument, not ) { + var results = [], + i = not ? 1 : 0, + len = elements.length; + for ( ; i < len; i = i + 2 ) { + results.push( elements[i] ); + } + return results; + }, + + "odd": function( elements, argument, not ) { + var results = [], + i = not ? 0 : 1, + len = elements.length; + for ( ; i < len; i = i + 2 ) { + results.push( elements[i] ); + } + return results; + }, + + "lt": function( elements, argument, not ) { + return not ? elements.slice( +argument ) : elements.slice( 0, +argument ); + }, + + "gt": function( elements, argument, not ) { + return not ? elements.slice( 0, +argument + 1 ) : elements.slice( +argument + 1 ); + }, + + "eq": function( elements, argument, not ) { + var elem = elements.splice( +argument, 1 ); + return not ? elements : elem; + } + } +}; + +function siblingCheck( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; +} + +sortOrder = docElem.compareDocumentPosition ? + function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + return ( !a.compareDocumentPosition || !b.compareDocumentPosition ? + a.compareDocumentPosition : + a.compareDocumentPosition(b) & 4 + ) ? -1 : 1; + } : + function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + +// Always assume the presence of duplicates if sort doesn't +// pass them to our comparison function (as in Google Chrome). +[0, 0].sort( sortOrder ); +baseHasDuplicate = !hasDuplicate; + +// Document sorting and removing duplicates +Sizzle.uniqueSort = function( results ) { + var elem, + i = 1; + + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( ; (elem = results[i]); i++ ) { + if ( elem === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + + return results; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +function tokenize( selector, context, xml, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, group, i, + preFilters, filters, + checkContext = !xml && context !== document, + // Token cache should maintain spaces + key = ( checkContext ? "" : "" ) + selector.replace( rtrim, "$1" ), + cached = tokenCache[ expando ][ key ]; + + if ( cached ) { + return parseOnly ? 0 : slice.call( cached, 0 ); + } + + soFar = selector; + groups = []; + i = 0; + preFilters = Expr.preFilter; + filters = Expr.filter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + soFar = soFar.slice( match[0].length ); + tokens.selector = group; + } + groups.push( tokens = [] ); + group = ""; + + // Need to make sure we're within a narrower context if necessary + // Adding a descendant combinator will generate what is needed + if ( checkContext ) { + soFar = " " + soFar; + } + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + group += match[0]; + soFar = soFar.slice( match[0].length ); + + // Cast descendant combinators to space + matched = tokens.push({ + part: match.pop().replace( rtrim, " " ), + string: match[0], + captures: match + }); + } + + // Filters + for ( type in filters ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + ( match = preFilters[ type ](match, context, xml) )) ) { + + group += match[0]; + soFar = soFar.slice( match[0].length ); + matched = tokens.push({ + part: type, + string: match.shift(), + captures: match + }); + } + } + + if ( !matched ) { + break; + } + } + + // Attach the full group as a selector + if ( group ) { + tokens.selector = group; + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + slice.call( tokenCache(key, groups), 0 ); +} + +function addCombinator( matcher, combinator, context, xml ) { + var dir = combinator.dir, + doneName = done++; + + if ( !matcher ) { + // If there is no matcher to check, check against the context + matcher = function( elem ) { + return elem === context; + }; + } + return combinator.first ? + function( elem ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 ) { + return matcher( elem ) && elem; + } + } + } : + xml ? + function( elem ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 ) { + if ( matcher( elem ) ) { + return elem; + } + } + } + } : + function( elem ) { + var cache, + dirkey = doneName + "." + dirruns, + cachedkey = dirkey + "." + cachedruns; + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 ) { + if ( (cache = elem[ expando ]) === cachedkey ) { + return elem.sizset; + } else if ( typeof cache === "string" && cache.indexOf(dirkey) === 0 ) { + if ( elem.sizset ) { + return elem; + } + } else { + elem[ expando ] = cachedkey; + if ( matcher( elem ) ) { + elem.sizset = true; + return elem; + } + elem.sizset = false; + } + } + } + }; +} + +function addMatcher( higher, deeper ) { + return higher ? + function( elem ) { + var result = deeper( elem ); + return result && higher( result === true ? elem : result ); + } : + deeper; +} + +// ["TAG", ">", "ID", " ", "CLASS"] +function matcherFromTokens( tokens, context, xml ) { + var token, matcher, + i = 0; + + for ( ; (token = tokens[i]); i++ ) { + if ( Expr.relative[ token.part ] ) { + matcher = addCombinator( matcher, Expr.relative[ token.part ], context, xml ); + } else { + matcher = addMatcher( matcher, Expr.filter[ token.part ].apply(null, token.captures.concat( context, xml )) ); + } + } + + return matcher; +} + +function matcherFromGroupMatchers( matchers ) { + return function( elem ) { + var matcher, + j = 0; + for ( ; (matcher = matchers[j]); j++ ) { + if ( matcher(elem) ) { + return true; + } + } + return false; + }; +} + +compile = Sizzle.compile = function( selector, context, xml ) { + var group, i, len, + cached = compilerCache[ expando ][ selector ]; + + // Return a cached group function if already generated (context dependent) + if ( cached && cached.context === context ) { + return cached; + } + + // Generate a function of recursive functions that can be used to check each element + group = tokenize( selector, context, xml ); + for ( i = 0, len = group.length; i < len; i++ ) { + group[i] = matcherFromTokens(group[i], context, xml); + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers(group) ); + cached.context = context; + cached.runs = cached.dirruns = 0; + return cached; +}; + +function multipleContexts( selector, contexts, results, seed ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results, seed ); + } +} + +function handlePOSGroup( selector, posfilter, argument, contexts, seed, not ) { + var results, + fn = Expr.setFilters[ posfilter.toLowerCase() ]; + + if ( !fn ) { + Sizzle.error( posfilter ); + } + + if ( selector || !(results = seed) ) { + multipleContexts( selector || "*", contexts, (results = []), seed ); + } + + return results.length > 0 ? fn( results, argument, not ) : []; +} + +function handlePOS( groups, context, results, seed ) { + var group, part, j, groupLen, token, selector, + anchor, elements, match, matched, + lastIndex, currentContexts, not, + i = 0, + len = groups.length, + rpos = matchExpr["POS"], + // This is generated here in case matchExpr["POS"] is extended + rposgroups = new RegExp( "^" + rpos.source + "(?!" + whitespace + ")", "i" ), + // This is for making sure non-participating + // matching groups are represented cross-browser (IE6-8) + setUndefined = function() { + var i = 1, + len = arguments.length - 2; + for ( ; i < len; i++ ) { + if ( arguments[i] === undefined ) { + match[i] = undefined; + } + } + }; + + for ( ; i < len; i++ ) { + group = groups[i]; + part = ""; + elements = seed; + for ( j = 0, groupLen = group.length; j < groupLen; j++ ) { + token = group[j]; + selector = token.string; + if ( token.part === "PSEUDO" ) { + // Reset regex index to 0 + rpos.exec(""); + anchor = 0; + while ( (match = rpos.exec( selector )) ) { + matched = true; + lastIndex = rpos.lastIndex = match.index + match[0].length; + if ( lastIndex > anchor ) { + part += selector.slice( anchor, match.index ); + anchor = lastIndex; + currentContexts = [ context ]; + + if ( rcombinators.test(part) ) { + if ( elements ) { + currentContexts = elements; + } + elements = seed; + } + + if ( (not = rendsWithNot.test( part )) ) { + part = part.slice( 0, -5 ).replace( rcombinators, "$&*" ); + anchor++; + } + + if ( match.length > 1 ) { + match[0].replace( rposgroups, setUndefined ); + } + elements = handlePOSGroup( part, match[1], match[2], currentContexts, elements, not ); + } + part = ""; + } + + } + + if ( !matched ) { + part += selector; + } + matched = false; + } + + if ( part ) { + if ( rcombinators.test(part) ) { + multipleContexts( part, elements || [ context ], results, seed ); + } else { + Sizzle( part, context, results, seed ? seed.concat(elements) : elements ); + } + } else { + push.apply( results, elements ); + } + } + + // Do not sort if this is a single filter + return len === 1 ? results : Sizzle.uniqueSort( results ); +} + +function select( selector, context, results, seed, xml ) { + // Remove excessive whitespace + selector = selector.replace( rtrim, "$1" ); + var elements, matcher, cached, elem, + i, tokens, token, lastToken, findContext, type, + match = tokenize( selector, context, xml ), + contextNodeType = context.nodeType; + + // POS handling + if ( matchExpr["POS"].test(selector) ) { + return handlePOS( match, context, results, seed ); + } + + if ( seed ) { + elements = slice.call( seed, 0 ); + + // To maintain document order, only narrow the + // set if there is one group + } else if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + if ( (tokens = slice.call( match[0], 0 )).length > 2 && + (token = tokens[0]).part === "ID" && + contextNodeType === 9 && !xml && + Expr.relative[ tokens[1].part ] ) { + + context = Expr.find["ID"]( token.captures[0].replace( rbackslash, "" ), context, xml )[0]; + if ( !context ) { + return results; + } + + selector = selector.slice( tokens.shift().string.length ); + } + + findContext = ( (match = rsibling.exec( tokens[0].string )) && !match.index && context.parentNode ) || context; + + // Reduce the set if possible + lastToken = ""; + for ( i = tokens.length - 1; i >= 0; i-- ) { + token = tokens[i]; + type = token.part; + lastToken = token.string + lastToken; + if ( Expr.relative[ type ] ) { + break; + } + if ( Expr.order.test(type) ) { + elements = Expr.find[ type ]( token.captures[0].replace( rbackslash, "" ), findContext, xml ); + if ( elements == null ) { + continue; + } else { + selector = selector.slice( 0, selector.length - lastToken.length ) + + lastToken.replace( matchExpr[ type ], "" ); + + if ( !selector ) { + push.apply( results, slice.call(elements, 0) ); + } + + break; + } + } + } + } + + // Only loop over the given elements once + if ( selector ) { + matcher = compile( selector, context, xml ); + dirruns = matcher.dirruns++; + if ( elements == null ) { + elements = Expr.find["TAG"]( "*", (rsibling.test( selector ) && context.parentNode) || context ); + } + + for ( i = 0; (elem = elements[i]); i++ ) { + cachedruns = matcher.runs++; + if ( matcher(elem) ) { + results.push( elem ); + } + } + } + + return results; +} + +if ( document.querySelectorAll ) { + (function() { + var disconnectedMatch, + oldSelect = select, + rescape = /'|\\/g, + rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g, + rbuggyQSA = [], + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + // A support test would require too much code (would include document ready) + // just skip matchesSelector for :active + rbuggyMatches = [":active"], + matches = docElem.matchesSelector || + docElem.mozMatchesSelector || + docElem.webkitMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector; + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explictly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = ""; + + // IE8 - Some boolean attributes are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here (do not put tests after this one) + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + + // Opera 10-12/IE9 - ^= $= *= and empty values + // Should not select anything + div.innerHTML = "

"; + if ( div.querySelectorAll("[test^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here (do not put tests after this one) + div.innerHTML = ""; + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push(":enabled", ":disabled"); + } + }); + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + + select = function( selector, context, results, seed, xml ) { + // Only use querySelectorAll when not filtering, + // when this is not xml, + // and when no QSA bugs apply + if ( !seed && !xml && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + if ( context.nodeType === 9 ) { + try { + push.apply( results, slice.call(context.querySelectorAll( selector ), 0) ); + return results; + } catch(qsaError) {} + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var groups, i, len, + old = context.getAttribute("id"), + nid = old || expando, + newContext = rsibling.test( selector ) && context.parentNode || context; + + if ( old ) { + nid = nid.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + + groups = tokenize(selector, context, xml); + // Trailing space is unnecessary + // There is always a context check + nid = "[id='" + nid + "']"; + for ( i = 0, len = groups.length; i < len; i++ ) { + groups[i] = nid + groups[i].selector; + } + try { + push.apply( results, slice.call( newContext.querySelectorAll( + groups.join(",") + ), 0 ) ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + + return oldSelect( selector, context, results, seed, xml ); + }; + + if ( matches ) { + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + try { + matches.call( div, "[test!='']:sizzle" ); + rbuggyMatches.push( matchExpr["PSEUDO"].source, matchExpr["POS"].source, "!=" ); + } catch ( e ) {} + }); + + // rbuggyMatches always contains :active, so no need for a length check + rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join("|") ); + + Sizzle.matchesSelector = function( elem, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + // rbuggyMatches always contains :active, so no need for an existence check + if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && (!rbuggyQSA || !rbuggyQSA.test( expr )) ) { + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch(e) {} + } + + return Sizzle( expr, null, null, [ elem ] ).length > 0; + }; + } + })(); +} + +// Deprecated +Expr.setFilters["nth"] = Expr.setFilters["eq"]; + +// Back-compat +Expr.filters = Expr.pseudos; + // Override sizzle attribute retrieval Sizzle.attr = jQuery.attr; jQuery.find = Sizzle; @@ -5197,9 +5197,9 @@ jQuery.unique = Sizzle.uniqueSort; jQuery.text = Sizzle.getText; jQuery.isXMLDoc = Sizzle.isXML; jQuery.contains = Sizzle.contains; - - -})( window ); + + +})( window ); var runtil = /Until$/, rparentsprev = /^(?:parents|prev(?:Until|All))/, isSimple = /^.[^:#\[\.,]*$/, diff --git a/tests/jquery-1.8.2.js b/tests/jquery-1.8.2.js index d4f3bb38cd..12c7797fdc 100644 --- a/tests/jquery-1.8.2.js +++ b/tests/jquery-1.8.2.js @@ -3665,1667 +3665,1667 @@ jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblcl jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; } }); -/*! - * Sizzle CSS Selector Engine - * Copyright 2012 jQuery Foundation and other contributors - * Released under the MIT license - * http://sizzlejs.com/ - */ -(function( window, undefined ) { - -var cachedruns, - assertGetIdNotName, - Expr, - getText, - isXML, - contains, - compile, - sortOrder, - hasDuplicate, - outermostContext, - - baseHasDuplicate = true, - strundefined = "undefined", - - expando = ( "sizcache" + Math.random() ).replace( ".", "" ), - - Token = String, - document = window.document, - docElem = document.documentElement, - dirruns = 0, - done = 0, - pop = [].pop, - push = [].push, - slice = [].slice, - // Use a stripped-down indexOf if a native one is unavailable - indexOf = [].indexOf || function( elem ) { - var i = 0, - len = this.length; - for ( ; i < len; i++ ) { - if ( this[i] === elem ) { - return i; - } - } - return -1; - }, - - // Augment a function for special use by Sizzle - markFunction = function( fn, value ) { - fn[ expando ] = value == null || value; - return fn; - }, - - createCache = function() { - var cache = {}, - keys = []; - - return markFunction(function( key, value ) { - // Only keep the most recent entries - if ( keys.push( key ) > Expr.cacheLength ) { - delete cache[ keys.shift() ]; - } - - return (cache[ key ] = value); - }, cache ); - }, - - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - - // Regex - - // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - // http://www.w3.org/TR/css3-syntax/#characters - characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+", - - // Loosely modeled on CSS identifier characters - // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors) - // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = characterEncoding.replace( "w", "w#" ), - - // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors - operators = "([*^$|!~]?=)", - attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + - "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", - - // Prefer arguments not in parens/brackets, - // then attribute selectors and non-pseudos (denoted by :), - // then anything else - // These preferences are here to reduce the number of selectors - // needing tokenize in the PSEUDO preFilter - pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)", - - // For matchExpr.POS and matchExpr.needsContext - pos = ":(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + - "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ), - rpseudo = new RegExp( pseudos ), - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/, - - rnot = /^:not/, - rsibling = /[\x20\t\r\n\f]*[+~]/, - rendsWithNot = /:not\($/, - - rheader = /h\d/i, - rinputs = /input|select|textarea|button/i, - - rbackslash = /\\(?!\\)/g, - - matchExpr = { - "ID": new RegExp( "^#(" + characterEncoding + ")" ), - "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), - "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ), - "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "POS": new RegExp( pos, "i" ), - "CHILD": new RegExp( "^:(only|nth|first|last)-child(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - // For use in libraries implementing .is() - "needsContext": new RegExp( "^" + whitespace + "*[>+~]|" + pos, "i" ) - }, - - // Support - - // Used for testing something on an element - assert = function( fn ) { - var div = document.createElement("div"); - - try { - return fn( div ); - } catch (e) { - return false; - } finally { - // release memory in IE - div = null; - } - }, - - // Check if getElementsByTagName("*") returns only elements - assertTagNameNoComments = assert(function( div ) { - div.appendChild( document.createComment("") ); - return !div.getElementsByTagName("*").length; - }), - - // Check if getAttribute returns normalized href attributes - assertHrefNotNormalized = assert(function( div ) { - div.innerHTML = ""; - return div.firstChild && typeof div.firstChild.getAttribute !== strundefined && - div.firstChild.getAttribute("href") === "#"; - }), - - // Check if attributes should be retrieved by attribute nodes - assertAttributes = assert(function( div ) { - div.innerHTML = ""; - var type = typeof div.lastChild.getAttribute("multiple"); - // IE8 returns a string for some attributes even when not present - return type !== "boolean" && type !== "string"; - }), - - // Check if getElementsByClassName can be trusted - assertUsableClassName = assert(function( div ) { - // Opera can't find a second classname (in 9.6) - div.innerHTML = ""; - if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) { - return false; - } - - // Safari 3.2 caches class attributes and doesn't catch changes - div.lastChild.className = "e"; - return div.getElementsByClassName("e").length === 2; - }), - - // Check if getElementById returns elements by name - // Check if getElementsByName privileges form controls or returns elements by ID - assertUsableName = assert(function( div ) { - // Inject content - div.id = expando + 0; - div.innerHTML = "
"; - docElem.insertBefore( div, docElem.firstChild ); - - // Test - var pass = document.getElementsByName && - // buggy browsers will return fewer than the correct 2 - document.getElementsByName( expando ).length === 2 + - // buggy browsers will return more than the correct 0 - document.getElementsByName( expando + 0 ).length; - assertGetIdNotName = !document.getElementById( expando ); - - // Cleanup - docElem.removeChild( div ); - - return pass; - }); - -// If slice is not available, provide a backup -try { - slice.call( docElem.childNodes, 0 )[0].nodeType; -} catch ( e ) { - slice = function( i ) { - var elem, - results = []; - for ( ; (elem = this[i]); i++ ) { - results.push( elem ); - } - return results; - }; -} - -function Sizzle( selector, context, results, seed ) { - results = results || []; - context = context || document; - var match, elem, xml, m, - nodeType = context.nodeType; - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - if ( nodeType !== 1 && nodeType !== 9 ) { - return []; - } - - xml = isXML( context ); - - if ( !xml && !seed ) { - if ( (match = rquickExpr.exec( selector )) ) { - // Speed-up: Sizzle("#ID") - if ( (m = match[1]) ) { - if ( nodeType === 9 ) { - elem = context.getElementById( m ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE, Opera, and Webkit return items - // by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - } else { - // Context is not a document - if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && - contains( context, elem ) && elem.id === m ) { - results.push( elem ); - return results; - } - } - - // Speed-up: Sizzle("TAG") - } else if ( match[2] ) { - push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) ); - return results; - - // Speed-up: Sizzle(".CLASS") - } else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) { - push.apply( results, slice.call(context.getElementsByClassName( m ), 0) ); - return results; - } - } - } - - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed, xml ); -} - -Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); -}; - -Sizzle.matchesSelector = function( elem, expr ) { - return Sizzle( expr, null, null, [ elem ] ).length > 0; -}; - -// Returns a function to use in pseudos for input types -function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; -} - -// Returns a function to use in pseudos for buttons -function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; -} - -// Returns a function to use in pseudos for positionals -function createPositionalPseudo( fn ) { - return markFunction(function( argument ) { - argument = +argument; - return markFunction(function( seed, matches ) { - var j, - matchIndexes = fn( [], seed.length, argument ), - i = matchIndexes.length; - - // Match elements found at the specified indexes - while ( i-- ) { - if ( seed[ (j = matchIndexes[i]) ] ) { - seed[j] = !(matches[j] = seed[j]); - } - } - }); - }); -} - -/** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if ( nodeType ) { - if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - // Use textContent for elements - // innerText usage removed for consistency of new lines (see #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - // Do not include comment or processing instruction nodes - } else { - - // If no nodeType, this is expected to be an array - for ( ; (node = elem[i]); i++ ) { - // Do not traverse comment nodes - ret += getText( node ); - } - } - return ret; -}; - -isXML = Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = elem && (elem.ownerDocument || elem).documentElement; - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -// Element contains another -contains = Sizzle.contains = docElem.contains ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) ); - } : - docElem.compareDocumentPosition ? - function( a, b ) { - return b && !!( a.compareDocumentPosition( b ) & 16 ); - } : - function( a, b ) { - while ( (b = b.parentNode) ) { - if ( b === a ) { - return true; - } - } - return false; - }; - -Sizzle.attr = function( elem, name ) { - var val, - xml = isXML( elem ); - - if ( !xml ) { - name = name.toLowerCase(); - } - if ( (val = Expr.attrHandle[ name ]) ) { - return val( elem ); - } - if ( xml || assertAttributes ) { - return elem.getAttribute( name ); - } - val = elem.getAttributeNode( name ); - return val ? - typeof elem[ name ] === "boolean" ? - elem[ name ] ? name : null : - val.specified ? val.value : null : - null; -}; - -Expr = Sizzle.selectors = { - - // Can be adjusted by the user - cacheLength: 50, - - createPseudo: markFunction, - - match: matchExpr, - - // IE6/7 return a modified href - attrHandle: assertHrefNotNormalized ? - {} : - { - "href": function( elem ) { - return elem.getAttribute( "href", 2 ); - }, - "type": function( elem ) { - return elem.getAttribute("type"); - } - }, - - find: { - "ID": assertGetIdNotName ? - function( id, context, xml ) { - if ( typeof context.getElementById !== strundefined && !xml ) { - var m = context.getElementById( id ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [m] : []; - } - } : - function( id, context, xml ) { - if ( typeof context.getElementById !== strundefined && !xml ) { - var m = context.getElementById( id ); - - return m ? - m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ? - [m] : - undefined : - []; - } - }, - - "TAG": assertTagNameNoComments ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== strundefined ) { - return context.getElementsByTagName( tag ); - } - } : - function( tag, context ) { - var results = context.getElementsByTagName( tag ); - - // Filter out possible comments - if ( tag === "*" ) { - var elem, - tmp = [], - i = 0; - - for ( ; (elem = results[i]); i++ ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } - - return tmp; - } - return results; - }, - - "NAME": assertUsableName && function( tag, context ) { - if ( typeof context.getElementsByName !== strundefined ) { - return context.getElementsByName( name ); - } - }, - - "CLASS": assertUsableClassName && function( className, context, xml ) { - if ( typeof context.getElementsByClassName !== strundefined && !xml ) { - return context.getElementsByClassName( className ); - } - } - }, - - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, - - preFilter: { - "ATTR": function( match ) { - match[1] = match[1].replace( rbackslash, "" ); - - // Move the given value to match[3] whether quoted or unquoted - match[3] = ( match[4] || match[5] || "" ).replace( rbackslash, "" ); - - if ( match[2] === "~=" ) { - match[3] = " " + match[3] + " "; - } - - return match.slice( 0, 4 ); - }, - - "CHILD": function( match ) { - /* matches from matchExpr["CHILD"] - 1 type (only|nth|...) - 2 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 3 xn-component of xn+y argument ([+-]?\d*n|) - 4 sign of xn-component - 5 x of xn-component - 6 sign of y-component - 7 y of y-component - */ - match[1] = match[1].toLowerCase(); - - if ( match[1] === "nth" ) { - // nth-child requires argument - if ( !match[2] ) { - Sizzle.error( match[0] ); - } - - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === "even" || match[2] === "odd" ) ); - match[4] = +( ( match[6] + match[7] ) || match[2] === "odd" ); - - // other types prohibit arguments - } else if ( match[2] ) { - Sizzle.error( match[0] ); - } - - return match; - }, - - "PSEUDO": function( match ) { - var unquoted, excess; - if ( matchExpr["CHILD"].test( match[0] ) ) { - return null; - } - - if ( match[3] ) { - match[2] = match[3]; - } else if ( (unquoted = match[4]) ) { - // Only check arguments that contain a pseudo - if ( rpseudo.test(unquoted) && - // Get excess from tokenize (recursively) - (excess = tokenize( unquoted, true )) && - // advance to the next closing parenthesis - (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { - - // excess is a negative index - unquoted = unquoted.slice( 0, excess ); - match[0] = match[0].slice( 0, excess ); - } - match[2] = unquoted; - } - - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice( 0, 3 ); - } - }, - - filter: { - "ID": assertGetIdNotName ? - function( id ) { - id = id.replace( rbackslash, "" ); - return function( elem ) { - return elem.getAttribute("id") === id; - }; - } : - function( id ) { - id = id.replace( rbackslash, "" ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); - return node && node.value === id; - }; - }, - - "TAG": function( nodeName ) { - if ( nodeName === "*" ) { - return function() { return true; }; - } - nodeName = nodeName.replace( rbackslash, "" ).toLowerCase(); - - return function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, - - "CLASS": function( className ) { - var pattern = classCache[ expando ][ className ]; - if ( !pattern ) { - pattern = classCache( className, new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)") ); - } - return function( elem ) { - return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" ); - }; - }, - - "ATTR": function( name, operator, check ) { - return function( elem, context ) { - var result = Sizzle.attr( elem, name ); - - if ( result == null ) { - return operator === "!="; - } - if ( !operator ) { - return true; - } - - result += ""; - - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf( check ) === 0 : - operator === "*=" ? check && result.indexOf( check ) > -1 : - operator === "$=" ? check && result.substr( result.length - check.length ) === check : - operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : - operator === "|=" ? result === check || result.substr( 0, check.length + 1 ) === check + "-" : - false; - }; - }, - - "CHILD": function( type, argument, first, last ) { - - if ( type === "nth" ) { - return function( elem ) { - var node, diff, - parent = elem.parentNode; - - if ( first === 1 && last === 0 ) { - return true; - } - - if ( parent ) { - diff = 0; - for ( node = parent.firstChild; node; node = node.nextSibling ) { - if ( node.nodeType === 1 ) { - diff++; - if ( elem === node ) { - break; - } - } - } - } - - // Incorporate the offset (or cast to NaN), then check against cycle size - diff -= last; - return diff === first || ( diff % first === 0 && diff / first >= 0 ); - }; - } - - return function( elem ) { - var node = elem; - - switch ( type ) { - case "only": - case "first": - while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - if ( type === "first" ) { - return true; - } - - node = elem; - - /* falls through */ - case "last": - while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - return true; - } - }; - }, - - "PSEUDO": function( pseudo, argument ) { - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - // Remember that setFilters inherits from pseudos - var args, - fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || - Sizzle.error( "unsupported pseudo: " + pseudo ); - - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if ( fn[ expando ] ) { - return fn( argument ); - } - - // But maintain support for old signatures - if ( fn.length > 1 ) { - args = [ pseudo, pseudo, "", argument ]; - return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction(function( seed, matches ) { - var idx, - matched = fn( seed, argument ), - i = matched.length; - while ( i-- ) { - idx = indexOf.call( seed, matched[i] ); - seed[ idx ] = !( matches[ idx ] = matched[i] ); - } - }) : - function( elem ) { - return fn( elem, 0, args ); - }; - } - - return fn; - } - }, - - pseudos: { - "not": markFunction(function( selector ) { - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var input = [], - results = [], - matcher = compile( selector.replace( rtrim, "$1" ) ); - - return matcher[ expando ] ? - markFunction(function( seed, matches, context, xml ) { - var elem, - unmatched = matcher( seed, null, xml, [] ), - i = seed.length; - - // Match elements unmatched by `matcher` - while ( i-- ) { - if ( (elem = unmatched[i]) ) { - seed[i] = !(matches[i] = elem); - } - } - }) : - function( elem, context, xml ) { - input[0] = elem; - matcher( input, null, xml, results ); - return !results.pop(); - }; - }), - - "has": markFunction(function( selector ) { - return function( elem ) { - return Sizzle( selector, elem ).length > 0; - }; - }), - - "contains": markFunction(function( text ) { - return function( elem ) { - return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; - }; - }), - - "enabled": function( elem ) { - return elem.disabled === false; - }, - - "disabled": function( elem ) { - return elem.disabled === true; - }, - - "checked": function( elem ) { - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); - }, - - "selected": function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - "parent": function( elem ) { - return !Expr.pseudos["empty"]( elem ); - }, - - "empty": function( elem ) { - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), - // not comment, processing instructions, or others - // Thanks to Diego Perini for the nodeName shortcut - // Greater than "@" means alpha characters (specifically not starting with "#" or "?") - var nodeType; - elem = elem.firstChild; - while ( elem ) { - if ( elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) { - return false; - } - elem = elem.nextSibling; - } - return true; - }, - - "header": function( elem ) { - return rheader.test( elem.nodeName ); - }, - - "text": function( elem ) { - var type, attr; - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) - // use getAttribute instead to test this case - return elem.nodeName.toLowerCase() === "input" && - (type = elem.type) === "text" && - ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type ); - }, - - // Input types - "radio": createInputPseudo("radio"), - "checkbox": createInputPseudo("checkbox"), - "file": createInputPseudo("file"), - "password": createInputPseudo("password"), - "image": createInputPseudo("image"), - - "submit": createButtonPseudo("submit"), - "reset": createButtonPseudo("reset"), - - "button": function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; - }, - - "input": function( elem ) { - return rinputs.test( elem.nodeName ); - }, - - "focus": function( elem ) { - var doc = elem.ownerDocument; - return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href); - }, - - "active": function( elem ) { - return elem === elem.ownerDocument.activeElement; - }, - - // Positional types - "first": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ 0 ]; - }), - - "last": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ length - 1 ]; - }), - - "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ argument < 0 ? argument + length : argument ]; - }), - - "even": createPositionalPseudo(function( matchIndexes, length, argument ) { - for ( var i = 0; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "odd": createPositionalPseudo(function( matchIndexes, length, argument ) { - for ( var i = 1; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { - for ( var i = argument < 0 ? argument + length : argument; --i >= 0; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { - for ( var i = argument < 0 ? argument + length : argument; ++i < length; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }) - } -}; - -function siblingCheck( a, b, ret ) { - if ( a === b ) { - return ret; - } - - var cur = a.nextSibling; - - while ( cur ) { - if ( cur === b ) { - return -1; - } - - cur = cur.nextSibling; - } - - return 1; -} - -sortOrder = docElem.compareDocumentPosition ? - function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - return ( !a.compareDocumentPosition || !b.compareDocumentPosition ? - a.compareDocumentPosition : - a.compareDocumentPosition(b) & 4 - ) ? -1 : 1; - } : - function( a, b ) { - // The nodes are identical, we can exit early - if ( a === b ) { - hasDuplicate = true; - return 0; - - // Fallback to using sourceIndex (in IE) if it's available on both nodes - } else if ( a.sourceIndex && b.sourceIndex ) { - return a.sourceIndex - b.sourceIndex; - } - - var al, bl, - ap = [], - bp = [], - aup = a.parentNode, - bup = b.parentNode, - cur = aup; - - // If the nodes are siblings (or identical) we can do a quick check - if ( aup === bup ) { - return siblingCheck( a, b ); - - // If no parents were found then the nodes are disconnected - } else if ( !aup ) { - return -1; - - } else if ( !bup ) { - return 1; - } - - // Otherwise they're somewhere else in the tree so we need - // to build up a full list of the parentNodes for comparison - while ( cur ) { - ap.unshift( cur ); - cur = cur.parentNode; - } - - cur = bup; - - while ( cur ) { - bp.unshift( cur ); - cur = cur.parentNode; - } - - al = ap.length; - bl = bp.length; - - // Start walking down the tree looking for a discrepancy - for ( var i = 0; i < al && i < bl; i++ ) { - if ( ap[i] !== bp[i] ) { - return siblingCheck( ap[i], bp[i] ); - } - } - - // We ended someplace up the tree so do a sibling check - return i === al ? - siblingCheck( a, bp[i], -1 ) : - siblingCheck( ap[i], b, 1 ); - }; - -// Always assume the presence of duplicates if sort doesn't -// pass them to our comparison function (as in Google Chrome). -[0, 0].sort( sortOrder ); -baseHasDuplicate = !hasDuplicate; - -// Document sorting and removing duplicates -Sizzle.uniqueSort = function( results ) { - var elem, - i = 1; - - hasDuplicate = baseHasDuplicate; - results.sort( sortOrder ); - - if ( hasDuplicate ) { - for ( ; (elem = results[i]); i++ ) { - if ( elem === results[ i - 1 ] ) { - results.splice( i--, 1 ); - } - } - } - - return results; -}; - -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; - -function tokenize( selector, parseOnly ) { - var matched, match, tokens, type, soFar, groups, preFilters, - cached = tokenCache[ expando ][ selector ]; - - if ( cached ) { - return parseOnly ? 0 : cached.slice( 0 ); - } - - soFar = selector; - groups = []; - preFilters = Expr.preFilter; - - while ( soFar ) { - - // Comma and first run - if ( !matched || (match = rcomma.exec( soFar )) ) { - if ( match ) { - soFar = soFar.slice( match[0].length ); - } - groups.push( tokens = [] ); - } - - matched = false; - - // Combinators - if ( (match = rcombinators.exec( soFar )) ) { - tokens.push( matched = new Token( match.shift() ) ); - soFar = soFar.slice( matched.length ); - - // Cast descendant combinators to space - matched.type = match[0].replace( rtrim, " " ); - } - - // Filters - for ( type in Expr.filter ) { - if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || - // The last two arguments here are (context, xml) for backCompat - (match = preFilters[ type ]( match, document, true ))) ) { - - tokens.push( matched = new Token( match.shift() ) ); - soFar = soFar.slice( matched.length ); - matched.type = type; - matched.matches = match; - } - } - - if ( !matched ) { - break; - } - } - - // Return the length of the invalid excess - // if we're just parsing - // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error( selector ) : - // Cache the tokens - tokenCache( selector, groups ).slice( 0 ); -} - -function addCombinator( matcher, combinator, base ) { - var dir = combinator.dir, - checkNonElements = base && combinator.dir === "parentNode", - doneName = done++; - - return combinator.first ? - // Check against closest ancestor/preceding element - function( elem, context, xml ) { - while ( (elem = elem[ dir ]) ) { - if ( checkNonElements || elem.nodeType === 1 ) { - return matcher( elem, context, xml ); - } - } - } : - - // Check against all ancestor/preceding elements - function( elem, context, xml ) { - // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching - if ( !xml ) { - var cache, - dirkey = dirruns + " " + doneName + " ", - cachedkey = dirkey + cachedruns; - while ( (elem = elem[ dir ]) ) { - if ( checkNonElements || elem.nodeType === 1 ) { - if ( (cache = elem[ expando ]) === cachedkey ) { - return elem.sizset; - } else if ( typeof cache === "string" && cache.indexOf(dirkey) === 0 ) { - if ( elem.sizset ) { - return elem; - } - } else { - elem[ expando ] = cachedkey; - if ( matcher( elem, context, xml ) ) { - elem.sizset = true; - return elem; - } - elem.sizset = false; - } - } - } - } else { - while ( (elem = elem[ dir ]) ) { - if ( checkNonElements || elem.nodeType === 1 ) { - if ( matcher( elem, context, xml ) ) { - return elem; - } - } - } - } - }; -} - -function elementMatcher( matchers ) { - return matchers.length > 1 ? - function( elem, context, xml ) { - var i = matchers.length; - while ( i-- ) { - if ( !matchers[i]( elem, context, xml ) ) { - return false; - } - } - return true; - } : - matchers[0]; -} - -function condense( unmatched, map, filter, context, xml ) { - var elem, - newUnmatched = [], - i = 0, - len = unmatched.length, - mapped = map != null; - - for ( ; i < len; i++ ) { - if ( (elem = unmatched[i]) ) { - if ( !filter || filter( elem, context, xml ) ) { - newUnmatched.push( elem ); - if ( mapped ) { - map.push( i ); - } - } - } - } - - return newUnmatched; -} - -function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { - if ( postFilter && !postFilter[ expando ] ) { - postFilter = setMatcher( postFilter ); - } - if ( postFinder && !postFinder[ expando ] ) { - postFinder = setMatcher( postFinder, postSelector ); - } - return markFunction(function( seed, results, context, xml ) { - // Positional selectors apply to seed elements, so it is invalid to follow them with relative ones - if ( seed && postFinder ) { - return; - } - - var i, elem, postFilterIn, - preMap = [], - postMap = [], - preexisting = results.length, - - // Get initial elements from seed or context - elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [], seed ), - - // Prefilter to get matcher input, preserving a map for seed-results synchronization - matcherIn = preFilter && ( seed || !selector ) ? - condense( elems, preMap, preFilter, context, xml ) : - elems, - - matcherOut = matcher ? - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || ( seed ? preFilter : preexisting || postFilter ) ? - - // ...intermediate processing is necessary - [] : - - // ...otherwise use results directly - results : - matcherIn; - - // Find primary matches - if ( matcher ) { - matcher( matcherIn, matcherOut, context, xml ); - } - - // Apply postFilter - if ( postFilter ) { - postFilterIn = condense( matcherOut, postMap ); - postFilter( postFilterIn, [], context, xml ); - - // Un-match failing elements by moving them back to matcherIn - i = postFilterIn.length; - while ( i-- ) { - if ( (elem = postFilterIn[i]) ) { - matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); - } - } - } - - // Keep seed and results synchronized - if ( seed ) { - // Ignore postFinder because it can't coexist with seed - i = preFilter && matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) ) { - seed[ preMap[i] ] = !(results[ preMap[i] ] = elem); - } - } - } else { - matcherOut = condense( - matcherOut === results ? - matcherOut.splice( preexisting, matcherOut.length ) : - matcherOut - ); - if ( postFinder ) { - postFinder( null, results, matcherOut, xml ); - } else { - push.apply( results, matcherOut ); - } - } - }); -} - -function matcherFromTokens( tokens ) { - var checkContext, matcher, j, - len = tokens.length, - leadingRelative = Expr.relative[ tokens[0].type ], - implicitRelative = leadingRelative || Expr.relative[" "], - i = leadingRelative ? 1 : 0, - - // The foundational matcher ensures that elements are reachable from top-level context(s) - matchContext = addCombinator( function( elem ) { - return elem === checkContext; - }, implicitRelative, true ), - matchAnyContext = addCombinator( function( elem ) { - return indexOf.call( checkContext, elem ) > -1; - }, implicitRelative, true ), - matchers = [ function( elem, context, xml ) { - return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - (checkContext = context).nodeType ? - matchContext( elem, context, xml ) : - matchAnyContext( elem, context, xml ) ); - } ]; - - for ( ; i < len; i++ ) { - if ( (matcher = Expr.relative[ tokens[i].type ]) ) { - matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; - } else { - // The concatenated values are (context, xml) for backCompat - matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); - - // Return special upon seeing a positional matcher - if ( matcher[ expando ] ) { - // Find the next relative operator (if any) for proper handling - j = ++i; - for ( ; j < len; j++ ) { - if ( Expr.relative[ tokens[j].type ] ) { - break; - } - } - return setMatcher( - i > 1 && elementMatcher( matchers ), - i > 1 && tokens.slice( 0, i - 1 ).join("").replace( rtrim, "$1" ), - matcher, - i < j && matcherFromTokens( tokens.slice( i, j ) ), - j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), - j < len && tokens.join("") - ); - } - matchers.push( matcher ); - } - } - - return elementMatcher( matchers ); -} - -function matcherFromGroupMatchers( elementMatchers, setMatchers ) { - var bySet = setMatchers.length > 0, - byElement = elementMatchers.length > 0, - superMatcher = function( seed, context, xml, results, expandContext ) { - var elem, j, matcher, - setMatched = [], - matchedCount = 0, - i = "0", - unmatched = seed && [], - outermost = expandContext != null, - contextBackup = outermostContext, - // We must always have either seed elements or context - elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), - // Nested matchers should use non-integer dirruns - dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.E); - - if ( outermost ) { - outermostContext = context !== document && context; - cachedruns = superMatcher.el; - } - - // Add elements passing elementMatchers directly to results - for ( ; (elem = elems[i]) != null; i++ ) { - if ( byElement && elem ) { - for ( j = 0; (matcher = elementMatchers[j]); j++ ) { - if ( matcher( elem, context, xml ) ) { - results.push( elem ); - break; - } - } - if ( outermost ) { - dirruns = dirrunsUnique; - cachedruns = ++superMatcher.el; - } - } - - // Track unmatched elements for set filters - if ( bySet ) { - // They will have gone through all possible matchers - if ( (elem = !matcher && elem) ) { - matchedCount--; - } - - // Lengthen the array for every element, matched or not - if ( seed ) { - unmatched.push( elem ); - } - } - } - - // Apply set filters to unmatched elements - matchedCount += i; - if ( bySet && i !== matchedCount ) { - for ( j = 0; (matcher = setMatchers[j]); j++ ) { - matcher( unmatched, setMatched, context, xml ); - } - - if ( seed ) { - // Reintegrate element matches to eliminate the need for sorting - if ( matchedCount > 0 ) { - while ( i-- ) { - if ( !(unmatched[i] || setMatched[i]) ) { - setMatched[i] = pop.call( results ); - } - } - } - - // Discard index placeholder values to get only actual matches - setMatched = condense( setMatched ); - } - - // Add matches to results - push.apply( results, setMatched ); - - // Seedless set matches succeeding multiple successful matchers stipulate sorting - if ( outermost && !seed && setMatched.length > 0 && - ( matchedCount + setMatchers.length ) > 1 ) { - - Sizzle.uniqueSort( results ); - } - } - - // Override manipulation of globals by nested matchers - if ( outermost ) { - dirruns = dirrunsUnique; - outermostContext = contextBackup; - } - - return unmatched; - }; - - superMatcher.el = 0; - return bySet ? - markFunction( superMatcher ) : - superMatcher; -} - -compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { - var i, - setMatchers = [], - elementMatchers = [], - cached = compilerCache[ expando ][ selector ]; - - if ( !cached ) { - // Generate a function of recursive functions that can be used to check each element - if ( !group ) { - group = tokenize( selector ); - } - i = group.length; - while ( i-- ) { - cached = matcherFromTokens( group[i] ); - if ( cached[ expando ] ) { - setMatchers.push( cached ); - } else { - elementMatchers.push( cached ); - } - } - - // Cache the compiled function - cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); - } - return cached; -}; - -function multipleContexts( selector, contexts, results, seed ) { - var i = 0, - len = contexts.length; - for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results, seed ); - } - return results; -} - -function select( selector, context, results, seed, xml ) { - var i, tokens, token, type, find, - match = tokenize( selector ), - j = match.length; - - if ( !seed ) { - // Try to minimize operations if there is only one group - if ( match.length === 1 ) { - - // Take a shortcut and set the context if the root selector is an ID - tokens = match[0] = match[0].slice( 0 ); - if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && - context.nodeType === 9 && !xml && - Expr.relative[ tokens[1].type ] ) { - - context = Expr.find["ID"]( token.matches[0].replace( rbackslash, "" ), context, xml )[0]; - if ( !context ) { - return results; - } - - selector = selector.slice( tokens.shift().length ); - } - - // Fetch a seed set for right-to-left matching - for ( i = matchExpr["POS"].test( selector ) ? -1 : tokens.length - 1; i >= 0; i-- ) { - token = tokens[i]; - - // Abort if we hit a combinator - if ( Expr.relative[ (type = token.type) ] ) { - break; - } - if ( (find = Expr.find[ type ]) ) { - // Search, expanding context for leading sibling combinators - if ( (seed = find( - token.matches[0].replace( rbackslash, "" ), - rsibling.test( tokens[0].type ) && context.parentNode || context, - xml - )) ) { - - // If seed is empty or no tokens remain, we can return early - tokens.splice( i, 1 ); - selector = seed.length && tokens.join(""); - if ( !selector ) { - push.apply( results, slice.call( seed, 0 ) ); - return results; - } - - break; - } - } - } - } - } - - // Compile and execute a filtering function - // Provide `match` to avoid retokenization if we modified the selector above - compile( selector, match )( - seed, - context, - xml, - results, - rsibling.test( selector ) - ); - return results; -} - -if ( document.querySelectorAll ) { - (function() { - var disconnectedMatch, - oldSelect = select, - rescape = /'|\\/g, - rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g, - - // qSa(:focus) reports false when true (Chrome 21), - // A support test would require too much code (would include document ready) - rbuggyQSA = [":focus"], - - // matchesSelector(:focus) reports false when true (Chrome 21), - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - // A support test would require too much code (would include document ready) - // just skip matchesSelector for :active - rbuggyMatches = [ ":active", ":focus" ], - matches = docElem.matchesSelector || - docElem.mozMatchesSelector || - docElem.webkitMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector; - - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert(function( div ) { - // Select is set to empty string on purpose - // This is to test IE's treatment of not explictly - // setting a boolean content attribute, - // since its presence should be enough - // http://bugs.jquery.com/ticket/12359 - div.innerHTML = ""; - - // IE8 - Some boolean attributes are not treated correctly - if ( !div.querySelectorAll("[selected]").length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" ); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here (do not put tests after this one) - if ( !div.querySelectorAll(":checked").length ) { - rbuggyQSA.push(":checked"); - } - }); - - assert(function( div ) { - - // Opera 10-12/IE9 - ^= $= *= and empty values - // Should not select anything - div.innerHTML = "

"; - if ( div.querySelectorAll("[test^='']").length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" ); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here (do not put tests after this one) - div.innerHTML = ""; - if ( !div.querySelectorAll(":enabled").length ) { - rbuggyQSA.push(":enabled", ":disabled"); - } - }); - - // rbuggyQSA always contains :focus, so no need for a length check - rbuggyQSA = /* rbuggyQSA.length && */ new RegExp( rbuggyQSA.join("|") ); - - select = function( selector, context, results, seed, xml ) { - // Only use querySelectorAll when not filtering, - // when this is not xml, - // and when no QSA bugs apply - if ( !seed && !xml && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { - var groups, i, - old = true, - nid = expando, - newContext = context, - newSelector = context.nodeType === 9 && selector; - - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - groups = tokenize( selector ); - - if ( (old = context.getAttribute("id")) ) { - nid = old.replace( rescape, "\\$&" ); - } else { - context.setAttribute( "id", nid ); - } - nid = "[id='" + nid + "'] "; - - i = groups.length; - while ( i-- ) { - groups[i] = nid + groups[i].join(""); - } - newContext = rsibling.test( selector ) && context.parentNode || context; - newSelector = groups.join(","); - } - - if ( newSelector ) { - try { - push.apply( results, slice.call( newContext.querySelectorAll( - newSelector - ), 0 ) ); - return results; - } catch(qsaError) { - } finally { - if ( !old ) { - context.removeAttribute("id"); - } - } - } - } - - return oldSelect( selector, context, results, seed, xml ); - }; - - if ( matches ) { - assert(function( div ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - disconnectedMatch = matches.call( div, "div" ); - - // This should fail with an exception - // Gecko does not error, returns false instead - try { - matches.call( div, "[test!='']:sizzle" ); - rbuggyMatches.push( "!=", pseudos ); - } catch ( e ) {} - }); - - // rbuggyMatches always contains :active and :focus, so no need for a length check - rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join("|") ); - - Sizzle.matchesSelector = function( elem, expr ) { - // Make sure that attribute selectors are quoted - expr = expr.replace( rattributeQuotes, "='$1']" ); - - // rbuggyMatches always contains :active, so no need for an existence check - if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && (!rbuggyQSA || !rbuggyQSA.test( expr )) ) { - try { - var ret = matches.call( elem, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { - return ret; - } - } catch(e) {} - } - - return Sizzle( expr, null, null, [ elem ] ).length > 0; - }; - } - })(); -} - -// Deprecated -Expr.pseudos["nth"] = Expr.pseudos["eq"]; - -// Back-compat -function setFilters() {} -Expr.filters = setFilters.prototype = Expr.pseudos; -Expr.setFilters = new setFilters(); - +/*! + * Sizzle CSS Selector Engine + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license + * http://sizzlejs.com/ + */ +(function( window, undefined ) { + +var cachedruns, + assertGetIdNotName, + Expr, + getText, + isXML, + contains, + compile, + sortOrder, + hasDuplicate, + outermostContext, + + baseHasDuplicate = true, + strundefined = "undefined", + + expando = ( "sizcache" + Math.random() ).replace( ".", "" ), + + Token = String, + document = window.document, + docElem = document.documentElement, + dirruns = 0, + done = 0, + pop = [].pop, + push = [].push, + slice = [].slice, + // Use a stripped-down indexOf if a native one is unavailable + indexOf = [].indexOf || function( elem ) { + var i = 0, + len = this.length; + for ( ; i < len; i++ ) { + if ( this[i] === elem ) { + return i; + } + } + return -1; + }, + + // Augment a function for special use by Sizzle + markFunction = function( fn, value ) { + fn[ expando ] = value == null || value; + return fn; + }, + + createCache = function() { + var cache = {}, + keys = []; + + return markFunction(function( key, value ) { + // Only keep the most recent entries + if ( keys.push( key ) > Expr.cacheLength ) { + delete cache[ keys.shift() ]; + } + + return (cache[ key ] = value); + }, cache ); + }, + + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + + // Regex + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors) + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors + operators = "([*^$|!~]?=)", + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + + "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", + + // Prefer arguments not in parens/brackets, + // then attribute selectors and non-pseudos (denoted by :), + // then anything else + // These preferences are here to reduce the number of selectors + // needing tokenize in the PSEUDO preFilter + pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)", + + // For matchExpr.POS and matchExpr.needsContext + pos = ":(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ), + rpseudo = new RegExp( pseudos ), + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/, + + rnot = /^:not/, + rsibling = /[\x20\t\r\n\f]*[+~]/, + rendsWithNot = /:not\($/, + + rheader = /h\d/i, + rinputs = /input|select|textarea|button/i, + + rbackslash = /\\(?!\\)/g, + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "POS": new RegExp( pos, "i" ), + "CHILD": new RegExp( "^:(only|nth|first|last)-child(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + // For use in libraries implementing .is() + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|" + pos, "i" ) + }, + + // Support + + // Used for testing something on an element + assert = function( fn ) { + var div = document.createElement("div"); + + try { + return fn( div ); + } catch (e) { + return false; + } finally { + // release memory in IE + div = null; + } + }, + + // Check if getElementsByTagName("*") returns only elements + assertTagNameNoComments = assert(function( div ) { + div.appendChild( document.createComment("") ); + return !div.getElementsByTagName("*").length; + }), + + // Check if getAttribute returns normalized href attributes + assertHrefNotNormalized = assert(function( div ) { + div.innerHTML = ""; + return div.firstChild && typeof div.firstChild.getAttribute !== strundefined && + div.firstChild.getAttribute("href") === "#"; + }), + + // Check if attributes should be retrieved by attribute nodes + assertAttributes = assert(function( div ) { + div.innerHTML = ""; + var type = typeof div.lastChild.getAttribute("multiple"); + // IE8 returns a string for some attributes even when not present + return type !== "boolean" && type !== "string"; + }), + + // Check if getElementsByClassName can be trusted + assertUsableClassName = assert(function( div ) { + // Opera can't find a second classname (in 9.6) + div.innerHTML = ""; + if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) { + return false; + } + + // Safari 3.2 caches class attributes and doesn't catch changes + div.lastChild.className = "e"; + return div.getElementsByClassName("e").length === 2; + }), + + // Check if getElementById returns elements by name + // Check if getElementsByName privileges form controls or returns elements by ID + assertUsableName = assert(function( div ) { + // Inject content + div.id = expando + 0; + div.innerHTML = "
"; + docElem.insertBefore( div, docElem.firstChild ); + + // Test + var pass = document.getElementsByName && + // buggy browsers will return fewer than the correct 2 + document.getElementsByName( expando ).length === 2 + + // buggy browsers will return more than the correct 0 + document.getElementsByName( expando + 0 ).length; + assertGetIdNotName = !document.getElementById( expando ); + + // Cleanup + docElem.removeChild( div ); + + return pass; + }); + +// If slice is not available, provide a backup +try { + slice.call( docElem.childNodes, 0 )[0].nodeType; +} catch ( e ) { + slice = function( i ) { + var elem, + results = []; + for ( ; (elem = this[i]); i++ ) { + results.push( elem ); + } + return results; + }; +} + +function Sizzle( selector, context, results, seed ) { + results = results || []; + context = context || document; + var match, elem, xml, m, + nodeType = context.nodeType; + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + if ( nodeType !== 1 && nodeType !== 9 ) { + return []; + } + + xml = isXML( context ); + + if ( !xml && !seed ) { + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) { + push.apply( results, slice.call(context.getElementsByClassName( m ), 0) ); + return results; + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed, xml ); +} + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + return Sizzle( expr, null, null, [ elem ] ).length > 0; +}; + +// Returns a function to use in pseudos for input types +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +// Returns a function to use in pseudos for buttons +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +// Returns a function to use in pseudos for positionals +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( nodeType ) { + if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (see #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + } else { + + // If no nodeType, this is expected to be an array + for ( ; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } + return ret; +}; + +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +// Element contains another +contains = Sizzle.contains = docElem.contains ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) ); + } : + docElem.compareDocumentPosition ? + function( a, b ) { + return b && !!( a.compareDocumentPosition( b ) & 16 ); + } : + function( a, b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + return false; + }; + +Sizzle.attr = function( elem, name ) { + var val, + xml = isXML( elem ); + + if ( !xml ) { + name = name.toLowerCase(); + } + if ( (val = Expr.attrHandle[ name ]) ) { + return val( elem ); + } + if ( xml || assertAttributes ) { + return elem.getAttribute( name ); + } + val = elem.getAttributeNode( name ); + return val ? + typeof elem[ name ] === "boolean" ? + elem[ name ] ? name : null : + val.specified ? val.value : null : + null; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + // IE6/7 return a modified href + attrHandle: assertHrefNotNormalized ? + {} : + { + "href": function( elem ) { + return elem.getAttribute( "href", 2 ); + }, + "type": function( elem ) { + return elem.getAttribute("type"); + } + }, + + find: { + "ID": assertGetIdNotName ? + function( id, context, xml ) { + if ( typeof context.getElementById !== strundefined && !xml ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + } : + function( id, context, xml ) { + if ( typeof context.getElementById !== strundefined && !xml ) { + var m = context.getElementById( id ); + + return m ? + m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ? + [m] : + undefined : + []; + } + }, + + "TAG": assertTagNameNoComments ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + var elem, + tmp = [], + i = 0; + + for ( ; (elem = results[i]); i++ ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }, + + "NAME": assertUsableName && function( tag, context ) { + if ( typeof context.getElementsByName !== strundefined ) { + return context.getElementsByName( name ); + } + }, + + "CLASS": assertUsableClassName && function( className, context, xml ) { + if ( typeof context.getElementsByClassName !== strundefined && !xml ) { + return context.getElementsByClassName( className ); + } + } + }, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( rbackslash, "" ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[4] || match[5] || "" ).replace( rbackslash, "" ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 3 xn-component of xn+y argument ([+-]?\d*n|) + 4 sign of xn-component + 5 x of xn-component + 6 sign of y-component + 7 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1] === "nth" ) { + // nth-child requires argument + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === "even" || match[2] === "odd" ) ); + match[4] = +( ( match[6] + match[7] ) || match[2] === "odd" ); + + // other types prohibit arguments + } else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var unquoted, excess; + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + if ( match[3] ) { + match[2] = match[3]; + } else if ( (unquoted = match[4]) ) { + // Only check arguments that contain a pseudo + if ( rpseudo.test(unquoted) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + unquoted = unquoted.slice( 0, excess ); + match[0] = match[0].slice( 0, excess ); + } + match[2] = unquoted; + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + "ID": assertGetIdNotName ? + function( id ) { + id = id.replace( rbackslash, "" ); + return function( elem ) { + return elem.getAttribute("id") === id; + }; + } : + function( id ) { + id = id.replace( rbackslash, "" ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === id; + }; + }, + + "TAG": function( nodeName ) { + if ( nodeName === "*" ) { + return function() { return true; }; + } + nodeName = nodeName.replace( rbackslash, "" ).toLowerCase(); + + return function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ expando ][ className ]; + if ( !pattern ) { + pattern = classCache( className, new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)") ); + } + return function( elem ) { + return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" ); + }; + }, + + "ATTR": function( name, operator, check ) { + return function( elem, context ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.substr( result.length - check.length ) === check : + operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.substr( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, argument, first, last ) { + + if ( type === "nth" ) { + return function( elem ) { + var node, diff, + parent = elem.parentNode; + + if ( first === 1 && last === 0 ) { + return true; + } + + if ( parent ) { + diff = 0; + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + diff++; + if ( elem === node ) { + break; + } + } + } + } + + // Incorporate the offset (or cast to NaN), then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + }; + } + + return function( elem ) { + var node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + /* falls through */ + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), + // not comment, processing instructions, or others + // Thanks to Diego Perini for the nodeName shortcut + // Greater than "@" means alpha characters (specifically not starting with "#" or "?") + var nodeType; + elem = elem.firstChild; + while ( elem ) { + if ( elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) { + return false; + } + elem = elem.nextSibling; + } + return true; + }, + + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "text": function( elem ) { + var type, attr; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && + (type = elem.type) === "text" && + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type ); + }, + + // Input types + "radio": createInputPseudo("radio"), + "checkbox": createInputPseudo("checkbox"), + "file": createInputPseudo("file"), + "password": createInputPseudo("password"), + "image": createInputPseudo("image"), + + "submit": createButtonPseudo("submit"), + "reset": createButtonPseudo("reset"), + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "focus": function( elem ) { + var doc = elem.ownerDocument; + return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href); + }, + + "active": function( elem ) { + return elem === elem.ownerDocument.activeElement; + }, + + // Positional types + "first": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length, argument ) { + for ( var i = 0; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length, argument ) { + for ( var i = 1; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + for ( var i = argument < 0 ? argument + length : argument; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + for ( var i = argument < 0 ? argument + length : argument; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +function siblingCheck( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; +} + +sortOrder = docElem.compareDocumentPosition ? + function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + return ( !a.compareDocumentPosition || !b.compareDocumentPosition ? + a.compareDocumentPosition : + a.compareDocumentPosition(b) & 4 + ) ? -1 : 1; + } : + function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + +// Always assume the presence of duplicates if sort doesn't +// pass them to our comparison function (as in Google Chrome). +[0, 0].sort( sortOrder ); +baseHasDuplicate = !hasDuplicate; + +// Document sorting and removing duplicates +Sizzle.uniqueSort = function( results ) { + var elem, + i = 1; + + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( ; (elem = results[i]); i++ ) { + if ( elem === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + + return results; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +function tokenize( selector, parseOnly ) { + var matched, match, tokens, type, soFar, groups, preFilters, + cached = tokenCache[ expando ][ selector ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + soFar = soFar.slice( match[0].length ); + } + groups.push( tokens = [] ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + tokens.push( matched = new Token( match.shift() ) ); + soFar = soFar.slice( matched.length ); + + // Cast descendant combinators to space + matched.type = match[0].replace( rtrim, " " ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + // The last two arguments here are (context, xml) for backCompat + (match = preFilters[ type ]( match, document, true ))) ) { + + tokens.push( matched = new Token( match.shift() ) ); + soFar = soFar.slice( matched.length ); + matched.type = type; + matched.matches = match; + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && combinator.dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( checkNonElements || elem.nodeType === 1 ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( !xml ) { + var cache, + dirkey = dirruns + " " + doneName + " ", + cachedkey = dirkey + cachedruns; + while ( (elem = elem[ dir ]) ) { + if ( checkNonElements || elem.nodeType === 1 ) { + if ( (cache = elem[ expando ]) === cachedkey ) { + return elem.sizset; + } else if ( typeof cache === "string" && cache.indexOf(dirkey) === 0 ) { + if ( elem.sizset ) { + return elem; + } + } else { + elem[ expando ] = cachedkey; + if ( matcher( elem, context, xml ) ) { + elem.sizset = true; + return elem; + } + elem.sizset = false; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( checkNonElements || elem.nodeType === 1 ) { + if ( matcher( elem, context, xml ) ) { + return elem; + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + // Positional selectors apply to seed elements, so it is invalid to follow them with relative ones + if ( seed && postFinder ) { + return; + } + + var i, elem, postFilterIn, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [], seed ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + postFilterIn = condense( matcherOut, postMap ); + postFilter( postFilterIn, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = postFilterIn.length; + while ( i-- ) { + if ( (elem = postFilterIn[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + // Keep seed and results synchronized + if ( seed ) { + // Ignore postFinder because it can't coexist with seed + i = preFilter && matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + seed[ preMap[i] ] = !(results[ preMap[i] ] = elem); + } + } + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + // The concatenated values are (context, xml) for backCompat + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && tokens.slice( 0, i - 1 ).join("").replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && tokens.join("") + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, expandContext ) { + var elem, j, matcher, + setMatched = [], + matchedCount = 0, + i = "0", + unmatched = seed && [], + outermost = expandContext != null, + contextBackup = outermostContext, + // We must always have either seed elements or context + elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), + // Nested matchers should use non-integer dirruns + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.E); + + if ( outermost ) { + outermostContext = context !== document && context; + cachedruns = superMatcher.el; + } + + // Add elements passing elementMatchers directly to results + for ( ; (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + for ( j = 0; (matcher = elementMatchers[j]); j++ ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + cachedruns = ++superMatcher.el; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + for ( j = 0; (matcher = setMatchers[j]); j++ ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + superMatcher.el = 0; + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ expando ][ selector ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !group ) { + group = tokenize( selector ); + } + i = group.length; + while ( i-- ) { + cached = matcherFromTokens( group[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + } + return cached; +}; + +function multipleContexts( selector, contexts, results, seed ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results, seed ); + } + return results; +} + +function select( selector, context, results, seed, xml ) { + var i, tokens, token, type, find, + match = tokenize( selector ), + j = match.length; + + if ( !seed ) { + // Try to minimize operations if there is only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + context.nodeType === 9 && !xml && + Expr.relative[ tokens[1].type ] ) { + + context = Expr.find["ID"]( token.matches[0].replace( rbackslash, "" ), context, xml )[0]; + if ( !context ) { + return results; + } + + selector = selector.slice( tokens.shift().length ); + } + + // Fetch a seed set for right-to-left matching + for ( i = matchExpr["POS"].test( selector ) ? -1 : tokens.length - 1; i >= 0; i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( rbackslash, "" ), + rsibling.test( tokens[0].type ) && context.parentNode || context, + xml + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && tokens.join(""); + if ( !selector ) { + push.apply( results, slice.call( seed, 0 ) ); + return results; + } + + break; + } + } + } + } + } + + // Compile and execute a filtering function + // Provide `match` to avoid retokenization if we modified the selector above + compile( selector, match )( + seed, + context, + xml, + results, + rsibling.test( selector ) + ); + return results; +} + +if ( document.querySelectorAll ) { + (function() { + var disconnectedMatch, + oldSelect = select, + rescape = /'|\\/g, + rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g, + + // qSa(:focus) reports false when true (Chrome 21), + // A support test would require too much code (would include document ready) + rbuggyQSA = [":focus"], + + // matchesSelector(:focus) reports false when true (Chrome 21), + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + // A support test would require too much code (would include document ready) + // just skip matchesSelector for :active + rbuggyMatches = [ ":active", ":focus" ], + matches = docElem.matchesSelector || + docElem.mozMatchesSelector || + docElem.webkitMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector; + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explictly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = ""; + + // IE8 - Some boolean attributes are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here (do not put tests after this one) + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + + // Opera 10-12/IE9 - ^= $= *= and empty values + // Should not select anything + div.innerHTML = "

"; + if ( div.querySelectorAll("[test^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here (do not put tests after this one) + div.innerHTML = ""; + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push(":enabled", ":disabled"); + } + }); + + // rbuggyQSA always contains :focus, so no need for a length check + rbuggyQSA = /* rbuggyQSA.length && */ new RegExp( rbuggyQSA.join("|") ); + + select = function( selector, context, results, seed, xml ) { + // Only use querySelectorAll when not filtering, + // when this is not xml, + // and when no QSA bugs apply + if ( !seed && !xml && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + var groups, i, + old = true, + nid = expando, + newContext = context, + newSelector = context.nodeType === 9 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + groups[i].join(""); + } + newContext = rsibling.test( selector ) && context.parentNode || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, slice.call( newContext.querySelectorAll( + newSelector + ), 0 ) ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + + return oldSelect( selector, context, results, seed, xml ); + }; + + if ( matches ) { + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + try { + matches.call( div, "[test!='']:sizzle" ); + rbuggyMatches.push( "!=", pseudos ); + } catch ( e ) {} + }); + + // rbuggyMatches always contains :active and :focus, so no need for a length check + rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join("|") ); + + Sizzle.matchesSelector = function( elem, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + // rbuggyMatches always contains :active, so no need for an existence check + if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && (!rbuggyQSA || !rbuggyQSA.test( expr )) ) { + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch(e) {} + } + + return Sizzle( expr, null, null, [ elem ] ).length > 0; + }; + } + })(); +} + +// Deprecated +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Back-compat +function setFilters() {} +Expr.filters = setFilters.prototype = Expr.pseudos; +Expr.setFilters = new setFilters(); + // Override sizzle attribute retrieval Sizzle.attr = jQuery.attr; jQuery.find = Sizzle; @@ -5335,9 +5335,9 @@ jQuery.unique = Sizzle.uniqueSort; jQuery.text = Sizzle.getText; jQuery.isXMLDoc = Sizzle.isXML; jQuery.contains = Sizzle.contains; - - -})( window ); + + +})( window ); var runtil = /Until$/, rparentsprev = /^(?:parents|prev(?:Until|All))/, isSimple = /^.[^:#\[\.,]*$/, From 49f9b849b9c5023f138e8932510b11bfc9765814 Mon Sep 17 00:00:00 2001 From: Trey Hunner Date: Sun, 21 Oct 2012 18:50:03 -0700 Subject: [PATCH 027/151] Remove trailing whitespace and add final newlines --- tests/jquery-1.6.1.js | 106 ++++++++++----------- tests/jquery-1.6.2.js | 110 +++++++++++----------- tests/jquery-1.6.3.js | 108 ++++++++++----------- tests/jquery-1.6.4.js | 108 ++++++++++----------- tests/jquery-1.6.js | 130 +++++++++++++------------- tests/jquery-1.7.1.js | 82 ++++++++-------- tests/jquery-1.7.2.js | 2 +- tests/jquery-1.7.js | 82 ++++++++-------- tests/jquery-1.8.0.js | 2 +- tests/jquery.simulate.js | 4 +- tests/unit/dialog/dialog_tickets.js | 6 +- ui/i18n/jquery.ui.datepicker-ar.js | 2 +- ui/i18n/jquery.ui.datepicker-az.js | 2 +- ui/i18n/jquery.ui.datepicker-bs.js | 10 +- ui/i18n/jquery.ui.datepicker-cy-GB.js | 2 +- ui/i18n/jquery.ui.datepicker-el.js | 2 +- ui/i18n/jquery.ui.datepicker-es.js | 2 +- ui/i18n/jquery.ui.datepicker-et.js | 2 +- ui/i18n/jquery.ui.datepicker-eu.js | 2 +- ui/i18n/jquery.ui.datepicker-fa.js | 6 +- ui/i18n/jquery.ui.datepicker-fr-CH.js | 2 +- ui/i18n/jquery.ui.datepicker-gl.js | 2 +- ui/i18n/jquery.ui.datepicker-hr.js | 2 +- ui/i18n/jquery.ui.datepicker-hy.js | 2 +- ui/i18n/jquery.ui.datepicker-id.js | 2 +- ui/i18n/jquery.ui.datepicker-is.js | 2 +- ui/i18n/jquery.ui.datepicker-ja.js | 2 +- ui/i18n/jquery.ui.datepicker-ko.js | 2 +- ui/i18n/jquery.ui.datepicker-lt.js | 2 +- ui/i18n/jquery.ui.datepicker-lv.js | 2 +- ui/i18n/jquery.ui.datepicker-ml.js | 2 +- ui/i18n/jquery.ui.datepicker-ms.js | 2 +- ui/i18n/jquery.ui.datepicker-nl.js | 2 +- ui/i18n/jquery.ui.datepicker-pt-BR.js | 2 +- ui/i18n/jquery.ui.datepicker-pt.js | 2 +- ui/i18n/jquery.ui.datepicker-ru.js | 2 +- ui/i18n/jquery.ui.datepicker-th.js | 2 +- ui/i18n/jquery.ui.datepicker-tj.js | 2 +- ui/i18n/jquery.ui.datepicker-tr.js | 2 +- ui/i18n/jquery.ui.datepicker-uk.js | 2 +- ui/jquery.ui.datepicker.js | 24 ++--- ui/jquery.ui.draggable.js | 40 ++++---- ui/jquery.ui.effect-highlight.js | 2 +- ui/jquery.ui.mouse.js | 2 +- ui/jquery.ui.resizable.js | 2 +- 45 files changed, 440 insertions(+), 440 deletions(-) diff --git a/tests/jquery-1.6.1.js b/tests/jquery-1.6.1.js index 5d5a1d58ee..33e87732dc 100644 --- a/tests/jquery-1.6.1.js +++ b/tests/jquery-1.6.1.js @@ -1895,11 +1895,11 @@ jQuery.fn.extend({ jQuery.removeAttr( this, name ); }); }, - + prop: function( name, value ) { return jQuery.access( this, name, value, true, jQuery.prop ); }, - + removeProp: function( name ) { name = jQuery.propFix[ name ] || name; return this.each(function() { @@ -2031,7 +2031,7 @@ jQuery.fn.extend({ val: function( value ) { var hooks, ret, elem = this[0]; - + if ( !arguments.length ) { if ( elem ) { hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; @@ -2159,15 +2159,15 @@ jQuery.extend({ height: true, offset: true }, - + attrFix: { // Always normalize to ensure hook usage tabindex: "tabIndex" }, - + attr: function( elem, name, value, pass ) { var nType = elem.nodeType; - + // don't get/set attributes on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return undefined; @@ -2235,7 +2235,7 @@ jQuery.extend({ var propName; if ( elem.nodeType === 1 ) { name = jQuery.attrFix[ name ] || name; - + if ( jQuery.support.getSetAttribute ) { // Use removeAttribute in browsers that support it elem.removeAttribute( name ); @@ -2299,7 +2299,7 @@ jQuery.extend({ frameborder: "frameBorder", contenteditable: "contentEditable" }, - + prop: function( elem, name, value ) { var nType = elem.nodeType; @@ -2313,7 +2313,7 @@ jQuery.extend({ // Try to normalize/fix the name name = notxml && jQuery.propFix[ name ] || name; - + hooks = jQuery.propHooks[ name ]; if ( value !== undefined ) { @@ -2333,7 +2333,7 @@ jQuery.extend({ } } }, - + propHooks: {} }); @@ -2388,7 +2388,7 @@ if ( !jQuery.support.getSetAttribute ) { // propFix is more comprehensive and contains all fixes jQuery.attrFix = jQuery.propFix; - + // Use this for any attribute on a form in IE6/7 formHook = jQuery.attrHooks.name = jQuery.valHooks.button = { get: function( elem, name ) { @@ -2759,7 +2759,7 @@ jQuery.event = { } } }, - + // Events that are safe to short-circuit if no handlers are attached. // Native DOM events should not be added, they may have inline handlers. customEvent: { @@ -2805,7 +2805,7 @@ jQuery.event = { event.exclusive = exclusive; event.namespace = namespaces.join("."); event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)"); - + // triggerHandler() and global events don't bubble or run the default action if ( onlyHandlers || !elem ) { event.preventDefault(); @@ -2896,7 +2896,7 @@ jQuery.event = { jQuery.event.triggered = undefined; } } - + return event.result; }, @@ -3731,7 +3731,7 @@ var Sizzle = function( selector, context, results, seed ) { if ( context.nodeType !== 1 && context.nodeType !== 9 ) { return []; } - + if ( !selector || typeof selector !== "string" ) { return results; } @@ -3741,7 +3741,7 @@ var Sizzle = function( selector, context, results, seed ) { contextXML = Sizzle.isXML( context ), parts = [], soFar = selector; - + // Reset the position of the chunker regexp (start from head) do { chunker.exec( "" ); @@ -3749,9 +3749,9 @@ var Sizzle = function( selector, context, results, seed ) { if ( m ) { soFar = m[3]; - + parts.push( m[1] ); - + if ( m[2] ) { extra = m[3]; break; @@ -3775,7 +3775,7 @@ var Sizzle = function( selector, context, results, seed ) { if ( Expr.relative[ selector ] ) { selector += parts.shift(); } - + set = posProcess( selector, set ); } } @@ -3904,7 +3904,7 @@ Sizzle.find = function( expr, context, isXML ) { for ( var i = 0, l = Expr.order.length; i < l; i++ ) { var match, type = Expr.order[i]; - + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { var left = match[1]; match.splice( 1, 1 ); @@ -4236,7 +4236,7 @@ var Expr = Sizzle.selectors = { ATTR: function( match, curLoop, inplace, result, not, isXML ) { var name = match[1] = match[1].replace( rBackslash, "" ); - + if ( !isXML && Expr.attrMap[name] ) { match[1] = Expr.attrMap[name]; } @@ -4270,7 +4270,7 @@ var Expr = Sizzle.selectors = { } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { return true; } - + return match; }, @@ -4280,7 +4280,7 @@ var Expr = Sizzle.selectors = { return match; } }, - + filters: { enabled: function( elem ) { return elem.disabled === false && elem.type !== "hidden"; @@ -4293,14 +4293,14 @@ var Expr = Sizzle.selectors = { checked: function( elem ) { return elem.checked === true; }, - + selected: function( elem ) { // Accessing this property makes selected-by-default // options in Safari work properly if ( elem.parentNode ) { elem.parentNode.selectedIndex; } - + return elem.selected === true; }, @@ -4322,7 +4322,7 @@ var Expr = Sizzle.selectors = { text: function( elem ) { var attr = elem.getAttribute( "type" ), type = elem.type; - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) // use getAttribute instead to test this case return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); }, @@ -4438,21 +4438,21 @@ var Expr = Sizzle.selectors = { case "only": case "first": while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; + if ( node.nodeType === 1 ) { + return false; } } - if ( type === "first" ) { - return true; + if ( type === "first" ) { + return true; } node = elem; case "last": while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; + if ( node.nodeType === 1 ) { + return false; } } @@ -4465,22 +4465,22 @@ var Expr = Sizzle.selectors = { if ( first === 1 && last === 0 ) { return true; } - + var doneName = match[0], parent = elem.parentNode; - + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { var count = 0; - + for ( node = parent.firstChild; node; node = node.nextSibling ) { if ( node.nodeType === 1 ) { node.nodeIndex = ++count; } - } + } parent.sizcache = doneName; } - + var diff = elem.nodeIndex - last; if ( first === 0 ) { @@ -4499,7 +4499,7 @@ var Expr = Sizzle.selectors = { TAG: function( elem, match ) { return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; }, - + CLASS: function( elem, match ) { return (" " + (elem.className || elem.getAttribute("class")) + " ") .indexOf( match ) > -1; @@ -4565,7 +4565,7 @@ var makeArray = function( array, results ) { results.push.apply( results, array ); return results; } - + return array; }; @@ -4817,7 +4817,7 @@ if ( document.querySelectorAll ) { if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { return; } - + Sizzle = function( query, context, extra, seed ) { context = context || document; @@ -4826,24 +4826,24 @@ if ( document.querySelectorAll ) { if ( !seed && !Sizzle.isXML(context) ) { // See if we find a selector to speed up var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); - + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { // Speed-up: Sizzle("TAG") if ( match[1] ) { return makeArray( context.getElementsByTagName( query ), extra ); - + // Speed-up: Sizzle(".CLASS") } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { return makeArray( context.getElementsByClassName( match[2] ), extra ); } } - + if ( context.nodeType === 9 ) { // Speed-up: Sizzle("body") // The body element only exists once, optimize finding it if ( query === "body" && context.body ) { return makeArray( [ context.body ], extra ); - + // Speed-up: Sizzle("#ID") } else if ( match && match[3] ) { var elem = context.getElementById( match[3] ); @@ -4856,12 +4856,12 @@ if ( document.querySelectorAll ) { if ( elem.id === match[3] ) { return makeArray( [ elem ], extra ); } - + } else { return makeArray( [], extra ); } } - + try { return makeArray( context.querySelectorAll(query), extra ); } catch(qsaError) {} @@ -4899,7 +4899,7 @@ if ( document.querySelectorAll ) { } } } - + return oldSizzle(query, context, extra, seed); }; @@ -4926,7 +4926,7 @@ if ( document.querySelectorAll ) { // This should fail with an exception // Gecko does not error, returns false instead matches.call( document.documentElement, "[test!='']:sizzle" ); - + } catch( pseudoError ) { pseudoWorks = true; } @@ -4936,7 +4936,7 @@ if ( document.querySelectorAll ) { expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); if ( !Sizzle.isXML( node ) ) { - try { + try { if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { var ret = matches.call( node, expr ); @@ -4973,7 +4973,7 @@ if ( document.querySelectorAll ) { if ( div.getElementsByClassName("e").length === 1 ) { return; } - + Expr.order.splice(1, 0, "CLASS"); Expr.find.CLASS = function( match, context, isXML ) { if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { @@ -5024,7 +5024,7 @@ function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { if ( elem ) { var match = false; - + elem = elem[dir]; while ( elem ) { @@ -5077,7 +5077,7 @@ if ( document.documentElement.contains ) { Sizzle.isXML = function( elem ) { // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) + // (such as loading iframes in IE - #4833) var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; @@ -5198,7 +5198,7 @@ jQuery.fn.extend({ closest: function( selectors, context ) { var ret = [], i, l, cur = this[0]; - + // Array if ( jQuery.isArray( selectors ) ) { var match, selector, diff --git a/tests/jquery-1.6.2.js b/tests/jquery-1.6.2.js index f3201aacb6..fc5a1d74d3 100644 --- a/tests/jquery-1.6.2.js +++ b/tests/jquery-1.6.2.js @@ -1511,7 +1511,7 @@ jQuery.extend({ return thisCache[ internalKey ] && thisCache[ internalKey ].events; } - return getByName ? + return getByName ? // Check for both converted-to-camel and non-converted data property names thisCache[ jQuery.camelCase( name ) ] || thisCache[ name ] : thisCache; @@ -1923,11 +1923,11 @@ jQuery.fn.extend({ jQuery.removeAttr( this, name ); }); }, - + prop: function( name, value ) { return jQuery.access( this, name, value, true, jQuery.prop ); }, - + removeProp: function( name ) { name = jQuery.propFix[ name ] || name; return this.each(function() { @@ -2060,7 +2060,7 @@ jQuery.fn.extend({ val: function( value ) { var hooks, ret, elem = this[0]; - + if ( !arguments.length ) { if ( elem ) { hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; @@ -2071,9 +2071,9 @@ jQuery.fn.extend({ ret = elem.value; - return typeof ret === "string" ? + return typeof ret === "string" ? // handle most common string cases - ret.replace(rreturn, "") : + ret.replace(rreturn, "") : // handle cases where value is null/undef or number ret == null ? "" : ret; } @@ -2194,15 +2194,15 @@ jQuery.extend({ height: true, offset: true }, - + attrFix: { // Always normalize to ensure hook usage tabindex: "tabIndex" }, - + attr: function( elem, name, value, pass ) { var nType = elem.nodeType; - + // don't get/set attributes on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return undefined; @@ -2273,7 +2273,7 @@ jQuery.extend({ var propName; if ( elem.nodeType === 1 ) { name = jQuery.attrFix[ name ] || name; - + if ( jQuery.support.getSetAttribute ) { // Use removeAttribute in browsers that support it elem.removeAttribute( name ); @@ -2356,7 +2356,7 @@ jQuery.extend({ frameborder: "frameBorder", contenteditable: "contentEditable" }, - + prop: function( elem, name, value ) { var nType = elem.nodeType; @@ -2391,7 +2391,7 @@ jQuery.extend({ } } }, - + propHooks: {} }); @@ -2428,7 +2428,7 @@ if ( !jQuery.support.getSetAttribute ) { // propFix is more comprehensive and contains all fixes jQuery.attrFix = jQuery.propFix; - + // Use this for any attribute on a form in IE6/7 formHook = jQuery.attrHooks.name = jQuery.attrHooks.title = jQuery.valHooks.button = { get: function( elem, name ) { @@ -2798,7 +2798,7 @@ jQuery.event = { } } }, - + // Events that are safe to short-circuit if no handlers are attached. // Native DOM events should not be added, they may have inline handlers. customEvent: { @@ -2844,7 +2844,7 @@ jQuery.event = { event.exclusive = exclusive; event.namespace = namespaces.join("."); event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)"); - + // triggerHandler() and global events don't bubble or run the default action if ( onlyHandlers || !elem ) { event.preventDefault(); @@ -2935,7 +2935,7 @@ jQuery.event = { jQuery.event.triggered = undefined; } } - + return event.result; }, @@ -3763,7 +3763,7 @@ var Sizzle = function( selector, context, results, seed ) { if ( context.nodeType !== 1 && context.nodeType !== 9 ) { return []; } - + if ( !selector || typeof selector !== "string" ) { return results; } @@ -3773,7 +3773,7 @@ var Sizzle = function( selector, context, results, seed ) { contextXML = Sizzle.isXML( context ), parts = [], soFar = selector; - + // Reset the position of the chunker regexp (start from head) do { chunker.exec( "" ); @@ -3781,9 +3781,9 @@ var Sizzle = function( selector, context, results, seed ) { if ( m ) { soFar = m[3]; - + parts.push( m[1] ); - + if ( m[2] ) { extra = m[3]; break; @@ -3807,7 +3807,7 @@ var Sizzle = function( selector, context, results, seed ) { if ( Expr.relative[ selector ] ) { selector += parts.shift(); } - + set = posProcess( selector, set ); } } @@ -3936,7 +3936,7 @@ Sizzle.find = function( expr, context, isXML ) { for ( var i = 0, l = Expr.order.length; i < l; i++ ) { var match, type = Expr.order[i]; - + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { var left = match[1]; match.splice( 1, 1 ); @@ -4268,7 +4268,7 @@ var Expr = Sizzle.selectors = { ATTR: function( match, curLoop, inplace, result, not, isXML ) { var name = match[1] = match[1].replace( rBackslash, "" ); - + if ( !isXML && Expr.attrMap[name] ) { match[1] = Expr.attrMap[name]; } @@ -4302,7 +4302,7 @@ var Expr = Sizzle.selectors = { } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { return true; } - + return match; }, @@ -4312,7 +4312,7 @@ var Expr = Sizzle.selectors = { return match; } }, - + filters: { enabled: function( elem ) { return elem.disabled === false && elem.type !== "hidden"; @@ -4325,14 +4325,14 @@ var Expr = Sizzle.selectors = { checked: function( elem ) { return elem.checked === true; }, - + selected: function( elem ) { // Accessing this property makes selected-by-default // options in Safari work properly if ( elem.parentNode ) { elem.parentNode.selectedIndex; } - + return elem.selected === true; }, @@ -4354,7 +4354,7 @@ var Expr = Sizzle.selectors = { text: function( elem ) { var attr = elem.getAttribute( "type" ), type = elem.type; - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) // use getAttribute instead to test this case return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); }, @@ -4470,21 +4470,21 @@ var Expr = Sizzle.selectors = { case "only": case "first": while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; + if ( node.nodeType === 1 ) { + return false; } } - if ( type === "first" ) { - return true; + if ( type === "first" ) { + return true; } node = elem; case "last": while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; + if ( node.nodeType === 1 ) { + return false; } } @@ -4497,22 +4497,22 @@ var Expr = Sizzle.selectors = { if ( first === 1 && last === 0 ) { return true; } - + var doneName = match[0], parent = elem.parentNode; - + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { var count = 0; - + for ( node = parent.firstChild; node; node = node.nextSibling ) { if ( node.nodeType === 1 ) { node.nodeIndex = ++count; } - } + } parent.sizcache = doneName; } - + var diff = elem.nodeIndex - last; if ( first === 0 ) { @@ -4531,7 +4531,7 @@ var Expr = Sizzle.selectors = { TAG: function( elem, match ) { return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; }, - + CLASS: function( elem, match ) { return (" " + (elem.className || elem.getAttribute("class")) + " ") .indexOf( match ) > -1; @@ -4597,7 +4597,7 @@ var makeArray = function( array, results ) { results.push.apply( results, array ); return results; } - + return array; }; @@ -4849,7 +4849,7 @@ if ( document.querySelectorAll ) { if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { return; } - + Sizzle = function( query, context, extra, seed ) { context = context || document; @@ -4858,24 +4858,24 @@ if ( document.querySelectorAll ) { if ( !seed && !Sizzle.isXML(context) ) { // See if we find a selector to speed up var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); - + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { // Speed-up: Sizzle("TAG") if ( match[1] ) { return makeArray( context.getElementsByTagName( query ), extra ); - + // Speed-up: Sizzle(".CLASS") } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { return makeArray( context.getElementsByClassName( match[2] ), extra ); } } - + if ( context.nodeType === 9 ) { // Speed-up: Sizzle("body") // The body element only exists once, optimize finding it if ( query === "body" && context.body ) { return makeArray( [ context.body ], extra ); - + // Speed-up: Sizzle("#ID") } else if ( match && match[3] ) { var elem = context.getElementById( match[3] ); @@ -4888,12 +4888,12 @@ if ( document.querySelectorAll ) { if ( elem.id === match[3] ) { return makeArray( [ elem ], extra ); } - + } else { return makeArray( [], extra ); } } - + try { return makeArray( context.querySelectorAll(query), extra ); } catch(qsaError) {} @@ -4931,7 +4931,7 @@ if ( document.querySelectorAll ) { } } } - + return oldSizzle(query, context, extra, seed); }; @@ -4958,7 +4958,7 @@ if ( document.querySelectorAll ) { // This should fail with an exception // Gecko does not error, returns false instead matches.call( document.documentElement, "[test!='']:sizzle" ); - + } catch( pseudoError ) { pseudoWorks = true; } @@ -4968,7 +4968,7 @@ if ( document.querySelectorAll ) { expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); if ( !Sizzle.isXML( node ) ) { - try { + try { if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { var ret = matches.call( node, expr ); @@ -5005,7 +5005,7 @@ if ( document.querySelectorAll ) { if ( div.getElementsByClassName("e").length === 1 ) { return; } - + Expr.order.splice(1, 0, "CLASS"); Expr.find.CLASS = function( match, context, isXML ) { if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { @@ -5056,7 +5056,7 @@ function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { if ( elem ) { var match = false; - + elem = elem[dir]; while ( elem ) { @@ -5109,7 +5109,7 @@ if ( document.documentElement.contains ) { Sizzle.isXML = function( elem ) { // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) + // (such as loading iframes in IE - #4833) var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; @@ -5230,7 +5230,7 @@ jQuery.fn.extend({ closest: function( selectors, context ) { var ret = [], i, l, cur = this[0]; - + // Array if ( jQuery.isArray( selectors ) ) { var match, selector, diff --git a/tests/jquery-1.6.3.js b/tests/jquery-1.6.3.js index 792e62f490..f69fd06b0a 100644 --- a/tests/jquery-1.6.3.js +++ b/tests/jquery-1.6.3.js @@ -1961,11 +1961,11 @@ jQuery.fn.extend({ jQuery.removeAttr( this, name ); }); }, - + prop: function( name, value ) { return jQuery.access( this, name, value, true, jQuery.prop ); }, - + removeProp: function( name ) { name = jQuery.propFix[ name ] || name; return this.each(function() { @@ -2098,7 +2098,7 @@ jQuery.fn.extend({ val: function( value ) { var hooks, ret, elem = this[0]; - + if ( !arguments.length ) { if ( elem ) { hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; @@ -2109,9 +2109,9 @@ jQuery.fn.extend({ ret = elem.value; - return typeof ret === "string" ? + return typeof ret === "string" ? // handle most common string cases - ret.replace(rreturn, "") : + ret.replace(rreturn, "") : // handle cases where value is null/undef or number ret == null ? "" : ret; } @@ -2232,15 +2232,15 @@ jQuery.extend({ height: true, offset: true }, - + attrFix: { // Always normalize to ensure hook usage tabindex: "tabIndex" }, - + attr: function( elem, name, value, pass ) { var nType = elem.nodeType; - + // don't get/set attributes on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return undefined; @@ -2373,7 +2373,7 @@ jQuery.extend({ frameborder: "frameBorder", contenteditable: "contentEditable" }, - + prop: function( elem, name, value ) { var nType = elem.nodeType; @@ -2408,7 +2408,7 @@ jQuery.extend({ } } }, - + propHooks: { tabIndex: { get: function( elem ) { @@ -2461,7 +2461,7 @@ boolHook = { // IE6/7 do not support getting/setting some attributes with get/setAttribute if ( !jQuery.support.getSetAttribute ) { - + // Use this for any attribute in IE6/7 // This fixes almost every IE6/7 issue nodeHook = jQuery.valHooks.button = { @@ -2833,7 +2833,7 @@ jQuery.event = { } } }, - + // Events that are safe to short-circuit if no handlers are attached. // Native DOM events should not be added, they may have inline handlers. customEvent: { @@ -2879,7 +2879,7 @@ jQuery.event = { event.exclusive = exclusive; event.namespace = namespaces.join("."); event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)"); - + // triggerHandler() and global events don't bubble or run the default action if ( onlyHandlers || !elem ) { event.preventDefault(); @@ -2970,7 +2970,7 @@ jQuery.event = { jQuery.event.triggered = undefined; } } - + return event.result; }, @@ -3799,7 +3799,7 @@ var Sizzle = function( selector, context, results, seed ) { if ( context.nodeType !== 1 && context.nodeType !== 9 ) { return []; } - + if ( !selector || typeof selector !== "string" ) { return results; } @@ -3809,7 +3809,7 @@ var Sizzle = function( selector, context, results, seed ) { contextXML = Sizzle.isXML( context ), parts = [], soFar = selector; - + // Reset the position of the chunker regexp (start from head) do { chunker.exec( "" ); @@ -3817,9 +3817,9 @@ var Sizzle = function( selector, context, results, seed ) { if ( m ) { soFar = m[3]; - + parts.push( m[1] ); - + if ( m[2] ) { extra = m[3]; break; @@ -3843,7 +3843,7 @@ var Sizzle = function( selector, context, results, seed ) { if ( Expr.relative[ selector ] ) { selector += parts.shift(); } - + set = posProcess( selector, set ); } } @@ -3972,7 +3972,7 @@ Sizzle.find = function( expr, context, isXML ) { for ( var i = 0, l = Expr.order.length; i < l; i++ ) { var match, type = Expr.order[i]; - + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { var left = match[1]; match.splice( 1, 1 ); @@ -4304,7 +4304,7 @@ var Expr = Sizzle.selectors = { ATTR: function( match, curLoop, inplace, result, not, isXML ) { var name = match[1] = match[1].replace( rBackslash, "" ); - + if ( !isXML && Expr.attrMap[name] ) { match[1] = Expr.attrMap[name]; } @@ -4338,7 +4338,7 @@ var Expr = Sizzle.selectors = { } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { return true; } - + return match; }, @@ -4348,7 +4348,7 @@ var Expr = Sizzle.selectors = { return match; } }, - + filters: { enabled: function( elem ) { return elem.disabled === false && elem.type !== "hidden"; @@ -4361,14 +4361,14 @@ var Expr = Sizzle.selectors = { checked: function( elem ) { return elem.checked === true; }, - + selected: function( elem ) { // Accessing this property makes selected-by-default // options in Safari work properly if ( elem.parentNode ) { elem.parentNode.selectedIndex; } - + return elem.selected === true; }, @@ -4390,7 +4390,7 @@ var Expr = Sizzle.selectors = { text: function( elem ) { var attr = elem.getAttribute( "type" ), type = elem.type; - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) // use getAttribute instead to test this case return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); }, @@ -4506,21 +4506,21 @@ var Expr = Sizzle.selectors = { case "only": case "first": while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; + if ( node.nodeType === 1 ) { + return false; } } - if ( type === "first" ) { - return true; + if ( type === "first" ) { + return true; } node = elem; case "last": while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; + if ( node.nodeType === 1 ) { + return false; } } @@ -4533,22 +4533,22 @@ var Expr = Sizzle.selectors = { if ( first === 1 && last === 0 ) { return true; } - + var doneName = match[0], parent = elem.parentNode; - + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { var count = 0; - + for ( node = parent.firstChild; node; node = node.nextSibling ) { if ( node.nodeType === 1 ) { node.nodeIndex = ++count; } - } + } parent.sizcache = doneName; } - + var diff = elem.nodeIndex - last; if ( first === 0 ) { @@ -4567,7 +4567,7 @@ var Expr = Sizzle.selectors = { TAG: function( elem, match ) { return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; }, - + CLASS: function( elem, match ) { return (" " + (elem.className || elem.getAttribute("class")) + " ") .indexOf( match ) > -1; @@ -4633,7 +4633,7 @@ var makeArray = function( array, results ) { results.push.apply( results, array ); return results; } - + return array; }; @@ -4885,7 +4885,7 @@ if ( document.querySelectorAll ) { if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { return; } - + Sizzle = function( query, context, extra, seed ) { context = context || document; @@ -4894,24 +4894,24 @@ if ( document.querySelectorAll ) { if ( !seed && !Sizzle.isXML(context) ) { // See if we find a selector to speed up var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); - + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { // Speed-up: Sizzle("TAG") if ( match[1] ) { return makeArray( context.getElementsByTagName( query ), extra ); - + // Speed-up: Sizzle(".CLASS") } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { return makeArray( context.getElementsByClassName( match[2] ), extra ); } } - + if ( context.nodeType === 9 ) { // Speed-up: Sizzle("body") // The body element only exists once, optimize finding it if ( query === "body" && context.body ) { return makeArray( [ context.body ], extra ); - + // Speed-up: Sizzle("#ID") } else if ( match && match[3] ) { var elem = context.getElementById( match[3] ); @@ -4924,12 +4924,12 @@ if ( document.querySelectorAll ) { if ( elem.id === match[3] ) { return makeArray( [ elem ], extra ); } - + } else { return makeArray( [], extra ); } } - + try { return makeArray( context.querySelectorAll(query), extra ); } catch(qsaError) {} @@ -4967,7 +4967,7 @@ if ( document.querySelectorAll ) { } } } - + return oldSizzle(query, context, extra, seed); }; @@ -4994,7 +4994,7 @@ if ( document.querySelectorAll ) { // This should fail with an exception // Gecko does not error, returns false instead matches.call( document.documentElement, "[test!='']:sizzle" ); - + } catch( pseudoError ) { pseudoWorks = true; } @@ -5004,7 +5004,7 @@ if ( document.querySelectorAll ) { expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); if ( !Sizzle.isXML( node ) ) { - try { + try { if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { var ret = matches.call( node, expr ); @@ -5041,7 +5041,7 @@ if ( document.querySelectorAll ) { if ( div.getElementsByClassName("e").length === 1 ) { return; } - + Expr.order.splice(1, 0, "CLASS"); Expr.find.CLASS = function( match, context, isXML ) { if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { @@ -5092,7 +5092,7 @@ function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { if ( elem ) { var match = false; - + elem = elem[dir]; while ( elem ) { @@ -5145,7 +5145,7 @@ if ( document.documentElement.contains ) { Sizzle.isXML = function( elem ) { // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) + // (such as loading iframes in IE - #4833) var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; @@ -5266,7 +5266,7 @@ jQuery.fn.extend({ closest: function( selectors, context ) { var ret = [], i, l, cur = this[0]; - + // Array if ( jQuery.isArray( selectors ) ) { var match, selector, @@ -6718,7 +6718,7 @@ var r20 = /%20/g, // Document location segments ajaxLocParts, - + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression allTypes = ["*/"] + ["*"]; diff --git a/tests/jquery-1.6.4.js b/tests/jquery-1.6.4.js index 11e6d06796..5ccaf5b8ee 100644 --- a/tests/jquery-1.6.4.js +++ b/tests/jquery-1.6.4.js @@ -1962,11 +1962,11 @@ jQuery.fn.extend({ jQuery.removeAttr( this, name ); }); }, - + prop: function( name, value ) { return jQuery.access( this, name, value, true, jQuery.prop ); }, - + removeProp: function( name ) { name = jQuery.propFix[ name ] || name; return this.each(function() { @@ -2099,7 +2099,7 @@ jQuery.fn.extend({ val: function( value ) { var hooks, ret, elem = this[0]; - + if ( !arguments.length ) { if ( elem ) { hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; @@ -2110,9 +2110,9 @@ jQuery.fn.extend({ ret = elem.value; - return typeof ret === "string" ? + return typeof ret === "string" ? // handle most common string cases - ret.replace(rreturn, "") : + ret.replace(rreturn, "") : // handle cases where value is null/undef or number ret == null ? "" : ret; } @@ -2233,15 +2233,15 @@ jQuery.extend({ height: true, offset: true }, - + attrFix: { // Always normalize to ensure hook usage tabindex: "tabIndex" }, - + attr: function( elem, name, value, pass ) { var nType = elem.nodeType; - + // don't get/set attributes on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return undefined; @@ -2374,7 +2374,7 @@ jQuery.extend({ frameborder: "frameBorder", contenteditable: "contentEditable" }, - + prop: function( elem, name, value ) { var nType = elem.nodeType; @@ -2409,7 +2409,7 @@ jQuery.extend({ } } }, - + propHooks: { tabIndex: { get: function( elem ) { @@ -2462,7 +2462,7 @@ boolHook = { // IE6/7 do not support getting/setting some attributes with get/setAttribute if ( !jQuery.support.getSetAttribute ) { - + // Use this for any attribute in IE6/7 // This fixes almost every IE6/7 issue nodeHook = jQuery.valHooks.button = { @@ -2834,7 +2834,7 @@ jQuery.event = { } } }, - + // Events that are safe to short-circuit if no handlers are attached. // Native DOM events should not be added, they may have inline handlers. customEvent: { @@ -2880,7 +2880,7 @@ jQuery.event = { event.exclusive = exclusive; event.namespace = namespaces.join("."); event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)"); - + // triggerHandler() and global events don't bubble or run the default action if ( onlyHandlers || !elem ) { event.preventDefault(); @@ -2971,7 +2971,7 @@ jQuery.event = { jQuery.event.triggered = undefined; } } - + return event.result; }, @@ -3801,7 +3801,7 @@ var Sizzle = function( selector, context, results, seed ) { if ( context.nodeType !== 1 && context.nodeType !== 9 ) { return []; } - + if ( !selector || typeof selector !== "string" ) { return results; } @@ -3811,7 +3811,7 @@ var Sizzle = function( selector, context, results, seed ) { contextXML = Sizzle.isXML( context ), parts = [], soFar = selector; - + // Reset the position of the chunker regexp (start from head) do { chunker.exec( "" ); @@ -3819,9 +3819,9 @@ var Sizzle = function( selector, context, results, seed ) { if ( m ) { soFar = m[3]; - + parts.push( m[1] ); - + if ( m[2] ) { extra = m[3]; break; @@ -3845,7 +3845,7 @@ var Sizzle = function( selector, context, results, seed ) { if ( Expr.relative[ selector ] ) { selector += parts.shift(); } - + set = posProcess( selector, set ); } } @@ -3974,7 +3974,7 @@ Sizzle.find = function( expr, context, isXML ) { for ( var i = 0, l = Expr.order.length; i < l; i++ ) { var match, type = Expr.order[i]; - + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { var left = match[1]; match.splice( 1, 1 ); @@ -4306,7 +4306,7 @@ var Expr = Sizzle.selectors = { ATTR: function( match, curLoop, inplace, result, not, isXML ) { var name = match[1] = match[1].replace( rBackslash, "" ); - + if ( !isXML && Expr.attrMap[name] ) { match[1] = Expr.attrMap[name]; } @@ -4340,7 +4340,7 @@ var Expr = Sizzle.selectors = { } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { return true; } - + return match; }, @@ -4350,7 +4350,7 @@ var Expr = Sizzle.selectors = { return match; } }, - + filters: { enabled: function( elem ) { return elem.disabled === false && elem.type !== "hidden"; @@ -4363,14 +4363,14 @@ var Expr = Sizzle.selectors = { checked: function( elem ) { return elem.checked === true; }, - + selected: function( elem ) { // Accessing this property makes selected-by-default // options in Safari work properly if ( elem.parentNode ) { elem.parentNode.selectedIndex; } - + return elem.selected === true; }, @@ -4392,7 +4392,7 @@ var Expr = Sizzle.selectors = { text: function( elem ) { var attr = elem.getAttribute( "type" ), type = elem.type; - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) // use getAttribute instead to test this case return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); }, @@ -4508,21 +4508,21 @@ var Expr = Sizzle.selectors = { case "only": case "first": while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; + if ( node.nodeType === 1 ) { + return false; } } - if ( type === "first" ) { - return true; + if ( type === "first" ) { + return true; } node = elem; case "last": while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; + if ( node.nodeType === 1 ) { + return false; } } @@ -4535,22 +4535,22 @@ var Expr = Sizzle.selectors = { if ( first === 1 && last === 0 ) { return true; } - + var doneName = match[0], parent = elem.parentNode; - + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { var count = 0; - + for ( node = parent.firstChild; node; node = node.nextSibling ) { if ( node.nodeType === 1 ) { node.nodeIndex = ++count; } - } + } parent.sizcache = doneName; } - + var diff = elem.nodeIndex - last; if ( first === 0 ) { @@ -4569,7 +4569,7 @@ var Expr = Sizzle.selectors = { TAG: function( elem, match ) { return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; }, - + CLASS: function( elem, match ) { return (" " + (elem.className || elem.getAttribute("class")) + " ") .indexOf( match ) > -1; @@ -4635,7 +4635,7 @@ var makeArray = function( array, results ) { results.push.apply( results, array ); return results; } - + return array; }; @@ -4887,7 +4887,7 @@ if ( document.querySelectorAll ) { if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { return; } - + Sizzle = function( query, context, extra, seed ) { context = context || document; @@ -4896,24 +4896,24 @@ if ( document.querySelectorAll ) { if ( !seed && !Sizzle.isXML(context) ) { // See if we find a selector to speed up var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); - + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { // Speed-up: Sizzle("TAG") if ( match[1] ) { return makeArray( context.getElementsByTagName( query ), extra ); - + // Speed-up: Sizzle(".CLASS") } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { return makeArray( context.getElementsByClassName( match[2] ), extra ); } } - + if ( context.nodeType === 9 ) { // Speed-up: Sizzle("body") // The body element only exists once, optimize finding it if ( query === "body" && context.body ) { return makeArray( [ context.body ], extra ); - + // Speed-up: Sizzle("#ID") } else if ( match && match[3] ) { var elem = context.getElementById( match[3] ); @@ -4926,12 +4926,12 @@ if ( document.querySelectorAll ) { if ( elem.id === match[3] ) { return makeArray( [ elem ], extra ); } - + } else { return makeArray( [], extra ); } } - + try { return makeArray( context.querySelectorAll(query), extra ); } catch(qsaError) {} @@ -4969,7 +4969,7 @@ if ( document.querySelectorAll ) { } } } - + return oldSizzle(query, context, extra, seed); }; @@ -4996,7 +4996,7 @@ if ( document.querySelectorAll ) { // This should fail with an exception // Gecko does not error, returns false instead matches.call( document.documentElement, "[test!='']:sizzle" ); - + } catch( pseudoError ) { pseudoWorks = true; } @@ -5006,7 +5006,7 @@ if ( document.querySelectorAll ) { expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); if ( !Sizzle.isXML( node ) ) { - try { + try { if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { var ret = matches.call( node, expr ); @@ -5043,7 +5043,7 @@ if ( document.querySelectorAll ) { if ( div.getElementsByClassName("e").length === 1 ) { return; } - + Expr.order.splice(1, 0, "CLASS"); Expr.find.CLASS = function( match, context, isXML ) { if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { @@ -5094,7 +5094,7 @@ function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { if ( elem ) { var match = false; - + elem = elem[dir]; while ( elem ) { @@ -5147,7 +5147,7 @@ if ( document.documentElement.contains ) { Sizzle.isXML = function( elem ) { // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) + // (such as loading iframes in IE - #4833) var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; @@ -5268,7 +5268,7 @@ jQuery.fn.extend({ closest: function( selectors, context ) { var ret = [], i, l, cur = this[0]; - + // Array if ( jQuery.isArray( selectors ) ) { var match, selector, @@ -6720,7 +6720,7 @@ var r20 = /%20/g, // Document location segments ajaxLocParts, - + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression allTypes = ["*/"] + ["*"]; diff --git a/tests/jquery-1.6.js b/tests/jquery-1.6.js index 9a13ab960e..61091a7e7c 100644 --- a/tests/jquery-1.6.js +++ b/tests/jquery-1.6.js @@ -1893,11 +1893,11 @@ jQuery.fn.extend({ jQuery.removeAttr( this, name ); }); }, - + prop: function( name, value ) { return jQuery.access( this, name, value, true, jQuery.prop ); }, - + removeProp: function( name ) { return this.each(function() { // try/catch handles cases where IE balks (such as removing a property on window) @@ -2028,7 +2028,7 @@ jQuery.fn.extend({ val: function( value ) { var hooks, ret, elem = this[0]; - + if ( !arguments.length ) { if ( elem ) { hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; @@ -2155,16 +2155,16 @@ jQuery.extend({ height: true, offset: true }, - + attrFix: { // Always normalize to ensure hook usage tabindex: "tabIndex", readonly: "readOnly" }, - + attr: function( elem, name, value, pass ) { var nType = elem.nodeType; - + // don't get/set attributes on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return undefined; @@ -2173,10 +2173,10 @@ jQuery.extend({ if ( pass && name in jQuery.attrFn ) { return jQuery( elem )[ name ]( value ); } - + var ret, hooks, notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - + // Normalize the name if needed name = notxml && jQuery.attrFix[ name ] || name; @@ -2223,11 +2223,11 @@ jQuery.extend({ } } }, - + removeAttr: function( elem, name ) { if ( elem.nodeType === 1 ) { name = jQuery.attrFix[ name ] || name; - + if ( jQuery.support.getSetAttribute ) { // Use removeAttribute in browsers that support it elem.removeAttribute( name ); @@ -2271,43 +2271,43 @@ jQuery.extend({ } } }, - + propFix: {}, - + prop: function( elem, name, value ) { var nType = elem.nodeType; - + // don't get/set properties on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return undefined; } - + var ret, hooks, notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - + // Try to normalize/fix the name name = notxml && jQuery.propFix[ name ] || name; - + hooks = jQuery.propHooks[ name ]; - + if ( value !== undefined ) { if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { return ret; - + } else { return (elem[ name ] = value); } - + } else { if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== undefined ) { return ret; - + } else { return elem[ name ]; } } }, - + propHooks: {} }); @@ -2324,7 +2324,7 @@ if ( !jQuery.support.getSetAttribute ) { usemap: "useMap", frameborder: "frameBorder" }); - + // Use this for any attribute on a form in IE6/7 formHook = jQuery.attrHooks.name = jQuery.attrHooks.value = jQuery.valHooks.button = { get: function( elem, name ) { @@ -2698,7 +2698,7 @@ jQuery.event = { } } }, - + // Events that are safe to short-circuit if no handlers are attached. // Native DOM events should not be added, they may have inline handlers. customEvent: { @@ -2744,7 +2744,7 @@ jQuery.event = { event.exclusive = exclusive; event.namespace = namespaces.join("."); event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)"); - + // triggerHandler() and global events don't bubble or run the default action if ( onlyHandlers || !elem ) { event.preventDefault(); @@ -2835,7 +2835,7 @@ jQuery.event = { jQuery.event.triggered = undefined; } } - + return event.result; }, @@ -3669,7 +3669,7 @@ var Sizzle = function( selector, context, results, seed ) { if ( context.nodeType !== 1 && context.nodeType !== 9 ) { return []; } - + if ( !selector || typeof selector !== "string" ) { return results; } @@ -3679,7 +3679,7 @@ var Sizzle = function( selector, context, results, seed ) { contextXML = Sizzle.isXML( context ), parts = [], soFar = selector; - + // Reset the position of the chunker regexp (start from head) do { chunker.exec( "" ); @@ -3687,9 +3687,9 @@ var Sizzle = function( selector, context, results, seed ) { if ( m ) { soFar = m[3]; - + parts.push( m[1] ); - + if ( m[2] ) { extra = m[3]; break; @@ -3713,7 +3713,7 @@ var Sizzle = function( selector, context, results, seed ) { if ( Expr.relative[ selector ] ) { selector += parts.shift(); } - + set = posProcess( selector, set ); } } @@ -3842,7 +3842,7 @@ Sizzle.find = function( expr, context, isXML ) { for ( var i = 0, l = Expr.order.length; i < l; i++ ) { var match, type = Expr.order[i]; - + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { var left = match[1]; match.splice( 1, 1 ); @@ -4174,7 +4174,7 @@ var Expr = Sizzle.selectors = { ATTR: function( match, curLoop, inplace, result, not, isXML ) { var name = match[1] = match[1].replace( rBackslash, "" ); - + if ( !isXML && Expr.attrMap[name] ) { match[1] = Expr.attrMap[name]; } @@ -4208,7 +4208,7 @@ var Expr = Sizzle.selectors = { } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { return true; } - + return match; }, @@ -4218,7 +4218,7 @@ var Expr = Sizzle.selectors = { return match; } }, - + filters: { enabled: function( elem ) { return elem.disabled === false && elem.type !== "hidden"; @@ -4231,14 +4231,14 @@ var Expr = Sizzle.selectors = { checked: function( elem ) { return elem.checked === true; }, - + selected: function( elem ) { // Accessing this property makes selected-by-default // options in Safari work properly if ( elem.parentNode ) { elem.parentNode.selectedIndex; } - + return elem.selected === true; }, @@ -4260,7 +4260,7 @@ var Expr = Sizzle.selectors = { text: function( elem ) { var attr = elem.getAttribute( "type" ), type = elem.type; - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) // use getAttribute instead to test this case return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); }, @@ -4375,21 +4375,21 @@ var Expr = Sizzle.selectors = { case "only": case "first": while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; + if ( node.nodeType === 1 ) { + return false; } } - if ( type === "first" ) { - return true; + if ( type === "first" ) { + return true; } node = elem; case "last": while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; + if ( node.nodeType === 1 ) { + return false; } } @@ -4402,22 +4402,22 @@ var Expr = Sizzle.selectors = { if ( first === 1 && last === 0 ) { return true; } - + var doneName = match[0], parent = elem.parentNode; - + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { var count = 0; - + for ( node = parent.firstChild; node; node = node.nextSibling ) { if ( node.nodeType === 1 ) { node.nodeIndex = ++count; } - } + } parent.sizcache = doneName; } - + var diff = elem.nodeIndex - last; if ( first === 0 ) { @@ -4436,7 +4436,7 @@ var Expr = Sizzle.selectors = { TAG: function( elem, match ) { return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; }, - + CLASS: function( elem, match ) { return (" " + (elem.className || elem.getAttribute("class")) + " ") .indexOf( match ) > -1; @@ -4502,7 +4502,7 @@ var makeArray = function( array, results ) { results.push.apply( results, array ); return results; } - + return array; }; @@ -4749,7 +4749,7 @@ if ( document.querySelectorAll ) { if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { return; } - + Sizzle = function( query, context, extra, seed ) { context = context || document; @@ -4758,24 +4758,24 @@ if ( document.querySelectorAll ) { if ( !seed && !Sizzle.isXML(context) ) { // See if we find a selector to speed up var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); - + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { // Speed-up: Sizzle("TAG") if ( match[1] ) { return makeArray( context.getElementsByTagName( query ), extra ); - + // Speed-up: Sizzle(".CLASS") } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { return makeArray( context.getElementsByClassName( match[2] ), extra ); } } - + if ( context.nodeType === 9 ) { // Speed-up: Sizzle("body") // The body element only exists once, optimize finding it if ( query === "body" && context.body ) { return makeArray( [ context.body ], extra ); - + // Speed-up: Sizzle("#ID") } else if ( match && match[3] ) { var elem = context.getElementById( match[3] ); @@ -4788,12 +4788,12 @@ if ( document.querySelectorAll ) { if ( elem.id === match[3] ) { return makeArray( [ elem ], extra ); } - + } else { return makeArray( [], extra ); } } - + try { return makeArray( context.querySelectorAll(query), extra ); } catch(qsaError) {} @@ -4831,7 +4831,7 @@ if ( document.querySelectorAll ) { } } } - + return oldSizzle(query, context, extra, seed); }; @@ -4858,7 +4858,7 @@ if ( document.querySelectorAll ) { // This should fail with an exception // Gecko does not error, returns false instead matches.call( document.documentElement, "[test!='']:sizzle" ); - + } catch( pseudoError ) { pseudoWorks = true; } @@ -4868,7 +4868,7 @@ if ( document.querySelectorAll ) { expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); if ( !Sizzle.isXML( node ) ) { - try { + try { if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { var ret = matches.call( node, expr ); @@ -4905,7 +4905,7 @@ if ( document.querySelectorAll ) { if ( div.getElementsByClassName("e").length === 1 ) { return; } - + Expr.order.splice(1, 0, "CLASS"); Expr.find.CLASS = function( match, context, isXML ) { if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { @@ -4956,7 +4956,7 @@ function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { if ( elem ) { var match = false; - + elem = elem[dir]; while ( elem ) { @@ -5009,7 +5009,7 @@ if ( document.documentElement.contains ) { Sizzle.isXML = function( elem ) { // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) + // (such as loading iframes in IE - #4833) var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; @@ -5130,7 +5130,7 @@ jQuery.fn.extend({ closest: function( selectors, context ) { var ret = [], i, l, cur = this[0]; - + // Array if ( jQuery.isArray( selectors ) ) { var match, selector, @@ -5884,7 +5884,7 @@ jQuery.each({ function getAll( elem ) { if ( "getElementsByTagName" in elem ) { return elem.getElementsByTagName( "*" ); - + } else if ( "querySelectorAll" in elem ) { return elem.querySelectorAll( "*" ); diff --git a/tests/jquery-1.7.1.js b/tests/jquery-1.7.1.js index 8ccd0ea786..c8e7d7a010 100644 --- a/tests/jquery-1.7.1.js +++ b/tests/jquery-1.7.1.js @@ -3885,7 +3885,7 @@ var Sizzle = function( selector, context, results, seed ) { if ( context.nodeType !== 1 && context.nodeType !== 9 ) { return []; } - + if ( !selector || typeof selector !== "string" ) { return results; } @@ -3895,7 +3895,7 @@ var Sizzle = function( selector, context, results, seed ) { contextXML = Sizzle.isXML( context ), parts = [], soFar = selector; - + // Reset the position of the chunker regexp (start from head) do { chunker.exec( "" ); @@ -3903,9 +3903,9 @@ var Sizzle = function( selector, context, results, seed ) { if ( m ) { soFar = m[3]; - + parts.push( m[1] ); - + if ( m[2] ) { extra = m[3]; break; @@ -3929,7 +3929,7 @@ var Sizzle = function( selector, context, results, seed ) { if ( Expr.relative[ selector ] ) { selector += parts.shift(); } - + set = posProcess( selector, set, seed ); } } @@ -4057,7 +4057,7 @@ Sizzle.find = function( expr, context, isXML ) { for ( i = 0, len = Expr.order.length; i < len; i++ ) { type = Expr.order[i]; - + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { left = match[1]; match.splice( 1, 1 ); @@ -4429,7 +4429,7 @@ var Expr = Sizzle.selectors = { ATTR: function( match, curLoop, inplace, result, not, isXML ) { var name = match[1] = match[1].replace( rBackslash, "" ); - + if ( !isXML && Expr.attrMap[name] ) { match[1] = Expr.attrMap[name]; } @@ -4463,7 +4463,7 @@ var Expr = Sizzle.selectors = { } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { return true; } - + return match; }, @@ -4473,7 +4473,7 @@ var Expr = Sizzle.selectors = { return match; } }, - + filters: { enabled: function( elem ) { return elem.disabled === false && elem.type !== "hidden"; @@ -4486,14 +4486,14 @@ var Expr = Sizzle.selectors = { checked: function( elem ) { return elem.checked === true; }, - + selected: function( elem ) { // Accessing this property makes selected-by-default // options in Safari work properly if ( elem.parentNode ) { elem.parentNode.selectedIndex; } - + return elem.selected === true; }, @@ -4515,7 +4515,7 @@ var Expr = Sizzle.selectors = { text: function( elem ) { var attr = elem.getAttribute( "type" ), type = elem.type; - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) // use getAttribute instead to test this case return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); }, @@ -4634,21 +4634,21 @@ var Expr = Sizzle.selectors = { case "only": case "first": while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; + if ( node.nodeType === 1 ) { + return false; } } - if ( type === "first" ) { - return true; + if ( type === "first" ) { + return true; } node = elem; case "last": while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; + if ( node.nodeType === 1 ) { + return false; } } @@ -4661,22 +4661,22 @@ var Expr = Sizzle.selectors = { if ( first === 1 && last === 0 ) { return true; } - + doneName = match[0]; parent = elem.parentNode; - + if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) { count = 0; - + for ( node = parent.firstChild; node; node = node.nextSibling ) { if ( node.nodeType === 1 ) { node.nodeIndex = ++count; } - } + } parent[ expando ] = doneName; } - + diff = elem.nodeIndex - last; if ( first === 0 ) { @@ -4695,7 +4695,7 @@ var Expr = Sizzle.selectors = { TAG: function( elem, match ) { return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match; }, - + CLASS: function( elem, match ) { return (" " + (elem.className || elem.getAttribute("class")) + " ") .indexOf( match ) > -1; @@ -4765,7 +4765,7 @@ var makeArray = function( array, results ) { results.push.apply( results, array ); return results; } - + return array; }; @@ -4997,7 +4997,7 @@ if ( document.querySelectorAll ) { if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { return; } - + Sizzle = function( query, context, extra, seed ) { context = context || document; @@ -5006,24 +5006,24 @@ if ( document.querySelectorAll ) { if ( !seed && !Sizzle.isXML(context) ) { // See if we find a selector to speed up var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); - + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { // Speed-up: Sizzle("TAG") if ( match[1] ) { return makeArray( context.getElementsByTagName( query ), extra ); - + // Speed-up: Sizzle(".CLASS") } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { return makeArray( context.getElementsByClassName( match[2] ), extra ); } } - + if ( context.nodeType === 9 ) { // Speed-up: Sizzle("body") // The body element only exists once, optimize finding it if ( query === "body" && context.body ) { return makeArray( [ context.body ], extra ); - + // Speed-up: Sizzle("#ID") } else if ( match && match[3] ) { var elem = context.getElementById( match[3] ); @@ -5036,12 +5036,12 @@ if ( document.querySelectorAll ) { if ( elem.id === match[3] ) { return makeArray( [ elem ], extra ); } - + } else { return makeArray( [], extra ); } } - + try { return makeArray( context.querySelectorAll(query), extra ); } catch(qsaError) {} @@ -5079,7 +5079,7 @@ if ( document.querySelectorAll ) { } } } - + return oldSizzle(query, context, extra, seed); }; @@ -5106,7 +5106,7 @@ if ( document.querySelectorAll ) { // This should fail with an exception // Gecko does not error, returns false instead matches.call( document.documentElement, "[test!='']:sizzle" ); - + } catch( pseudoError ) { pseudoWorks = true; } @@ -5116,7 +5116,7 @@ if ( document.querySelectorAll ) { expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); if ( !Sizzle.isXML( node ) ) { - try { + try { if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { var ret = matches.call( node, expr ); @@ -5153,7 +5153,7 @@ if ( document.querySelectorAll ) { if ( div.getElementsByClassName("e").length === 1 ) { return; } - + Expr.order.splice(1, 0, "CLASS"); Expr.find.CLASS = function( match, context, isXML ) { if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { @@ -5204,7 +5204,7 @@ function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { if ( elem ) { var match = false; - + elem = elem[dir]; while ( elem ) { @@ -5257,7 +5257,7 @@ if ( document.documentElement.contains ) { Sizzle.isXML = function( elem ) { // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) + // (such as loading iframes in IE - #4833) var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; @@ -5374,11 +5374,11 @@ jQuery.fn.extend({ }, is: function( selector ) { - return !!selector && ( + return !!selector && ( typeof selector === "string" ? // If this is a positional selector, check membership in the returned set // so $("p:first").is("p:last") won't return true for a doc with two "p". - POS.test( selector ) ? + POS.test( selector ) ? jQuery( selector, this.context ).index( this[0] ) >= 0 : jQuery.filter( selector, this ).length > 0 : this.filter( selector ).length > 0 ); @@ -5386,7 +5386,7 @@ jQuery.fn.extend({ closest: function( selectors, context ) { var ret = [], i, l, cur = this[0]; - + // Array (deprecated as of jQuery 1.7) if ( jQuery.isArray( selectors ) ) { var level = 1; diff --git a/tests/jquery-1.7.2.js b/tests/jquery-1.7.2.js index 3774ff9861..ceb681ff9f 100644 --- a/tests/jquery-1.7.2.js +++ b/tests/jquery-1.7.2.js @@ -3645,7 +3645,7 @@ if ( !jQuery.support.submitBubbles ) { }); // return undefined since we don't need an event listener }, - + postDispatch: function( event ) { // If form was submitted by the user, bubble the event up the tree if ( event._submit_bubble ) { diff --git a/tests/jquery-1.7.js b/tests/jquery-1.7.js index eda55db355..3c9ea9e564 100644 --- a/tests/jquery-1.7.js +++ b/tests/jquery-1.7.js @@ -3947,7 +3947,7 @@ var Sizzle = function( selector, context, results, seed ) { if ( context.nodeType !== 1 && context.nodeType !== 9 ) { return []; } - + if ( !selector || typeof selector !== "string" ) { return results; } @@ -3957,7 +3957,7 @@ var Sizzle = function( selector, context, results, seed ) { contextXML = Sizzle.isXML( context ), parts = [], soFar = selector; - + // Reset the position of the chunker regexp (start from head) do { chunker.exec( "" ); @@ -3965,9 +3965,9 @@ var Sizzle = function( selector, context, results, seed ) { if ( m ) { soFar = m[3]; - + parts.push( m[1] ); - + if ( m[2] ) { extra = m[3]; break; @@ -3991,7 +3991,7 @@ var Sizzle = function( selector, context, results, seed ) { if ( Expr.relative[ selector ] ) { selector += parts.shift(); } - + set = posProcess( selector, set, seed ); } } @@ -4119,7 +4119,7 @@ Sizzle.find = function( expr, context, isXML ) { for ( i = 0, len = Expr.order.length; i < len; i++ ) { type = Expr.order[i]; - + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { left = match[1]; match.splice( 1, 1 ); @@ -4491,7 +4491,7 @@ var Expr = Sizzle.selectors = { ATTR: function( match, curLoop, inplace, result, not, isXML ) { var name = match[1] = match[1].replace( rBackslash, "" ); - + if ( !isXML && Expr.attrMap[name] ) { match[1] = Expr.attrMap[name]; } @@ -4525,7 +4525,7 @@ var Expr = Sizzle.selectors = { } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { return true; } - + return match; }, @@ -4535,7 +4535,7 @@ var Expr = Sizzle.selectors = { return match; } }, - + filters: { enabled: function( elem ) { return elem.disabled === false && elem.type !== "hidden"; @@ -4548,14 +4548,14 @@ var Expr = Sizzle.selectors = { checked: function( elem ) { return elem.checked === true; }, - + selected: function( elem ) { // Accessing this property makes selected-by-default // options in Safari work properly if ( elem.parentNode ) { elem.parentNode.selectedIndex; } - + return elem.selected === true; }, @@ -4577,7 +4577,7 @@ var Expr = Sizzle.selectors = { text: function( elem ) { var attr = elem.getAttribute( "type" ), type = elem.type; - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) // use getAttribute instead to test this case return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); }, @@ -4696,21 +4696,21 @@ var Expr = Sizzle.selectors = { case "only": case "first": while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; + if ( node.nodeType === 1 ) { + return false; } } - if ( type === "first" ) { - return true; + if ( type === "first" ) { + return true; } node = elem; case "last": while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; + if ( node.nodeType === 1 ) { + return false; } } @@ -4723,22 +4723,22 @@ var Expr = Sizzle.selectors = { if ( first === 1 && last === 0 ) { return true; } - + doneName = match[0]; parent = elem.parentNode; - + if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) { count = 0; - + for ( node = parent.firstChild; node; node = node.nextSibling ) { if ( node.nodeType === 1 ) { node.nodeIndex = ++count; } - } + } parent[ expando ] = doneName; } - + diff = elem.nodeIndex - last; if ( first === 0 ) { @@ -4757,7 +4757,7 @@ var Expr = Sizzle.selectors = { TAG: function( elem, match ) { return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match; }, - + CLASS: function( elem, match ) { return (" " + (elem.className || elem.getAttribute("class")) + " ") .indexOf( match ) > -1; @@ -4827,7 +4827,7 @@ var makeArray = function( array, results ) { results.push.apply( results, array ); return results; } - + return array; }; @@ -5059,7 +5059,7 @@ if ( document.querySelectorAll ) { if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { return; } - + Sizzle = function( query, context, extra, seed ) { context = context || document; @@ -5068,24 +5068,24 @@ if ( document.querySelectorAll ) { if ( !seed && !Sizzle.isXML(context) ) { // See if we find a selector to speed up var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); - + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { // Speed-up: Sizzle("TAG") if ( match[1] ) { return makeArray( context.getElementsByTagName( query ), extra ); - + // Speed-up: Sizzle(".CLASS") } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { return makeArray( context.getElementsByClassName( match[2] ), extra ); } } - + if ( context.nodeType === 9 ) { // Speed-up: Sizzle("body") // The body element only exists once, optimize finding it if ( query === "body" && context.body ) { return makeArray( [ context.body ], extra ); - + // Speed-up: Sizzle("#ID") } else if ( match && match[3] ) { var elem = context.getElementById( match[3] ); @@ -5098,12 +5098,12 @@ if ( document.querySelectorAll ) { if ( elem.id === match[3] ) { return makeArray( [ elem ], extra ); } - + } else { return makeArray( [], extra ); } } - + try { return makeArray( context.querySelectorAll(query), extra ); } catch(qsaError) {} @@ -5141,7 +5141,7 @@ if ( document.querySelectorAll ) { } } } - + return oldSizzle(query, context, extra, seed); }; @@ -5168,7 +5168,7 @@ if ( document.querySelectorAll ) { // This should fail with an exception // Gecko does not error, returns false instead matches.call( document.documentElement, "[test!='']:sizzle" ); - + } catch( pseudoError ) { pseudoWorks = true; } @@ -5178,7 +5178,7 @@ if ( document.querySelectorAll ) { expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); if ( !Sizzle.isXML( node ) ) { - try { + try { if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { var ret = matches.call( node, expr ); @@ -5215,7 +5215,7 @@ if ( document.querySelectorAll ) { if ( div.getElementsByClassName("e").length === 1 ) { return; } - + Expr.order.splice(1, 0, "CLASS"); Expr.find.CLASS = function( match, context, isXML ) { if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { @@ -5266,7 +5266,7 @@ function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { if ( elem ) { var match = false; - + elem = elem[dir]; while ( elem ) { @@ -5319,7 +5319,7 @@ if ( document.documentElement.contains ) { Sizzle.isXML = function( elem ) { // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) + // (such as loading iframes in IE - #4833) var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; @@ -5436,11 +5436,11 @@ jQuery.fn.extend({ }, is: function( selector ) { - return !!selector && ( + return !!selector && ( typeof selector === "string" ? // If this is a positional selector, check membership in the returned set // so $("p:first").is("p:last") won't return true for a doc with two "p". - POS.test( selector ) ? + POS.test( selector ) ? jQuery( selector, this.context ).index( this[0] ) >= 0 : jQuery.filter( selector, this ).length > 0 : this.filter( selector ).length > 0 ); @@ -5448,7 +5448,7 @@ jQuery.fn.extend({ closest: function( selectors, context ) { var ret = [], i, l, cur = this[0]; - + // Array (deprecated as of jQuery 1.7) if ( jQuery.isArray( selectors ) ) { var level = 1; diff --git a/tests/jquery-1.8.0.js b/tests/jquery-1.8.0.js index dfe5eb00a9..f81bd3d46f 100644 --- a/tests/jquery-1.8.0.js +++ b/tests/jquery-1.8.0.js @@ -6322,7 +6322,7 @@ jQuery.sub = function() { var rootjQuerySub = jQuerySub(document); return jQuerySub; }; - + })(); var curCSS, iframe, iframeDoc, ralpha = /alpha\([^)]*\)/i, diff --git a/tests/jquery.simulate.js b/tests/jquery.simulate.js index 790c88c27b..08cbaafda2 100644 --- a/tests/jquery.simulate.js +++ b/tests/jquery.simulate.js @@ -228,7 +228,7 @@ function findCenter( elem ) { document = $( elem.ownerDocument ); elem = $( elem ); offset = elem.offset(); - + return { x: offset.left + elem.outerWidth() / 2 - document.scrollLeft(), y: offset.top + elem.outerHeight() / 2 - document.scrollTop() @@ -241,7 +241,7 @@ $.extend( $.simulate.prototype, { options = this.options, center = findCenter( target ), x = Math.floor( center.x ), - y = Math.floor( center.y ), + y = Math.floor( center.y ), dx = options.dx || 0, dy = options.dy || 0, coord = { clientX: x, clientY: y }; diff --git a/tests/unit/dialog/dialog_tickets.js b/tests/unit/dialog/dialog_tickets.js index 5c3277c2f3..e17d55a159 100644 --- a/tests/unit/dialog/dialog_tickets.js +++ b/tests/unit/dialog/dialog_tickets.js @@ -125,7 +125,7 @@ test("#6966: Escape key closes all dialogs, not the top one", function(){ ok(d1.data('dialog') && d1.dialog('isOpen'), 'first dialog is open'); ok(d2.data('dialog') && d2.dialog('isOpen'), 'second dialog is open'); - + $( document ).simulate('keydown', {keyCode: $.ui.keyCode.ESCAPE}); ok(d1.data('dialog') && d1.dialog('isOpen'), 'first dialog still open'); ok(!d2.data('dialog'), 'second dialog is closed'); @@ -136,14 +136,14 @@ test("#6966: Escape key closes all dialogs, not the top one", function(){ d2.remove(); d1.remove(); - + // test with close function removing dialog triggered through the dialog d1 = $('
Dialog 1
').dialog({modal: true, close: function(){ d1.remove(); }}); d2 = $('
Dialog 2
').dialog({modal: true, close: function(){ d2.remove(); }}); ok(d1.data('dialog') && d1.dialog('isOpen'), 'first dialog is open'); ok(d2.data('dialog') && d2.dialog('isOpen'), 'second dialog is open'); - + d2.simulate('keydown', {keyCode: $.ui.keyCode.ESCAPE}); ok(d1.data('dialog') && d1.dialog('isOpen'), 'first dialog still open'); ok(!d2.data('dialog'), 'second dialog is closed'); diff --git a/ui/i18n/jquery.ui.datepicker-ar.js b/ui/i18n/jquery.ui.datepicker-ar.js index f0d009667e..cef0f08fd2 100644 --- a/ui/i18n/jquery.ui.datepicker-ar.js +++ b/ui/i18n/jquery.ui.datepicker-ar.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['ar']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-az.js b/ui/i18n/jquery.ui.datepicker-az.js index 1101c8b91b..a133a9eb23 100644 --- a/ui/i18n/jquery.ui.datepicker-az.js +++ b/ui/i18n/jquery.ui.datepicker-az.js @@ -20,4 +20,4 @@ jQuery(function($) { showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['az']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-bs.js b/ui/i18n/jquery.ui.datepicker-bs.js index d645737554..f08870ffe3 100644 --- a/ui/i18n/jquery.ui.datepicker-bs.js +++ b/ui/i18n/jquery.ui.datepicker-bs.js @@ -2,10 +2,10 @@ /* Written by Kenan Konjo. */ jQuery(function($){ $.datepicker.regional['bs'] = { - closeText: 'Zatvori', - prevText: '<', - nextText: '>', - currentText: 'Danas', + closeText: 'Zatvori', + prevText: '<', + nextText: '>', + currentText: 'Danas', monthNames: ['Januar','Februar','Mart','April','Maj','Juni', 'Juli','August','Septembar','Oktobar','Novembar','Decembar'], monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun', @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['bs']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-cy-GB.js b/ui/i18n/jquery.ui.datepicker-cy-GB.js index dfee2f9d4c..cf3a38e6cd 100644 --- a/ui/i18n/jquery.ui.datepicker-cy-GB.js +++ b/ui/i18n/jquery.ui.datepicker-cy-GB.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['cy-GB']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-el.js b/ui/i18n/jquery.ui.datepicker-el.js index 6d775f995f..1ac47561a4 100644 --- a/ui/i18n/jquery.ui.datepicker-el.js +++ b/ui/i18n/jquery.ui.datepicker-el.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['el']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-es.js b/ui/i18n/jquery.ui.datepicker-es.js index 63368aecce..97a2d6ead7 100644 --- a/ui/i18n/jquery.ui.datepicker-es.js +++ b/ui/i18n/jquery.ui.datepicker-es.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['es']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-et.js b/ui/i18n/jquery.ui.datepicker-et.js index 32702b2430..62cbea8fa8 100644 --- a/ui/i18n/jquery.ui.datepicker-et.js +++ b/ui/i18n/jquery.ui.datepicker-et.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['et']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-eu.js b/ui/i18n/jquery.ui.datepicker-eu.js index 846ce3abc6..a71db2c721 100644 --- a/ui/i18n/jquery.ui.datepicker-eu.js +++ b/ui/i18n/jquery.ui.datepicker-eu.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['eu']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-fa.js b/ui/i18n/jquery.ui.datepicker-fa.js index be8acd2a5a..bb957f6d8d 100644 --- a/ui/i18n/jquery.ui.datepicker-fa.js +++ b/ui/i18n/jquery.ui.datepicker-fa.js @@ -37,7 +37,7 @@ jQuery(function($) { 'س', 'چ', 'پ', - 'ج', + 'ج', 'ش' ], dayNamesMin: [ @@ -46,7 +46,7 @@ jQuery(function($) { 'س', 'چ', 'پ', - 'ج', + 'ج', 'ش' ], weekHeader: 'هف', @@ -56,4 +56,4 @@ jQuery(function($) { showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['fa']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-fr-CH.js b/ui/i18n/jquery.ui.datepicker-fr-CH.js index fec03a042f..e574537b05 100644 --- a/ui/i18n/jquery.ui.datepicker-fr-CH.js +++ b/ui/i18n/jquery.ui.datepicker-fr-CH.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['fr-CH']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-gl.js b/ui/i18n/jquery.ui.datepicker-gl.js index 0de64968f3..59b989a6dd 100644 --- a/ui/i18n/jquery.ui.datepicker-gl.js +++ b/ui/i18n/jquery.ui.datepicker-gl.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['gl']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-hr.js b/ui/i18n/jquery.ui.datepicker-hr.js index 6bc5aade12..2fe37b64b7 100644 --- a/ui/i18n/jquery.ui.datepicker-hr.js +++ b/ui/i18n/jquery.ui.datepicker-hr.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['hr']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-hy.js b/ui/i18n/jquery.ui.datepicker-hy.js index b428515961..6d4eca5556 100644 --- a/ui/i18n/jquery.ui.datepicker-hy.js +++ b/ui/i18n/jquery.ui.datepicker-hy.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['hy']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-id.js b/ui/i18n/jquery.ui.datepicker-id.js index 4ad46f6408..6327fa60c7 100644 --- a/ui/i18n/jquery.ui.datepicker-id.js +++ b/ui/i18n/jquery.ui.datepicker-id.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['id']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-is.js b/ui/i18n/jquery.ui.datepicker-is.js index f1b067ebf1..925341a7a5 100644 --- a/ui/i18n/jquery.ui.datepicker-is.js +++ b/ui/i18n/jquery.ui.datepicker-is.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['is']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-ja.js b/ui/i18n/jquery.ui.datepicker-ja.js index afd2983157..4d0b63c77d 100644 --- a/ui/i18n/jquery.ui.datepicker-ja.js +++ b/ui/i18n/jquery.ui.datepicker-ja.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: true, yearSuffix: '年'}; $.datepicker.setDefaults($.datepicker.regional['ja']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-ko.js b/ui/i18n/jquery.ui.datepicker-ko.js index 04112424da..af36f3d6b9 100644 --- a/ui/i18n/jquery.ui.datepicker-ko.js +++ b/ui/i18n/jquery.ui.datepicker-ko.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: true, yearSuffix: '년'}; $.datepicker.setDefaults($.datepicker.regional['ko']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-lt.js b/ui/i18n/jquery.ui.datepicker-lt.js index 2970f8f37c..1afaaac5df 100644 --- a/ui/i18n/jquery.ui.datepicker-lt.js +++ b/ui/i18n/jquery.ui.datepicker-lt.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['lt']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-lv.js b/ui/i18n/jquery.ui.datepicker-lv.js index 003934e721..28cc102fc8 100644 --- a/ui/i18n/jquery.ui.datepicker-lv.js +++ b/ui/i18n/jquery.ui.datepicker-lv.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['lv']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-ml.js b/ui/i18n/jquery.ui.datepicker-ml.js index 1e3432c0a8..9b8f460dbc 100644 --- a/ui/i18n/jquery.ui.datepicker-ml.js +++ b/ui/i18n/jquery.ui.datepicker-ml.js @@ -3,7 +3,7 @@ jQuery(function($){ $.datepicker.regional['ml'] = { closeText: 'ശരി', - prevText: 'മുന്നത്തെ', + prevText: 'മുന്നത്തെ', nextText: 'അടുത്തത് ', currentText: 'ഇന്ന്', monthNames: ['ജനുവരി','ഫെബ്രുവരി','മാര്‍ച്ച്','ഏപ്രില്‍','മേയ്','ജൂണ്‍', diff --git a/ui/i18n/jquery.ui.datepicker-ms.js b/ui/i18n/jquery.ui.datepicker-ms.js index c290af10a5..e70de72995 100644 --- a/ui/i18n/jquery.ui.datepicker-ms.js +++ b/ui/i18n/jquery.ui.datepicker-ms.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['ms']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-nl.js b/ui/i18n/jquery.ui.datepicker-nl.js index 781fe61917..203f16069d 100644 --- a/ui/i18n/jquery.ui.datepicker-nl.js +++ b/ui/i18n/jquery.ui.datepicker-nl.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional.nl); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-pt-BR.js b/ui/i18n/jquery.ui.datepicker-pt-BR.js index 0741892abb..521967ec39 100644 --- a/ui/i18n/jquery.ui.datepicker-pt-BR.js +++ b/ui/i18n/jquery.ui.datepicker-pt-BR.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['pt-BR']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-pt.js b/ui/i18n/jquery.ui.datepicker-pt.js index 98925b4558..999f20e3e9 100644 --- a/ui/i18n/jquery.ui.datepicker-pt.js +++ b/ui/i18n/jquery.ui.datepicker-pt.js @@ -19,4 +19,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['pt']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-ru.js b/ui/i18n/jquery.ui.datepicker-ru.js index 2017e05378..a519714055 100644 --- a/ui/i18n/jquery.ui.datepicker-ru.js +++ b/ui/i18n/jquery.ui.datepicker-ru.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['ru']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-th.js b/ui/i18n/jquery.ui.datepicker-th.js index d57541f640..aecfd27cc0 100644 --- a/ui/i18n/jquery.ui.datepicker-th.js +++ b/ui/i18n/jquery.ui.datepicker-th.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['th']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-tj.js b/ui/i18n/jquery.ui.datepicker-tj.js index ed662392c5..9a20e4d379 100644 --- a/ui/i18n/jquery.ui.datepicker-tj.js +++ b/ui/i18n/jquery.ui.datepicker-tj.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['tj']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-tr.js b/ui/i18n/jquery.ui.datepicker-tr.js index 1b5cafc395..75b583a778 100644 --- a/ui/i18n/jquery.ui.datepicker-tr.js +++ b/ui/i18n/jquery.ui.datepicker-tr.js @@ -20,4 +20,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['tr']); -}); \ No newline at end of file +}); diff --git a/ui/i18n/jquery.ui.datepicker-uk.js b/ui/i18n/jquery.ui.datepicker-uk.js index 31964af440..2bdc82ff70 100644 --- a/ui/i18n/jquery.ui.datepicker-uk.js +++ b/ui/i18n/jquery.ui.datepicker-uk.js @@ -21,4 +21,4 @@ jQuery(function($){ showMonthAfterYear: false, yearSuffix: ''}; $.datepicker.setDefaults($.datepicker.regional['uk']); -}); \ No newline at end of file +}); diff --git a/ui/jquery.ui.datepicker.js b/ui/jquery.ui.datepicker.js index 4643af2eb0..7dacbc7c1c 100644 --- a/ui/jquery.ui.datepicker.js +++ b/ui/jquery.ui.datepicker.js @@ -116,7 +116,7 @@ function Datepicker() { $.extend(Datepicker.prototype, { /* Class name added to elements to indicate already configured with a date picker. */ markerClassName: 'hasDatepicker', - + //Keep track of the maximum number of rows displayed (see #7043) maxRows: 4, @@ -125,7 +125,7 @@ $.extend(Datepicker.prototype, { if (this.debug) console.log.apply('', arguments); }, - + // TODO rename to "widget" when switching to widget factory _widgetDatepicker: function() { return this.dpDiv; @@ -235,7 +235,7 @@ $.extend(Datepicker.prototype, { if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0]) $.datepicker._hideDatepicker(); else if ($.datepicker._datepickerShowing && $.datepicker._lastInput != input[0]) { - $.datepicker._hideDatepicker(); + $.datepicker._hideDatepicker(); $.datepicker._showDatepicker(input[0]); } else $.datepicker._showDatepicker(input[0]); @@ -531,7 +531,7 @@ $.extend(Datepicker.prototype, { case 9: $.datepicker._hideDatepicker(); handled = false; break; // hide on tab out - case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' + + case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' + $.datepicker._currentClass + ')', inst.dpDiv); if (sel[0]) $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); @@ -629,7 +629,7 @@ $.extend(Datepicker.prototype, { }, /* Pop-up the date picker for a given input field. - If false returned from beforeShow event handler do not show. + If false returned from beforeShow event handler do not show. @param input element - the input field attached to the date picker or event - if triggered by focus */ _showDatepicker: function(input) { @@ -733,7 +733,7 @@ $.extend(Datepicker.prototype, { // this breaks the change event in IE inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement) inst.input.focus(); - // deffered render of the years select (to avoid flashes on Firefox) + // deffered render of the years select (to avoid flashes on Firefox) if( inst.yearshtml ){ var origyearshtml = inst.yearshtml; setTimeout(function(){ @@ -1442,7 +1442,7 @@ $.extend(Datepicker.prototype, { $(this).bind(this.getAttribute('data-event'), handler[this.getAttribute('data-handler')]); }); }, - + /* Generate the HTML for the current state of the date picker. */ _generateHTML: function(inst) { var today = new Date(); @@ -1599,7 +1599,7 @@ $.extend(Datepicker.prototype, { drawMonth = 0; drawYear++; } - calender += '' + (isMultiMonth ? '' + + calender += '' + (isMultiMonth ? '' + ((numMonths[0] > 0 && col == numMonths[1]-1) ? '
' : '') : ''); group += calender; } @@ -1663,7 +1663,7 @@ $.extend(Datepicker.prototype, { '>' + year + ''; } inst.yearshtml += ''; - + html += inst.yearshtml; inst.yearshtml = null; } @@ -1774,7 +1774,7 @@ $.extend(Datepicker.prototype, { * Bind hover events for datepicker elements. * Done via delegate so the binding only occurs once in the lifetime of the parent div. * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. - */ + */ function bindHover(dpDiv) { var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a'; return dpDiv.delegate(selector, 'mouseout', function() { @@ -1806,12 +1806,12 @@ function extendRemove(target, props) { Object - settings for attaching new datepicker functionality @return jQuery object */ $.fn.datepicker = function(options){ - + /* Verify an empty collection wasn't passed - Fixes #6976 */ if ( !this.length ) { return this; } - + /* Initialise the date picker. */ if (!$.datepicker.initialized) { $(document).mousedown($.datepicker._checkExternalClick). diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 5d91a3d948..aa62752526 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -73,7 +73,7 @@ $.widget("ui.draggable", $.ui.mouse, { this.handle = this._getHandle(event); if (!this.handle) return false; - + $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() { $('
') .css({ @@ -157,12 +157,12 @@ $.widget("ui.draggable", $.ui.mouse, { if ($.ui.ddmanager && !o.dropBehaviour) $.ui.ddmanager.prepareOffsets(this, event); - + this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position - + //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event); - + return true; }, @@ -201,7 +201,7 @@ $.widget("ui.draggable", $.ui.mouse, { dropped = this.dropped; this.dropped = false; } - + //if the original element is no longer in the DOM don't bother to continue (see #8269) var element = this.element[0], elementInDom = false; while ( element && (element = element.parentNode) ) { @@ -227,29 +227,29 @@ $.widget("ui.draggable", $.ui.mouse, { return false; }, - + _mouseUp: function(event) { //Remove frame helpers - $("div.ui-draggable-iframeFix").each(function() { - this.parentNode.removeChild(this); + $("div.ui-draggable-iframeFix").each(function() { + this.parentNode.removeChild(this); }); - + //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event); - + return $.ui.mouse.prototype._mouseUp.call(this, event); }, - + cancel: function() { - + if(this.helper.is(".ui-draggable-dragging")) { this._mouseUp({}); } else { this._clear(); } - + return this; - + }, _getHandle: function(event) { @@ -570,14 +570,14 @@ $.ui.plugin.add("draggable", "connectToSortable", { }; $.each(inst.sortables, function(i) { - + var innermostIntersecting = false; var thisSortable = this; //Copy over some variables to allow calling the sortable's native _intersectsWith this.instance.positionAbs = inst.positionAbs; this.instance.helperProportions = inst.helperProportions; this.instance.offset.click = inst.offset.click; - + if(this.instance._intersectsWith(this.instance.containerCache)) { innermostIntersecting = true; $.each(inst.sortables, function () { @@ -634,13 +634,13 @@ $.ui.plugin.add("draggable", "connectToSortable", { this.instance.isOver = 0; this.instance.cancelHelperRemoval = true; - + //Prevent reverting on this forced stop this.instance.options.revert = false; - + // The out event needs to be triggered independently this.instance._trigger('out', event, this.instance._uiHash(this.instance)); - + this.instance._mouseStop(event, true); this.instance.options.helper = this.instance.options._helper; @@ -810,7 +810,7 @@ $.ui.plugin.add("draggable", "stack", { return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0); }); if (!group.length) { return; } - + var min = parseInt(group[0].style.zIndex) || 0; $(group).each(function(i) { this.style.zIndex = min + i; diff --git a/ui/jquery.ui.effect-highlight.js b/ui/jquery.ui.effect-highlight.js index 0b0dbd9888..99c41de2f3 100644 --- a/ui/jquery.ui.effect-highlight.js +++ b/ui/jquery.ui.effect-highlight.js @@ -26,7 +26,7 @@ $.effects.effect.highlight = function( o, done ) { } $.effects.save( elem, props ); - + elem .show() .css({ diff --git a/ui/jquery.ui.mouse.js b/ui/jquery.ui.mouse.js index f5069d00c4..cdc063f91d 100644 --- a/ui/jquery.ui.mouse.js +++ b/ui/jquery.ui.mouse.js @@ -104,7 +104,7 @@ $.widget("ui.mouse", { .bind('mouseup.'+this.widgetName, this._mouseUpDelegate); event.preventDefault(); - + mouseHandled = true; return true; }, diff --git a/ui/jquery.ui.resizable.js b/ui/jquery.ui.resizable.js index c1fd676d97..fc4868c376 100644 --- a/ui/jquery.ui.resizable.js +++ b/ui/jquery.ui.resizable.js @@ -574,7 +574,7 @@ $.ui.plugin.add("resizable", "alsoResize", { _alsoResize = function (exp, c) { $(exp).each(function() { - var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, + var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left']; $.each(css, function (i, prop) { From ac43938c8c1c908546cdb967dce11806bf2b4197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Zaefferer?= Date: Mon, 22 Oct 2012 10:48:46 -0400 Subject: [PATCH 028/151] Spinner: Remove z-index from buttons. Whatever the original purpose, its not needed anymore. Fixes #8655 - Spinner buttons displayed on top of Datepicker. --- themes/base/jquery.ui.spinner.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes/base/jquery.ui.spinner.css b/themes/base/jquery.ui.spinner.css index fd2a449af9..95f865b925 100644 --- a/themes/base/jquery.ui.spinner.css +++ b/themes/base/jquery.ui.spinner.css @@ -10,7 +10,7 @@ */ .ui-spinner { position:relative; display: inline-block; overflow: hidden; padding: 0; vertical-align: middle; } .ui-spinner-input { border: none; background: none; padding: 0; margin: .2em 0; vertical-align: middle; margin-left: .4em; margin-right: 22px; } -.ui-spinner-button { width: 16px; height: 50%; font-size: .5em; padding: 0; margin: 0; z-index: 100; text-align: center; position: absolute; cursor: default; display: block; overflow: hidden; right: 0; } +.ui-spinner-button { width: 16px; height: 50%; font-size: .5em; padding: 0; margin: 0; text-align: center; position: absolute; cursor: default; display: block; overflow: hidden; right: 0; } .ui-spinner a.ui-spinner-button { border-top: none; border-bottom: none; border-right: none; } /* more specificity required here to overide default borders */ .ui-spinner .ui-icon { position: absolute; margin-top: -8px; top: 50%; left: 0; } /* vertical centre icon */ .ui-spinner-up { top: 0; } From 6bedc0af357d9326ac39c37372b04d3bf7747454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Mon, 22 Oct 2012 14:57:53 -0400 Subject: [PATCH 029/151] Whitespace. --- tests/unit/widget/widget_extend.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/widget/widget_extend.js b/tests/unit/widget/widget_extend.js index ae98559297..3ad59a9ccb 100644 --- a/tests/unit/widget/widget_extend.js +++ b/tests/unit/widget/widget_extend.js @@ -79,7 +79,7 @@ test( "$.widget.extend()", function() { ret = $.widget.extend( { foo: "1,2,3" }, { foo: [1, 2, 3] } ); strictEqual( typeof ret.foo, "object", "Check to make sure values equal with coersion (but not actually equal) overwrite correctly" ); - ret = $.widget.extend( { foo:"bar" }, { foo:null } ); + ret = $.widget.extend( { foo: "bar" }, { foo: null } ); strictEqual( typeof ret.foo, "object", "Make sure a null value doesn't crash with deep extend, for #1908" ); obj = { foo:null }; From 9b908878ae3a9c0fbbd9958b579f223a648c5c69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Mon, 22 Oct 2012 15:33:57 -0400 Subject: [PATCH 030/151] Widget: $.widget.extend(): Properly handle extending a string with an object. Fixes #8713 - Passing an object as ui.resizable handles parameter does not work. --- tests/unit/widget/widget_extend.js | 13 ++++++++----- ui/jquery.ui.widget.js | 6 +++++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/tests/unit/widget/widget_extend.js b/tests/unit/widget/widget_extend.js index 3ad59a9ccb..14f9a46e0d 100644 --- a/tests/unit/widget/widget_extend.js +++ b/tests/unit/widget/widget_extend.js @@ -1,5 +1,5 @@ test( "$.widget.extend()", function() { - expect( 26 ); + expect( 27 ); var ret, empty, optionsWithLength, optionsWithDate, myKlass, customObject, optionsWithCustomObject, nullUndef, target, recursive, obj, input, output, @@ -76,13 +76,16 @@ test( "$.widget.extend()", function() { ret = $.widget.extend( { foo: [] }, { foo: [0] } ); // 1907 equal( ret.foo.length, 1, "Check to make sure a value with coersion 'false' copies over when necessary to fix #1907" ); - ret = $.widget.extend( { foo: "1,2,3" }, { foo: [1, 2, 3] } ); - strictEqual( typeof ret.foo, "object", "Check to make sure values equal with coersion (but not actually equal) overwrite correctly" ); + ret = $.widget.extend( { foo: "1,2,3" }, { foo: [ 1, 2, 3 ] } ); + deepEqual( ret.foo, [ 1, 2, 3 ], "Properly extend a string to array." ); + + ret = $.widget.extend( { foo: "1,2,3" }, { foo: { to: "object" } } ); + deepEqual( ret.foo, { to: "object" }, "Properly extend a string to object." ); ret = $.widget.extend( { foo: "bar" }, { foo: null } ); - strictEqual( typeof ret.foo, "object", "Make sure a null value doesn't crash with deep extend, for #1908" ); + strictEqual( ret.foo, null, "Make sure a null value doesn't crash with deep extend, for #1908" ); - obj = { foo:null }; + obj = { foo: null }; $.widget.extend( obj, { foo:"notnull" } ); equal( obj.foo, "notnull", "Make sure a null value can be overwritten" ); diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index a125dd5ac9..96cc6071c8 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -143,7 +143,11 @@ $.widget.extend = function( target ) { for ( key in input[ inputIndex ] ) { value = input[ inputIndex ][ key ]; if (input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { - target[ key ] = $.isPlainObject( value ) ? $.widget.extend( {}, target[ key ], value ) : value; + if ( $.isPlainObject( value ) && $.isPlainObject( target[ key ] ) ) { + target[ key ] = $.widget.extend( {}, target[ key ], value ); + } else { + target[ key ] = value; + } } } } From d67522e3290948c0497ab7c6511e9ea29b22b851 Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Mon, 22 Oct 2012 17:41:54 -0400 Subject: [PATCH 031/151] Build: Upgrade to the latest Grunt and JSHint - Closes gh-786 --- .jshintrc | 3 +- build/.jshintrc | 13 --- build/release/release.js | 2 + build/tasks/build.js | 5 +- build/tasks/testswarm.js | 3 +- grunt.js | 7 +- package.json | 2 +- tests/.jshintrc | 1 - tests/unit/datepicker/datepicker_tickets.js | 96 ++++++++++----------- tests/unit/testsuite.js | 8 +- ui/.jshintrc | 1 - ui/jquery.ui.autocomplete.js | 2 +- 12 files changed, 68 insertions(+), 75 deletions(-) delete mode 100644 build/.jshintrc diff --git a/.jshintrc b/.jshintrc index 99161bd4e3..e22109220d 100644 --- a/.jshintrc +++ b/.jshintrc @@ -3,10 +3,9 @@ "eqnull": true, "eqeqeq": true, "expr": true, - "latedef": true, "noarg": true, + "node": true, "onevar": true, - "smarttabs": true, "trailing": true, "undef": true } diff --git a/build/.jshintrc b/build/.jshintrc deleted file mode 100644 index 9e6abf31d7..0000000000 --- a/build/.jshintrc +++ /dev/null @@ -1,13 +0,0 @@ -{ - "curly": true, - "eqnull": true, - "eqeqeq": true, - "expr": true, - "noarg": true, - "node": true, - "onevar": true, - "smarttabs": true, - "strict": false, - "trailing": true, - "undef": true -} diff --git a/build/release/release.js b/build/release/release.js index 77430d8d16..ae705a90fc 100644 --- a/build/release/release.js +++ b/build/release/release.js @@ -1,6 +1,8 @@ #!/usr/bin/env node /*global cat:true cd:true cp:true echo:true exec:true exit:true ls:true*/ +"use strict"; + var baseDir, repoDir, prevVersion, newVersion, nextVersion, tagTime, fs = require( "fs" ), path = require( "path" ), diff --git a/build/tasks/build.js b/build/tasks/build.js index 3f3dd31c55..b59c728d30 100644 --- a/build/tasks/build.js +++ b/build/tasks/build.js @@ -1,6 +1,9 @@ module.exports = function( grunt ) { -var path = require( "path" ); +"use strict"; + +var path = require( "path" ), + fs = require( "fs" ); grunt.registerTask( "manifest", "Generate jquery.json manifest files", function() { var pkg = grunt.config( "pkg" ), diff --git a/build/tasks/testswarm.js b/build/tasks/testswarm.js index 34c17d4f6b..244113786c 100644 --- a/build/tasks/testswarm.js +++ b/build/tasks/testswarm.js @@ -1,6 +1,7 @@ -/*jshint node: true */ module.exports = function( grunt ) { +"use strict"; + var versions = { "git": "git", "1.8": "1.8.0 1.8.1 1.8.2", diff --git a/grunt.js b/grunt.js index 9e03c95fac..6e8655b409 100644 --- a/grunt.js +++ b/grunt.js @@ -1,6 +1,7 @@ -/*jshint node: true */ module.exports = function( grunt ) { +"use strict"; + var // files coreFiles = [ @@ -326,9 +327,7 @@ grunt.initConfig({ } return { - // TODO: use "faux strict mode" https://github.com/jshint/jshint/issues/504 - // TODO: limit `smarttabs` to multi-line comments https://github.com/jshint/jshint/issues/503 - options: parserc(), + grunt: parserc(), ui: parserc( "ui/" ), // TODO: `evil: true` is only for document.write() https://github.com/jshint/jshint/issues/519 // TODO: don't create so many globals in tests diff --git a/package.json b/package.json index 3625c1f442..110a23a6e7 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ ], "dependencies": {}, "devDependencies": { - "grunt": "~0.3.9", + "grunt": "~0.3.17", "grunt-css": "0.2.0", "grunt-compare-size": "0.1.4", "grunt-html": "0.1.1", diff --git a/tests/.jshintrc b/tests/.jshintrc index 7832372183..20094d4363 100644 --- a/tests/.jshintrc +++ b/tests/.jshintrc @@ -9,7 +9,6 @@ "latedef": true, "noarg": true, "onevar": true, - "smarttabs": true, "trailing": true, "undef": true, "predef": [ diff --git a/tests/unit/datepicker/datepicker_tickets.js b/tests/unit/datepicker/datepicker_tickets.js index e1b882a89e..57b25c3fff 100644 --- a/tests/unit/datepicker/datepicker_tickets.js +++ b/tests/unit/datepicker/datepicker_tickets.js @@ -7,9 +7,9 @@ module("datepicker: tickets"); // http://forum.jquery.com/topic/several-breaking-changes-in-jquery-ui-1-8rc1 test('beforeShowDay-getDate', function() { - expect( 3 ); + expect( 3 ); var inp = init('#inp', {beforeShowDay: function(date) { inp.datepicker('getDate'); return [true, '']; }}), - dp = $('#ui-datepicker-div'); + dp = $('#ui-datepicker-div'); inp.val('01/01/2010').datepicker('show'); // contains non-breaking space equal($('div.ui-datepicker-title').text(), 'January 2010', 'Initial month'); @@ -26,63 +26,63 @@ test('beforeShowDay-getDate', function() { }); test('Ticket 7602: Stop datepicker from appearing with beforeShow event handler', function(){ - expect( 3 ); - var inp = init('#inp',{ - beforeShow: function(){ - return false; - } - }), - dp = $('#ui-datepicker-div'); - inp.datepicker('show'); - equal(dp.css('display'), 'none',"beforeShow returns false"); - inp.datepicker('destroy'); + expect( 3 ); + var inp = init('#inp',{ + beforeShow: function(){ + return false; + } + }), + dp = $('#ui-datepicker-div'); + inp.datepicker('show'); + equal(dp.css('display'), 'none',"beforeShow returns false"); + inp.datepicker('destroy'); - inp = init('#inp',{ - beforeShow: function(){ - } - }); - dp = $('#ui-datepicker-div'); - inp.datepicker('show'); - equal(dp.css('display'), 'block',"beforeShow returns nothing"); + inp = init('#inp',{ + beforeShow: function(){ + } + }); + dp = $('#ui-datepicker-div'); + inp.datepicker('show'); + equal(dp.css('display'), 'block',"beforeShow returns nothing"); inp.datepicker('hide'); - inp.datepicker('destroy'); + inp.datepicker('destroy'); - inp = init('#inp',{ - beforeShow: function(){ - return true; - } - }); - dp = $('#ui-datepicker-div'); - inp.datepicker('show'); - equal(dp.css('display'), 'block',"beforeShow returns true"); + inp = init('#inp',{ + beforeShow: function(){ + return true; + } + }); + dp = $('#ui-datepicker-div'); + inp.datepicker('show'); + equal(dp.css('display'), 'block',"beforeShow returns true"); inp.datepicker('hide'); - inp.datepicker('destroy'); + inp.datepicker('destroy'); }); test('Ticket 6827: formatDate day of year calculation is wrong during day lights savings time', function(){ - expect( 1 ); - var time = $.datepicker.formatDate("oo", new Date("2010/03/30 12:00:00 CDT")); - equal(time, "089"); + expect( 1 ); + var time = $.datepicker.formatDate("oo", new Date("2010/03/30 12:00:00 CDT")); + equal(time, "089"); }); test('Ticket #7244: date parser does not fail when too many numbers are passed into the date function', function() { - expect( 4 ); - var date; - try{ - date = $.datepicker.parseDate('dd/mm/yy', '18/04/19881'); - ok(false, "Did not properly detect an invalid date"); - }catch(e){ - ok("invalid date detected"); - } + expect( 4 ); + var date; + try{ + date = $.datepicker.parseDate('dd/mm/yy', '18/04/19881'); + ok(false, "Did not properly detect an invalid date"); + }catch(e){ + ok("invalid date detected"); + } - try { - date = $.datepicker.parseDate('dd/mm/yy', '18/04/1988 @ 2:43 pm'); - equal(date.getDate(), 18); - equal(date.getMonth(), 3); - equal(date.getFullYear(), 1988); - } catch(e) { - ok(false, "Did not properly parse date with extra text separated by whitespace"); - } + try { + date = $.datepicker.parseDate('dd/mm/yy', '18/04/1988 @ 2:43 pm'); + equal(date.getDate(), 18); + equal(date.getMonth(), 3); + equal(date.getFullYear(), 1988); + } catch(e) { + ok(false, "Did not properly parse date with extra text separated by whitespace"); + } }); })(jQuery); diff --git a/tests/unit/testsuite.js b/tests/unit/testsuite.js index 06890d8d91..74a561c0d2 100644 --- a/tests/unit/testsuite.js +++ b/tests/unit/testsuite.js @@ -12,6 +12,10 @@ function includeScript( url ) { document.write( "" ); } +function url( value ) { + return value + (/\?/.test(value) ? "&" : "?") + new Date().getTime() + "" + parseInt(Math.random() * 100000, 10); +} + reset = QUnit.reset; QUnit.reset = function() { // Ensure jQuery events and data on the fixture are properly removed @@ -65,11 +69,11 @@ TestHelpers.testJshint = function( module ) { $.when( $.ajax({ - url: "../../../ui/.jshintrc", + url: url("../../../ui/.jshintrc"), dataType: "json" }), $.ajax({ - url: "../../../ui/jquery.ui." + module + ".js", + url: url("../../../ui/jquery.ui." + module + ".js"), dataType: "text" }) ).done(function( hintArgs, srcArgs ) { diff --git a/ui/.jshintrc b/ui/.jshintrc index 415d69e905..26b8087740 100644 --- a/ui/.jshintrc +++ b/ui/.jshintrc @@ -8,7 +8,6 @@ "latedef": true, "noarg": true, "onevar": true, - "smarttabs": true, "trailing": true, "undef": true, "predef": [ diff --git a/ui/jquery.ui.autocomplete.js b/ui/jquery.ui.autocomplete.js index f181e91805..aec12bf8f3 100644 --- a/ui/jquery.ui.autocomplete.js +++ b/ui/jquery.ui.autocomplete.js @@ -292,7 +292,7 @@ $.widget( "ui.autocomplete", { .insertAfter( this.element ); if ( $.fn.bgiframe ) { - this.menu.element.bgiframe(); + this.menu.element.bgiframe(); } // turning off autocomplete prevents the browser from remembering the From 7af1ec727bcca8367e804cea77b9dd238b1c0d69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Tue, 23 Oct 2012 10:15:19 -0400 Subject: [PATCH 032/151] Tooltip: Position below the element and set a max width of 300px to more closely match native tooltip behavior. Fixes #8718 - tooltip flickers when too long. --- themes/base/jquery.ui.tooltip.css | 1 + ui/jquery.ui.tooltip.js | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/themes/base/jquery.ui.tooltip.css b/themes/base/jquery.ui.tooltip.css index e293eeb23e..acc39a0021 100644 --- a/themes/base/jquery.ui.tooltip.css +++ b/themes/base/jquery.ui.tooltip.css @@ -10,6 +10,7 @@ padding:8px; position:absolute; z-index:9999; + max-width: 300px; -o-box-shadow: 0 0 5px #aaa; -moz-box-shadow: 0 0 5px #aaa; -webkit-box-shadow: 0 0 5px #aaa; diff --git a/ui/jquery.ui.tooltip.js b/ui/jquery.ui.tooltip.js index a04b842893..4a17f1f20f 100644 --- a/ui/jquery.ui.tooltip.js +++ b/ui/jquery.ui.tooltip.js @@ -52,8 +52,8 @@ $.widget( "ui.tooltip", { // Disabled elements have inconsistent behavior across browsers (#8661) items: "[title]:not([disabled])", position: { - my: "left+15 center", - at: "right center", + my: "left top+15", + at: "left bottom", collision: "flipfit flipfit" }, show: true, From e1230997aa14dae6f35326c8ba20bfe2428507c2 Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Tue, 23 Oct 2012 09:36:42 -0500 Subject: [PATCH 033/151] Build: Enable "unused" option in jshint - Remove unused variables from codebase. - Closes gh-788 Squashed commit of the following: commit 7f19f92c646f180bc067bb24123175251a64a9d6 Author: Mike Sherov Date: Tue Oct 23 10:34:28 2012 -0400 put back in fake args for signatures that we want to keep commit 257505a9e69da0c53e3a989dab87a13112045a29 Author: Mike Sherov Date: Tue Oct 23 08:10:20 2012 -0400 changes per @scott_gonzalez commit 12725480cb58e70865e5aa6e735009b6b035c8f3 Author: Mike Sherov Date: Mon Oct 22 22:54:05 2012 -0400 clean up unused vars in ui directory commit 563595e7aee5d4a5c096b2d1de655abdf920aacd Author: Mike Sherov Date: Mon Oct 22 22:37:42 2012 -0400 clean up unused vars in grunt and tests --- .jshintrc | 3 +- build/release/release.js | 2 +- build/tasks/build.js | 2 +- tests/.jshintrc | 12 +---- tests/unit/autocomplete/autocomplete_core.js | 3 +- .../unit/autocomplete/autocomplete_events.js | 6 +-- .../unit/autocomplete/autocomplete_options.js | 2 +- tests/unit/button/button_events.js | 2 +- tests/unit/datepicker/datepicker_core.js | 18 ++----- tests/unit/datepicker/datepicker_defaults.js | 4 +- tests/unit/datepicker/datepicker_events.js | 6 +-- tests/unit/datepicker/datepicker_methods.js | 20 +++---- tests/unit/datepicker/datepicker_options.js | 24 +++------ tests/unit/datepicker/datepicker_tickets.js | 2 +- tests/unit/dialog/dialog_core.js | 48 +++++++---------- tests/unit/dialog/dialog_events.js | 6 +-- tests/unit/dialog/dialog_methods.js | 2 +- tests/unit/dialog/dialog_options.js | 30 +++++------ tests/unit/dialog/dialog_tickets.js | 8 +-- tests/unit/draggable/draggable_core.js | 5 +- tests/unit/draggable/draggable_options.js | 44 ++++++++-------- tests/unit/droppable/droppable_core.js | 12 ++--- tests/unit/droppable/droppable_events.js | 4 ++ tests/unit/droppable/droppable_methods.js | 16 +++--- tests/unit/effects/effects_core.js | 14 ++--- tests/unit/menu/menu_events.js | 30 +++++------ tests/unit/menu/menu_methods.js | 2 +- tests/unit/menu/menu_options.js | 4 +- tests/unit/resizable/resizable_core.js | 36 ++++++------- tests/unit/resizable/resizable_events.js | 4 ++ tests/unit/resizable/resizable_methods.js | 3 ++ tests/unit/resizable/resizable_options.js | 52 +++++++++---------- tests/unit/selectable/selectable_core.js | 2 +- tests/unit/selectable/selectable_events.js | 4 +- tests/unit/selectable/selectable_methods.js | 2 +- tests/unit/selectable/selectable_options.js | 8 +-- tests/unit/slider/slider_events.js | 24 ++++----- tests/unit/slider/slider_methods.js | 4 +- tests/unit/sortable/sortable_core.js | 4 ++ tests/unit/sortable/sortable_options.js | 4 ++ tests/unit/sortable/sortable_tickets.js | 6 +-- tests/unit/spinner/spinner_options.js | 6 +-- tests/unit/tabs/tabs_core.js | 5 +- tests/unit/tabs/tabs_deprecated.js | 16 +++--- tests/unit/testsuite.js | 4 +- tests/unit/tooltip/tooltip_options.js | 2 +- tests/unit/widget/widget_core.js | 8 +-- ui/.jshintrc | 1 + ui/jquery.ui.accordion.js | 2 +- ui/jquery.ui.autocomplete.js | 4 +- ui/jquery.ui.dialog.js | 28 +++++----- ui/jquery.ui.effect.js | 11 ++-- ui/jquery.ui.slider.js | 4 +- ui/jquery.ui.tabs.js | 12 ++--- ui/jquery.ui.tooltip.js | 4 +- ui/jquery.ui.widget.js | 2 +- 56 files changed, 282 insertions(+), 311 deletions(-) diff --git a/.jshintrc b/.jshintrc index e22109220d..d6966c51d9 100644 --- a/.jshintrc +++ b/.jshintrc @@ -7,5 +7,6 @@ "node": true, "onevar": true, "trailing": true, - "undef": true + "undef": true, + "unused": true } diff --git a/build/release/release.js b/build/release/release.js index ae705a90fc..2227bf0e6d 100644 --- a/build/release/release.js +++ b/build/release/release.js @@ -425,7 +425,7 @@ function abort( msg ) { function walk( methods ) { var method = methods.shift(); - function next( error ) { + function next() { if ( methods.length ) { walk( methods ); } diff --git a/build/tasks/build.js b/build/tasks/build.js index b59c728d30..18e427a565 100644 --- a/build/tasks/build.js +++ b/build/tasks/build.js @@ -146,7 +146,7 @@ grunt.registerMultiTask( "zip", "Create a zip file for release", function() { opts: { cwd: 'dist' } - }, function( err, result ) { + }, function( err ) { if ( err ) { grunt.log.error( err ); done(); diff --git a/tests/.jshintrc b/tests/.jshintrc index 20094d4363..c0f0f8d532 100644 --- a/tests/.jshintrc +++ b/tests/.jshintrc @@ -11,8 +11,8 @@ "onevar": true, "trailing": true, "undef": true, + "unused": true, "predef": [ - "addMonths", "asyncTest", "container", "deepEqual", @@ -29,8 +29,6 @@ "Globalize", "heightAfter", "init", - "isNotOpen", - "isOpen", "modal", "module", "moved", @@ -38,15 +36,7 @@ "offsetAfter", "offsetBefore", "ok", - "PROP_NAME", "QUnit", - "restoreScroll", - "shouldBeDroppable", - "shouldmove", - "shouldNotBeDroppable", - "shouldnotmove", - "shouldnotresize", - "shouldresize", "start", "strictEqual", "stop", diff --git a/tests/unit/autocomplete/autocomplete_core.js b/tests/unit/autocomplete/autocomplete_core.js index f0ad36a57e..f2062cacda 100644 --- a/tests/unit/autocomplete/autocomplete_core.js +++ b/tests/unit/autocomplete/autocomplete_core.js @@ -109,8 +109,7 @@ test( "allow form submit on enter when menu is not active", function() { function arrowsMoveFocus( id, isKeyUp ) { expect( 1 ); - var didMove = false, - element = $( id ).autocomplete({ + var element = $( id ).autocomplete({ source: [ "a" ], delay: 0, minLength: 0 diff --git a/tests/unit/autocomplete/autocomplete_events.js b/tests/unit/autocomplete/autocomplete_events.js index 082263a35e..fb1cf73a69 100644 --- a/tests/unit/autocomplete/autocomplete_events.js +++ b/tests/unit/autocomplete/autocomplete_events.js @@ -39,7 +39,7 @@ $.each([ ], "response ui.content" ); ui.content.splice( 0, 1 ); }, - open: function( event ) { + open: function() { ok( menu.is( ":visible" ), "menu open on open" ); }, focus: function( event, ui ) { @@ -127,7 +127,7 @@ asyncTest( "cancel focus", function() { element = $( "#autocomplete" ).autocomplete({ delay: 0, source: data, - focus: function( event, ui ) { + focus: function() { $( this ).val( customVal ); return false; } @@ -146,7 +146,7 @@ asyncTest( "cancel select", function() { element = $( "#autocomplete" ).autocomplete({ delay: 0, source: data, - select: function( event, ui ) { + select: function() { $( this ).val( customVal ); return false; } diff --git a/tests/unit/autocomplete/autocomplete_options.js b/tests/unit/autocomplete/autocomplete_options.js index 1ab40f36c7..8331c53d54 100644 --- a/tests/unit/autocomplete/autocomplete_options.js +++ b/tests/unit/autocomplete/autocomplete_options.js @@ -33,7 +33,7 @@ function autoFocusTest( afValue, focusedLength ) { autoFocus: afValue, delay: 0, source: data, - open: function( event, ui ) { + open: function() { equal( element.autocomplete( "widget" ).children( ".ui-menu-item:first" ).find( ".ui-state-focus" ).length, focusedLength, "first item is " + (afValue ? "" : "not") + " auto focused" ); start(); diff --git a/tests/unit/button/button_events.js b/tests/unit/button/button_events.js index a2154021df..40d2a1a96a 100644 --- a/tests/unit/button/button_events.js +++ b/tests/unit/button/button_events.js @@ -1,7 +1,7 @@ /* * button_events.js */ -(function($) { +(function() { module("button: events"); diff --git a/tests/unit/datepicker/datepicker_core.js b/tests/unit/datepicker/datepicker_core.js index e17b239e5c..4abdfd106e 100644 --- a/tests/unit/datepicker/datepicker_core.js +++ b/tests/unit/datepicker/datepicker_core.js @@ -12,31 +12,19 @@ function equalsDate(d1, d2, message) { equal(d1.toString(), d2.toString(), message); } -function equalsDateArray(a1, a2, message) { - if (!a1 || !a2) { - ok(false, message + ' - missing dates'); - return; - } - a1[0] = (a1[0] ? new Date(a1[0].getFullYear(), a1[0].getMonth(), a1[0].getDate()) : ''); - a1[1] = (a1[1] ? new Date(a1[1].getFullYear(), a1[1].getMonth(), a1[1].getDate()) : ''); - a2[0] = (a2[0] ? new Date(a2[0].getFullYear(), a2[0].getMonth(), a2[0].getDate()) : ''); - a2[1] = (a2[1] ? new Date(a2[1].getFullYear(), a2[1].getMonth(), a2[1].getDate()) : ''); - deepEqual(a1, a2, message); -} - -function addMonths(date, offset) { +TestHelpers.addMonths = function(date, offset) { var maxDay = 32 - new Date(date.getFullYear(), date.getMonth() + offset, 32).getDate(); date.setDate(Math.min(date.getDate(), maxDay)); date.setMonth(date.getMonth() + offset); return date; -} +}; function init(id, options) { $.datepicker.setDefaults($.datepicker.regional['']); return $(id).datepicker($.extend({showAnim: ''}, options || {})); } -var PROP_NAME = 'datepicker'; +TestHelpers.PROP_NAME = 'datepicker'; (function($) { diff --git a/tests/unit/datepicker/datepicker_defaults.js b/tests/unit/datepicker/datepicker_defaults.js index 28e150791c..1e7d908529 100644 --- a/tests/unit/datepicker/datepicker_defaults.js +++ b/tests/unit/datepicker/datepicker_defaults.js @@ -2,8 +2,10 @@ * datepicker_defaults.js */ +/* var datepicker_defaults = { disabled: false }; -//TestHelpers.commonWidgetTests('datepicker', { defaults: datepicker_defaults }); +TestHelpers.commonWidgetTests('datepicker', { defaults: datepicker_defaults }); +*/ diff --git a/tests/unit/datepicker/datepicker_events.js b/tests/unit/datepicker/datepicker_events.js index e35be62cee..b710674727 100644 --- a/tests/unit/datepicker/datepicker_events.js +++ b/tests/unit/datepicker/datepicker_events.js @@ -30,7 +30,7 @@ test('events', function() { inp.val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); equal(selectedThis, inp[0], 'Callback selected this'); - equal(selectedInst, $.data(inp[0], PROP_NAME), 'Callback selected inst'); + equal(selectedInst, $.data(inp[0], TestHelpers.PROP_NAME), 'Callback selected inst'); equal(selectedDate, $.datepicker.formatDate('mm/dd/yy', date), 'Callback selected date'); inp.val('').datepicker('show'). @@ -59,7 +59,7 @@ test('events', function() { inp.simulate('keydown', {keyCode: $.ui.keyCode.PAGE_UP}); date.setMonth(date.getMonth() - 1); equal(selectedThis, inp[0], 'Callback change month/year this'); - equal(selectedInst, $.data(inp[0], PROP_NAME), 'Callback change month/year inst'); + equal(selectedInst, $.data(inp[0], TestHelpers.PROP_NAME), 'Callback change month/year inst'); equal(selectedDate, newMonthYear(date), 'Callback change month/year date - pgup'); inp.simulate('keydown', {keyCode: $.ui.keyCode.PAGE_DOWN}); @@ -107,7 +107,7 @@ test('events', function() { val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ESCAPE}); equal(selectedThis, inp[0], 'Callback close this'); - equal(selectedInst, $.data(inp[0], PROP_NAME), 'Callback close inst'); + equal(selectedInst, $.data(inp[0], TestHelpers.PROP_NAME), 'Callback close inst'); equal(selectedDate, '', 'Callback close date - esc'); inp.val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); diff --git a/tests/unit/datepicker/datepicker_methods.js b/tests/unit/datepicker/datepicker_methods.js index e7aa7602e1..5e692d1a0e 100644 --- a/tests/unit/datepicker/datepicker_methods.js +++ b/tests/unit/datepicker/datepicker_methods.js @@ -10,56 +10,56 @@ test('destroy', function() { var inl, inp = init('#inp'); ok(inp.is('.hasDatepicker'), 'Default - marker class set'); - ok($.data(inp[0], PROP_NAME), 'Default - instance present'); + ok($.data(inp[0], TestHelpers.PROP_NAME), 'Default - instance present'); ok(inp.next().is('#alt'), 'Default - button absent'); inp.datepicker('destroy'); inp = $('#inp'); ok(!inp.is('.hasDatepicker'), 'Default - marker class cleared'); - ok(!$.data(inp[0], PROP_NAME), 'Default - instance absent'); + ok(!$.data(inp[0], TestHelpers.PROP_NAME), 'Default - instance absent'); ok(inp.next().is('#alt'), 'Default - button absent'); // With button inp= init('#inp', {showOn: 'both'}); ok(inp.is('.hasDatepicker'), 'Button - marker class set'); - ok($.data(inp[0], PROP_NAME), 'Button - instance present'); + ok($.data(inp[0], TestHelpers.PROP_NAME), 'Button - instance present'); ok(inp.next().text() === '...', 'Button - button added'); inp.datepicker('destroy'); inp = $('#inp'); ok(!inp.is('.hasDatepicker'), 'Button - marker class cleared'); - ok(!$.data(inp[0], PROP_NAME), 'Button - instance absent'); + ok(!$.data(inp[0], TestHelpers.PROP_NAME), 'Button - instance absent'); ok(inp.next().is('#alt'), 'Button - button removed'); // With append text inp = init('#inp', {appendText: 'Testing'}); ok(inp.is('.hasDatepicker'), 'Append - marker class set'); - ok($.data(inp[0], PROP_NAME), 'Append - instance present'); + ok($.data(inp[0], TestHelpers.PROP_NAME), 'Append - instance present'); ok(inp.next().text() === 'Testing', 'Append - append text added'); inp.datepicker('destroy'); inp = $('#inp'); ok(!inp.is('.hasDatepicker'), 'Append - marker class cleared'); - ok(!$.data(inp[0], PROP_NAME), 'Append - instance absent'); + ok(!$.data(inp[0], TestHelpers.PROP_NAME), 'Append - instance absent'); ok(inp.next().is('#alt'), 'Append - append text removed'); // With both inp= init('#inp', {showOn: 'both', buttonImageOnly: true, buttonImage: 'img/calendar.gif', appendText: 'Testing'}); ok(inp.is('.hasDatepicker'), 'Both - marker class set'); - ok($.data(inp[0], PROP_NAME), 'Both - instance present'); + ok($.data(inp[0], TestHelpers.PROP_NAME), 'Both - instance present'); ok(inp.next()[0].nodeName.toLowerCase() === 'img', 'Both - button added'); ok(inp.next().next().text() === 'Testing', 'Both - append text added'); inp.datepicker('destroy'); inp = $('#inp'); ok(!inp.is('.hasDatepicker'), 'Both - marker class cleared'); - ok(!$.data(inp[0], PROP_NAME), 'Both - instance absent'); + ok(!$.data(inp[0], TestHelpers.PROP_NAME), 'Both - instance absent'); ok(inp.next().is('#alt'), 'Both - button and append text absent'); // Inline inl = init('#inl'); ok(inl.is('.hasDatepicker'), 'Inline - marker class set'); ok(inl.html() !== '', 'Inline - datepicker present'); - ok($.data(inl[0], PROP_NAME), 'Inline - instance present'); + ok($.data(inl[0], TestHelpers.PROP_NAME), 'Inline - instance present'); ok(inl.next().length === 0 || inl.next().is('p'), 'Inline - button absent'); inl.datepicker('destroy'); inl = $('#inl'); ok(!inl.is('.hasDatepicker'), 'Inline - marker class cleared'); ok(inl.html() === '', 'Inline - datepicker absent'); - ok(!$.data(inl[0], PROP_NAME), 'Inline - instance absent'); + ok(!$.data(inl[0], TestHelpers.PROP_NAME), 'Inline - instance absent'); ok(inl.next().length === 0 || inl.next().is('p'), 'Inline - button absent'); }); diff --git a/tests/unit/datepicker/datepicker_options.js b/tests/unit/datepicker/datepicker_options.js index a01b9c7e0a..7d3217364b 100644 --- a/tests/unit/datepicker/datepicker_options.js +++ b/tests/unit/datepicker/datepicker_options.js @@ -8,7 +8,7 @@ module("datepicker: options"); test('setDefaults', function() { expect( 3 ); - var inp = init('#inp'); + init('#inp'); equal($.datepicker._defaults.showOn, 'focus', 'Initial showOn'); $.datepicker.setDefaults({showOn: 'button'}); equal($.datepicker._defaults.showOn, 'button', 'Change default showOn'); @@ -19,7 +19,7 @@ test('setDefaults', function() { test('option', function() { expect( 17 ); var inp = init('#inp'), - inst = $.data(inp[0], PROP_NAME); + inst = $.data(inp[0], TestHelpers.PROP_NAME); // Set option equal(inst.settings.showOn, null, 'Initial setting showOn'); equal($.datepicker._get(inst, 'showOn'), 'focus', 'Initial instance showOn'); @@ -51,7 +51,7 @@ test('option', function() { test('change', function() { expect( 12 ); var inp = init('#inp'), - inst = $.data(inp[0], PROP_NAME); + inst = $.data(inp[0], TestHelpers.PROP_NAME); equal(inst.settings.showOn, null, 'Initial setting showOn'); equal($.datepicker._get(inst, 'showOn'), 'focus', 'Initial instance showOn'); equal($.datepicker._defaults.showOn, 'focus', 'Initial default showOn'); @@ -215,12 +215,12 @@ test('defaultDate', function() { inp.datepicker('option', {defaultDate: ' -1 m '}). datepicker('hide').val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - date = addMonths(new Date(), -1); + date = TestHelpers.addMonths(new Date(), -1); equalsDate(inp.datepicker('getDate'), date, 'Default date -1 m'); inp.datepicker('option', {defaultDate: '+2M'}). datepicker('hide').val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - date = addMonths(new Date(), 2); + date = TestHelpers.addMonths(new Date(), 2); equalsDate(inp.datepicker('getDate'), date, 'Default date +2M'); inp.datepicker('option', {defaultDate: '-2y'}). datepicker('hide').val('').datepicker('show'). @@ -236,7 +236,7 @@ test('defaultDate', function() { inp.datepicker('option', {defaultDate: '+1M +10d'}). datepicker('hide').val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - date = addMonths(new Date(), 1); + date = TestHelpers.addMonths(new Date(), 1); date.setDate(date.getDate() + 10); equalsDate(inp.datepicker('getDate'), date, 'Default date +1M +10d'); // String date values @@ -380,7 +380,7 @@ test('minMax', function() { simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); equalsDate(inp.datepicker('getDate'), date, 'Min/max - -1w, +1 M +10 D - ctrl+pgup'); - date = addMonths(new Date(), 1); + date = TestHelpers.addMonths(new Date(), 1); date.setDate(date.getDate() + 10); inp.val('').datepicker('show'); inp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}). @@ -665,16 +665,6 @@ function beforeDay(date) { (date.getDate() % 3 === 0 ? 'Divisble by 3' : '')]; } -function calcWeek(date) { - var doy = date.getDate() + 6, - m = date.getMonth() - 1; - for (; m >= 0; m--) { - doy += $.datepicker._getDaysInMonth(date.getFullYear(), m); - } - // Simple count from 01/01 starting at week 1 - return Math.floor(doy / 7); -} - test('callbacks', function() { expect( 13 ); // Before show diff --git a/tests/unit/datepicker/datepicker_tickets.js b/tests/unit/datepicker/datepicker_tickets.js index 57b25c3fff..ff5dfde637 100644 --- a/tests/unit/datepicker/datepicker_tickets.js +++ b/tests/unit/datepicker/datepicker_tickets.js @@ -8,7 +8,7 @@ module("datepicker: tickets"); // http://forum.jquery.com/topic/several-breaking-changes-in-jquery-ui-1-8rc1 test('beforeShowDay-getDate', function() { expect( 3 ); - var inp = init('#inp', {beforeShowDay: function(date) { inp.datepicker('getDate'); return [true, '']; }}), + var inp = init('#inp', {beforeShowDay: function() { inp.datepicker('getDate'); return [true, '']; }}), dp = $('#ui-datepicker-div'); inp.val('01/01/2010').datepicker('show'); // contains non-breaking space diff --git a/tests/unit/dialog/dialog_core.js b/tests/unit/dialog/dialog_core.js index e0a5c87017..a9e5e9be2c 100644 --- a/tests/unit/dialog/dialog_core.js +++ b/tests/unit/dialog/dialog_core.js @@ -12,13 +12,13 @@ function dlg() { return el.dialog('widget'); } -function isOpen(why) { +TestHelpers.isOpen = function(why) { ok(dlg().is(":visible"), why); -} +}; -function isNotOpen(why) { +TestHelpers.isNotOpen = function(why) { ok(!dlg().is(":visible"), why); -} +}; function drag(handle, dx, dy) { var d = dlg(); @@ -38,51 +38,43 @@ function drag(handle, dx, dy) { widthAfter = d.width(); } -function moved(dx, dy, msg) { +TestHelpers.dialogMoved = function(dx, dy, msg) { msg = msg ? msg + "." : ""; var actual = { left: Math.round(offsetAfter.left), top: Math.round(offsetAfter.top) }, expected = { left: Math.round(offsetBefore.left + dx), top: Math.round(offsetBefore.top + dy) }; deepEqual(actual, expected, 'dragged[' + dragged.dx + ', ' + dragged.dy + '] ' + msg); -} +}; -function shouldmove(why) { +TestHelpers.shouldmove = function(why) { var handle = $(".ui-dialog-titlebar", dlg()); drag(handle, 50, -50); - moved(50, -50, why); -} + TestHelpers.dialogMoved(50, -50, why); +}; -function shouldnotmove(why) { +TestHelpers.shouldnotmove = function(why) { var handle = $(".ui-dialog-titlebar", dlg()); drag(handle, 50, -50); - moved(0, 0, why); -} + TestHelpers.dialogMoved(0, 0, why); +}; -function resized(dw, dh, msg) { +TestHelpers.resized = function(dw, dh, msg) { msg = msg ? msg + "." : ""; var actual = { width: widthAfter, height: heightAfter }, expected = { width: widthBefore + dw, height: heightBefore + dh }; deepEqual(actual, expected, 'resized[' + dragged.dx + ', ' + dragged.dy + '] ' + msg); -} +}; -function shouldresize(why) { +TestHelpers.shouldresize = function(why) { var handle = $(".ui-resizable-se", dlg()); drag(handle, 50, 50); - resized(50, 50, why); -} + TestHelpers.resized(50, 50, why); +}; -function shouldnotresize(why) { +TestHelpers.shouldnotresize = function(why) { var handle = $(".ui-resizable-se", dlg()); drag(handle, 50, 50); - resized(0, 0, why); -} - -function broder(el, side){ - return parseInt(el.css('border-' + side + '-width'), 10); -} - -function margin(el, side) { - return parseInt(el.css('margin-' + side), 10); -} + TestHelpers.resized(0, 0, why); +}; (function($) { diff --git a/tests/unit/dialog/dialog_events.js b/tests/unit/dialog/dialog_events.js index 515bebdc19..38b75a714d 100644 --- a/tests/unit/dialog/dialog_events.js +++ b/tests/unit/dialog/dialog_events.js @@ -244,7 +244,7 @@ test("beforeClose", function() { } }); el.dialog('close'); - isOpen('beforeClose callback should prevent dialog from closing'); + TestHelpers.isOpen('beforeClose callback should prevent dialog from closing'); el.remove(); el = $('
').dialog(); @@ -256,7 +256,7 @@ test("beforeClose", function() { return false; }); el.dialog('close'); - isOpen('beforeClose callback should prevent dialog from closing'); + TestHelpers.isOpen('beforeClose callback should prevent dialog from closing'); el.remove(); el = $('
').dialog().bind('dialogbeforeclose', function(ev, ui) { @@ -266,7 +266,7 @@ test("beforeClose", function() { return false; }); el.dialog('close'); - isOpen('dialogbeforeclose event should prevent dialog from closing'); + TestHelpers.isOpen('dialogbeforeclose event should prevent dialog from closing'); el.remove(); }); diff --git a/tests/unit/dialog/dialog_methods.js b/tests/unit/dialog/dialog_methods.js index ba0c2bd412..3c80a9bea1 100644 --- a/tests/unit/dialog/dialog_methods.js +++ b/tests/unit/dialog/dialog_methods.js @@ -25,7 +25,7 @@ test("init", function() { ok(true, '.dialog() called on disconnected DOMElement - removed'); el = $('
').dialog(); - var foo = el.dialog("option", "foo"); + el.dialog("option", "foo"); el.remove(); ok(true, 'arbitrary option getter after init'); diff --git a/tests/unit/dialog/dialog_options.js b/tests/unit/dialog/dialog_options.js index ba217c6f46..1c823868e3 100644 --- a/tests/unit/dialog/dialog_options.js +++ b/tests/unit/dialog/dialog_options.js @@ -9,11 +9,11 @@ test("autoOpen", function() { expect(2); el = $('
').dialog({ autoOpen: false }); - isNotOpen('.dialog({ autoOpen: false })'); + TestHelpers.isNotOpen('.dialog({ autoOpen: false })'); el.remove(); el = $('
').dialog({ autoOpen: true }); - isOpen('.dialog({ autoOpen: true })'); + TestHelpers.isOpen('.dialog({ autoOpen: true })'); el.remove(); }); @@ -22,12 +22,12 @@ test("buttons", function() { var btn, i, newButtons, buttons = { - "Ok": function(ev, ui) { + "Ok": function( ev ) { ok(true, "button click fires callback"); equal(this, el[0], "context of callback"); equal(ev.target, btn[0], "event target"); }, - "Cancel": function(ev, ui) { + "Cancel": function( ev ) { ok(true, "button click fires callback"); equal(this, el[0], "context of callback"); equal(ev.target, btn[1], "event target"); @@ -39,7 +39,7 @@ test("buttons", function() { equal(btn.length, 2, "number of buttons"); i = 0; - $.each(buttons, function(key, val) { + $.each(buttons, function( key ) { equal(btn.eq(i).text(), key, "text of button " + (i+1)); i++; }); @@ -50,7 +50,7 @@ test("buttons", function() { btn.trigger("click"); newButtons = { - "Close": function(ev, ui) { + "Close": function( ev ) { ok(true, "button click fires callback"); equal(this, el[0], "context of callback"); equal(ev.target, btn[0], "event target"); @@ -66,7 +66,7 @@ test("buttons", function() { btn.trigger('click'); i = 0; - $.each(newButtons, function(key, val) { + $.each(newButtons, function( key ) { equal(btn.eq(i).text(), key, "text of button " + (i+1)); i += 1; }); @@ -166,15 +166,15 @@ test("draggable", function() { expect(4); el = $('
').dialog({ draggable: false }); - shouldnotmove(); + TestHelpers.shouldnotmove(); el.dialog('option', 'draggable', true); - shouldmove(); + TestHelpers.shouldmove(); el.remove(); el = $('
').dialog({ draggable: true }); - shouldmove(); + TestHelpers.shouldmove(); el.dialog('option', 'draggable', false); - shouldnotmove(); + TestHelpers.shouldnotmove(); el.remove(); }); @@ -395,15 +395,15 @@ test("resizable", function() { expect(4); el = $('
').dialog(); - shouldresize("[default]"); + TestHelpers.shouldresize("[default]"); el.dialog('option', 'resizable', false); - shouldnotresize('disabled after init'); + TestHelpers.shouldnotresize('disabled after init'); el.remove(); el = $('
').dialog({ resizable: false }); - shouldnotresize("disabled in init options"); + TestHelpers.shouldnotresize("disabled in init options"); el.dialog('option', 'resizable', true); - shouldresize('enabled after init'); + TestHelpers.shouldresize('enabled after init'); el.remove(); }); diff --git a/tests/unit/dialog/dialog_tickets.js b/tests/unit/dialog/dialog_tickets.js index e17d55a159..cf4ab02191 100644 --- a/tests/unit/dialog/dialog_tickets.js +++ b/tests/unit/dialog/dialog_tickets.js @@ -39,18 +39,18 @@ test("#4826: setting resizable false toggles resizable on dialog", function() { var i; el = $('
').dialog({ resizable: false }); - shouldnotresize("[default]"); + TestHelpers.shouldnotresize("[default]"); for (i=0; i<2; i++) { el.dialog('close').dialog('open'); - shouldnotresize('initialized with resizable false toggle ('+ (i+1) +')'); + TestHelpers.shouldnotresize('initialized with resizable false toggle ('+ (i+1) +')'); } el.remove(); el = $('
').dialog({ resizable: true }); - shouldresize("[default]"); + TestHelpers.shouldresize("[default]"); for (i=0; i<2; i++) { el.dialog('close').dialog('option', 'resizable', false).dialog('open'); - shouldnotresize('set option resizable false toggle ('+ (i+1) +')'); + TestHelpers.shouldnotresize('set option resizable false toggle ('+ (i+1) +')'); } el.remove(); diff --git a/tests/unit/draggable/draggable_core.js b/tests/unit/draggable/draggable_core.js index 9193881ad3..80d9ca83e8 100644 --- a/tests/unit/draggable/draggable_core.js +++ b/tests/unit/draggable/draggable_core.js @@ -5,7 +5,6 @@ var el, offsetBefore, offsetAfter, dragged; function drag(handle, dx, dy) { - var element = el.data("draggable").element; offsetBefore = el.offset(); $(handle).simulate("drag", { dx: dx || 0, @@ -22,8 +21,8 @@ function moved(dx, dy, msg) { deepEqual(actual, expected, 'dragged[' + dragged.dx + ', ' + dragged.dy + '] ' + msg); } -function restoreScroll(what) { - if(what) { +TestHelpers.restoreScroll = function( what ) { + if( what ) { $(document).scrollTop(0); $(document).scrollLeft(0); } else { $("#main")[0].scrollTop = 0; $("#main")[0].scrollLeft = 0; diff --git a/tests/unit/draggable/draggable_options.js b/tests/unit/draggable/draggable_options.js index ea4611d692..4f77815154 100644 --- a/tests/unit/draggable/draggable_options.js +++ b/tests/unit/draggable/draggable_options.js @@ -210,7 +210,7 @@ test("{ cursor: 'auto' }, default", function() { el = $("#draggable2").draggable({ cursor: expected, - start: function(event, ui) { + start: function() { actual = getCursor(); } }); @@ -234,7 +234,7 @@ test("{ cursor: 'move' }", function() { el = $("#draggable2").draggable({ cursor: expected, - start: function(event, ui) { + start: function() { actual = getCursor(); } }); @@ -449,7 +449,7 @@ test("{ helper: 'original' }, relative, with scroll offset on parent", function( setScroll(); testScroll('absolute'); - restoreScroll(); + TestHelpers.restoreScroll(); }); @@ -466,7 +466,7 @@ test("{ helper: 'original' }, relative, with scroll offset on root", function() setScroll('root'); testScroll('absolute'); - restoreScroll('root'); + TestHelpers.restoreScroll('root'); }); @@ -486,8 +486,8 @@ test("{ helper: 'original' }, relative, with scroll offset on root and parent", setScroll('root'); testScroll('absolute'); - restoreScroll(); - restoreScroll('root'); + TestHelpers.restoreScroll(); + TestHelpers.restoreScroll('root'); }); @@ -504,7 +504,7 @@ test("{ helper: 'original' }, absolute, with scroll offset on parent", function( setScroll(); testScroll('absolute'); - restoreScroll(); + TestHelpers.restoreScroll(); }); @@ -521,7 +521,7 @@ test("{ helper: 'original' }, absolute, with scroll offset on root", function() setScroll('root'); testScroll('absolute'); - restoreScroll('root'); + TestHelpers.restoreScroll('root'); }); @@ -541,8 +541,8 @@ test("{ helper: 'original' }, absolute, with scroll offset on root and parent", setScroll('root'); testScroll('absolute'); - restoreScroll(); - restoreScroll('root'); + TestHelpers.restoreScroll(); + TestHelpers.restoreScroll('root'); }); @@ -559,7 +559,7 @@ test("{ helper: 'original' }, fixed, with scroll offset on parent", function() { setScroll(); testScroll('absolute'); - restoreScroll(); + TestHelpers.restoreScroll(); }); @@ -576,7 +576,7 @@ test("{ helper: 'original' }, fixed, with scroll offset on root", function() { setScroll('root'); testScroll('absolute'); - restoreScroll('root'); + TestHelpers.restoreScroll('root'); }); test("{ helper: 'original' }, fixed, with scroll offset on root and parent", function() { @@ -595,8 +595,8 @@ test("{ helper: 'original' }, fixed, with scroll offset on root and parent", fun setScroll('root'); testScroll('absolute'); - restoreScroll(); - restoreScroll('root'); + TestHelpers.restoreScroll(); + TestHelpers.restoreScroll('root'); }); @@ -639,7 +639,7 @@ test("{ helper: 'clone' }, absolute with scroll offset on parent", function() { drag(el, 1, 1); deepEqual({ top: helperOffset.top-1, left: helperOffset.left-1 }, origOffset, 'dragged[' + dragged.dx + ', ' + dragged.dy + '] '); - restoreScroll(); + TestHelpers.restoreScroll(); }); @@ -668,7 +668,7 @@ test("{ helper: 'clone' }, absolute with scroll offset on root", function() { drag(el, 1, 1); deepEqual({ top: helperOffset.top-1, left: helperOffset.left-1 }, origOffset, 'dragged[' + dragged.dx + ', ' + dragged.dy + '] '); - restoreScroll('root'); + TestHelpers.restoreScroll('root'); }); @@ -698,8 +698,8 @@ test("{ helper: 'clone' }, absolute with scroll offset on root and parent", func drag(el, 1, 1); deepEqual({ top: helperOffset.top-1, left: helperOffset.left-1 }, origOffset, 'dragged[' + dragged.dx + ', ' + dragged.dy + '] '); - restoreScroll('root'); - restoreScroll(); + TestHelpers.restoreScroll('root'); + TestHelpers.restoreScroll(); }); @@ -710,7 +710,7 @@ test("{ opacity: 0.5 }", function() { var opacity = null; el = $("#draggable2").draggable({ opacity: 0.5, - start: function(event, ui) { + start: function() { opacity = $(this).css("opacity"); } }); @@ -726,11 +726,11 @@ test("{ zIndex: 10 }", function() { expect(1); var actual, - expected = 10, - zIndex = null; + expected = 10; + el = $("#draggable2").draggable({ zIndex: expected, - start: function(event, ui) { + start: function() { actual = $(this).css("zIndex"); } }); diff --git a/tests/unit/droppable/droppable_core.js b/tests/unit/droppable/droppable_core.js index 3f709d25d0..1ec50eecce 100644 --- a/tests/unit/droppable/droppable_core.js +++ b/tests/unit/droppable/droppable_core.js @@ -2,15 +2,15 @@ * droppable_core.js */ -var el, drg; +var el; -function shouldBeDroppable() { +TestHelpers.shouldBeDroppable = function() { ok(false, 'missing test - untested code is broken code'); -} +}; -function shouldNotBeDroppable() { +TestHelpers.shouldNotBeDroppable = function() { ok(false, 'missing test - untested code is broken code'); -} +}; (function($) { @@ -27,7 +27,7 @@ test("element types", function() { el = $(document.createElement(typeName)).appendTo('body'); (typeName === 'table' && el.append("content")); el.droppable(); - shouldBeDroppable(); + TestHelpers.shouldBeDroppable(); el.droppable("destroy"); el.remove(); }); diff --git a/tests/unit/droppable/droppable_events.js b/tests/unit/droppable/droppable_events.js index f22a035407..2e01b0c9c3 100644 --- a/tests/unit/droppable/droppable_events.js +++ b/tests/unit/droppable/droppable_events.js @@ -5,6 +5,10 @@ module("droppable: events"); +// this is here to make JSHint pass "unused", and we don't want to +// remove the parameter for when we finally implement +$.noop(); + test("activate", function() { ok(false, 'missing test - untested code is broken code'); }); diff --git a/tests/unit/droppable/droppable_methods.js b/tests/unit/droppable/droppable_methods.js index 8fd49d2657..51581b425b 100644 --- a/tests/unit/droppable/droppable_methods.js +++ b/tests/unit/droppable/droppable_methods.js @@ -48,16 +48,16 @@ test("destroy", function() { test("enable", function() { expect(7); el = $("#droppable1").droppable({ disabled: true }); - shouldNotBeDroppable(); + TestHelpers.shouldNotBeDroppable(); el.droppable("enable"); - shouldBeDroppable(); + TestHelpers.shouldBeDroppable(); equal(el.droppable("option", "disabled"), false, "disabled option getter"); el.droppable("destroy"); el.droppable({ disabled: true }); - shouldNotBeDroppable(); + TestHelpers.shouldNotBeDroppable(); el.droppable("option", "disabled", false); equal(el.droppable("option", "disabled"), false, "disabled option setter"); - shouldBeDroppable(); + TestHelpers.shouldBeDroppable(); var expected = $('
').droppable(), actual = expected.droppable('enable'); @@ -67,16 +67,16 @@ test("enable", function() { test("disable", function() { expect(7); el = $("#droppable1").droppable({ disabled: false }); - shouldBeDroppable(); + TestHelpers.shouldBeDroppable(); el.droppable("disable"); - shouldNotBeDroppable(); + TestHelpers.shouldNotBeDroppable(); equal(el.droppable("option", "disabled"), true, "disabled option getter"); el.droppable("destroy"); el.droppable({ disabled: false }); - shouldBeDroppable(); + TestHelpers.shouldBeDroppable(); el.droppable("option", "disabled", true); equal(el.droppable("option", "disabled"), true, "disabled option setter"); - shouldNotBeDroppable(); + TestHelpers.shouldNotBeDroppable(); var expected = $('
').droppable(), actual = expected.droppable('disable'); diff --git a/tests/unit/effects/effects_core.js b/tests/unit/effects/effects_core.js index c4e5c24f92..26390b7d34 100644 --- a/tests/unit/effects/effects_core.js +++ b/tests/unit/effects/effects_core.js @@ -12,10 +12,7 @@ function notPresent( value, array, message ) { var minDuration = 15, // duration is used for "long" animates where we plan on testing properties during animation - duration = 200, - - // mid is used for testing in the "middle" of the "duration" animations - mid = duration / 2; + duration = 200; module( "effects.core" ); @@ -58,8 +55,7 @@ test( "createWrapper and removeWrapper retain focused elements (#7595)", functio module( "effects.core: animateClass" ); asyncTest( "animateClass works with borderStyle", function() { - var test = $("div.animateClass"), - count = 0; + var test = $("div.animateClass"); expect(3); test.toggleClass("testAddBorder", minDuration, function() { test.toggleClass("testAddBorder", minDuration, function() { @@ -73,8 +69,8 @@ asyncTest( "animateClass works with borderStyle", function() { asyncTest( "animateClass works with colors", function() { var test = $("div.animateClass"), - count = 0, oldStep = jQuery.fx.step.backgroundColor; + expect(2); // we want to catch the first frame of animation @@ -102,7 +98,7 @@ asyncTest( "animateClass works with colors", function() { asyncTest( "animateClass calls step option", 1, function() { var test = jQuery( "div.animateClass" ), - step = function( fx ) { + step = function() { ok( true, "Step Function Called" ); test.stop(); start(); @@ -216,7 +212,7 @@ $.each( $.effects.effect, function( effect ) { equal( hidden.css("display"), "block", "Hidden is shown after .show(\"" +effect+ "\", time)" ); })).queue( queueTest() ).hide( effect, minDuration, queueTest(function() { equal( hidden.css("display"), "none", "Back to hidden after .hide(\"" +effect+ "\", time)" ); - })).queue( queueTest(function(next) { + })).queue( queueTest(function() { deepEqual( hidden.queue(), ["inprogress"], "Only the inprogress sentinel remains"); start(); })); diff --git a/tests/unit/menu/menu_events.js b/tests/unit/menu/menu_events.js index d69fc46a33..a94968138e 100644 --- a/tests/unit/menu/menu_events.js +++ b/tests/unit/menu/menu_events.js @@ -13,7 +13,7 @@ module( "menu: events", { test( "handle click on menu", function() { expect( 1 ); var element = $( "#menu1" ).menu({ - select: function( event, ui ) { + select: function() { log(); } }); @@ -29,7 +29,7 @@ test( "handle click on menu", function() { test( "handle click on custom item menu", function() { expect( 1 ); var element = $( "#menu5" ).menu({ - select: function( event, ui ) { + select: function() { log(); }, menus: "div" @@ -47,7 +47,7 @@ asyncTest( "handle blur", function() { expect( 1 ); var blurHandled = false, element = $( "#menu1" ).menu({ - blur: function( event, ui ) { + blur: function( event ) { // Ignore duplicate blur event fired by IE if ( !blurHandled ) { blurHandled = true; @@ -69,7 +69,7 @@ asyncTest( "handle blur via click outside", function() { expect( 1 ); var blurHandled = false, element = $( "#menu1" ).menu({ - blur: function( event, ui ) { + blur: function( event ) { // Ignore duplicate blur event fired by IE if ( !blurHandled ) { blurHandled = true; @@ -90,7 +90,7 @@ asyncTest( "handle blur via click outside", function() { test( "handle focus of menu with active item", function() { expect( 1 ); var element = $( "#menu1" ).menu({ - focus: function( event, ui ) { + focus: function( event ) { log( $( event.target ).find( ".ui-state-focus" ).parent().index() ); } }); @@ -168,7 +168,7 @@ test( "handle keyboard navigation on menu without scroll and without submenus", select: function( event, ui ) { log( $( ui.item[0] ).text() ); }, - focus: function( event, ui ) { + focus: function( event ) { log( $( event.target ).find( ".ui-state-focus" ).parent().index() ); } }); @@ -230,13 +230,13 @@ asyncTest( "handle keyboard navigation on menu without scroll and with submenus" select: function( event, ui ) { log( $( ui.item[0] ).text() ); }, - focus: function( event, ui ) { + focus: function( event ) { log( $( event.target ).find( ".ui-state-focus" ).parent().index() ); } }); log( "keydown", true ); - element.one( "menufocus", function( event, ui ) { + element.one( "menufocus", function() { element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); equal( logOutput(), "keydown,1,2", "Keydown DOWN" ); @@ -350,7 +350,7 @@ test( "handle keyboard navigation on menu with scroll and without submenus", fun select: function( event, ui ) { log( $( ui.item[0] ).text() ); }, - focus: function( event, ui ) { + focus: function( event ) { log( $( event.target ).find( ".ui-state-focus" ).parent().index()); } }); @@ -421,13 +421,13 @@ asyncTest( "handle keyboard navigation on menu with scroll and with submenus", f select: function( event, ui ) { log( $( ui.item[0] ).text() ); }, - focus: function( event, ui ) { + focus: function( event ) { log( $( event.target ).find( ".ui-state-focus" ).parent().index()); } }); log( "keydown", true ); - element.one( "menufocus", function( event, ui ) { + element.one( "menufocus", function() { element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); equal( logOutput(), "keydown,1,2", "Keydown DOWN" ); @@ -516,13 +516,13 @@ asyncTest( "handle keyboard navigation and mouse click on menu with disabled ite select: function( event, ui ) { log( $( ui.item[0] ).text() ); }, - focus: function( event, ui ) { + focus: function( event ) { log( $( event.target ).find( ".ui-state-focus" ).parent().index()); } }); log( "keydown", true ); - element.one( "menufocus", function( event, ui ) { + element.one( "menufocus", function() { element.simulate( "keydown", { keyCode: $.ui.keyCode.DOWN } ); element.simulate( "keydown", { keyCode: $.ui.keyCode.ENTER } ); equal( logOutput(), "keydown,1", "Keydown focus but not select disabled item" ); @@ -564,13 +564,13 @@ asyncTest( "handle keyboard navigation and mouse click on menu with disabled ite test( "handle keyboard navigation with spelling of menu items", function() { expect( 2 ); var element = $( "#menu2" ).menu({ - focus: function( event, ui ) { + focus: function( event ) { log( $( event.target ).find( ".ui-state-focus" ).parent().index() ); } }); log( "keydown", true ); - element.one( "menufocus", function( event, ui ) { + element.one( "menufocus", function() { element.simulate( "keydown", { keyCode: 65 } ); element.simulate( "keydown", { keyCode: 68 } ); element.simulate( "keydown", { keyCode: 68 } ); diff --git a/tests/unit/menu/menu_methods.js b/tests/unit/menu/menu_methods.js index f9241f27b6..c49783c3e4 100644 --- a/tests/unit/menu/menu_methods.js +++ b/tests/unit/menu/menu_methods.js @@ -29,7 +29,7 @@ test( "destroy", function() { test( "enable/disable", function() { expect( 3 ); var element = $( "#menu1" ).menu({ - select: function( event, ui ) { + select: function() { log(); } }); diff --git a/tests/unit/menu/menu_options.js b/tests/unit/menu/menu_options.js index a8b0292013..2c8749e3ca 100644 --- a/tests/unit/menu/menu_options.js +++ b/tests/unit/menu/menu_options.js @@ -14,7 +14,7 @@ test( "{ disabled: true }", function() { expect( 2 ); var element = $( "#menu1" ).menu({ disabled: true, - select: function(event, ui) { + select: function() { log(); } }); @@ -29,7 +29,7 @@ test( "{ disabled: false }", function() { expect( 2 ); var element = $( "#menu1" ).menu({ disabled: false, - select: function( event, ui ) { + select: function() { log(); } }); diff --git a/tests/unit/resizable/resizable_core.js b/tests/unit/resizable/resizable_core.js index aef2ae15c7..8cc6cec82a 100644 --- a/tests/unit/resizable/resizable_core.js +++ b/tests/unit/resizable/resizable_core.js @@ -2,9 +2,7 @@ * resizable_core.js */ -var el; - -var drag = function(el, dx, dy, complete) { +TestHelpers.resizableDrag = function(el, dx, dy, complete) { // speed = sync -> Drag syncrhonously. // speed = fast|slow -> Drag asyncrhonously - animated. @@ -46,10 +44,10 @@ test("n", function() { var handle = '.ui-resizable-n', target = $('#resizable1').resizable({ handles: 'all' }); - drag(handle, 0, -50); + TestHelpers.resizableDrag(handle, 0, -50); equal( target.height(), 150, "compare height" ); - drag(handle, 0, 50); + TestHelpers.resizableDrag(handle, 0, 50); equal( target.height(), 100, "compare height" ); }); @@ -58,10 +56,10 @@ test("s", function() { var handle = '.ui-resizable-s', target = $('#resizable1').resizable({ handles: 'all' }); - drag(handle, 0, 50); + TestHelpers.resizableDrag(handle, 0, 50); equal( target.height(), 150, "compare height" ); - drag(handle, 0, -50); + TestHelpers.resizableDrag(handle, 0, -50); equal( target.height(), 100, "compare height" ); }); @@ -70,10 +68,10 @@ test("e", function() { var handle = '.ui-resizable-e', target = $('#resizable1').resizable({ handles: 'all' }); - drag(handle, 50); + TestHelpers.resizableDrag(handle, 50); equal( target.width(), 150, "compare width"); - drag(handle, -50); + TestHelpers.resizableDrag(handle, -50); equal( target.width(), 100, "compare width" ); }); @@ -82,10 +80,10 @@ test("w", function() { var handle = '.ui-resizable-w', target = $('#resizable1').resizable({ handles: 'all' }); - drag(handle, -50); + TestHelpers.resizableDrag(handle, -50); equal( target.width(), 150, "compare width" ); - drag(handle, 50); + TestHelpers.resizableDrag(handle, 50); equal( target.width(), 100, "compare width" ); }); @@ -94,11 +92,11 @@ test("ne", function() { var handle = '.ui-resizable-ne', target = $('#resizable1').css({ overflow: 'hidden' }).resizable({ handles: 'all' }); - drag(handle, -50, -50); + TestHelpers.resizableDrag(handle, -50, -50); equal( target.width(), 50, "compare width" ); equal( target.height(), 150, "compare height" ); - drag(handle, 50, 50); + TestHelpers.resizableDrag(handle, 50, 50); equal( target.width(), 100, "compare width" ); equal( target.height(), 100, "compare height" ); }); @@ -108,11 +106,11 @@ test("se", function() { var handle = '.ui-resizable-se', target = $('#resizable1').resizable({ handles: 'all' }); - drag(handle, 50, 50); + TestHelpers.resizableDrag(handle, 50, 50); equal( target.width(), 150, "compare width" ); equal( target.height(), 150, "compare height" ); - drag(handle, -50, -50); + TestHelpers.resizableDrag(handle, -50, -50); equal( target.width(), 100, "compare width" ); equal( target.height(), 100, "compare height" ); }); @@ -122,11 +120,11 @@ test("sw", function() { var handle = '.ui-resizable-sw', target = $('#resizable1').resizable({ handles: 'all' }); - drag(handle, -50, -50); + TestHelpers.resizableDrag(handle, -50, -50); equal( target.width(), 150, "compare width" ); equal( target.height(), 50, "compare height" ); - drag(handle, 50, 50); + TestHelpers.resizableDrag(handle, 50, 50); equal( target.width(), 100, "compare width" ); equal( target.height(), 100, "compare height" ); }); @@ -136,11 +134,11 @@ test("nw", function() { var handle = '.ui-resizable-nw', target = $('#resizable1').resizable({ handles: 'all' }); - drag(handle, -50, -50); + TestHelpers.resizableDrag(handle, -50, -50); equal( target.width(), 150, "compare width" ); equal( target.height(), 150, "compare height" ); - drag(handle, 50, 50); + TestHelpers.resizableDrag(handle, 50, 50); equal( target.width(), 100, "compare width" ); equal( target.height(), 100, "compare height" ); }); diff --git a/tests/unit/resizable/resizable_events.js b/tests/unit/resizable/resizable_events.js index 52d55731c9..d7793ff2f3 100644 --- a/tests/unit/resizable/resizable_events.js +++ b/tests/unit/resizable/resizable_events.js @@ -5,4 +5,8 @@ module("resizable: events"); +// this is here to make JSHint pass "unused", and we don't want to +// remove the parameter for when we finally implement +$.noop(); + })(jQuery); diff --git a/tests/unit/resizable/resizable_methods.js b/tests/unit/resizable/resizable_methods.js index 87859acf70..b12f3035a2 100644 --- a/tests/unit/resizable/resizable_methods.js +++ b/tests/unit/resizable/resizable_methods.js @@ -5,5 +5,8 @@ module("resizable: methods"); +// this is here to make JSHint pass "unused", and we don't want to +// remove the parameter for when we finally implement +$.noop(); })(jQuery); diff --git a/tests/unit/resizable/resizable_options.js b/tests/unit/resizable/resizable_options.js index e10a55a31f..c17f329fd8 100644 --- a/tests/unit/resizable/resizable_options.js +++ b/tests/unit/resizable/resizable_options.js @@ -10,11 +10,11 @@ test("aspectRatio: 'preserve' (e)", function() { var handle = '.ui-resizable-e', target = $('#resizable1').resizable({ aspectRatio: 'preserve', handles: 'all', minWidth: 70, minHeight: 50, maxWidth: 150, maxHeight: 130 }); - drag(handle, 80); + TestHelpers.resizableDrag(handle, 80); equal( target.width(), 130, "compare maxWidth"); equal( target.height(), 130, "compare maxHeight"); - drag(handle, -130); + TestHelpers.resizableDrag(handle, -130); equal( target.width(), 70, "compare minWidth"); equal( target.height(), 70, "compare minHeight"); }); @@ -24,11 +24,11 @@ test("aspectRatio: 'preserve' (w)", function() { var handle = '.ui-resizable-w', target = $('#resizable1').resizable({ aspectRatio: 'preserve', handles: 'all', minWidth: 70, minHeight: 50, maxWidth: 150, maxHeight: 130 }); - drag(handle, -80); + TestHelpers.resizableDrag(handle, -80); equal( target.width(), 130, "compare maxWidth"); equal( target.height(), 130, "compare maxHeight"); - drag(handle, 130); + TestHelpers.resizableDrag(handle, 130); equal( target.width(), 70, "compare minWidth"); equal( target.height(), 70, "compare minHeight"); }); @@ -38,11 +38,11 @@ test("aspectRatio: 'preserve' (n)", function() { var handle = '.ui-resizable-n', target = $('#resizable1').resizable({ aspectRatio: 'preserve', handles: 'all', minWidth: 70, minHeight: 50, maxWidth: 150, maxHeight: 130 }); - drag(handle, 0, -80); + TestHelpers.resizableDrag(handle, 0, -80); equal( target.width(), 130, "compare maxWidth"); equal( target.height(), 130, "compare maxHeight"); - drag(handle, 0, 80); + TestHelpers.resizableDrag(handle, 0, 80); equal( target.width(), 70, "compare minWidth"); equal( target.height(), 70, "compare minHeight"); }); @@ -52,11 +52,11 @@ test("aspectRatio: 'preserve' (s)", function() { var handle = '.ui-resizable-s', target = $('#resizable1').resizable({ aspectRatio: 'preserve', handles: 'all', minWidth: 70, minHeight: 50, maxWidth: 150, maxHeight: 130 }); - drag(handle, 0, 80); + TestHelpers.resizableDrag(handle, 0, 80); equal( target.width(), 130, "compare maxWidth"); equal( target.height(), 130, "compare maxHeight"); - drag(handle, 0, -80); + TestHelpers.resizableDrag(handle, 0, -80); equal( target.width(), 70, "compare minWidth"); equal( target.height(), 70, "compare minHeight"); }); @@ -66,11 +66,11 @@ test("aspectRatio: 'preserve' (se)", function() { var handle = '.ui-resizable-se', target = $('#resizable1').resizable({ aspectRatio: 'preserve', handles: 'all', minWidth: 70, minHeight: 50, maxWidth: 150, maxHeight: 130 }); - drag(handle, 80, 80); + TestHelpers.resizableDrag(handle, 80, 80); equal( target.width(), 130, "compare maxWidth"); equal( target.height(), 130, "compare maxHeight"); - drag(handle, -80, -80); + TestHelpers.resizableDrag(handle, -80, -80); equal( target.width(), 70, "compare minWidth"); equal( target.height(), 70, "compare minHeight"); }); @@ -80,11 +80,11 @@ test("aspectRatio: 'preserve' (sw)", function() { var handle = '.ui-resizable-sw', target = $('#resizable1').resizable({ aspectRatio: 'preserve', handles: 'all', minWidth: 70, minHeight: 50, maxWidth: 150, maxHeight: 130 }); - drag(handle, -80, 80); + TestHelpers.resizableDrag(handle, -80, 80); equal( target.width(), 130, "compare maxWidth"); equal( target.height(), 130, "compare maxHeight"); - drag(handle, 80, -80); + TestHelpers.resizableDrag(handle, 80, -80); equal( target.width(), 70, "compare minWidth"); equal( target.height(), 70, "compare minHeight"); }); @@ -94,11 +94,11 @@ test("aspectRatio: 'preserve' (ne)", function() { var handle = '.ui-resizable-ne', target = $('#resizable1').resizable({ aspectRatio: 'preserve', handles: 'all', minWidth: 70, minHeight: 50, maxWidth: 150, maxHeight: 130 }); - drag(handle, 80, -80); + TestHelpers.resizableDrag(handle, 80, -80); equal( target.width(), 130, "compare maxWidth"); equal( target.height(), 130, "compare maxHeight"); - drag(handle, -80, 80); + TestHelpers.resizableDrag(handle, -80, 80); equal( target.width(), 70, "compare minWidth"); equal( target.height(), 70, "compare minHeight"); }); @@ -108,11 +108,11 @@ test("grid", function() { var handle = '.ui-resizable-se', target = $('#resizable1').resizable({ handles: 'all', grid: [0, 20] }); - drag(handle, 3, 9); + TestHelpers.resizableDrag(handle, 3, 9); equal( target.width(), 103, "compare width"); equal( target.height(), 100, "compare height"); - drag(handle, 15, 11); + TestHelpers.resizableDrag(handle, 15, 11); equal( target.width(), 118, "compare width"); equal( target.height(), 120, "compare height"); }); @@ -122,11 +122,11 @@ test("grid (wrapped)", function() { var handle = '.ui-resizable-se', target = $('#resizable2').resizable({ handles: 'all', grid: [0, 20] }); - drag(handle, 3, 9); + TestHelpers.resizableDrag(handle, 3, 9); equal( target.width(), 103, "compare width"); equal( target.height(), 100, "compare height"); - drag(handle, 15, 11); + TestHelpers.resizableDrag(handle, 15, 11); equal( target.width(), 118, "compare width"); equal( target.height(), 120, "compare height"); }); @@ -136,11 +136,11 @@ test("ui-resizable-se { handles: 'all', minWidth: 60, minHeight: 60, maxWidth: 1 var handle = '.ui-resizable-se', target = $('#resizable1').resizable({ handles: 'all', minWidth: 60, minHeight: 60, maxWidth: 100, maxHeight: 100 }); - drag(handle, -50, -50); + TestHelpers.resizableDrag(handle, -50, -50); equal( target.width(), 60, "compare minWidth" ); equal( target.height(), 60, "compare minHeight" ); - drag(handle, 70, 70); + TestHelpers.resizableDrag(handle, 70, 70); equal( target.width(), 100, "compare maxWidth" ); equal( target.height(), 100, "compare maxHeight" ); }); @@ -150,11 +150,11 @@ test("ui-resizable-sw { handles: 'all', minWidth: 60, minHeight: 60, maxWidth: 1 var handle = '.ui-resizable-sw', target = $('#resizable1').resizable({ handles: 'all', minWidth: 60, minHeight: 60, maxWidth: 100, maxHeight: 100 }); - drag(handle, 50, -50); + TestHelpers.resizableDrag(handle, 50, -50); equal( target.width(), 60, "compare minWidth" ); equal( target.height(), 60, "compare minHeight" ); - drag(handle, -70, 70); + TestHelpers.resizableDrag(handle, -70, 70); equal( target.width(), 100, "compare maxWidth" ); equal( target.height(), 100, "compare maxHeight" ); }); @@ -164,11 +164,11 @@ test("ui-resizable-ne { handles: 'all', minWidth: 60, minHeight: 60, maxWidth: 1 var handle = '.ui-resizable-ne', target = $('#resizable1').resizable({ handles: 'all', minWidth: 60, minHeight: 60, maxWidth: 100, maxHeight: 100 }); - drag(handle, -50, 50); + TestHelpers.resizableDrag(handle, -50, 50); equal( target.width(), 60, "compare minWidth" ); equal( target.height(), 60, "compare minHeight" ); - drag(handle, 70, -70); + TestHelpers.resizableDrag(handle, 70, -70); equal( target.width(), 100, "compare maxWidth" ); equal( target.height(), 100, "compare maxHeight" ); }); @@ -178,11 +178,11 @@ test("ui-resizable-nw { handles: 'all', minWidth: 60, minHeight: 60, maxWidth: 1 var handle = '.ui-resizable-nw', target = $('#resizable1').resizable({ handles: 'all', minWidth: 60, minHeight: 60, maxWidth: 100, maxHeight: 100 }); - drag(handle, 70, 70); + TestHelpers.resizableDrag(handle, 70, 70); equal( target.width(), 60, "compare minWidth" ); equal( target.height(), 60, "compare minHeight" ); - drag(handle, -70, -70); + TestHelpers.resizableDrag(handle, -70, -70); equal( target.width(), 100, "compare maxWidth" ); equal( target.height(), 100, "compare maxHeight" ); }); diff --git a/tests/unit/selectable/selectable_core.js b/tests/unit/selectable/selectable_core.js index 18ea3a3021..d2e885fc71 100644 --- a/tests/unit/selectable/selectable_core.js +++ b/tests/unit/selectable/selectable_core.js @@ -4,7 +4,7 @@ var el; -var drag = function(dx, dy) { +TestHelpers.selectableDrag = function drag(dx, dy) { var off = el.offset(), pos = { clientX: off.left, clientY: off.top }; el.simulate("mousedown", pos); $(document).simulate("mousemove", pos); diff --git a/tests/unit/selectable/selectable_events.js b/tests/unit/selectable/selectable_events.js index 2623818a75..bfd431bd8d 100644 --- a/tests/unit/selectable/selectable_events.js +++ b/tests/unit/selectable/selectable_events.js @@ -9,7 +9,7 @@ test("start", function() { expect(2); el = $("#selectable1"); el.selectable({ - start: function(ev, ui) { + start: function() { ok(true, "drag fired start callback"); equal(this, el[0], "context of callback"); } @@ -21,7 +21,7 @@ test("stop", function() { expect(2); el = $("#selectable1"); el.selectable({ - start: function(ev, ui) { + start: function() { ok(true, "drag fired stop callback"); equal(this, el[0], "context of callback"); } diff --git a/tests/unit/selectable/selectable_methods.js b/tests/unit/selectable/selectable_methods.js index dbc88f2698..ee7242d9b0 100644 --- a/tests/unit/selectable/selectable_methods.js +++ b/tests/unit/selectable/selectable_methods.js @@ -21,7 +21,7 @@ test("init", function() { ok(true, 'arbitrary method called after init'); el = $("
").selectable(); - var foo = el.selectable("option", "foo"); + el.selectable("option", "foo"); el.remove(); ok(true, 'arbitrary option getter after init'); diff --git a/tests/unit/selectable/selectable_options.js b/tests/unit/selectable/selectable_options.js index be9fdf5feb..ad57000a9e 100644 --- a/tests/unit/selectable/selectable_options.js +++ b/tests/unit/selectable/selectable_options.js @@ -13,7 +13,7 @@ test("autoRefresh", function() { actual = 0; el = $("#selectable1").selectable({ autoRefresh: false, selected: selected }); sel.hide(); - drag(1000, 1000); + TestHelpers.selectableDrag(1000, 1000); equal(actual, sel.length); el.selectable("destroy"); @@ -21,10 +21,10 @@ test("autoRefresh", function() { sel.show(); el = $("#selectable1").selectable({ autoRefresh: true, selected: selected }); sel.hide(); - drag(1000, 1000); + TestHelpers.selectableDrag(1000, 1000); equal(actual, 0); sel.show(); - drag(1000, 1000); + TestHelpers.selectableDrag(1000, 1000); equal(actual, sel.length); el.selectable("destroy"); sel.show(); @@ -37,7 +37,7 @@ test("filter", function() { actual = 0; el = $("#selectable1").selectable({ filter: '.special', selected: selected }); - drag(1000, 1000); + TestHelpers.selectableDrag(1000, 1000); ok(sel.length !== 1, "this test assumes more than 1 selectee"); equal(actual, 1); el.selectable("destroy"); diff --git a/tests/unit/slider/slider_events.js b/tests/unit/slider/slider_events.js index 4d0896442b..2fb9b37b61 100644 --- a/tests/unit/slider/slider_events.js +++ b/tests/unit/slider/slider_events.js @@ -14,16 +14,16 @@ test( "mouse based interaction", function() { var el = $( "#slider1" ) .slider({ - start: function(event, ui) { + start: function( event ) { equal( event.originalEvent.type, "mousedown", "start triggered by mousedown" ); }, - slide: function(event, ui) { + slide: function( event) { equal( event.originalEvent.type, "mousemove", "slider triggered by mousemove" ); }, - stop: function(event, ui) { + stop: function( event ) { equal( event.originalEvent.type, "mouseup", "stop triggered by mouseup" ); }, - change: function(event, ui) { + change: function( event ) { equal( event.originalEvent.type, "mouseup", "change triggered by mouseup" ); } }); @@ -38,16 +38,16 @@ test( "keyboard based interaction", function() { // Test keyup at end of handle slide (keyboard) var el = $( "#slider1" ) .slider({ - start: function(event, ui) { + start: function( event ) { equal( event.originalEvent.type, "keydown", "start triggered by keydown" ); }, - slide: function(event, ui) { + slide: function() { ok( false, "Slider never triggered by keys" ); }, - stop: function(event, ui) { + stop: function( event ) { equal( event.originalEvent.type, "keyup", "stop triggered by keyup" ); }, - change: function(event, ui) { + change: function( event ) { equal( event.originalEvent.type, "keyup", "change triggered by keyup" ); } }); @@ -64,7 +64,7 @@ test( "programmatic event triggers", function() { // Test value method var el = $( "
" ) .slider({ - change: function(event, ui) { + change: function() { ok( true, "change triggered by value method" ); } }) @@ -75,7 +75,7 @@ test( "programmatic event triggers", function() { el = $( "
" ) .slider({ values: [ 10, 20 ], - change: function(event, ui) { + change: function() { ok( true, "change triggered by values method" ); } }) @@ -85,7 +85,7 @@ test( "programmatic event triggers", function() { // Test value option el = $( "
" ) .slider({ - change: function(event, ui) { + change: function() { ok( true, "change triggered by value option" ); } }) @@ -96,7 +96,7 @@ test( "programmatic event triggers", function() { el = $( "
" ) .slider({ values: [ 10, 20 ], - change: function(event, ui) { + change: function() { ok( true, "change triggered by values option" ); } }) diff --git a/tests/unit/slider/slider_methods.js b/tests/unit/slider/slider_methods.js index 1a6b493c95..11d679845a 100644 --- a/tests/unit/slider/slider_methods.js +++ b/tests/unit/slider/slider_methods.js @@ -17,8 +17,8 @@ test("init", function() { $('
').slider().remove(); ok(true, '.slider() called on disconnected DOMElement'); - var el = $('
').slider(), - foo = el.slider("option", "foo"); + var el = $('
').slider(); + el.slider("option", "foo"); el.remove(); ok(true, 'arbitrary option getter after init'); diff --git a/tests/unit/sortable/sortable_core.js b/tests/unit/sortable/sortable_core.js index ff18598745..540e06f0f5 100644 --- a/tests/unit/sortable/sortable_core.js +++ b/tests/unit/sortable/sortable_core.js @@ -6,4 +6,8 @@ module("sortable: core"); +// this is here to make JSHint pass "unused", and we don't want to +// remove the parameter for when we finally implement +$.noop(); + })(jQuery); diff --git a/tests/unit/sortable/sortable_options.js b/tests/unit/sortable/sortable_options.js index a043e68fe6..d5d7b3de11 100644 --- a/tests/unit/sortable/sortable_options.js +++ b/tests/unit/sortable/sortable_options.js @@ -5,6 +5,10 @@ module("sortable: options"); +// this is here to make JSHint pass "unused", and we don't want to +// remove the parameter for when we finally implement +$.noop(); + test("{ appendTo: 'parent' }, default", function() { ok(false, "missing test - untested code is broken code."); }); diff --git a/tests/unit/sortable/sortable_tickets.js b/tests/unit/sortable/sortable_tickets.js index 22ad61baf8..14bb705eaa 100644 --- a/tests/unit/sortable/sortable_tickets.js +++ b/tests/unit/sortable/sortable_tickets.js @@ -44,13 +44,13 @@ test('#4752: link event firing on sortable with connect list', function () { $('#main ul').sortable({ connectWith: '#main ul', - change: function (e, ui) { + change: function () { fired.change = true; }, - receive: function (e, ui) { + receive: function () { fired.receive = true; }, - remove: function (e, ui) { + remove: function () { fired.remove = true; } }); diff --git a/tests/unit/spinner/spinner_options.js b/tests/unit/spinner/spinner_options.js index 1f6646a33b..284e03a3e3 100644 --- a/tests/unit/spinner/spinner_options.js +++ b/tests/unit/spinner/spinner_options.js @@ -1,7 +1,5 @@ (function( $ ) { -var simulateKeyDownUp = TestHelpers.spinner.simulateKeyDownUp; - module( "spinner: options" ); // culture is tested after numberFormat, since it depends on numberFormat @@ -28,7 +26,7 @@ test( "icons: custom ", function() { test( "incremental, false", function() { expect( 100 ); - var i, diff, + var i, prev = 0, element = $( "#spin" ).val( prev ).spinner({ incremental: false, @@ -53,7 +51,7 @@ test( "incremental, true", function() { }); } - var i, diff, + var i, prev = 0, expected = [].concat( fill( 18, 1 ), fill( 37, 2 ), fill( 14, 3 ), fill( 9, 4 ), fill( 6, 5 ), fill( 5, 6 ), fill ( 5, 7 ), diff --git a/tests/unit/tabs/tabs_core.js b/tests/unit/tabs/tabs_core.js index 5dbe1d6b12..6307c44887 100644 --- a/tests/unit/tabs/tabs_core.js +++ b/tests/unit/tabs/tabs_core.js @@ -132,7 +132,6 @@ test( "accessibility", function() { asyncTest( "accessibility - ajax", function() { expect( 4 ); var element = $( "#tabs2" ).tabs(), - tab = element.find( ".ui-tabs-nav li" ).eq( 3 ), panel = $( "#custom-id" ); equal( panel.attr( "aria-live" ), "polite", "remote panel has aria-live" ); @@ -588,7 +587,7 @@ asyncTest( "keyboard support - CTRL+UP, ALT+PAGE_DOWN, ALT+PAGE_UP", function() test( "#3627 - Ajax tab with url containing a fragment identifier fails to load", function() { expect( 1 ); - var element = $( "#tabs2" ).tabs({ + $( "#tabs2" ).tabs({ active: 2, beforeLoad: function( event, ui ) { event.preventDefault(); @@ -603,7 +602,7 @@ test( "#4033 - IE expands hash to full url and misinterprets tab as ajax", funct var element = $( "" ); element.appendTo( "#main" ); element.tabs({ - beforeLoad: function( event, ui ) { + beforeLoad: function() { event.preventDefault(); ok( false, "should not be an ajax tab" ); } diff --git a/tests/unit/tabs/tabs_deprecated.js b/tests/unit/tabs/tabs_deprecated.js index 4a938c078a..297a4546e0 100644 --- a/tests/unit/tabs/tabs_deprecated.js +++ b/tests/unit/tabs/tabs_deprecated.js @@ -53,20 +53,20 @@ asyncTest( "cache", function() { var element = $( "#tabs2" ).tabs({ cache: true }); - element.one( "tabsshow", function( event, ui ) { + element.one( "tabsshow", function() { state( element, 0, 0, 1, 0, 0 ); }); - element.one( "tabsload", function( event, ui ) { + element.one( "tabsload", function() { ok( true, "tabsload" ); setTimeout(function() { element.tabs( "option", "active", 0 ); state( element, 1, 0, 0, 0, 0 ); - element.one( "tabsshow", function( event, ui ) { + element.one( "tabsshow", function() { state( element, 0, 0, 1, 0, 0 ); }); - element.one( "tabsload", function( event, ui ) { + element.one( "tabsload", function() { ok( false, "should be cached" ); }); element.tabs( "option", "active", 2 ); @@ -159,10 +159,10 @@ asyncTest( "spinner", function() { var element = $( "#tabs2" ).tabs(); - element.one( "tabsbeforeload", function( event, ui ) { + element.one( "tabsbeforeload", function() { equal( element.find( ".ui-tabs-nav li:eq(2) em" ).length, 1, "beforeload" ); }); - element.one( "tabsload", function( event, ui ) { + element.one( "tabsload", function() { // wait until after the load finishes before checking for the spinner to be removed setTimeout(function() { equal( element.find( ".ui-tabs-nav li:eq(2) em" ).length, 0, "load" ); @@ -351,7 +351,7 @@ test( "show", function() { state( element, 0, 1, 0 ); // collapsing - element.one( "tabsshow", function( event, ui ) { + element.one( "tabsshow", function() { ok( false, "collapsing" ); }); element.tabs( "option", "active", false ); @@ -391,7 +391,7 @@ test( "select", function() { state( element, 0, 1, 0 ); // collapsing - element.one( "tabsselect", function( event, ui ) { + element.one( "tabsselect", function() { ok( false, "collapsing" ); }); element.tabs( "option", "active", false ); diff --git a/tests/unit/testsuite.js b/tests/unit/testsuite.js index 74a561c0d2..c0ab490e16 100644 --- a/tests/unit/testsuite.js +++ b/tests/unit/testsuite.js @@ -116,7 +116,7 @@ function testWidgetDefaults( widget, defaults ) { // ensure that all defaults were tested test( "tested defaults", function() { var count = 0; - $.each( pluginDefaults, function( key, val ) { + $.each( pluginDefaults, function( key ) { expect( ++count ); ok( key in defaults, key ); }); @@ -227,7 +227,7 @@ window.domEqual = function( selector, modifier, message ) { delete result.data[ $.expando ]; children = elem.children(); if ( children.length ) { - result.children = elem.children().map(function( ind ) { + result.children = elem.children().map(function() { return extract( $( this ) ); }).get(); } else { diff --git a/tests/unit/tooltip/tooltip_options.js b/tests/unit/tooltip/tooltip_options.js index e5046f4648..3be6518558 100644 --- a/tests/unit/tooltip/tooltip_options.js +++ b/tests/unit/tooltip/tooltip_options.js @@ -67,7 +67,7 @@ test( "content: change while open", function() { test( "content: string", function() { expect( 1 ); - var element = $( "#tooltipped1" ).tooltip({ + $( "#tooltipped1" ).tooltip({ content: "just a string", open: function( event, ui ) { equal( ui.tooltip.text(), "just a string" ); diff --git a/tests/unit/widget/widget_core.js b/tests/unit/widget/widget_core.js index 5efd91268a..848579a1dc 100644 --- a/tests/unit/widget/widget_core.js +++ b/tests/unit/widget/widget_core.js @@ -313,7 +313,7 @@ test( "re-init", function() { _init: function() { actions.push( "init" ); }, - _setOption: function( key, value ) { + _setOption: function( key ) { actions.push( "option" + key ); } }); @@ -959,11 +959,11 @@ test( "._trigger() - cancelled event", function() { }); $( "#widget" ).testWidget({ - foo: function( event, ui ) { + foo: function() { ok( true, "callback invoked even if event is cancelled" ); } }) - .bind( "testwidgetfoo", function( event, ui ) { + .bind( "testwidgetfoo", function() { ok( true, "event was triggered" ); return false; }); @@ -978,7 +978,7 @@ test( "._trigger() - cancelled callback", function() { }); $( "#widget" ).testWidget({ - foo: function( event, ui ) { + foo: function() { return false; } }); diff --git a/ui/.jshintrc b/ui/.jshintrc index 26b8087740..edf09721b6 100644 --- a/ui/.jshintrc +++ b/ui/.jshintrc @@ -10,6 +10,7 @@ "onevar": true, "trailing": true, "undef": true, + "unused": true, "predef": [ "Globalize" ] diff --git a/ui/jquery.ui.accordion.js b/ui/jquery.ui.accordion.js index a23d5e66d2..1086474199 100644 --- a/ui/jquery.ui.accordion.js +++ b/ui/jquery.ui.accordion.js @@ -603,7 +603,7 @@ if ( $.uiBackCompat !== false ) { _create.call( this ); }, - _setOption: function( key, value ) { + _setOption: function( key ) { if ( key === "autoHeight" || key === "clearStyle" || key === "fillSpace" ) { this.options.heightStyle = this._mergeHeightStyle(); } diff --git a/ui/jquery.ui.autocomplete.js b/ui/jquery.ui.autocomplete.js index aec12bf8f3..7bacca006d 100644 --- a/ui/jquery.ui.autocomplete.js +++ b/ui/jquery.ui.autocomplete.js @@ -359,7 +359,7 @@ $.widget( "ui.autocomplete", { url: url, data: request, dataType: "json", - success: function( data, status ) { + success: function( data ) { response( data ); }, error: function() { @@ -541,7 +541,7 @@ $.widget( "ui.autocomplete", { return this.menu.element; }, - _value: function( value ) { + _value: function() { return this.valueMethod.apply( this.element, arguments ); }, diff --git a/ui/jquery.ui.dialog.js b/ui/jquery.ui.dialog.js index e234464ad9..f2e3f945f4 100644 --- a/ui/jquery.ui.dialog.js +++ b/ui/jquery.ui.dialog.js @@ -88,6 +88,11 @@ $.widget("ui.dialog", { options = this.options, title = options.title || " ", + uiDialog, + uiDialogTitlebar, + uiDialogTitlebarClose, + uiDialogTitle, + uiDialogButtonPane; uiDialog = ( this.uiDialog = $( "
" ) ) .addClass( uiDialogClasses + options.dialogClass ) @@ -108,13 +113,13 @@ $.widget("ui.dialog", { .mousedown(function( event ) { that.moveToTop( false, event ); }) - .appendTo( "body" ), + .appendTo( "body" ); - uiDialogContent = this.element + this.element .show() .removeAttr( "title" ) .addClass( "ui-dialog-content ui-widget-content" ) - .appendTo( uiDialog ), + .appendTo( uiDialog ); uiDialogTitlebar = ( this.uiDialogTitlebar = $( "
" ) ) .addClass( "ui-dialog-titlebar ui-widget-header " + @@ -123,7 +128,7 @@ $.widget("ui.dialog", { // Dialog isn't getting focus when dragging (#8063) uiDialog.focus(); }) - .prependTo( uiDialog ), + .prependTo( uiDialog ); uiDialogTitlebarClose = $( "" ) .addClass( "ui-dialog-titlebar-close ui-corner-all" ) @@ -132,23 +137,23 @@ $.widget("ui.dialog", { event.preventDefault(); that.close( event ); }) - .appendTo( uiDialogTitlebar ), + .appendTo( uiDialogTitlebar ); - uiDialogTitlebarCloseText = ( this.uiDialogTitlebarCloseText = $( "" ) ) + ( this.uiDialogTitlebarCloseText = $( "" ) ) .addClass( "ui-icon ui-icon-closethick" ) .text( options.closeText ) - .appendTo( uiDialogTitlebarClose ), + .appendTo( uiDialogTitlebarClose ); uiDialogTitle = $( "" ) .uniqueId() .addClass( "ui-dialog-title" ) .html( title ) - .prependTo( uiDialogTitlebar ), + .prependTo( uiDialogTitlebar ); uiDialogButtonPane = ( this.uiDialogButtonPane = $( "
" ) ) - .addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" ), + .addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" ); - uiButtonSet = ( this.uiButtonSet = $( "
" ) ) + ( this.uiButtonSet = $( "
" ) ) .addClass( "ui-dialog-buttonset" ) .appendTo( uiDialogButtonPane ); @@ -350,8 +355,7 @@ $.widget("ui.dialog", { }, _createButtons: function( buttons ) { - var uiDialogButtonPane, uiButtonSet, - that = this, + var that = this, hasButtons = false; // if we already have a button pane, remove it diff --git a/ui/jquery.ui.effect.js b/ui/jquery.ui.effect.js index 8d875746e8..37ca48795d 100644 --- a/ui/jquery.ui.effect.js +++ b/ui/jquery.ui.effect.js @@ -245,8 +245,7 @@ color.fn = jQuery.extend( color.prototype, { var inst = this, type = jQuery.type( red ), - rgba = this._rgba = [], - source; + rgba = this._rgba = []; // more than 1 argument specified - assume ( red, green, blue, alpha ) if ( green !== undefined ) { @@ -427,7 +426,7 @@ color.fn = jQuery.extend( color.prototype, { rgba.push( ~~( alpha * 255 ) ); } - return "#" + jQuery.map( rgba, function( v, i ) { + return "#" + jQuery.map( rgba, function( v ) { // default to 0 when nulls exist v = ( v || 0 ).toString( 16 ); @@ -501,8 +500,7 @@ spaces.hsla.from = function ( hsla ) { l = hsla[ 2 ], a = hsla[ 3 ], q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, - p = 2 * l - q, - r, g, b; + p = 2 * l - q; return [ Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), @@ -710,7 +708,6 @@ function getElementStyles() { this.currentStyle, newStyle = {}, key, - camelCase, len; // webkit enumerates style porperties @@ -1114,7 +1111,7 @@ function standardSpeed( speed ) { } $.fn.extend({ - effect: function( effect, options, speed, callback ) { + effect: function( /* effect, options, speed, callback */ ) { var args = _normalizeArguments.apply( this, arguments ), mode = args.mode, queue = args.queue, diff --git a/ui/jquery.ui.slider.js b/ui/jquery.ui.slider.js index eb0f7fc15c..18f7113d40 100644 --- a/ui/jquery.ui.slider.js +++ b/ui/jquery.ui.slider.js @@ -278,7 +278,7 @@ $.widget( "ui.slider", $.ui.mouse, { return true; }, - _mouseStart: function( event ) { + _mouseStart: function() { return true; }, @@ -591,7 +591,7 @@ $.widget( "ui.slider", $.ui.mouse, { _set = {}; if ( this.options.values && this.options.values.length ) { - this.handles.each(function( i, j ) { + this.handles.each(function( i ) { valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100; _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index 05456374d2..0d920c3a13 100644 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -45,8 +45,7 @@ $.widget( "ui.tabs", { }, _create: function() { - var panel, - that = this, + var that = this, options = this.options, active = options.active, locationHash = location.hash.substring( 1 ); @@ -295,8 +294,7 @@ $.widget( "ui.tabs", { }, refresh: function() { - var next, - options = this.options, + var options = this.options, lis = this.tablist.children( ":has(a[href])" ); // get disabled tabs from class attribute from HTML @@ -922,7 +920,7 @@ if ( $.uiBackCompat !== false ) { this._super(); }, - url: function( index, url ){ + url: function( index ){ this.anchors.eq( index ).removeData( "cache.tabs" ); this._superApply( arguments ); } @@ -1158,7 +1156,7 @@ if ( $.uiBackCompat !== false ) { } }, - _eventHandler: function( event ) { + _eventHandler: function() { this._superApply( arguments ); this.options.selected = this.options.active; if ( this.options.selected === false ) { @@ -1254,7 +1252,7 @@ if ( $.uiBackCompat !== false ) { this._cookie( this.options.active, this.options.cookie ); } }, - _eventHandler: function( event ) { + _eventHandler: function() { this._superApply( arguments ); if ( this.options.cookie ) { this._cookie( this.options.active, this.options.cookie ); diff --git a/ui/jquery.ui.tooltip.js b/ui/jquery.ui.tooltip.js index 4a17f1f20f..43788a082e 100644 --- a/ui/jquery.ui.tooltip.js +++ b/ui/jquery.ui.tooltip.js @@ -284,7 +284,7 @@ $.widget( "ui.tooltip", { this.close( fakeEvent, true ); } }, - remove: function( event ) { + remove: function() { this._removeTooltip( tooltip ); } }; @@ -297,7 +297,7 @@ $.widget( "ui.tooltip", { this._on( target, events ); }, - close: function( event, force ) { + close: function( event ) { var that = this, target = $( event ? event.currentTarget : this.element ), tooltip = this._find( target ); diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index 96cc6071c8..59fd81b9e0 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -200,7 +200,7 @@ $.widget.bridge = function( name, object ) { }; }; -$.Widget = function( options, element ) {}; +$.Widget = function( /* options, element */ ) {}; $.Widget._childConstructors = []; $.Widget.prototype = { From d535f6869fa252af4cddd8394b2a53100ed6618c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Tue, 23 Oct 2012 11:18:51 -0400 Subject: [PATCH 034/151] Tooltip: Cleaned up CSS. --- themes/base/jquery.ui.tooltip.css | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/themes/base/jquery.ui.tooltip.css b/themes/base/jquery.ui.tooltip.css index acc39a0021..89217ab005 100644 --- a/themes/base/jquery.ui.tooltip.css +++ b/themes/base/jquery.ui.tooltip.css @@ -7,12 +7,10 @@ * http://jquery.org/license */ .ui-tooltip { - padding:8px; - position:absolute; - z-index:9999; + padding: 8px; + position: absolute; + z-index: 9999; max-width: 300px; - -o-box-shadow: 0 0 5px #aaa; - -moz-box-shadow: 0 0 5px #aaa; -webkit-box-shadow: 0 0 5px #aaa; box-shadow: 0 0 5px #aaa; } @@ -20,4 +18,4 @@ * html .ui-tooltip { background-image: none; } -body .ui-tooltip { border-width:2px; } +body .ui-tooltip { border-width: 2px; } From 5e0a2ca1e502c482e3e281d07a37558b75ce3308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Tue, 23 Oct 2012 11:45:16 -0400 Subject: [PATCH 035/151] Widget: Fixed $.widget.extend() to never copy objects by reference. --- ui/jquery.ui.widget.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index 59fd81b9e0..05487f7edb 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -142,9 +142,14 @@ $.widget.extend = function( target ) { for ( ; inputIndex < inputLength; inputIndex++ ) { for ( key in input[ inputIndex ] ) { value = input[ inputIndex ][ key ]; - if (input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { - if ( $.isPlainObject( value ) && $.isPlainObject( target[ key ] ) ) { - target[ key ] = $.widget.extend( {}, target[ key ], value ); + if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { + // Clone objects + if ( $.isPlainObject( value ) ) { + target[ key ] = $.isPlainObject( target[ key ] ) ? + $.widget.extend( {}, target[ key ], value ) : + // Don't extend strings, arrays, etc. with objects + $.widget.extend( {}, value ); + // Copy everything else by reference } else { target[ key ] = value; } From b1b07e8046aa0f0b543ade96eb28567af68efb81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Zaefferer?= Date: Tue, 23 Oct 2012 11:54:32 -0400 Subject: [PATCH 036/151] Grunt: Disable csslint's vendor-prefix rule, we're including only the prefixes that are still necessary in supported browsers --- grunt.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/grunt.js b/grunt.js index 6e8655b409..96b53fe95c 100644 --- a/grunt.js +++ b/grunt.js @@ -306,7 +306,8 @@ grunt.initConfig({ "important": false, "outline-none": false, // especially this one - "overqualified-elements": false + "overqualified-elements": false, + "compatible-vendor-prefixes": false } } }, From 8bb05d23e2c49ecbe2f83a3552efb0a93c48bb85 Mon Sep 17 00:00:00 2001 From: Marc-Andre Lafortune Date: Sun, 7 Oct 2012 02:35:01 -0400 Subject: [PATCH 037/151] Widget: Destroy only when element is the actual target. Fixes #8652 - Widget: Destroy only when element is the actual target. --- tests/unit/widget/widget_core.js | 7 +++++++ ui/jquery.ui.widget.js | 8 +++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/unit/widget/widget_core.js b/tests/unit/widget/widget_core.js index 848579a1dc..31f2b9ccff 100644 --- a/tests/unit/widget/widget_core.js +++ b/tests/unit/widget/widget_core.js @@ -1167,6 +1167,13 @@ test( "._trigger() - instance as element", function() { $( "#widget" ).testWidget().detach(); }); }); + + test( "destroy - remove event bubbling", function() { + shouldDestroy( false, function() { + $( "
child
" ).appendTo( $( "#widget" ).testWidget() ) + .trigger( "remove" ); + }); + }); }()); test( "redefine", function() { diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index 05487f7edb..ccbe0cac58 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -237,7 +237,13 @@ $.Widget.prototype = { // TODO remove dual storage $.data( element, this.widgetName, this ); $.data( element, this.widgetFullName, this ); - this._on({ remove: "destroy" }); + this._on({ + remove: function( event ) { + if ( event.target === element ) { + this.destroy(); + } + } + }); this.document = $( element.style ? // element within the document element.ownerDocument : From f4b3cd527116b25d4d6f44c2df0f2c472b961e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Mrozi=C5=84ski?= Date: Sun, 21 Oct 2012 22:24:50 +0200 Subject: [PATCH 038/151] Accordion: Remove code that sets accordion height. Fixed #8696 - Multiple collapsible Accordions won't work together. --- ui/jquery.ui.accordion.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/ui/jquery.ui.accordion.js b/ui/jquery.ui.accordion.js index 1086474199..fd3a983b8f 100644 --- a/ui/jquery.ui.accordion.js +++ b/ui/jquery.ui.accordion.js @@ -75,7 +75,6 @@ $.widget( "ui.accordion", { .show(); this._createIcons(); - this.originalHeight = this.element[0].style.height; this.refresh(); // ARIA @@ -198,7 +197,6 @@ $.widget( "ui.accordion", { } }); if ( this.options.heightStyle !== "content" ) { - this.element.css( "height", this.originalHeight ); contents.css( "height", "" ); } }, @@ -289,7 +287,6 @@ $.widget( "ui.accordion", { heightStyle = this.options.heightStyle, parent = this.element.parent(); - this.element.css( "height", this.originalHeight ); if ( heightStyle === "fill" ) { // IE 6 treats height like minHeight, so we need to turn off overflow @@ -332,10 +329,6 @@ $.widget( "ui.accordion", { }) .height( maxHeight ); } - - if ( heightStyle !== "content" ) { - this.element.height( this.element.height() ); - } }, _activate: function( index ) { From 568aec62d977af89a5a1aa0f9dbf1301b8df0ea0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Zaefferer?= Date: Tue, 23 Oct 2012 14:03:04 -0400 Subject: [PATCH 039/151] Menu: Remove stupid demos, add an icons demo, improve the default demo --- demos/menu/default.html | 57 +++++++++++++++------- demos/menu/icons.html | 44 +++++++++++++++++ demos/menu/index.html | 3 +- demos/menu/navigationmenu.html | 74 ----------------------------- demos/menu/topalignmenu.html | 87 ---------------------------------- 5 files changed, 86 insertions(+), 179 deletions(-) create mode 100644 demos/menu/icons.html delete mode 100644 demos/menu/navigationmenu.html delete mode 100644 demos/menu/topalignmenu.html diff --git a/demos/menu/default.html b/demos/menu/default.html index 27b1f249c7..5b535856b5 100644 --- a/demos/menu/default.html +++ b/demos/menu/default.html @@ -7,6 +7,7 @@ + +
-

A menu with the default configuration. A list is transformed, adding theming, mouse and keyboard navigation support. Try to tab to the menu then use the cursor keys to navigate.

+

A menu with the default configuration, disabled items and nested menus. A list is transformed, adding theming, mouse and keyboard navigation support. Try to tab to the menu then use the cursor keys to navigate.

diff --git a/demos/menu/icons.html b/demos/menu/icons.html new file mode 100644 index 0000000000..b7a04e6653 --- /dev/null +++ b/demos/menu/icons.html @@ -0,0 +1,44 @@ + + + + + jQuery UI Menu - Icons + + + + + + + + + + + + + + +
+

A menu with the default configuration, showing how to use a menu with icons.

+
+ + diff --git a/demos/menu/index.html b/demos/menu/index.html index 07556c6ec1..40e9e0b54e 100644 --- a/demos/menu/index.html +++ b/demos/menu/index.html @@ -8,8 +8,7 @@ diff --git a/demos/menu/navigationmenu.html b/demos/menu/navigationmenu.html deleted file mode 100644 index c2bb307bab..0000000000 --- a/demos/menu/navigationmenu.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - - jQuery UI Menu - Navigation Menu - - - - - - - - - - - - - - -
-

A navigation menu. A list is transformed, adding theming, mouse and keyboard navigation support. Try to tab to the menu then use the cursor keys to navigate.

-
- - diff --git a/demos/menu/topalignmenu.html b/demos/menu/topalignmenu.html deleted file mode 100644 index 4f34b98c2a..0000000000 --- a/demos/menu/topalignmenu.html +++ /dev/null @@ -1,87 +0,0 @@ - - - - - Menu Demo: Top-aligned Menu - - - - - - - - - - - - - - -
-

Menus can use custom positioning. There is a delay before activing an item on hover and a delay before closing a menu on mouse out to allow for moving to a submenu that is not touching its parent item.

-
- - From 11effcbd35c7a0b36af2a710b385d741f5849cbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Tue, 23 Oct 2012 14:49:16 -0400 Subject: [PATCH 040/151] Dialog: Don't use deprecated offset option for .position(). Fixes #8675 - Dialog: Position with pixels in array doesn't work with back compat disabled. --- ui/jquery.ui.dialog.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/jquery.ui.dialog.js b/ui/jquery.ui.dialog.js index f2e3f945f4..c1ac7bc9ef 100644 --- a/ui/jquery.ui.dialog.js +++ b/ui/jquery.ui.dialog.js @@ -509,9 +509,9 @@ $.widget("ui.dialog", { }); position = { - my: myAt.join( " " ), - at: myAt.join( " " ), - offset: offset.join( " " ) + my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " + + myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]), + at: myAt.join( " " ) }; } From 97b4813f30a0f197e96ec51bdd1d23cbc571add0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Tue, 23 Oct 2012 15:07:19 -0400 Subject: [PATCH 041/151] Tooltip tests: Fixed new default value for position option. --- tests/unit/tooltip/tooltip_common.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/tooltip/tooltip_common.js b/tests/unit/tooltip/tooltip_common.js index a4958ca9a8..008511e1a2 100644 --- a/tests/unit/tooltip/tooltip_common.js +++ b/tests/unit/tooltip/tooltip_common.js @@ -5,8 +5,8 @@ TestHelpers.commonWidgetTests( "tooltip", { hide: true, items: "[title]:not([disabled])", position: { - my: "left+15 center", - at: "right center", + my: "left top+15", + at: "left bottom", collision: "flipfit flipfit" }, show: true, From 86a958d3aa04a5928484d16b27a4d3eea39142e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Tue, 23 Oct 2012 15:12:54 -0400 Subject: [PATCH 042/151] Core: Update :focsable and :tabbable to handle parents with no height/width, but visible overflow. Fixes #8643 - :focusable pseudo-selector does not find elements if parent has 0x0 dimension. --- tests/unit/core/core.html | 5 +++++ tests/unit/core/selector.js | 12 ++++++++++++ ui/jquery.ui.core.js | 8 ++++---- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/tests/unit/core/core.html b/tests/unit/core/core.html index e259f3270d..41c8db8273 100644 --- a/tests/unit/core/core.html +++ b/tests/unit/core/core.html @@ -112,6 +112,11 @@ .
+
+ + +
+
.
diff --git a/tests/unit/core/selector.js b/tests/unit/core/selector.js index 7876cdd07f..f30ad17bec 100644 --- a/tests/unit/core/selector.js +++ b/tests/unit/core/selector.js @@ -157,6 +157,12 @@ test("focusable - area elements", function() { isNotFocusable('#areaNoImg', 'not associated with an image'); }); +test( "focusable - dimensionless parent with overflow", function() { + expect( 1 ); + + isFocusable( "#dimensionlessParent", "input" ); +}); + test("tabbable - visible, enabled elements", function() { expect(18); @@ -236,4 +242,10 @@ test("tabbable - area elements", function() { isNotTabbable('#areaNoImg', 'not associated with an image'); }); +test( "tabbable - dimensionless parent with overflow", function() { + expect( 1 ); + + isTabbable( "#dimensionlessParent", "input" ); +}); + })(jQuery); diff --git a/ui/jquery.ui.core.js b/ui/jquery.ui.core.js index e569eea423..2e9d53ae34 100644 --- a/ui/jquery.ui.core.js +++ b/ui/jquery.ui.core.js @@ -198,10 +198,10 @@ function focusable( element, isTabIndexNotNaN ) { } function visible( element ) { - return !$( element ).parents().andSelf().filter(function() { - return $.css( this, "visibility" ) === "hidden" || - $.expr.filters.hidden( this ); - }).length; + return $.expr.filters.visible( element ) && + !$( element ).parents().andSelf().filter(function() { + return $.css( this, "visibility" ) === "hidden"; + }).length; } $.extend( $.expr[ ":" ], { From c45dc65291f8c1d46eaa0f741216631468787f29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Tue, 23 Oct 2012 15:15:20 -0400 Subject: [PATCH 043/151] Updated list of maintainers. --- package.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/package.json b/package.json index 110a23a6e7..cb5037da9f 100644 --- a/package.json +++ b/package.json @@ -19,11 +19,6 @@ "email": "joern.zaefferer@gmail.com", "url": "http://bassistance.de" }, - { - "name": "Richard D. Worth", - "email": "rdworth@gmail.com", - "url": "http://rdworth.org" - }, { "name": "Kris Borchers", "email": "kris.borchers@gmail.com", From dcb671539286dcc58b7e6ffa6035c647500e699a Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Tue, 23 Oct 2012 22:10:20 -0400 Subject: [PATCH 044/151] Fixes #8714, Build: Updated internal JSHint to latest --- external/jshint.js | 2791 +++++++++++++++++++++++++------------------- 1 file changed, 1618 insertions(+), 1173 deletions(-) diff --git a/external/jshint.js b/external/jshint.js index 5bf937c4b8..8f06d9be03 100644 --- a/external/jshint.js +++ b/external/jshint.js @@ -1,8 +1,8 @@ /*! * JSHint, by JSHint Community. * - * Licensed under the same slightly modified MIT license that JSLint is. - * It stops evil-doers everywhere. + * This file (and this file only) is licensed under the same slightly modified + * MIT license that JSLint is. It stops evil-doers everywhere. * * JSHint is a derivative work of JSLint: * @@ -28,8 +28,6 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * - * JSHint was forked from 2010-12-16 edition of JSLint. - * */ /* @@ -55,8 +53,8 @@ JSHINT.errors is an array of objects containing these members: { - line : The line (relative to 0) at which the lint was found - character : The character (relative to 0) at which the lint was found + line : The line (relative to 1) at which the lint was found + character : The character (relative to 1) at which the lint was found reason : The problem evidence : The text line in which the problem occurred raw : The raw message before the details were inserted @@ -69,15 +67,6 @@ If a fatal error was found, a null will be the last element of the JSHINT.errors array. - You can request a Function Report, which shows all of the functions - and the parameters and vars that they use. This can be used to find - implied global variables and other problems. The report is in HTML and - can be inserted in an HTML . - - var myReport = JSHINT.report(limited); - - If limited is true, then the report will be limited to only errors. - You can request a data structure which contains JSHint's results. var myData = JSHINT.data(); @@ -96,7 +85,9 @@ functions: [ name: STRING, line: NUMBER, + character: NUMBER, last: NUMBER, + lastcharacter: NUMBER, param: [ STRING ], @@ -152,19 +143,20 @@ /*jshint evil: true, nomen: false, onevar: false, regexp: false, strict: true, boss: true, - undef: true, maxlen: 100, indent:4 + undef: true, maxlen: 100, indent: 4, quotmark: double, unused: true */ /*members "\b", "\t", "\n", "\f", "\r", "!=", "!==", "\"", "%", "(begin)", - "(breakage)", "(context)", "(error)", "(global)", "(identifier)", "(last)", - "(line)", "(loopage)", "(name)", "(onevar)", "(params)", "(scope)", - "(statement)", "(verb)", "*", "+", "++", "-", "--", "\/", "<", "<=", "==", + "(breakage)", "(character)", "(context)", "(error)", "(explicitNewcap)", "(global)", + "(identifier)", "(last)", "(lastcharacter)", "(line)", "(loopage)", "(metrics)", + "(name)", "(onevar)", "(params)", "(scope)", "(statement)", "(verb)", "(tokens)", "(catch)", + "*", "+", "++", "-", "--", "\/", "<", "<=", "==", "===", ">", ">=", $, $$, $A, $F, $H, $R, $break, $continue, $w, Abstract, Ajax, __filename, __dirname, ActiveXObject, Array, ArrayBuffer, ArrayBufferView, Audio, - Autocompleter, Assets, Boolean, Builder, Buffer, Browser, COM, CScript, Canvas, - CustomAnimation, Class, Control, Chain, Color, Cookie, Core, DataView, Date, - Debug, Draggable, Draggables, Droppables, Document, DomReady, DOMReady, Drag, - E, Enumerator, Enumerable, Element, Elements, Error, Effect, EvalError, Event, + Autocompleter, Asset, Boolean, Builder, Buffer, Browser, Blob, COM, CScript, Canvas, + CustomAnimation, Class, Control, ComplexityCount, Chain, Color, Cookie, Core, DataView, Date, + Debug, Draggable, Draggables, Droppables, Document, DomReady, DOMEvent, DOMReady, DOMParser, + Drag, E, Enumerator, Enumerable, Element, Elements, Error, Effect, EvalError, Event, Events, FadeAnimation, Field, Flash, Float32Array, Float64Array, Form, FormField, Frame, FormData, Function, Fx, GetObject, Group, Hash, HotKey, HTMLElement, HTMLAnchorElement, HTMLBaseElement, HTMLBlockquoteElement, @@ -181,49 +173,53 @@ HtmlTable, HTMLTableCaptionElement, HTMLTableCellElement, HTMLTableColElement, HTMLTableElement, HTMLTableRowElement, HTMLTableSectionElement, HTMLTextAreaElement, HTMLTitleElement, HTMLUListElement, HTMLVideoElement, - Iframe, IframeShim, Image, Int16Array, Int32Array, Int8Array, + Iframe, IframeShim, Image, importScripts, Int16Array, Int32Array, Int8Array, Insertion, InputValidator, JSON, Keyboard, Locale, LN10, LN2, LOG10E, LOG2E, - MAX_VALUE, MIN_VALUE, Mask, Math, MenuItem, MoveAnimation, MooTools, Native, - NEGATIVE_INFINITY, Number, Object, ObjectRange, Option, Options, OverText, PI, - POSITIVE_INFINITY, PeriodicalExecuter, Point, Position, Prototype, RangeError, - Rectangle, ReferenceError, RegExp, ResizeAnimation, Request, RotateAnimation, + MAX_VALUE, MIN_VALUE, Map, Mask, Math, MenuItem, MessageChannel, MessageEvent, MessagePort, + MoveAnimation, MooTools, MutationObserver, NaN, Native, NEGATIVE_INFINITY, Node, NodeFilter, + Number, Object, ObjectRange, + Option, Options, OverText, PI, POSITIVE_INFINITY, PeriodicalExecuter, Point, Position, Prototype, + RangeError, Rectangle, ReferenceError, RegExp, ResizeAnimation, Request, RotateAnimation, Set, SQRT1_2, SQRT2, ScrollBar, ScriptEngine, ScriptEngineBuildVersion, ScriptEngineMajorVersion, ScriptEngineMinorVersion, Scriptaculous, Scroller, Slick, Slider, Selector, SharedWorker, String, Style, SyntaxError, Sortable, Sortables, SortableObserver, Sound, Spinner, System, Swiff, Text, TextArea, Template, Timer, Tips, Type, TypeError, Toggle, Try, "use strict", unescape, URI, URIError, URL, - VBArray, WSH, WScript, XDomainRequest, Web, Window, XMLDOM, XMLHttpRequest, XPathEvaluator, - XPathException, XPathExpression, XPathNamespace, XPathNSResolver, XPathResult, "\\", a, - addEventListener, address, alert, apply, applicationCache, arguments, arity, - asi, b, basic, basicToken, bitwise, block, blur, boolOptions, boss, browser, c, call, callee, - caller, cases, charAt, charCodeAt, character, clearInterval, clearTimeout, - close, closed, closure, comment, condition, confirm, console, constructor, - content, couch, create, css, curly, d, data, datalist, dd, debug, decodeURI, - decodeURIComponent, defaultStatus, defineClass, deserialize, devel, document, - dojo, dijit, dojox, define, else, emit, encodeURI, encodeURIComponent, - entityify, eqeqeq, eqnull, errors, es5, escape, esnext, eval, event, evidence, evil, - ex, exception, exec, exps, expr, exports, FileReader, first, floor, focus, + VBArray, WeakMap, WSH, WScript, XDomainRequest, Web, Window, XMLDOM, XMLHttpRequest, XMLSerializer, + XPathEvaluator, XPathException, XPathExpression, XPathNamespace, XPathNSResolver, XPathResult, + "\\", a, abs, addEventListener, address, alert, apply, applicationCache, arguments, arity, + asi, atob, b, basic, basicToken, bitwise, blacklist, block, blur, boolOptions, boss, + browser, btoa, c, call, callee, caller, camelcase, cases, charAt, charCodeAt, character, + clearInterval, clearTimeout, close, closed, closure, comment, complexityCount, condition, + confirm, console, constructor, content, couch, create, css, curly, d, data, datalist, dd, debug, + decodeURI, decodeURIComponent, defaultStatus, defineClass, deserialize, devel, document, + dojo, dijit, dojox, define, else, emit, encodeURI, encodeURIComponent, elem, + eqeq, eqeqeq, eqnull, errors, es5, escape, esnext, eval, event, evidence, evil, + ex, exception, exec, exps, expr, exports, FileReader, first, floor, focus, forEach, forin, fragment, frames, from, fromCharCode, fud, funcscope, funct, function, functions, g, gc, getComputedStyle, getRow, getter, getterToken, GLOBAL, global, globals, globalstrict, hasOwnProperty, help, history, i, id, identifier, immed, implieds, importPackage, include, - indent, indexOf, init, ins, instanceOf, isAlpha, isApplicationRunning, isArray, + indent, indexOf, init, ins, internals, instanceOf, isAlpha, isApplicationRunning, isArray, isDigit, isFinite, isNaN, iterator, java, join, jshint, - JSHINT, json, jquery, jQuery, keys, label, labelled, last, lastsemic, laxbreak, laxcomma, - latedef, lbp, led, left, length, line, load, loadClass, localStorage, location, - log, loopfunc, m, match, maxerr, maxlen, member,message, meta, module, moveBy, - moveTo, mootools, multistr, name, navigator, new, newcap, noarg, node, noempty, nomen, - nonew, nonstandard, nud, onbeforeunload, onblur, onerror, onevar, onecase, onfocus, - onload, onresize, onunload, open, openDatabase, openURL, opener, opera, options, outer, param, - parent, parseFloat, parseInt, passfail, plusplus, predef, print, process, prompt, - proto, prototype, prototypejs, provides, push, quit, range, raw, reach, reason, regexp, - readFile, readUrl, regexdash, removeEventListener, replace, report, require, - reserved, resizeBy, resizeTo, resolvePath, resumeUpdates, respond, rhino, right, - runCommand, scroll, screen, scripturl, scrollBy, scrollTo, scrollbar, search, seal, - send, serialize, sessionStorage, setInterval, setTimeout, setter, setterToken, shift, slice, - smarttabs, sort, spawn, split, stack, status, start, strict, sub, substr, supernew, shadow, - supplant, sum, sync, test, toLowerCase, toString, toUpperCase, toint32, token, top, trailing, - type, typeOf, Uint16Array, Uint32Array, Uint8Array, undef, undefs, unused, urls, validthis, - value, valueOf, var, version, WebSocket, white, window, Worker, wsh*/ + JSHINT, json, jquery, jQuery, keys, label, labelled, last, lastcharacter, lastsemic, laxbreak, + laxcomma, latedef, lbp, led, left, length, line, load, loadClass, localStorage, location, + log, loopfunc, m, match, max, maxcomplexity, maxdepth, maxerr, maxlen, maxstatements, maxparams, + member, message, meta, module, moveBy, moveTo, mootools, multistr, name, navigator, new, newcap, + nestedBlockDepth, noarg, node, noempty, nomen, nonew, nonstandard, nud, onbeforeunload, onblur, + onerror, onevar, onecase, onfocus, onload, onresize, onunload, open, openDatabase, openURL, + opener, opera, options, outer, param, parent, parseFloat, parseInt, passfail, plusplus, + postMessage, pop, predef, print, process, prompt, proto, prototype, prototypejs, provides, push, + quit, quotmark, range, raw, reach, reason, regexp, readFile, readUrl, regexdash, + removeEventListener, replace, report, require, reserved, resizeBy, resizeTo, resolvePath, + resumeUpdates, respond, rhino, right, runCommand, scroll, scope, screen, scripturl, scrollBy, + scrollTo, scrollbar, search, seal, self, send, serialize, sessionStorage, setInterval, setTimeout, + setter, setterToken, shift, slice, smarttabs, sort, spawn, split, statement, statementCount, stack, + status, start, strict, sub, substr, supernew, shadow, supplant, sum, sync, test, toLowerCase, + toString, toUpperCase, toint32, token, tokens, top, trailing, type, typeOf, Uint16Array, + Uint32Array, Uint8Array, undef, undefs, unused, urls, validthis, value, valueOf, var, vars, + version, verifyMaxParametersPerFunction, verifyMaxStatementsPerFunction, + verifyMaxComplexityPerFunction, verifyMaxNestedBlockDepthPerFunction, WebSocket, withstmt, white, + window, windows, Worker, worker, wsh, yui, YUI, Y, YUI_config*/ /*global exports: false */ @@ -239,19 +235,19 @@ var JSHINT = (function () { // These are operators that should not be used with the ! operator. bang = { - '<' : true, - '<=' : true, - '==' : true, - '===': true, - '!==': true, - '!=' : true, - '>' : true, - '>=' : true, - '+' : true, - '-' : true, - '*' : true, - '/' : true, - '%' : true + "<" : true, + "<=" : true, + "==" : true, + "===": true, + "!==": true, + "!=" : true, + ">" : true, + ">=" : true, + "+" : true, + "-" : true, + "*" : true, + "/" : true, + "%" : true }, // These are the JSHint boolean options. @@ -260,6 +256,7 @@ var JSHINT = (function () { bitwise : true, // if bitwise operators should not be allowed boss : true, // if advanced usage of assignments should be allowed browser : true, // if the standard browser globals should be predefined + camelcase : true, // if identifiers should be required in camel case couch : true, // if CouchDB globals should be predefined curly : true, // if curly braces around all blocks should be required debug : true, // if debugger statements should be allowed @@ -311,6 +308,7 @@ var JSHINT = (function () { regexp : true, // if the . should not be allowed in regexp literals rhino : true, // if the Rhino environment globals should be predefined undef : true, // if variables should be declared before used + unused : true, // if variables should be always used scripturl : true, // if script-targeted URLs should be tolerated shadow : true, // if variable shadowing should be tolerated smarttabs : true, // if smarttabs should be tolerated @@ -322,25 +320,73 @@ var JSHINT = (function () { trailing : true, // if trailing whitespace rules apply validthis : true, // if 'this' inside a non-constructor function is valid. // This is a function scoped option only. + withstmt : true, // if with statements should be allowed white : true, // if strict whitespace rules apply - wsh : true // if the Windows Scripting Host environment globals + worker : true, // if Web Worker script symbols should be allowed + wsh : true, // if the Windows Scripting Host environment globals // should be predefined + yui : true // YUI variables should be predefined }, + // These are the JSHint options that can take any value + // (we use this object to detect invalid options) + valOptions = { + maxlen : false, + indent : false, + maxerr : false, + predef : false, + quotmark : false, //'single'|'double'|true + scope : false, + maxstatements: false, // {int} max statements per function + maxdepth : false, // {int} max nested block depth per function + maxparams : false, // {int} max params per function + maxcomplexity: false // {int} max cyclomatic complexity per function + }, + + // These are JSHint boolean options which are shared with JSLint + // where the definition in JSHint is opposite JSLint + invertedOptions = { + bitwise : true, + forin : true, + newcap : true, + nomen : true, + plusplus : true, + regexp : true, + undef : true, + white : true, + + // Inverted and renamed, use JSHint name here + eqeqeq : true, + onevar : true + }, + + // These are JSHint boolean options which are shared with JSLint + // where the name has been changed but the effect is unchanged + renamedOptions = { + eqeq : "eqeqeq", + vars : "onevar", + windows : "wsh" + }, + + // browser contains a set of global names which are commonly provided by a // web browser environment. browser = { ArrayBuffer : false, ArrayBufferView : false, Audio : false, + Blob : false, addEventListener : false, applicationCache : false, + atob : false, blur : false, + btoa : false, clearInterval : false, clearTimeout : false, close : false, closed : false, DataView : false, + DOMParser : false, defaultStatus : false, document : false, event : false, @@ -413,9 +459,15 @@ var JSHINT = (function () { length : false, localStorage : false, location : false, + MessageChannel : false, + MessageEvent : false, + MessagePort : false, moveBy : false, moveTo : false, + MutationObserver : false, name : false, + Node : false, + NodeFilter : false, navigator : false, onbeforeunload : true, onblur : true, @@ -450,6 +502,7 @@ var JSHINT = (function () { window : false, Worker : false, XMLHttpRequest : false, + XMLSerializer : false, XPathEvaluator : false, XPathException : false, XPathExpression : false, @@ -472,6 +525,8 @@ var JSHINT = (function () { provides : false }, + declared, // Globals that were declared using /*global ... */ syntax. + devel = { alert : false, confirm : false, @@ -489,22 +544,11 @@ var JSHINT = (function () { "require" : false }, - escapes = { - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '"' : '\\"', - '/' : '\\/', - '\\': '\\\\' - }, - funct, // The current function functionicity = [ - 'closure', 'exception', 'global', 'label', - 'outer', 'unused', 'var' + "closure", "exception", "global", "label", + "outer", "unused", "var" ], functions, // All of the functions @@ -516,7 +560,7 @@ var JSHINT = (function () { jsonmode, jquery = { - '$' : false, + "$" : false, jQuery : false }, @@ -526,9 +570,9 @@ var JSHINT = (function () { membersOnly, mootools = { - '$' : false, - '$$' : false, - Assets : false, + "$" : false, + "$$" : false, + Asset : false, Browser : false, Chain : false, Class : false, @@ -537,6 +581,7 @@ var JSHINT = (function () { Core : false, Document : false, DomReady : false, + DOMEvent : false, DOMReady : false, Drag : false, Element : false, @@ -579,7 +624,7 @@ var JSHINT = (function () { __dirname : false, Buffer : false, console : false, - exports : false, + exports : true, // In Node it is ok to exports = module.exports = foo(); GLOBAL : false, global : false, module : false, @@ -598,15 +643,15 @@ var JSHINT = (function () { prevtoken, prototypejs = { - '$' : false, - '$$' : false, - '$A' : false, - '$F' : false, - '$H' : false, - '$R' : false, - '$break' : false, - '$continue' : false, - '$w' : false, + "$" : false, + "$$" : false, + "$A" : false, + "$F" : false, + "$H" : false, + "$R" : false, + "$break" : false, + "$continue" : false, + "$w" : false, Abstract : false, Ajax : false, Class : false, @@ -638,6 +683,8 @@ var JSHINT = (function () { Scriptaculous : false }, + quotmark, + rhino = { defineClass : false, deserialize : false, @@ -674,14 +721,16 @@ var JSHINT = (function () { encodeURI : false, encodeURIComponent : false, Error : false, - 'eval' : false, + "eval" : false, EvalError : false, Function : false, hasOwnProperty : false, isFinite : false, isNaN : false, JSON : false, + Map : false, Math : false, + NaN : false, Number : false, Object : false, parseInt : false, @@ -689,10 +738,12 @@ var JSHINT = (function () { RangeError : false, ReferenceError : false, RegExp : false, + Set : false, String : false, SyntaxError : false, TypeError : false, - URIError : false + URIError : false, + WeakMap : false }, // widely adopted global names that are not part of ECMAScript standard @@ -701,29 +752,21 @@ var JSHINT = (function () { unescape : false }, - standard_member = { - E : true, - LN2 : true, - LN10 : true, - LOG2E : true, - LOG10E : true, - MAX_VALUE : true, - MIN_VALUE : true, - NEGATIVE_INFINITY : true, - PI : true, - POSITIVE_INFINITY : true, - SQRT1_2 : true, - SQRT2 : true - }, - directive, syntax = {}, tab, token, + unuseds, urls, useESNextSyntax, warnings, + worker = { + importScripts : true, + postMessage : true, + self : true + }, + wsh = { ActiveXObject : true, Enumerator : true, @@ -736,8 +779,13 @@ var JSHINT = (function () { WSH : true, WScript : true, XDomainRequest : true - }; + }, + yui = { + YUI : false, + Y : false, + YUI_config : false + }; // Regular expressions. Some of these are stupidly long. var ax, cx, tx, nx, nxg, lx, ix, jx, ft; (function () { @@ -750,14 +798,14 @@ var JSHINT = (function () { cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/; // token - tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/(\*(jshint|jslint|members?|global)?|=|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/; + tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/=(?!(\S*\/[gim]?))|\/(\*(jshint|jslint|members?|global)?|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/; // characters in strings that need escapement nx = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/; nxg = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; // star slash - lx = /\*\/|\/\*/; + lx = /\*\//; // identifier ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/; @@ -772,29 +820,85 @@ var JSHINT = (function () { function F() {} // Used by Object.create function is_own(object, name) { - -// The object.hasOwnProperty method fails when the property under consideration -// is named 'hasOwnProperty'. So we have to use this more convoluted form. - + // The object.hasOwnProperty method fails when the property under consideration + // is named 'hasOwnProperty'. So we have to use this more convoluted form. return Object.prototype.hasOwnProperty.call(object, name); } -// Provide critical ES5 functions to ES3. + function checkOption(name, t) { + if (valOptions[name] === undefined && boolOptions[name] === undefined) { + warning("Bad option: '" + name + "'.", t); + } + } - if (typeof Array.isArray !== 'function') { + function isString(obj) { + return Object.prototype.toString.call(obj) === "[object String]"; + } + + // Provide critical ES5 functions to ES3. + + if (typeof Array.isArray !== "function") { Array.isArray = function (o) { - return Object.prototype.toString.apply(o) === '[object Array]'; + return Object.prototype.toString.apply(o) === "[object Array]"; }; } - if (typeof Object.create !== 'function') { + if (!Array.prototype.forEach) { + Array.prototype.forEach = function (fn, scope) { + var len = this.length; + + for (var i = 0; i < len; i++) { + fn.call(scope || this, this[i], i, this); + } + }; + } + + if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) { + if (this === null || this === undefined) { + throw new TypeError(); + } + + var t = new Object(this); + var len = t.length >>> 0; + + if (len === 0) { + return -1; + } + + var n = 0; + if (arguments.length > 0) { + n = Number(arguments[1]); + if (n != n) { // shortcut for verifying if it's NaN + n = 0; + } else if (n !== 0 && n != Infinity && n != -Infinity) { + n = (n > 0 || -1) * Math.floor(Math.abs(n)); + } + } + + if (n >= len) { + return -1; + } + + var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0); + for (; k < len; k++) { + if (k in t && t[k] === searchElement) { + return k; + } + } + + return -1; + }; + } + + if (typeof Object.create !== "function") { Object.create = function (o) { F.prototype = o; return new F(); }; } - if (typeof Object.keys !== 'function') { + if (typeof Object.keys !== "function") { Object.keys = function (o) { var a = [], k; for (k in o) { @@ -806,74 +910,49 @@ var JSHINT = (function () { }; } -// Non standard methods + // Non standard methods - if (typeof String.prototype.entityify !== 'function') { - String.prototype.entityify = function () { - return this - .replace(/&/g, '&') - .replace(//g, '>'); - }; + function isAlpha(str) { + return (str >= "a" && str <= "z\uffff") || + (str >= "A" && str <= "Z\uffff"); } - if (typeof String.prototype.isAlpha !== 'function') { - String.prototype.isAlpha = function () { - return (this >= 'a' && this <= 'z\uffff') || - (this >= 'A' && this <= 'Z\uffff'); - }; + function isDigit(str) { + return (str >= "0" && str <= "9"); } - if (typeof String.prototype.isDigit !== 'function') { - String.prototype.isDigit = function () { - return (this >= '0' && this <= '9'); - }; + function isIdentifier(token, value) { + if (!token) + return false; + + if (!token.identifier || token.value !== value) + return false; + + return true; } - if (typeof String.prototype.supplant !== 'function') { - String.prototype.supplant = function (o) { - return this.replace(/\{([^{}]*)\}/g, function (a, b) { - var r = o[b]; - return typeof r === 'string' || typeof r === 'number' ? r : a; - }); - }; + function supplant(str, data) { + return str.replace(/\{([^{}]*)\}/g, function (a, b) { + var r = data[b]; + return typeof r === "string" || typeof r === "number" ? r : a; + }); } - if (typeof String.prototype.name !== 'function') { - String.prototype.name = function () { - -// If the string looks like an identifier, then we can return it as is. -// If the string contains no control characters, no quote characters, and no -// backslash characters, then we can simply slap some quotes around it. -// Otherwise we must also replace the offending characters with safe -// sequences. - - if (ix.test(this)) { - return this; - } - if (nx.test(this)) { - return '"' + this.replace(nxg, function (a) { - var c = escapes[a]; - if (c) { - return c; - } - return '\\u' + ('0000' + a.charCodeAt().toString(16)).slice(-4); - }) + '"'; - } - return '"' + this + '"'; - }; - } - - function combine(t, o) { var n; for (n in o) { - if (is_own(o, n)) { + if (is_own(o, n) && !is_own(JSHINT.blacklist, n)) { t[n] = o[n]; } } } + function updatePredefined() { + Object.keys(JSHINT.blacklist).forEach(function (key) { + delete predefined[key]; + }); + } + function assume() { if (option.couch) { combine(predefined, couch); @@ -889,6 +968,7 @@ var JSHINT = (function () { if (option.node) { combine(predefined, node); + option.globalstrict = true; } if (option.devel) { @@ -915,6 +995,10 @@ var JSHINT = (function () { combine(predefined, mootools); } + if (option.worker) { + combine(predefined, worker); + } + if (option.wsh) { combine(predefined, wsh); } @@ -926,6 +1010,10 @@ var JSHINT = (function () { if (option.globalstrict && option.strict !== false) { option.strict = true; } + + if (option.yui) { + combine(predefined, yui); + } } @@ -934,7 +1022,7 @@ var JSHINT = (function () { var percentage = Math.floor((line / lines.length) * 100); throw { - name: 'JSHintError', + name: "JSHintError", line: line, character: chr, message: message + " (" + percentage + "% scanned).", @@ -949,26 +1037,27 @@ var JSHINT = (function () { function warning(m, t, a, b, c, d) { var ch, l, w; t = t || nexttoken; - if (t.id === '(end)') { // `~ + if (t.id === "(end)") { // `~ t = token; } l = t.line || 0; ch = t.from || 0; w = { - id: '(error)', + id: "(error)", raw: m, - evidence: lines[l - 1] || '', + evidence: lines[l - 1] || "", line: l, character: ch, + scope: JSHINT.scope, a: a, b: b, c: c, d: d }; - w.reason = m.supplant(w); + w.reason = supplant(m, w); JSHINT.errors.push(w); if (option.passfail) { - quit('Stopping. ', l, ch); + quit("Stopping. ", l, ch); } warnings += 1; if (warnings >= option.maxerr) { @@ -985,7 +1074,7 @@ var JSHINT = (function () { } function error(m, t, a, b, c, d) { - var w = warning(m, t, a, b, c, d); + warning(m, t, a, b, c, d); } function errorAt(m, l, ch, a, b, c, d) { @@ -995,6 +1084,17 @@ var JSHINT = (function () { }, a, b, c, d); } + // Tracking of "internal" scripts, like eval containing a static string + function addInternalSrc(elem, src) { + var i; + i = { + id: "(internal)", + elem: elem, + value: src + }; + JSHINT.internals.push(i); + return i; + } // lexical analysis and token construction @@ -1006,6 +1106,7 @@ var JSHINT = (function () { function nextLine() { var at, + match, tw; // trailing whitespace check if (line >= lines.length) @@ -1017,10 +1118,14 @@ var JSHINT = (function () { // If smarttabs option is used check for spaces followed by tabs only. // Otherwise check for any occurence of mixed tabs and spaces. - if (option.smarttabs) - at = s.search(/ \t/); - else - at = s.search(/ \t|\t /); + // Tabs and one space followed by block comment is allowed. + if (option.smarttabs) { + // negative look-behind for "//" + match = s.match(/(\/\/)? \t/); + at = match && !match[1] ? 0 : -1; + } else { + at = s.search(/ \t|\t [^\*]/); + } if (at >= 0) warningAt("Mixed spaces and tabs.", line, at + 1); @@ -1035,9 +1140,9 @@ var JSHINT = (function () { warningAt("Line too long.", line, s.length); // Check for trailing whitespaces - tw = /\s+$/.test(s); - if (option.trailing && tw && !/^\s+$/.test(s)) { - warningAt("Trailing whitespace.", line, tw); + tw = option.trailing && s.match(/^(.*?)\s+$/); + if (tw && !/^\s+$/.test(s)) { + warningAt("Trailing whitespace.", line, tw[1].length + 1); } return true; } @@ -1046,46 +1151,74 @@ var JSHINT = (function () { function it(type, value) { var i, t; - if (type === '(color)' || type === '(range)') { + + function checkName(name) { + if (!option.proto && name === "__proto__") { + warningAt("The '{a}' property is deprecated.", line, from, name); + return; + } + + if (!option.iterator && name === "__iterator__") { + warningAt("'{a}' is only available in JavaScript 1.7.", line, from, name); + return; + } + + // Check for dangling underscores unless we're in Node + // environment and this identifier represents built-in + // Node globals with underscores. + + var hasDangling = /^(_+.*|.*_+)$/.test(name); + + if (option.nomen && hasDangling && name !== "_") { + if (option.node && token.id !== "." && /^(__dirname|__filename)$/.test(name)) + return; + + warningAt("Unexpected {a} in '{b}'.", line, from, "dangling '_'", name); + return; + } + + // Check for non-camelcase names. Names like MY_VAR and + // _myVar are okay though. + + if (option.camelcase) { + if (name.replace(/^_+/, "").indexOf("_") > -1 && !name.match(/^[A-Z0-9_]*$/)) { + warningAt("Identifier '{a}' is not in camel case.", line, from, value); + } + } + } + + if (type === "(color)" || type === "(range)") { t = {type: type}; - } else if (type === '(punctuator)' || - (type === '(identifier)' && is_own(syntax, value))) { - t = syntax[value] || syntax['(error)']; + } else if (type === "(punctuator)" || + (type === "(identifier)" && is_own(syntax, value))) { + t = syntax[value] || syntax["(error)"]; } else { t = syntax[type]; } + t = Object.create(t); - if (type === '(string)' || type === '(range)') { + + if (type === "(string)" || type === "(range)") { if (!option.scripturl && jx.test(value)) { warningAt("Script URL.", line, from); } } - if (type === '(identifier)') { + + if (type === "(identifier)") { t.identifier = true; - if (value === '__proto__' && !option.proto) { - warningAt("The '{a}' property is deprecated.", - line, from, value); - } else if (value === '__iterator__' && !option.iterator) { - warningAt("'{a}' is only available in JavaScript 1.7.", - line, from, value); - } else if (option.nomen && (value.charAt(0) === '_' || - value.charAt(value.length - 1) === '_')) { - if (!option.node || token.id === '.' || - (value !== '__dirname' && value !== '__filename')) { - warningAt("Unexpected {a} in '{b}'.", line, from, "dangling '_'", value); - } - } + checkName(value); } + t.value = value; t.line = line; t.character = character; t.from = from; i = t.id; - if (i !== '(endline)') { + if (i !== "(endline)") { prereg = i && - (('(,=:[!&|?{};'.indexOf(i.charAt(i.length - 1)) >= 0) || - i === 'return' || - i === 'case'); + (("(,=:[!&|?{};".indexOf(i.charAt(i.length - 1)) >= 0) || + i === "return" || + i === "case"); } return t; } @@ -1093,19 +1226,19 @@ var JSHINT = (function () { // Public lex methods return { init: function (source) { - if (typeof source === 'string') { + if (typeof source === "string") { lines = source - .replace(/\r\n/g, '\n') - .replace(/\r/g, '\n') - .split('\n'); + .replace(/\r\n/g, "\n") + .replace(/\r/g, "\n") + .split("\n"); } else { lines = source; } // If the first line is a shebang (#!), make it a blank and move on. // Shebangs are used by Node scripts. - if (lines[0] && lines[0].substr(0, 2) === '#!') - lines[0] = ''; + if (lines[0] && lines[0].substr(0, 2) === "#!") + lines[0] = ""; line = 0; nextLine(); @@ -1113,7 +1246,7 @@ var JSHINT = (function () { }, range: function (begin, end) { - var c, value = ''; + var c, value = ""; from = character; if (s.charAt(0) !== begin) { errorAt("Expected '{a}' and instead saw '{b}'.", @@ -1124,14 +1257,14 @@ var JSHINT = (function () { character += 1; c = s.charAt(0); switch (c) { - case '': + case "": errorAt("Missing '{a}'.", line, character, c); break; case end: s = s.slice(1); character += 1; - return it('(range)', value); - case '\\': + return it("(range)", value); + case "\\": warningAt("Unexpected '{a}'.", line, character, c); } value += c; @@ -1142,10 +1275,11 @@ var JSHINT = (function () { // token -- this is called by advance to get the next token token: function () { - var b, c, captures, d, depth, high, i, l, low, q, t, isLiteral, isInRange; + var b, c, captures, d, depth, high, i, l, low, q, t, isLiteral, isInRange, n; function match(x) { var r = x.exec(s), r1; + if (r) { l = r[0].length; r1 = r[1]; @@ -1158,13 +1292,29 @@ var JSHINT = (function () { } function string(x) { - var c, j, r = '', allowNewLine = false; + var c, j, r = "", allowNewLine = false; - if (jsonmode && x !== '"') { + if (jsonmode && x !== "\"") { warningAt("Strings must use doublequote.", line, character); } + if (option.quotmark) { + if (option.quotmark === "single" && x !== "'") { + warningAt("Strings must use singlequote.", + line, character); + } else if (option.quotmark === "double" && x !== "\"") { + warningAt("Strings must use doublequote.", + line, character); + } else if (option.quotmark === true) { + quotmark = quotmark || x; + if (quotmark !== x) { + warningAt("Mixed double and single quotes.", + line, character); + } + } + } + function esc(n) { var i = parseInt(s.substr(j + 1, n), 16); j += n; @@ -1175,8 +1325,11 @@ var JSHINT = (function () { character += n; c = String.fromCharCode(i); } + j = 0; -unclosedString: for (;;) { + +unclosedString: + for (;;) { while (j >= s.length) { j = 0; @@ -1192,63 +1345,77 @@ unclosedString: for (;;) { warningAt("Unclosed string.", cl, cf); } } + c = s.charAt(j); if (c === x) { character += 1; s = s.substr(j + 1); - return it('(string)', r, x); + return it("(string)", r, x); } - if (c < ' ') { - if (c === '\n' || c === '\r') { + + if (c < " ") { + if (c === "\n" || c === "\r") { break; } warningAt("Control character in string: {a}.", line, character + j, s.slice(0, j)); - } else if (c === '\\') { + } else if (c === "\\") { j += 1; character += 1; c = s.charAt(j); + n = s.charAt(j + 1); switch (c) { - case '\\': - case '"': - case '/': + case "\\": + case "\"": + case "/": break; - case '\'': + case "\'": if (jsonmode) { warningAt("Avoid \\'.", line, character); } break; - case 'b': - c = '\b'; + case "b": + c = "\b"; break; - case 'f': - c = '\f'; + case "f": + c = "\f"; break; - case 'n': - c = '\n'; + case "n": + c = "\n"; break; - case 'r': - c = '\r'; + case "r": + c = "\r"; break; - case 't': - c = '\t'; + case "t": + c = "\t"; break; - case 'u': + case "0": + c = "\0"; + // Octal literals fail in strict mode + // check if the number is between 00 and 07 + // where 'n' is the token next to 'c' + if (n >= 0 && n <= 7 && directive["use strict"]) { + warningAt( + "Octal literals are not allowed in strict mode.", + line, character); + } + break; + case "u": esc(4); break; - case 'v': + case "v": if (jsonmode) { warningAt("Avoid \\v.", line, character); } - c = '\v'; + c = "\v"; break; - case 'x': + case "x": if (jsonmode) { warningAt("Avoid \\x-.", line, character); } esc(2); break; - case '': + case "": // last character is escape character // always allow new line if escaped, but show // warning if option is not set @@ -1257,13 +1424,17 @@ unclosedString: for (;;) { if (jsonmode) { warningAt("Avoid EOL escapement.", line, character); } - c = ''; + c = ""; character -= 1; break; } warningAt("Bad escapement of EOL. Use option multistr if needed.", line, character); break; + case "!": + if (s.charAt(j - 2) === "<") + break; + /*falls through*/ default: warningAt("Bad escapement.", line, character); } @@ -1276,74 +1447,76 @@ unclosedString: for (;;) { for (;;) { if (!s) { - return it(nextLine() ? '(endline)' : '(end)', ''); + return it(nextLine() ? "(endline)" : "(end)", ""); } + t = match(tx); + if (!t) { - t = ''; - c = ''; - while (s && s < '!') { + t = ""; + c = ""; + while (s && s < "!") { s = s.substr(1); } if (s) { errorAt("Unexpected '{a}'.", line, character, s.substr(0, 1)); - s = ''; + s = ""; } } else { // identifier - if (c.isAlpha() || c === '_' || c === '$') { - return it('(identifier)', t); + if (isAlpha(c) || c === "_" || c === "$") { + return it("(identifier)", t); } // number - if (c.isDigit()) { + if (isDigit(c)) { if (!isFinite(Number(t))) { warningAt("Bad number '{a}'.", line, character, t); } - if (s.substr(0, 1).isAlpha()) { + if (isAlpha(s.substr(0, 1))) { warningAt("Missing space after '{a}'.", line, character, t); } - if (c === '0') { + if (c === "0") { d = t.substr(1, 1); - if (d.isDigit()) { - if (token.id !== '.') { + if (isDigit(d)) { + if (token.id !== ".") { warningAt("Don't use extra leading zeros '{a}'.", line, character, t); } - } else if (jsonmode && (d === 'x' || d === 'X')) { + } else if (jsonmode && (d === "x" || d === "X")) { warningAt("Avoid 0x-. '{a}'.", line, character, t); } } - if (t.substr(t.length - 1) === '.') { + if (t.substr(t.length - 1) === ".") { warningAt( "A trailing decimal point can be confused with a dot '{a}'.", line, character, t); } - return it('(number)', t); + return it("(number)", t); } switch (t) { // string - case '"': + case "\"": case "'": return string(t); // // comment - case '//': - s = ''; + case "//": + s = ""; token.comment = true; break; // /* comment - case '/*': + case "/*": for (;;) { i = s.search(lx); if (i >= 0) { @@ -1353,38 +1526,35 @@ unclosedString: for (;;) { errorAt("Unclosed comment.", line, character); } } - character += i + 2; - if (s.substr(i, 1) === '/') { - errorAt("Nested comment.", line, character); - } s = s.substr(i + 2); token.comment = true; break; // /*members /*jshint /*global - case '/*members': - case '/*member': - case '/*jshint': - case '/*jslint': - case '/*global': - case '*/': + case "/*members": + case "/*member": + case "/*jshint": + case "/*jslint": + case "/*global": + case "*/": return { value: t, - type: 'special', + type: "special", line: line, character: character, from: from }; - case '': + case "": break; // / - case '/': - if (token.id === '/=') { + case "/": + if (s.charAt(0) === "=") { errorAt("A regular expression literal can be confused with '/='.", line, from); } + if (prereg) { depth = 0; captures = 0; @@ -1394,10 +1564,10 @@ unclosedString: for (;;) { c = s.charAt(l); l += 1; switch (c) { - case '': + case "": errorAt("Unclosed regular expression.", line, from); - return quit('Stopping.', line, from); - case '/': + return quit("Stopping.", line, from); + case "/": if (depth > 0) { warningAt("{a} unterminated regular expression " + "group(s).", line, from + l, depth); @@ -1415,55 +1585,55 @@ unclosedString: for (;;) { character += l; s = s.substr(l); q = s.charAt(0); - if (q === '/' || q === '*') { + if (q === "/" || q === "*") { errorAt("Confusing regular expression.", line, from); } - return it('(regexp)', c); - case '\\': + return it("(regexp)", c); + case "\\": c = s.charAt(l); - if (c < ' ') { + if (c < " ") { warningAt( "Unexpected control character in regular expression.", line, from + l); - } else if (c === '<') { + } else if (c === "<") { warningAt( "Unexpected escaped character '{a}' in regular expression.", line, from + l, c); } l += 1; break; - case '(': + case "(": depth += 1; b = false; - if (s.charAt(l) === '?') { + if (s.charAt(l) === "?") { l += 1; switch (s.charAt(l)) { - case ':': - case '=': - case '!': + case ":": + case "=": + case "!": l += 1; break; default: warningAt( -"Expected '{a}' and instead saw '{b}'.", line, from + l, ':', s.charAt(l)); +"Expected '{a}' and instead saw '{b}'.", line, from + l, ":", s.charAt(l)); } } else { captures += 1; } break; - case '|': + case "|": b = false; break; - case ')': + case ")": if (depth === 0) { warningAt("Unescaped '{a}'.", - line, from + l, ')'); + line, from + l, ")"); } else { depth -= 1; } break; - case ' ': + case " ": q = 1; - while (s.charAt(l) === ' ') { + while (s.charAt(l) === " ") { l += 1; q += 1; } @@ -1472,30 +1642,28 @@ unclosedString: for (;;) { "Spaces are hard to count. Use {{a}}.", line, from + l, q); } break; - case '[': + case "[": c = s.charAt(l); - if (c === '^') { + if (c === "^") { l += 1; - if (option.regexp) { - warningAt("Insecure '{a}'.", - line, from + l, c); - } else if (s.charAt(l) === ']') { + if (s.charAt(l) === "]") { errorAt("Unescaped '{a}'.", - line, from + l, '^'); + line, from + l, "^"); } } - if (c === ']') { + if (c === "]") { warningAt("Empty class.", line, from + l - 1); } isLiteral = false; isInRange = false; -klass: do { +klass: + do { c = s.charAt(l); l += 1; switch (c) { - case '[': - case '^': + case "[": + case "^": warningAt("Unescaped '{a}'.", line, from + l, c); if (isInRange) { @@ -1504,35 +1672,35 @@ klass: do { isLiteral = true; } break; - case '-': + case "-": if (isLiteral && !isInRange) { isLiteral = false; isInRange = true; } else if (isInRange) { isInRange = false; - } else if (s.charAt(l) === ']') { + } else if (s.charAt(l) === "]") { isInRange = true; } else { if (option.regexdash !== (l === 2 || (l === 3 && - s.charAt(1) === '^'))) { + s.charAt(1) === "^"))) { warningAt("Unescaped '{a}'.", - line, from + l - 1, '-'); + line, from + l - 1, "-"); } isLiteral = true; } break; - case ']': + case "]": if (isInRange && !option.regexdash) { warningAt("Unescaped '{a}'.", - line, from + l - 1, '-'); + line, from + l - 1, "-"); } break klass; - case '\\': + case "\\": c = s.charAt(l); - if (c < ' ') { + if (c < " ") { warningAt( "Unexpected control character in regular expression.", line, from + l); - } else if (c === '<') { + } else if (c === "<") { warningAt( "Unexpected escaped character '{a}' in regular expression.", line, from + l, c); } @@ -1542,7 +1710,7 @@ klass: do { if (/[wsd]/i.test(c)) { if (isInRange) { warningAt("Unescaped '{a}'.", - line, from + l, '-'); + line, from + l, "-"); isInRange = false; } isLiteral = false; @@ -1552,9 +1720,9 @@ klass: do { isLiteral = true; } break; - case '/': + case "/": warningAt("Unescaped '{a}'.", - line, from + l - 1, '/'); + line, from + l - 1, "/"); if (isInRange) { isInRange = false; @@ -1562,7 +1730,7 @@ klass: do { isLiteral = true; } break; - case '<': + case "<": if (isInRange) { isInRange = false; } else { @@ -1578,59 +1746,60 @@ klass: do { } } while (c); break; - case '.': + case ".": if (option.regexp) { warningAt("Insecure '{a}'.", line, from + l, c); } break; - case ']': - case '?': - case '{': - case '}': - case '+': - case '*': + case "]": + case "?": + case "{": + case "}": + case "+": + case "*": warningAt("Unescaped '{a}'.", line, from + l, c); } if (b) { switch (s.charAt(l)) { - case '?': - case '+': - case '*': + case "?": + case "+": + case "*": l += 1; - if (s.charAt(l) === '?') { + if (s.charAt(l) === "?") { l += 1; } break; - case '{': + case "{": l += 1; c = s.charAt(l); - if (c < '0' || c > '9') { + if (c < "0" || c > "9") { warningAt( "Expected a number and instead saw '{a}'.", line, from + l, c); + break; // No reason to continue checking numbers. } l += 1; low = +c; for (;;) { c = s.charAt(l); - if (c < '0' || c > '9') { + if (c < "0" || c > "9") { break; } l += 1; low = +c + (low * 10); } high = low; - if (c === ',') { + if (c === ",") { l += 1; high = Infinity; c = s.charAt(l); - if (c >= '0' && c <= '9') { + if (c >= "0" && c <= "9") { l += 1; high = +c; for (;;) { c = s.charAt(l); - if (c < '0' || c > '9') { + if (c < "0" || c > "9") { break; } l += 1; @@ -1638,13 +1807,13 @@ klass: do { } } } - if (s.charAt(l) !== '}') { + if (s.charAt(l) !== "}") { warningAt( -"Expected '{a}' and instead saw '{b}'.", line, from + l, '}', c); +"Expected '{a}' and instead saw '{b}'.", line, from + l, "}", c); } else { l += 1; } - if (s.charAt(l) === '?') { + if (s.charAt(l) === "?") { l += 1; } if (low > high) { @@ -1657,16 +1826,16 @@ klass: do { c = s.substr(0, l - 1); character += l; s = s.substr(l); - return it('(regexp)', c); + return it("(regexp)", c); } - return it('(punctuator)', t); + return it("(punctuator)", t); // punctuator - case '#': - return it('(punctuator)', t); + case "#": + return it("(punctuator)", t); default: - return it('(punctuator)', t); + return it("(punctuator)", t); } } } @@ -1675,25 +1844,38 @@ klass: do { }()); - function addlabel(t, type) { - - if (t === 'hasOwnProperty') { + function addlabel(t, type, token) { + if (t === "hasOwnProperty") { warning("'hasOwnProperty' is a really bad name."); } -// Define t in the current function in the current scope. - if (is_own(funct, t) && !funct['(global)']) { + // Define t in the current function in the current scope. + if (type === "exception") { + if (is_own(funct["(context)"], t)) { + if (funct[t] !== true && !option.node) { + warning("Value of '{a}' may be overwritten in IE.", nexttoken, t); + } + } + } + + if (is_own(funct, t) && !funct["(global)"]) { if (funct[t] === true) { if (option.latedef) warning("'{a}' was used before it was defined.", nexttoken, t); } else { - if (!option.shadow && type !== "exception") + if (!option.shadow && type !== "exception") { warning("'{a}' is already defined.", nexttoken, t); + } } } funct[t] = type; - if (funct['(global)']) { + + if (token) { + funct["(tokens)"][t] = token; + } + + if (funct["(global)"]) { global[t] = funct; if (is_own(implied, t)) { if (option.latedef) @@ -1707,102 +1889,163 @@ klass: do { function doOption() { - var b, obj, filter, o = nexttoken.value, t, v; + var nt = nexttoken; + var o = nt.value; + var quotmarkValue = option.quotmark; + var predef = {}; + var b, obj, filter, t, tn, v, minus; + switch (o) { - case '*/': + case "*/": error("Unbegun comment."); break; - case '/*members': - case '/*member': - o = '/*members'; + case "/*members": + case "/*member": + o = "/*members"; if (!membersOnly) { membersOnly = {}; } obj = membersOnly; + option.quotmark = false; break; - case '/*jshint': - case '/*jslint': + case "/*jshint": + case "/*jslint": obj = option; filter = boolOptions; break; - case '/*global': - obj = predefined; + case "/*global": + obj = predef; break; default: error("What?"); } + t = lex.token(); -loop: for (;;) { + +loop: + for (;;) { + minus = false; for (;;) { - if (t.type === 'special' && t.value === '*/') { + if (t.type === "special" && t.value === "*/") { break loop; } - if (t.id !== '(endline)' && t.id !== ',') { + if (t.id !== "(endline)" && t.id !== ",") { break; } t = lex.token(); } - if (t.type !== '(string)' && t.type !== '(identifier)' && - o !== '/*members') { + + if (o === "/*global" && t.value === "-") { + minus = true; + t = lex.token(); + } + + if (t.type !== "(string)" && t.type !== "(identifier)" && o !== "/*members") { error("Bad option.", t); } + v = lex.token(); - if (v.id === ':') { + if (v.id === ":") { v = lex.token(); + if (obj === membersOnly) { - error("Expected '{a}' and instead saw '{b}'.", - t, '*/', ':'); + error("Expected '{a}' and instead saw '{b}'.", t, "*/", ":"); } - if (t.value === 'indent' && (o === '/*jshint' || o === '/*jslint')) { + + if (o === "/*jshint") { + checkOption(t.value, t); + } + + var numericVals = [ + "maxstatements", + "maxparams", + "maxdepth", + "maxcomplexity", + "maxerr", + "maxlen", + "indent" + ]; + + if (numericVals.indexOf(t.value) > -1 && (o === "/*jshint" || o === "/*jslint")) { b = +v.value; - if (typeof b !== 'number' || !isFinite(b) || b <= 0 || - Math.floor(b) !== b) { - error("Expected a small integer and instead saw '{a}'.", - v, v.value); + + if (typeof b !== "number" || !isFinite(b) || b <= 0 || Math.floor(b) !== b) { + error("Expected a small integer and instead saw '{a}'.", v, v.value); } - obj.white = true; - obj.indent = b; - } else if (t.value === 'maxerr' && (o === '/*jshint' || o === '/*jslint')) { - b = +v.value; - if (typeof b !== 'number' || !isFinite(b) || b <= 0 || - Math.floor(b) !== b) { - error("Expected a small integer and instead saw '{a}'.", - v, v.value); - } - obj.maxerr = b; - } else if (t.value === 'maxlen' && (o === '/*jshint' || o === '/*jslint')) { - b = +v.value; - if (typeof b !== 'number' || !isFinite(b) || b <= 0 || - Math.floor(b) !== b) { - error("Expected a small integer and instead saw '{a}'.", - v, v.value); - } - obj.maxlen = b; - } else if (t.value === 'validthis') { - if (funct['(global)']) { + + if (t.value === "indent") + obj.white = true; + + obj[t.value] = b; + } else if (t.value === "validthis") { + if (funct["(global)"]) { error("Option 'validthis' can't be used in a global scope."); } else { - if (v.value === 'true' || v.value === 'false') - obj[t.value] = v.value === 'true'; + if (v.value === "true" || v.value === "false") + obj[t.value] = v.value === "true"; else error("Bad option value.", v); } - } else if (v.value === 'true') { - obj[t.value] = true; - } else if (v.value === 'false') { - obj[t.value] = false; + } else if (t.value === "quotmark" && (o === "/*jshint")) { + switch (v.value) { + case "true": + obj.quotmark = true; + break; + case "false": + obj.quotmark = false; + break; + case "double": + case "single": + obj.quotmark = v.value; + break; + default: + error("Bad option value.", v); + } + } else if (v.value === "true" || v.value === "false") { + if (o === "/*jslint") { + tn = renamedOptions[t.value] || t.value; + obj[tn] = v.value === "true"; + if (invertedOptions[tn] !== undefined) { + obj[tn] = !obj[tn]; + } + } else { + obj[t.value] = v.value === "true"; + } + + if (t.value === "newcap") + obj["(explicitNewcap)"] = true; } else { error("Bad option value.", v); } t = lex.token(); } else { - if (o === '/*jshint' || o === '/*jslint') { + if (o === "/*jshint" || o === "/*jslint") { error("Missing option value.", t); } + obj[t.value] = false; + + if (o === "/*global" && minus === true) { + JSHINT.blacklist[t.value] = t.value; + updatePredefined(); + } + t = v; } } + + if (o === "/*members") { + option.quotmark = quotmarkValue; + } + + combine(predefined, predef); + + for (var key in predef) { + if (is_own(predef, key)) { + declared[key] = nt; + } + } + if (filter) { assume(); } @@ -1834,36 +2077,36 @@ loop: for (;;) { function advance(id, t) { switch (token.id) { - case '(number)': - if (nexttoken.id === '.') { + case "(number)": + if (nexttoken.id === ".") { warning("A dot following a number can be confused with a decimal point.", token); } break; - case '-': - if (nexttoken.id === '-' || nexttoken.id === '--') { + case "-": + if (nexttoken.id === "-" || nexttoken.id === "--") { warning("Confusing minusses."); } break; - case '+': - if (nexttoken.id === '+' || nexttoken.id === '++') { + case "+": + if (nexttoken.id === "+" || nexttoken.id === "++") { warning("Confusing plusses."); } break; } - if (token.type === '(string)' || token.identifier) { + if (token.type === "(string)" || token.identifier) { anonname = token.value; } if (id && nexttoken.id !== id) { if (t) { - if (nexttoken.id === '(end)') { + if (nexttoken.id === "(end)") { warning("Unmatched '{a}'.", t, t.id); } else { warning("Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.", nexttoken, id, t.id, t.line, nexttoken.value); } - } else if (nexttoken.type !== '(identifier)' || + } else if (nexttoken.type !== "(identifier)" || nexttoken.value !== id) { warning("Expected '{a}' and instead saw '{b}'.", nexttoken, id, nexttoken.value); @@ -1874,13 +2117,13 @@ loop: for (;;) { token = nexttoken; for (;;) { nexttoken = lookahead.shift() || lex.token(); - if (nexttoken.id === '(end)' || nexttoken.id === '(error)') { + if (nexttoken.id === "(end)" || nexttoken.id === "(error)") { return; } - if (nexttoken.type === 'special') { + if (nexttoken.type === "special") { doOption(); } else { - if (nexttoken.id !== '(endline)') { + if (nexttoken.id !== "(endline)") { break; } } @@ -1903,15 +2146,15 @@ loop: for (;;) { // They are elements of the parsing method called Top Down Operator Precedence. function expression(rbp, initial) { - var left, isArray = false; + var left, isArray = false, isObject = false; - if (nexttoken.id === '(end)') + if (nexttoken.id === "(end)") error("Unexpected early end of program.", token); advance(); if (initial) { - anonname = 'anonymous'; - funct['(verb)'] = token.value; + anonname = "anonymous"; + funct["(verb)"] = token.value; } if (initial === true && token.fud) { left = token.fud(); @@ -1919,7 +2162,7 @@ loop: for (;;) { if (token.nud) { left = token.nud(); } else { - if (nexttoken.type === '(number)' && token.id === '.') { + if (nexttoken.type === "(number)" && token.id === ".") { warning("A leading decimal point can be confused with a dot: '.{a}'.", token, nexttoken.value); advance(); @@ -1930,10 +2173,32 @@ loop: for (;;) { } } while (rbp < nexttoken.lbp) { - isArray = token.value === 'Array'; + isArray = token.value === "Array"; + isObject = token.value === "Object"; + + // #527, new Foo.Array(), Foo.Array(), new Foo.Object(), Foo.Object() + // Line breaks in IfStatement heads exist to satisfy the checkJSHint + // "Line too long." error. + if (left && (left.value || (left.first && left.first.value))) { + // If the left.value is not "new", or the left.first.value is a "." + // then safely assume that this is not "new Array()" and possibly + // not "new Object()"... + if (left.value !== "new" || + (left.first && left.first.value && left.first.value === ".")) { + isArray = false; + // ...In the case of Object, if the left.value and token.value + // are not equal, then safely assume that this not "new Object()" + if (left.value !== token.value) { + isObject = false; + } + } + } + advance(); - if (isArray && token.id === '(' && nexttoken.id === ')') + if (isArray && token.id === "(" && nexttoken.id === ")") warning("Use the array literal notation [].", token); + if (isObject && token.id === "(" && nexttoken.id === ")") + warning("Use the object literal notation {}.", token); if (token.led) { left = token.led(left); } else { @@ -1981,6 +2246,9 @@ loop: for (;;) { if (option.white) { left = left || token; right = right || nexttoken; + if (left.value === ";" && right.value === ";") { + return; + } if (left.line === right.line && left.character === right.from) { left.from += (left.character - left.from); warning("Missing space after '{a}'.", @@ -2007,7 +2275,7 @@ loop: for (;;) { function indentation(bias) { var i; - if (option.white && nexttoken.id !== '(end)') { + if (option.white && nexttoken.id !== "(end)") { i = indent + (bias || 0); if (nexttoken.from !== i) { warning( @@ -2038,19 +2306,17 @@ loop: for (;;) { token.from += (token.character - token.from); warning("Unexpected space after '{a}'.", token, token.value); } - advance(','); + advance(","); nonadjacent(token, nexttoken); } - comma.first = true; - // Functional constructors for making the symbols that will be inherited by // tokens. function symbol(s, p) { var x = syntax[s]; - if (!x || typeof x !== 'object') { + if (!x || typeof x !== "object") { syntax[s] = x = { id: s, lbp: p, @@ -2083,7 +2349,7 @@ loop: for (;;) { function reserveName(x) { var c = x.id.charAt(0); - if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z")) { x.identifier = x.reserved = true; } return x; @@ -2093,14 +2359,14 @@ loop: for (;;) { function prefix(s, f) { var x = symbol(s, 150); reserveName(x); - x.nud = (typeof f === 'function') ? f : function () { + x.nud = (typeof f === "function") ? f : function () { this.right = expression(150); - this.arity = 'unary'; - if (this.id === '++' || this.id === '--') { + this.arity = "unary"; + if (this.id === "++" || this.id === "--") { if (option.plusplus) { warning("Unexpected use of '{a}'.", this, this.id); } else if ((!this.right.identifier || this.right.reserved) && - this.right.id !== '.' && this.right.id !== '[') { + this.right.id !== "." && this.right.id !== "[") { warning("Bad operand.", this); } } @@ -2127,7 +2393,7 @@ loop: for (;;) { function reservevar(s, v) { return reserve(s, function () { - if (typeof v === 'function') { + if (typeof v === "function") { v(this); } return this; @@ -2144,9 +2410,9 @@ loop: for (;;) { nonadjacent(token, nexttoken); } if (s === "in" && left.id === "!") { - warning("Confusing use of '{a}'.", left, '!'); + warning("Confusing use of '{a}'.", left, "!"); } - if (typeof f === 'function') { + if (typeof f === "function") { return f(left, this); } else { this.left = left; @@ -2164,16 +2430,17 @@ loop: for (;;) { nobreaknonadjacent(prevtoken, token); nonadjacent(token, nexttoken); var right = expression(100); - if ((left && left.id === 'NaN') || (right && right.id === 'NaN')) { + + if (isIdentifier(left, "NaN") || isIdentifier(right, "NaN")) { warning("Use the isNaN function to compare with NaN.", this); } else if (f) { f.apply(this, [left, right]); } - if (left.id === '!') { - warning("Confusing use of '{a}'.", left, '!'); + if (left.id === "!") { + warning("Confusing use of '{a}'.", left, "!"); } - if (right.id === '!') { - warning("Confusing use of '{a}'.", right, '!'); + if (right.id === "!") { + warning("Confusing use of '{a}'.", right, "!"); } this.left = left; this.right = right; @@ -2185,49 +2452,54 @@ loop: for (;;) { function isPoorRelation(node) { return node && - ((node.type === '(number)' && +node.value === 0) || - (node.type === '(string)' && node.value === '') || - (node.type === 'null' && !option.eqnull) || - node.type === 'true' || - node.type === 'false' || - node.type === 'undefined'); + ((node.type === "(number)" && +node.value === 0) || + (node.type === "(string)" && node.value === "") || + (node.type === "null" && !option.eqnull) || + node.type === "true" || + node.type === "false" || + node.type === "undefined"); } - function assignop(s, f) { + function assignop(s) { symbol(s, 20).exps = true; + return infix(s, function (left, that) { - var l; that.left = left; + if (predefined[left.value] === false && - scope[left.value]['(global)'] === true) { + scope[left.value]["(global)"] === true) { warning("Read only.", left); - } else if (left['function']) { + } else if (left["function"]) { warning("'{a}' is a function.", left, left.value); } + if (left) { - if (option.esnext && funct[left.value] === 'const') { + if (option.esnext && funct[left.value] === "const") { warning("Attempting to override '{a}' which is a constant", left, left.value); } - if (left.id === '.' || left.id === '[') { - if (!left.left || left.left.value === 'arguments') { - warning('Bad assignment.', that); + + if (left.id === "." || left.id === "[") { + if (!left.left || left.left.value === "arguments") { + warning("Bad assignment.", that); } that.right = expression(19); return that; } else if (left.identifier && !left.reserved) { - if (funct[left.value] === 'exception') { + if (funct[left.value] === "exception") { warning("Do not assign to the exception parameter.", left); } that.right = expression(19); return that; } - if (left === syntax['function']) { + + if (left === syntax["function"]) { warning( "Expected an identifier in an assignment and instead saw a function invocation.", token); } } + error("Bad assignment.", that); }, 20); } @@ -2236,7 +2508,7 @@ loop: for (;;) { function bitwise(s, f, p) { var x = symbol(s, p); reserveName(x); - x.led = (typeof f === 'function') ? f : function (left) { + x.led = (typeof f === "function") ? f : function (left) { if (option.bitwise) { warning("Unexpected use of '{a}'.", this, this.id); } @@ -2257,12 +2529,12 @@ loop: for (;;) { nonadjacent(prevtoken, token); nonadjacent(token, nexttoken); if (left) { - if (left.id === '.' || left.id === '[' || + if (left.id === "." || left.id === "[" || (left.identifier && !left.reserved)) { expression(19); return that; } - if (left === syntax['function']) { + if (left === syntax["function"]) { warning( "Expected an identifier in an assignment, and instead saw a function invocation.", token); @@ -2274,13 +2546,13 @@ loop: for (;;) { } - function suffix(s, f) { + function suffix(s) { var x = symbol(s, 150); x.led = function (left) { if (option.plusplus) { warning("Unexpected use of '{a}'.", this, this.id); } else if ((!left.identifier || left.reserved) && - left.id !== '.' && left.id !== '[') { + left.id !== "." && left.id !== "[") { warning("Bad operand.", this); } this.left = left; @@ -2299,7 +2571,7 @@ loop: for (;;) { // `undefined` as a function param is a common pattern to protect // against the case when somebody does `undefined = true` and // help with minification. More info: https://gist.github.com/315916 - if (!fnparam || token.value !== 'undefined') { + if (!fnparam || token.value !== "undefined") { warning("Expected an identifier and instead saw '{a}' (a reserved word).", token, token.id); } @@ -2315,7 +2587,7 @@ loop: for (;;) { if (i) { return i; } - if (token.id === 'function' && nexttoken.id === '(') { + if (token.id === "function" && nexttoken.id === "(") { warning("Missing name in function declaration."); } else { error("Expected an identifier and instead saw '{a}'.", @@ -2326,7 +2598,7 @@ loop: for (;;) { function reachable(s) { var i = 0, t; - if (nexttoken.id !== ';' || noreach) { + if (nexttoken.id !== ";" || noreach) { return; } for (;;) { @@ -2334,8 +2606,8 @@ loop: for (;;) { if (t.reach) { return; } - if (t.id !== '(endline)') { - if (t.id === 'function') { + if (t.id !== "(endline)") { + if (t.id === "function") { if (!option.latedef) { break; } @@ -2359,26 +2631,34 @@ loop: for (;;) { return; } -// Is this a labelled statement? + // Is this a labelled statement? - if (t.identifier && !t.reserved && peek().id === ':') { + if (t.identifier && !t.reserved && peek().id === ":") { advance(); - advance(':'); + advance(":"); scope = Object.create(s); - addlabel(t.value, 'label'); - if (!nexttoken.labelled) { - warning("Label '{a}' on {b} statement.", - nexttoken, t.value, nexttoken.value); + addlabel(t.value, "label"); + + if (!nexttoken.labelled && nexttoken.value !== "{") { + warning("Label '{a}' on {b} statement.", nexttoken, t.value, nexttoken.value); } - if (jx.test(t.value + ':')) { - warning("Label '{a}' looks like a javascript url.", - t, t.value); + + if (jx.test(t.value + ":")) { + warning("Label '{a}' looks like a javascript url.", t, t.value); } + nexttoken.label = t.value; t = nexttoken; } -// Parse the statement. + // Is it a lonely block? + + if (t.id === "{") { + block(true, true); + return; + } + + // Parse the statement. if (!noindent) { indentation(); @@ -2386,27 +2666,32 @@ loop: for (;;) { r = expression(0, true); // Look for the final semicolon. + if (!t.block) { if (!option.expr && (!r || !r.exps)) { warning("Expected an assignment or function call and instead saw an expression.", token); - } else if (option.nonew && r.id === '(' && r.left.id === 'new') { - warning("Do not use 'new' for side effects."); + } else if (option.nonew && r.id === "(" && r.left.id === "new") { + warning("Do not use 'new' for side effects.", t); } - if (nexttoken.id !== ';') { + if (nexttoken.id === ",") { + return comma(); + } + + if (nexttoken.id !== ";") { if (!option.asi) { // If this is the last statement in a block that ends on // the same line *and* option lastsemic is on, ignore the warning. // Otherwise, complain about missing semicolon. - if (!option.lastsemic || nexttoken.id !== '}' || + if (!option.lastsemic || nexttoken.id !== "}" || nexttoken.line !== token.line) { warningAt("Missing semicolon.", token.line, token.character); } } } else { adjacent(token, nexttoken); - advance(';'); + advance(";"); nonadjacent(token, nexttoken); } } @@ -2420,15 +2705,15 @@ loop: for (;;) { function statements(startLine) { - var a = [], f, p; + var a = [], p; - while (!nexttoken.reach && nexttoken.id !== '(end)') { - if (nexttoken.id === ';') { + while (!nexttoken.reach && nexttoken.id !== "(end)") { + if (nexttoken.id === ";") { p = peek(); if (!p || p.id !== "(") { warning("Unnecessary semicolon."); } - advance(';'); + advance(";"); } else { a.push(statement(startLine === nexttoken.line)); } @@ -2479,7 +2764,8 @@ loop: for (;;) { } if (token.value === "use strict") { - option.newcap = true; + if (!option["(explicitNewcap)"]) + option.newcap = true; option.undef = true; } @@ -2515,14 +2801,21 @@ loop: for (;;) { d; inblock = ordinary; - if (!ordinary || !option.funcscope) scope = Object.create(scope); + + if (!ordinary || !option.funcscope) + scope = Object.create(scope); + nonadjacent(token, nexttoken); t = nexttoken; - if (nexttoken.id === '{') { - advance('{'); + var metrics = funct["(metrics)"]; + metrics.nestedBlockDepth += 1; + metrics.verifyMaxNestedBlockDepthPerFunction(); + + if (nexttoken.id === "{") { + advance("{"); line = token.line; - if (nexttoken.id !== '}') { + if (nexttoken.id !== "}") { indent += option.indent; while (!ordinary && nexttoken.from > indent) { indent += option.indent; @@ -2537,7 +2830,7 @@ loop: for (;;) { } directives(); - if (option.strict && funct['(context)']['(global)']) { + if (option.strict && funct["(context)"]["(global)"]) { if (!m["use strict"] && !directive["use strict"]) { warning("Missing \"use strict\" statement."); } @@ -2546,6 +2839,8 @@ loop: for (;;) { a = statements(line); + metrics.statementCount += a.length; + if (isfunc) { directive = m; } @@ -2557,15 +2852,15 @@ loop: for (;;) { } else if (line !== nexttoken.line) { indentation(); } - advance('}', t); + advance("}", t); indent = old_indent; } else if (!ordinary) { error("Expected '{a}' and instead saw '{b}'.", - nexttoken, '{', nexttoken.value); + nexttoken, "{", nexttoken.value); } else { if (!stmt || option.curly) warning("Expected '{a}' and instead saw '{b}'.", - nexttoken, '{', nexttoken.value); + nexttoken, "{", nexttoken.value); noreach = true; indent += option.indent; @@ -2574,21 +2869,22 @@ loop: for (;;) { indent -= option.indent; noreach = false; } - funct['(verb)'] = null; + funct["(verb)"] = null; if (!ordinary || !option.funcscope) scope = s; inblock = b; if (ordinary && option.noempty && (!a || a.length === 0)) { warning("Empty block."); } + metrics.nestedBlockDepth -= 1; return a; } function countMember(m) { - if (membersOnly && typeof membersOnly[m] !== 'boolean') { + if (membersOnly && typeof membersOnly[m] !== "boolean") { warning("Unexpected /*member '{a}'.", token, m); } - if (typeof member[m] === 'number') { + if (typeof member[m] === "number") { member[m] += 1; } else { member[m] = 1; @@ -2598,7 +2894,7 @@ loop: for (;;) { function note_implied(token) { var name = token.value, line = token.line, a = implied[name]; - if (typeof a === 'function') { + if (typeof a === "function") { a = false; } @@ -2613,16 +2909,16 @@ loop: for (;;) { // Build the syntax table by declaring the syntactic elements of the language. - type('(number)', function () { + type("(number)", function () { return this; }); - type('(string)', function () { + type("(string)", function () { return this; }); - syntax['(identifier)'] = { - type: '(identifier)', + syntax["(identifier)"] = { + type: "(identifier)", lbp: 0, identifier: true, nud: function () { @@ -2630,13 +2926,13 @@ loop: for (;;) { s = scope[v], f; - if (typeof s === 'function') { + if (typeof s === "function") { // Protection against accidental inheritance. s = undefined; - } else if (typeof s === 'boolean') { + } else if (typeof s === "boolean") { f = funct; funct = functions[0]; - addlabel(v, 'var'); + addlabel(v, "var"); s = funct; funct = f; } @@ -2645,21 +2941,21 @@ loop: for (;;) { if (funct === s) { // Change 'unused' to 'var', and reject labels. switch (funct[v]) { - case 'unused': - funct[v] = 'var'; + case "unused": + funct[v] = "var"; break; - case 'unction': - funct[v] = 'function'; - this['function'] = true; + case "unction": + funct[v] = "function"; + this["function"] = true; break; - case 'function': - this['function'] = true; + case "function": + this["function"] = true; break; - case 'label': + case "label": warning("'{a}' is a statement label.", token, v); break; } - } else if (funct['(global)']) { + } else if (funct["(global)"]) { // The name is not defined in the function. If we are in the global // scope, then we have an undefined variable. // @@ -2667,32 +2963,33 @@ loop: for (;;) { // the base object of a reference is null so no need to display warning // if we're inside of typeof or delete. - if (option.undef && typeof predefined[v] !== 'boolean') { + if (option.undef && typeof predefined[v] !== "boolean") { // Attempting to subscript a null reference will throw an // error, even within the typeof and delete operators - if (!(anonname === 'typeof' || anonname === 'delete') || - (nexttoken && (nexttoken.value === '.' || nexttoken.value === '['))) { + if (!(anonname === "typeof" || anonname === "delete") || + (nexttoken && (nexttoken.value === "." || nexttoken.value === "["))) { isundef(funct, "'{a}' is not defined.", token, v); } } + note_implied(token); } else { // If the name is already defined in the current // function, but not as outer, then there is a scope error. switch (funct[v]) { - case 'closure': - case 'function': - case 'var': - case 'unused': + case "closure": + case "function": + case "var": + case "unused": warning("'{a}' used out of scope.", token, v); break; - case 'label': + case "label": warning("'{a}' is a statement label.", token, v); break; - case 'outer': - case 'global': + case "outer": + case "global": break; default: // If the name is defined in an outer function, make an outer entry, @@ -2702,16 +2999,16 @@ loop: for (;;) { } else if (s === null) { warning("'{a}' is not allowed.", token, v); note_implied(token); - } else if (typeof s !== 'object') { + } else if (typeof s !== "object") { // Operators typeof and delete do not raise runtime errors even // if the base object of a reference is null so no need to // display warning if we're inside of typeof or delete. if (option.undef) { // Attempting to subscript a null reference will throw an // error, even within the typeof and delete operators - if (!(anonname === 'typeof' || anonname === 'delete') || + if (!(anonname === "typeof" || anonname === "delete") || (nexttoken && - (nexttoken.value === '.' || nexttoken.value === '['))) { + (nexttoken.value === "." || nexttoken.value === "["))) { isundef(funct, "'{a}' is not defined.", token, v); } @@ -2720,22 +3017,21 @@ loop: for (;;) { note_implied(token); } else { switch (s[v]) { - case 'function': - case 'unction': - this['function'] = true; - s[v] = 'closure'; - funct[v] = s['(global)'] ? 'global' : 'outer'; + case "function": + case "unction": + this["function"] = true; + s[v] = "closure"; + funct[v] = s["(global)"] ? "global" : "outer"; break; - case 'var': - case 'unused': - s[v] = 'closure'; - funct[v] = s['(global)'] ? 'global' : 'outer'; + case "var": + case "unused": + s[v] = "closure"; + funct[v] = s["(global)"] ? "global" : "outer"; break; - case 'closure': - case 'parameter': - funct[v] = s['(global)'] ? 'global' : 'outer'; + case "closure": + funct[v] = s["(global)"] ? "global" : "outer"; break; - case 'label': + case "label": warning("'{a}' is a statement label.", token, v); } } @@ -2749,123 +3045,122 @@ loop: for (;;) { } }; - type('(regexp)', function () { + type("(regexp)", function () { return this; }); // ECMAScript parser - delim('(endline)'); - delim('(begin)'); - delim('(end)').reach = true; - delim(''); - delim('(error)').reach = true; - delim('}').reach = true; - delim(')'); - delim(']'); - delim('"').reach = true; + delim("(endline)"); + delim("(begin)"); + delim("(end)").reach = true; + delim(""); + delim("(error)").reach = true; + delim("}").reach = true; + delim(")"); + delim("]"); + delim("\"").reach = true; delim("'").reach = true; - delim(';'); - delim(':').reach = true; - delim(','); - delim('#'); - delim('@'); - reserve('else'); - reserve('case').reach = true; - reserve('catch'); - reserve('default').reach = true; - reserve('finally'); - reservevar('arguments', function (x) { - if (directive['use strict'] && funct['(global)']) { + delim(";"); + delim(":").reach = true; + delim(","); + delim("#"); + delim("@"); + reserve("else"); + reserve("case").reach = true; + reserve("catch"); + reserve("default").reach = true; + reserve("finally"); + reservevar("arguments", function (x) { + if (directive["use strict"] && funct["(global)"]) { warning("Strict violation.", x); } }); - reservevar('eval'); - reservevar('false'); - reservevar('Infinity'); - reservevar('NaN'); - reservevar('null'); - reservevar('this', function (x) { - if (directive['use strict'] && !option.validthis && ((funct['(statement)'] && - funct['(name)'].charAt(0) > 'Z') || funct['(global)'])) { + reservevar("eval"); + reservevar("false"); + reservevar("Infinity"); + reservevar("null"); + reservevar("this", function (x) { + if (directive["use strict"] && !option.validthis && ((funct["(statement)"] && + funct["(name)"].charAt(0) > "Z") || funct["(global)"])) { warning("Possible strict violation.", x); } }); - reservevar('true'); - reservevar('undefined'); - assignop('=', 'assign', 20); - assignop('+=', 'assignadd', 20); - assignop('-=', 'assignsub', 20); - assignop('*=', 'assignmult', 20); - assignop('/=', 'assigndiv', 20).nud = function () { + reservevar("true"); + reservevar("undefined"); + assignop("=", "assign", 20); + assignop("+=", "assignadd", 20); + assignop("-=", "assignsub", 20); + assignop("*=", "assignmult", 20); + assignop("/=", "assigndiv", 20).nud = function () { error("A regular expression literal can be confused with '/='."); }; - assignop('%=', 'assignmod', 20); - bitwiseassignop('&=', 'assignbitand', 20); - bitwiseassignop('|=', 'assignbitor', 20); - bitwiseassignop('^=', 'assignbitxor', 20); - bitwiseassignop('<<=', 'assignshiftleft', 20); - bitwiseassignop('>>=', 'assignshiftright', 20); - bitwiseassignop('>>>=', 'assignshiftrightunsigned', 20); - infix('?', function (left, that) { + assignop("%=", "assignmod", 20); + bitwiseassignop("&=", "assignbitand", 20); + bitwiseassignop("|=", "assignbitor", 20); + bitwiseassignop("^=", "assignbitxor", 20); + bitwiseassignop("<<=", "assignshiftleft", 20); + bitwiseassignop(">>=", "assignshiftright", 20); + bitwiseassignop(">>>=", "assignshiftrightunsigned", 20); + infix("?", function (left, that) { that.left = left; that.right = expression(10); - advance(':'); - that['else'] = expression(10); + advance(":"); + that["else"] = expression(10); return that; }, 30); - infix('||', 'or', 40); - infix('&&', 'and', 50); - bitwise('|', 'bitor', 70); - bitwise('^', 'bitxor', 80); - bitwise('&', 'bitand', 90); - relation('==', function (left, right) { - var eqnull = option.eqnull && (left.value === 'null' || right.value === 'null'); + infix("||", "or", 40); + infix("&&", "and", 50); + bitwise("|", "bitor", 70); + bitwise("^", "bitxor", 80); + bitwise("&", "bitand", 90); + relation("==", function (left, right) { + var eqnull = option.eqnull && (left.value === "null" || right.value === "null"); if (!eqnull && option.eqeqeq) - warning("Expected '{a}' and instead saw '{b}'.", this, '===', '=='); + warning("Expected '{a}' and instead saw '{b}'.", this, "===", "=="); else if (isPoorRelation(left)) - warning("Use '{a}' to compare with '{b}'.", this, '===', left.value); + warning("Use '{a}' to compare with '{b}'.", this, "===", left.value); else if (isPoorRelation(right)) - warning("Use '{a}' to compare with '{b}'.", this, '===', right.value); + warning("Use '{a}' to compare with '{b}'.", this, "===", right.value); return this; }); - relation('==='); - relation('!=', function (left, right) { + relation("==="); + relation("!=", function (left, right) { var eqnull = option.eqnull && - (left.value === 'null' || right.value === 'null'); + (left.value === "null" || right.value === "null"); if (!eqnull && option.eqeqeq) { warning("Expected '{a}' and instead saw '{b}'.", - this, '!==', '!='); + this, "!==", "!="); } else if (isPoorRelation(left)) { warning("Use '{a}' to compare with '{b}'.", - this, '!==', left.value); + this, "!==", left.value); } else if (isPoorRelation(right)) { warning("Use '{a}' to compare with '{b}'.", - this, '!==', right.value); + this, "!==", right.value); } return this; }); - relation('!=='); - relation('<'); - relation('>'); - relation('<='); - relation('>='); - bitwise('<<', 'shiftleft', 120); - bitwise('>>', 'shiftright', 120); - bitwise('>>>', 'shiftrightunsigned', 120); - infix('in', 'in', 120); - infix('instanceof', 'instanceof', 120); - infix('+', function (left, that) { + relation("!=="); + relation("<"); + relation(">"); + relation("<="); + relation(">="); + bitwise("<<", "shiftleft", 120); + bitwise(">>", "shiftright", 120); + bitwise(">>>", "shiftrightunsigned", 120); + infix("in", "in", 120); + infix("instanceof", "instanceof", 120); + infix("+", function (left, that) { var right = expression(130); - if (left && right && left.id === '(string)' && right.id === '(string)') { + if (left && right && left.id === "(string)" && right.id === "(string)") { left.value += right.value; left.character = right.character; if (!option.scripturl && jx.test(left.value)) { @@ -2877,105 +3172,102 @@ loop: for (;;) { that.right = right; return that; }, 130); - prefix('+', 'num'); - prefix('+++', function () { + prefix("+", "num"); + prefix("+++", function () { warning("Confusing pluses."); this.right = expression(150); - this.arity = 'unary'; + this.arity = "unary"; return this; }); - infix('+++', function (left) { + infix("+++", function (left) { warning("Confusing pluses."); this.left = left; this.right = expression(130); return this; }, 130); - infix('-', 'sub', 130); - prefix('-', 'neg'); - prefix('---', function () { + infix("-", "sub", 130); + prefix("-", "neg"); + prefix("---", function () { warning("Confusing minuses."); this.right = expression(150); - this.arity = 'unary'; + this.arity = "unary"; return this; }); - infix('---', function (left) { + infix("---", function (left) { warning("Confusing minuses."); this.left = left; this.right = expression(130); return this; }, 130); - infix('*', 'mult', 140); - infix('/', 'div', 140); - infix('%', 'mod', 140); + infix("*", "mult", 140); + infix("/", "div", 140); + infix("%", "mod", 140); - suffix('++', 'postinc'); - prefix('++', 'preinc'); - syntax['++'].exps = true; + suffix("++", "postinc"); + prefix("++", "preinc"); + syntax["++"].exps = true; - suffix('--', 'postdec'); - prefix('--', 'predec'); - syntax['--'].exps = true; - prefix('delete', function () { + suffix("--", "postdec"); + prefix("--", "predec"); + syntax["--"].exps = true; + prefix("delete", function () { var p = expression(0); - if (!p || (p.id !== '.' && p.id !== '[')) { + if (!p || (p.id !== "." && p.id !== "[")) { warning("Variables should not be deleted."); } this.first = p; return this; }).exps = true; - prefix('~', function () { + prefix("~", function () { if (option.bitwise) { - warning("Unexpected '{a}'.", this, '~'); + warning("Unexpected '{a}'.", this, "~"); } expression(150); return this; }); - prefix('!', function () { + prefix("!", function () { this.right = expression(150); - this.arity = 'unary'; + this.arity = "unary"; if (bang[this.right.id] === true) { - warning("Confusing use of '{a}'.", this, '!'); + warning("Confusing use of '{a}'.", this, "!"); } return this; }); - prefix('typeof', 'typeof'); - prefix('new', function () { + prefix("typeof", "typeof"); + prefix("new", function () { var c = expression(155), i; - if (c && c.id !== 'function') { + if (c && c.id !== "function") { if (c.identifier) { - c['new'] = true; + c["new"] = true; switch (c.value) { - case 'Object': - warning("Use the object literal notation {}.", token); + case "Number": + case "String": + case "Boolean": + case "Math": + case "JSON": + warning("Do not use {a} as a constructor.", prevtoken, c.value); break; - case 'Number': - case 'String': - case 'Boolean': - case 'Math': - case 'JSON': - warning("Do not use {a} as a constructor.", token, c.value); - break; - case 'Function': + case "Function": if (!option.evil) { warning("The Function constructor is eval."); } break; - case 'Date': - case 'RegExp': + case "Date": + case "RegExp": break; default: - if (c.id !== 'function') { + if (c.id !== "function") { i = c.value.substr(0, 1); - if (option.newcap && (i < 'A' || i > 'Z')) { + if (option.newcap && (i < "A" || i > "Z") && !is_own(global, c.value)) { warning("A constructor name should start with an uppercase letter.", token); } } } } else { - if (c.id !== '.' && c.id !== '[' && c.id !== '(') { + if (c.id !== "." && c.id !== "[" && c.id !== "(") { warning("Bad constructor.", token); } } @@ -2984,46 +3276,47 @@ loop: for (;;) { warning("Weird construction. Delete 'new'.", this); } adjacent(token, nexttoken); - if (nexttoken.id !== '(' && !option.supernew) { - warning("Missing '()' invoking a constructor."); + if (nexttoken.id !== "(" && !option.supernew) { + warning("Missing '()' invoking a constructor.", + token, token.value); } this.first = c; return this; }); - syntax['new'].exps = true; + syntax["new"].exps = true; - prefix('void').exps = true; + prefix("void").exps = true; - infix('.', function (left, that) { + infix(".", function (left, that) { adjacent(prevtoken, token); nobreak(); var m = identifier(); - if (typeof m === 'string') { + if (typeof m === "string") { countMember(m); } that.left = left; that.right = m; - if (left && left.value === 'arguments' && (m === 'callee' || m === 'caller')) { + if (left && left.value === "arguments" && (m === "callee" || m === "caller")) { if (option.noarg) warning("Avoid arguments.{a}.", left, m); - else if (directive['use strict']) - error('Strict violation.'); - } else if (!option.evil && left && left.value === 'document' && - (m === 'write' || m === 'writeln')) { + else if (directive["use strict"]) + error("Strict violation."); + } else if (!option.evil && left && left.value === "document" && + (m === "write" || m === "writeln")) { warning("document.write can be a form of eval.", left); } - if (!option.evil && (m === 'eval' || m === 'execScript')) { - warning('eval is evil.'); + if (!option.evil && (m === "eval" || m === "execScript")) { + warning("eval is evil."); } return that; }, 160, true); - infix('(', function (left, that) { - if (prevtoken.id !== '}' && prevtoken.id !== ')') { + infix("(", function (left, that) { + if (prevtoken.id !== "}" && prevtoken.id !== ")") { nobreak(prevtoken, token); } nospace(); - if (option.immed && !left.immed && left.id === 'function') { + if (option.immed && !left.immed && left.id === "function") { warning("Wrap an immediate function invocation in parentheses " + "to assist the reader in understanding that the expression " + "is the result of a function, and not the function itself."); @@ -3031,51 +3324,63 @@ loop: for (;;) { var n = 0, p = []; if (left) { - if (left.type === '(identifier)') { + if (left.type === "(identifier)") { if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) { - if (left.value !== 'Number' && left.value !== 'String' && - left.value !== 'Boolean' && - left.value !== 'Date') { - if (left.value === 'Math') { + if ("Number String Boolean Date Object".indexOf(left.value) === -1) { + if (left.value === "Math") { warning("Math is not a function.", left); } else if (option.newcap) { - warning( -"Missing 'new' prefix when invoking a constructor.", left); + warning("Missing 'new' prefix when invoking a constructor.", left); } } } } } - if (nexttoken.id !== ')') { + if (nexttoken.id !== ")") { for (;;) { p[p.length] = expression(10); n += 1; - if (nexttoken.id !== ',') { + if (nexttoken.id !== ",") { break; } comma(); } } - advance(')'); + advance(")"); nospace(prevtoken, token); - if (typeof left === 'object') { - if (left.value === 'parseInt' && n === 1) { - warning("Missing radix parameter.", left); + if (typeof left === "object") { + if (left.value === "parseInt" && n === 1) { + warning("Missing radix parameter.", token); } if (!option.evil) { - if (left.value === 'eval' || left.value === 'Function' || - left.value === 'execScript') { + if (left.value === "eval" || left.value === "Function" || + left.value === "execScript") { warning("eval is evil.", left); - } else if (p[0] && p[0].id === '(string)' && - (left.value === 'setTimeout' || - left.value === 'setInterval')) { + + if (p[0] && [0].id === "(string)") { + addInternalSrc(left, p[0].value); + } + } else if (p[0] && p[0].id === "(string)" && + (left.value === "setTimeout" || + left.value === "setInterval")) { warning( "Implied eval is evil. Pass a function instead of a string.", left); + addInternalSrc(left, p[0].value); + + // window.setTimeout/setInterval + } else if (p[0] && p[0].id === "(string)" && + left.value === "." && + left.left.value === "window" && + (left.right === "setTimeout" || + left.right === "setInterval")) { + warning( + "Implied eval is evil. Pass a function instead of a string.", left); + addInternalSrc(left, p[0].value); } } - if (!left.identifier && left.id !== '.' && left.id !== '[' && - left.id !== '(' && left.id !== '&&' && left.id !== '||' && - left.id !== '?') { + if (!left.identifier && left.id !== "." && left.id !== "[" && + left.id !== "(" && left.id !== "&&" && left.id !== "||" && + left.id !== "?") { warning("Bad invocation.", left); } } @@ -3083,34 +3388,32 @@ loop: for (;;) { return that; }, 155, true).exps = true; - prefix('(', function () { + prefix("(", function () { nospace(); - if (nexttoken.id === 'function') { + if (nexttoken.id === "function") { nexttoken.immed = true; } var v = expression(0); - advance(')', this); + advance(")", this); nospace(prevtoken, token); - if (option.immed && v.id === 'function') { - if (nexttoken.id === '(' || - (nexttoken.id === '.' && (peek().value === 'call' || peek().value === 'apply'))) { - warning( -"Move the invocation into the parens that contain the function.", nexttoken); - } else { + if (option.immed && v.id === "function") { + if (nexttoken.id !== "(" && + (nexttoken.id !== "." || (peek().value !== "call" && peek().value !== "apply"))) { warning( "Do not wrap function literals in parens unless they are to be immediately invoked.", this); } } + return v; }); - infix('[', function (left, that) { + infix("[", function (left, that) { nobreak(prevtoken, token); nospace(); var e = expression(0), s; - if (e && e.type === '(string)') { - if (!option.evil && (e.value === 'eval' || e.value === 'execScript')) { + if (e && e.type === "(string)") { + if (!option.evil && (e.value === "eval" || e.value === "execScript")) { warning("eval is evil.", that); } countMember(e.value); @@ -3118,18 +3421,18 @@ loop: for (;;) { s = syntax[e.value]; if (!s || !s.reserved) { warning("['{a}'] is better written in dot notation.", - e, e.value); + prevtoken, e.value); } } } - advance(']', that); + advance("]", that); nospace(prevtoken, token); that.left = left; that.right = e; return that; }, 160, true); - prefix('[', function () { + prefix("[", function () { var b = token.line !== nexttoken.line; this.first = []; if (b) { @@ -3138,21 +3441,22 @@ loop: for (;;) { indent += option.indent; } } - while (nexttoken.id !== '(end)') { - while (nexttoken.id === ',') { - warning("Extra comma."); - advance(','); + while (nexttoken.id !== "(end)") { + while (nexttoken.id === ",") { + if (!option.es5) + warning("Extra comma."); + advance(","); } - if (nexttoken.id === ']') { + if (nexttoken.id === "]") { break; } if (b && token.line !== nexttoken.line) { indentation(); } this.first.push(expression(10)); - if (nexttoken.id === ',') { + if (nexttoken.id === ",") { comma(); - if (nexttoken.id === ']' && !option.es5) { + if (nexttoken.id === "]" && !option.es5) { warning("Extra comma.", token); break; } @@ -3164,7 +3468,7 @@ loop: for (;;) { indent -= option.indent; indentation(); } - advance(']', this); + advance("]", this); return this; }, 160); @@ -3172,10 +3476,10 @@ loop: for (;;) { function property_name() { var id = optionalidentifier(true); if (!id) { - if (nexttoken.id === '(string)') { + if (nexttoken.id === "(string)") { id = nexttoken.value; advance(); - } else if (nexttoken.id === '(number)') { + } else if (nexttoken.id === "(number)") { id = nexttoken.value.toString(); advance(); } @@ -3185,65 +3489,130 @@ loop: for (;;) { function functionparams() { - var i, t = nexttoken, p = []; - advance('('); + var next = nexttoken; + var params = []; + var ident; + + advance("("); nospace(); - if (nexttoken.id === ')') { - advance(')'); + + if (nexttoken.id === ")") { + advance(")"); return; } + for (;;) { - i = identifier(true); - p.push(i); - addlabel(i, 'parameter'); - if (nexttoken.id === ',') { + ident = identifier(true); + params.push(ident); + addlabel(ident, "unused", token); + if (nexttoken.id === ",") { comma(); } else { - advance(')', t); + advance(")", next); nospace(prevtoken, token); - return p; + return params; } } } - function doFunction(i, statement) { - var f, - oldOption = option, - oldScope = scope; + function doFunction(name, statement) { + var f; + var oldOption = option; + var oldScope = scope; option = Object.create(option); - scope = Object.create(scope); + scope = Object.create(scope); funct = { - '(name)' : i || '"' + anonname + '"', - '(line)' : nexttoken.line, - '(context)' : funct, - '(breakage)' : 0, - '(loopage)' : 0, - '(scope)' : scope, - '(statement)': statement + "(name)" : name || "\"" + anonname + "\"", + "(line)" : nexttoken.line, + "(character)": nexttoken.character, + "(context)" : funct, + "(breakage)" : 0, + "(loopage)" : 0, + "(metrics)" : createMetrics(nexttoken), + "(scope)" : scope, + "(statement)": statement, + "(tokens)" : {} }; + f = funct; token.funct = funct; + functions.push(funct); - if (i) { - addlabel(i, 'function'); + + if (name) { + addlabel(name, "function"); } - funct['(params)'] = functionparams(); + + funct["(params)"] = functionparams(); + funct["(metrics)"].verifyMaxParametersPerFunction(funct["(params)"]); block(false, false, true); + + funct["(metrics)"].verifyMaxStatementsPerFunction(); + funct["(metrics)"].verifyMaxComplexityPerFunction(); + scope = oldScope; option = oldOption; - funct['(last)'] = token.line; - funct = funct['(context)']; + funct["(last)"] = token.line; + funct["(lastcharacter)"] = token.character; + funct = funct["(context)"]; + return f; } + function createMetrics(functionStartToken) { + return { + statementCount: 0, + nestedBlockDepth: -1, + ComplexityCount: 1, + verifyMaxStatementsPerFunction: function () { + if (option.maxstatements && + this.statementCount > option.maxstatements) { + var message = "Too many statements per function (" + this.statementCount + ")."; + warning(message, functionStartToken); + } + }, + + verifyMaxParametersPerFunction: function (params) { + params = params || []; + + if (option.maxparams && params.length > option.maxparams) { + var message = "Too many parameters per function (" + params.length + ")."; + warning(message, functionStartToken); + } + }, + + verifyMaxNestedBlockDepthPerFunction: function () { + if (option.maxdepth && + this.nestedBlockDepth > 0 && + this.nestedBlockDepth === option.maxdepth + 1) { + var message = "Blocks are nested too deeply (" + this.nestedBlockDepth + ")."; + warning(message); + } + }, + + verifyMaxComplexityPerFunction: function () { + var max = option.maxcomplexity; + var cc = this.ComplexityCount; + if (max && cc > max) { + var message = "Cyclomatic complexity is too high per function (" + cc + ")."; + warning(message, functionStartToken); + } + } + }; + } + + function increaseComplexityCount() { + funct["(metrics)"].ComplexityCount += 1; + } + (function (x) { x.nud = function () { - var b, f, i, j, p, t; + var b, f, i, p, t; var props = {}; // All properties, including accessors function saveProperty(name, token) { @@ -3288,14 +3657,14 @@ loop: for (;;) { } } for (;;) { - if (nexttoken.id === '}') { + if (nexttoken.id === "}") { break; } if (b) { indentation(); } - if (nexttoken.value === 'get' && peek().id !== ':') { - advance('get'); + if (nexttoken.value === "get" && peek().id !== ":") { + advance("get"); if (!option.es5) { error("get/set are ES5 features."); } @@ -3307,13 +3676,13 @@ loop: for (;;) { t = nexttoken; adjacent(token, nexttoken); f = doFunction(); - p = f['(params)']; + p = f["(params)"]; if (p) { warning("Unexpected parameter '{a}' in get {b} function.", t, p[0], i); } adjacent(token, nexttoken); - } else if (nexttoken.value === 'set' && peek().id !== ':') { - advance('set'); + } else if (nexttoken.value === "set" && peek().id !== ":") { + advance("set"); if (!option.es5) { error("get/set are ES5 features."); } @@ -3325,27 +3694,27 @@ loop: for (;;) { t = nexttoken; adjacent(token, nexttoken); f = doFunction(); - p = f['(params)']; + p = f["(params)"]; if (!p || p.length !== 1) { warning("Expected a single parameter in set {a} function.", t, i); } } else { i = property_name(); saveProperty(i, nexttoken); - if (typeof i !== 'string') { + if (typeof i !== "string") { break; } - advance(':'); + advance(":"); nonadjacent(token, nexttoken); expression(10); } countMember(i); - if (nexttoken.id === ',') { + if (nexttoken.id === ",") { comma(); - if (nexttoken.id === ',') { + if (nexttoken.id === ",") { warning("Extra comma.", token); - } else if (nexttoken.id === '}' && !option.es5) { + } else if (nexttoken.id === "}" && !option.es5) { warning("Extra comma.", token); } } else { @@ -3356,7 +3725,7 @@ loop: for (;;) { indent -= option.indent; indentation(); } - advance('}', this); + advance("}", this); // Check for lonely setters if in the ES5 mode. if (option.es5) { @@ -3371,13 +3740,13 @@ loop: for (;;) { x.fud = function () { error("Expected to see a statement and instead saw a block.", token); }; - }(delim('{'))); + }(delim("{"))); // This Function is called when esnext option is set to true // it adds the `const` statement to JSHINT useESNextSyntax = function () { - var conststatement = stmt('const', function (prefix) { + var conststatement = stmt("const", function (prefix) { var id, name, value; this.first = []; @@ -3387,10 +3756,10 @@ loop: for (;;) { if (funct[id] === "const") { warning("const '" + id + "' has already been declared"); } - if (funct['(global)'] && predefined[id] === false) { + if (funct["(global)"] && predefined[id] === false) { warning("Redefinition of '{a}'.", token, id); } - addlabel(id, 'const'); + addlabel(id, "const"); if (prefix) { break; } @@ -3402,15 +3771,15 @@ loop: for (;;) { "'{a}' is initialized to 'undefined'.", token, id); } - if (nexttoken.id === '=') { + if (nexttoken.id === "=") { nonadjacent(token, nexttoken); - advance('='); + advance("="); nonadjacent(token, nexttoken); - if (nexttoken.id === 'undefined') { + if (nexttoken.id === "undefined") { warning("It is not necessary to initialize " + "'{a}' to 'undefined'.", token, id); } - if (peek(0).id === '=' && nexttoken.identifier) { + if (peek(0).id === "=" && nexttoken.identifier) { error("Constant {a} was not declared correctly.", nexttoken, nexttoken.value); } @@ -3418,7 +3787,7 @@ loop: for (;;) { name.first = value; } - if (nexttoken.id !== ',') { + if (nexttoken.id !== ",") { break; } comma(); @@ -3428,47 +3797,55 @@ loop: for (;;) { conststatement.exps = true; }; - var varstatement = stmt('var', function (prefix) { + var varstatement = stmt("var", function (prefix) { // JavaScript does not have block scope. It only has function scope. So, // declaring a variable in a block can have unexpected consequences. var id, name, value; - if (funct['(onevar)'] && option.onevar) { + if (funct["(onevar)"] && option.onevar) { warning("Too many var statements."); - } else if (!funct['(global)']) { - funct['(onevar)'] = true; + } else if (!funct["(global)"]) { + funct["(onevar)"] = true; } + this.first = []; + for (;;) { nonadjacent(token, nexttoken); id = identifier(); + if (option.esnext && funct[id] === "const") { warning("const '" + id + "' has already been declared"); } - if (funct['(global)'] && predefined[id] === false) { + + if (funct["(global)"] && predefined[id] === false) { warning("Redefinition of '{a}'.", token, id); } - addlabel(id, 'unused'); + + addlabel(id, "unused", token); + if (prefix) { break; } + name = token; this.first.push(token); - if (nexttoken.id === '=') { + + if (nexttoken.id === "=") { nonadjacent(token, nexttoken); - advance('='); + advance("="); nonadjacent(token, nexttoken); - if (nexttoken.id === 'undefined') { + if (nexttoken.id === "undefined") { warning("It is not necessary to initialize '{a}' to 'undefined'.", token, id); } - if (peek(0).id === '=' && nexttoken.identifier) { + if (peek(0).id === "=" && nexttoken.identifier) { error("Variable {a} was not declared correctly.", nexttoken, nexttoken.value); } value = expression(0); name.first = value; } - if (nexttoken.id !== ',') { + if (nexttoken.id !== ",") { break; } comma(); @@ -3477,7 +3854,7 @@ loop: for (;;) { }); varstatement.exps = true; - blockstmt('function', function () { + blockstmt("function", function () { if (inblock) { warning("Function declarations should not be placed in blocks. " + "Use a function expression or move the statement to the top of " + @@ -3489,16 +3866,17 @@ loop: for (;;) { warning("const '" + i + "' has already been declared"); } adjacent(token, nexttoken); - addlabel(i, 'unction'); - doFunction(i, true); - if (nexttoken.id === '(' && nexttoken.line === token.line) { + addlabel(i, "unction", token); + + doFunction(i, { statement: true }); + if (nexttoken.id === "(" && nexttoken.line === token.line) { error( "Function declarations are not invocable. Wrap the whole function invocation in parens."); } return this; }); - prefix('function', function () { + prefix("function", function () { var i = optionalidentifier(); if (i) { adjacent(token, nexttoken); @@ -3506,31 +3884,32 @@ loop: for (;;) { nonadjacent(token, nexttoken); } doFunction(i); - if (!option.loopfunc && funct['(loopage)']) { + if (!option.loopfunc && funct["(loopage)"]) { warning("Don't make functions within a loop."); } return this; }); - blockstmt('if', function () { + blockstmt("if", function () { var t = nexttoken; - advance('('); + increaseComplexityCount(); + advance("("); nonadjacent(this, t); nospace(); expression(20); - if (nexttoken.id === '=') { + if (nexttoken.id === "=") { if (!option.boss) warning("Expected a conditional expression and instead saw an assignment."); - advance('='); + advance("="); expression(20); } - advance(')', t); + advance(")", t); nospace(prevtoken, token); block(true, true); - if (nexttoken.id === 'else') { + if (nexttoken.id === "else") { nonadjacent(token, nexttoken); - advance('else'); - if (nexttoken.id === 'if' || nexttoken.id === 'switch') { + advance("else"); + if (nexttoken.id === "if" || nexttoken.id === "switch") { statement(true); } else { block(true, true); @@ -3539,90 +3918,146 @@ loop: for (;;) { return this; }); - blockstmt('try', function () { - var b, e, s; + blockstmt("try", function () { + var b; + + function doCatch() { + var oldScope = scope; + var e; + + advance("catch"); + nonadjacent(token, nexttoken); + advance("("); + + scope = Object.create(oldScope); + + e = nexttoken.value; + if (nexttoken.type !== "(identifier)") { + e = null; + warning("Expected an identifier and instead saw '{a}'.", nexttoken, e); + } + + advance(); + advance(")"); + + funct = { + "(name)" : "(catch)", + "(line)" : nexttoken.line, + "(character)": nexttoken.character, + "(context)" : funct, + "(breakage)" : funct["(breakage)"], + "(loopage)" : funct["(loopage)"], + "(scope)" : scope, + "(statement)": false, + "(metrics)" : createMetrics(nexttoken), + "(catch)" : true, + "(tokens)" : {} + }; + + if (e) { + addlabel(e, "exception"); + } + + token.funct = funct; + functions.push(funct); + + block(false); + + scope = oldScope; + + funct["(last)"] = token.line; + funct["(lastcharacter)"] = token.character; + funct = funct["(context)"]; + } block(false); - if (nexttoken.id === 'catch') { - advance('catch'); - nonadjacent(token, nexttoken); - advance('('); - s = scope; - scope = Object.create(s); - e = nexttoken.value; - if (nexttoken.type !== '(identifier)') { - warning("Expected an identifier and instead saw '{a}'.", - nexttoken, e); - } else { - addlabel(e, 'exception'); - } - advance(); - advance(')'); - block(false); + + if (nexttoken.id === "catch") { + increaseComplexityCount(); + doCatch(); b = true; - scope = s; } - if (nexttoken.id === 'finally') { - advance('finally'); + + if (nexttoken.id === "finally") { + advance("finally"); block(false); return; } else if (!b) { error("Expected '{a}' and instead saw '{b}'.", - nexttoken, 'catch', nexttoken.value); + nexttoken, "catch", nexttoken.value); } + return this; }); - blockstmt('while', function () { + blockstmt("while", function () { var t = nexttoken; - funct['(breakage)'] += 1; - funct['(loopage)'] += 1; - advance('('); + funct["(breakage)"] += 1; + funct["(loopage)"] += 1; + increaseComplexityCount(); + advance("("); nonadjacent(this, t); nospace(); expression(20); - if (nexttoken.id === '=') { + if (nexttoken.id === "=") { if (!option.boss) warning("Expected a conditional expression and instead saw an assignment."); - advance('='); + advance("="); expression(20); } - advance(')', t); + advance(")", t); nospace(prevtoken, token); block(true, true); - funct['(breakage)'] -= 1; - funct['(loopage)'] -= 1; + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; return this; }).labelled = true; - reserve('with'); + blockstmt("with", function () { + var t = nexttoken; + if (directive["use strict"]) { + error("'with' is not allowed in strict mode.", token); + } else if (!option.withstmt) { + warning("Don't use 'with'.", token); + } - blockstmt('switch', function () { + advance("("); + nonadjacent(this, t); + nospace(); + expression(0); + advance(")", t); + nospace(prevtoken, token); + block(true, true); + + return this; + }); + + blockstmt("switch", function () { var t = nexttoken, g = false; - funct['(breakage)'] += 1; - advance('('); + funct["(breakage)"] += 1; + advance("("); nonadjacent(this, t); nospace(); this.condition = expression(20); - advance(')', t); + advance(")", t); nospace(prevtoken, token); nonadjacent(token, nexttoken); t = nexttoken; - advance('{'); + advance("{"); nonadjacent(token, nexttoken); indent += option.indent; this.cases = []; for (;;) { switch (nexttoken.id) { - case 'case': - switch (funct['(verb)']) { - case 'break': - case 'case': - case 'continue': - case 'return': - case 'switch': - case 'throw': + case "case": + switch (funct["(verb)"]) { + case "break": + case "case": + case "continue": + case "return": + case "switch": + case "throw": break; default: // You can tell JSHint that you don't use break intentionally by @@ -3635,18 +4070,19 @@ loop: for (;;) { } } indentation(-option.indent); - advance('case'); + advance("case"); this.cases.push(expression(20)); + increaseComplexityCount(); g = true; - advance(':'); - funct['(verb)'] = 'case'; + advance(":"); + funct["(verb)"] = "case"; break; - case 'default': - switch (funct['(verb)']) { - case 'break': - case 'continue': - case 'return': - case 'throw': + case "default": + switch (funct["(verb)"]) { + case "break": + case "continue": + case "return": + case "throw": break; default: if (!ft.test(lines[nexttoken.line - 2])) { @@ -3656,32 +4092,32 @@ loop: for (;;) { } } indentation(-option.indent); - advance('default'); + advance("default"); g = true; - advance(':'); + advance(":"); break; - case '}': + case "}": indent -= option.indent; indentation(); - advance('}', t); - if (this.cases.length === 1 || this.condition.id === 'true' || - this.condition.id === 'false') { + advance("}", t); + if (this.cases.length === 1 || this.condition.id === "true" || + this.condition.id === "false") { if (!option.onecase) warning("This 'switch' should be an 'if'.", this); } - funct['(breakage)'] -= 1; - funct['(verb)'] = undefined; + funct["(breakage)"] -= 1; + funct["(verb)"] = undefined; return; - case '(end)': - error("Missing '{a}'.", nexttoken, '}'); + case "(end)": + error("Missing '{a}'.", nexttoken, "}"); return; default: if (g) { switch (token.id) { - case ',': + case ",": error("Each value should have its own case label."); return; - case ':': + case ":": g = false; statements(); break; @@ -3690,13 +4126,13 @@ loop: for (;;) { return; } } else { - if (token.id === ':') { - advance(':'); - error("Unexpected '{a}'.", token, ':'); + if (token.id === ":") { + advance(":"); + error("Unexpected '{a}'.", token, ":"); statements(); } else { error("Expected '{a}' and instead saw '{b}'.", - nexttoken, 'case', nexttoken.value); + nexttoken, "case", nexttoken.value); return; } } @@ -3704,7 +4140,7 @@ loop: for (;;) { } }).labelled = true; - stmt('debugger', function () { + stmt("debugger", function () { if (!option.debug) { warning("All 'debugger' statements should be removed."); } @@ -3712,49 +4148,52 @@ loop: for (;;) { }).exps = true; (function () { - var x = stmt('do', function () { - funct['(breakage)'] += 1; - funct['(loopage)'] += 1; + var x = stmt("do", function () { + funct["(breakage)"] += 1; + funct["(loopage)"] += 1; + increaseComplexityCount(); + this.first = block(true); - advance('while'); + advance("while"); var t = nexttoken; nonadjacent(token, t); - advance('('); + advance("("); nospace(); expression(20); - if (nexttoken.id === '=') { + if (nexttoken.id === "=") { if (!option.boss) warning("Expected a conditional expression and instead saw an assignment."); - advance('='); + advance("="); expression(20); } - advance(')', t); + advance(")", t); nospace(prevtoken, token); - funct['(breakage)'] -= 1; - funct['(loopage)'] -= 1; + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; return this; }); x.labelled = true; x.exps = true; }()); - blockstmt('for', function () { + blockstmt("for", function () { var s, t = nexttoken; - funct['(breakage)'] += 1; - funct['(loopage)'] += 1; - advance('('); + funct["(breakage)"] += 1; + funct["(loopage)"] += 1; + increaseComplexityCount(); + advance("("); nonadjacent(this, t); nospace(); - if (peek(nexttoken.id === 'var' ? 1 : 0).id === 'in') { - if (nexttoken.id === 'var') { - advance('var'); + if (peek(nexttoken.id === "var" ? 1 : 0).id === "in") { + if (nexttoken.id === "var") { + advance("var"); varstatement.fud.call(varstatement, true); } else { switch (funct[nexttoken.value]) { - case 'unused': - funct[nexttoken.value] = 'var'; + case "unused": + funct[nexttoken.value] = "var"; break; - case 'var': + case "var": break; default: warning("Bad for in variable '{a}'.", @@ -3762,27 +4201,27 @@ loop: for (;;) { } advance(); } - advance('in'); + advance("in"); expression(20); - advance(')', t); + advance(")", t); s = block(true, true); - if (option.forin && s && (s.length > 1 || typeof s[0] !== 'object' || - s[0].value !== 'if')) { + if (option.forin && s && (s.length > 1 || typeof s[0] !== "object" || + s[0].value !== "if")) { warning("The body of a for in should be wrapped in an if statement to filter " + "unwanted properties from the prototype.", this); } - funct['(breakage)'] -= 1; - funct['(loopage)'] -= 1; + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; return this; } else { - if (nexttoken.id !== ';') { - if (nexttoken.id === 'var') { - advance('var'); + if (nexttoken.id !== ";") { + if (nexttoken.id === "var") { + advance("var"); varstatement.fud.call(varstatement); } else { for (;;) { - expression(0, 'for'); - if (nexttoken.id !== ',') { + expression(0, "for"); + if (nexttoken.id !== ",") { break; } comma(); @@ -3790,53 +4229,53 @@ loop: for (;;) { } } nolinebreak(token); - advance(';'); - if (nexttoken.id !== ';') { + advance(";"); + if (nexttoken.id !== ";") { expression(20); - if (nexttoken.id === '=') { + if (nexttoken.id === "=") { if (!option.boss) warning("Expected a conditional expression and instead saw an assignment."); - advance('='); + advance("="); expression(20); } } nolinebreak(token); - advance(';'); - if (nexttoken.id === ';') { + advance(";"); + if (nexttoken.id === ";") { error("Expected '{a}' and instead saw '{b}'.", - nexttoken, ')', ';'); + nexttoken, ")", ";"); } - if (nexttoken.id !== ')') { + if (nexttoken.id !== ")") { for (;;) { - expression(0, 'for'); - if (nexttoken.id !== ',') { + expression(0, "for"); + if (nexttoken.id !== ",") { break; } comma(); } } - advance(')', t); + advance(")", t); nospace(prevtoken, token); block(true, true); - funct['(breakage)'] -= 1; - funct['(loopage)'] -= 1; + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; return this; } }).labelled = true; - stmt('break', function () { + stmt("break", function () { var v = nexttoken.value; - if (funct['(breakage)'] === 0) + if (funct["(breakage)"] === 0) warning("Unexpected '{a}'.", nexttoken, this.value); if (!option.asi) nolinebreak(this); - if (nexttoken.id !== ';') { + if (nexttoken.id !== ";") { if (token.line === nexttoken.line) { - if (funct[v] !== 'label') { + if (funct[v] !== "label") { warning("'{a}' is not a statement label.", nexttoken, v); } else if (scope[v] !== funct) { warning("'{a}' is out of scope.", nexttoken, v); @@ -3845,23 +4284,23 @@ loop: for (;;) { advance(); } } - reachable('break'); + reachable("break"); return this; }).exps = true; - stmt('continue', function () { + stmt("continue", function () { var v = nexttoken.value; - if (funct['(breakage)'] === 0) + if (funct["(breakage)"] === 0) warning("Unexpected '{a}'.", nexttoken, this.value); if (!option.asi) nolinebreak(this); - if (nexttoken.id !== ';') { + if (nexttoken.id !== ";") { if (token.line === nexttoken.line) { - if (funct[v] !== 'label') { + if (funct[v] !== "label") { warning("'{a}' is not a statement label.", nexttoken, v); } else if (scope[v] !== funct) { warning("'{a}' is out of scope.", nexttoken, v); @@ -3869,20 +4308,20 @@ loop: for (;;) { this.first = nexttoken; advance(); } - } else if (!funct['(loopage)']) { + } else if (!funct["(loopage)"]) { warning("Unexpected '{a}'.", nexttoken, this.value); } - reachable('continue'); + reachable("continue"); return this; }).exps = true; - stmt('return', function () { + stmt("return", function () { if (this.line === nexttoken.line) { - if (nexttoken.id === '(regexp)') + if (nexttoken.id === "(regexp)") warning("Wrap the /regexp/ literal in parens to disambiguate the slash operator."); - if (nexttoken.id !== ';' && !nexttoken.reach) { + if (nexttoken.id !== ";" && !nexttoken.reach) { nonadjacent(token, nexttoken); if (peek().value === "=" && !option.boss) { warningAt("Did you mean to return a conditional instead of an assignment?", @@ -3893,38 +4332,38 @@ loop: for (;;) { } else if (!option.asi) { nolinebreak(this); // always warn (Line breaking error) } - reachable('return'); + reachable("return"); return this; }).exps = true; - stmt('throw', function () { + stmt("throw", function () { nolinebreak(this); nonadjacent(token, nexttoken); this.first = expression(20); - reachable('throw'); + reachable("throw"); return this; }).exps = true; // Superfluous reserved words - reserve('class'); - reserve('const'); - reserve('enum'); - reserve('export'); - reserve('extends'); - reserve('import'); - reserve('super'); + reserve("class"); + reserve("const"); + reserve("enum"); + reserve("export"); + reserve("extends"); + reserve("import"); + reserve("super"); - reserve('let'); - reserve('yield'); - reserve('implements'); - reserve('interface'); - reserve('package'); - reserve('private'); - reserve('protected'); - reserve('public'); - reserve('static'); + reserve("let"); + reserve("yield"); + reserve("implements"); + reserve("interface"); + reserve("package"); + reserve("private"); + reserve("protected"); + reserve("public"); + reserve("static"); // Parse JSON @@ -3933,26 +4372,26 @@ loop: for (;;) { function jsonObject() { var o = {}, t = nexttoken; - advance('{'); - if (nexttoken.id !== '}') { + advance("{"); + if (nexttoken.id !== "}") { for (;;) { - if (nexttoken.id === '(end)') { + if (nexttoken.id === "(end)") { error("Missing '}' to match '{' from line {a}.", nexttoken, t.line); - } else if (nexttoken.id === '}') { + } else if (nexttoken.id === "}") { warning("Unexpected comma.", token); break; - } else if (nexttoken.id === ',') { + } else if (nexttoken.id === ",") { error("Unexpected comma.", nexttoken); - } else if (nexttoken.id !== '(string)') { + } else if (nexttoken.id !== "(string)") { warning("Expected a string and instead saw {a}.", nexttoken, nexttoken.value); } if (o[nexttoken.value] === true) { warning("Duplicate key '{a}'.", nexttoken, nexttoken.value); - } else if ((nexttoken.value === '__proto__' && - !option.proto) || (nexttoken.value === '__iterator__' && + } else if ((nexttoken.value === "__proto__" && + !option.proto) || (nexttoken.value === "__iterator__" && !option.iterator)) { warning("The '{a}' key may produce unexpected results.", nexttoken, nexttoken.value); @@ -3960,62 +4399,62 @@ loop: for (;;) { o[nexttoken.value] = true; } advance(); - advance(':'); + advance(":"); jsonValue(); - if (nexttoken.id !== ',') { + if (nexttoken.id !== ",") { break; } - advance(','); + advance(","); } } - advance('}'); + advance("}"); } function jsonArray() { var t = nexttoken; - advance('['); - if (nexttoken.id !== ']') { + advance("["); + if (nexttoken.id !== "]") { for (;;) { - if (nexttoken.id === '(end)') { + if (nexttoken.id === "(end)") { error("Missing ']' to match '[' from line {a}.", nexttoken, t.line); - } else if (nexttoken.id === ']') { + } else if (nexttoken.id === "]") { warning("Unexpected comma.", token); break; - } else if (nexttoken.id === ',') { + } else if (nexttoken.id === ",") { error("Unexpected comma.", nexttoken); } jsonValue(); - if (nexttoken.id !== ',') { + if (nexttoken.id !== ",") { break; } - advance(','); + advance(","); } } - advance(']'); + advance("]"); } switch (nexttoken.id) { - case '{': + case "{": jsonObject(); break; - case '[': + case "[": jsonArray(); break; - case 'true': - case 'false': - case 'null': - case '(number)': - case '(string)': + case "true": + case "false": + case "null": + case "(number)": + case "(string)": advance(); break; - case '-': - advance('-'); + case "-": + advance("-"); if (token.character !== nexttoken.from) { warning("Unexpected space after '-'.", token); } adjacent(token, nexttoken); - advance('(number)'); + advance("(number)"); break; default: error("Expected a JSON value.", nexttoken); @@ -4023,48 +4462,75 @@ loop: for (;;) { } -// The actual JSHINT function itself. - + // The actual JSHINT function itself. var itself = function (s, o, g) { - var a, i, k; - JSHINT.errors = []; - JSHINT.undefs = []; + var a, i, k, x; + var optionKeys; + var newOptionObj = {}; + + if (o && o.scope) { + JSHINT.scope = o.scope; + } else { + JSHINT.errors = []; + JSHINT.undefs = []; + JSHINT.internals = []; + JSHINT.blacklist = {}; + JSHINT.scope = "(main)"; + } + predefined = Object.create(standard); + declared = Object.create(null); combine(predefined, g || {}); + if (o) { a = o.predef; if (a) { - if (Array.isArray(a)) { - for (i = 0; i < a.length; i += 1) { - predefined[a[i]] = true; - } - } else if (typeof a === 'object') { - k = Object.keys(a); - for (i = 0; i < k.length; i += 1) { - predefined[k[i]] = !!a[k[i]]; - } + if (!Array.isArray(a) && typeof a === "object") { + a = Object.keys(a); } + a.forEach(function (item) { + var slice; + if (item[0] === "-") { + slice = item.slice(1); + JSHINT.blacklist[slice] = slice; + } else { + predefined[item] = true; + } + }); + } + + optionKeys = Object.keys(o); + for (x = 0; x < optionKeys.length; x++) { + newOptionObj[optionKeys[x]] = o[optionKeys[x]]; + + if (optionKeys[x] === "newcap" && o[optionKeys[x]] === false) + newOptionObj["(explicitNewcap)"] = true; + + if (optionKeys[x] === "indent") + newOptionObj.white = true; } - option = o; - } else { - option = {}; } + + option = newOptionObj; + option.indent = option.indent || 4; option.maxerr = option.maxerr || 50; - tab = ''; + tab = ""; for (i = 0; i < option.indent; i += 1) { - tab += ' '; + tab += " "; } indent = 1; global = Object.create(predefined); scope = global; funct = { - '(global)': true, - '(name)': '(global)', - '(scope)': scope, - '(breakage)': 0, - '(loopage)': 0 + "(global)": true, + "(name)": "(global)", + "(scope)": scope, + "(breakage)": 0, + "(loopage)": 0, + "(tokens)": {}, + "(metrics)": createMetrics(nexttoken) }; functions = [funct]; urls = []; @@ -4076,21 +4542,52 @@ loop: for (;;) { lookahead = []; jsonmode = false; warnings = 0; + lines = []; + unuseds = []; + + if (!isString(s) && !Array.isArray(s)) { + errorAt("Input is neither a string nor an array of strings.", 0); + return false; + } + + if (isString(s) && /^\s*$/g.test(s)) { + errorAt("Input is an empty string.", 0); + return false; + } + + if (s.length === 0) { + errorAt("Input is an empty array.", 0); + return false; + } + lex.init(s); + prereg = true; directive = {}; - prevtoken = token = nexttoken = syntax['(begin)']; + prevtoken = token = nexttoken = syntax["(begin)"]; + + // Check options + for (var name in o) { + if (is_own(o, name)) { + checkOption(name, token); + } + } + assume(); // combine the passed globals after we've assumed all our options combine(predefined, g || {}); + //reset values + comma.first = true; + quotmark = undefined; + try { advance(); switch (nexttoken.id) { - case '{': - case '[': + case "{": + case "[": option.laxbreak = true; jsonmode = true; jsonValue(); @@ -4103,26 +4600,26 @@ loop: for (;;) { statements(); } - advance('(end)'); + advance((nexttoken && nexttoken.value !== ".") ? "(end)" : undefined); var markDefined = function (name, context) { do { - if (typeof context[name] === 'string') { + if (typeof context[name] === "string") { // JSHINT marks unused variables as 'unused' and // unused function declaration as 'unction'. This // code changes such instances back 'var' and // 'closure' so that the code in JSHINT.data() // doesn't think they're unused. - if (context[name] === 'unused') - context[name] = 'var'; - else if (context[name] === 'unction') - context[name] = 'closure'; + if (context[name] === "unused") + context[name] = "var"; + else if (context[name] === "unction") + context[name] = "closure"; return true; } - context = context['(context)']; + context = context["(context)"]; } while (context); return false; @@ -4144,6 +4641,37 @@ loop: for (;;) { implied[name] = newImplied; }; + var warnUnused = function (name, token) { + var line = token.line; + var chr = token.character; + + if (option.unused) + warningAt("'{a}' is defined but never used.", line, chr, name); + + unuseds.push({ + name: name, + line: line, + character: chr + }); + }; + + var checkUnused = function (func, key) { + var type = func[key]; + var token = func["(tokens)"][key]; + + if (key.charAt(0) === "(") + return; + + if (type !== "unused" && type !== "unction") + return; + + // Params are checked separately from other variables. + if (func["(params)"] && func["(params)"].indexOf(key) !== -1) + return; + + warnUnused(key, token); + }; + // Check queued 'x is not defined' instances to see if they're still undefined. for (i = 0; i < JSHINT.undefs.length; i += 1) { k = JSHINT.undefs[i].slice(0); @@ -4154,6 +4682,43 @@ loop: for (;;) { warning.apply(warning, k.slice(1)); } } + + functions.forEach(function (func) { + for (var key in func) { + if (is_own(func, key)) { + checkUnused(func, key); + } + } + + if (!func["(params)"]) + return; + + var params = func["(params)"].slice(); + var param = params.pop(); + var type; + + while (param) { + type = func[param]; + + // 'undefined' is a special case for (function (window, undefined) { ... })(); + // patterns. + + if (param === "undefined") + return; + + if (type !== "unused" && type !== "unction") + return; + + warnUnused(param, func["(tokens)"][param]); + param = params.pop(); + } + }); + + for (var key in declared) { + if (is_own(declared, key) && !is_own(global, key)) { + warnUnused(key, declared[key]); + } + } } catch (e) { if (e) { var nt = nexttoken || {}; @@ -4166,14 +4731,31 @@ loop: for (;;) { } } + // Loop over the listed "internals", and check them as well. + + if (JSHINT.scope === "(main)") { + o = o || {}; + + for (i = 0; i < JSHINT.internals.length; i += 1) { + k = JSHINT.internals[i]; + o.scope = k.elem; + itself(k.value, o, g); + } + } + return JSHINT.errors.length === 0; }; // Data summary. itself.data = function () { + var data = { + functions: [], + options: option + }; + var implieds = []; + var members = []; + var fu, f, i, j, n, globals; - var data = { functions: [], options: option }, fu, globals, implieds = [], f, i, j, - members = [], n, unused = [], v; if (itself.errors.length) { data.errors = itself.errors; } @@ -4190,6 +4772,7 @@ loop: for (;;) { }); } } + if (implieds.length > 0) { data.implieds = implieds; } @@ -4202,49 +4785,37 @@ loop: for (;;) { if (globals.length > 0) { data.globals = globals; } + for (i = 1; i < functions.length; i += 1) { f = functions[i]; fu = {}; + for (j = 0; j < functionicity.length; j += 1) { fu[functionicity[j]] = []; } - for (n in f) { - if (is_own(f, n) && n.charAt(0) !== '(') { - v = f[n]; - if (v === 'unction') { - v = 'unused'; - } - if (Array.isArray(fu[v])) { - fu[v].push(n); - if (v === 'unused') { - unused.push({ - name: n, - line: f['(line)'], - 'function': f['(name)'] - }); - } - } - } - } + for (j = 0; j < functionicity.length; j += 1) { if (fu[functionicity[j]].length === 0) { delete fu[functionicity[j]]; } } - fu.name = f['(name)']; - fu.param = f['(params)']; - fu.line = f['(line)']; - fu.last = f['(last)']; + + fu.name = f["(name)"]; + fu.param = f["(params)"]; + fu.line = f["(line)"]; + fu.character = f["(character)"]; + fu.last = f["(last)"]; + fu.lastcharacter = f["(lastcharacter)"]; data.functions.push(fu); } - if (unused.length > 0) { - data.unused = unused; + if (unuseds.length > 0) { + data.unused = unuseds; } members = []; for (n in member) { - if (typeof member[n] === 'number') { + if (typeof member[n] === "number") { data.member = member; break; } @@ -4253,138 +4824,12 @@ loop: for (;;) { return data; }; - itself.report = function (option) { - var data = itself.data(); - - var a = [], c, e, err, f, i, k, l, m = '', n, o = [], s; - - function detail(h, array) { - var b, i, singularity; - if (array) { - o.push('
' + h + ' '); - array = array.sort(); - for (i = 0; i < array.length; i += 1) { - if (array[i] !== singularity) { - singularity = array[i]; - o.push((b ? ', ' : '') + singularity); - b = true; - } - } - o.push('
'); - } - } - - - if (data.errors || data.implieds || data.unused) { - err = true; - o.push('
Error:'); - if (data.errors) { - for (i = 0; i < data.errors.length; i += 1) { - c = data.errors[i]; - if (c) { - e = c.evidence || ''; - o.push('

Problem' + (isFinite(c.line) ? ' at line ' + - c.line + ' character ' + c.character : '') + - ': ' + c.reason.entityify() + - '

' + - (e && (e.length > 80 ? e.slice(0, 77) + '...' : - e).entityify()) + '

'); - } - } - } - - if (data.implieds) { - s = []; - for (i = 0; i < data.implieds.length; i += 1) { - s[i] = '' + data.implieds[i].name + ' ' + - data.implieds[i].line + ''; - } - o.push('

Implied global: ' + s.join(', ') + '

'); - } - - if (data.unused) { - s = []; - for (i = 0; i < data.unused.length; i += 1) { - s[i] = '' + data.unused[i].name + ' ' + - data.unused[i].line + ' ' + - data.unused[i]['function'] + ''; - } - o.push('

Unused variable: ' + s.join(', ') + '

'); - } - if (data.json) { - o.push('

JSON: bad.

'); - } - o.push('
'); - } - - if (!option) { - - o.push('
'); - - if (data.urls) { - detail("URLs
", data.urls, '
'); - } - - if (data.json && !err) { - o.push('

JSON: good.

'); - } else if (data.globals) { - o.push('
Global ' + - data.globals.sort().join(', ') + '
'); - } else { - o.push('
No new global variables introduced.
'); - } - - for (i = 0; i < data.functions.length; i += 1) { - f = data.functions[i]; - - o.push('
' + f.line + '-' + - f.last + ' ' + (f.name || '') + '(' + - (f.param ? f.param.join(', ') : '') + ')
'); - detail('Unused', f.unused); - detail('Closure', f.closure); - detail('Variable', f['var']); - detail('Exception', f.exception); - detail('Outer', f.outer); - detail('Global', f.global); - detail('Label', f.label); - } - - if (data.member) { - a = Object.keys(data.member); - if (a.length) { - a = a.sort(); - m = '
/*members ';
-                    l = 10;
-                    for (i = 0; i < a.length; i += 1) {
-                        k = a[i];
-                        n = k.name();
-                        if (l + n.length > 72) {
-                            o.push(m + '
'); - m = ' '; - l = 1; - } - l += n.length + 2; - if (data.member[k] === 1) { - n = '' + n + ''; - } - if (i < a.length - 1) { - n += ', '; - } - m += n; - } - o.push(m + '
*/
'); - } - o.push('
'); - } - } - return o.join(''); - }; - itself.jshint = itself; return itself; }()); // Make JSHINT a Node module, if possible. -if (typeof exports === 'object' && exports) +if (typeof exports === "object" && exports) { exports.JSHINT = JSHINT; +} \ No newline at end of file From 1fcccd45ce0eb73c4f54650d7929d788847f3e37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Zaefferer?= Date: Wed, 24 Oct 2012 09:32:07 -0400 Subject: [PATCH 045/151] Menu: Use start icon (first is deprecated) --- demos/menu/icons.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/menu/icons.html b/demos/menu/icons.html index b7a04e6653..56cf242f33 100644 --- a/demos/menu/icons.html +++ b/demos/menu/icons.html @@ -29,7 +29,7 @@
  • Playback
      -
    • Prev
    • +
    • Prev
    • Stop
    • Play
    • Next
    • From ba752cf7eda841ded93688ab3167b5515fa1660c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Zaefferer?= Date: Wed, 24 Oct 2012 10:00:39 -0400 Subject: [PATCH 046/151] Tooltip: Run _disable when disabled option is set on create. Fixes #8712 - Tooltip: Disabled tooltips on initialization. --- tests/unit/tooltip/tooltip_options.js | 8 ++++++++ ui/jquery.ui.tooltip.js | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/tests/unit/tooltip/tooltip_options.js b/tests/unit/tooltip/tooltip_options.js index 3be6518558..9f0de2b570 100644 --- a/tests/unit/tooltip/tooltip_options.js +++ b/tests/unit/tooltip/tooltip_options.js @@ -2,6 +2,14 @@ module( "tooltip: options" ); +test( "disabled: true", function() { + expect( 1 ); + $( "#tooltipped1" ).tooltip({ + disabled: true + }).tooltip( "open" ); + equal( $( ".ui-tooltip" ).length, 0 ); +}); + test( "content: default", function() { expect( 1 ); var element = $( "#tooltipped1" ).tooltip().tooltip( "open" ); diff --git a/ui/jquery.ui.tooltip.js b/ui/jquery.ui.tooltip.js index 43788a082e..f93dd7a2f8 100644 --- a/ui/jquery.ui.tooltip.js +++ b/ui/jquery.ui.tooltip.js @@ -75,6 +75,10 @@ $.widget( "ui.tooltip", { this.tooltips = {}; // IDs of parent tooltips where we removed the title attribute this.parents = {}; + + if ( this.options.disabled ) { + this._disable(); + } }, _setOption: function( key, value ) { From 848ab485839b6dd26f2b6c6680141d95cab32ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Wed, 24 Oct 2012 10:13:14 -0400 Subject: [PATCH 047/151] Widget: Use existing widgetEventPrefix when extending. Fixes #8724 - widgetEventPrefix is lost when extending existing widget. --- tests/unit/widget/widget_core.js | 15 +++++++++++++++ ui/jquery.ui.widget.js | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/tests/unit/widget/widget_core.js b/tests/unit/widget/widget_core.js index 31f2b9ccff..624ccf7435 100644 --- a/tests/unit/widget/widget_core.js +++ b/tests/unit/widget/widget_core.js @@ -1240,6 +1240,21 @@ test( "redefine deep prototype chain", function() { delete $.ui.testWidget2; }); +test( "redefine - widgetEventPrefix", function() { + expect( 2 ); + + $.widget( "ui.testWidget", { + widgetEventPrefix: "test" + }); + equal( $.ui.testWidget.prototype.widgetEventPrefix, "test", + "cusotm prefix in original" ); + + $.widget( "ui.testWidget", $.ui.testWidget, {} ); + equal( $.ui.testWidget.prototype.widgetEventPrefix, "test", + "cusotm prefix in extension" ); + +}); + asyncTest( "_delay", function() { expect( 6 ); var order = 0, diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index ccbe0cac58..eea12c471f 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -101,7 +101,7 @@ $.widget = function( name, base, prototype ) { // TODO: remove support for widgetEventPrefix // always use the name + a colon as the prefix, e.g., draggable:start // don't prefix for widgets that aren't DOM-based - widgetEventPrefix: name + widgetEventPrefix: basePrototype.widgetEventPrefix || name }, prototype, { constructor: constructor, namespace: namespace, From 721a4b4ae027b140ca280bbc8fb8ed334081b184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Zaefferer?= Date: Wed, 24 Oct 2012 10:41:48 -0400 Subject: [PATCH 048/151] Widget: Fix _on to use element argument for delegated events. Fixes #8658 - Widget: this._on delegates using instance.widget() instead of passed element --- tests/unit/widget/widget_core.js | 24 ++++++++++++++++++++++++ ui/jquery.ui.widget.js | 8 +++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/tests/unit/widget/widget_core.js b/tests/unit/widget/widget_core.js index 624ccf7435..7bddc7f5c1 100644 --- a/tests/unit/widget/widget_core.js +++ b/tests/unit/widget/widget_core.js @@ -760,6 +760,30 @@ test( "_on() with delegate", function() { $.ui.testWidget(); }); +test( "_on() with delegate to descendent", function() { + expect( 4 ); + $.widget( "ui.testWidget", { + _create: function() { + this.target = $( "

      hello world

      " ); + this.child = this.target.children(); + this._on( this.target, { + "keyup": "handlerDirect", + "keyup strong": "handlerDelegated" + }); + this.child.trigger( "keyup" ); + }, + handlerDirect: function( event ) { + deepEqual( event.currentTarget, this.target[ 0 ] ); + deepEqual( event.target, this.child[ 0 ] ); + }, + handlerDelegated: function( event ) { + deepEqual( event.currentTarget, this.child[ 0 ] ); + deepEqual( event.target, this.child[ 0 ] ); + } + }); + $.ui.testWidget(); +}); + test( "_on() to common element", function() { expect( 1 ); $.widget( "ui.testWidget", { diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index eea12c471f..a6eae65800 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -362,17 +362,19 @@ $.Widget.prototype = { }, _on: function( element, handlers ) { + var delegateElement, + instance = this; // no element argument, shuffle and use this.element if ( !handlers ) { handlers = element; element = this.element; + delegateElement = this.widget(); } else { // accept selectors, DOM elements - element = $( element ); + element = delegateElement = $( element ); this.bindings = this.bindings.add( element ); } - var instance = this; $.each( handlers, function( event, handler ) { function handlerProxy() { // allow widgets to customize the disabled handling @@ -396,7 +398,7 @@ $.Widget.prototype = { eventName = match[1] + instance.eventNamespace, selector = match[2]; if ( selector ) { - instance.widget().delegate( selector, eventName, handlerProxy ); + delegateElement.delegate( selector, eventName, handlerProxy ); } else { element.bind( eventName, handlerProxy ); } From 5f9d5c54c31546977792f4493b419f6c72fcc93e Mon Sep 17 00:00:00 2001 From: Kato Kazuyoshi Date: Wed, 24 Oct 2012 10:27:05 -0500 Subject: [PATCH 049/151] Effects (size): Adjusting behavior of toggled size effects - See gh-203 - Partial Fix for #7041 --- ui/jquery.ui.effect-scale.js | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/ui/jquery.ui.effect-scale.js b/ui/jquery.ui.effect-scale.js index 933530a673..7fa04bed66 100644 --- a/ui/jquery.ui.effect-scale.js +++ b/ui/jquery.ui.effect-scale.js @@ -102,8 +102,9 @@ $.effects.effect.scale = function( o, done ) { $.effects.effect.size = function( o, done ) { // Create element - var el = $( this ), - props = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ], + var original, baseline, factor, + el = $( this ), + props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ], // Always restore props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ], @@ -119,8 +120,12 @@ $.effects.effect.size = function( o, done ) { restore = o.restore || mode !== "effect", scale = o.scale || "both", origin = o.origin || [ "middle", "center" ], - original, baseline, factor, - position = el.css( "position" ); + position = el.css( "position" ), + props = restore ? props0 : props1, + zero = { + height: 0, + width: 0 + }; if ( mode === "show" ) { el.show(); @@ -132,8 +137,13 @@ $.effects.effect.size = function( o, done ) { outerWidth: el.outerWidth() }; - el.from = o.from || original; - el.to = o.to || original; + if ( o.mode === "toggle" && mode === "show" ) { + el.from = o.to || zero; + el.to = o.from || original; + } else { + el.from = o.from || ( mode === "show" ? zero : original ); + el.to = o.to || ( mode === "hide" ? zero : original ); + } // Set scaling factor factor = { @@ -170,13 +180,13 @@ $.effects.effect.size = function( o, done ) { // Vertical props scaling if ( factor.from.y !== factor.to.y ) { - props = props.concat( cProps ); + props = props.concat( cProps ).concat( props2 ); el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from ); el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to ); } } - $.effects.save( el, restore ? props : props1 ); + $.effects.save( el, props ); el.show(); $.effects.createWrapper( el ); el.css( "overflow", "hidden" ).css( el.from ); @@ -197,7 +207,7 @@ $.effects.effect.size = function( o, done ) { // Add margins/font-size vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps); hProps = hProps.concat([ "marginLeft", "marginRight" ]); - props2 = props.concat(vProps).concat(hProps); + props2 = props0.concat(vProps).concat(hProps); el.find( "*[width]" ).each( function(){ var child = $( this ), @@ -254,7 +264,7 @@ $.effects.effect.size = function( o, done ) { if( mode === "hide" ) { el.hide(); } - $.effects.restore( el, restore ? props : props1 ); + $.effects.restore( el, props ); if ( !restore ) { // we need to calculate our new positioning based on the scaling From eaadcc0eebcd6ea45523e19f79b042dc0d6a30bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Wed, 24 Oct 2012 12:00:03 -0400 Subject: [PATCH 050/151] Widget: Bind the remove event to the element, not the .widget() element. --- ui/jquery.ui.autocomplete.js | 3 ++- ui/jquery.ui.widget.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ui/jquery.ui.autocomplete.js b/ui/jquery.ui.autocomplete.js index 7bacca006d..2d064834ce 100644 --- a/ui/jquery.ui.autocomplete.js +++ b/ui/jquery.ui.autocomplete.js @@ -64,7 +64,7 @@ $.widget( "ui.autocomplete", { .addClass( "ui-autocomplete-input" ) .attr( "autocomplete", "off" ); - this._on({ + this._on( this.element, { keydown: function( event ) { if ( this.element.prop( "readOnly" ) ) { suppressKeyPress = true; @@ -191,6 +191,7 @@ $.widget( "ui.autocomplete", { .zIndex( this.element.zIndex() + 1 ) .hide() .data( "menu" ); + this._on( this.menu.element, { mousedown: function( event ) { // prevent moving focus out of the text field diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index a6eae65800..f4805fb757 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -237,7 +237,7 @@ $.Widget.prototype = { // TODO remove dual storage $.data( element, this.widgetName, this ); $.data( element, this.widgetFullName, this ); - this._on({ + this._on( this.element, { remove: function( event ) { if ( event.target === element ) { this.destroy(); From 88bfb7572d888b2a835888281f19770361b318d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Zaefferer?= Date: Wed, 24 Oct 2012 11:40:06 -0400 Subject: [PATCH 051/151] Cleanup demos: Copy&paste errors in titles, bad descriptions or styling --- demos/droppable/shopping-cart.html | 2 +- demos/position/cycler.html | 6 ++++-- demos/slider/hotelrooms.html | 2 +- demos/tooltip/forms.html | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/demos/droppable/shopping-cart.html b/demos/droppable/shopping-cart.html index 60468aab7f..7c33a3d4b5 100644 --- a/demos/droppable/shopping-cart.html +++ b/demos/droppable/shopping-cart.html @@ -88,7 +88,7 @@
  • -

    Demonstrate how to use an accordion to structure products into a catalog and make use drag and drop for adding them to a shopping cart, where they are sortable.

    +

    Demonstrate how to use an accordion to structure products into a catalog and make use of drag and drop for adding them to a shopping cart, where they are sortable.

    diff --git a/demos/position/cycler.html b/demos/position/cycler.html index 2c421211f8..dc9c8a0bd3 100644 --- a/demos/position/cycler.html +++ b/demos/position/cycler.html @@ -10,6 +10,9 @@ - - - -

    jQuery UI Tabs Test Suite

    -

    -
    -

    -
      -
      - -
      -
        -
      • 1
      • -
      • 2
      • -
      • 3
      • -
      -
      -
      -
      -
      - -
      - -
      -
      -
      -
      - -
      -
      -
        -
      • 1
      • -
      -
      -
      - -
      -
        -
      • 1
      • -
      -
        -
      1. 1
      2. -
      -
      - -
      -
        -
      1. 1
      2. -
      -
        -
      • 1
      • -
      -
      - -
      -
      -
        -
        -
        - -
        -
          -
        • 1 -
            -
          • 3
          • -
          • 4
          • -
          -
        • -
        • 2
        • -
        -
        -
        -
        - -
        -
          -
        • 1
        • -
        • 2
        • -
        -
        -
        -
        - -
        -
        -
          -
        • 1
        • -
        • 2
        • -
        -
        -

        Lorem ipsum

        -

        Lorem ipsum

        -

        Lorem ipsum

        -
        -
        -

        Lorem ipsum

        -
        -
        -
        - -
        -
          -
        • not a tab
        • -
        • tab
        • -
        -
        -
        - -
        - - diff --git a/tests/unit/tabs/tabs_deprecated.js b/tests/unit/tabs/tabs_deprecated.js deleted file mode 100644 index 9d35994948..0000000000 --- a/tests/unit/tabs/tabs_deprecated.js +++ /dev/null @@ -1,182 +0,0 @@ -(function( $ ) { - -var state = TestHelpers.tabs.state; - -module( "tabs (deprecated): core" ); - -test( "panel ids", function() { - expect( 2 ); - - var element = $( "#tabs2" ).tabs(); - - element.one( "tabsbeforeload", function( event, ui ) { - equal( ui.panel.attr( "id" ), "∫ßáö_Սե", "from title attribute" ); - event.preventDefault(); - }); - element.tabs( "option", "active", 4 ); - - element.one( "tabsbeforeload", function( event, ui ) { - ok( /^ui-tabs-\d+$/.test( ui.panel.attr( "id" ) ), "generated id" ); - event.preventDefault(); - }); - element.tabs( "option", "active", 2 ); -}); - -module( "tabs (deprecated): options" ); - -test( "idPrefix", function() { - expect( 1 ); - - $( "#tabs2" ) - .one( "tabsbeforeload", function( event, ui ) { - ok( /^testing-\d+$/.test( ui.panel.attr( "id" ) ), "generated id" ); - event.preventDefault(); - }) - .tabs({ - idPrefix: "testing-", - active: 2 - }); -}); - -test( "tabTemplate + panelTemplate", function() { - // defaults are tested in the add method test - expect( 11 ); - - var tab, anchor, - element = $( "#tabs2" ).tabs({ - tabTemplate: "
      • #{label}
      • ", - panelTemplate: "
        " - }); - element.one( "tabsadd", function( event, ui ) { - var anchor = $( ui.tab ); - equal( ui.index, 5, "ui.index" ); - equal( anchor.text(), "New", "ui.tab" ); - equal( anchor.attr( "href" ), "http://example.com/#new", "tab href" ); - ok( anchor.parent().hasClass( "customTab" ), "tab custom class" ); - equal( ui.panel.id, "new", "ui.panel" ); - ok( $( ui.panel ).hasClass( "customPanel" ), "panel custom class" ); - }); - element.tabs( "add", "#new", "New" ); - tab = element.find( ".ui-tabs-nav li" ).last(); - anchor = tab.find( ".ui-tabs-anchor" ); - equal( tab.text(), "New", "label" ); - ok( tab.hasClass( "customTab" ), "tab custom class" ); - equal( anchor.attr( "href" ), "http://example.com/#new", "href" ); - equal( tab.attr( "aria-controls" ), "new", "aria-controls" ); - ok( element.find( "#new" ).hasClass( "customPanel" ), "panel custom class" ); -}); - -module( "tabs (deprecated): methods" ); - -test( "add", function() { - expect( 28 ); - - var tab, anchor, - element = $( "#tabs1" ).tabs(); - - function stripLeadingSlash( str ) { - return str.substr( str.charAt( 0 ) === "/" ? 1 : 0 ); - } - - state( element, 1, 0, 0 ); - - // add without index - element.one( "tabsadd", function( event, ui ) { - equal( ui.index, 3, "ui.index" ); - equal( $( ui.tab ).text(), "New", "ui.tab" ); - equal( ui.panel.id, "new", "ui.panel" ); - }); - element.tabs( "add", "#new", "New" ); - state( element, 1, 0, 0, 0 ); - tab = element.find( ".ui-tabs-nav li" ).last(); - anchor = tab.find( ".ui-tabs-anchor" ); - equal( tab.text(), "New", "label" ); - equal( stripLeadingSlash( anchor[0].pathname ), stripLeadingSlash( location.pathname ), "href pathname" ); - equal( anchor[0].hash, "#new", "href hash" ); - equal( tab.attr( "aria-controls" ), "new", "aria-controls" ); - ok( !tab.hasClass( "ui-state-hover" ), "not hovered" ); - anchor.simulate( "mouseover" ); - ok( tab.hasClass( "ui-state-hover" ), "hovered" ); - anchor.simulate( "click" ); - state( element, 0, 0, 0, 1 ); - - // add remote tab with index - element.one( "tabsadd", function( event, ui ) { - equal( ui.index, 1, "ui.index" ); - equal( $( ui.tab ).text(), "New Remote", "ui.tab" ); - equal( ui.panel.id, $( ui.tab ).closest( "li" ).attr( "aria-controls" ), "ui.panel" ); - }); - element.tabs( "add", "data/test.html", "New Remote", 1 ); - state( element, 0, 0, 0, 0, 1 ); - tab = element.find( ".ui-tabs-nav li" ).eq( 1 ); - anchor = tab.find( ".ui-tabs-anchor" ); - equal( tab.text(), "New Remote", "label" ); - equal( stripLeadingSlash( stripLeadingSlash( - anchor[0].pathname.replace( stripLeadingSlash( location.pathname ).split( "/" ).slice( 0, -1 ).join( "/" ), "" ) - ) ), "data/test.html", "href" ); - ok( /^ui-tabs-\d+$/.test( tab.attr( "aria-controls" ) ), "aria controls" ); - ok( !tab.hasClass( "ui-state-hover" ), "not hovered" ); - anchor.simulate( "mouseover" ); - ok( tab.hasClass( "ui-state-hover" ), "hovered" ); - anchor.simulate( "click" ); - state( element, 0, 1, 0, 0, 0 ); - - // add to empty tab set - element = $( "
          " ).tabs(); - equal( element.tabs( "option", "active" ), false, "active: false on init" ); - element.one( "tabsadd", function( event, ui ) { - equal( ui.index, 0, "ui.index" ); - equal( $( ui.tab ).text(), "First", "ui.tab" ); - equal( ui.panel.id, "first", "ui.panel" ); - }); - element.tabs( "add", "#first", "First" ); - state( element, 1 ); - equal( element.tabs( "option", "active" ), 0, "active: 0 after add" ); -}); - -test( "#5069 - ui.tabs.add creates two tab panels when using a full URL", function() { - expect( 2 ); - - var element = $( "#tabs2" ).tabs(); - equal( element.children( "div" ).length, element.find( ".ui-tabs-nav li" ).length ); - element.tabs( "add", "/new", "New" ); - equal( element.children( "div" ).length, element.find( ".ui-tabs-nav li" ).length ); -}); - -test( "remove", function() { - expect( 17 ); - - var element = $( "#tabs1" ).tabs({ active: 1 }); - state( element, 0, 1, 0 ); - - element.one( "tabsremove", function( event, ui ) { - equal( ui.index, -1, "ui.index" ); - equal( $( ui.tab ).text(), "2", "ui.tab" ); - equal( ui.panel.id, "fragment-2", "ui.panel" ); - }); - element.tabs( "remove", 1 ); - state( element, 0, 1 ); - equal( element.tabs( "option", "active" ), 1 ); - equal( element.find( ".ui-tabs-nav li a[href$='fragment-2']" ).length, 0, - "remove correct list item" ); - equal( element.find( "#fragment-2" ).length, 0, "remove correct panel" ); - - element.one( "tabsremove", function( event, ui ) { - equal( ui.index, -1, "ui.index" ); - equal( $( ui.tab ).text(), "3", "ui.tab" ); - equal( ui.panel.id, "fragment-3", "ui.panel" ); - }); - element.tabs( "remove", 1 ); - state( element, 1 ); - equal( element.tabs( "option", "active"), 0 ); - - element.one( "tabsremove", function( event, ui ) { - equal( ui.index, -1, "ui.index" ); - equal( $( ui.tab ).text(), "1", "ui.tab" ); - equal( ui.panel.id, "fragment-1", "ui.panel" ); - }); - element.tabs( "remove", 0 ); - equal( element.tabs( "option", "active" ), false ); -}); - -}( jQuery ) ); diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index 70a827acec..9918d6de27 100644 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -842,138 +842,4 @@ $.widget( "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 ) - }; - }; - - // add/remove methods and events - $.widget( "ui.tabs", $.ui.tabs, { - options: { - add: null, - remove: null, - tabTemplate: "
        • #{label}
        • " - }, - - add: function( url, label, index ) { - if ( index === undefined ) { - index = this.anchors.length; - } - - var doInsertAfter, panel, - options = this.options, - li = $( options.tabTemplate - .replace( /#\{href\}/g, url ) - .replace( /#\{label\}/g, label ) ), - id = !url.indexOf( "#" ) ? - url.replace( "#", "" ) : - this._tabId( li ); - - li.addClass( "ui-state-default ui-corner-top" ).data( "ui-tabs-destroy", true ); - li.attr( "aria-controls", id ); - - doInsertAfter = index >= this.tabs.length; - - // try to find an existing element before creating a new one - panel = this.element.find( "#" + id ); - if ( !panel.length ) { - panel = this._createPanel( id ); - if ( doInsertAfter ) { - if ( index > 0 ) { - panel.insertAfter( this.panels.eq( -1 ) ); - } else { - panel.appendTo( this.element ); - } - } else { - panel.insertBefore( this.panels[ index ] ); - } - } - panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ).hide(); - - if ( doInsertAfter ) { - li.appendTo( this.tablist ); - } else { - li.insertBefore( this.tabs[ index ] ); - } - - options.disabled = $.map( options.disabled, function( n ) { - return n >= index ? ++n : n; - }); - - this.refresh(); - if ( this.tabs.length === 1 && options.active === false ) { - this.option( "active", 0 ); - } - - this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); - return this; - }, - - remove: function( index ) { - index = this._getIndex( index ); - var options = this.options, - tab = this.tabs.eq( index ).remove(), - panel = this._getPanelForTab( tab ).remove(); - - // If selected tab was removed focus tab to the right or - // in case the last tab was removed the tab to the left. - // We check for more than 2 tabs, because if there are only 2, - // then when we remove this tab, there will only be one tab left - // so we don't need to detect which tab to activate. - if ( tab.hasClass( "ui-tabs-active" ) && this.anchors.length > 2 ) { - this._activate( index + ( index + 1 < this.anchors.length ? 1 : -1 ) ); - } - - options.disabled = $.map( - $.grep( options.disabled, function( n ) { - return n !== index; - }), - function( n ) { - return n >= index ? --n : n; - }); - - this.refresh(); - - this._trigger( "remove", null, this._ui( tab.find( "a" )[ 0 ], panel[ 0 ] ) ); - return this; - } - }); - - // panel ids (idPrefix option + title attribute) - $.widget( "ui.tabs", $.ui.tabs, { - options: { - idPrefix: "ui-tabs-" - }, - - _tabId: function( tab ) { - var a = tab.is( "li" ) ? tab.find( "a[href]" ) : tab; - a = a[0]; - return $( a ).closest( "li" ).attr( "aria-controls" ) || - a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF\-]/g, "" ) || - this.options.idPrefix + getNextTabId(); - } - }); - - // _createPanel method - $.widget( "ui.tabs", $.ui.tabs, { - options: { - panelTemplate: "
          " - }, - - _createPanel: function( id ) { - return $( this.options.panelTemplate ) - .attr( "id", id ) - .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) - .data( "ui-tabs-destroy", true ); - } - }); -} - })( jQuery ); From 8d35c03dfdb3d4368bf38b113e25c06a82129cd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Thu, 25 Oct 2012 06:15:30 -0400 Subject: [PATCH 078/151] Accordion: Removed animated option. Fixes #8601 - Accordion: Remove animated option. --- .../accordion/accordion_common_deprecated.js | 3 +- ui/jquery.ui.accordion.js | 34 ------------------- 2 files changed, 1 insertion(+), 36 deletions(-) diff --git a/tests/unit/accordion/accordion_common_deprecated.js b/tests/unit/accordion/accordion_common_deprecated.js index 0ce36991cc..3b1e0f4fe8 100644 --- a/tests/unit/accordion/accordion_common_deprecated.js +++ b/tests/unit/accordion/accordion_common_deprecated.js @@ -1,8 +1,7 @@ TestHelpers.commonWidgetTests( "accordion", { defaults: { active: 0, - animate: null, - animated: "slide", + animate: {}, collapsible: false, disabled: false, event: "click", diff --git a/ui/jquery.ui.accordion.js b/ui/jquery.ui.accordion.js index 6bafdd91fc..6ec85b6814 100644 --- a/ui/jquery.ui.accordion.js +++ b/ui/jquery.ui.accordion.js @@ -576,40 +576,6 @@ if ( $.uiBackCompat !== false ) { return ret; }; }( jQuery, jQuery.ui.accordion.prototype ) ); - - // animated option - // NOTE: this only provides support for "slide", "bounceslide", and easings - // not the full $.ui.accordion.animations API - (function( $, prototype ) { - $.extend( prototype.options, { - animate: null, - animated: "slide" - }); - - var _create = prototype._create; - prototype._create = function() { - var options = this.options; - if ( options.animate === null ) { - if ( !options.animated ) { - options.animate = false; - } else if ( options.animated === "slide" ) { - options.animate = 300; - } else if ( options.animated === "bounceslide" ) { - options.animate = { - duration: 200, - down: { - easing: "easeOutBounce", - duration: 1000 - } - }; - } else { - options.animate = options.animated; - } - } - - _create.call( this ); - }; - }( jQuery, jQuery.ui.accordion.prototype ) ); } })( jQuery ); From bc44e61dd9e6797bb23bc3038d43436a8ba052c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Thu, 25 Oct 2012 06:19:25 -0400 Subject: [PATCH 079/151] Accordion: Removed change and changestart events. Fixes #6841 - Accordion: Remove changestart event. Fixes #6843 - Accordion: Remove change event. --- build/tasks/testswarm.js | 1 - tests/unit/accordion/accordion.html | 3 - .../accordion/accordion_common_deprecated.js | 22 --- .../unit/accordion/accordion_deprecated.html | 140 ------------------ tests/unit/accordion/accordion_deprecated.js | 99 ------------- tests/unit/all-active.html | 1 - tests/unit/all.html | 1 - tests/unit/subsuite.js | 1 - ui/jquery.ui.accordion.js | 38 ----- 9 files changed, 306 deletions(-) delete mode 100644 tests/unit/accordion/accordion_common_deprecated.js delete mode 100644 tests/unit/accordion/accordion_deprecated.html delete mode 100644 tests/unit/accordion/accordion_deprecated.js diff --git a/build/tasks/testswarm.js b/build/tasks/testswarm.js index 7219bcf0c3..96e33b0f4c 100644 --- a/build/tasks/testswarm.js +++ b/build/tasks/testswarm.js @@ -10,7 +10,6 @@ var versions = { }, tests = { "Accordion": "accordion/accordion.html", - "Accordion_deprecated": "accordion/accordion_deprecated.html", "Autocomplete": "autocomplete/autocomplete.html", "Button": "button/button.html", "Core": "core/core.html", diff --git a/tests/unit/accordion/accordion.html b/tests/unit/accordion/accordion.html index b3b7caeae4..4f40091bc2 100644 --- a/tests/unit/accordion/accordion.html +++ b/tests/unit/accordion/accordion.html @@ -5,9 +5,6 @@ jQuery UI Accordion Test Suite - diff --git a/tests/unit/accordion/accordion_common_deprecated.js b/tests/unit/accordion/accordion_common_deprecated.js deleted file mode 100644 index 3b1e0f4fe8..0000000000 --- a/tests/unit/accordion/accordion_common_deprecated.js +++ /dev/null @@ -1,22 +0,0 @@ -TestHelpers.commonWidgetTests( "accordion", { - defaults: { - active: 0, - animate: {}, - collapsible: false, - disabled: false, - event: "click", - header: "> li > :first-child,> :not(li):even", - heightStyle: "auto", - icons: { - "activeHeader": "ui-icon-triangle-1-s", - "header": "ui-icon-triangle-1-e" - }, - - // callbacks - activate: null, - beforeActivate: null, - change: null, - changestart: null, - create: null - } -}); diff --git a/tests/unit/accordion/accordion_deprecated.html b/tests/unit/accordion/accordion_deprecated.html deleted file mode 100644 index dfb9fa90ef..0000000000 --- a/tests/unit/accordion/accordion_deprecated.html +++ /dev/null @@ -1,140 +0,0 @@ - - - - - jQuery UI Accordion Test Suite - - - - - - - - - - - - - - - - - - - - -

          jQuery UI Accordion Test Suite

          -

          -
          -

          -
            -
            - -
            -

            There is one obvious advantage:

            -
            -

            - You've seen it coming! -
            - Buy now and get nothing for free! -
            - Well, at least no free beer. Perhaps a bear, if you can afford it. -

            -
            -

            Now that you've got...

            -
            -

            - your bear, you have to admit it! -
            - No, we aren't selling bears. -

            -

            - We could talk about renting one. -

            -
            -

            Rent one bear, ...

            -
            -

            - get two for three beer. -

            -

            - And now, for something completely different. -

            -
            -
            - - - -
            -
            - Accordion Header 1 -
            -
            - Accordion Content 1 -
            -
            - Accordion Header 2 -
            -
            - Accordion Content 2 -
            -
            - Accordion Header 3 -
            -
            - Accordion Content 3 -
            -
            - -
            - - diff --git a/tests/unit/accordion/accordion_deprecated.js b/tests/unit/accordion/accordion_deprecated.js deleted file mode 100644 index 57dabf4184..0000000000 --- a/tests/unit/accordion/accordion_deprecated.js +++ /dev/null @@ -1,99 +0,0 @@ -(function( $ ) { - -var equalHeight = TestHelpers.accordion.equalHeight, - setupTeardown = TestHelpers.accordion.setupTeardown, - state = TestHelpers.accordion.state; - -module( "accordion (deprecated) - changestart/change events", setupTeardown() ); - -test( "changestart", function() { - expect( 26 ); - var element = $( "#list1" ).accordion({ - active: false, - collapsible: true - }), - headers = element.find( ".ui-accordion-header" ), - content = element.find( ".ui-accordion-content" ); - - element.one( "accordionchangestart", function( event, ui ) { - equal( ui.oldHeader.length, 0 ); - equal( ui.oldContent.length, 0 ); - equal( ui.newHeader.length, 1 ); - strictEqual( ui.newHeader[ 0 ], headers[ 0 ] ); - equal( ui.newContent.length, 1 ); - strictEqual( ui.newContent[ 0 ], content[ 0 ] ); - state( element, 0, 0, 0 ); - }); - element.accordion( "option", "active", 0 ); - state( element, 1, 0, 0 ); - - element.one( "accordionchangestart", function( event, ui ) { - equal( ui.oldHeader.length, 1 ); - strictEqual( ui.oldHeader[ 0 ], headers[ 0 ] ); - equal( ui.oldContent.length, 1 ); - strictEqual( ui.oldContent[ 0 ], content[ 0 ] ); - equal( ui.newHeader.length, 1 ); - strictEqual( ui.newHeader[ 0 ], headers[ 1 ] ); - equal( ui.newContent.length, 1 ); - strictEqual( ui.newContent[ 0 ], content[ 1 ] ); - state( element, 1, 0, 0 ); - }); - headers.eq( 1 ).click(); - state( element, 0, 1, 0 ); - - element.one( "accordionchangestart", function( event, ui ) { - equal( ui.oldHeader.length, 1 ); - strictEqual( ui.oldHeader[ 0 ], headers[ 1 ] ); - equal( ui.oldContent.length, 1 ); - strictEqual( ui.oldContent[ 0 ], content[ 1 ] ); - equal( ui.newHeader.length, 0 ); - equal( ui.newContent.length, 0 ); - state( element, 0, 1, 0 ); - }); - element.accordion( "option", "active", false ); - state( element, 0, 0, 0 ); -}); - -test( "change", function() { - expect( 20 ); - var element = $( "#list1" ).accordion({ - active: false, - collapsible: true - }), - headers = element.find( ".ui-accordion-header" ), - content = element.find( ".ui-accordion-content" ); - - element.one( "accordionchange", function( event, ui ) { - equal( ui.oldHeader.length, 0 ); - equal( ui.oldContent.length, 0 ); - equal( ui.newHeader.length, 1 ); - strictEqual( ui.newHeader[ 0 ], headers[ 0 ] ); - equal( ui.newContent.length, 1 ); - strictEqual( ui.newContent[ 0 ], content[ 0 ] ); - }); - element.accordion( "option", "active", 0 ); - - element.one( "accordionchange", function( event, ui ) { - equal( ui.oldHeader.length, 1 ); - strictEqual( ui.oldHeader[ 0 ], headers[ 0 ] ); - equal( ui.oldContent.length, 1 ); - strictEqual( ui.oldContent[ 0 ], content[ 0 ] ); - equal( ui.newHeader.length, 1 ); - strictEqual( ui.newHeader[ 0 ], headers[ 1 ] ); - equal( ui.newContent.length, 1 ); - strictEqual( ui.newContent[ 0 ], content[ 1 ] ); - }); - headers.eq( 1 ).click(); - - element.one( "accordionchange", function( event, ui ) { - equal( ui.oldHeader.length, 1 ); - strictEqual( ui.oldHeader[ 0 ], headers[ 1 ] ); - equal( ui.oldContent.length, 1 ); - strictEqual( ui.oldContent[ 0 ], content[ 1 ] ); - equal( ui.newHeader.length, 0 ); - equal( ui.newContent.length, 0 ); - }); - element.accordion( "option", "active", false ); -}); - -})(jQuery); diff --git a/tests/unit/all-active.html b/tests/unit/all-active.html index f842aa5cc4..2364114755 100644 --- a/tests/unit/all-active.html +++ b/tests/unit/all-active.html @@ -17,7 +17,6 @@ var params = [], suites = [ "accordion/accordion.html", - "accordion/accordion_deprecated.html", "autocomplete/autocomplete.html", "button/button.html", "core/core.html", diff --git a/tests/unit/all.html b/tests/unit/all.html index bc204c9762..e8dac887c2 100644 --- a/tests/unit/all.html +++ b/tests/unit/all.html @@ -17,7 +17,6 @@ var params = [], suites = [ "accordion/accordion.html", - "accordion/accordion_deprecated.html", "autocomplete/autocomplete.html", "button/button.html", "core/core.html", diff --git a/tests/unit/subsuite.js b/tests/unit/subsuite.js index 6238cb2b1d..b583bbd759 100644 --- a/tests/unit/subsuite.js +++ b/tests/unit/subsuite.js @@ -7,7 +7,6 @@ var versions = [ "git" ], additionalTests = { - accordion: [ "accordion_deprecated.html" ], position: [ "position_deprecated.html" ] }; diff --git a/ui/jquery.ui.accordion.js b/ui/jquery.ui.accordion.js index 6ec85b6814..b22f0c4e28 100644 --- a/ui/jquery.ui.accordion.js +++ b/ui/jquery.ui.accordion.js @@ -540,42 +540,4 @@ $.widget( "ui.accordion", { } }); - - -// DEPRECATED -if ( $.uiBackCompat !== false ) { - // change events - (function( $, prototype ) { - $.extend( prototype.options, { - change: null, - changestart: null - }); - - var _trigger = prototype._trigger; - prototype._trigger = function( type, event, data ) { - var ret = _trigger.apply( this, arguments ); - if ( !ret ) { - return false; - } - - if ( type === "beforeActivate" ) { - ret = _trigger.call( this, "changestart", event, { - oldHeader: data.oldHeader, - oldContent: data.oldPanel, - newHeader: data.newHeader, - newContent: data.newPanel - }); - } else if ( type === "activate" ) { - ret = _trigger.call( this, "change", event, { - oldHeader: data.oldHeader, - oldContent: data.oldPanel, - newHeader: data.newHeader, - newContent: data.newPanel - }); - } - return ret; - }; - }( jQuery, jQuery.ui.accordion.prototype ) ); -} - })( jQuery ); From 2582bfab46613da613f1a3354bc733b68a110b95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Thu, 25 Oct 2012 06:39:14 -0400 Subject: [PATCH 080/151] Position: Removed offset option. Fixes #6982 - Position: Remove offset option. --- build/tasks/testswarm.js | 1 - demos/position/default.html | 5 -- tests/unit/all-active.html | 1 - tests/unit/all.html | 1 - tests/unit/position/position.html | 3 -- tests/unit/position/position_deprecated.html | 56 -------------------- tests/unit/position/position_deprecated.js | 33 ------------ tests/unit/subsuite.js | 2 +- tests/visual/position/position_feedback.html | 29 +++++----- tests/visual/tooltip/tooltip.html | 6 +-- ui/jquery.ui.position.js | 36 ------------- 11 files changed, 17 insertions(+), 156 deletions(-) delete mode 100644 tests/unit/position/position_deprecated.html delete mode 100644 tests/unit/position/position_deprecated.js diff --git a/build/tasks/testswarm.js b/build/tasks/testswarm.js index 96e33b0f4c..21b644a522 100644 --- a/build/tasks/testswarm.js +++ b/build/tasks/testswarm.js @@ -20,7 +20,6 @@ var versions = { "Effects": "effects/effects.html", "Menu": "menu/menu.html", "Position": "position/position.html", - "Position_deprecated": "position/position_deprecated.html", "Progressbar": "progressbar/progressbar.html", //"resizable/resizable.html", //"selectable/selectable.html", diff --git a/demos/position/default.html b/demos/position/default.html index 223788b1fb..48fd07e35f 100644 --- a/demos/position/default.html +++ b/demos/position/default.html @@ -48,7 +48,6 @@ of: $( "#parent" ), my: $( "#my_horizontal" ).val() + " " + $( "#my_vertical" ).val(), at: $( "#at_horizontal" ).val() + " " + $( "#at_vertical" ).val(), - offset: $( "#offset" ).val(), collision: $( "#collision_horizontal" ).val() + " " + $( "#collision_vertical" ).val() }); } @@ -113,10 +112,6 @@
            -
            - offset: - -
            collision: +
            + + + + + From 039ee746d3eaeeaa4ad92ecd8ebf4e6fcd11768c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Zaefferer?= Date: Thu, 25 Oct 2012 20:47:22 -0400 Subject: [PATCH 088/151] Dialog: Visual test page for modal form dialogs --- tests/visual/dialog/form.html | 70 +++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 tests/visual/dialog/form.html diff --git a/tests/visual/dialog/form.html b/tests/visual/dialog/form.html new file mode 100644 index 0000000000..c974a500a4 --- /dev/null +++ b/tests/visual/dialog/form.html @@ -0,0 +1,70 @@ + + + + + Dialog Visual Test + + + + + + + + + + + + + + + + + + +

            WHAT: A modal dialog containing form fields, with groups to describe each section. A second modal dialog with just an input and some text markup.

            +

            EXPECTED: Dialog shows up, screenreader reads the dialog's title, the word "dialog" (or equivalent), the text before the first input (description of the first section) and the label of the first, focused input. When tabbing to the next group, the screenreader should announce the description of that group, along with the label of the focused field.

            +

            For the second dialog, the behaviour should be similar, except that the whole content is read as the description of the dialog, likely causing the input's label to be read twice.

            +

            NOTE: Using fieldset with legend seems to have the same result as using role="group" and aria-describedby. The latter needs an id-attribute, offers more flexibilty in markup order and has no built-in styling.

            + +
            +
            + Please share some personal information + + +
            +
            +

            Some more (optional) information

            + +
            +
            + + + +
            +

            Please enter password to continue.

            + +
            + + + + + From 68cab60fa758b34c024742daa9dbc3e6bf6a0521 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Fri, 26 Oct 2012 10:53:17 -0400 Subject: [PATCH 089/151] Removed bgiframe. --- demos/dialog/animated.html | 1 - demos/dialog/default.html | 1 - demos/dialog/modal-confirmation.html | 1 - demos/dialog/modal-form.html | 1 - demos/dialog/modal-message.html | 1 - demos/dialog/modal.html | 1 - external/jquery.bgiframe-2.1.2.js | 39 ------------------------ tests/unit/dialog/dialog.html | 1 - tests/visual/dialog/animated.html | 1 - tests/visual/dialog/complex-dialogs.html | 1 - tests/visual/dialog/form.html | 1 - tests/visual/dialog/performance.html | 1 - ui/jquery.ui.autocomplete.js | 4 --- ui/jquery.ui.dialog.js | 8 ----- ui/jquery.ui.position.js | 4 --- ui/jquery.ui.tooltip.js | 3 -- 16 files changed, 69 deletions(-) delete mode 100644 external/jquery.bgiframe-2.1.2.js diff --git a/demos/dialog/animated.html b/demos/dialog/animated.html index 808d0e926c..92d7b642db 100644 --- a/demos/dialog/animated.html +++ b/demos/dialog/animated.html @@ -5,7 +5,6 @@ jQuery UI Dialog - Animation - diff --git a/demos/dialog/default.html b/demos/dialog/default.html index 5dcb1a05c6..19cf912e29 100644 --- a/demos/dialog/default.html +++ b/demos/dialog/default.html @@ -5,7 +5,6 @@ jQuery UI Dialog - Default functionality - diff --git a/demos/dialog/modal-confirmation.html b/demos/dialog/modal-confirmation.html index cca3b296dd..b9bf6396ff 100644 --- a/demos/dialog/modal-confirmation.html +++ b/demos/dialog/modal-confirmation.html @@ -5,7 +5,6 @@ jQuery UI Dialog - Modal confirmation - diff --git a/demos/dialog/modal-form.html b/demos/dialog/modal-form.html index 48452f8629..1c0cd6fc3b 100644 --- a/demos/dialog/modal-form.html +++ b/demos/dialog/modal-form.html @@ -5,7 +5,6 @@ jQuery UI Dialog - Modal form - diff --git a/demos/dialog/modal-message.html b/demos/dialog/modal-message.html index d443310177..3c877b26e8 100644 --- a/demos/dialog/modal-message.html +++ b/demos/dialog/modal-message.html @@ -5,7 +5,6 @@ jQuery UI Dialog - Modal message - diff --git a/demos/dialog/modal.html b/demos/dialog/modal.html index 2b1ac25745..9bb6d95b24 100644 --- a/demos/dialog/modal.html +++ b/demos/dialog/modal.html @@ -5,7 +5,6 @@ jQuery UI Dialog - Basic modal - diff --git a/external/jquery.bgiframe-2.1.2.js b/external/jquery.bgiframe-2.1.2.js deleted file mode 100644 index 5cd38bb1d1..0000000000 --- a/external/jquery.bgiframe-2.1.2.js +++ /dev/null @@ -1,39 +0,0 @@ -/*! Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net) - * Licensed under the MIT License (LICENSE.txt). - * - * Version 2.1.2 - */ - -(function($){ - -$.fn.bgiframe = ($.browser.msie && /msie 6\.0/i.test(navigator.userAgent) ? function(s) { - s = $.extend({ - top : 'auto', // auto == .currentStyle.borderTopWidth - left : 'auto', // auto == .currentStyle.borderLeftWidth - width : 'auto', // auto == offsetWidth - height : 'auto', // auto == offsetHeight - opacity : true, - src : 'javascript:false;' - }, s); - var html = '' : ''); + html += buttonPanel; inst._keyEvent = false; return html; }, From 995eb1261e5e6bb57cad292a56911893d539472e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Fri, 26 Oct 2012 16:08:05 -0400 Subject: [PATCH 103/151] Core: Removed $.ui.ie6. --- ui/jquery.ui.core.js | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/jquery.ui.core.js b/ui/jquery.ui.core.js index 7b5590fc10..fadd42cad4 100644 --- a/ui/jquery.ui.core.js +++ b/ui/jquery.ui.core.js @@ -239,7 +239,6 @@ $.support.selectstart = "onselectstart" in document.createElement( "div" ); (function() { var uaMatch = /msie ([\w.]+)/.exec( navigator.userAgent.toLowerCase() ) || []; $.ui.ie = uaMatch.length ? true : false; - $.ui.ie6 = parseFloat( uaMatch[ 1 ], 10 ) === 6; })(); $.fn.extend({ From be51d5358609295c6827b6d54db95b648e8ce6fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Fri, 26 Oct 2012 16:32:50 -0400 Subject: [PATCH 104/151] Droppable demo: Removed IE6 CSS hack. --- demos/droppable/photo-manager.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/demos/droppable/photo-manager.html b/demos/droppable/photo-manager.html index 315473761f..7da5f53702 100644 --- a/demos/droppable/photo-manager.html +++ b/demos/droppable/photo-manager.html @@ -15,7 +15,7 @@ diff --git a/tests/unit/sortable/sortable_common.js b/tests/unit/sortable/sortable_common.js index ae21f7dd26..0a8e9f2b98 100644 --- a/tests/unit/sortable/sortable_common.js +++ b/tests/unit/sortable/sortable_common.js @@ -5,6 +5,7 @@ TestHelpers.commonWidgetTests( "sortable", { cancel: "input,textarea,button,select,option", connectWith: false, containment: false, + create: null, cursor: "auto", cursorAt: false, delay: 0, diff --git a/tests/unit/sortable/sortable_core.js b/tests/unit/sortable/sortable_core.js index 540e06f0f5..f036121b8e 100644 --- a/tests/unit/sortable/sortable_core.js +++ b/tests/unit/sortable/sortable_core.js @@ -4,10 +4,16 @@ (function($) { +TestHelpers.sortable = { + sort: function(handle, dx, dy, index, msg) { + $(handle).simulate("drag", { + dx: dx || 0, + dy: dy || 0 + }); + equal($(handle).parent().children().index(handle), index, msg); + } +}; + module("sortable: core"); -// this is here to make JSHint pass "unused", and we don't want to -// remove the parameter for when we finally implement -$.noop(); - })(jQuery); diff --git a/tests/unit/sortable/sortable_events.js b/tests/unit/sortable/sortable_events.js index 6ed54e1b6c..556f539e10 100644 --- a/tests/unit/sortable/sortable_events.js +++ b/tests/unit/sortable/sortable_events.js @@ -6,6 +6,7 @@ module("sortable: events"); test("start", function() { + expect( 7 ); var hash; $("#sortable") @@ -15,15 +16,18 @@ test("start", function() { ok(hash, 'start event triggered'); ok(hash.helper, 'UI hash includes: helper'); ok(hash.placeholder, 'UI hash includes: placeholder'); - ok(hash.position && (hash.position.top && hash.position.left), 'UI hash includes: position'); - ok(hash.offset && (hash.offset.top && hash.offset.left), 'UI hash includes: offset'); ok(hash.item, 'UI hash includes: item'); ok(!hash.sender, 'UI hash does not include: sender'); + // todo: see if these events should actually have sane values in them + ok('position' in hash, 'UI hash includes: position'); + ok('offset' in hash, 'UI hash includes: offset'); + }); test("sort", function() { + expect( 7 ); var hash; $("#sortable") @@ -33,7 +37,7 @@ test("sort", function() { ok(hash, 'sort event triggered'); ok(hash.helper, 'UI hash includes: helper'); ok(hash.placeholder, 'UI hash includes: placeholder'); - ok(hash.position && (hash.position.top && hash.position.left), 'UI hash includes: position'); + ok(hash.position && ('top' in hash.position && 'left' in hash.position), 'UI hash includes: position'); ok(hash.offset && (hash.offset.top && hash.offset.left), 'UI hash includes: offset'); ok(hash.item, 'UI hash includes: item'); ok(!hash.sender, 'UI hash does not include: sender'); @@ -41,6 +45,7 @@ test("sort", function() { }); test("change", function() { + expect( 8 ); var hash; $("#sortable") @@ -51,12 +56,12 @@ test("change", function() { $("#sortable") .sortable({ change: function(e, ui) { hash = ui; } }) - .find('li:eq(0)').simulate("drag", { dx: 0, dy: 20 }); + .find('li:eq(0)').simulate("drag", { dx: 0, dy: 22 }); ok(hash, 'change event triggered'); ok(hash.helper, 'UI hash includes: helper'); ok(hash.placeholder, 'UI hash includes: placeholder'); - ok(hash.position && (hash.position.top && hash.position.left), 'UI hash includes: position'); + ok(hash.position && ('top' in hash.position && 'left' in hash.position), 'UI hash includes: position'); ok(hash.offset && (hash.offset.top && hash.offset.left), 'UI hash includes: offset'); ok(hash.item, 'UI hash includes: item'); ok(!hash.sender, 'UI hash does not include: sender'); @@ -64,6 +69,7 @@ test("change", function() { }); test("beforeStop", function() { + expect( 7 ); var hash; $("#sortable") @@ -73,7 +79,7 @@ test("beforeStop", function() { ok(hash, 'beforeStop event triggered'); ok(hash.helper, 'UI hash includes: helper'); ok(hash.placeholder, 'UI hash includes: placeholder'); - ok(hash.position && (hash.position.top && hash.position.left), 'UI hash includes: position'); + ok(hash.position && ('top' in hash.position && 'left' in hash.position), 'UI hash includes: position'); ok(hash.offset && (hash.offset.top && hash.offset.left), 'UI hash includes: offset'); ok(hash.item, 'UI hash includes: item'); ok(!hash.sender, 'UI hash does not include: sender'); @@ -81,6 +87,7 @@ test("beforeStop", function() { }); test("stop", function() { + expect( 7 ); var hash; $("#sortable") @@ -90,7 +97,7 @@ test("stop", function() { ok(hash, 'stop event triggered'); ok(!hash.helper, 'UI should not include: helper'); ok(hash.placeholder, 'UI hash includes: placeholder'); - ok(hash.position && (hash.position.top && hash.position.left), 'UI hash includes: position'); + ok(hash.position && ('top' in hash.position && 'left' in hash.position), 'UI hash includes: position'); ok(hash.offset && (hash.offset.top && hash.offset.left), 'UI hash includes: offset'); ok(hash.item, 'UI hash includes: item'); ok(!hash.sender, 'UI hash does not include: sender'); @@ -98,6 +105,7 @@ test("stop", function() { }); test("update", function() { + expect( 8 ); var hash; $("#sortable") @@ -108,18 +116,19 @@ test("update", function() { $("#sortable") .sortable({ update: function(e, ui) { hash = ui; } }) - .find('li:eq(0)').simulate("drag", { dx: 0, dy: 20 }); + .find('li:eq(0)').simulate("drag", { dx: 0, dy: 22 }); ok(hash, 'update event triggered'); ok(!hash.helper, 'UI hash should not include: helper'); ok(hash.placeholder, 'UI hash includes: placeholder'); - ok(hash.position && (hash.position.top && hash.position.left), 'UI hash includes: position'); + ok(hash.position && ('top' in hash.position && 'left' in hash.position), 'UI hash includes: position'); ok(hash.offset && (hash.offset.top && hash.offset.left), 'UI hash includes: offset'); ok(hash.item, 'UI hash includes: item'); ok(!hash.sender, 'UI hash does not include: sender'); }); +/* test("receive", function() { ok(false, "missing test - untested code is broken code."); }); @@ -143,5 +152,6 @@ test("activate", function() { test("deactivate", function() { ok(false, "missing test - untested code is broken code."); }); +*/ })(jQuery); diff --git a/tests/unit/sortable/sortable_methods.js b/tests/unit/sortable/sortable_methods.js index c2a0b95481..85b418ac83 100644 --- a/tests/unit/sortable/sortable_methods.js +++ b/tests/unit/sortable/sortable_methods.js @@ -3,27 +3,10 @@ */ (function($) { -var el, offsetBefore, offsetAfter, dragged; - -function drag(handle, dx, dy) { - offsetBefore = $(handle).offset(); - $(handle).simulate("drag", { - dx: dx || 0, - dy: dy || 0 - }); - dragged = { dx: dx, dy: dy }; - offsetAfter = $(handle).offset(); -} - -function sort(handle, dx, dy, index, msg) { - drag(handle, dx, dy); - equal($(handle).parent().children().index(handle), index, msg); -} - module("sortable: methods"); test("init", function() { - expect(6); + expect(5); $("
            ").appendTo('body').sortable().remove(); ok(true, '.sortable() called on element'); @@ -34,9 +17,6 @@ test("init", function() { $("
            ").sortable(); ok(true, '.sortable() called on disconnected DOMElement'); - $("
            ").sortable().sortable("foo"); - ok(true, 'arbitrary method called after init'); - $("
            ").sortable().sortable("option", "foo"); ok(true, 'arbitrary option getter after init'); @@ -45,6 +25,7 @@ test("init", function() { }); test("destroy", function() { + expect(4); $("
            ").appendTo('body').sortable().sortable("destroy").remove(); ok(true, '.sortable("destroy") called on element'); @@ -54,9 +35,6 @@ test("destroy", function() { $("
            ").sortable().sortable("destroy"); ok(true, '.sortable("destroy") called on disconnected DOMElement'); - $("
            ").sortable().sortable("destroy").sortable("foo"); - ok(true, 'arbitrary method called after destroy'); - var expected = $('
            ').sortable(), actual = expected.sortable('destroy'); equal(actual, expected, 'destroy is chainable'); @@ -66,7 +44,7 @@ test("enable", function() { expect(5); el = $("#sortable").sortable({ disabled: true }); - sort($("li", el)[0], 0, 40, 0, '.sortable({ disabled: true })'); + TestHelpers.sortable.sort($("li", el)[0], 0, 44, 0, '.sortable({ disabled: true })'); el.sortable("enable"); equal(el.sortable("option", "disabled"), false, "disabled option getter"); @@ -76,7 +54,7 @@ test("enable", function() { el.sortable("option", "disabled", false); equal(el.sortable("option", "disabled"), false, "disabled option setter"); - sort($("li", el)[0], 0, 40, 2, '.sortable("option", "disabled", false)'); + TestHelpers.sortable.sort($("li", el)[0], 0, 44, 2, '.sortable("option", "disabled", false)'); var expected = $('
            ').sortable(), actual = expected.sortable('enable'); @@ -86,19 +64,19 @@ test("enable", function() { test("disable", function() { expect(7); el = $("#sortable").sortable({ disabled: false }); - sort($("li", el)[0], 0, 40, 2, '.sortable({ disabled: false })'); + TestHelpers.sortable.sort($("li", el)[0], 0, 44, 2, '.sortable({ disabled: false })'); el.sortable("disable"); - sort($("li", el)[0], 0, 40, 0, 'disabled.sortable getter'); + TestHelpers.sortable.sort($("li", el)[0], 0, 44, 0, 'disabled.sortable getter'); el.sortable("destroy"); el.sortable({ disabled: false }); - sort($("li", el)[0], 0, 40, 2, '.sortable({ disabled: false })'); + TestHelpers.sortable.sort($("li", el)[0], 0, 44, 2, '.sortable({ disabled: false })'); el.sortable("option", "disabled", true); equal(el.sortable("option", "disabled"), true, "disabled option setter"); ok(el.sortable("widget").is(":not(.ui-state-disabled)"), "sortable element does not get ui-state-disabled since it's an interaction"); - sort($("li", el)[0], 0, 40, 0, '.sortable("option", "disabled", true)'); + TestHelpers.sortable.sort($("li", el)[0], 0, 44, 0, '.sortable("option", "disabled", true)'); var expected = $('
            ').sortable(), actual = expected.sortable('disable'); diff --git a/tests/unit/sortable/sortable_options.js b/tests/unit/sortable/sortable_options.js index d5d7b3de11..cf35aedb1d 100644 --- a/tests/unit/sortable/sortable_options.js +++ b/tests/unit/sortable/sortable_options.js @@ -9,6 +9,7 @@ module("sortable: options"); // remove the parameter for when we finally implement $.noop(); +/* test("{ appendTo: 'parent' }, default", function() { ok(false, "missing test - untested code is broken code."); }); @@ -256,5 +257,5 @@ test("{ zIndex: 1 }", function() { test("{ zIndex: false }", function() { ok(false, "missing test - untested code is broken code."); }); - +*/ })(jQuery); diff --git a/tests/unit/sortable/sortable_tickets.js b/tests/unit/sortable/sortable_tickets.js index 14bb705eaa..c8ec08502c 100644 --- a/tests/unit/sortable/sortable_tickets.js +++ b/tests/unit/sortable/sortable_tickets.js @@ -3,26 +3,10 @@ */ (function($) { -var el, offsetBefore, offsetAfter, dragged; - -function drag(handle, dx, dy) { - offsetBefore = $(handle).offset(); - $(handle).simulate("drag", { - dx: dx || 0, - dy: dy || 0 - }); - dragged = { dx: dx, dy: dy }; - offsetAfter = $(handle).offset(); -} - -function sort(handle, dx, dy, index, msg) { - drag(handle, dx, dy); - equal($(handle).parent().children().index(handle), index, msg); -} - module("sortable: tickets"); test("#3019: Stop fires too early", function() { + expect(2); var helper = null; el = $("#sortable").sortable({ @@ -31,19 +15,21 @@ test("#3019: Stop fires too early", function() { } }); - sort($("li", el)[0], 0, 40, 2, 'Dragging the sortable'); + TestHelpers.sortable.sort($("li", el)[0], 0, 44, 2, 'Dragging the sortable'); equal(helper, null, "helper should be false"); }); test('#4752: link event firing on sortable with connect list', function () { + expect( 10 ); + var fired = {}, hasFired = function (type) { return (type in fired) && (true === fired[type]); }; $('#sortable').clone().attr('id', 'sortable2').insertAfter('#sortable'); - $('#main ul').sortable({ - connectWith: '#main ul', + $('#qunit-fixture ul').sortable({ + connectWith: '#qunit-fixture ul', change: function () { fired.change = true; }, @@ -55,7 +41,7 @@ test('#4752: link event firing on sortable with connect list', function () { } }); - $('#main ul li').live('click.ui-sortable-test', function () { + $('#qunit-fixture ul').bind('click.ui-sortable-test', function () { fired.click = true; }); diff --git a/ui/jquery.ui.sortable.js b/ui/jquery.ui.sortable.js index a2132a9bdc..a95c80c68d 100644 --- a/ui/jquery.ui.sortable.js +++ b/ui/jquery.ui.sortable.js @@ -15,6 +15,7 @@ */ (function( $, undefined ) { +/*jshint onevar: false, curly: false, eqeqeq: false, laxbreak: true, shadow: true, loopfunc: true */ $.widget("ui.sortable", $.ui.mouse, { version: "@VERSION", widgetEventPrefix: "sort", @@ -62,7 +63,7 @@ $.widget("ui.sortable", $.ui.mouse, { this._mouseInit(); //We're ready to go - this.ready = true + this.ready = true; }, @@ -101,7 +102,9 @@ $.widget("ui.sortable", $.ui.mouse, { this._refreshItems(event); //Find out if the clicked node (or one of its parents) is a actual item in this.items - var currentItem = null, nodes = $(event.target).parents().each(function() { + var currentItem = null; + + $(event.target).parents().each(function() { if($.data(this, that.widgetName + '-item') == that) { currentItem = $(this); return false; @@ -221,7 +224,7 @@ $.widget("ui.sortable", $.ui.mouse, { //Post 'activate' events to possible containers if(!noActivation) { - for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, this._uiHash(this)); } + for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, this._uiHash(this)); } } //Prepare possible droppables @@ -418,7 +421,7 @@ $.widget("ui.sortable", $.ui.mouse, { var str = []; o = o || {}; $(items).each(function() { - var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/)); + var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[\-=_](.+)/)); if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2])); }); @@ -458,7 +461,7 @@ $.widget("ui.sortable", $.ui.mouse, { var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r; - if( this.options.tolerance == "pointer" + if (this.options.tolerance == "pointer" || this.options.forcePointerForContainers || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height']) ) { @@ -507,12 +510,12 @@ $.widget("ui.sortable", $.ui.mouse, { _getDragVerticalDirection: function() { var delta = this.positionAbs.top - this.lastPositionAbs.top; - return delta != 0 && (delta > 0 ? "down" : "up"); + return delta !== 0 && (delta > 0 ? "down" : "up"); }, _getDragHorizontalDirection: function() { var delta = this.positionAbs.left - this.lastPositionAbs.left; - return delta != 0 && (delta > 0 ? "right" : "left"); + return delta !== 0 && (delta > 0 ? "right" : "left"); }, refresh: function(event) { @@ -542,8 +545,8 @@ $.widget("ui.sortable", $.ui.mouse, { if(inst && inst != this && !inst.options.disabled) { queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]); } - }; - }; + } + } } queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]); @@ -552,7 +555,7 @@ $.widget("ui.sortable", $.ui.mouse, { queries[i][0].each(function() { items.push(this); }); - }; + } return $(items); @@ -566,7 +569,7 @@ $.widget("ui.sortable", $.ui.mouse, { for (var j=0; j < list.length; j++) { if(list[j] == item.item[0]) return false; - }; + } return true; }); @@ -589,8 +592,8 @@ $.widget("ui.sortable", $.ui.mouse, { queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); this.containers.push(inst); } - }; - }; + } + } } for (var i = queries.length - 1; i >= 0; i--) { @@ -608,8 +611,8 @@ $.widget("ui.sortable", $.ui.mouse, { width: 0, height: 0, left: 0, top: 0 }); - }; - }; + } + } }, @@ -637,7 +640,7 @@ $.widget("ui.sortable", $.ui.mouse, { var p = t.offset(); item.left = p.left; item.top = p.top; - }; + } if(this.options.custom && this.options.custom.refreshContainers) { this.options.custom.refreshContainers.call(this); @@ -648,7 +651,7 @@ $.widget("ui.sortable", $.ui.mouse, { this.containers[i].containerCache.top = p.top; this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); - }; + } } return this; @@ -679,8 +682,8 @@ $.widget("ui.sortable", $.ui.mouse, { if(className && !o.forcePlaceholderSize) return; //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item - if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css('paddingTop')||0, 10) - parseInt(that.currentItem.css('paddingBottom')||0, 10)); }; - if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css('paddingLeft')||0, 10) - parseInt(that.currentItem.css('paddingRight')||0, 10)); }; + if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css('paddingTop')||0, 10) - parseInt(that.currentItem.css('paddingBottom')||0, 10)); } + if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css('paddingLeft')||0, 10) - parseInt(that.currentItem.css('paddingRight')||0, 10)); } } }; } @@ -786,8 +789,8 @@ $.widget("ui.sortable", $.ui.mouse, { if(helper[0] == this.currentItem[0]) this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") }; - if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width()); - if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height()); + if(!helper[0].style.width || o.forceHelperSize) helper.width(this.currentItem.width()); + if(!helper[0].style.height || o.forceHelperSize) helper.height(this.currentItem.height()); return helper; @@ -899,7 +902,7 @@ $.widget("ui.sortable", $.ui.mouse, { if(!pos) pos = this.position; var mod = d == "absolute" ? 1 : -1; - var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + var scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); return { top: ( @@ -949,10 +952,10 @@ $.widget("ui.sortable", $.ui.mouse, { if(o.grid) { var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; - pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; + pageY = this.containment ? ( (top - this.offset.click.top >= this.containment[1] && top - this.offset.click.top <= this.containment[3]) ? top : ((top - this.offset.click.top >= this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; - pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; + pageX = this.containment ? ( (left - this.offset.click.left >= this.containment[0] && left - this.offset.click.left <= this.containment[2]) ? left : ((left - this.offset.click.left >= this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; } } @@ -1047,7 +1050,9 @@ $.widget("ui.sortable", $.ui.mouse, { if(this.cancelHelperRemoval) { if(!noPropagation) { this._trigger("beforeStop", event, this._uiHash()); - for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events + for (var i=0; i < delayedTriggers.length; i++) { + delayedTriggers[i].call(this, event); + } //Trigger all delayed events this._trigger("stop", event, this._uiHash()); } @@ -1063,7 +1068,9 @@ $.widget("ui.sortable", $.ui.mouse, { if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null; if(!noPropagation) { - for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events + for (var i=0; i < delayedTriggers.length; i++) { + delayedTriggers[i].call(this, event); + } //Trigger all delayed events this._trigger("stop", event, this._uiHash()); } From 3df9ea29e644a3dd6345161513dae5823d9b0460 Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Sat, 3 Nov 2012 16:17:16 -0400 Subject: [PATCH 115/151] Dev: remove globals from tests and moved test helpers to correct location - Fixed #8770 Dev: Remove globals and Standardize Test Suite --- tests/.jshintrc | 15 -- tests/unit/datepicker/datepicker.html | 1 + tests/unit/datepicker/datepicker_core.js | 130 ++++------ tests/unit/datepicker/datepicker_events.js | 10 +- tests/unit/datepicker/datepicker_methods.js | 38 +-- tests/unit/datepicker/datepicker_options.js | 216 ++++++++-------- .../datepicker/datepicker_test_helpers.js | 22 ++ tests/unit/datepicker/datepicker_tickets.js | 8 +- tests/unit/dialog/dialog.html | 1 + tests/unit/dialog/dialog_core.js | 91 +------ tests/unit/dialog/dialog_events.js | 238 +++++++++--------- tests/unit/dialog/dialog_methods.js | 28 ++- tests/unit/dialog/dialog_options.js | 189 +++++++------- tests/unit/dialog/dialog_test_helpers.js | 45 ++++ tests/unit/dialog/dialog_tickets.js | 35 +-- tests/unit/draggable/draggable.html | 1 + tests/unit/draggable/draggable_core.js | 77 +----- tests/unit/draggable/draggable_events.js | 44 ++-- tests/unit/draggable/draggable_methods.js | 14 +- tests/unit/draggable/draggable_options.js | 226 +++++++++-------- .../unit/draggable/draggable_test_helpers.js | 57 +++++ tests/unit/droppable/droppable.html | 1 + tests/unit/droppable/droppable_core.js | 11 - tests/unit/droppable/droppable_methods.js | 14 +- tests/unit/droppable/droppable_options.js | 4 +- .../unit/droppable/droppable_test_helpers.js | 10 + tests/unit/resizable/resizable.html | 1 + tests/unit/resizable/resizable_core.js | 16 -- .../unit/resizable/resizable_test_helpers.js | 15 ++ tests/unit/selectable/selectable.html | 1 + tests/unit/selectable/selectable_core.js | 15 +- .../selectable/selectable_test_helpers.js | 12 + tests/unit/sortable/sortable.html | 1 + tests/unit/sortable/sortable_core.js | 18 +- tests/unit/sortable/sortable_methods.js | 14 +- tests/unit/sortable/sortable_test_helpers.js | 9 + tests/unit/sortable/sortable_tickets.js | 12 +- 37 files changed, 821 insertions(+), 819 deletions(-) create mode 100644 tests/unit/datepicker/datepicker_test_helpers.js create mode 100644 tests/unit/dialog/dialog_test_helpers.js create mode 100644 tests/unit/draggable/draggable_test_helpers.js create mode 100644 tests/unit/droppable/droppable_test_helpers.js create mode 100644 tests/unit/resizable/resizable_test_helpers.js create mode 100644 tests/unit/selectable/selectable_test_helpers.js create mode 100644 tests/unit/sortable/sortable_test_helpers.js diff --git a/tests/.jshintrc b/tests/.jshintrc index c0f0f8d532..9e2881c124 100644 --- a/tests/.jshintrc +++ b/tests/.jshintrc @@ -14,27 +14,13 @@ "unused": true, "predef": [ "asyncTest", - "container", "deepEqual", - "d1", - "d2", - "dlg", "domEqual", - "drag", - "dragged", - "el", "equal", - "equalsDate", "expect", "Globalize", - "heightAfter", - "init", - "modal", "module", - "moved", "notEqual", - "offsetAfter", - "offsetBefore", "ok", "QUnit", "start", @@ -42,7 +28,6 @@ "stop", "test", "TestHelpers", - "widthAfter", "JSHINT" ] } \ No newline at end of file diff --git a/tests/unit/datepicker/datepicker.html b/tests/unit/datepicker/datepicker.html index 9530600f14..c0c68979d5 100644 --- a/tests/unit/datepicker/datepicker.html +++ b/tests/unit/datepicker/datepicker.html @@ -27,6 +27,7 @@ + diff --git a/tests/unit/datepicker/datepicker_core.js b/tests/unit/datepicker/datepicker_core.js index 1a7d8cc827..86f71a1c4f 100644 --- a/tests/unit/datepicker/datepicker_core.js +++ b/tests/unit/datepicker/datepicker_core.js @@ -2,30 +2,6 @@ * datepicker_core.js */ -function equalsDate(d1, d2, message) { - if (!d1 || !d2) { - ok(false, message + ' - missing date'); - return; - } - d1 = new Date(d1.getFullYear(), d1.getMonth(), d1.getDate()); - d2 = new Date(d2.getFullYear(), d2.getMonth(), d2.getDate()); - equal(d1.toString(), d2.toString(), message); -} - -TestHelpers.addMonths = function(date, offset) { - var maxDay = 32 - new Date(date.getFullYear(), date.getMonth() + offset, 32).getDate(); - date.setDate(Math.min(date.getDate(), maxDay)); - date.setMonth(date.getMonth() + offset); - return date; -}; - -function init(id, options) { - $.datepicker.setDefaults($.datepicker.regional['']); - return $(id).datepicker($.extend({showAnim: ''}, options || {})); -} - -TestHelpers.PROP_NAME = 'datepicker'; - (function($) { module("datepicker: core"); @@ -45,7 +21,7 @@ test("widget method", function() { test('baseStructure', function() { expect( 58 ); var header, title, table, thead, week, panel, inl, child, - inp = init('#inp').focus(), + inp = TestHelpers.datepicker.init('#inp').focus(), dp = $('#ui-datepicker-div'); ok(dp.is(':visible'), 'Structure - datepicker visible'); ok(!dp.is('.ui-datepicker-rtl'), 'Structure - not right-to-left'); @@ -80,7 +56,7 @@ test('baseStructure', function() { inp.datepicker('hide').datepicker('destroy'); // Editable month/year and button panel - inp = init('#inp', {changeMonth: true, changeYear: true, showButtonPanel: true}); + inp = TestHelpers.datepicker.init('#inp', {changeMonth: true, changeYear: true, showButtonPanel: true}); inp.focus(); title = dp.find('div.ui-datepicker-title'); @@ -95,7 +71,7 @@ test('baseStructure', function() { inp.datepicker('hide').datepicker('destroy'); // Multi-month 2 - inp = init('#inp', {numberOfMonths: 2}); + inp = TestHelpers.datepicker.init('#inp', {numberOfMonths: 2}); inp.focus(); ok(dp.is('.ui-datepicker-multi'), 'Structure multi [2] - multi-month'); equal(dp.children().length, 3, 'Structure multi [2] - child count'); @@ -109,14 +85,14 @@ test('baseStructure', function() { inp.datepicker('hide').datepicker('destroy'); // Multi-month 3 - inp = init('#inp', {numberOfMonths: 3}); + inp = TestHelpers.datepicker.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 = TestHelpers.datepicker.init('#inp', {numberOfMonths: [2, 2]}); inp.focus(); ok(dp.is('.ui-datepicker-multi'), 'Structure multi - multi-month'); equal(dp.children().length, 6, 'Structure multi [2,2] - child count'); @@ -135,7 +111,7 @@ test('baseStructure', function() { inp.datepicker('hide').datepicker('destroy'); // Inline - inl = init('#inl'); + inl = TestHelpers.datepicker.init('#inl'); dp = inl.children(); ok(dp.is('.ui-datepicker-inline'), 'Structure inline - main div'); ok(!dp.is('.ui-datepicker-rtl'), 'Structure inline - not right-to-left'); @@ -151,7 +127,7 @@ test('baseStructure', function() { inl.datepicker('destroy'); // Inline multi-month - inl = init('#inl', {numberOfMonths: 2}); + inl = TestHelpers.datepicker.init('#inl', {numberOfMonths: 2}); dp = inl.children(); ok(dp.is('.ui-datepicker-inline') && dp.is('.ui-datepicker-multi'), 'Structure inline multi - main div'); equal(dp.children().length, 3, 'Structure inline multi - child count'); @@ -169,7 +145,7 @@ test('customStructure', function() { var header, panel, title, thead, dp = $('#ui-datepicker-div'), // Check right-to-left localisation - inp = init('#inp', $.datepicker.regional.he); + inp = TestHelpers.datepicker.init('#inp', $.datepicker.regional.he); inp.data('showButtonPanel.datepicker',true); inp.focus(); ok(dp.is('.ui-datepicker-rtl'), 'Structure RTL - right-to-left'); @@ -186,7 +162,7 @@ test('customStructure', function() { inp.datepicker('hide').datepicker('destroy'); // Hide prev/next - inp = init('#inp', {hideIfNoPrevNext: true, minDate: new Date(2008, 2 - 1, 4), maxDate: new Date(2008, 2 - 1, 14)}); + inp = TestHelpers.datepicker.init('#inp', {hideIfNoPrevNext: true, minDate: new Date(2008, 2 - 1, 4), maxDate: new Date(2008, 2 - 1, 14)}); inp.val('02/10/2008').focus(); header = dp.children(':first'); ok(header.is('div.ui-datepicker-header'), 'Structure hide prev/next - header division'); @@ -195,7 +171,7 @@ test('customStructure', function() { inp.datepicker('hide').datepicker('destroy'); // Changeable Month with read-only year - inp = init('#inp', {changeMonth: true}); + inp = TestHelpers.datepicker.init('#inp', {changeMonth: true}); inp.focus(); title = dp.children(':first').children(':last'); equal(title.children().length, 2, 'Structure changeable month - title child count'); @@ -204,7 +180,7 @@ test('customStructure', function() { inp.datepicker('hide').datepicker('destroy'); // Changeable year with read-only month - inp = init('#inp', {changeYear: true}); + inp = TestHelpers.datepicker.init('#inp', {changeYear: true}); inp.focus(); title = dp.children(':first').children(':last'); equal(title.children().length, 2, 'Structure changeable year - title child count'); @@ -213,7 +189,7 @@ test('customStructure', function() { inp.datepicker('hide').datepicker('destroy'); // Read-only first day of week - inp = init('#inp', {changeFirstDay: false}); + inp = TestHelpers.datepicker.init('#inp', {changeFirstDay: false}); inp.focus(); thead = dp.find('.ui-datepicker-calendar thead tr'); equal(thead.children().length, 7, 'Structure read-only first day - thead child count'); @@ -223,19 +199,19 @@ test('customStructure', function() { test('keystrokes', function() { expect( 26 ); - var inp = init('#inp'), + var inp = TestHelpers.datepicker.init('#inp'), date = new Date(); inp.val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), date, 'Keystroke enter'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Keystroke enter'); inp.val('02/04/2008').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 4), + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 4), 'Keystroke enter - preset'); inp.val('02/04/2008').datepicker('show'). simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.HOME}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), date, 'Keystroke ctrl+home'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Keystroke ctrl+home'); inp.val('02/04/2008').datepicker('show'). simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.END}); ok(inp.datepicker('getDate') == null, 'Keystroke ctrl+end'); @@ -244,95 +220,95 @@ test('keystrokes', function() { ok(inp.datepicker('getDate') == null, 'Keystroke esc'); inp.val('02/04/2008').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ESCAPE}); - equalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 4), + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 4), 'Keystroke esc - preset'); inp.val('02/04/2008').datepicker('show'). simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}). simulate('keydown', {keyCode: $.ui.keyCode.ESCAPE}); - equalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 4), + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 4), 'Keystroke esc - abandoned'); // Moving by day or week inp.val('').datepicker('show'). simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.LEFT}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); date.setDate(date.getDate() - 1); - equalsDate(inp.datepicker('getDate'), date, 'Keystroke ctrl+left'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Keystroke ctrl+left'); inp.val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.LEFT}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); date.setDate(date.getDate() + 1); - equalsDate(inp.datepicker('getDate'), date, 'Keystroke left'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Keystroke left'); inp.val('').datepicker('show'). simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.RIGHT}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); date.setDate(date.getDate() + 1); - equalsDate(inp.datepicker('getDate'), date, 'Keystroke ctrl+right'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Keystroke ctrl+right'); inp.val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.RIGHT}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); date.setDate(date.getDate() - 1); - equalsDate(inp.datepicker('getDate'), date, 'Keystroke right'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Keystroke right'); inp.val('').datepicker('show'). simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.UP}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); date.setDate(date.getDate() - 7); - equalsDate(inp.datepicker('getDate'), date, 'Keystroke ctrl+up'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Keystroke ctrl+up'); inp.val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.UP}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); date.setDate(date.getDate() + 7); - equalsDate(inp.datepicker('getDate'), date, 'Keystroke up'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Keystroke up'); inp.val('').datepicker('show'). simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.DOWN}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); date.setDate(date.getDate() + 7); - equalsDate(inp.datepicker('getDate'), date, 'Keystroke ctrl+down'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Keystroke ctrl+down'); inp.val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.DOWN}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); date.setDate(date.getDate() - 7); - equalsDate(inp.datepicker('getDate'), date, 'Keystroke down'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Keystroke down'); // Moving by month or year inp.val('02/04/2008').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.PAGE_UP}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), new Date(2008, 1 - 1, 4), + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2008, 1 - 1, 4), 'Keystroke pgup'); inp.val('02/04/2008').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.PAGE_DOWN}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), new Date(2008, 3 - 1, 4), + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2008, 3 - 1, 4), 'Keystroke pgdn'); inp.val('02/04/2008').datepicker('show'). simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), new Date(2007, 2 - 1, 4), + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2007, 2 - 1, 4), 'Keystroke ctrl+pgup'); inp.val('02/04/2008').datepicker('show'). simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), new Date(2009, 2 - 1, 4), + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2009, 2 - 1, 4), 'Keystroke ctrl+pgdn'); // Check for moving to short months inp.val('03/31/2008').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.PAGE_UP}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 29), + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 29), 'Keystroke pgup - Feb'); inp.val('01/30/2008').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.PAGE_DOWN}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 29), + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 29), 'Keystroke pgdn - Feb'); inp.val('02/29/2008').datepicker('show'). simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), new Date(2007, 2 - 1, 28), + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2007, 2 - 1, 28), 'Keystroke ctrl+pgup - Feb'); inp.val('02/29/2008').datepicker('show'). simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), new Date(2009, 2 - 1, 28), + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2009, 2 - 1, 28), 'Keystroke ctrl+pgdn - Feb'); // Goto current inp.datepicker('option', {gotoCurrent: true}). @@ -340,35 +316,35 @@ test('keystrokes', function() { simulate('keydown', {keyCode: $.ui.keyCode.PAGE_DOWN}). simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.HOME}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 4), + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 4), 'Keystroke ctrl+home'); // Change steps inp.datepicker('option', {stepMonths: 2, gotoCurrent: false}). datepicker('hide').val('02/04/2008').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.PAGE_UP}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), new Date(2007, 12 - 1, 4), + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2007, 12 - 1, 4), 'Keystroke pgup step 2'); inp.val('02/04/2008').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.PAGE_DOWN}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), new Date(2008, 4 - 1, 4), + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2008, 4 - 1, 4), 'Keystroke pgdn step 2'); }); test('mouse', function() { expect( 15 ); var inl, - inp = init('#inp'), + inp = TestHelpers.datepicker.init('#inp'), dp = $('#ui-datepicker-div'), date = new Date(); inp.val('').datepicker('show'); $('.ui-datepicker-calendar tbody a:contains(10)', dp).simulate('click', {}); date.setDate(10); - equalsDate(inp.datepicker('getDate'), date, 'Mouse click'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Mouse click'); inp.val('02/04/2008').datepicker('show'); $('.ui-datepicker-calendar tbody a:contains(12)', dp).simulate('click', {}); - equalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 12), + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 12), 'Mouse click - preset'); inp.val('02/04/2008').datepicker('show'); inp.val('').datepicker('show'); @@ -376,66 +352,66 @@ test('mouse', function() { ok(inp.datepicker('getDate') == null, 'Mouse click - close'); inp.val('02/04/2008').datepicker('show'); $('button.ui-datepicker-close', dp).simulate('click', {}); - equalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 4), + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 4), 'Mouse click - close + preset'); inp.val('02/04/2008').datepicker('show'); $('a.ui-datepicker-prev', dp).simulate('click', {}); $('button.ui-datepicker-close', dp).simulate('click', {}); - equalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 4), + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 4), 'Mouse click - abandoned'); // Current/previous/next inp.val('02/04/2008').datepicker('option', {showButtonPanel: true}).datepicker('show'); $('.ui-datepicker-current', dp).simulate('click', {}); $('.ui-datepicker-calendar tbody a:contains(14)', dp).simulate('click', {}); date.setDate(14); - equalsDate(inp.datepicker('getDate'), date, 'Mouse click - current'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Mouse click - current'); inp.val('02/04/2008').datepicker('show'); $('.ui-datepicker-prev', dp).simulate('click'); $('.ui-datepicker-calendar tbody a:contains(16)', dp).simulate('click'); - equalsDate(inp.datepicker('getDate'), new Date(2008, 1 - 1, 16), + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2008, 1 - 1, 16), 'Mouse click - previous'); inp.val('02/04/2008').datepicker('show'); $('.ui-datepicker-next', dp).simulate('click'); $('.ui-datepicker-calendar tbody a:contains(18)', dp).simulate('click'); - equalsDate(inp.datepicker('getDate'), new Date(2008, 3 - 1, 18), + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2008, 3 - 1, 18), 'Mouse click - next'); // Previous/next with minimum/maximum inp.datepicker('option', {minDate: new Date(2008, 2 - 1, 2), maxDate: new Date(2008, 2 - 1, 26)}).val('02/04/2008').datepicker('show'); $('.ui-datepicker-prev', dp).simulate('click'); $('.ui-datepicker-calendar tbody a:contains(16)', dp).simulate('click'); - equalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 16), + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 16), 'Mouse click - previous + min/max'); inp.val('02/04/2008').datepicker('show'); $('.ui-datepicker-next', dp).simulate('click'); $('.ui-datepicker-calendar tbody a:contains(18)', dp).simulate('click'); - equalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 18), + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2008, 2 - 1, 18), 'Mouse click - next + min/max'); // Inline - inl = init('#inl'); + inl = TestHelpers.datepicker.init('#inl'); dp = $('.ui-datepicker-inline', inl); date = new Date(); inl.datepicker('setDate', date); $('.ui-datepicker-calendar tbody a:contains(10)', dp).simulate('click', {}); date.setDate(10); - equalsDate(inl.datepicker('getDate'), date, 'Mouse click inline'); + TestHelpers.datepicker.equalsDate(inl.datepicker('getDate'), date, 'Mouse click inline'); inl.datepicker('option', {showButtonPanel: true}).datepicker('setDate', new Date(2008, 2 - 1, 4)); $('.ui-datepicker-calendar tbody a:contains(12)', dp).simulate('click', {}); - equalsDate(inl.datepicker('getDate'), new Date(2008, 2 - 1, 12), 'Mouse click inline - preset'); + TestHelpers.datepicker.equalsDate(inl.datepicker('getDate'), new Date(2008, 2 - 1, 12), 'Mouse click inline - preset'); inl.datepicker('option', {showButtonPanel: true}); $('.ui-datepicker-current', dp).simulate('click', {}); $('.ui-datepicker-calendar tbody a:contains(14)', dp).simulate('click', {}); date.setDate(14); - equalsDate(inl.datepicker('getDate'), date, 'Mouse click inline - current'); + TestHelpers.datepicker.equalsDate(inl.datepicker('getDate'), date, 'Mouse click inline - current'); inl.datepicker('setDate', new Date(2008, 2 - 1, 4)); $('.ui-datepicker-prev', dp).simulate('click'); $('.ui-datepicker-calendar tbody a:contains(16)', dp).simulate('click'); - equalsDate(inl.datepicker('getDate'), new Date(2008, 1 - 1, 16), + TestHelpers.datepicker.equalsDate(inl.datepicker('getDate'), new Date(2008, 1 - 1, 16), 'Mouse click inline - previous'); inl.datepicker('setDate', new Date(2008, 2 - 1, 4)); $('.ui-datepicker-next', dp).simulate('click'); $('.ui-datepicker-calendar tbody a:contains(18)', dp).simulate('click'); - equalsDate(inl.datepicker('getDate'), new Date(2008, 3 - 1, 18), + TestHelpers.datepicker.equalsDate(inl.datepicker('getDate'), new Date(2008, 3 - 1, 18), 'Mouse click inline - next'); }); diff --git a/tests/unit/datepicker/datepicker_events.js b/tests/unit/datepicker/datepicker_events.js index b710674727..81b152c66a 100644 --- a/tests/unit/datepicker/datepicker_events.js +++ b/tests/unit/datepicker/datepicker_events.js @@ -24,13 +24,13 @@ function callback2(year, month, inst) { test('events', function() { expect( 26 ); var dateStr, newMonthYear, inp2, - inp = init('#inp', {onSelect: callback}), + inp = TestHelpers.datepicker.init('#inp', {onSelect: callback}), date = new Date(); // onSelect inp.val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); equal(selectedThis, inp[0], 'Callback selected this'); - equal(selectedInst, $.data(inp[0], TestHelpers.PROP_NAME), 'Callback selected inst'); + equal(selectedInst, $.data(inp[0], TestHelpers.datepicker.PROP_NAME), 'Callback selected inst'); equal(selectedDate, $.datepicker.formatDate('mm/dd/yy', date), 'Callback selected date'); inp.val('').datepicker('show'). @@ -59,7 +59,7 @@ test('events', function() { inp.simulate('keydown', {keyCode: $.ui.keyCode.PAGE_UP}); date.setMonth(date.getMonth() - 1); equal(selectedThis, inp[0], 'Callback change month/year this'); - equal(selectedInst, $.data(inp[0], TestHelpers.PROP_NAME), 'Callback change month/year inst'); + equal(selectedInst, $.data(inp[0], TestHelpers.datepicker.PROP_NAME), 'Callback change month/year inst'); equal(selectedDate, newMonthYear(date), 'Callback change month/year date - pgup'); inp.simulate('keydown', {keyCode: $.ui.keyCode.PAGE_DOWN}); @@ -107,7 +107,7 @@ test('events', function() { val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ESCAPE}); equal(selectedThis, inp[0], 'Callback close this'); - equal(selectedInst, $.data(inp[0], TestHelpers.PROP_NAME), 'Callback close inst'); + equal(selectedInst, $.data(inp[0], TestHelpers.datepicker.PROP_NAME), 'Callback close inst'); equal(selectedDate, '', 'Callback close date - esc'); inp.val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); @@ -120,7 +120,7 @@ test('events', function() { simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.END}); equal(selectedDate, '', 'Callback close date - ctrl+end'); - inp2 = init('#inp2'); + inp2 = TestHelpers.datepicker.init('#inp2'); inp2.datepicker().datepicker('option', {onClose: callback}).datepicker('show'); inp.datepicker('show'); equal(selectedThis, inp2[0], 'Callback close this'); diff --git a/tests/unit/datepicker/datepicker_methods.js b/tests/unit/datepicker/datepicker_methods.js index 5e692d1a0e..d2964a2662 100644 --- a/tests/unit/datepicker/datepicker_methods.js +++ b/tests/unit/datepicker/datepicker_methods.js @@ -8,65 +8,65 @@ module("datepicker: methods"); test('destroy', function() { expect( 33 ); var inl, - inp = init('#inp'); + inp = TestHelpers.datepicker.init('#inp'); ok(inp.is('.hasDatepicker'), 'Default - marker class set'); - ok($.data(inp[0], TestHelpers.PROP_NAME), 'Default - instance present'); + ok($.data(inp[0], TestHelpers.datepicker.PROP_NAME), 'Default - instance present'); ok(inp.next().is('#alt'), 'Default - button absent'); inp.datepicker('destroy'); inp = $('#inp'); ok(!inp.is('.hasDatepicker'), 'Default - marker class cleared'); - ok(!$.data(inp[0], TestHelpers.PROP_NAME), 'Default - instance absent'); + ok(!$.data(inp[0], TestHelpers.datepicker.PROP_NAME), 'Default - instance absent'); ok(inp.next().is('#alt'), 'Default - button absent'); // With button - inp= init('#inp', {showOn: 'both'}); + inp= TestHelpers.datepicker.init('#inp', {showOn: 'both'}); ok(inp.is('.hasDatepicker'), 'Button - marker class set'); - ok($.data(inp[0], TestHelpers.PROP_NAME), 'Button - instance present'); + ok($.data(inp[0], TestHelpers.datepicker.PROP_NAME), 'Button - instance present'); ok(inp.next().text() === '...', 'Button - button added'); inp.datepicker('destroy'); inp = $('#inp'); ok(!inp.is('.hasDatepicker'), 'Button - marker class cleared'); - ok(!$.data(inp[0], TestHelpers.PROP_NAME), 'Button - instance absent'); + ok(!$.data(inp[0], TestHelpers.datepicker.PROP_NAME), 'Button - instance absent'); ok(inp.next().is('#alt'), 'Button - button removed'); // With append text - inp = init('#inp', {appendText: 'Testing'}); + inp = TestHelpers.datepicker.init('#inp', {appendText: 'Testing'}); ok(inp.is('.hasDatepicker'), 'Append - marker class set'); - ok($.data(inp[0], TestHelpers.PROP_NAME), 'Append - instance present'); + ok($.data(inp[0], TestHelpers.datepicker.PROP_NAME), 'Append - instance present'); ok(inp.next().text() === 'Testing', 'Append - append text added'); inp.datepicker('destroy'); inp = $('#inp'); ok(!inp.is('.hasDatepicker'), 'Append - marker class cleared'); - ok(!$.data(inp[0], TestHelpers.PROP_NAME), 'Append - instance absent'); + ok(!$.data(inp[0], TestHelpers.datepicker.PROP_NAME), 'Append - instance absent'); ok(inp.next().is('#alt'), 'Append - append text removed'); // With both - inp= init('#inp', {showOn: 'both', buttonImageOnly: true, + inp= TestHelpers.datepicker.init('#inp', {showOn: 'both', buttonImageOnly: true, buttonImage: 'img/calendar.gif', appendText: 'Testing'}); ok(inp.is('.hasDatepicker'), 'Both - marker class set'); - ok($.data(inp[0], TestHelpers.PROP_NAME), 'Both - instance present'); + ok($.data(inp[0], TestHelpers.datepicker.PROP_NAME), 'Both - instance present'); ok(inp.next()[0].nodeName.toLowerCase() === 'img', 'Both - button added'); ok(inp.next().next().text() === 'Testing', 'Both - append text added'); inp.datepicker('destroy'); inp = $('#inp'); ok(!inp.is('.hasDatepicker'), 'Both - marker class cleared'); - ok(!$.data(inp[0], TestHelpers.PROP_NAME), 'Both - instance absent'); + ok(!$.data(inp[0], TestHelpers.datepicker.PROP_NAME), 'Both - instance absent'); ok(inp.next().is('#alt'), 'Both - button and append text absent'); // Inline - inl = init('#inl'); + inl = TestHelpers.datepicker.init('#inl'); ok(inl.is('.hasDatepicker'), 'Inline - marker class set'); ok(inl.html() !== '', 'Inline - datepicker present'); - ok($.data(inl[0], TestHelpers.PROP_NAME), 'Inline - instance present'); + ok($.data(inl[0], TestHelpers.datepicker.PROP_NAME), 'Inline - instance present'); ok(inl.next().length === 0 || inl.next().is('p'), 'Inline - button absent'); inl.datepicker('destroy'); inl = $('#inl'); ok(!inl.is('.hasDatepicker'), 'Inline - marker class cleared'); ok(inl.html() === '', 'Inline - datepicker absent'); - ok(!$.data(inl[0], TestHelpers.PROP_NAME), 'Inline - instance absent'); + ok(!$.data(inl[0], TestHelpers.datepicker.PROP_NAME), 'Inline - instance absent'); ok(inl.next().length === 0 || inl.next().is('p'), 'Inline - button absent'); }); test('enableDisable', function() { expect( 33 ); var inl, dp, - inp = init('#inp'); + inp = TestHelpers.datepicker.init('#inp'); ok(!inp.datepicker('isDisabled'), 'Enable/disable - initially marked as enabled'); ok(!inp[0].disabled, 'Enable/disable - field initially enabled'); inp.datepicker('disable'); @@ -77,7 +77,7 @@ test('enableDisable', function() { ok(!inp[0].disabled, 'Enable/disable - field now enabled'); inp.datepicker('destroy'); // With a button - inp = init('#inp', {showOn: 'button'}); + inp = TestHelpers.datepicker.init('#inp', {showOn: 'button'}); ok(!inp.datepicker('isDisabled'), 'Enable/disable button - initially marked as enabled'); ok(!inp[0].disabled, 'Enable/disable button - field initially enabled'); ok(!inp.next('button')[0].disabled, 'Enable/disable button - button initially enabled'); @@ -91,7 +91,7 @@ test('enableDisable', function() { ok(!inp.next('button')[0].disabled, 'Enable/disable button - button now enabled'); inp.datepicker('destroy'); // With an image button - inp = init('#inp', {showOn: 'button', buttonImageOnly: true, + inp = TestHelpers.datepicker.init('#inp', {showOn: 'button', buttonImageOnly: true, buttonImage: 'img/calendar.gif'}); ok(!inp.datepicker('isDisabled'), 'Enable/disable image - initially marked as enabled'); ok(!inp[0].disabled, 'Enable/disable image - field initially enabled'); @@ -106,7 +106,7 @@ test('enableDisable', function() { ok(parseFloat(inp.next('img').css('opacity')) === 1, 'Enable/disable image - image now enabled'); inp.datepicker('destroy'); // Inline - inl = init('#inl', {changeYear: true}); + inl = TestHelpers.datepicker.init('#inl', {changeYear: true}); dp = $('.ui-datepicker-inline', inl); ok(!inl.datepicker('isDisabled'), 'Enable/disable inline - initially marked as enabled'); ok(!dp.children().is('.ui-state-disabled'), 'Enable/disable inline - not visually disabled initially'); diff --git a/tests/unit/datepicker/datepicker_options.js b/tests/unit/datepicker/datepicker_options.js index 7d3217364b..00910469e1 100644 --- a/tests/unit/datepicker/datepicker_options.js +++ b/tests/unit/datepicker/datepicker_options.js @@ -8,7 +8,7 @@ module("datepicker: options"); test('setDefaults', function() { expect( 3 ); - init('#inp'); + TestHelpers.datepicker.init('#inp'); equal($.datepicker._defaults.showOn, 'focus', 'Initial showOn'); $.datepicker.setDefaults({showOn: 'button'}); equal($.datepicker._defaults.showOn, 'button', 'Change default showOn'); @@ -18,8 +18,8 @@ test('setDefaults', function() { test('option', function() { expect( 17 ); - var inp = init('#inp'), - inst = $.data(inp[0], TestHelpers.PROP_NAME); + var inp = TestHelpers.datepicker.init('#inp'), + inst = $.data(inp[0], TestHelpers.datepicker.PROP_NAME); // Set option equal(inst.settings.showOn, null, 'Initial setting showOn'); equal($.datepicker._get(inst, 'showOn'), 'focus', 'Initial instance showOn'); @@ -37,7 +37,7 @@ test('option', function() { equal($.datepicker._get(inst, 'showOn'), 'focus', 'Restore instance showOn'); equal($.datepicker._defaults.showOn, 'focus', 'Retain default showOn'); // Get option - inp = init('#inp'); + inp = TestHelpers.datepicker.init('#inp'); equal(inp.datepicker('option', 'showOn'), 'focus', 'Initial setting showOn'); inp.datepicker('option', 'showOn', 'button'); equal(inp.datepicker('option', 'showOn'), 'button', 'Change instance showOn'); @@ -50,8 +50,8 @@ test('option', function() { test('change', function() { expect( 12 ); - var inp = init('#inp'), - inst = $.data(inp[0], TestHelpers.PROP_NAME); + var inp = TestHelpers.datepicker.init('#inp'), + inst = $.data(inp[0], TestHelpers.datepicker.PROP_NAME); equal(inst.settings.showOn, null, 'Initial setting showOn'); equal($.datepicker._get(inst, 'showOn'), 'focus', 'Initial instance showOn'); equal($.datepicker._defaults.showOn, 'focus', 'Initial default showOn'); @@ -72,7 +72,7 @@ test('change', function() { test('invocation', function() { expect( 29 ); var button, image, - inp = init('#inp'), + inp = TestHelpers.datepicker.init('#inp'), dp = $('#ui-datepicker-div'), body = $('body'); // On focus @@ -90,7 +90,7 @@ test('invocation', function() { ok(!dp.is(':visible'), 'Focus - hidden on external click'); inp.datepicker('hide').datepicker('destroy'); // On button - inp = init('#inp', {showOn: 'button', buttonText: 'Popup'}); + inp = TestHelpers.datepicker.init('#inp', {showOn: 'button', buttonText: 'Popup'}); ok(!dp.is(':visible'), 'Button - initially hidden'); button = inp.siblings('button'); image = inp.siblings('img'); @@ -105,7 +105,7 @@ test('invocation', function() { ok(!dp.is(':visible'), 'Button - hidden on second button click'); inp.datepicker('hide').datepicker('destroy'); // On image button - inp = init('#inp', {showOn: 'button', buttonImageOnly: true, + inp = TestHelpers.datepicker.init('#inp', {showOn: 'button', buttonImageOnly: true, buttonImage: 'img/calendar.gif', buttonText: 'Cal'}); ok(!dp.is(':visible'), 'Image button - initially hidden'); button = inp.siblings('button'); @@ -122,7 +122,7 @@ test('invocation', function() { ok(!dp.is(':visible'), 'Image button - hidden on second image click'); inp.datepicker('hide').datepicker('destroy'); // On both - inp = init('#inp', {showOn: 'both', buttonImage: 'img/calendar.gif'}); + inp = TestHelpers.datepicker.init('#inp', {showOn: 'both', buttonImage: 'img/calendar.gif'}); ok(!dp.is(':visible'), 'Both - initially hidden'); button = inp.siblings('button'); ok(button.length === 1, 'Both - button present'); @@ -143,7 +143,7 @@ test('invocation', function() { test('otherMonths', function() { expect( 8 ); - var inp = init('#inp'), + var inp = TestHelpers.datepicker.init('#inp'), pop = $('#ui-datepicker-div'); inp.val('06/01/2009').datepicker('show'); equal(pop.find('tbody').text(), '\u00a0123456789101112131415161718192021222324252627282930\u00a0\u00a0\u00a0\u00a0', @@ -165,104 +165,104 @@ test('otherMonths', function() { test('defaultDate', function() { expect( 17 ); - var inp = init('#inp'), + var inp = TestHelpers.datepicker.init('#inp'), date = new Date(); inp.val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), date, 'Default date null'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Default date null'); // Numeric values inp.datepicker('option', {defaultDate: -2}). datepicker('hide').val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); date.setDate(date.getDate() - 2); - equalsDate(inp.datepicker('getDate'), date, 'Default date -2'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Default date -2'); inp.datepicker('option', {defaultDate: 3}). datepicker('hide').val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); date.setDate(date.getDate() + 5); - equalsDate(inp.datepicker('getDate'), date, 'Default date 3'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Default date 3'); inp.datepicker('option', {defaultDate: 1 / 0}). datepicker('hide').val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); date.setDate(date.getDate() - 3); - equalsDate(inp.datepicker('getDate'), date, 'Default date Infinity'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Default date Infinity'); inp.datepicker('option', {defaultDate: 1 / 'a'}). datepicker('hide').val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), date, 'Default date NaN'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Default date NaN'); // String offset values inp.datepicker('option', {defaultDate: '-1d'}). datepicker('hide').val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); date.setDate(date.getDate() - 1); - equalsDate(inp.datepicker('getDate'), date, 'Default date -1d'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Default date -1d'); inp.datepicker('option', {defaultDate: '+3D'}). datepicker('hide').val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); date.setDate(date.getDate() + 4); - equalsDate(inp.datepicker('getDate'), date, 'Default date +3D'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Default date +3D'); inp.datepicker('option', {defaultDate: ' -2 w '}). datepicker('hide').val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); date = new Date(); date.setDate(date.getDate() - 14); - equalsDate(inp.datepicker('getDate'), date, 'Default date -2 w'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Default date -2 w'); inp.datepicker('option', {defaultDate: '+1 W'}). datepicker('hide').val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); date.setDate(date.getDate() + 21); - equalsDate(inp.datepicker('getDate'), date, 'Default date +1 W'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Default date +1 W'); inp.datepicker('option', {defaultDate: ' -1 m '}). datepicker('hide').val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - date = TestHelpers.addMonths(new Date(), -1); - equalsDate(inp.datepicker('getDate'), date, 'Default date -1 m'); + date = TestHelpers.datepicker.addMonths(new Date(), -1); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Default date -1 m'); inp.datepicker('option', {defaultDate: '+2M'}). datepicker('hide').val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - date = TestHelpers.addMonths(new Date(), 2); - equalsDate(inp.datepicker('getDate'), date, 'Default date +2M'); + date = TestHelpers.datepicker.addMonths(new Date(), 2); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Default date +2M'); inp.datepicker('option', {defaultDate: '-2y'}). datepicker('hide').val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); date = new Date(); date.setFullYear(date.getFullYear() - 2); - equalsDate(inp.datepicker('getDate'), date, 'Default date -2y'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Default date -2y'); inp.datepicker('option', {defaultDate: '+1 Y '}). datepicker('hide').val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); date.setFullYear(date.getFullYear() + 3); - equalsDate(inp.datepicker('getDate'), date, 'Default date +1 Y'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Default date +1 Y'); inp.datepicker('option', {defaultDate: '+1M +10d'}). datepicker('hide').val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - date = TestHelpers.addMonths(new Date(), 1); + date = TestHelpers.datepicker.addMonths(new Date(), 1); date.setDate(date.getDate() + 10); - equalsDate(inp.datepicker('getDate'), date, 'Default date +1M +10d'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Default date +1M +10d'); // String date values inp.datepicker('option', {defaultDate: '07/04/2007'}). datepicker('hide').val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); date = new Date(2007, 7 - 1, 4); - equalsDate(inp.datepicker('getDate'), date, 'Default date 07/04/2007'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Default date 07/04/2007'); inp.datepicker('option', {dateFormat: 'yy-mm-dd', defaultDate: '2007-04-02'}). datepicker('hide').val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); date = new Date(2007, 4 - 1, 2); - equalsDate(inp.datepicker('getDate'), date, 'Default date 2007-04-02'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Default date 2007-04-02'); // Date value date = new Date(2007, 1 - 1, 26); inp.datepicker('option', {dateFormat: 'mm/dd/yy', defaultDate: date}). datepicker('hide').val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), date, 'Default date 01/26/2007'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Default date 01/26/2007'); }); test('miscellaneous', function() { expect( 19 ); var curYear, longNames, shortNames, date, dp = $('#ui-datepicker-div'), - inp = init('#inp'); + inp = TestHelpers.datepicker.init('#inp'); // Year range function genRange(start, offset) { var i = start, @@ -323,7 +323,7 @@ test('miscellaneous', function() { test('minMax', function() { expect( 17 ); var date, - inp = init('#inp'), + inp = TestHelpers.datepicker.init('#inp'), lastYear = new Date(2007, 6 - 1, 4), nextYear = new Date(2009, 6 - 1, 4), minDate = new Date(2008, 2 - 1, 29), @@ -331,45 +331,45 @@ test('minMax', function() { inp.val('06/04/2008').datepicker('show'); inp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), lastYear, + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), lastYear, 'Min/max - null, null - ctrl+pgup'); inp.val('06/04/2008').datepicker('show'); inp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), nextYear, + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), nextYear, 'Min/max - null, null - ctrl+pgdn'); inp.datepicker('option', {minDate: minDate}). datepicker('hide').val('06/04/2008').datepicker('show'); inp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), minDate, + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), minDate, 'Min/max - 02/29/2008, null - ctrl+pgup'); inp.val('06/04/2008').datepicker('show'); inp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), nextYear, + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), nextYear, 'Min/max - 02/29/2008, null - ctrl+pgdn'); inp.datepicker('option', {maxDate: maxDate}). datepicker('hide').val('06/04/2008').datepicker('show'); inp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), minDate, + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), minDate, 'Min/max - 02/29/2008, 12/07/2008 - ctrl+pgup'); inp.val('06/04/2008').datepicker('show'); inp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), maxDate, + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), maxDate, 'Min/max - 02/29/2008, 12/07/2008 - ctrl+pgdn'); inp.datepicker('option', {minDate: null}). datepicker('hide').val('06/04/2008').datepicker('show'); inp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), lastYear, + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), lastYear, 'Min/max - null, 12/07/2008 - ctrl+pgup'); inp.val('06/04/2008').datepicker('show'); inp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), maxDate, + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), maxDate, 'Min/max - null, 12/07/2008 - ctrl+pgdn'); // Relative dates date = new Date(); @@ -378,80 +378,80 @@ test('minMax', function() { datepicker('hide').val('').datepicker('show'); inp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_UP}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), date, + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Min/max - -1w, +1 M +10 D - ctrl+pgup'); - date = TestHelpers.addMonths(new Date(), 1); + date = TestHelpers.datepicker.addMonths(new Date(), 1); date.setDate(date.getDate() + 10); inp.val('').datepicker('show'); inp.simulate('keydown', {ctrlKey: true, keyCode: $.ui.keyCode.PAGE_DOWN}). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - equalsDate(inp.datepicker('getDate'), date, + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Min/max - -1w, +1 M +10 D - ctrl+pgdn'); // With existing date - inp = init('#inp'); + inp = TestHelpers.datepicker.init('#inp'); inp.val('06/04/2008').datepicker('option', {minDate: minDate}); - equalsDate(inp.datepicker('getDate'), new Date(2008, 6 - 1, 4), 'Min/max - setDate > min'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2008, 6 - 1, 4), 'Min/max - setDate > min'); inp.datepicker('option', {minDate: null}).val('01/04/2008').datepicker('option', {minDate: minDate}); - equalsDate(inp.datepicker('getDate'), minDate, 'Min/max - setDate < min'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), minDate, 'Min/max - setDate < min'); inp.datepicker('option', {minDate: null}).val('06/04/2008').datepicker('option', {maxDate: maxDate}); - equalsDate(inp.datepicker('getDate'), new Date(2008, 6 - 1, 4), 'Min/max - setDate < max'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2008, 6 - 1, 4), 'Min/max - setDate < max'); inp.datepicker('option', {maxDate: null}).val('01/04/2009').datepicker('option', {maxDate: maxDate}); - equalsDate(inp.datepicker('getDate'), maxDate, 'Min/max - setDate > max'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), maxDate, 'Min/max - setDate > max'); inp.datepicker('option', {maxDate: null}).val('01/04/2008').datepicker('option', {minDate: minDate, maxDate: maxDate}); - equalsDate(inp.datepicker('getDate'), minDate, 'Min/max - setDate < min'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), minDate, 'Min/max - setDate < min'); inp.datepicker('option', {maxDate: null}).val('06/04/2008').datepicker('option', {minDate: minDate, maxDate: maxDate}); - equalsDate(inp.datepicker('getDate'), new Date(2008, 6 - 1, 4), 'Min/max - setDate > min, < max'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), new Date(2008, 6 - 1, 4), 'Min/max - setDate > min, < max'); inp.datepicker('option', {maxDate: null}).val('01/04/2009').datepicker('option', {minDate: minDate, maxDate: maxDate}); - equalsDate(inp.datepicker('getDate'), maxDate, 'Min/max - setDate > max'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), maxDate, 'Min/max - setDate > max'); }); test('setDate', function() { expect( 24 ); var inl, alt, minDate, maxDate, dateAndTimeToSet, dateAndTimeClone, - inp = init('#inp'), + inp = TestHelpers.datepicker.init('#inp'), date1 = new Date(2008, 6 - 1, 4), date2 = new Date(); ok(inp.datepicker('getDate') == null, 'Set date - default'); inp.datepicker('setDate', date1); - equalsDate(inp.datepicker('getDate'), date1, 'Set date - 2008-06-04'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date1, 'Set date - 2008-06-04'); date1 = new Date(); date1.setDate(date1.getDate() + 7); inp.datepicker('setDate', +7); - equalsDate(inp.datepicker('getDate'), date1, 'Set date - +7'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date1, 'Set date - +7'); date2.setFullYear(date2.getFullYear() + 2); inp.datepicker('setDate', '+2y'); - equalsDate(inp.datepicker('getDate'), date2, 'Set date - +2y'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date2, 'Set date - +2y'); inp.datepicker('setDate', date1, date2); - equalsDate(inp.datepicker('getDate'), date1, 'Set date - two dates'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date1, 'Set date - two dates'); inp.datepicker('setDate'); ok(inp.datepicker('getDate') == null, 'Set date - null'); // Relative to current date date1 = new Date(); date1.setDate(date1.getDate() + 7); inp.datepicker('setDate', 'c +7'); - equalsDate(inp.datepicker('getDate'), date1, 'Set date - c +7'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date1, 'Set date - c +7'); date1.setDate(date1.getDate() + 7); inp.datepicker('setDate', 'c+7'); - equalsDate(inp.datepicker('getDate'), date1, 'Set date - c+7'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date1, 'Set date - c+7'); date1.setDate(date1.getDate() - 21); inp.datepicker('setDate', 'c -3 w'); - equalsDate(inp.datepicker('getDate'), date1, 'Set date - c -3 w'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date1, 'Set date - c -3 w'); // Inline - inl = init('#inl'); + inl = TestHelpers.datepicker.init('#inl'); date1 = new Date(2008, 6 - 1, 4); date2 = new Date(); - equalsDate(inl.datepicker('getDate'), date2, 'Set date inline - default'); + TestHelpers.datepicker.equalsDate(inl.datepicker('getDate'), date2, 'Set date inline - default'); inl.datepicker('setDate', date1); - equalsDate(inl.datepicker('getDate'), date1, 'Set date inline - 2008-06-04'); + TestHelpers.datepicker.equalsDate(inl.datepicker('getDate'), date1, 'Set date inline - 2008-06-04'); date1 = new Date(); date1.setDate(date1.getDate() + 7); inl.datepicker('setDate', +7); - equalsDate(inl.datepicker('getDate'), date1, 'Set date inline - +7'); + TestHelpers.datepicker.equalsDate(inl.datepicker('getDate'), date1, 'Set date inline - +7'); date2.setFullYear(date2.getFullYear() + 2); inl.datepicker('setDate', '+2y'); - equalsDate(inl.datepicker('getDate'), date2, 'Set date inline - +2y'); + TestHelpers.datepicker.equalsDate(inl.datepicker('getDate'), date2, 'Set date inline - +2y'); inl.datepicker('setDate', date1, date2); - equalsDate(inl.datepicker('getDate'), date1, 'Set date inline - two dates'); + TestHelpers.datepicker.equalsDate(inl.datepicker('getDate'), date1, 'Set date inline - two dates'); inl.datepicker('setDate'); ok(inl.datepicker('getDate') == null, 'Set date inline - null'); // Alternate field @@ -462,23 +462,23 @@ test('setDate', function() { equal(inp.val(), '06/04/2008', 'Set date alternate - 06/04/2008'); equal(alt.val(), '2008-06-04', 'Set date alternate - 2008-06-04'); // With minimum/maximum - inp = init('#inp'); + inp = TestHelpers.datepicker.init('#inp'); date1 = new Date(2008, 1 - 1, 4); date2 = new Date(2008, 6 - 1, 4); minDate = new Date(2008, 2 - 1, 29); maxDate = new Date(2008, 3 - 1, 28); inp.val('').datepicker('option', {minDate: minDate}).datepicker('setDate', date2); - equalsDate(inp.datepicker('getDate'), date2, 'Set date min/max - setDate > min'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date2, 'Set date min/max - setDate > min'); inp.datepicker('setDate', date1); - equalsDate(inp.datepicker('getDate'), minDate, 'Set date min/max - setDate < min'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), minDate, 'Set date min/max - setDate < min'); inp.val('').datepicker('option', {maxDate: maxDate, minDate: null}).datepicker('setDate', date1); - equalsDate(inp.datepicker('getDate'), date1, 'Set date min/max - setDate < max'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date1, 'Set date min/max - setDate < max'); inp.datepicker('setDate', date2); - equalsDate(inp.datepicker('getDate'), maxDate, 'Set date min/max - setDate > max'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), maxDate, 'Set date min/max - setDate > max'); inp.val('').datepicker('option', {minDate: minDate}).datepicker('setDate', date1); - equalsDate(inp.datepicker('getDate'), minDate, 'Set date min/max - setDate < min'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), minDate, 'Set date min/max - setDate < min'); inp.datepicker('setDate', date2); - equalsDate(inp.datepicker('getDate'), maxDate, 'Set date min/max - setDate > max'); + TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), maxDate, 'Set date min/max - setDate > max'); dateAndTimeToSet = new Date(2008, 3 - 1, 28, 1, 11, 0); dateAndTimeClone = new Date(2008, 3 - 1, 28, 1, 11, 0); inp.datepicker('setDate', dateAndTimeToSet); @@ -487,7 +487,7 @@ test('setDate', function() { test('altField', function() { expect( 10 ); - var inp = init('#inp'), + var inp = TestHelpers.datepicker.init('#inp'), alt = $('#alt'); // No alternate field set alt.val(''); @@ -526,7 +526,7 @@ test('altField', function() { test('autoSize', function() { expect( 15 ); - var inp = init('#inp'); + var inp = TestHelpers.datepicker.init('#inp'); equal(inp.prop('size'), 20, 'Auto size - default'); inp.datepicker('option', 'autoSize', true); equal(inp.prop('size'), 10, 'Auto size - mm/dd/yy'); @@ -562,7 +562,7 @@ test('autoSize', function() { test('daylightSaving', function() { expect( 25 ); - var inp = init('#inp'), + var inp = TestHelpers.datepicker.init('#inp'), dp = $('#ui-datepicker-div'); ok(true, 'Daylight saving - ' + new Date()); // Australia, Sydney - AM change, southern hemisphere @@ -669,7 +669,7 @@ test('callbacks', function() { expect( 13 ); // Before show var dp, day20, day21, - inp = init('#inp', {beforeShow: beforeAll}), + inp = TestHelpers.datepicker.init('#inp', {beforeShow: beforeAll}), inst = $.data(inp[0], 'datepicker'); equal($.datepicker._get(inst, 'currentText'), 'Today', 'Before show - initial'); inp.val('02/04/2008').datepicker('show'); @@ -679,7 +679,7 @@ test('callbacks', function() { deepEqual(beforeShowInst, inst, 'Before show - inst OK'); inp.datepicker('hide').datepicker('destroy'); // Before show day - inp = init('#inp', {beforeShowDay: beforeDay}); + inp = TestHelpers.datepicker.init('#inp', {beforeShowDay: beforeDay}); dp = $('#ui-datepicker-div'); inp.val('02/04/2008').datepicker('show'); ok(beforeShowDayThis.id === inp[0].id, 'Before show day - this OK'); @@ -698,7 +698,7 @@ test('callbacks', function() { test('localisation', function() { expect( 24 ); var dp, month, day, date, - inp = init('#inp', $.datepicker.regional.fr); + inp = TestHelpers.datepicker.init('#inp', $.datepicker.regional.fr); inp.datepicker('option', {dateFormat: 'DD, d MM yy', showButtonPanel:true, changeMonth:true, changeYear:true}).val('').datepicker('show'); dp = $('#ui-datepicker-div'); equal($('.ui-datepicker-close', dp).text(), 'Fermer', 'Localisation - close'); @@ -765,72 +765,72 @@ test('iso8601Week', function() { test('parseDate', function() { expect( 26 ); - init('#inp'); + TestHelpers.datepicker.init('#inp'); var currentYear, gmtDate, fr, settings, zh; ok($.datepicker.parseDate('d m y', '') == null, 'Parse date empty'); - equalsDate($.datepicker.parseDate('d m y', '3 2 01'), + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('d m y', '3 2 01'), new Date(2001, 2 - 1, 3), 'Parse date d m y'); - equalsDate($.datepicker.parseDate('dd mm yy', '03 02 2001'), + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('dd mm yy', '03 02 2001'), new Date(2001, 2 - 1, 3), 'Parse date dd mm yy'); - equalsDate($.datepicker.parseDate('d m y', '13 12 01'), + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('d m y', '13 12 01'), new Date(2001, 12 - 1, 13), 'Parse date d m y'); - equalsDate($.datepicker.parseDate('dd mm yy', '13 12 2001'), + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('dd mm yy', '13 12 2001'), new Date(2001, 12 - 1, 13), 'Parse date dd mm yy'); - equalsDate($.datepicker.parseDate('y-o', '01-34'), + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('y-o', '01-34'), new Date(2001, 2 - 1, 3), 'Parse date y-o'); - equalsDate($.datepicker.parseDate('yy-oo', '2001-347'), + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('yy-oo', '2001-347'), new Date(2001, 12 - 1, 13), 'Parse date yy-oo'); - equalsDate($.datepicker.parseDate('oo yy', '348 2004'), + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('oo yy', '348 2004'), new Date(2004, 12 - 1, 13), 'Parse date oo yy'); - equalsDate($.datepicker.parseDate('D d M y', 'Sat 3 Feb 01'), + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('D d M y', 'Sat 3 Feb 01'), new Date(2001, 2 - 1, 3), 'Parse date D d M y'); - equalsDate($.datepicker.parseDate('d MM DD yy', '3 February Saturday 2001'), + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('d MM DD yy', '3 February Saturday 2001'), new Date(2001, 2 - 1, 3), 'Parse date dd MM DD yy'); - equalsDate($.datepicker.parseDate('DD, MM d, yy', 'Saturday, February 3, 2001'), + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('DD, MM d, yy', 'Saturday, February 3, 2001'), new Date(2001, 2 - 1, 3), 'Parse date DD, MM d, yy'); - equalsDate($.datepicker.parseDate('\'day\' d \'of\' MM (\'\'DD\'\'), yy', + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('\'day\' d \'of\' MM (\'\'DD\'\'), yy', 'day 3 of February (\'Saturday\'), 2001'), new Date(2001, 2 - 1, 3), 'Parse date \'day\' d \'of\' MM (\'\'DD\'\'), yy'); currentYear = new Date().getFullYear(); - equalsDate($.datepicker.parseDate('y-m-d', (currentYear - 2000) + '-02-03'), + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('y-m-d', (currentYear - 2000) + '-02-03'), new Date(currentYear, 2 - 1, 3), 'Parse date y-m-d - default cutuff'); - equalsDate($.datepicker.parseDate('y-m-d', (currentYear - 2000 + 10) + '-02-03'), + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('y-m-d', (currentYear - 2000 + 10) + '-02-03'), new Date(currentYear+10, 2 - 1, 3), 'Parse date y-m-d - default cutuff'); - equalsDate($.datepicker.parseDate('y-m-d', (currentYear - 2000 + 11) + '-02-03'), + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('y-m-d', (currentYear - 2000 + 11) + '-02-03'), new Date(currentYear-89, 2 - 1, 3), 'Parse date y-m-d - default cutuff'); - equalsDate($.datepicker.parseDate('y-m-d', '80-02-03', {shortYearCutoff: 80}), + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('y-m-d', '80-02-03', {shortYearCutoff: 80}), new Date(2080, 2 - 1, 3), 'Parse date y-m-d - cutoff 80'); - equalsDate($.datepicker.parseDate('y-m-d', '81-02-03', {shortYearCutoff: 80}), + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('y-m-d', '81-02-03', {shortYearCutoff: 80}), new Date(1981, 2 - 1, 3), 'Parse date y-m-d - cutoff 80'); - equalsDate($.datepicker.parseDate('y-m-d', (currentYear - 2000 + 60) + '-02-03', {shortYearCutoff: '+60'}), + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('y-m-d', (currentYear - 2000 + 60) + '-02-03', {shortYearCutoff: '+60'}), new Date(currentYear + 60, 2 - 1, 3), 'Parse date y-m-d - cutoff +60'); - equalsDate($.datepicker.parseDate('y-m-d', (currentYear - 2000 + 61) + '-02-03', {shortYearCutoff: '+60'}), + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('y-m-d', (currentYear - 2000 + 61) + '-02-03', {shortYearCutoff: '+60'}), new Date(currentYear - 39, 2 - 1, 3), 'Parse date y-m-d - cutoff +60'); gmtDate = new Date(2001, 2 - 1, 3); gmtDate.setMinutes(gmtDate.getMinutes() - gmtDate.getTimezoneOffset()); - equalsDate($.datepicker.parseDate('@', '981158400000'), gmtDate, 'Parse date @'); - equalsDate($.datepicker.parseDate('!', '631167552000000000'), gmtDate, 'Parse date !'); + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('@', '981158400000'), gmtDate, 'Parse date @'); + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('!', '631167552000000000'), gmtDate, 'Parse date !'); fr = $.datepicker.regional.fr; settings = {dayNamesShort: fr.dayNamesShort, dayNames: fr.dayNames, monthNamesShort: fr.monthNamesShort, monthNames: fr.monthNames}; - equalsDate($.datepicker.parseDate('D d M y', 'Lun. 9 Avril 01', settings), + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('D d M y', 'Lun. 9 Avril 01', settings), new Date(2001, 4 - 1, 9), 'Parse date D M y with settings'); - equalsDate($.datepicker.parseDate('d MM DD yy', '9 Avril Lundi 2001', settings), + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('d MM DD yy', '9 Avril Lundi 2001', settings), new Date(2001, 4 - 1, 9), 'Parse date d MM DD yy with settings'); - equalsDate($.datepicker.parseDate('DD, MM d, yy', 'Lundi, Avril 9, 2001', settings), + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('DD, MM d, yy', 'Lundi, Avril 9, 2001', settings), new Date(2001, 4 - 1, 9), 'Parse date DD, MM d, yy with settings'); - equalsDate($.datepicker.parseDate('\'jour\' d \'de\' MM (\'\'DD\'\'), yy', + TestHelpers.datepicker.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'); zh = $.datepicker.regional['zh-CN']; - equalsDate($.datepicker.parseDate('yy M d', '2011 十一 22', zh), + TestHelpers.datepicker.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() { expect( 17 ); - init('#inp'); + TestHelpers.datepicker.init('#inp'); var fr, settings; function expectError(expr, value, error) { try { @@ -883,7 +883,7 @@ test('parseDateErrors', function() { test('formatDate', function() { expect( 16 ); - init('#inp'); + TestHelpers.datepicker.init('#inp'); var gmtDate, fr, settings; equal($.datepicker.formatDate('d m y', new Date(2001, 2 - 1, 3)), '3 2 01', 'Format date d m y'); diff --git a/tests/unit/datepicker/datepicker_test_helpers.js b/tests/unit/datepicker/datepicker_test_helpers.js new file mode 100644 index 0000000000..2d374f561e --- /dev/null +++ b/tests/unit/datepicker/datepicker_test_helpers.js @@ -0,0 +1,22 @@ +TestHelpers.datepicker = { + addMonths: function(date, offset) { + var maxDay = 32 - new Date(date.getFullYear(), date.getMonth() + offset, 32).getDate(); + date.setDate(Math.min(date.getDate(), maxDay)); + date.setMonth(date.getMonth() + offset); + return date; + }, + equalsDate: function(d1, d2, message) { + if (!d1 || !d2) { + ok(false, message + ' - missing date'); + return; + } + d1 = new Date(d1.getFullYear(), d1.getMonth(), d1.getDate()); + d2 = new Date(d2.getFullYear(), d2.getMonth(), d2.getDate()); + equal(d1.toString(), d2.toString(), message); + }, + init: function(id, options) { + $.datepicker.setDefaults($.datepicker.regional['']); + return $(id).datepicker($.extend({showAnim: ''}, options || {})); + }, + PROP_NAME: 'datepicker' +}; \ No newline at end of file diff --git a/tests/unit/datepicker/datepicker_tickets.js b/tests/unit/datepicker/datepicker_tickets.js index ff5dfde637..4440992ae0 100644 --- a/tests/unit/datepicker/datepicker_tickets.js +++ b/tests/unit/datepicker/datepicker_tickets.js @@ -8,7 +8,7 @@ module("datepicker: tickets"); // http://forum.jquery.com/topic/several-breaking-changes-in-jquery-ui-1-8rc1 test('beforeShowDay-getDate', function() { expect( 3 ); - var inp = init('#inp', {beforeShowDay: function() { inp.datepicker('getDate'); return [true, '']; }}), + var inp = TestHelpers.datepicker.init('#inp', {beforeShowDay: function() { inp.datepicker('getDate'); return [true, '']; }}), dp = $('#ui-datepicker-div'); inp.val('01/01/2010').datepicker('show'); // contains non-breaking space @@ -27,7 +27,7 @@ test('beforeShowDay-getDate', function() { test('Ticket 7602: Stop datepicker from appearing with beforeShow event handler', function(){ expect( 3 ); - var inp = init('#inp',{ + var inp = TestHelpers.datepicker.init('#inp',{ beforeShow: function(){ return false; } @@ -37,7 +37,7 @@ test('Ticket 7602: Stop datepicker from appearing with beforeShow event handler' equal(dp.css('display'), 'none',"beforeShow returns false"); inp.datepicker('destroy'); - inp = init('#inp',{ + inp = TestHelpers.datepicker.init('#inp',{ beforeShow: function(){ } }); @@ -47,7 +47,7 @@ test('Ticket 7602: Stop datepicker from appearing with beforeShow event handler' inp.datepicker('hide'); inp.datepicker('destroy'); - inp = init('#inp',{ + inp = TestHelpers.datepicker.init('#inp',{ beforeShow: function(){ return true; } diff --git a/tests/unit/dialog/dialog.html b/tests/unit/dialog/dialog.html index 6722f1bb0e..cb74bb654c 100644 --- a/tests/unit/dialog/dialog.html +++ b/tests/unit/dialog/dialog.html @@ -29,6 +29,7 @@ + diff --git a/tests/unit/dialog/dialog_core.js b/tests/unit/dialog/dialog_core.js index a9e5e9be2c..b36f6204fc 100644 --- a/tests/unit/dialog/dialog_core.js +++ b/tests/unit/dialog/dialog_core.js @@ -2,80 +2,6 @@ * dialog_core.js */ -var el, - offsetBefore, offsetAfter, - heightBefore, heightAfter, - widthBefore, widthAfter, - dragged; - -function dlg() { - return el.dialog('widget'); -} - -TestHelpers.isOpen = function(why) { - ok(dlg().is(":visible"), why); -}; - -TestHelpers.isNotOpen = function(why) { - ok(!dlg().is(":visible"), why); -}; - -function drag(handle, dx, dy) { - var d = dlg(); - offsetBefore = d.offset(); - heightBefore = d.height(); - widthBefore = d.width(); - //this mouseover is to work around a limitation in resizable - //TODO: fix resizable so handle doesn't require mouseover in order to be used - $(handle, d).simulate("mouseover"); - $(handle, d).simulate("drag", { - dx: dx || 0, - dy: dy || 0 - }); - dragged = { dx: dx, dy: dy }; - offsetAfter = d.offset(); - heightAfter = d.height(); - widthAfter = d.width(); -} - -TestHelpers.dialogMoved = function(dx, dy, msg) { - msg = msg ? msg + "." : ""; - var actual = { left: Math.round(offsetAfter.left), top: Math.round(offsetAfter.top) }, - expected = { left: Math.round(offsetBefore.left + dx), top: Math.round(offsetBefore.top + dy) }; - deepEqual(actual, expected, 'dragged[' + dragged.dx + ', ' + dragged.dy + '] ' + msg); -}; - -TestHelpers.shouldmove = function(why) { - var handle = $(".ui-dialog-titlebar", dlg()); - drag(handle, 50, -50); - TestHelpers.dialogMoved(50, -50, why); -}; - -TestHelpers.shouldnotmove = function(why) { - var handle = $(".ui-dialog-titlebar", dlg()); - drag(handle, 50, -50); - TestHelpers.dialogMoved(0, 0, why); -}; - -TestHelpers.resized = function(dw, dh, msg) { - msg = msg ? msg + "." : ""; - var actual = { width: widthAfter, height: heightAfter }, - expected = { width: widthBefore + dw, height: heightBefore + dh }; - deepEqual(actual, expected, 'resized[' + dragged.dx + ', ' + dragged.dy + '] ' + msg); -}; - -TestHelpers.shouldresize = function(why) { - var handle = $(".ui-resizable-se", dlg()); - drag(handle, 50, 50); - TestHelpers.resized(50, 50, why); -}; - -TestHelpers.shouldnotresize = function(why) { - var handle = $(".ui-resizable-se", dlg()); - drag(handle, 50, 50); - TestHelpers.resized(0, 0, why); -}; - (function($) { module("dialog: core"); @@ -83,8 +9,10 @@ module("dialog: core"); test("title id", function() { expect(1); - el = $('
            ').dialog(); - var titleId = dlg().find('.ui-dialog-title').attr('id'); + var titleId, + el = $('
            ').dialog(); + + titleId = el.dialog('widget').find('.ui-dialog-title').attr('id'); ok( /ui-id-\d+$/.test( titleId ), 'auto-numbered title id'); el.remove(); }); @@ -92,16 +20,17 @@ test("title id", function() { test("ARIA", function() { expect(4); - el = $('
            ').dialog(); + var labelledBy, + el = $('
            ').dialog(); - equal(dlg().attr('role'), 'dialog', 'dialog role'); + equal(el.dialog('widget').attr('role'), 'dialog', 'dialog role'); - var labelledBy = dlg().attr('aria-labelledby'); + labelledBy = el.dialog('widget').attr('aria-labelledby'); ok(labelledBy.length > 0, 'has aria-labelledby attribute'); - equal(dlg().find('.ui-dialog-title').attr('id'), labelledBy, + equal(el.dialog('widget').find('.ui-dialog-title').attr('id'), labelledBy, 'proper aria-labelledby attribute'); - equal(dlg().find('.ui-dialog-titlebar-close').attr('role'), 'button', + equal(el.dialog('widget').find('.ui-dialog-titlebar-close').attr('role'), 'button', 'close link role'); el.remove(); diff --git a/tests/unit/dialog/dialog_events.js b/tests/unit/dialog/dialog_events.js index 38b75a714d..c5090d8f67 100644 --- a/tests/unit/dialog/dialog_events.js +++ b/tests/unit/dialog/dialog_events.js @@ -8,7 +8,7 @@ module("dialog: events"); test("open", function() { expect(13); - el = $("
            "); + var el = $("
            "); el.dialog({ open: function(ev, ui) { ok(el.data("dialog")._isOpen, "interal _isOpen flag is set"); @@ -42,163 +42,171 @@ test("open", function() { test("dragStart", function() { expect(9); - el = $('
            ').dialog({ - dragStart: function(ev, ui) { - ok(true, 'dragging fires dragStart callback'); - equal(this, el[0], "context of callback"); - equal(ev.type, 'dialogdragstart', 'event type in callback'); + var handle, + el = $('
            ').dialog({ + dragStart: function(ev, ui) { + ok(true, 'dragging fires dragStart callback'); + equal(this, el[0], "context of callback"); + equal(ev.type, 'dialogdragstart', 'event type in callback'); + ok(ui.position !== undefined, "ui.position in callback"); + ok(ui.offset !== undefined, "ui.offset in callback"); + } + }).bind('dialogdragstart', function(ev, ui) { + ok(true, 'dragging fires dialogdragstart event'); + equal(this, el[0], 'context of event'); ok(ui.position !== undefined, "ui.position in callback"); ok(ui.offset !== undefined, "ui.offset in callback"); - } - }).bind('dialogdragstart', function(ev, ui) { - ok(true, 'dragging fires dialogdragstart event'); - equal(this, el[0], 'context of event'); - ok(ui.position !== undefined, "ui.position in callback"); - ok(ui.offset !== undefined, "ui.offset in callback"); - }); - var handle = $(".ui-dialog-titlebar", dlg()); - drag(handle, 50, 50); + }); + + handle = $(".ui-dialog-titlebar", el.dialog('widget')); + TestHelpers.dialog.drag(el, handle, 50, 50); el.remove(); }); test("drag", function() { expect(9); var handle, - hasDragged = false; + hasDragged = false, + el = $('
            ').dialog({ + drag: function(ev, ui) { + if (!hasDragged) { + ok(true, 'dragging fires drag callback'); + equal(this, el[0], "context of callback"); + equal(ev.type, 'dialogdrag', 'event type in callback'); + ok(ui.position !== undefined, "ui.position in callback"); + ok(ui.offset !== undefined, "ui.offset in callback"); - el = $('
            ').dialog({ - drag: function(ev, ui) { - if (!hasDragged) { - ok(true, 'dragging fires drag callback'); - equal(this, el[0], "context of callback"); - equal(ev.type, 'dialogdrag', 'event type in callback'); - ok(ui.position !== undefined, "ui.position in callback"); - ok(ui.offset !== undefined, "ui.offset in callback"); - - hasDragged = true; + hasDragged = true; + } } - } - }).one('dialogdrag', function(ev, ui) { - ok(true, 'dragging fires dialogdrag event'); - equal(this, el[0], 'context of event'); - ok(ui.position !== undefined, "ui.position in callback"); - ok(ui.offset !== undefined, "ui.offset in callback"); - }); - handle = $(".ui-dialog-titlebar", dlg()); - drag(handle, 50, 50); + }).one('dialogdrag', function(ev, ui) { + ok(true, 'dragging fires dialogdrag event'); + equal(this, el[0], 'context of event'); + ok(ui.position !== undefined, "ui.position in callback"); + ok(ui.offset !== undefined, "ui.offset in callback"); + }); + + handle = $(".ui-dialog-titlebar", el.dialog('widget')); + TestHelpers.dialog.drag(el, handle, 50, 50); el.remove(); }); test("dragStop", function() { expect(9); - el = $('
            ').dialog({ - dragStop: function(ev, ui) { - ok(true, 'dragging fires dragStop callback'); - equal(this, el[0], "context of callback"); - equal(ev.type, 'dialogdragstop', 'event type in callback'); + var handle, + el = $('
            ').dialog({ + dragStop: function(ev, ui) { + ok(true, 'dragging fires dragStop callback'); + equal(this, el[0], "context of callback"); + equal(ev.type, 'dialogdragstop', 'event type in callback'); + ok(ui.position !== undefined, "ui.position in callback"); + ok(ui.offset !== undefined, "ui.offset in callback"); + } + }).bind('dialogdragstop', function(ev, ui) { + ok(true, 'dragging fires dialogdragstop event'); + equal(this, el[0], 'context of event'); ok(ui.position !== undefined, "ui.position in callback"); ok(ui.offset !== undefined, "ui.offset in callback"); - } - }).bind('dialogdragstop', function(ev, ui) { - ok(true, 'dragging fires dialogdragstop event'); - equal(this, el[0], 'context of event'); - ok(ui.position !== undefined, "ui.position in callback"); - ok(ui.offset !== undefined, "ui.offset in callback"); - }); - var handle = $(".ui-dialog-titlebar", dlg()); - drag(handle, 50, 50); + }); + + handle = $(".ui-dialog-titlebar", el.dialog('widget')); + TestHelpers.dialog.drag(el, handle, 50, 50); el.remove(); }); test("resizeStart", function() { expect(13); - el = $('
            ').dialog({ - resizeStart: function(ev, ui) { - ok(true, 'resizing fires resizeStart callback'); - equal(this, el[0], "context of callback"); - equal(ev.type, 'dialogresizestart', 'event type in callback'); + var handle, + el = $('
            ').dialog({ + resizeStart: function(ev, ui) { + ok(true, 'resizing fires resizeStart callback'); + equal(this, el[0], "context of callback"); + equal(ev.type, 'dialogresizestart', 'event type in callback'); + ok(ui.originalPosition !== undefined, "ui.originalPosition in callback"); + ok(ui.originalSize !== undefined, "ui.originalSize in callback"); + ok(ui.position !== undefined, "ui.position in callback"); + ok(ui.size !== undefined, "ui.size in callback"); + } + }).bind('dialogresizestart', function(ev, ui) { + ok(true, 'resizing fires dialogresizestart event'); + equal(this, el[0], 'context of event'); ok(ui.originalPosition !== undefined, "ui.originalPosition in callback"); ok(ui.originalSize !== undefined, "ui.originalSize in callback"); ok(ui.position !== undefined, "ui.position in callback"); ok(ui.size !== undefined, "ui.size in callback"); - } - }).bind('dialogresizestart', function(ev, ui) { - ok(true, 'resizing fires dialogresizestart event'); - equal(this, el[0], 'context of event'); - ok(ui.originalPosition !== undefined, "ui.originalPosition in callback"); - ok(ui.originalSize !== undefined, "ui.originalSize in callback"); - ok(ui.position !== undefined, "ui.position in callback"); - ok(ui.size !== undefined, "ui.size in callback"); - }); - var handle = $(".ui-resizable-se", dlg()); - drag(handle, 50, 50); + }); + + handle = $(".ui-resizable-se", el.dialog('widget')); + TestHelpers.dialog.drag(el, handle, 50, 50); el.remove(); }); test("resize", function() { expect(13); var handle, - hasResized = false; + hasResized = false, + el = $('
            ').dialog({ + resize: function(ev, ui) { + if (!hasResized) { + ok(true, 'resizing fires resize callback'); + equal(this, el[0], "context of callback"); + equal(ev.type, 'dialogresize', 'event type in callback'); + ok(ui.originalPosition !== undefined, "ui.originalPosition in callback"); + ok(ui.originalSize !== undefined, "ui.originalSize in callback"); + ok(ui.position !== undefined, "ui.position in callback"); + ok(ui.size !== undefined, "ui.size in callback"); - el = $('
            ').dialog({ - resize: function(ev, ui) { - if (!hasResized) { - ok(true, 'resizing fires resize callback'); - equal(this, el[0], "context of callback"); - equal(ev.type, 'dialogresize', 'event type in callback'); - ok(ui.originalPosition !== undefined, "ui.originalPosition in callback"); - ok(ui.originalSize !== undefined, "ui.originalSize in callback"); - ok(ui.position !== undefined, "ui.position in callback"); - ok(ui.size !== undefined, "ui.size in callback"); - - hasResized = true; + hasResized = true; + } } - } - }).one('dialogresize', function(ev, ui) { - ok(true, 'resizing fires dialogresize event'); - equal(this, el[0], 'context of event'); - ok(ui.originalPosition !== undefined, "ui.originalPosition in callback"); - ok(ui.originalSize !== undefined, "ui.originalSize in callback"); - ok(ui.position !== undefined, "ui.position in callback"); - ok(ui.size !== undefined, "ui.size in callback"); - }); - handle = $(".ui-resizable-se", dlg()); - drag(handle, 50, 50); + }).one('dialogresize', function(ev, ui) { + ok(true, 'resizing fires dialogresize event'); + equal(this, el[0], 'context of event'); + ok(ui.originalPosition !== undefined, "ui.originalPosition in callback"); + ok(ui.originalSize !== undefined, "ui.originalSize in callback"); + ok(ui.position !== undefined, "ui.position in callback"); + ok(ui.size !== undefined, "ui.size in callback"); + }); + + handle = $(".ui-resizable-se", el.dialog('widget')); + TestHelpers.dialog.drag(el, handle, 50, 50); el.remove(); }); test("resizeStop", function() { expect(13); - el = $('
            ').dialog({ - resizeStop: function(ev, ui) { - ok(true, 'resizing fires resizeStop callback'); - equal(this, el[0], "context of callback"); - equal(ev.type, 'dialogresizestop', 'event type in callback'); - ok(ui.originalPosition !== undefined, "ui.originalPosition in callback"); - ok(ui.originalSize !== undefined, "ui.originalSize in callback"); - ok(ui.position !== undefined, "ui.position in callback"); - ok(ui.size !== undefined, "ui.size in callback"); - } - }).bind('dialogresizestop', function(ev, ui) { - ok(true, 'resizing fires dialogresizestop event'); - equal(this, el[0], 'context of event'); - ok(ui.originalPosition !== undefined, "ui.originalPosition in callback"); - ok(ui.originalSize !== undefined, "ui.originalSize in callback"); - ok(ui.position !== undefined, "ui.position in callback"); - ok(ui.size !== undefined, "ui.size in callback"); - }); - var handle = $(".ui-resizable-se", dlg()); - drag(handle, 50, 50); + var handle, + el = $('
            ').dialog({ + resizeStop: function(ev, ui) { + ok(true, 'resizing fires resizeStop callback'); + equal(this, el[0], "context of callback"); + equal(ev.type, 'dialogresizestop', 'event type in callback'); + ok(ui.originalPosition !== undefined, "ui.originalPosition in callback"); + ok(ui.originalSize !== undefined, "ui.originalSize in callback"); + ok(ui.position !== undefined, "ui.position in callback"); + ok(ui.size !== undefined, "ui.size in callback"); + } + }).bind('dialogresizestop', function(ev, ui) { + ok(true, 'resizing fires dialogresizestop event'); + equal(this, el[0], 'context of event'); + ok(ui.originalPosition !== undefined, "ui.originalPosition in callback"); + ok(ui.originalSize !== undefined, "ui.originalSize in callback"); + ok(ui.position !== undefined, "ui.position in callback"); + ok(ui.size !== undefined, "ui.size in callback"); + }); + + handle = $(".ui-resizable-se", el.dialog('widget')); + TestHelpers.dialog.drag(el, handle, 50, 50); el.remove(); }); asyncTest("close", function() { expect(14); - el = $('
            ').dialog({ + var el = $('
            ').dialog({ close: function(ev, ui) { ok(true, '.dialog("close") fires close callback'); equal(this, el[0], "context of callback"); @@ -234,7 +242,7 @@ asyncTest("close", function() { test("beforeClose", function() { expect(14); - el = $('
            ').dialog({ + var el = $('
            ').dialog({ beforeClose: function(ev, ui) { ok(true, '.dialog("close") fires beforeClose callback'); equal(this, el[0], "context of callback"); @@ -243,8 +251,9 @@ test("beforeClose", function() { return false; } }); + el.dialog('close'); - TestHelpers.isOpen('beforeClose callback should prevent dialog from closing'); + ok( el.dialog("widget").is(":visible"), 'beforeClose callback should prevent dialog from closing'); el.remove(); el = $('
            ').dialog(); @@ -256,7 +265,8 @@ test("beforeClose", function() { return false; }); el.dialog('close'); - TestHelpers.isOpen('beforeClose callback should prevent dialog from closing'); + + ok( el.dialog("widget").is(":visible"), 'beforeClose callback should prevent dialog from closing'); el.remove(); el = $('
            ').dialog().bind('dialogbeforeclose', function(ev, ui) { @@ -266,7 +276,7 @@ test("beforeClose", function() { return false; }); el.dialog('close'); - TestHelpers.isOpen('dialogbeforeclose event should prevent dialog from closing'); + ok( el.dialog("widget").is(":visible"), 'dialogbeforeclose event should prevent dialog from closing'); el.remove(); }); diff --git a/tests/unit/dialog/dialog_methods.js b/tests/unit/dialog/dialog_methods.js index e7b2fc710d..7048a76a93 100644 --- a/tests/unit/dialog/dialog_methods.js +++ b/tests/unit/dialog/dialog_methods.js @@ -24,7 +24,7 @@ test("init", function() { $('
            ').appendTo('body').remove().dialog().remove(); ok(true, '.dialog() called on disconnected DOMElement - removed'); - el = $('
            ').dialog(); + var el = $('
            ').dialog(); el.dialog("option", "foo"); el.remove(); ok(true, 'arbitrary option getter after init'); @@ -53,46 +53,49 @@ test("destroy", function() { test("enable", function() { expect( 3 ); - var expected = $('
            ').dialog(), + var el, + expected = $('
            ').dialog(), actual = expected.dialog('enable'); equal(actual, expected, 'enable is chainable'); el = $('
            ').dialog({ disabled: true }); el.dialog('enable'); equal(el.dialog('option', 'disabled'), false, 'enable method sets disabled option to false'); - ok(!dlg().hasClass('ui-dialog-disabled'), 'enable method removes ui-dialog-disabled class from ui-dialog element'); + ok(!el.dialog('widget').hasClass('ui-dialog-disabled'), 'enable method removes ui-dialog-disabled class from ui-dialog element'); }); test("disable", function() { expect( 3 ); - var expected = $('
            ').dialog(), + var el, + expected = $('
            ').dialog(), actual = expected.dialog('disable'); equal(actual, expected, 'disable is chainable'); el = $('
            ').dialog({ disabled: false }); el.dialog('disable'); equal(el.dialog('option', 'disabled'), true, 'disable method sets disabled option to true'); - ok(dlg().hasClass('ui-dialog-disabled'), 'disable method adds ui-dialog-disabled class to ui-dialog element'); + ok(el.dialog('widget').hasClass('ui-dialog-disabled'), 'disable method adds ui-dialog-disabled class to ui-dialog element'); }); test("close", function() { expect( 3 ); - var expected = $('
            ').dialog(), + var el, + expected = $('
            ').dialog(), actual = expected.dialog('close'); equal(actual, expected, 'close is chainable'); el = $('
            ').dialog(); - ok(dlg().is(':visible') && !dlg().is(':hidden'), 'dialog visible before close method called'); + ok(el.dialog('widget').is(':visible') && !el.dialog('widget').is(':hidden'), 'dialog visible before close method called'); el.dialog('close'); - ok(dlg().is(':hidden') && !dlg().is(':visible'), 'dialog hidden after close method called'); + ok(el.dialog('widget').is(':hidden') && !el.dialog('widget').is(':visible'), 'dialog hidden after close method called'); }); test("isOpen", function() { expect(4); - el = $('
            ').dialog(); + var el = $('
            ').dialog(); equal(el.dialog('isOpen'), true, "dialog is open after init"); el.dialog('close'); equal(el.dialog('isOpen'), false, "dialog is closed"); @@ -134,14 +137,15 @@ test("moveToTop", function() { test("open", function() { expect( 3 ); - var expected = $('
            ').dialog(), + var el, + expected = $('
            ').dialog(), actual = expected.dialog('open'); equal(actual, expected, 'open is chainable'); el = $('
            ').dialog({ autoOpen: false }); - ok(dlg().is(':hidden') && !dlg().is(':visible'), 'dialog hidden before open method called'); + ok(el.dialog('widget').is(':hidden') && !el.dialog('widget').is(':visible'), 'dialog hidden before open method called'); el.dialog('open'); - ok(dlg().is(':visible') && !dlg().is(':hidden'), 'dialog visible after open method called'); + ok(el.dialog('widget').is(':visible') && !el.dialog('widget').is(':hidden'), 'dialog visible after open method called'); }); })(jQuery); diff --git a/tests/unit/dialog/dialog_options.js b/tests/unit/dialog/dialog_options.js index 1c823868e3..b6ff2dfc4a 100644 --- a/tests/unit/dialog/dialog_options.js +++ b/tests/unit/dialog/dialog_options.js @@ -8,12 +8,12 @@ module("dialog: options"); test("autoOpen", function() { expect(2); - el = $('
            ').dialog({ autoOpen: false }); - TestHelpers.isNotOpen('.dialog({ autoOpen: false })'); + var el = $('
            ').dialog({ autoOpen: false }); + ok( !el.dialog("widget").is(":visible"), '.dialog({ autoOpen: false })'); el.remove(); el = $('
            ').dialog({ autoOpen: true }); - TestHelpers.isOpen('.dialog({ autoOpen: true })'); + ok( el.dialog("widget").is(":visible"), '.dialog({ autoOpen: true })'); el.remove(); }); @@ -22,20 +22,20 @@ test("buttons", function() { var btn, i, newButtons, buttons = { - "Ok": function( ev ) { - ok(true, "button click fires callback"); - equal(this, el[0], "context of callback"); - equal(ev.target, btn[0], "event target"); + "Ok": function( ev ) { + ok(true, "button click fires callback"); + equal(this, el[0], "context of callback"); + equal(ev.target, btn[0], "event target"); + }, + "Cancel": function( ev ) { + ok(true, "button click fires callback"); + equal(this, el[0], "context of callback"); + equal(ev.target, btn[1], "event target"); + } }, - "Cancel": function( ev ) { - ok(true, "button click fires callback"); - equal(this, el[0], "context of callback"); - equal(ev.target, btn[1], "event target"); - } - }; + el = $('
            ').dialog({ buttons: buttons }); - el = $('
            ').dialog({ buttons: buttons }); - btn = $("button", dlg()); + btn = $("button", el.dialog('widget')); equal(btn.length, 2, "number of buttons"); i = 0; @@ -61,7 +61,7 @@ test("buttons", function() { el.dialog("option", "buttons", newButtons); deepEqual(el.dialog("option", "buttons"), newButtons, '.dialog("option", "buttons", ...) setter'); - btn = $("button", dlg()); + btn = $("button", el.dialog('widget')); equal(btn.length, 1, "number of buttons after setter"); btn.trigger('click'); @@ -72,7 +72,7 @@ test("buttons", function() { }); el.dialog("option", "buttons", null); - btn = $("button", dlg()); + btn = $("button", el.dialog('widget')); equal(btn.length, 0, "all buttons have been removed"); equal(el.find(".ui-dialog-buttonset").length, 0, "buttonset has been removed"); equal(el.parent().hasClass('ui-dialog-buttons'), false, "dialog wrapper removes class about having buttons"); @@ -83,19 +83,21 @@ test("buttons", function() { test("buttons - advanced", function() { expect(5); - el = $("
            ").dialog({ - buttons: [ - { - text: "a button", - "class": "additional-class", - id: "my-button-id", - click: function() { - equal(this, el[0], "correct context"); + var buttons, + el = $("
            ").dialog({ + buttons: [ + { + text: "a button", + "class": "additional-class", + id: "my-button-id", + click: function() { + equal(this, el[0], "correct context"); + } } - } - ] - }); - var buttons = dlg().find("button"); + ] + }); + + buttons = el.dialog('widget').find("button"); equal(buttons.length, 1, "correct number of buttons"); equal(buttons.attr("id"), "my-button-id", "correct id"); equal(buttons.text(), "a button", "correct label"); @@ -107,40 +109,40 @@ test("buttons - advanced", function() { test("closeOnEscape", function() { expect( 6 ); - el = $('
            ').dialog({ closeOnEscape: false }); + var el = $('
            ').dialog({ closeOnEscape: false }); ok(true, 'closeOnEscape: false'); - ok(dlg().is(':visible') && !dlg().is(':hidden'), 'dialog is open before ESC'); + ok(el.dialog('widget').is(':visible') && !el.dialog('widget').is(':hidden'), 'dialog is open before ESC'); el.simulate('keydown', { keyCode: $.ui.keyCode.ESCAPE }) .simulate('keypress', { keyCode: $.ui.keyCode.ESCAPE }) .simulate('keyup', { keyCode: $.ui.keyCode.ESCAPE }); - ok(dlg().is(':visible') && !dlg().is(':hidden'), 'dialog is open after ESC'); + ok(el.dialog('widget').is(':visible') && !el.dialog('widget').is(':hidden'), 'dialog is open after ESC'); el.remove(); el = $('
            ').dialog({ closeOnEscape: true }); ok(true, 'closeOnEscape: true'); - ok(dlg().is(':visible') && !dlg().is(':hidden'), 'dialog is open before ESC'); + ok(el.dialog('widget').is(':visible') && !el.dialog('widget').is(':hidden'), 'dialog is open before ESC'); el.simulate('keydown', { keyCode: $.ui.keyCode.ESCAPE }) .simulate('keypress', { keyCode: $.ui.keyCode.ESCAPE }) .simulate('keyup', { keyCode: $.ui.keyCode.ESCAPE }); - ok(dlg().is(':hidden') && !dlg().is(':visible'), 'dialog is closed after ESC'); + ok(el.dialog('widget').is(':hidden') && !el.dialog('widget').is(':visible'), 'dialog is closed after ESC'); }); test("closeText", function() { expect(3); - el = $('
            ').dialog(); - equal(dlg().find('.ui-dialog-titlebar-close span').text(), 'close', + var el = $('
            ').dialog(); + equal(el.dialog('widget').find('.ui-dialog-titlebar-close span').text(), 'close', 'default close text'); el.remove(); el = $('
            ').dialog({ closeText: "foo" }); - equal(dlg().find('.ui-dialog-titlebar-close span').text(), 'foo', + equal(el.dialog('widget').find('.ui-dialog-titlebar-close span').text(), 'foo', 'closeText on init'); el.remove(); el = $('
            ').dialog().dialog('option', 'closeText', 'bar'); - equal(dlg().find('.ui-dialog-titlebar-close span').text(), 'bar', + equal(el.dialog('widget').find('.ui-dialog-titlebar-close span').text(), 'bar', 'closeText via option method'); el.remove(); }); @@ -148,131 +150,132 @@ test("closeText", function() { test("dialogClass", function() { expect(4); - el = $('
            ').dialog(); - equal(dlg().is(".foo"), false, 'dialogClass not specified. foo class added'); + var el = $('
            ').dialog(); + equal(el.dialog('widget').is(".foo"), false, 'dialogClass not specified. foo class added'); el.remove(); el = $('
            ').dialog({ dialogClass: "foo" }); - equal(dlg().is(".foo"), true, 'dialogClass in init. foo class added'); + equal(el.dialog('widget').is(".foo"), true, 'dialogClass in init. foo class added'); el.remove(); el = $('
            ').dialog({ dialogClass: "foo bar" }); - equal(dlg().is(".foo"), true, 'dialogClass in init, two classes. foo class added'); - equal(dlg().is(".bar"), true, 'dialogClass in init, two classes. bar class added'); + equal(el.dialog('widget').is(".foo"), true, 'dialogClass in init, two classes. foo class added'); + equal(el.dialog('widget').is(".bar"), true, 'dialogClass in init, two classes. bar class added'); el.remove(); }); test("draggable", function() { expect(4); - el = $('
            ').dialog({ draggable: false }); - TestHelpers.shouldnotmove(); + var el = $('
            ').dialog({ draggable: false }); + + TestHelpers.dialog.testDrag(el, 50, -50, 0, 0); el.dialog('option', 'draggable', true); - TestHelpers.shouldmove(); + TestHelpers.dialog.testDrag(el, 50, -50, 50, -50); el.remove(); el = $('
            ').dialog({ draggable: true }); - TestHelpers.shouldmove(); + TestHelpers.dialog.testDrag(el, 50, -50, 50, -50); el.dialog('option', 'draggable', false); - TestHelpers.shouldnotmove(); + TestHelpers.dialog.testDrag(el, 50, -50, 0, 0); el.remove(); }); test("height", function() { expect(4); - el = $('
            ').dialog(); - equal(dlg().outerHeight(), 150, "default height"); + var el = $('
            ').dialog(); + equal(el.dialog('widget').outerHeight(), 150, "default height"); el.remove(); el = $('
            ').dialog({ height: 237 }); - equal(dlg().outerHeight(), 237, "explicit height"); + equal(el.dialog('widget').outerHeight(), 237, "explicit height"); el.remove(); el = $('
            ').dialog(); el.dialog('option', 'height', 238); - equal(dlg().outerHeight(), 238, "explicit height set after init"); + equal(el.dialog('widget').outerHeight(), 238, "explicit height set after init"); el.remove(); el = $('
            ').css("padding", "20px") .dialog({ height: 240 }); - equal(dlg().outerHeight(), 240, "explicit height with padding"); + equal(el.dialog('widget').outerHeight(), 240, "explicit height with padding"); el.remove(); }); test("maxHeight", function() { expect(3); - el = $('
            ').dialog({ maxHeight: 200 }); - drag('.ui-resizable-s', 1000, 1000); - equal(heightAfter, 200, "maxHeight"); + var el = $('
            ').dialog({ maxHeight: 200 }); + TestHelpers.dialog.drag(el, '.ui-resizable-s', 1000, 1000); + equal(el.dialog('widget').height(), 200, "maxHeight"); el.remove(); el = $('
            ').dialog({ maxHeight: 200 }); - drag('.ui-resizable-n', -1000, -1000); - equal(heightAfter, 200, "maxHeight"); + TestHelpers.dialog.drag(el, '.ui-resizable-n', -1000, -1000); + equal(el.dialog('widget').height(), 200, "maxHeight"); el.remove(); el = $('
            ').dialog({ maxHeight: 200 }).dialog('option', 'maxHeight', 300); - drag('.ui-resizable-s', 1000, 1000); - equal(heightAfter, 300, "maxHeight"); + TestHelpers.dialog.drag(el, '.ui-resizable-s', 1000, 1000); + equal(el.dialog('widget').height(), 300, "maxHeight"); el.remove(); }); test("maxWidth", function() { expect(3); - el = $('
            ').dialog({ maxWidth: 200 }); - drag('.ui-resizable-e', 1000, 1000); - equal(widthAfter, 200, "maxWidth"); + var el = $('
            ').dialog({ maxWidth: 200 }); + TestHelpers.dialog.drag(el, '.ui-resizable-e', 1000, 1000); + equal(el.dialog('widget').width(), 200, "maxWidth"); el.remove(); el = $('
            ').dialog({ maxWidth: 200 }); - drag('.ui-resizable-w', -1000, -1000); - equal(widthAfter, 200, "maxWidth"); + TestHelpers.dialog.drag(el, '.ui-resizable-w', -1000, -1000); + equal(el.dialog('widget').width(), 200, "maxWidth"); el.remove(); el = $('
            ').dialog({ maxWidth: 200 }).dialog('option', 'maxWidth', 300); - drag('.ui-resizable-w', -1000, -1000); - equal(widthAfter, 300, "maxWidth"); + TestHelpers.dialog.drag(el, '.ui-resizable-w', -1000, -1000); + equal(el.dialog('widget').width(), 300, "maxWidth"); el.remove(); }); test("minHeight", function() { expect(3); - el = $('
            ').dialog({ minHeight: 10 }); - drag('.ui-resizable-s', -1000, -1000); - equal(heightAfter, 10, "minHeight"); + var el = $('
            ').dialog({ minHeight: 10 }); + TestHelpers.dialog.drag(el, '.ui-resizable-s', -1000, -1000); + equal(el.dialog('widget').height(), 10, "minHeight"); el.remove(); el = $('
            ').dialog({ minHeight: 10 }); - drag('.ui-resizable-n', 1000, 1000); - equal(heightAfter, 10, "minHeight"); + TestHelpers.dialog.drag(el, '.ui-resizable-n', 1000, 1000); + equal(el.dialog('widget').height(), 10, "minHeight"); el.remove(); el = $('
            ').dialog({ minHeight: 10 }).dialog('option', 'minHeight', 30); - drag('.ui-resizable-n', 1000, 1000); - equal(heightAfter, 30, "minHeight"); + TestHelpers.dialog.drag(el, '.ui-resizable-n', 1000, 1000); + equal(el.dialog('widget').height(), 30, "minHeight"); el.remove(); }); test("minWidth", function() { expect(3); - el = $('
            ').dialog({ minWidth: 10 }); - drag('.ui-resizable-e', -1000, -1000); - equal(widthAfter, 10, "minWidth"); + var el = $('
            ').dialog({ minWidth: 10 }); + TestHelpers.dialog.drag(el, '.ui-resizable-e', -1000, -1000); + equal(el.dialog('widget').width(), 10, "minWidth"); el.remove(); el = $('
            ').dialog({ minWidth: 10 }); - drag('.ui-resizable-w', 1000, 1000); - equal(widthAfter, 10, "minWidth"); + TestHelpers.dialog.drag(el, '.ui-resizable-w', 1000, 1000); + equal(el.dialog('widget').width(), 10, "minWidth"); el.remove(); el = $('
            ').dialog({ minWidth: 30 }).dialog('option', 'minWidth', 30); - drag('.ui-resizable-w', 1000, 1000); - equal(widthAfter, 30, "minWidth"); + TestHelpers.dialog.drag(el, '.ui-resizable-w', 1000, 1000); + equal(el.dialog('widget').width(), 30, "minWidth"); el.remove(); }); @@ -394,16 +397,16 @@ test("position, at another element", function() { test("resizable", function() { expect(4); - el = $('
            ').dialog(); - TestHelpers.shouldresize("[default]"); + var el = $('
            ').dialog(); + TestHelpers.dialog.shouldResize(el, 50, 50, "[default]"); el.dialog('option', 'resizable', false); - TestHelpers.shouldnotresize('disabled after init'); + TestHelpers.dialog.shouldResize(el, 0, 0, 'disabled after init'); el.remove(); el = $('
            ').dialog({ resizable: false }); - TestHelpers.shouldnotresize("disabled in init options"); + TestHelpers.dialog.shouldResize(el, 0, 0, "disabled in init options"); el.dialog('option', 'resizable', true); - TestHelpers.shouldresize('enabled after init'); + TestHelpers.dialog.shouldResize(el, 50, 50, 'enabled after init'); el.remove(); }); @@ -411,13 +414,13 @@ test("title", function() { expect(9); function titleText() { - return dlg().find(".ui-dialog-title").html(); + return el.dialog('widget').find(".ui-dialog-title").html(); } - el = $('
            ').dialog(); + var el = $('
            ').dialog(); // some browsers return a non-breaking space and some return " " // so we get the text to normalize to the actual non-breaking space - equal(dlg().find(".ui-dialog-title").text(), " ", "[default]"); + equal(el.dialog('widget').find(".ui-dialog-title").text(), " ", "[default]"); equal(el.dialog("option", "title"), "", "option not changed"); el.remove(); @@ -444,14 +447,14 @@ test("title", function() { test("width", function() { expect(3); - el = $('
            ').dialog(); - equal(dlg().width(), 300, "default width"); + var el = $('
            ').dialog(); + equal(el.dialog('widget').width(), 300, "default width"); el.remove(); el = $('
            ').dialog({width: 437 }); - equal(dlg().width(), 437, "explicit width"); + equal(el.dialog('widget').width(), 437, "explicit width"); el.dialog('option', 'width', 438); - equal(dlg().width(), 438, 'explicit width after init'); + equal(el.dialog('widget').width(), 438, 'explicit width after init'); el.remove(); }); diff --git a/tests/unit/dialog/dialog_test_helpers.js b/tests/unit/dialog/dialog_test_helpers.js new file mode 100644 index 0000000000..bbf43f48f4 --- /dev/null +++ b/tests/unit/dialog/dialog_test_helpers.js @@ -0,0 +1,45 @@ +TestHelpers.dialog = { + drag: function(el, handle, dx, dy) { + var d = el.dialog('widget'); + //this mouseover is to work around a limitation in resizable + //TODO: fix resizable so handle doesn't require mouseover in order to be used + $(handle, d).simulate("mouseover"); + $(handle, d).simulate("drag", { + dx: dx || 0, + dy: dy || 0 + }); + }, + testDrag: function(el, dx, dy, expectedDX, expectedDY, msg) { + var actual, expected, offsetAfter, + d = el.dialog('widget'), + handle = $(".ui-dialog-titlebar", d), + offsetBefore = d.offset(); + + TestHelpers.dialog.drag(el, handle, dx, dy); + + offsetAfter = d.offset(); + + msg = msg ? msg + "." : ""; + + actual = { left: Math.round(offsetAfter.left), top: Math.round(offsetAfter.top) }, + expected = { left: Math.round(offsetBefore.left + expectedDX), top: Math.round(offsetBefore.top + expectedDY) }; + deepEqual(actual, expected, 'dragged[' + expectedDX + ', ' + expectedDY + '] ' + msg); + }, + shouldResize: function(el, dw, dh, msg) { + var heightAfter, widthAfter, actual, expected, + d = el.dialog('widget'), + handle = $(".ui-resizable-se", d), + heightBefore = d.height(), + widthBefore = d.width(); + + TestHelpers.dialog.drag(el, handle, 50, 50); + + heightAfter = d.height(); + widthAfter = d.width(); + + msg = msg ? msg + "." : ""; + actual = { width: widthAfter, height: heightAfter }, + expected = { width: widthBefore + dw, height: heightBefore + dh }; + deepEqual(actual, expected, 'resized[' + 50 + ', ' + 50 + '] ' + msg); + } +}; \ No newline at end of file diff --git a/tests/unit/dialog/dialog_tickets.js b/tests/unit/dialog/dialog_tickets.js index 2b02147185..3055c5fc1a 100644 --- a/tests/unit/dialog/dialog_tickets.js +++ b/tests/unit/dialog/dialog_tickets.js @@ -36,21 +36,21 @@ asyncTest( "#3123: Prevent tabbing out of modal dialogs", function() { test("#4826: setting resizable false toggles resizable on dialog", function() { expect(6); - var i; + var i, + el = $('
            ').dialog({ resizable: false }); - el = $('
            ').dialog({ resizable: false }); - TestHelpers.shouldnotresize("[default]"); + TestHelpers.dialog.shouldResize(el, 0, 0, "[default]"); for (i=0; i<2; i++) { el.dialog('close').dialog('open'); - TestHelpers.shouldnotresize('initialized with resizable false toggle ('+ (i+1) +')'); + TestHelpers.dialog.shouldResize(el, 0, 0, 'initialized with resizable false toggle ('+ (i+1) +')'); } el.remove(); el = $('
            ').dialog({ resizable: true }); - TestHelpers.shouldresize("[default]"); + TestHelpers.dialog.shouldResize(el, 50, 50, "[default]"); for (i=0; i<2; i++) { el.dialog('close').dialog('option', 'resizable', false).dialog('open'); - TestHelpers.shouldnotresize('set option resizable false toggle ('+ (i+1) +')'); + TestHelpers.dialog.shouldResize(el, 0, 0, 'set option resizable false toggle ('+ (i+1) +')'); } el.remove(); @@ -59,11 +59,11 @@ test("#4826: setting resizable false toggles resizable on dialog", function() { test("#5184: isOpen in dialogclose event is true", function() { expect( 3 ); - el = $( "
            " ).dialog({ - close: function() { - ok( !el.dialog("isOpen"), "dialog is not open during close" ); - } - }); + var el = $( "
            " ).dialog({ + close: function() { + ok( !el.dialog("isOpen"), "dialog is not open during close" ); + } + }); ok( el.dialog("isOpen"), "dialog is open after init" ); el.dialog( "close" ); ok( !el.dialog("isOpen"), "dialog is not open after close" ); @@ -72,7 +72,7 @@ test("#5184: isOpen in dialogclose event is true", function() { test("#5531: dialog width should be at least minWidth on creation", function () { expect( 4 ); - el = $('
            ').dialog({ + var el = $('
            ').dialog({ width: 200, minWidth: 300 }); @@ -95,7 +95,7 @@ test("#5531: dialog width should be at least minWidth on creation", function () test("#6137: dialog('open') causes form elements to reset on IE7", function() { expect(2); - d1 = $('' + + var d1 = $('' + 'b').appendTo( "body" ).dialog({autoOpen: false}); d1.find('#b').prop( "checked", true ); @@ -109,8 +109,9 @@ test("#6137: dialog('open') causes form elements to reset on IE7", function() { test("#6645: Missing element not found check in overlay", function(){ expect(2); - d1 = $('
            Dialog 1
            ').dialog({modal: true}); - d2 = $('
            Dialog 2
            ').dialog({modal: true, close: function(){ d2.remove(); }}); + var d1 = $('
            Dialog 1
            ').dialog({modal: true}), + d2 = $('
            Dialog 2
            ').dialog({modal: true, close: function(){ d2.remove(); }}); + equal($.ui.dialog.overlay.instances.length, 2, 'two overlays created'); d2.dialog('close'); equal($.ui.dialog.overlay.instances.length, 1, 'one overlay remains after closing the 2nd overlay'); @@ -119,8 +120,8 @@ test("#6645: Missing element not found check in overlay", function(){ test("#4980: Destroy should place element back in original DOM position", function(){ expect( 2 ); - container = $('
            '); - modal = container.find('#modal'); + var container = $('
            '), + modal = container.find('#modal'); modal.dialog(); ok(!$.contains(container[0], modal[0]), 'dialog should move modal element to outside container element'); modal.dialog('destroy'); diff --git a/tests/unit/draggable/draggable.html b/tests/unit/draggable/draggable.html index 160467e897..dce226a9ae 100644 --- a/tests/unit/draggable/draggable.html +++ b/tests/unit/draggable/draggable.html @@ -26,6 +26,7 @@ + diff --git a/tests/unit/draggable/draggable_core.js b/tests/unit/draggable/draggable_core.js index 3ec3fb8dd7..0e9d04be1f 100644 --- a/tests/unit/draggable/draggable_core.js +++ b/tests/unit/draggable/draggable_core.js @@ -2,70 +2,6 @@ * draggable_core.js */ -TestHelpers.draggable = {}; - -// todo: remove these hacks -TestHelpers.draggable.unreliableOffset = $.ui.ie && ( !document.documentMode || document.documentMode < 8 ) ? 2 : 0; - -TestHelpers.draggable.drag = function(handle, dx, dy) { - $(handle).simulate("drag", { - dx: dx || 0, - dy: dy || 0 - }); - return el.offset(); -}; - -TestHelpers.draggable.testDrag = function(el, handle, dx, dy, expectedDX, expectedDY, msg) { - - var offsetBefore = el.offset(), - offsetAfter = TestHelpers.draggable.drag(handle, dx, dy), - actual = { left: offsetAfter.left, top: offsetAfter.top }, - expected = { left: offsetBefore.left + expectedDX, top: offsetBefore.top + expectedDY }; - - msg = msg ? msg + "." : ""; - deepEqual(actual, expected, 'dragged[' + dx + ', ' + dy + '] ' + msg); -}; - -TestHelpers.draggable.shouldMove = function(el, why) { - TestHelpers.draggable.testDrag(el, el, 50, 50, 50, 50, why); -}; - -TestHelpers.draggable.shouldNotMove = function(el, why) { - TestHelpers.draggable.testDrag(el, el, 50, 50, 0, 0, why); -}; - -TestHelpers.draggable.testScroll = function(el, position ) { - var oldPosition = $("#main").css('position'); - $("#main").css('position', position); - TestHelpers.draggable.shouldMove(el, position+' parent'); - $("#main").css('position', oldPosition); -}; - -TestHelpers.draggable.restoreScroll = function( what ) { - if( what ) { - $(document).scrollTop(0); $(document).scrollLeft(0); - } else { - $("#main").scrollTop(0); $("#main").scrollLeft(0); - } -}; - -TestHelpers.draggable.setScroll = function( what ) { - if(what) { - // todo: currently, the draggable interaction doesn't properly account for scrolled pages, - // uncomment the line below to make the tests fail that should when the page is scrolled - // $(document).scrollTop(100); $(document).scrollLeft(100); - } else { - $("#main").scrollTop(100); $("#main").scrollLeft(100); - } -}; - -TestHelpers.draggable.border = function(el, side) { - return parseInt(el.css('border-' + side + '-width'), 10) || 0; -}; -TestHelpers.draggable.margin = function(el, side) { - return parseInt(el.css('margin-' + side), 10) || 0; -}; - (function($) { module("draggable"); @@ -79,12 +15,15 @@ test("element types", function() { expect( typeNames.length ); $.each(typeNames, function(i) { - var offsetBefore, offsetAfter, typeName = typeNames[i]; - el = $(document.createElement(typeName)).appendTo('#main'); + var offsetBefore, offsetAfter, + typeName = typeNames[i], + el = $(document.createElement(typeName)).appendTo('#main'); + (typeName === 'table' && el.append("content")); el.draggable({ cancel: '' }); offsetBefore = el.offset(); - offsetAfter =TestHelpers.draggable.drag(el, 50, 50); + TestHelpers.draggable.drag(el, 50, 50); + offsetAfter = el.offset(); //there are some rounding errors in FF and Chrome, so we can't say equal, we have to settle for close enough ok(offsetAfter.left - offsetBefore.left - 50 < 1 && offsetAfter.top - offsetBefore.top - 50 < 1, 'dragged[50, 50] ' + "<" + typeName + ">"); el.draggable("destroy"); @@ -94,13 +33,13 @@ test("element types", function() { test("No options, relative", function() { expect( 1 ); - el = $("#draggable1").draggable(); + var el = $("#draggable1").draggable(); TestHelpers.draggable.shouldMove(el); }); test("No options, absolute", function() { expect( 1 ); - el = $("#draggable2").draggable(); + var el = $("#draggable2").draggable(); TestHelpers.draggable.shouldMove(el); }); diff --git a/tests/unit/draggable/draggable_events.js b/tests/unit/draggable/draggable_events.js index 65e8097a77..6b1136cb04 100644 --- a/tests/unit/draggable/draggable_events.js +++ b/tests/unit/draggable/draggable_events.js @@ -9,12 +9,14 @@ test("callbacks occurrence count", function() { expect(3); - var start = 0, stop = 0, dragc = 0; - el = $("#draggable2").draggable({ - start: function() { start++; }, - drag: function() { dragc++; }, - stop: function() { stop++; } - }); + var start = 0, + stop = 0, + dragc = 0, + el = $("#draggable2").draggable({ + start: function() { start++; }, + drag: function() { dragc++; }, + stop: function() { stop++; } + }); TestHelpers.draggable.drag(el, 10, 10); @@ -28,12 +30,14 @@ test("stopping the start callback", function() { expect(3); - var start = 0, stop = 0, dragc = 0; - el = $("#draggable2").draggable({ - start: function() { start++; return false; }, - drag: function() { dragc++; }, - stop: function() { stop++; } - }); + var start = 0, + stop = 0, + dragc = 0, + el = $("#draggable2").draggable({ + start: function() { start++; return false; }, + drag: function() { dragc++; }, + stop: function() { stop++; } + }); TestHelpers.draggable.drag(el, 10, 10); @@ -47,12 +51,14 @@ test("stopping the drag callback", function() { expect(3); - var start = 0, stop = 0, dragc = 0; - el = $("#draggable2").draggable({ - start: function() { start++;}, - drag: function() { dragc++; return false; }, - stop: function() { stop++; } - }); + var start = 0, + stop = 0, + dragc = 0, + el = $("#draggable2").draggable({ + start: function() { start++;}, + drag: function() { dragc++; return false; }, + stop: function() { stop++; } + }); TestHelpers.draggable.drag(el, 10, 10); @@ -66,7 +72,7 @@ test("stopping the stop callback", function() { expect(1); - el = $("#draggable2").draggable({ + var el = $("#draggable2").draggable({ helper: 'clone', stop: function() { return false; } }); diff --git a/tests/unit/draggable/draggable_methods.js b/tests/unit/draggable/draggable_methods.js index b4b7888b6f..9ea353ca6f 100644 --- a/tests/unit/draggable/draggable_methods.js +++ b/tests/unit/draggable/draggable_methods.js @@ -42,6 +42,9 @@ test("destroy", function() { test("enable", function() { expect(7); + + var expected, actual, el; + el = $("#draggable2").draggable({ disabled: true }); TestHelpers.draggable.shouldNotMove(el, '.draggable({ disabled: true })'); @@ -57,13 +60,16 @@ test("enable", function() { equal(el.draggable("option", "disabled"), false, "disabled option setter"); TestHelpers.draggable.shouldMove(el, '.draggable("option", "disabled", false)'); - var expected = $('
            ').draggable(), - actual = expected.draggable('enable'); + expected = $('
            ').draggable(), + actual = expected.draggable('enable'); equal(actual, expected, 'enable is chainable'); }); test("disable", function() { expect(7); + + var expected, actual, el; + el = $("#draggable2").draggable({ disabled: false }); TestHelpers.draggable.shouldMove(el, '.draggable({ disabled: false })'); @@ -80,8 +86,8 @@ test("disable", function() { equal(el.draggable("option", "disabled"), true, "disabled option setter"); TestHelpers.draggable.shouldNotMove(el, '.draggable("option", "disabled", true)'); - var expected = $('
            ').draggable(), - actual = expected.draggable('disable'); + expected = $('
            ').draggable(), + actual = expected.draggable('disable'); equal(actual, expected, 'disable is chainable'); }); diff --git a/tests/unit/draggable/draggable_options.js b/tests/unit/draggable/draggable_options.js index 4834dd9c4f..3f4592d31f 100644 --- a/tests/unit/draggable/draggable_options.js +++ b/tests/unit/draggable/draggable_options.js @@ -7,7 +7,7 @@ module("draggable: options"); test("{ addClasses: true }, default", function() { expect( 1 ); - el = $("
            ").draggable({ addClasses: true }); + var el = $("
            ").draggable({ addClasses: true }); ok(el.is(".ui-draggable"), "'ui-draggable' class added"); el.draggable("destroy"); @@ -15,7 +15,7 @@ test("{ addClasses: true }, default", function() { test("{ addClasses: false }", function() { expect( 1 ); - el = $("
            ").draggable({ addClasses: false }); + var el = $("
            ").draggable({ addClasses: false }); ok(!el.is(".ui-draggable"), "'ui-draggable' class not added"); el.draggable("destroy"); @@ -23,7 +23,7 @@ test("{ addClasses: false }", function() { test("{ appendTo: 'parent' }, default", function() { expect( 2 ); - el = $("#draggable2").draggable({ appendTo: 'parent' }); + var el = $("#draggable2").draggable({ appendTo: 'parent' }); TestHelpers.draggable.shouldMove(el); el = $("#draggable1").draggable({ appendTo: 'parent' }); @@ -33,7 +33,7 @@ test("{ appendTo: 'parent' }, default", function() { test("{ appendTo: Element }", function() { expect( 2 ); - el = $("#draggable2").draggable({ appendTo: $("#draggable2").parent()[0] }); + var el = $("#draggable2").draggable({ appendTo: $("#draggable2").parent()[0] }); TestHelpers.draggable.shouldMove(el); el = $("#draggable1").draggable({ appendTo: $("#draggable2").parent()[0] }); @@ -42,7 +42,7 @@ test("{ appendTo: Element }", function() { test("{ appendTo: Selector }", function() { expect( 2 ); - el = $("#draggable2").draggable({ appendTo: "#main" }); + var el = $("#draggable2").draggable({ appendTo: "#main" }); TestHelpers.draggable.shouldMove(el); el = $("#draggable1").draggable({ appendTo: "#main" }); @@ -51,31 +51,32 @@ test("{ appendTo: Selector }", function() { test("{ axis: false }, default", function() { expect( 1 ); - el = $("#draggable2").draggable({ axis: false }); + var el = $("#draggable2").draggable({ axis: false }); TestHelpers.draggable.shouldMove(el); }); test("{ axis: 'x' }", function() { expect( 1 ); - el = $("#draggable2").draggable({ axis: "x" }); + var el = $("#draggable2").draggable({ axis: "x" }); TestHelpers.draggable.testDrag(el, el, 50, 50, 50, 0); }); test("{ axis: 'y' }", function() { expect( 1 ); - el = $("#draggable2").draggable({ axis: "y" }); + var el = $("#draggable2").draggable({ axis: "y" }); TestHelpers.draggable.testDrag(el, el, 50, 50, 0, 50); }); test("{ axis: ? }, unexpected", function() { - var unexpected = { - "true": true, - "{}": {}, - "[]": [], - "null": null, - "undefined": undefined, - "function() {}": function() {} - }; + var el, + unexpected = { + "true": true, + "{}": {}, + "[]": [], + "null": null, + "undefined": undefined, + "function() {}": function() {} + }; expect( 6 ); @@ -91,7 +92,7 @@ test("{ cancel: 'input,textarea,button,select,option' }, default", function() { $('
            ').appendTo('#main'); - el = $("#draggable-option-cancel-default").draggable({ cancel: "input,textarea,button,select,option" }); + var el = $("#draggable-option-cancel-default").draggable({ cancel: "input,textarea,button,select,option" }); TestHelpers.draggable.shouldMove(el); el.draggable("destroy"); @@ -104,7 +105,7 @@ test("{ cancel: 'input,textarea,button,select,option' }, default", function() { test("{ cancel: 'span' }", function() { expect( 2 ); - el = $("#draggable2").draggable(); + var el = $("#draggable2").draggable(); TestHelpers.draggable.testDrag(el, "#draggable2 span", 50, 50, 50, 50); el.draggable("destroy"); @@ -114,17 +115,18 @@ test("{ cancel: 'span' }", function() { }); test("{ cancel: ? }, unexpected", function() { - var unexpected = { - "true": true, - "false": false, - "{}": {}, - "[]": [], - "null": null, - "undefined": undefined, - "function() {return '';}": function() {return '';}, - "function() {return true;}": function() {return true;}, - "function() {return false;}": function() {return false;} - }; + var el, + unexpected = { + "true": true, + "false": false, + "{}": {}, + "[]": [], + "null": null, + "undefined": undefined, + "function() {return '';}": function() {return '';}, + "function() {return true;}": function() {return true;}, + "function() {return false;}": function() {return false;} + }; expect( 9 ); @@ -152,28 +154,32 @@ test("{ containment: Element }", function() { test("{ containment: 'parent' }, relative", function() { expect( 1 ); - el = $("#draggable1").draggable({ containment: 'parent' }); - var p = el.parent(), + var offsetAfter, + el = $("#draggable1").draggable({ containment: 'parent' }), + p = el.parent(), po = p.offset(), expected = { left: po.left + TestHelpers.draggable.border(p, 'left') + TestHelpers.draggable.margin(el, 'left'), top: po.top + TestHelpers.draggable.border(p, 'top') + TestHelpers.draggable.margin(el, 'top') - }, - offsetAfter = TestHelpers.draggable.drag(el, -100, -100); + }; + TestHelpers.draggable.drag(el, -100, -100); + offsetAfter = el.offset(); deepEqual(offsetAfter, expected, 'compare offset to parent'); }); test("{ containment: 'parent' }, absolute", function() { expect( 1 ); - el = $("#draggable2").draggable({ containment: 'parent' }); - var p = el.parent(), + var offsetAfter, + el = $("#draggable2").draggable({ containment: 'parent' }), + p = el.parent(), po = p.offset(), expected = { left: po.left + TestHelpers.draggable.border(p, 'left') + TestHelpers.draggable.margin(el, 'left'), top: po.top + TestHelpers.draggable.border(p, 'top') + TestHelpers.draggable.margin(el, 'top') - }, - offsetAfter = TestHelpers.draggable.drag(el, -100, -100); + }; + TestHelpers.draggable.drag(el, -100, -100); + offsetAfter = el.offset(); deepEqual(offsetAfter, expected, 'compare offset to parent'); }); @@ -210,7 +216,7 @@ test("{ cursor: 'auto' }, default", function() { var expected = "auto", actual, before, after; - el = $("#draggable2").draggable({ + $("#draggable2").draggable({ cursor: expected, start: function() { actual = getCursor(); @@ -234,7 +240,7 @@ test("{ cursor: 'move' }", function() { var expected = "move", actual, before, after; - el = $("#draggable2").draggable({ + $("#draggable2").draggable({ cursor: expected, start: function() { actual = getCursor(); @@ -266,14 +272,14 @@ test("{ cursorAt: { left: -5, top: -5 } }", function() { cursorAtX = -5, cursorAtY = -5; $.each(['relative', 'absolute'], function(i, position) { - var before, pos, expected; - el = $('#draggable' + (i + 1)).draggable({ - cursorAt: { left: cursorAtX, top: cursorAtY }, - drag: function(event, ui) { - equal(ui.offset.left, expected.left, position + ' left'); - equal(ui.offset.top, expected.top, position + ' top'); - } - }); + var before, pos, expected, + el = $('#draggable' + (i + 1)).draggable({ + cursorAt: { left: cursorAtX, top: cursorAtY }, + drag: function(event, ui) { + equal(ui.offset.left, expected.left, position + ' left'); + equal(ui.offset.top, expected.top, position + ' top'); + } + }); before = el.offset(); pos = { @@ -285,6 +291,7 @@ test("{ cursorAt: { left: -5, top: -5 } }", function() { top: before.top + offsetY - cursorAtY + deltaY - TestHelpers.draggable.unreliableOffset }; + // todo: replace this with simulated drag event el.simulate("mousedown", pos); pos.clientX += deltaX; pos.clientY += deltaY; @@ -301,14 +308,14 @@ test("{ cursorAt: { right: 10, bottom: 20 } }", function() { cursorAtX = 10, cursorAtY = 20; $.each(['relative', 'absolute'], function(i, position) { - var before, pos, expected; - el = $('#draggable' + (i + 1)).draggable({ - cursorAt: { right: cursorAtX, bottom: cursorAtY }, - drag: function(event, ui) { - equal(ui.offset.left, expected.left, position + ' left'); - equal(ui.offset.top, expected.top, position + ' top'); - } - }); + var before, pos, expected, + el = $('#draggable' + (i + 1)).draggable({ + cursorAt: { right: cursorAtX, bottom: cursorAtY }, + drag: function(event, ui) { + equal(ui.offset.left, expected.left, position + ' left'); + equal(ui.offset.top, expected.top, position + ' top'); + } + }); before = el.offset(); pos = { clientX: before.left + offsetX, @@ -319,6 +326,7 @@ test("{ cursorAt: { right: 10, bottom: 20 } }", function() { top: before.top + offsetY - el.height() + cursorAtY + deltaY - TestHelpers.draggable.unreliableOffset }; + // todo: replace this with simulated drag event el.simulate("mousedown", pos); pos.clientX += deltaX; pos.clientY += deltaY; @@ -335,14 +343,15 @@ test("{ cursorAt: [10, 20] }", function() { cursorAtX = 10, cursorAtY = 20; $.each(['relative', 'absolute'], function(i, position) { - var before, pos, expected; - el = $('#draggable' + (i + 1)).draggable({ - cursorAt: { left: cursorAtX, top: cursorAtY }, - drag: function(event, ui) { - equal(ui.offset.left, expected.left, position + ' left'); - equal(ui.offset.top, expected.top, position + ' top'); - } - }); + var before, pos, expected, + el = $('#draggable' + (i + 1)).draggable({ + cursorAt: { left: cursorAtX, top: cursorAtY }, + drag: function(event, ui) { + equal(ui.offset.left, expected.left, position + ' left'); + equal(ui.offset.top, expected.top, position + ' top'); + } + }); + before = el.offset(); pos = { clientX: before.left + offsetX, @@ -353,6 +362,7 @@ test("{ cursorAt: [10, 20] }", function() { top: before.top + offsetY - cursorAtY + deltaY - TestHelpers.draggable.unreliableOffset }; + // todo: replace this with simulated drag event el.simulate("mousedown", pos); pos.clientX += deltaX; pos.clientY += deltaY; @@ -369,14 +379,15 @@ test("{ cursorAt: '20, 40' }", function() { cursorAtX = 20, cursorAtY = 40; $.each(['relative', 'absolute'], function(i, position) { - var before, pos, expected; - el = $('#draggable' + (i + 1)).draggable({ - cursorAt: { left: cursorAtX, top: cursorAtY }, - drag: function(event, ui) { - equal(ui.offset.left, expected.left, position + ' left'); - equal(ui.offset.top, expected.top, position + ' top'); - } - }); + var before, pos, expected, + el = $('#draggable' + (i + 1)).draggable({ + cursorAt: { left: cursorAtX, top: cursorAtY }, + drag: function(event, ui) { + equal(ui.offset.left, expected.left, position + ' left'); + equal(ui.offset.top, expected.top, position + ' top'); + } + }); + before = el.offset(); pos = { clientX: before.left + offsetX, @@ -387,6 +398,7 @@ test("{ cursorAt: '20, 40' }", function() { top: before.top + offsetY - cursorAtY + deltaY - TestHelpers.draggable.unreliableOffset }; + // todo: replace this with simulated drag event el.simulate("mousedown", pos); pos.clientX += deltaX; pos.clientY += deltaY; @@ -398,7 +410,7 @@ test("{ cursorAt: '20, 40' }", function() { test("{ distance: 10 }", function() { expect( 3 ); - el = $("#draggable2").draggable({ distance: 10 }); + var el = $("#draggable2").draggable({ distance: 10 }); TestHelpers.draggable.testDrag(el, el, -9, -9, 0, 0, 'distance not met'); TestHelpers.draggable.testDrag(el, el, -10, -10, -10, -10, 'distance met'); @@ -410,7 +422,7 @@ test("{ distance: 10 }", function() { test("{ grid: [50, 50] }, relative", function() { expect( 2 ); - el = $("#draggable1").draggable({ grid: [50, 50] }); + var el = $("#draggable1").draggable({ grid: [50, 50] }); TestHelpers.draggable.testDrag(el, el, 24, 24, 0, 0); TestHelpers.draggable.testDrag(el, el, 26, 25, 50, 50); }); @@ -418,7 +430,7 @@ test("{ grid: [50, 50] }, relative", function() { test("{ grid: [50, 50] }, absolute", function() { expect( 2 ); - el = $("#draggable2").draggable({ grid: [50, 50] }); + var el = $("#draggable2").draggable({ grid: [50, 50] }); TestHelpers.draggable.testDrag(el, el, 24, 24, 0, 0); TestHelpers.draggable.testDrag(el, el, 26, 25, 50, 50); }); @@ -426,7 +438,7 @@ test("{ grid: [50, 50] }, absolute", function() { test("{ handle: 'span' }", function() { expect( 2 ); - el = $("#draggable2").draggable({ handle: 'span' }); + var el = $("#draggable2").draggable({ handle: 'span' }); TestHelpers.draggable.testDrag(el, "#draggable2 span", 50, 50, 50, 50, "drag span"); TestHelpers.draggable.shouldNotMove(el, "drag element"); @@ -435,21 +447,21 @@ test("{ handle: 'span' }", function() { test("{ helper: 'clone' }, relative", function() { expect( 1 ); - el = $("#draggable1").draggable({ helper: "clone" }); + var el = $("#draggable1").draggable({ helper: "clone" }); TestHelpers.draggable.shouldNotMove(el); }); test("{ helper: 'clone' }, absolute", function() { expect( 1 ); - el = $("#draggable2").draggable({ helper: "clone" }); + var el = $("#draggable2").draggable({ helper: "clone" }); TestHelpers.draggable.shouldNotMove(el); }); test("{ helper: 'original' }, relative, with scroll offset on parent", function() { expect( 3 ); - el = $("#draggable1").draggable({ helper: "original" }); + var el = $("#draggable1").draggable({ helper: "original" }); TestHelpers.draggable.setScroll(); TestHelpers.draggable.testScroll(el, 'relative'); @@ -467,7 +479,7 @@ test("{ helper: 'original' }, relative, with scroll offset on parent", function( test("{ helper: 'original' }, relative, with scroll offset on root", function() { expect( 3 ); - el = $("#draggable1").draggable({ helper: "original" }); + var el = $("#draggable1").draggable({ helper: "original" }); TestHelpers.draggable.setScroll('root'); TestHelpers.draggable.testScroll(el, 'relative'); @@ -486,7 +498,7 @@ test("{ helper: 'original' }, relative, with scroll offset on root and parent", expect(3); - el = $("#draggable1").draggable({ helper: "original" }); + var el = $("#draggable1").draggable({ helper: "original" }); TestHelpers.draggable.setScroll(); TestHelpers.draggable.setScroll('root'); @@ -509,7 +521,7 @@ test("{ helper: 'original' }, absolute, with scroll offset on parent", function( expect(3); - el = $("#draggable1").css({ position: 'absolute', top: 0, left: 0 }).draggable({ helper: "original" }); + var el = $("#draggable1").css({ position: 'absolute', top: 0, left: 0 }).draggable({ helper: "original" }); TestHelpers.draggable.setScroll(); TestHelpers.draggable.testScroll(el, 'relative'); @@ -528,7 +540,7 @@ test("{ helper: 'original' }, absolute, with scroll offset on root", function() expect(3); - el = $("#draggable1").css({ position: 'absolute', top: 0, left: 0 }).draggable({ helper: "original" }); + var el = $("#draggable1").css({ position: 'absolute', top: 0, left: 0 }).draggable({ helper: "original" }); TestHelpers.draggable.setScroll('root'); TestHelpers.draggable.testScroll(el, 'relative'); @@ -547,7 +559,7 @@ test("{ helper: 'original' }, absolute, with scroll offset on root and parent", expect(3); - el = $("#draggable1").css({ position: 'absolute', top: 0, left: 0 }).draggable({ helper: "original" }); + var el = $("#draggable1").css({ position: 'absolute', top: 0, left: 0 }).draggable({ helper: "original" }); TestHelpers.draggable.setScroll(); TestHelpers.draggable.setScroll('root'); @@ -570,7 +582,7 @@ test("{ helper: 'original' }, fixed, with scroll offset on parent", function() { expect(3); - el = $("#draggable1").css({ position: 'fixed', top: 0, left: 0 }).draggable({ helper: "original" }); + var el = $("#draggable1").css({ position: 'fixed', top: 0, left: 0 }).draggable({ helper: "original" }); TestHelpers.draggable.setScroll(); TestHelpers.draggable.testScroll(el, 'relative'); @@ -589,7 +601,7 @@ test("{ helper: 'original' }, fixed, with scroll offset on root", function() { expect(3); - el = $("#draggable1").css({ position: 'fixed', top: 0, left: 0 }).draggable({ helper: "original" }); + var el = $("#draggable1").css({ position: 'fixed', top: 0, left: 0 }).draggable({ helper: "original" }); TestHelpers.draggable.setScroll('root'); TestHelpers.draggable.testScroll(el, 'relative'); @@ -607,7 +619,7 @@ test("{ helper: 'original' }, fixed, with scroll offset on root and parent", fun expect(3); - el = $("#draggable1").css({ position: 'fixed', top: 0, left: 0 }).draggable({ helper: "original" }); + var el = $("#draggable1").css({ position: 'fixed', top: 0, left: 0 }).draggable({ helper: "original" }); TestHelpers.draggable.setScroll(); TestHelpers.draggable.setScroll('root'); @@ -631,11 +643,10 @@ test("{ helper: 'clone' }, absolute", function() { expect(1); var helperOffset = null, - origOffset = $("#draggable1").offset(); - - el = $("#draggable1").draggable({ helper: "clone", drag: function(event, ui) { - helperOffset = ui.helper.offset(); - } }); + origOffset = $("#draggable1").offset(), + el = $("#draggable1").draggable({ helper: "clone", drag: function(event, ui) { + helperOffset = ui.helper.offset(); + } }); TestHelpers.draggable.drag(el, 1, 1); deepEqual({ top: helperOffset.top-1, left: helperOffset.left-1 }, origOffset, 'dragged[1, 1] '); @@ -648,11 +659,10 @@ test("{ helper: 'clone' }, absolute with scroll offset on parent", function() { TestHelpers.draggable.setScroll(); var helperOffset = null, - origOffset = null; - - el = $("#draggable1").draggable({ helper: "clone", drag: function(event, ui) { - helperOffset = ui.helper.offset(); - } }); + origOffset = null, + el = $("#draggable1").draggable({ helper: "clone", drag: function(event, ui) { + helperOffset = ui.helper.offset(); + } }); $("#main").css('position', 'relative'); origOffset = $("#draggable1").offset(); @@ -679,11 +689,10 @@ test("{ helper: 'clone' }, absolute with scroll offset on root", function() { TestHelpers.draggable.setScroll('root'); var helperOffset = null, - origOffset = null; - - el = $("#draggable1").draggable({ helper: "clone", drag: function(event, ui) { - helperOffset = ui.helper.offset(); - } }); + origOffset = null, + el = $("#draggable1").draggable({ helper: "clone", drag: function(event, ui) { + helperOffset = ui.helper.offset(); + } }); $("#main").css('position', 'relative'); origOffset = $("#draggable1").offset(); @@ -710,12 +719,12 @@ test("{ helper: 'clone' }, absolute with scroll offset on root and parent", func TestHelpers.draggable.setScroll('root'); TestHelpers.draggable.setScroll(); - var helperOffset = null, - origOffset = null; - el = $("#draggable1").draggable({ helper: "clone", drag: function(event, ui) { - helperOffset = ui.helper.offset(); - } }); + var helperOffset = null, + origOffset = null, + el = $("#draggable1").draggable({ helper: "clone", drag: function(event, ui) { + helperOffset = ui.helper.offset(); + } }); $("#main").css('position', 'relative'); origOffset = $("#draggable1").offset(); @@ -742,7 +751,8 @@ test("{ opacity: 0.5 }", function() { expect(1); var opacity = null; - el = $("#draggable2").draggable({ + + $("#draggable2").draggable({ opacity: 0.5, start: function() { opacity = $(this).css("opacity"); @@ -762,7 +772,7 @@ test("{ zIndex: 10 }", function() { var actual, expected = 10; - el = $("#draggable2").draggable({ + $("#draggable2").draggable({ zIndex: expected, start: function() { actual = $(this).css("zIndex"); diff --git a/tests/unit/draggable/draggable_test_helpers.js b/tests/unit/draggable/draggable_test_helpers.js new file mode 100644 index 0000000000..7057df1f84 --- /dev/null +++ b/tests/unit/draggable/draggable_test_helpers.js @@ -0,0 +1,57 @@ +TestHelpers.draggable = { + // todo: remove the unreliable offset hacks + unreliableOffset: $.ui.ie && ( !document.documentMode || document.documentMode < 8 ) ? 2 : 0, + drag: function(handle, dx, dy) { + $(handle).simulate("drag", { + dx: dx || 0, + dy: dy || 0 + }); + }, + testDrag: function(el, handle, dx, dy, expectedDX, expectedDY, msg) { + var offsetAfter, actual, expected, + offsetBefore = el.offset(); + + TestHelpers.draggable.drag(handle, dx, dy); + offsetAfter = el.offset(); + + actual = { left: offsetAfter.left, top: offsetAfter.top }, + expected = { left: offsetBefore.left + expectedDX, top: offsetBefore.top + expectedDY }; + + msg = msg ? msg + "." : ""; + deepEqual(actual, expected, 'dragged[' + dx + ', ' + dy + '] ' + msg); + }, + shouldMove: function(el, why) { + TestHelpers.draggable.testDrag(el, el, 50, 50, 50, 50, why); + }, + shouldNotMove: function(el, why) { + TestHelpers.draggable.testDrag(el, el, 50, 50, 0, 0, why); + }, + testScroll: function(el, position ) { + var oldPosition = $("#main").css('position'); + $("#main").css('position', position); + TestHelpers.draggable.shouldMove(el, position+' parent'); + $("#main").css('position', oldPosition); + }, + restoreScroll: function( what ) { + if( what ) { + $(document).scrollTop(0); $(document).scrollLeft(0); + } else { + $("#main").scrollTop(0); $("#main").scrollLeft(0); + } + }, + setScroll: function( what ) { + if(what) { + // todo: currently, the draggable interaction doesn't properly account for scrolled pages, + // uncomment the line below to make the tests fail that should when the page is scrolled + // $(document).scrollTop(100); $(document).scrollLeft(100); + } else { + $("#main").scrollTop(100); $("#main").scrollLeft(100); + } + }, + border: function(el, side) { + return parseInt(el.css('border-' + side + '-width'), 10) || 0; + }, + margin: function(el, side) { + return parseInt(el.css('margin-' + side), 10) || 0; + } +}; \ No newline at end of file diff --git a/tests/unit/droppable/droppable.html b/tests/unit/droppable/droppable.html index cd29b1cdf3..7cd5eb0f54 100644 --- a/tests/unit/droppable/droppable.html +++ b/tests/unit/droppable/droppable.html @@ -27,6 +27,7 @@ + diff --git a/tests/unit/droppable/droppable_core.js b/tests/unit/droppable/droppable_core.js index 21763bc63d..c98850a03e 100644 --- a/tests/unit/droppable/droppable_core.js +++ b/tests/unit/droppable/droppable_core.js @@ -2,17 +2,6 @@ * droppable_core.js */ -TestHelpers.droppable = { - shouldDrop: function() { - // todo: actually implement this - ok(true, 'missing test - untested code is broken code'); - }, - shouldNotDrop: function() { - // todo: actually implement this - ok(true, 'missing test - untested code is broken code'); - } -}; - (function($) { module("droppable: core"); diff --git a/tests/unit/droppable/droppable_methods.js b/tests/unit/droppable/droppable_methods.js index 3f1293ae45..76501c5b1b 100644 --- a/tests/unit/droppable/droppable_methods.js +++ b/tests/unit/droppable/droppable_methods.js @@ -43,6 +43,9 @@ test("destroy", function() { test("enable", function() { expect(7); + + var el, expected, actual; + el = $("#droppable1").droppable({ disabled: true }); TestHelpers.droppable.shouldNotDrop(); el.droppable("enable"); @@ -55,13 +58,16 @@ test("enable", function() { equal(el.droppable("option", "disabled"), false, "disabled option setter"); TestHelpers.droppable.shouldDrop(); - var expected = $('
            ').droppable(), - actual = expected.droppable('enable'); + expected = $('
            ').droppable(), + actual = expected.droppable('enable'); equal(actual, expected, 'enable is chainable'); }); test("disable", function() { expect(7); + + var el, actual, expected; + el = $("#droppable1").droppable({ disabled: false }); TestHelpers.droppable.shouldDrop(); el.droppable("disable"); @@ -74,8 +80,8 @@ test("disable", function() { equal(el.droppable("option", "disabled"), true, "disabled option setter"); TestHelpers.droppable.shouldNotDrop(); - var expected = $('
            ').droppable(), - actual = expected.droppable('disable'); + expected = $('
            ').droppable(), + actual = expected.droppable('disable'); equal(actual, expected, 'disable is chainable'); }); diff --git a/tests/unit/droppable/droppable_options.js b/tests/unit/droppable/droppable_options.js index db3201e889..c2ecdcfda9 100644 --- a/tests/unit/droppable/droppable_options.js +++ b/tests/unit/droppable/droppable_options.js @@ -24,14 +24,14 @@ test("activeClass", function() { */ test("{ addClasses: true }, default", function() { expect( 1 ); - el = $("
            ").droppable({ addClasses: true }); + var el = $("
            ").droppable({ addClasses: true }); ok(el.is(".ui-droppable"), "'ui-droppable' class added"); el.droppable("destroy"); }); test("{ addClasses: false }", function() { expect( 1 ); - el = $("
            ").droppable({ addClasses: false }); + var el = $("
            ").droppable({ addClasses: false }); ok(!el.is(".ui-droppable"), "'ui-droppable' class not added"); el.droppable("destroy"); }); diff --git a/tests/unit/droppable/droppable_test_helpers.js b/tests/unit/droppable/droppable_test_helpers.js new file mode 100644 index 0000000000..79311788c2 --- /dev/null +++ b/tests/unit/droppable/droppable_test_helpers.js @@ -0,0 +1,10 @@ +TestHelpers.droppable = { + shouldDrop: function() { + // todo: actually implement this + ok(true, 'missing test - untested code is broken code'); + }, + shouldNotDrop: function() { + // todo: actually implement this + ok(true, 'missing test - untested code is broken code'); + } +}; \ No newline at end of file diff --git a/tests/unit/resizable/resizable.html b/tests/unit/resizable/resizable.html index 50099efeea..eca465ae90 100644 --- a/tests/unit/resizable/resizable.html +++ b/tests/unit/resizable/resizable.html @@ -26,6 +26,7 @@ + diff --git a/tests/unit/resizable/resizable_core.js b/tests/unit/resizable/resizable_core.js index f4e6cdedd8..01f15bd4be 100644 --- a/tests/unit/resizable/resizable_core.js +++ b/tests/unit/resizable/resizable_core.js @@ -2,22 +2,6 @@ * resizable_core.js */ -TestHelpers.resizable = { - drag: function(el, dx, dy, complete) { - - // speed = sync -> Drag syncrhonously. - // speed = fast|slow -> Drag asyncrhonously - animated. - - //this mouseover is to work around a limitation in resizable - //TODO: fix resizable so handle doesn't require mouseover in order to be used - $(el).simulate("mouseover"); - - return $(el).simulate("drag", { - dx: dx||0, dy: dy||0, speed: 'sync', complete: complete - }); - } -}; - (function($) { module("resizable: core"); diff --git a/tests/unit/resizable/resizable_test_helpers.js b/tests/unit/resizable/resizable_test_helpers.js new file mode 100644 index 0000000000..fe6c849006 --- /dev/null +++ b/tests/unit/resizable/resizable_test_helpers.js @@ -0,0 +1,15 @@ +TestHelpers.resizable = { + drag: function(el, dx, dy, complete) { + + // speed = sync -> Drag syncrhonously. + // speed = fast|slow -> Drag asyncrhonously - animated. + + //this mouseover is to work around a limitation in resizable + //TODO: fix resizable so handle doesn't require mouseover in order to be used + $(el).simulate("mouseover"); + + return $(el).simulate("drag", { + dx: dx||0, dy: dy||0, speed: 'sync', complete: complete + }); + } +}; \ No newline at end of file diff --git a/tests/unit/selectable/selectable.html b/tests/unit/selectable/selectable.html index 18ffc6ef77..13718e1f3a 100644 --- a/tests/unit/selectable/selectable.html +++ b/tests/unit/selectable/selectable.html @@ -26,6 +26,7 @@ + diff --git a/tests/unit/selectable/selectable_core.js b/tests/unit/selectable/selectable_core.js index de89e66a73..9953b6c074 100644 --- a/tests/unit/selectable/selectable_core.js +++ b/tests/unit/selectable/selectable_core.js @@ -1,16 +1,3 @@ /* * selectable_core.js - */ - -TestHelpers.selectable = { - drag: function drag(el, dx, dy) { - var off = el.offset(), - pos = { clientX: off.left, clientY: off.top }; - el.simulate("mousedown", pos); - $(document).simulate("mousemove", pos); - pos.clientX += dx; - pos.clientY += dy; - $(document).simulate("mousemove", pos); - $(document).simulate("mouseup", pos); - } -}; \ No newline at end of file + */ \ No newline at end of file diff --git a/tests/unit/selectable/selectable_test_helpers.js b/tests/unit/selectable/selectable_test_helpers.js new file mode 100644 index 0000000000..c707ab622d --- /dev/null +++ b/tests/unit/selectable/selectable_test_helpers.js @@ -0,0 +1,12 @@ +TestHelpers.selectable = { + drag: function(el, dx, dy) { + var off = el.offset(), + pos = { clientX: off.left, clientY: off.top }; + el.simulate("mousedown", pos); + $(document).simulate("mousemove", pos); + pos.clientX += dx; + pos.clientY += dy; + $(document).simulate("mousemove", pos); + $(document).simulate("mouseup", pos); + } +}; \ No newline at end of file diff --git a/tests/unit/sortable/sortable.html b/tests/unit/sortable/sortable.html index 644b931ee9..b7b7b00076 100644 --- a/tests/unit/sortable/sortable.html +++ b/tests/unit/sortable/sortable.html @@ -26,6 +26,7 @@ + diff --git a/tests/unit/sortable/sortable_core.js b/tests/unit/sortable/sortable_core.js index f036121b8e..211f8ac954 100644 --- a/tests/unit/sortable/sortable_core.js +++ b/tests/unit/sortable/sortable_core.js @@ -1,19 +1,3 @@ /* * sortable_core.js - */ - -(function($) { - -TestHelpers.sortable = { - sort: function(handle, dx, dy, index, msg) { - $(handle).simulate("drag", { - dx: dx || 0, - dy: dy || 0 - }); - equal($(handle).parent().children().index(handle), index, msg); - } -}; - -module("sortable: core"); - -})(jQuery); + */ \ No newline at end of file diff --git a/tests/unit/sortable/sortable_methods.js b/tests/unit/sortable/sortable_methods.js index 85b418ac83..de32e2f5dd 100644 --- a/tests/unit/sortable/sortable_methods.js +++ b/tests/unit/sortable/sortable_methods.js @@ -42,6 +42,9 @@ test("destroy", function() { test("enable", function() { expect(5); + + var el, actual, expected; + el = $("#sortable").sortable({ disabled: true }); TestHelpers.sortable.sort($("li", el)[0], 0, 44, 0, '.sortable({ disabled: true })'); @@ -56,13 +59,16 @@ test("enable", function() { TestHelpers.sortable.sort($("li", el)[0], 0, 44, 2, '.sortable("option", "disabled", false)'); - var expected = $('
            ').sortable(), - actual = expected.sortable('enable'); + expected = $('
            ').sortable(), + actual = expected.sortable('enable'); equal(actual, expected, 'enable is chainable'); }); test("disable", function() { expect(7); + + var el, actual, expected; + el = $("#sortable").sortable({ disabled: false }); TestHelpers.sortable.sort($("li", el)[0], 0, 44, 2, '.sortable({ disabled: false })'); @@ -78,8 +84,8 @@ test("disable", function() { ok(el.sortable("widget").is(":not(.ui-state-disabled)"), "sortable element does not get ui-state-disabled since it's an interaction"); TestHelpers.sortable.sort($("li", el)[0], 0, 44, 0, '.sortable("option", "disabled", true)'); - var expected = $('
            ').sortable(), - actual = expected.sortable('disable'); + expected = $('
            ').sortable(), + actual = expected.sortable('disable'); equal(actual, expected, 'disable is chainable'); }); diff --git a/tests/unit/sortable/sortable_test_helpers.js b/tests/unit/sortable/sortable_test_helpers.js new file mode 100644 index 0000000000..7569b5797f --- /dev/null +++ b/tests/unit/sortable/sortable_test_helpers.js @@ -0,0 +1,9 @@ +TestHelpers.sortable = { + sort: function(handle, dx, dy, index, msg) { + $(handle).simulate("drag", { + dx: dx || 0, + dy: dy || 0 + }); + equal($(handle).parent().children().index(handle), index, msg); + } +}; \ No newline at end of file diff --git a/tests/unit/sortable/sortable_tickets.js b/tests/unit/sortable/sortable_tickets.js index c8ec08502c..eebd8dc211 100644 --- a/tests/unit/sortable/sortable_tickets.js +++ b/tests/unit/sortable/sortable_tickets.js @@ -8,12 +8,12 @@ module("sortable: tickets"); test("#3019: Stop fires too early", function() { expect(2); - var helper = null; - el = $("#sortable").sortable({ - stop: function(event, ui) { - helper = ui.helper; - } - }); + var helper = null, + el = $("#sortable").sortable({ + stop: function(event, ui) { + helper = ui.helper; + } + }); TestHelpers.sortable.sort($("li", el)[0], 0, 44, 2, 'Dragging the sortable'); equal(helper, null, "helper should be false"); From 068d597166468470dd8c7888a9f892f0ae4bedb5 Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Sun, 4 Nov 2012 09:31:56 -0500 Subject: [PATCH 116/151] Dev: fix IE fails in draggable and selectable - Fixed #8770 Dev: Remove globals and Standardize Test Suite --- tests/unit/draggable/draggable_core.js | 4 ++-- tests/unit/selectable/selectable_options.js | 2 +- tests/unit/selectable/selectable_test_helpers.js | 14 +++++--------- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/tests/unit/draggable/draggable_core.js b/tests/unit/draggable/draggable_core.js index 0e9d04be1f..39151d5f7f 100644 --- a/tests/unit/draggable/draggable_core.js +++ b/tests/unit/draggable/draggable_core.js @@ -24,8 +24,8 @@ test("element types", function() { offsetBefore = el.offset(); TestHelpers.draggable.drag(el, 50, 50); offsetAfter = el.offset(); - //there are some rounding errors in FF and Chrome, so we can't say equal, we have to settle for close enough - ok(offsetAfter.left - offsetBefore.left - 50 < 1 && offsetAfter.top - offsetBefore.top - 50 < 1, 'dragged[50, 50] ' + "<" + typeName + ">"); + // there are some rounding errors in FF, Chrome, and IE9, so we can't say equal, we have to settle for close enough + ok( offsetAfter.left - offsetBefore.left - 50 <= 1 && offsetAfter.top - offsetBefore.top - 50 <= 1, "dragged[50, 50] " + "<" + typeName + ">" ); el.draggable("destroy"); el.remove(); }); diff --git a/tests/unit/selectable/selectable_options.js b/tests/unit/selectable/selectable_options.js index 2b7fc16487..50e047427a 100644 --- a/tests/unit/selectable/selectable_options.js +++ b/tests/unit/selectable/selectable_options.js @@ -26,7 +26,7 @@ test("autoRefresh", function() { TestHelpers.selectable.drag(el, 1000, 1000); equal(actual, 0); sel.show(); - TestHelpers.selectable.drag(el, 1000, 1000); + TestHelpers.selectable.drag( sel[ 0 ], 1000, 1000 ); equal(actual, sel.length); el.selectable("destroy"); sel.show(); diff --git a/tests/unit/selectable/selectable_test_helpers.js b/tests/unit/selectable/selectable_test_helpers.js index c707ab622d..6f87efbb38 100644 --- a/tests/unit/selectable/selectable_test_helpers.js +++ b/tests/unit/selectable/selectable_test_helpers.js @@ -1,12 +1,8 @@ TestHelpers.selectable = { - drag: function(el, dx, dy) { - var off = el.offset(), - pos = { clientX: off.left, clientY: off.top }; - el.simulate("mousedown", pos); - $(document).simulate("mousemove", pos); - pos.clientX += dx; - pos.clientY += dy; - $(document).simulate("mousemove", pos); - $(document).simulate("mouseup", pos); + drag: function( el, dx, dy ) { + $( el ).simulate( "drag", { + dx: dx || 0, + dy: dy || 0 + }); } }; \ No newline at end of file From 1fe06f03fac30ce76b87eab8c5a9acc72becd587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Zaefferer?= Date: Sun, 4 Nov 2012 17:11:41 +0100 Subject: [PATCH 117/151] CSS Framework: Set out-of-view background-position for ui-icon. Fixes #5659 - CSS Framework: Don't show icon when only ui-icon class is present. --- themes/base/jquery.ui.theme.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/themes/base/jquery.ui.theme.css b/themes/base/jquery.ui.theme.css index bf8ef96338..67b74dcd7f 100644 --- a/themes/base/jquery.ui.theme.css +++ b/themes/base/jquery.ui.theme.css @@ -47,7 +47,7 @@ ----------------------------------*/ /* states and images */ -.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; } +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; background-position: 16px 16px; } .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; } .ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsHeader}*/; } .ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png)/*{iconsDefault}*/; } @@ -245,4 +245,4 @@ /* Overlays */ .ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; } -.ui-widget-shadow { margin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/; padding: 8px/*{thicknessShadow}*/; background: #aaaaaa/*{bgColorShadow}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; -moz-border-radius: 8px/*{cornerRadiusShadow}*/; -khtml-border-radius: 8px/*{cornerRadiusShadow}*/; -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; border-radius: 8px/*{cornerRadiusShadow}*/; } \ No newline at end of file +.ui-widget-shadow { margin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/; padding: 8px/*{thicknessShadow}*/; background: #aaaaaa/*{bgColorShadow}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; -moz-border-radius: 8px/*{cornerRadiusShadow}*/; -khtml-border-radius: 8px/*{cornerRadiusShadow}*/; -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; border-radius: 8px/*{cornerRadiusShadow}*/; } From a8de99c791ae24e558920e1756fb7d0bf9dfc166 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Mon, 5 Nov 2012 09:37:01 -0500 Subject: [PATCH 118/151] Dialog: Don't use .attr( props, true ). --- ui/jquery.ui.dialog.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/ui/jquery.ui.dialog.js b/ui/jquery.ui.dialog.js index dcf44580ef..203618fc25 100644 --- a/ui/jquery.ui.dialog.js +++ b/ui/jquery.ui.dialog.js @@ -334,15 +334,18 @@ $.widget("ui.dialog", { } if ( hasButtons ) { $.each( buttons, function( name, props ) { + var button, click; props = $.isFunction( props ) ? { click: props, text: name } : props; - var button = $( "" ) - .attr( props, true ) - .unbind( "click" ) - .click(function() { - props.click.apply( that.element[0], arguments ); - }) + // Default to a non-submitting button + props = $.extend( { type: "button" }, props ); + // Change the context for the click callback to be the main element + click = props.click; + props.click = function() { + click.apply( that.element[0], arguments ); + }; + button = $( "", props ) .appendTo( that.uiButtonSet ); if ( $.fn.button ) { button.button(); From c67727582148d1d4ed657b654eff5da914c7ac97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Mon, 5 Nov 2012 11:28:04 -0500 Subject: [PATCH 119/151] Core: Simplify IE check now that we don't care about IE6. --- ui/jquery.ui.core.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/ui/jquery.ui.core.js b/ui/jquery.ui.core.js index fadd42cad4..26a956b1ae 100644 --- a/ui/jquery.ui.core.js +++ b/ui/jquery.ui.core.js @@ -235,11 +235,7 @@ $.support.selectstart = "onselectstart" in document.createElement( "div" ); // deprecated - -(function() { - var uaMatch = /msie ([\w.]+)/.exec( navigator.userAgent.toLowerCase() ) || []; - $.ui.ie = uaMatch.length ? true : false; -})(); +$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() ); $.fn.extend({ disableSelection: function() { From 8bdf0359bbb3401c053fa453496ffd0c4b9f61bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Mon, 5 Nov 2012 11:31:33 -0500 Subject: [PATCH 120/151] Skip collision: fit test in IE until TestSwarm stops using iframes. --- tests/unit/position/position_core.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/unit/position/position_core.js b/tests/unit/position/position_core.js index 3b749a2186..7b51223acf 100644 --- a/tests/unit/position/position_core.js +++ b/tests/unit/position/position_core.js @@ -342,6 +342,8 @@ test( "collision: fit, no collision", function() { }, "with offset" ); }); +// Currently failing in IE8 due to the iframe used by TestSwarm +if ( !/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() ) ) { test( "collision: fit, collision", function() { expect( 2 + (scrollTopSupport() ? 1 : 0) ); @@ -372,6 +374,7 @@ test( "collision: fit, collision", function() { win.scrollTop( 0 ).scrollLeft( 0 ); } }); +} test( "collision: flip, no collision", function() { expect( 2 ); From 8b3e57024138f1a40be762fd5d29cc390129a8ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Zaefferer?= Date: Mon, 5 Nov 2012 18:37:48 +0100 Subject: [PATCH 121/151] Menu: Look into submenus for uninitialized menu items. Fixes #8773 - Menu: refresh() doesn't refresh existing submenus. --- tests/unit/menu/menu_methods.js | 9 +++++++ ui/jquery.ui.menu.js | 47 +++++++++++++++++---------------- 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/tests/unit/menu/menu_methods.js b/tests/unit/menu/menu_methods.js index c49783c3e4..a7e78ea699 100644 --- a/tests/unit/menu/menu_methods.js +++ b/tests/unit/menu/menu_methods.js @@ -60,6 +60,15 @@ test( "refresh", function() { equal( element.find( ".ui-menu-item" ).length, 5, "Incorrect number of menu items" ); }); +test( "refresh submenu", function() { + expect( 2 ); + var element = $( "#menu2" ).menu(); + equal( element.find( "ul:first .ui-menu-item" ).length, 3 ); + element.find( "ul" ).andSelf().append( "
          1. New Item
          2. " ); + element.menu("refresh"); + equal( element.find( "ul:first .ui-menu-item" ).length, 4 ); +}); + test( "widget", function() { expect( 2 ); var element = $( "#menu1" ).menu(), diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index 5d401da535..45c1ec2e4b 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -277,21 +277,35 @@ $.widget( "ui.menu", { }, refresh: function() { - // Initialize nested menus var menus, icon = this.options.icons.submenu, - submenus = this.element.find( this.options.menus + ":not(.ui-menu)" ) - .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) - .hide() - .attr({ - role: this.options.role, - "aria-hidden": "true", - "aria-expanded": "false" - }); + submenus = this.element.find( this.options.menus ); + + // Initialize nested menus + submenus.filter( ":not(.ui-menu)" ) + .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) + .hide() + .attr({ + role: this.options.role, + "aria-hidden": "true", + "aria-expanded": "false" + }) + .each(function() { + var menu = $( this ), + item = menu.prev( "a" ), + submenuCarat = $( "" ) + .addClass( "ui-menu-icon ui-icon " + icon ) + .data( "ui-menu-submenu-carat", true ); + + item + .attr( "aria-haspopup", "true" ) + .prepend( submenuCarat ); + menu.attr( "aria-labelledby", item.attr( "id" ) ); + }); - // Don't refresh list items that are already adapted menus = submenus.add( this.element ); + // Don't refresh list items that are already adapted menus.children( ":not(.ui-menu-item):has(a)" ) .addClass( "ui-menu-item" ) .attr( "role", "presentation" ) @@ -315,19 +329,6 @@ $.widget( "ui.menu", { // Add aria-disabled attribute to any disabled menu item menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" ); - submenus.each(function() { - var menu = $( this ), - item = menu.prev( "a" ), - submenuCarat = $( "" ) - .addClass( "ui-menu-icon ui-icon " + icon ) - .data( "ui-menu-submenu-carat", true ); - - item - .attr( "aria-haspopup", "true" ) - .prepend( submenuCarat ); - menu.attr( "aria-labelledby", item.attr( "id" ) ); - }); - // If the active item has been removed, blur the menu if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { this.blur(); From 98173a3d0ea8e2e6aeb19dda9b232cb65a0684e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Zaefferer?= Date: Mon, 5 Nov 2012 18:59:52 +0100 Subject: [PATCH 122/151] Tooltip: Check type on event directly, preventing TypeError when programmatically moving focus to track-toolipped-input. Fixes #8747 - Tooltip: Using the track option within dialogs creates JS errors --- tests/unit/tooltip/tooltip_options.js | 8 ++++++++ ui/jquery.ui.tooltip.js | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/unit/tooltip/tooltip_options.js b/tests/unit/tooltip/tooltip_options.js index 9f0de2b570..f9da27fb74 100644 --- a/tests/unit/tooltip/tooltip_options.js +++ b/tests/unit/tooltip/tooltip_options.js @@ -146,4 +146,12 @@ test( "track + show delay", function() { equal( $( ".ui-tooltip" ).css( "top" ), topVal + offsetVal + "px" ); }); +test( "track and programmatic focus", function() { + expect( 1 ); + $( "#qunit-fixture div input" ).tooltip({ + track: true + }).focus(); + equal( "inputtitle", $( ".ui-tooltip" ).text() ); +}); + }( jQuery ) ); diff --git a/ui/jquery.ui.tooltip.js b/ui/jquery.ui.tooltip.js index c05be1d457..325e20efba 100644 --- a/ui/jquery.ui.tooltip.js +++ b/ui/jquery.ui.tooltip.js @@ -252,7 +252,7 @@ $.widget( "ui.tooltip", { } tooltip.position( positionOption ); } - if ( this.options.track && event && /^mouse/.test( event.originalEvent.type ) ) { + if ( this.options.track && event && /^mouse/.test( event.type ) ) { this._on( this.document, { mousemove: position }); From 1d9eab1ead0d5a6f60e31437bb539eb3f804bacc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Zaefferer?= Date: Mon, 5 Nov 2012 19:05:58 +0100 Subject: [PATCH 123/151] Tooltip: Make 'flipfit flip' the collision default to avoid the tooltip ever overlapping the trigger. Also fix max-width for custom-content demo. Fixes #8739 - Tooltip: Default positioning on large items off. --- demos/tooltip/custom-content.html | 3 +++ ui/jquery.ui.tooltip.js | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/demos/tooltip/custom-content.html b/demos/tooltip/custom-content.html index 93172524ad..20039e2b83 100644 --- a/demos/tooltip/custom-content.html +++ b/demos/tooltip/custom-content.html @@ -22,6 +22,9 @@ width: 350px; height: 350px; } + .ui-tooltip { + max-width: 350px; + } + @@ -134,6 +135,7 @@ + diff --git a/ui/i18n/jquery.ui.datepicker-ky.js b/ui/i18n/jquery.ui.datepicker-ky.js new file mode 100644 index 0000000000..2f04308c4f --- /dev/null +++ b/ui/i18n/jquery.ui.datepicker-ky.js @@ -0,0 +1,23 @@ +/* Kyrgyz (UTF-8) initialisation for the jQuery UI date picker plugin. */ +/* Written by Sergey Kartashov (ebishkek@yandex.ru). */ +jQuery(function($){ + $.datepicker.regional['ky'] = { + closeText: 'Жабуу', + prevText: '<Мур', + nextText: 'Кий>', + currentText: 'Бүгүн', + monthNames: ['Январь','Февраль','Март','Апрель','Май','Июнь', + 'Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь'], + monthNamesShort: ['Янв','Фев','Мар','Апр','Май','Июн', + 'Июл','Авг','Сен','Окт','Ноя','Дек'], + dayNames: ['жекшемби', 'дүйшөмбү', 'шейшемби', 'шаршемби', 'бейшемби', 'жума', 'ишемби'], + dayNamesShort: ['жек', 'дүй', 'шей', 'шар', 'бей', 'жум', 'ише'], + dayNamesMin: ['Жк','Дш','Шш','Шр','Бш','Жм','Иш'], + weekHeader: 'Жум', + dateFormat: 'dd.mm.yy', + firstDay: 1, + isRTL: false, + showMonthAfterYear: false, + yearSuffix: ''}; +$.datepicker.setDefaults($.datepicker.regional['ky']); +}); \ No newline at end of file From 59865715fbec0462a0cc872195b44d3e3704a24b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Tue, 6 Nov 2012 14:41:44 -0500 Subject: [PATCH 131/151] Dialog: Set top and left properties in the default styles to avoid a bug in core. Fixes #8741 - Dialog: dialog with position:fixed goes offscreen when opening after scrolling down since v 1.9.0. --- themes/base/jquery.ui.dialog.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes/base/jquery.ui.dialog.css b/themes/base/jquery.ui.dialog.css index 4c54829e28..2f523b30c5 100644 --- a/themes/base/jquery.ui.dialog.css +++ b/themes/base/jquery.ui.dialog.css @@ -8,7 +8,7 @@ * * http://docs.jquery.com/UI/Dialog#theming */ -.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; outline: 0; } +.ui-dialog { position: absolute; top: 0; left: 0; padding: .2em; width: 300px; overflow: hidden; outline: 0; } .ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; } .ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } .ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } From 979bcab51353d53625c28bbe97dd1ce971ac2a5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Tue, 6 Nov 2012 15:09:21 -0500 Subject: [PATCH 132/151] Revert "Datepicker: Added Kyrgyz localisation" This reverts commit 4995ea05fef171bc6cb2f941f062997d2cab76a4. --- demos/datepicker/localization.html | 2 -- ui/i18n/jquery.ui.datepicker-ky.js | 23 ----------------------- 2 files changed, 25 deletions(-) delete mode 100644 ui/i18n/jquery.ui.datepicker-ky.js diff --git a/demos/datepicker/localization.html b/demos/datepicker/localization.html index f6d00631a8..4fd7a1c461 100644 --- a/demos/datepicker/localization.html +++ b/demos/datepicker/localization.html @@ -46,7 +46,6 @@ - @@ -135,7 +134,6 @@ - diff --git a/ui/i18n/jquery.ui.datepicker-ky.js b/ui/i18n/jquery.ui.datepicker-ky.js deleted file mode 100644 index 2f04308c4f..0000000000 --- a/ui/i18n/jquery.ui.datepicker-ky.js +++ /dev/null @@ -1,23 +0,0 @@ -/* Kyrgyz (UTF-8) initialisation for the jQuery UI date picker plugin. */ -/* Written by Sergey Kartashov (ebishkek@yandex.ru). */ -jQuery(function($){ - $.datepicker.regional['ky'] = { - closeText: 'Жабуу', - prevText: '<Мур', - nextText: 'Кий>', - currentText: 'Бүгүн', - monthNames: ['Январь','Февраль','Март','Апрель','Май','Июнь', - 'Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь'], - monthNamesShort: ['Янв','Фев','Мар','Апр','Май','Июн', - 'Июл','Авг','Сен','Окт','Ноя','Дек'], - dayNames: ['жекшемби', 'дүйшөмбү', 'шейшемби', 'шаршемби', 'бейшемби', 'жума', 'ишемби'], - dayNamesShort: ['жек', 'дүй', 'шей', 'шар', 'бей', 'жум', 'ише'], - dayNamesMin: ['Жк','Дш','Шш','Шр','Бш','Жм','Иш'], - weekHeader: 'Жум', - dateFormat: 'dd.mm.yy', - firstDay: 1, - isRTL: false, - showMonthAfterYear: false, - yearSuffix: ''}; -$.datepicker.setDefaults($.datepicker.regional['ky']); -}); \ No newline at end of file From 75bd22eb731f5a81099ad97c88eede3862195fec Mon Sep 17 00:00:00 2001 From: Avinash R Date: Wed, 7 Nov 2012 10:05:00 -0500 Subject: [PATCH 133/151] Widget: Bridge falls back to name if there is no widgetFullName, and always stores instances in data. Fixed #8775 - Widget: Bridge fails if widgetFullName is not supplied. --- tests/unit/widget/widget_core.js | 53 ++++++++++++++++++++++++++++++++ ui/jquery.ui.widget.js | 4 +-- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/tests/unit/widget/widget_core.js b/tests/unit/widget/widget_core.js index 7bddc7f5c1..acf461a9af 100644 --- a/tests/unit/widget/widget_core.js +++ b/tests/unit/widget/widget_core.js @@ -4,6 +4,7 @@ module( "widget factory", { teardown: function() { if ( $.ui ) { delete $.ui.testWidget; + delete $.fn.testWidget; } } }); @@ -1305,4 +1306,56 @@ asyncTest( "_delay", function() { $( "#widget" ).testWidget(); }); +test( "$.widget.bridge()", function() { + expect( 9 ); + + var instance, ret, + elem = $( "
            " ); + + function TestWidget( options, element ) { + deepEqual( options, { foo: "bar" }, "options passed" ); + strictEqual( element, elem[ 0 ], "element passed" ); + } + + $.extend( TestWidget.prototype, { + method: function( param ) { + ok( true, "method called via .pluginName(methodName)" ); + equal( param, "value1", + "parameter passed via .pluginName(methodName, param)" ); + }, + getter: function() { + return "qux"; + } + }); + + $.widget.bridge( "testWidget", TestWidget ); + + ok( $.isFunction( $.fn.testWidget ), "jQuery plugin was created" ); + + strictEqual( elem.testWidget({ foo: "bar" }), elem, "plugin returns original jQuery object" ); + instance = elem.data( "testWidget" ); + equal( typeof instance, "object", "instance stored in .data(pluginName)" ); + + ret = elem.testWidget( "method", "value1" ); + equal( ret, elem, "jQuery object returned from method call" ); + + ret = elem.testWidget( "getter" ); + equal( ret, "qux", "getter returns value" ); +}); + +test( "$.widget.bridge() - widgetFullName", function() { + expect( 1 ); + + var instance, + elem = $( "
            " ); + + function TestWidget() {} + TestWidget.prototype.widgetFullName = "custom-widget"; + $.widget.bridge( "testWidget", TestWidget ); + + elem.testWidget(); + instance = elem.data( "custom-widget" ); + equal( typeof instance, "object", "instance stored in .data(widgetFullName)" ); +}); + }( jQuery ) ); diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index 00f36fe67c..5a069f2ef5 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -158,7 +158,7 @@ $.widget.extend = function( target ) { }; $.widget.bridge = function( name, object ) { - var fullName = object.prototype.widgetFullName; + var fullName = object.prototype.widgetFullName || name; $.fn[ name ] = function( options ) { var isMethodCall = typeof options === "string", args = slice.call( arguments, 1 ), @@ -194,7 +194,7 @@ $.widget.bridge = function( name, object ) { if ( instance ) { instance.option( options || {} )._init(); } else { - new object( options, this ); + $.data( this, fullName, new object( options, this ) ); } }); } From 1e19e5e90bd801540e98c67f583a2f5aa30ffb53 Mon Sep 17 00:00:00 2001 From: Sergey Kartashov Date: Fri, 2 Nov 2012 11:31:21 +0600 Subject: [PATCH 134/151] Datepicker: Added Kyrgyz localization. Fixes #8787 - Datepicker: Add Kyrgyz localization. --- demos/datepicker/localization.html | 2 ++ ui/i18n/jquery.ui.datepicker-ky.js | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 ui/i18n/jquery.ui.datepicker-ky.js diff --git a/demos/datepicker/localization.html b/demos/datepicker/localization.html index 4fd7a1c461..f6d00631a8 100644 --- a/demos/datepicker/localization.html +++ b/demos/datepicker/localization.html @@ -46,6 +46,7 @@ + @@ -134,6 +135,7 @@ + diff --git a/ui/i18n/jquery.ui.datepicker-ky.js b/ui/i18n/jquery.ui.datepicker-ky.js new file mode 100644 index 0000000000..d4466b12e6 --- /dev/null +++ b/ui/i18n/jquery.ui.datepicker-ky.js @@ -0,0 +1,24 @@ +/* Kyrgyz (UTF-8) initialisation for the jQuery UI date picker plugin. */ +/* Written by Sergey Kartashov (ebishkek@yandex.ru). */ +jQuery(function($){ + $.datepicker.regional['ky'] = { + closeText: 'Жабуу', + prevText: '<Мур', + nextText: 'Кий>', + currentText: 'Бүгүн', + monthNames: ['Январь','Февраль','Март','Апрель','Май','Июнь', + 'Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь'], + monthNamesShort: ['Янв','Фев','Мар','Апр','Май','Июн', + 'Июл','Авг','Сен','Окт','Ноя','Дек'], + dayNames: ['жекшемби', 'дүйшөмбү', 'шейшемби', 'шаршемби', 'бейшемби', 'жума', 'ишемби'], + dayNamesShort: ['жек', 'дүй', 'шей', 'шар', 'бей', 'жум', 'ише'], + dayNamesMin: ['Жк','Дш','Шш','Шр','Бш','Жм','Иш'], + weekHeader: 'Жум', + dateFormat: 'dd.mm.yy', + firstDay: 1, + isRTL: false, + showMonthAfterYear: false, + yearSuffix: '' + }; + $.datepicker.setDefaults($.datepicker.regional['ky']); +}); From 8976bc7e3d1f03254f914297b1be1b730690d2b8 Mon Sep 17 00:00:00 2001 From: Kris Borchers Date: Thu, 8 Nov 2012 12:02:25 -0600 Subject: [PATCH 135/151] Progressbar: Refactor to better handle option changes and sanitize values. Fixes #8785 - Progressbar: Remove _value() and always sanitize value option --- tests/unit/progressbar/progressbar_options.js | 18 ++++ ui/jquery.ui.progressbar.js | 83 +++++++++++++------ 2 files changed, 76 insertions(+), 25 deletions(-) diff --git a/tests/unit/progressbar/progressbar_options.js b/tests/unit/progressbar/progressbar_options.js index fd5988ebde..e4d9b7ab8e 100644 --- a/tests/unit/progressbar/progressbar_options.js +++ b/tests/unit/progressbar/progressbar_options.js @@ -60,3 +60,21 @@ test( "{ max : 5, value : 10 }", function() { }); deepEqual( 5, $( "#progressbar" ).progressbar( "value" ) ); }); + +test( "{ value : 10, max : 5 }", function() { + expect( 1 ); + $("#progressbar").progressbar({ + max: 5, + value: 10 + }); + deepEqual( 5, $( "#progressbar" ).progressbar( "value" ) ); +}); + +test( "{ max : 5 }", function() { + expect( 1 ); + $("#progressbar").progressbar({ + max: 10, + value: 10 + }).progressbar( "option", "max", 5 ); + deepEqual( 5, $( "#progressbar" ).progressbar( "value" ) ); +}); diff --git a/ui/jquery.ui.progressbar.js b/ui/jquery.ui.progressbar.js index cb561ebc6b..5a7fd87d37 100644 --- a/ui/jquery.ui.progressbar.js +++ b/ui/jquery.ui.progressbar.js @@ -24,19 +24,22 @@ $.widget( "ui.progressbar", { min: 0, _create: function() { + // Constrain initial value + this.options.value = this._constrainedValue(); + this.element .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) .attr({ role: "progressbar", "aria-valuemin": this.min, "aria-valuemax": this.options.max, - "aria-valuenow": this._value() + "aria-valuenow": this.options.value }); this.valueDiv = $( "
            " ) .appendTo( this.element ); - this.oldValue = this._value(); + this.oldValue = this.options.value; this._refreshValue(); }, @@ -53,52 +56,82 @@ $.widget( "ui.progressbar", { value: function( newValue ) { if ( newValue === undefined ) { - return this._value(); + return this.options.value; } - this._setOption( "value", newValue ); + this._setOption( "value", this._constrainedValue( newValue ) ); return this; }, - _setOption: function( key, value ) { - if ( key === "value" ) { - this.options.value = value; - this._refreshValue(); - if ( this._value() === this.options.max ) { - this._trigger( "complete" ); - } + _constrainedValue: function( newValue ) { + var val; + if ( newValue === undefined ) { + val = this.options.value; + } else { + val = newValue; } - this._super( key, value ); - }, - - _value: function() { - var val = this.options.value; - // normalize invalid value + // sanitize value if ( typeof val !== "number" ) { val = 0; } return Math.min( this.options.max, Math.max( this.min, val ) ); }, + _setOptions: function( options ) { + var key, val; + + for ( key in options ) { + if ( key === "value" ) { + // Store value to update last in case max is being updated at the same time + val = options[ key ]; + } else { + this._setOption( key, options[ key ] ); + } + } + + if ( val !== undefined ) { + this._setOption( "value", val ); + } + }, + + _setOption: function( key, value ) { + if ( key === "max" ) { + // Don't allow a max less than min + this.options.max = Math.max( this.min, value ); + this.options.value = this._constrainedValue(); + } + if ( key === "value" ) { + this.options.value = this._constrainedValue( value ); + } + else { + this._super( key, value ); + } + + this._refreshValue(); + }, + _percentage: function() { - return 100 * this._value() / this.options.max; + return 100 * this.options.value / this.options.max; }, _refreshValue: function() { - var value = this.value(), - percentage = this._percentage(); + var percentage = this._percentage(); - if ( this.oldValue !== value ) { - this.oldValue = value; + if ( this.oldValue !== this.options.value ) { + this.oldValue = this.options.value; this._trigger( "change" ); } + if ( this.options.value === this.options.max ) { + this._trigger( "complete" ); + } this.valueDiv - .toggle( value > this.min ) - .toggleClass( "ui-corner-right", value === this.options.max ) + .toggle( this.options.value > this.min ) + .toggleClass( "ui-corner-right", this.options.value === this.options.max ) .width( percentage.toFixed(0) + "%" ); - this.element.attr( "aria-valuenow", value ); + this.element.attr( "aria-valuemax", this.options.max ); + this.element.attr( "aria-valuenow", this.options.value ); } }); From 48e0aa0fd2782380931af43abb5bb92b73ebe4ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Fri, 9 Nov 2012 08:10:57 -0500 Subject: [PATCH 136/151] CSS: Update .ui-helper-hidden-accessible to match H5BP's current .visuallyhidden. Fixes #8793 - Dialog: Internal autocomplete causes scroll bars. --- themes/base/jquery.ui.core.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes/base/jquery.ui.core.css b/themes/base/jquery.ui.core.css index b94c043dac..5bfe620b9c 100644 --- a/themes/base/jquery.ui.core.css +++ b/themes/base/jquery.ui.core.css @@ -12,7 +12,7 @@ /* Layout helpers ----------------------------------*/ .ui-helper-hidden { display: none; } -.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); } +.ui-helper-hidden-accessible { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } .ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; } .ui-helper-clearfix:after { clear: both; } From 6e0a0553ce85997e4f37597800b440b1e4371b5b Mon Sep 17 00:00:00 2001 From: Ethan Romba Date: Tue, 10 Jul 2012 10:21:56 -0700 Subject: [PATCH 137/151] Resizable: Grid now respects min/max dimensions. Fixed #8435 - grid does not respect min/max dimensions --- tests/unit/resizable/resizable_options.js | 14 ++++++++ ui/jquery.ui.resizable.js | 44 +++++++++++++++-------- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/tests/unit/resizable/resizable_options.js b/tests/unit/resizable/resizable_options.js index 730a3389a8..4b47762ab8 100644 --- a/tests/unit/resizable/resizable_options.js +++ b/tests/unit/resizable/resizable_options.js @@ -117,6 +117,20 @@ test("grid", function() { equal( target.height(), 120, "compare height"); }); +test("grid (min/max dimensions)", function() { + expect(4); + + var handle = ".ui-resizable-se", target = $("#resizable1").resizable({ handles: "all", grid: 20, minWidth: 65, minHeight: 65, maxWidth: 135, maxHeight: 135 }); + + TestHelpers.resizable.drag(handle, 50, 50); + equal( target.width(), 120, "grid should respect maxWidth"); + equal( target.height(), 120, "grid should respect maxHeight"); + + TestHelpers.resizable.drag(handle, -100, -100); + equal( target.width(), 80, "grid should respect minWidth"); + equal( target.height(), 80, "grid should respect minHeight"); +}); + test("grid (wrapped)", function() { expect(4); diff --git a/ui/jquery.ui.resizable.js b/ui/jquery.ui.resizable.js index c2ad287162..c701c06be6 100644 --- a/ui/jquery.ui.resizable.js +++ b/ui/jquery.ui.resizable.js @@ -769,25 +769,39 @@ $.ui.plugin.add("resizable", "grid", { resize: function() { var that = $(this).data("resizable"), o = that.options, cs = that.size, os = that.originalSize, op = that.originalPosition, a = that.axis; o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid; - var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1); + var gridX = (o.grid[0]||1), gridY = (o.grid[1]||1), + ox = Math.round((cs.width - os.width) / gridX) * gridX, oy = Math.round((cs.height - os.height) / gridY) * gridY, + newWidth = os.width + ox, newHeight = os.height + oy, + isMaxWidth = o.maxWidth && (o.maxWidth < newWidth), isMaxHeight = o.maxHeight && (o.maxHeight < newHeight), + isMinWidth = o.minWidth && (o.minWidth > newWidth), isMinHeight = o.minHeight && (o.minHeight > newHeight); + + if (isMinWidth) { + newWidth = newWidth + gridX; + } + if (isMinHeight) { + newHeight = newHeight + gridY; + } + if (isMaxWidth) { + newWidth = newWidth - gridX; + } + if (isMaxHeight) { + newHeight = newHeight - gridY; + } if (/^(se|s|e)$/.test(a)) { - that.size.width = os.width + ox; - that.size.height = os.height + oy; - } - else if (/^(ne)$/.test(a)) { - that.size.width = os.width + ox; - that.size.height = os.height + oy; + that.size.width = newWidth; + that.size.height = newHeight; + } else if (/^(ne)$/.test(a)) { + that.size.width = newWidth; + that.size.height = newHeight; that.position.top = op.top - oy; - } - else if (/^(sw)$/.test(a)) { - that.size.width = os.width + ox; - that.size.height = os.height + oy; + } else if (/^(sw)$/.test(a)) { + that.size.width = newWidth; + that.size.height = newHeight; that.position.left = op.left - ox; - } - else { - that.size.width = os.width + ox; - that.size.height = os.height + oy; + } else { + that.size.width = newWidth; + that.size.height = newHeight; that.position.top = op.top - oy; that.position.left = op.left - ox; } From 84cd214486769a3527b3ab420219c8f9c78f9879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Fri, 9 Nov 2012 12:39:41 -0500 Subject: [PATCH 138/151] Widget: Added suppressDisabledCheck flag to _on(). Fixes #8800 - Widget: Ability to use _on() even when disabled. --- tests/unit/widget/widget_core.js | 40 ++++++++++++++++++++++++++++++++ ui/jquery.ui.widget.js | 15 +++++++++--- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/tests/unit/widget/widget_core.js b/tests/unit/widget/widget_core.js index acf461a9af..9180072e3f 100644 --- a/tests/unit/widget/widget_core.js +++ b/tests/unit/widget/widget_core.js @@ -662,6 +662,46 @@ test( "._on() to element (default)", function() { .trigger( "keydown" ); }); +test( "._on() to element with suppressDisabledCheck", function() { + expect( 18 ); + var that, widget; + $.widget( "ui.testWidget", { + _create: function() { + that = this; + this._on( true, { + keyup: this.keyup, + keydown: "keydown" + }); + }, + keyup: function( event ) { + equal( that, this ); + equal( that.element[0], event.currentTarget ); + equal( "keyup", event.type ); + }, + keydown: function( event ) { + equal( that, this ); + equal( that.element[0], event.currentTarget ); + equal( "keydown", event.type ); + } + }); + widget = $( "
            " ) + .testWidget() + .trigger( "keyup" ) + .trigger( "keydown" ); + widget + .testWidget( "disable" ) + .trigger( "keyup" ) + .trigger( "keydown" ); + widget + .testWidget( "enable" ) + .trigger( "keyup" ) + .trigger( "keydown" ); + widget + .testWidget( "destroy" ) + .trigger( "keyup" ) + .trigger( "keydown" ); +}); + test( "._on() to descendent", function() { expect( 12 ); var that, widget, descendant; diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index 5a069f2ef5..83696e9405 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -359,9 +359,17 @@ $.Widget.prototype = { return this._setOption( "disabled", true ); }, - _on: function( element, handlers ) { + _on: function( suppressDisabledCheck, element, handlers ) { var delegateElement, instance = this; + + // no suppressDisabledCheck flag, shuffle arguments + if ( typeof suppressDisabledCheck !== "boolean" ) { + handlers = element; + element = suppressDisabledCheck; + suppressDisabledCheck = false; + } + // no element argument, shuffle and use this.element if ( !handlers ) { handlers = element; @@ -378,8 +386,9 @@ $.Widget.prototype = { // allow widgets to customize the disabled handling // - disabled as an array instead of boolean // - disabled class as method for disabling individual parts - if ( instance.options.disabled === true || - $( this ).hasClass( "ui-state-disabled" ) ) { + if ( !suppressDisabledCheck && + ( instance.options.disabled === true || + $( this ).hasClass( "ui-state-disabled" ) ) ) { return; } return ( typeof handler === "string" ? instance[ handler ] : handler ) From d44557f50ad7b3c512bdd8bc2ba3eed5672b3b12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Fri, 9 Nov 2012 12:51:26 -0500 Subject: [PATCH 139/151] Widget: Removed dual storage of widget instances. Fixes #8801 - Widget: Remove data fallbacks for widget names. --- tests/unit/widget/widget_core.js | 18 ++++++------------ ui/jquery.ui.widget.js | 3 --- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/tests/unit/widget/widget_core.js b/tests/unit/widget/widget_core.js index 9180072e3f..b0812638a2 100644 --- a/tests/unit/widget/widget_core.js +++ b/tests/unit/widget/widget_core.js @@ -89,9 +89,9 @@ test( "custom selector expression", function() { }); test( "jQuery usage", function() { - expect( 16 ); + expect( 14 ); - var elem, instance, ret, bcInstance, + var elem, instance, ret, shouldCreate = false; $.widget( "ui.testWidget", { @@ -134,12 +134,6 @@ test( "jQuery usage", function() { ret = elem.testWidget( "methodWithParams", "value1", "value2" ); equal( ret, elem, "jQuery object returned from method call" ); - // 1.9 BC for #7810 - // TODO remove - bcInstance = elem.data("testWidget"); - equal( typeof bcInstance, "object", "instance stored in .data(pluginName)" ); - equal( bcInstance.element[0], elem[0], "element stored on widget" ); - ret = elem.testWidget( "getterSetterMethod" ); equal( ret, 5, "getter/setter can act as getter" ); ret = elem.testWidget( "getterSetterMethod", 30 ); @@ -837,7 +831,7 @@ test( "_on() to common element", function() { ok( true, "handler triggered" ); } }); - var widget = $( "#widget" ).testWidget().data( "testWidget" ); + var widget = $( "#widget" ).testWidget().data( "ui-testWidget" ); $( "#widget-wrapper" ).testWidget(); widget.destroy(); $( document ).trigger( "customevent" ); @@ -849,7 +843,7 @@ test( "_off() - single event", function() { $.widget( "ui.testWidget", {} ); var shouldTriggerWidget, shouldTriggerOther, element = $( "#widget" ), - widget = element.testWidget().data( "testWidget" ); + widget = element.testWidget().data( "ui-testWidget" ); widget._on( element, { foo: function() { ok( shouldTriggerWidget, "foo called from _on" ); }}); @@ -870,7 +864,7 @@ test( "_off() - multiple events", function() { $.widget( "ui.testWidget", {} ); var shouldTriggerWidget, shouldTriggerOther, element = $( "#widget" ), - widget = element.testWidget().data( "testWidget" ); + widget = element.testWidget().data( "ui-testWidget" ); widget._on( element, { foo: function() { ok( shouldTriggerWidget, "foo called from _on" ); @@ -898,7 +892,7 @@ test( "_off() - all events", function() { $.widget( "ui.testWidget", {} ); var shouldTriggerWidget, shouldTriggerOther, element = $( "#widget" ), - widget = element.testWidget().data( "testWidget" ); + widget = element.testWidget().data( "ui-testWidget" ); widget._on( element, { foo: function() { ok( shouldTriggerWidget, "foo called from _on" ); diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index 83696e9405..65ac155ae4 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -231,9 +231,6 @@ $.Widget.prototype = { this.focusable = $(); if ( element !== this ) { - // 1.9 BC for #7810 - // TODO remove dual storage - $.data( element, this.widgetName, this ); $.data( element, this.widgetFullName, this ); this._on( this.element, { remove: function( event ) { From 1cdeeccab0e76495842cad9d04e686aee802777d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Fri, 9 Nov 2012 12:54:33 -0500 Subject: [PATCH 140/151] Widget: Suppress disabled check when binding destroy to the remove event. Fixes #8769 - Widget: ui-state-disabled blocks destroy to be triggered on remove. --- tests/unit/widget/widget_core.js | 6 ++++++ ui/jquery.ui.widget.js | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/unit/widget/widget_core.js b/tests/unit/widget/widget_core.js index b0812638a2..418cc4d397 100644 --- a/tests/unit/widget/widget_core.js +++ b/tests/unit/widget/widget_core.js @@ -1197,6 +1197,12 @@ test( "._trigger() - instance as element", function() { }); }); + test( "auto-destroy - .remove() when disabled", function() { + shouldDestroy( true, function() { + $( "#widget" ).testWidget({ disabled: true }).remove(); + }); + }); + test( "auto-destroy - .remove() on parent", function() { shouldDestroy( true, function() { $( "#widget" ).testWidget().parent().remove(); diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index 65ac155ae4..02f89bc988 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -232,7 +232,7 @@ $.Widget.prototype = { if ( element !== this ) { $.data( element, this.widgetFullName, this ); - this._on( this.element, { + this._on( true, this.element, { remove: function( event ) { if ( event.target === element ) { this.destroy(); From 498aadf644ddca86de838dc2001267ded972df2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Fri, 9 Nov 2012 13:07:53 -0500 Subject: [PATCH 141/151] Tooltip: Ignore disabled checks when closing. Fixes #8758 - Tooltip: Tooltip is shown, but not hidden if element has class=ui-state-disabled. --- tests/unit/tooltip/tooltip_core.js | 13 +++++++++++++ ui/jquery.ui.tooltip.js | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/unit/tooltip/tooltip_core.js b/tests/unit/tooltip/tooltip_core.js index f0aed72aad..69936dba20 100644 --- a/tests/unit/tooltip/tooltip_core.js +++ b/tests/unit/tooltip/tooltip_core.js @@ -94,4 +94,17 @@ test( "form containing an input with name title", function() { equal( $( ".ui-tooltip" ).length, 0, "no tooltip for form" ); }); +test( "tooltip on .ui-state-disabled element", function() { + expect( 2 ); + + var container = $( "#contains-tooltipped" ).tooltip(), + element = $( "#contained-tooltipped" ).addClass( "ui-state-disabled" ); + + element.trigger( "mouseover" ); + equal( $( ".ui-tooltip" ).length, 1 ); + + container.empty(); + equal( $( ".ui-tooltip" ).length, 0 ); +}); + }( jQuery ) ); diff --git a/ui/jquery.ui.tooltip.js b/ui/jquery.ui.tooltip.js index 5145884a3f..e5b496beeb 100644 --- a/ui/jquery.ui.tooltip.js +++ b/ui/jquery.ui.tooltip.js @@ -299,7 +299,7 @@ $.widget( "ui.tooltip", { if ( !event || event.type === "focusin" ) { events.focusout = "close"; } - this._on( target, events ); + this._on( true, target, events ); }, close: function( event ) { From f5870712c1f73c474a6980bb16d12768f4150984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Fri, 9 Nov 2012 13:28:13 -0500 Subject: [PATCH 142/151] Updated all widgets to use proper data keys when getting plugin instances. --- tests/unit/autocomplete/autocomplete_core.js | 4 +-- tests/unit/dialog/dialog_events.js | 4 +-- tests/unit/draggable/draggable_events.js | 2 +- tests/unit/tabs/tabs_core.js | 6 ++-- tests/unit/tabs/tabs_options.js | 4 +-- ui/jquery.ui.autocomplete.js | 2 +- ui/jquery.ui.button.js | 2 +- ui/jquery.ui.dialog.js | 8 ++--- ui/jquery.ui.draggable.js | 34 ++++++++++---------- ui/jquery.ui.droppable.js | 12 +++---- ui/jquery.ui.resizable.js | 26 +++++++-------- ui/jquery.ui.sortable.js | 4 +-- 12 files changed, 54 insertions(+), 54 deletions(-) diff --git a/tests/unit/autocomplete/autocomplete_core.js b/tests/unit/autocomplete/autocomplete_core.js index f2062cacda..845a3b19de 100644 --- a/tests/unit/autocomplete/autocomplete_core.js +++ b/tests/unit/autocomplete/autocomplete_core.js @@ -99,7 +99,7 @@ test( "allow form submit on enter when menu is not active", function() { delay: 0, minLength: 0 }); - element.data( "autocomplete" )._move = function() { + element.data( "ui-autocomplete" )._move = function() { didMove = true; }; element.simulate( "keydown", { keyCode: ( isKeyUp ? $.ui.keyCode.UP : $.ui.keyCode.DOWN ) } ); @@ -114,7 +114,7 @@ test( "allow form submit on enter when menu is not active", function() { delay: 0, minLength: 0 }); - element.data( "autocomplete" )._move = function() { + element.data( "ui-autocomplete" )._move = function() { ok( true, "repsond to arrow" ); }; element.autocomplete( "search" ); diff --git a/tests/unit/dialog/dialog_events.js b/tests/unit/dialog/dialog_events.js index c5090d8f67..ee7a8bcb3e 100644 --- a/tests/unit/dialog/dialog_events.js +++ b/tests/unit/dialog/dialog_events.js @@ -11,7 +11,7 @@ test("open", function() { var el = $("
            "); el.dialog({ open: function(ev, ui) { - ok(el.data("dialog")._isOpen, "interal _isOpen flag is set"); + ok(el.data("ui-dialog")._isOpen, "interal _isOpen flag is set"); ok(true, 'autoOpen: true fires open callback'); equal(this, el[0], "context of callback"); equal(ev.type, 'dialogopen', 'event type in callback'); @@ -30,7 +30,7 @@ test("open", function() { deepEqual(ui, {}, 'ui hash in callback'); } }).bind('dialogopen', function(ev, ui) { - ok(el.data("dialog")._isOpen, "interal _isOpen flag is set"); + ok(el.data("ui-dialog")._isOpen, "interal _isOpen flag is set"); ok(true, 'dialog("open") fires open event'); equal(this, el[0], 'context of event'); deepEqual(ui, {}, 'ui hash in event'); diff --git a/tests/unit/draggable/draggable_events.js b/tests/unit/draggable/draggable_events.js index 6b1136cb04..5eab97713c 100644 --- a/tests/unit/draggable/draggable_events.js +++ b/tests/unit/draggable/draggable_events.js @@ -79,7 +79,7 @@ test("stopping the stop callback", function() { TestHelpers.draggable.drag(el, 10, 10); - ok($("#draggable2").data('draggable').helper, "the clone should not be deleted if the stop callback is stopped"); + ok($("#draggable2").data('ui-draggable').helper, "the clone should not be deleted if the stop callback is stopped"); }); diff --git a/tests/unit/tabs/tabs_core.js b/tests/unit/tabs/tabs_core.js index 6307c44887..20364a37db 100644 --- a/tests/unit/tabs/tabs_core.js +++ b/tests/unit/tabs/tabs_core.js @@ -33,7 +33,7 @@ test( "nested list", function() { expect( 1 ); var element = $( "#tabs6" ).tabs(); - equal( element.data( "tabs" ).anchors.length, 2, "should contain 2 tab" ); + equal( element.data( "ui-tabs" ).anchors.length, 2, "should contain 2 tab" ); }); test( "disconnected from DOM", function() { @@ -155,7 +155,7 @@ asyncTest( "keyboard support - LEFT, RIGHT, UP, DOWN, HOME, END, SPACE, ENTER", panels = element.find( ".ui-tabs-panel" ), keyCode = $.ui.keyCode; - element.data( "tabs" ).delay = 50; + element.data( "ui-tabs" ).delay = 50; equal( tabs.filter( ".ui-state-focus" ).length, 0, "no tabs focused on init" ); tabs.eq( 0 ).simulate( "focus" ); @@ -306,7 +306,7 @@ asyncTest( "keyboard support - CTRL navigation", function() { panels = element.find( ".ui-tabs-panel" ), keyCode = $.ui.keyCode; - element.data( "tabs" ).delay = 50; + element.data( "ui-tabs" ).delay = 50; equal( tabs.filter( ".ui-state-focus" ).length, 0, "no tabs focused on init" ); tabs.eq( 0 ).simulate( "focus" ); diff --git a/tests/unit/tabs/tabs_options.js b/tests/unit/tabs/tabs_options.js index c320c9d467..f6e89e84f8 100644 --- a/tests/unit/tabs/tabs_options.js +++ b/tests/unit/tabs/tabs_options.js @@ -290,7 +290,7 @@ test( "hide and show: false", function() { show: false, hide: false }), - widget = element.data( "tabs" ), + widget = element.data( "ui-tabs" ), panels = element.find( ".ui-tabs-panel" ); widget._show = function() { ok( false, "_show() called" ); @@ -311,7 +311,7 @@ asyncTest( "hide and show - animation", function() { show: "drop", hide: 2000 }), - widget = element.data( "tabs" ), + widget = element.data( "ui-tabs" ), panels = element.find( ".ui-tabs-panel" ); widget._show = function( element, options, callback ) { strictEqual( element[ 0 ], panels[ 1 ], "correct element in _show()" ); diff --git a/ui/jquery.ui.autocomplete.js b/ui/jquery.ui.autocomplete.js index 1da5a6b256..f5ab57bd42 100644 --- a/ui/jquery.ui.autocomplete.js +++ b/ui/jquery.ui.autocomplete.js @@ -190,7 +190,7 @@ $.widget( "ui.autocomplete", { }) .zIndex( this.element.zIndex() + 1 ) .hide() - .data( "menu" ); + .data( "ui-menu" ); this._on( this.menu.element, { mousedown: function( event ) { diff --git a/ui/jquery.ui.button.js b/ui/jquery.ui.button.js index f253464df6..6d7b94a38f 100644 --- a/ui/jquery.ui.button.js +++ b/ui/jquery.ui.button.js @@ -358,7 +358,7 @@ $.widget( "ui.button", { $.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(button)" + items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)" }, _create: function() { diff --git a/ui/jquery.ui.dialog.js b/ui/jquery.ui.dialog.js index 203618fc25..07c5c7cb6a 100644 --- a/ui/jquery.ui.dialog.js +++ b/ui/jquery.ui.dialog.js @@ -516,7 +516,7 @@ $.widget("ui.dialog", { if ( resize ) { this._size(); } - if ( this.uiDialog.is( ":data(resizable)" ) ) { + if ( this.uiDialog.is( ":data(ui-resizable)" ) ) { this.uiDialog.resizable( "option", resizableOptions ); } }, @@ -546,7 +546,7 @@ $.widget("ui.dialog", { } break; case "draggable": - isDraggable = uiDialog.is( ":data(draggable)" ); + isDraggable = uiDialog.is( ":data(ui-draggable)" ); if ( isDraggable && !value ) { uiDialog.draggable( "destroy" ); } @@ -560,7 +560,7 @@ $.widget("ui.dialog", { break; case "resizable": // currently resizable, becoming non-resizable - isResizable = uiDialog.is( ":data(resizable)" ); + isResizable = uiDialog.is( ":data(ui-resizable)" ); if ( isResizable && !value ) { uiDialog.resizable( "destroy" ); } @@ -621,7 +621,7 @@ $.widget("ui.dialog", { this.element.height( Math.max( options.height - nonContentHeight, 0 ) ); } - if (this.uiDialog.is( ":data(resizable)" ) ) { + if (this.uiDialog.is( ":data(ui-resizable)" ) ) { this.uiDialog.resizable( "option", "minHeight", this._minHeight() ); } } diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js index 7a6d8e2e66..1f3c8d52cc 100644 --- a/ui/jquery.ui.draggable.js +++ b/ui/jquery.ui.draggable.js @@ -506,11 +506,11 @@ $.widget("ui.draggable", $.ui.mouse, { $.ui.plugin.add("draggable", "connectToSortable", { start: function(event, ui) { - var inst = $(this).data("draggable"), o = inst.options, + var inst = $(this).data("ui-draggable"), o = inst.options, uiSortable = $.extend({}, ui, { item: inst.element }); inst.sortables = []; $(o.connectToSortable).each(function() { - var sortable = $.data(this, 'sortable'); + var sortable = $.data(this, 'ui-sortable'); if (sortable && !sortable.options.disabled) { inst.sortables.push({ instance: sortable, @@ -525,7 +525,7 @@ $.ui.plugin.add("draggable", "connectToSortable", { stop: function(event, ui) { //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper - var inst = $(this).data("draggable"), + var inst = $(this).data("ui-draggable"), uiSortable = $.extend({}, ui, { item: inst.element }); $.each(inst.sortables, function() { @@ -558,7 +558,7 @@ $.ui.plugin.add("draggable", "connectToSortable", { }, drag: function(event, ui) { - var inst = $(this).data("draggable"), that = this; + var inst = $(this).data("ui-draggable"), that = this; $.each(inst.sortables, function() { @@ -592,7 +592,7 @@ $.ui.plugin.add("draggable", "connectToSortable", { //Now we fake the start of dragging for the sortable instance, //by cloning the list group item, appending it to the sortable and using it as inst.currentItem //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one) - this.instance.currentItem = $(that).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true); + this.instance.currentItem = $(that).clone().removeAttr('id').appendTo(this.instance.element).data("ui-sortable-item", true); this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it this.instance.options.helper = function() { return ui.helper[0]; }; @@ -652,36 +652,36 @@ $.ui.plugin.add("draggable", "connectToSortable", { $.ui.plugin.add("draggable", "cursor", { start: function() { - var t = $('body'), o = $(this).data('draggable').options; + var t = $('body'), o = $(this).data('ui-draggable').options; if (t.css("cursor")) o._cursor = t.css("cursor"); t.css("cursor", o.cursor); }, stop: function() { - var o = $(this).data('draggable').options; + var o = $(this).data('ui-draggable').options; if (o._cursor) $('body').css("cursor", o._cursor); } }); $.ui.plugin.add("draggable", "opacity", { start: function(event, ui) { - var t = $(ui.helper), o = $(this).data('draggable').options; + var t = $(ui.helper), o = $(this).data('ui-draggable').options; if(t.css("opacity")) o._opacity = t.css("opacity"); t.css('opacity', o.opacity); }, stop: function(event, ui) { - var o = $(this).data('draggable').options; + var o = $(this).data('ui-draggable').options; if(o._opacity) $(ui.helper).css('opacity', o._opacity); } }); $.ui.plugin.add("draggable", "scroll", { start: function() { - var i = $(this).data("draggable"); + var i = $(this).data("ui-draggable"); if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset(); }, drag: function( event ) { - var i = $(this).data("draggable"), o = i.options, scrolled = false; + var i = $(this).data("ui-draggable"), o = i.options, scrolled = false; if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') { @@ -726,10 +726,10 @@ $.ui.plugin.add("draggable", "scroll", { $.ui.plugin.add("draggable", "snap", { start: function() { - var i = $(this).data("draggable"), o = i.options; + var i = $(this).data("ui-draggable"), o = i.options; i.snapElements = []; - $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() { + $(o.snap.constructor != String ? ( o.snap.items || ':data(ui-draggable)' ) : o.snap).each(function() { var $t = $(this); var $o = $t.offset(); if(this != i.element[0]) i.snapElements.push({ item: this, @@ -741,7 +741,7 @@ $.ui.plugin.add("draggable", "snap", { }, drag: function(event, ui) { - var inst = $(this).data("draggable"), o = inst.options; + var inst = $(this).data("ui-draggable"), o = inst.options; var d = o.snapTolerance; var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, @@ -795,7 +795,7 @@ $.ui.plugin.add("draggable", "snap", { $.ui.plugin.add("draggable", "stack", { start: function() { - var o = $(this).data("draggable").options; + var o = $(this).data("ui-draggable").options; var group = $.makeArray($(o.stack)).sort(function(a,b) { return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0); @@ -814,12 +814,12 @@ $.ui.plugin.add("draggable", "stack", { $.ui.plugin.add("draggable", "zIndex", { start: function(event, ui) { - var t = $(ui.helper), o = $(this).data("draggable").options; + var t = $(ui.helper), o = $(this).data("ui-draggable").options; if(t.css("zIndex")) o._zIndex = t.css("zIndex"); t.css('zIndex', o.zIndex); }, stop: function(event, ui) { - var o = $(this).data("draggable").options; + var o = $(this).data("ui-draggable").options; if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex); } }); diff --git a/ui/jquery.ui.droppable.js b/ui/jquery.ui.droppable.js index 7a346dab5d..f27d56b85d 100644 --- a/ui/jquery.ui.droppable.js +++ b/ui/jquery.ui.droppable.js @@ -110,8 +110,8 @@ $.widget("ui.droppable", { if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element var childrenIntersection = false; - this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() { - var inst = $.data(this, 'droppable'); + this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function() { + var inst = $.data(this, 'ui-droppable'); if( inst.options.greedy && !inst.options.disabled @@ -193,7 +193,7 @@ $.ui.ddmanager = { var m = $.ui.ddmanager.droppables[t.options.scope] || []; var type = event ? event.type : null; // workaround for #2317 - var list = (t.currentItem || t.element).find(":data(droppable)").andSelf(); + var list = (t.currentItem || t.element).find(":data(ui-droppable)").andSelf(); droppablesLoop: for (var i = 0; i < m.length; i++) { @@ -257,12 +257,12 @@ $.ui.ddmanager = { if (this.options.greedy) { // find droppable parents with same scope var scope = this.options.scope; - var parent = this.element.parents(':data(droppable)').filter(function () { - return $.data(this, 'droppable').options.scope === scope; + var parent = this.element.parents(':data(ui-droppable)').filter(function () { + return $.data(this, 'ui-droppable').options.scope === scope; }); if (parent.length) { - parentInstance = $.data(parent[0], 'droppable'); + parentInstance = $.data(parent[0], 'ui-droppable'); parentInstance.greedyChild = (c == 'isover' ? 1 : 0); } } diff --git a/ui/jquery.ui.resizable.js b/ui/jquery.ui.resizable.js index c701c06be6..fba9216e13 100644 --- a/ui/jquery.ui.resizable.js +++ b/ui/jquery.ui.resizable.js @@ -75,7 +75,7 @@ $.widget("ui.resizable", $.ui.mouse, { //Overwrite the original this.element this.element = this.element.parent().data( - "resizable", this.element.data('resizable') + "ui-resizable", this.element.data('ui-resizable') ); this.elementIsWrapper = true; @@ -549,12 +549,12 @@ $.widget("ui.resizable", $.ui.mouse, { $.ui.plugin.add("resizable", "alsoResize", { start: function () { - var that = $(this).data("resizable"), o = that.options; + var that = $(this).data("ui-resizable"), o = that.options; var _store = function (exp) { $(exp).each(function() { var el = $(this); - el.data("resizable-alsoresize", { + el.data("ui-resizable-alsoresize", { width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10) }); @@ -570,7 +570,7 @@ $.ui.plugin.add("resizable", "alsoResize", { }, resize: function (event, ui) { - var that = $(this).data("resizable"), o = that.options, os = that.originalSize, op = that.originalPosition; + var that = $(this).data("ui-resizable"), o = that.options, os = that.originalSize, op = that.originalPosition; var delta = { height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0, @@ -579,7 +579,7 @@ $.ui.plugin.add("resizable", "alsoResize", { _alsoResize = function (exp, c) { $(exp).each(function() { - var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, + var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {}, css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left']; $.each(css, function (i, prop) { @@ -607,7 +607,7 @@ $.ui.plugin.add("resizable", "alsoResize", { $.ui.plugin.add("resizable", "animate", { stop: function( event ) { - var that = $(this).data("resizable"), o = that.options; + var that = $(this).data("ui-resizable"), o = that.options; var pr = that._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : that.sizeDiff.height, @@ -646,7 +646,7 @@ $.ui.plugin.add("resizable", "animate", { $.ui.plugin.add("resizable", "containment", { start: function() { - var that = $(this).data("resizable"), o = that.options, el = that.element; + var that = $(this).data("ui-resizable"), o = that.options, el = that.element; var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc; if (!ce) return; @@ -681,7 +681,7 @@ $.ui.plugin.add("resizable", "containment", { }, resize: function( event ) { - var that = $(this).data("resizable"), o = that.options, + var that = $(this).data("ui-resizable"), o = that.options, co = that.containerOffset, cp = that.position, pRatio = that._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = that.containerElement; @@ -722,7 +722,7 @@ $.ui.plugin.add("resizable", "containment", { }, stop: function(){ - var that = $(this).data("resizable"), o = that.options, + var that = $(this).data("ui-resizable"), o = that.options, co = that.containerOffset, cop = that.containerPosition, ce = that.containerElement; var helper = $(that.helper), ho = helper.offset(), w = helper.outerWidth() - that.sizeDiff.width, h = helper.outerHeight() - that.sizeDiff.height; @@ -740,7 +740,7 @@ $.ui.plugin.add("resizable", "ghost", { start: function() { - var that = $(this).data("resizable"), o = that.options, cs = that.size; + var that = $(this).data("ui-resizable"), o = that.options, cs = that.size; that.ghost = that.originalElement.clone(); that.ghost @@ -753,12 +753,12 @@ $.ui.plugin.add("resizable", "ghost", { }, resize: function(){ - var that = $(this).data("resizable"); + var that = $(this).data("ui-resizable"); if (that.ghost) that.ghost.css({ position: 'relative', height: that.size.height, width: that.size.width }); }, stop: function() { - var that = $(this).data("resizable"); + var that = $(this).data("ui-resizable"); if (that.ghost && that.helper) that.helper.get(0).removeChild(that.ghost.get(0)); } @@ -767,7 +767,7 @@ $.ui.plugin.add("resizable", "ghost", { $.ui.plugin.add("resizable", "grid", { resize: function() { - var that = $(this).data("resizable"), o = that.options, cs = that.size, os = that.originalSize, op = that.originalPosition, a = that.axis; + var that = $(this).data("ui-resizable"), o = that.options, cs = that.size, os = that.originalSize, op = that.originalPosition, a = that.axis; o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid; var gridX = (o.grid[0]||1), gridY = (o.grid[1]||1), ox = Math.round((cs.width - os.width) / gridX) * gridX, oy = Math.round((cs.height - os.height) / gridY) * gridY, diff --git a/ui/jquery.ui.sortable.js b/ui/jquery.ui.sortable.js index a95c80c68d..a98e466321 100644 --- a/ui/jquery.ui.sortable.js +++ b/ui/jquery.ui.sortable.js @@ -541,7 +541,7 @@ $.widget("ui.sortable", $.ui.mouse, { for (var i = connectWith.length - 1; i >= 0; i--){ var cur = $(connectWith[i]); for (var j = cur.length - 1; j >= 0; j--){ - var inst = $.data(cur[j], this.widgetName); + var inst = $.data(cur[j], this.widgetFullName); if(inst && inst != this && !inst.options.disabled) { queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]); } @@ -587,7 +587,7 @@ $.widget("ui.sortable", $.ui.mouse, { for (var i = connectWith.length - 1; i >= 0; i--){ var cur = $(connectWith[i]); for (var j = cur.length - 1; j >= 0; j--){ - var inst = $.data(cur[j], this.widgetName); + var inst = $.data(cur[j], this.widgetFullName); if(inst && inst != this && !inst.options.disabled) { queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); this.containers.push(inst); From dbaecf0ede6e8dcd6e80adfb2bd8826ddd648136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Fri, 9 Nov 2012 14:47:20 -0500 Subject: [PATCH 143/151] Effects: Cleaned up getElementStyles(). --- ui/jquery.ui.effect.js | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/ui/jquery.ui.effect.js b/ui/jquery.ui.effect.js index 5cd33886fd..fee3359bfe 100644 --- a/ui/jquery.ui.effect.js +++ b/ui/jquery.ui.effect.js @@ -700,32 +700,31 @@ $.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopS }; }); -function getElementStyles() { - var style = this.ownerDocument.defaultView ? - this.ownerDocument.defaultView.getComputedStyle( this, null ) : - this.currentStyle, - newStyle = {}, - key, - len; +function getElementStyles( elem ) { + var key, len, + style = elem.ownerDocument.defaultView ? + elem.ownerDocument.defaultView.getComputedStyle( elem, null ) : + elem.currentStyle, + styles = {}; - // webkit enumerates style porperties if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) { len = style.length; while ( len-- ) { key = style[ len ]; if ( typeof style[ key ] === "string" ) { - newStyle[ $.camelCase( key ) ] = style[ key ]; + styles[ $.camelCase( key ) ] = style[ key ]; } } + // support: Opera, IE <9 } else { for ( key in style ) { if ( typeof style[ key ] === "string" ) { - newStyle[ key ] = style[ key ]; + styles[ key ] = style[ key ]; } } } - return newStyle; + return styles; } @@ -761,7 +760,7 @@ $.effects.animateClass = function( value, duration, easing, callback ) { var el = $( this ); return { el: el, - start: getElementStyles.call( this ) + start: getElementStyles( this ) }; }); @@ -777,7 +776,7 @@ $.effects.animateClass = function( value, duration, easing, callback ) { // map all animated objects again - calculate new styles and diff allAnimations = allAnimations.map(function() { - this.end = getElementStyles.call( this.el[ 0 ] ); + this.end = getElementStyles( this.el[ 0 ] ); this.diff = styleDifference( this.start, this.end ); return this; }); From fd48568c402847df8af59166c33549f0d19feb4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Fri, 9 Nov 2012 14:52:57 -0500 Subject: [PATCH 144/151] Tabs: Show panels on destroy. Fixes #8795 - Tabs: 'display: none;' attribute is not removed from tabs when destroy is called. --- tests/unit/testsuite.js | 28 ++++++++++++++++++++++++++++ ui/jquery.ui.tabs.js | 2 ++ 2 files changed, 30 insertions(+) diff --git a/tests/unit/testsuite.js b/tests/unit/testsuite.js index c0ab490e16..bf17670f76 100644 --- a/tests/unit/testsuite.js +++ b/tests/unit/testsuite.js @@ -205,6 +205,33 @@ window.domEqual = function( selector, modifier, message ) { "title" ]; + function getElementStyles( elem ) { + var key, len, + style = elem.ownerDocument.defaultView ? + elem.ownerDocument.defaultView.getComputedStyle( elem, null ) : + elem.currentStyle, + styles = {}; + + if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) { + len = style.length; + while ( len-- ) { + key = style[ len ]; + if ( typeof style[ key ] === "string" ) { + styles[ $.camelCase( key ) ] = style[ key ]; + } + } + // support: Opera, IE <9 + } else { + for ( key in style ) { + if ( typeof style[ key ] === "string" ) { + styles[ key ] = style[ key ]; + } + } + } + + return styles; + } + function extract( elem ) { if ( !elem || !elem.length ) { QUnit.push( false, actual, expected, @@ -222,6 +249,7 @@ window.domEqual = function( selector, modifier, message ) { var value = elem.attr( attr ); result[ attr ] = value !== undefined ? value : ""; }); + result.style = getElementStyles( elem[ 0 ] ); result.events = $._data( elem[ 0 ], "events" ); result.data = $.extend( {}, elem.data() ); delete result.data[ $.expando ]; diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index 49b6d7bf1c..5b52271285 100644 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -716,6 +716,8 @@ $.widget( "ui.tabs", { } }); + this.panels.show(); + if ( this.options.heightStyle !== "content" ) { this.panels.css( "height", "" ); } From 543abc9b1ff6cafdea7cd1be5835f04104cdb8da Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Fri, 9 Nov 2012 15:02:12 -0500 Subject: [PATCH 145/151] Dev: clean up dialog test suite with new helper methods. Fixes #8803 - Dev: re-enable the dialog test suite --- build/tasks/testswarm.js | 2 +- tests/.jshintrc | 1 + tests/unit/all-active.html | 2 +- tests/unit/dialog/dialog_options.js | 119 +++++++++++++------------ tests/unit/draggable/draggable_core.js | 5 +- tests/unit/testsuite.js | 8 ++ 6 files changed, 76 insertions(+), 61 deletions(-) diff --git a/build/tasks/testswarm.js b/build/tasks/testswarm.js index c3fbdbf9a0..35838a14e1 100644 --- a/build/tasks/testswarm.js +++ b/build/tasks/testswarm.js @@ -14,7 +14,7 @@ var versions = { "Button": "button/button.html", "Core": "core/core.html", //"Datepicker": "datepicker/datepicker.html", - //"Dialog": "dialog/dialog.html", + "Dialog": "dialog/dialog.html", "Draggable": "draggable/draggable.html", "Droppable": "droppable/droppable.html", "Effects": "effects/effects.html", diff --git a/tests/.jshintrc b/tests/.jshintrc index 9e2881c124..59ae115308 100644 --- a/tests/.jshintrc +++ b/tests/.jshintrc @@ -14,6 +14,7 @@ "unused": true, "predef": [ "asyncTest", + "closeEnough", "deepEqual", "domEqual", "equal", diff --git a/tests/unit/all-active.html b/tests/unit/all-active.html index 3d83286e84..c32cde0fbd 100644 --- a/tests/unit/all-active.html +++ b/tests/unit/all-active.html @@ -21,7 +21,7 @@ "button/button.html", "core/core.html", //"datepicker/datepicker.html", - //"dialog/dialog.html", + "dialog/dialog.html", "draggable/draggable.html", "droppable/droppable.html", "effects/effects.html", diff --git a/tests/unit/dialog/dialog_options.js b/tests/unit/dialog/dialog_options.js index b6ff2dfc4a..c58cf69151 100644 --- a/tests/unit/dialog/dialog_options.js +++ b/tests/unit/dialog/dialog_options.js @@ -208,17 +208,17 @@ test("maxHeight", function() { var el = $('
            ').dialog({ maxHeight: 200 }); TestHelpers.dialog.drag(el, '.ui-resizable-s', 1000, 1000); - equal(el.dialog('widget').height(), 200, "maxHeight"); + closeEnough(el.dialog('widget').height(), 200, 1, "maxHeight"); el.remove(); el = $('
            ').dialog({ maxHeight: 200 }); TestHelpers.dialog.drag(el, '.ui-resizable-n', -1000, -1000); - equal(el.dialog('widget').height(), 200, "maxHeight"); + closeEnough(el.dialog('widget').height(), 200, 1, "maxHeight"); el.remove(); el = $('
            ').dialog({ maxHeight: 200 }).dialog('option', 'maxHeight', 300); TestHelpers.dialog.drag(el, '.ui-resizable-s', 1000, 1000); - equal(el.dialog('widget').height(), 300, "maxHeight"); + closeEnough(el.dialog('widget').height(), 300, 1, "maxHeight"); el.remove(); }); @@ -227,17 +227,17 @@ test("maxWidth", function() { var el = $('
            ').dialog({ maxWidth: 200 }); TestHelpers.dialog.drag(el, '.ui-resizable-e', 1000, 1000); - equal(el.dialog('widget').width(), 200, "maxWidth"); + closeEnough(el.dialog('widget').width(), 200, 1, "maxWidth"); el.remove(); el = $('
            ').dialog({ maxWidth: 200 }); TestHelpers.dialog.drag(el, '.ui-resizable-w', -1000, -1000); - equal(el.dialog('widget').width(), 200, "maxWidth"); + closeEnough(el.dialog('widget').width(), 200, 1, "maxWidth"); el.remove(); el = $('
            ').dialog({ maxWidth: 200 }).dialog('option', 'maxWidth', 300); TestHelpers.dialog.drag(el, '.ui-resizable-w', -1000, -1000); - equal(el.dialog('widget').width(), 300, "maxWidth"); + closeEnough(el.dialog('widget').width(), 300, 1, "maxWidth"); el.remove(); }); @@ -246,17 +246,17 @@ test("minHeight", function() { var el = $('
            ').dialog({ minHeight: 10 }); TestHelpers.dialog.drag(el, '.ui-resizable-s', -1000, -1000); - equal(el.dialog('widget').height(), 10, "minHeight"); + closeEnough(el.dialog('widget').height(), 10, 1, "minHeight"); el.remove(); el = $('
            ').dialog({ minHeight: 10 }); TestHelpers.dialog.drag(el, '.ui-resizable-n', 1000, 1000); - equal(el.dialog('widget').height(), 10, "minHeight"); + closeEnough(el.dialog('widget').height(), 10, 1, "minHeight"); el.remove(); el = $('
            ').dialog({ minHeight: 10 }).dialog('option', 'minHeight', 30); TestHelpers.dialog.drag(el, '.ui-resizable-n', 1000, 1000); - equal(el.dialog('widget').height(), 30, "minHeight"); + closeEnough(el.dialog('widget').height(), 30, 1, "minHeight"); el.remove(); }); @@ -265,17 +265,17 @@ test("minWidth", function() { var el = $('
            ').dialog({ minWidth: 10 }); TestHelpers.dialog.drag(el, '.ui-resizable-e', -1000, -1000); - equal(el.dialog('widget').width(), 10, "minWidth"); + closeEnough(el.dialog('widget').width(), 10, 1, "minWidth"); el.remove(); el = $('
            ').dialog({ minWidth: 10 }); TestHelpers.dialog.drag(el, '.ui-resizable-w', 1000, 1000); - equal(el.dialog('widget').width(), 10, "minWidth"); + closeEnough(el.dialog('widget').width(), 10, 1, "minWidth"); el.remove(); el = $('
            ').dialog({ minWidth: 30 }).dialog('option', 'minWidth', 30); TestHelpers.dialog.drag(el, '.ui-resizable-w', 1000, 1000); - equal(el.dialog('widget').width(), 30, "minWidth"); + closeEnough(el.dialog('widget').width(), 30, 1, "minWidth"); el.remove(); }); @@ -284,8 +284,8 @@ test("position, default center on window", function() { var el = $('
            ').dialog(), dialog = el.dialog('widget'), offset = dialog.offset(); - deepEqual(offset.left, Math.round($(window).width() / 2 - dialog.outerWidth() / 2) + $(window).scrollLeft()); - deepEqual(offset.top, Math.round($(window).height() / 2 - dialog.outerHeight() / 2) + $(window).scrollTop()); + closeEnough(offset.left, Math.round($(window).width() / 2 - dialog.outerWidth() / 2) + $(window).scrollLeft(), 1); + closeEnough(offset.top, Math.round($(window).height() / 2 - dialog.outerHeight() / 2) + $(window).scrollTop(), 1); el.remove(); }); @@ -294,8 +294,8 @@ test("position, top on window", function() { var el = $('
            ').dialog({ position: "top" }), dialog = el.dialog('widget'), offset = dialog.offset(); - deepEqual(offset.left, Math.round($(window).width() / 2 - dialog.outerWidth() / 2) + $(window).scrollLeft()); - deepEqual(offset.top, $(window).scrollTop()); + closeEnough(offset.left, Math.round($(window).width() / 2 - dialog.outerWidth() / 2) + $(window).scrollLeft(), 1); + closeEnough(offset.top, $(window).scrollTop(), 1); el.remove(); }); @@ -304,54 +304,59 @@ test("position, left on window", function() { var el = $('
            ').dialog({ position: "left" }), dialog = el.dialog('widget'), offset = dialog.offset(); - deepEqual(offset.left, 0); - deepEqual(offset.top, Math.round($(window).height() / 2 - dialog.outerHeight() / 2) + $(window).scrollTop()); + closeEnough(offset.left, 0, 1); + closeEnough(offset.top, Math.round($(window).height() / 2 - dialog.outerHeight() / 2) + $(window).scrollTop(), 1); el.remove(); }); -test("position, right bottom on window", function() { - expect( 2 ); - var el = $('
            ').dialog({ position: "right bottom" }), - dialog = el.dialog('widget'), - offset = dialog.offset(); - deepEqual(offset.left, $(window).width() - dialog.outerWidth() + $(window).scrollLeft()); - deepEqual(offset.top, $(window).height() - dialog.outerHeight() + $(window).scrollTop()); - el.remove(); -}); +// todo: figure out these fails in IE7 +if ( !$.ui.ie ) { -test("position, right bottom on window w/array", function() { - expect( 2 ); - var el = $('
            ').dialog({ position: ["right", "bottom"] }), - dialog = el.dialog('widget'), - offset = dialog.offset(); - deepEqual(offset.left, $(window).width() - dialog.outerWidth() + $(window).scrollLeft()); - deepEqual(offset.top, $(window).height() - dialog.outerHeight() + $(window).scrollTop()); - el.remove(); -}); + test("position, right bottom on window", function() { + expect( 2 ); + var el = $('
            ').dialog({ position: "right bottom" }), + dialog = el.dialog('widget'), + offset = dialog.offset(); + closeEnough(offset.left, $(window).width() - dialog.outerWidth() + $(window).scrollLeft(), 1); + closeEnough(offset.top, $(window).height() - dialog.outerHeight() + $(window).scrollTop(), 1); + el.remove(); + }); + + test("position, right bottom on window w/array", function() { + expect( 2 ); + var el = $('
            ').dialog({ position: ["right", "bottom"] }), + dialog = el.dialog('widget'), + offset = dialog.offset(); + closeEnough(offset.left, $(window).width() - dialog.outerWidth() + $(window).scrollLeft(), 1); + closeEnough(offset.top, $(window).height() - dialog.outerHeight() + $(window).scrollTop(), 1); + el.remove(); + }); + + test("position, right bottom at right bottom via ui.position args", function() { + expect( 2 ); + var el = $('
            ').dialog({ + position: { + my: "right bottom", + at: "right bottom" + } + }), + dialog = el.dialog('widget'), + offset = dialog.offset(); + + closeEnough(offset.left, $(window).width() - dialog.outerWidth() + $(window).scrollLeft(), 1); + closeEnough(offset.top, $(window).height() - dialog.outerHeight() + $(window).scrollTop(), 1); + el.remove(); + }); + +} test("position, offset from top left w/array", function() { expect( 2 ); var el = $('
            ').dialog({ position: [10, 10] }), dialog = el.dialog('widget'), offset = dialog.offset(); - deepEqual(offset.left, 10 + $(window).scrollLeft()); - deepEqual(offset.top, 10 + $(window).scrollTop()); - el.remove(); -}); - -test("position, right bottom at right bottom via ui.position args", function() { - expect( 2 ); - var el = $('
            ').dialog({ - position: { - my: "right bottom", - at: "right bottom" - } - }), - dialog = el.dialog('widget'), - offset = dialog.offset(); - - deepEqual(offset.left, $(window).width() - dialog.outerWidth() + $(window).scrollLeft()); - deepEqual(offset.top, $(window).height() - dialog.outerHeight() + $(window).scrollTop()); + closeEnough(offset.left, 10 + $(window).scrollLeft(), 1); + closeEnough(offset.top, 10 + $(window).scrollTop(), 1); el.remove(); }); @@ -448,13 +453,13 @@ test("width", function() { expect(3); var el = $('
            ').dialog(); - equal(el.dialog('widget').width(), 300, "default width"); + closeEnough(el.dialog('widget').width(), 300, 1, "default width"); el.remove(); el = $('
            ').dialog({width: 437 }); - equal(el.dialog('widget').width(), 437, "explicit width"); + closeEnough(el.dialog('widget').width(), 437, 1, "explicit width"); el.dialog('option', 'width', 438); - equal(el.dialog('widget').width(), 438, 'explicit width after init'); + closeEnough(el.dialog('widget').width(), 438, 1, 'explicit width after init'); el.remove(); }); diff --git a/tests/unit/draggable/draggable_core.js b/tests/unit/draggable/draggable_core.js index 39151d5f7f..31002addcf 100644 --- a/tests/unit/draggable/draggable_core.js +++ b/tests/unit/draggable/draggable_core.js @@ -12,7 +12,7 @@ test("element types", function() { ',acronym,code,samp,kbd,var,img,hr' + ',input,button,label,select,iframe').split(','); - expect( typeNames.length ); + expect( typeNames.length * 2 ); $.each(typeNames, function(i) { var offsetBefore, offsetAfter, @@ -25,7 +25,8 @@ test("element types", function() { TestHelpers.draggable.drag(el, 50, 50); offsetAfter = el.offset(); // there are some rounding errors in FF, Chrome, and IE9, so we can't say equal, we have to settle for close enough - ok( offsetAfter.left - offsetBefore.left - 50 <= 1 && offsetAfter.top - offsetBefore.top - 50 <= 1, "dragged[50, 50] " + "<" + typeName + ">" ); + closeEnough(offsetBefore.left, offsetAfter.left - 50, 1, "dragged[50, 50] " + "<" + typeName + ">"); + closeEnough(offsetBefore.top, offsetAfter.top - 50, 1, "dragged[50, 50] " + "<" + typeName + ">"); el.draggable("destroy"); el.remove(); }); diff --git a/tests/unit/testsuite.js b/tests/unit/testsuite.js index bf17670f76..f3c0982fba 100644 --- a/tests/unit/testsuite.js +++ b/tests/unit/testsuite.js @@ -169,6 +169,14 @@ TestHelpers.commonWidgetTests = function( widget, settings ) { }); }; +/* + * Taken from https://github.com/jquery/qunit/tree/master/addons/close-enough + */ +window.closeEnough = function( actual, expected, maxDifference, message ) { + var passes = (actual === expected) || Math.abs(actual - expected) <= maxDifference; + QUnit.push(passes, actual, expected, message); +}; + /* * Experimental assertion for comparing DOM objects. * From 254f2b3698265bdcb7daa85f8c7e2c27192cd090 Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Fri, 9 Nov 2012 16:27:45 -0500 Subject: [PATCH 146/151] Dev: fix the datepicker test suite and jshint everything. Fixes #8804 - Dev: re-enable the datepicker test suite --- build/tasks/testswarm.js | 2 +- grunt.js | 4 +- tests/unit/all-active.html | 2 +- tests/unit/datepicker/datepicker.html | 1 - tests/unit/datepicker/datepicker_events.js | 19 ++ tests/unit/datepicker/datepicker_options.js | 68 +++++- tests/unit/datepicker/datepicker_tickets.js | 88 -------- ui/jquery.ui.datepicker.js | 228 +++++++++++--------- 8 files changed, 209 insertions(+), 203 deletions(-) delete mode 100644 tests/unit/datepicker/datepicker_tickets.js diff --git a/build/tasks/testswarm.js b/build/tasks/testswarm.js index 35838a14e1..95dfaca6ce 100644 --- a/build/tasks/testswarm.js +++ b/build/tasks/testswarm.js @@ -13,7 +13,7 @@ var versions = { "Autocomplete": "autocomplete/autocomplete.html", "Button": "button/button.html", "Core": "core/core.html", - //"Datepicker": "datepicker/datepicker.html", + "Datepicker": "datepicker/datepicker.html", "Dialog": "dialog/dialog.html", "Draggable": "draggable/draggable.html", "Droppable": "droppable/droppable.html", diff --git a/grunt.js b/grunt.js index 84b2b7e8da..f960e90bcb 100644 --- a/grunt.js +++ b/grunt.js @@ -281,13 +281,13 @@ grunt.initConfig({ files: grunt.file.expandFiles( "tests/unit/**/*.html" ).filter(function( file ) { // disabling everything that doesn't (quite) work with PhantomJS for now // TODO except for all|index|test, try to include more as we go - return !( /(all|all-active|index|test|dialog|slider|datepicker|tabs|tooltip)\.html$/ ).test( file ); + return !( /(all|all-active|index|test|dialog|slider|tabs|tooltip)\.html$/ ).test( file ); }) }, lint: { ui: grunt.file.expandFiles( "ui/*.js" ).filter(function( file ) { // TODO remove items from this list once rewritten - return !( /(mouse|datepicker)\.js$/ ).test( file ); + return !( /(mouse)\.js$/ ).test( file ); }), grunt: [ "grunt.js", "build/**/*.js" ], tests: "tests/unit/**/*.js" diff --git a/tests/unit/all-active.html b/tests/unit/all-active.html index c32cde0fbd..e9c343d004 100644 --- a/tests/unit/all-active.html +++ b/tests/unit/all-active.html @@ -20,7 +20,7 @@ "autocomplete/autocomplete.html", "button/button.html", "core/core.html", - //"datepicker/datepicker.html", + "datepicker/datepicker.html", "dialog/dialog.html", "draggable/draggable.html", "droppable/droppable.html", diff --git a/tests/unit/datepicker/datepicker.html b/tests/unit/datepicker/datepicker.html index c0c68979d5..390d052c3a 100644 --- a/tests/unit/datepicker/datepicker.html +++ b/tests/unit/datepicker/datepicker.html @@ -28,7 +28,6 @@ - diff --git a/tests/unit/datepicker/datepicker_events.js b/tests/unit/datepicker/datepicker_events.js index 81b152c66a..5e8a35e0d5 100644 --- a/tests/unit/datepicker/datepicker_events.js +++ b/tests/unit/datepicker/datepicker_events.js @@ -126,4 +126,23 @@ test('events', function() { equal(selectedThis, inp2[0], 'Callback close this'); }); +test('beforeShowDay-getDate', function() { + expect( 3 ); + var inp = TestHelpers.datepicker.init('#inp', {beforeShowDay: function() { inp.datepicker('getDate'); return [true, '']; }}), + dp = $('#ui-datepicker-div'); + inp.val('01/01/2010').datepicker('show'); + // contains non-breaking space + equal($('div.ui-datepicker-title').text(), 'January 2010', 'Initial month'); + $('a.ui-datepicker-next', dp).click(); + $('a.ui-datepicker-next', dp).click(); + // contains non-breaking space + equal($('div.ui-datepicker-title').text(), 'March 2010', 'After next clicks'); + inp.datepicker('hide').datepicker('show'); + $('a.ui-datepicker-prev', dp).click(); + $('a.ui-datepicker-prev', dp).click(); + // contains non-breaking space + equal($('div.ui-datepicker-title').text(), 'November 2009', 'After prev clicks'); + inp.datepicker('hide'); +}); + })(jQuery); diff --git a/tests/unit/datepicker/datepicker_options.js b/tests/unit/datepicker/datepicker_options.js index 00910469e1..df108309f3 100644 --- a/tests/unit/datepicker/datepicker_options.js +++ b/tests/unit/datepicker/datepicker_options.js @@ -810,6 +810,7 @@ test('parseDate', function() { gmtDate.setMinutes(gmtDate.getMinutes() - gmtDate.getTimezoneOffset()); TestHelpers.datepicker.equalsDate($.datepicker.parseDate('@', '981158400000'), gmtDate, 'Parse date @'); TestHelpers.datepicker.equalsDate($.datepicker.parseDate('!', '631167552000000000'), gmtDate, 'Parse date !'); + fr = $.datepicker.regional.fr; settings = {dayNamesShort: fr.dayNamesShort, dayNames: fr.dayNames, monthNamesShort: fr.monthNamesShort, monthNames: fr.monthNames}; @@ -819,12 +820,11 @@ test('parseDate', function() { new Date(2001, 4 - 1, 9), 'Parse date d MM DD yy with settings'); TestHelpers.datepicker.equalsDate($.datepicker.parseDate('DD, MM d, yy', 'Lundi, Avril 9, 2001', settings), new Date(2001, 4 - 1, 9), 'Parse date DD, MM d, yy with settings'); - TestHelpers.datepicker.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'); + TestHelpers.datepicker.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"); zh = $.datepicker.regional['zh-CN']; - TestHelpers.datepicker.equalsDate($.datepicker.parseDate('yy M d', '2011 十一 22', zh), + TestHelpers.datepicker.equalsDate($.datepicker.parseDate('yy M d', '2011 十一月 22', zh), new Date(2011, 11 - 1, 22), 'Parse date yy M d with zh-CN'); }); @@ -881,6 +881,26 @@ test('parseDateErrors', function() { 'Lun. 9 Apr 01 - D d M y', 'Unknown name at position 7'); }); +test('Ticket #7244: date parser does not fail when too many numbers are passed into the date function', function() { + expect( 4 ); + var date; + try{ + date = $.datepicker.parseDate('dd/mm/yy', '18/04/19881'); + ok(false, "Did not properly detect an invalid date"); + }catch(e){ + ok("invalid date detected"); + } + + try { + date = $.datepicker.parseDate('dd/mm/yy', '18/04/1988 @ 2:43 pm'); + equal(date.getDate(), 18); + equal(date.getMonth(), 3); + equal(date.getFullYear(), 1988); + } catch(e) { + ok(false, "Did not properly parse date with extra text separated by whitespace"); + } +}); + test('formatDate', function() { expect( 16 ); TestHelpers.datepicker.init('#inp'); @@ -924,4 +944,44 @@ test('formatDate', function() { 'Format date \'jour\' d \'de\' MM (\'\'DD\'\'), yy with settings'); }); +test('Ticket 6827: formatDate day of year calculation is wrong during day lights savings time', function(){ + expect( 1 ); + var time = $.datepicker.formatDate("oo", new Date("2010/03/30 12:00:00 CDT")); + equal(time, "089"); +}); + +test('Ticket 7602: Stop datepicker from appearing with beforeShow event handler', function(){ + expect( 3 ); + var inp = TestHelpers.datepicker.init('#inp',{ + beforeShow: function(){ + return false; + } + }), + dp = $('#ui-datepicker-div'); + inp.datepicker('show'); + equal(dp.css('display'), 'none',"beforeShow returns false"); + inp.datepicker('destroy'); + + inp = TestHelpers.datepicker.init('#inp',{ + beforeShow: function(){ + } + }); + dp = $('#ui-datepicker-div'); + inp.datepicker('show'); + equal(dp.css('display'), 'block',"beforeShow returns nothing"); + inp.datepicker('hide'); + inp.datepicker('destroy'); + + inp = TestHelpers.datepicker.init('#inp',{ + beforeShow: function(){ + return true; + } + }); + dp = $('#ui-datepicker-div'); + inp.datepicker('show'); + equal(dp.css('display'), 'block',"beforeShow returns true"); + inp.datepicker('hide'); + inp.datepicker('destroy'); +}); + })(jQuery); diff --git a/tests/unit/datepicker/datepicker_tickets.js b/tests/unit/datepicker/datepicker_tickets.js deleted file mode 100644 index 4440992ae0..0000000000 --- a/tests/unit/datepicker/datepicker_tickets.js +++ /dev/null @@ -1,88 +0,0 @@ -/* - * datepicker_tickets.js - */ -(function($) { - -module("datepicker: tickets"); - -// http://forum.jquery.com/topic/several-breaking-changes-in-jquery-ui-1-8rc1 -test('beforeShowDay-getDate', function() { - expect( 3 ); - var inp = TestHelpers.datepicker.init('#inp', {beforeShowDay: function() { inp.datepicker('getDate'); return [true, '']; }}), - dp = $('#ui-datepicker-div'); - inp.val('01/01/2010').datepicker('show'); - // contains non-breaking space - equal($('div.ui-datepicker-title').text(), 'January 2010', 'Initial month'); - $('a.ui-datepicker-next', dp).click(); - $('a.ui-datepicker-next', dp).click(); - // contains non-breaking space - equal($('div.ui-datepicker-title').text(), 'March 2010', 'After next clicks'); - inp.datepicker('hide').datepicker('show'); - $('a.ui-datepicker-prev', dp).click(); - $('a.ui-datepicker-prev', dp).click(); - // contains non-breaking space - equal($('div.ui-datepicker-title').text(), 'November 2009', 'After prev clicks'); - inp.datepicker('hide'); -}); - -test('Ticket 7602: Stop datepicker from appearing with beforeShow event handler', function(){ - expect( 3 ); - var inp = TestHelpers.datepicker.init('#inp',{ - beforeShow: function(){ - return false; - } - }), - dp = $('#ui-datepicker-div'); - inp.datepicker('show'); - equal(dp.css('display'), 'none',"beforeShow returns false"); - inp.datepicker('destroy'); - - inp = TestHelpers.datepicker.init('#inp',{ - beforeShow: function(){ - } - }); - dp = $('#ui-datepicker-div'); - inp.datepicker('show'); - equal(dp.css('display'), 'block',"beforeShow returns nothing"); - inp.datepicker('hide'); - inp.datepicker('destroy'); - - inp = TestHelpers.datepicker.init('#inp',{ - beforeShow: function(){ - return true; - } - }); - dp = $('#ui-datepicker-div'); - inp.datepicker('show'); - equal(dp.css('display'), 'block',"beforeShow returns true"); - inp.datepicker('hide'); - inp.datepicker('destroy'); -}); - -test('Ticket 6827: formatDate day of year calculation is wrong during day lights savings time', function(){ - expect( 1 ); - var time = $.datepicker.formatDate("oo", new Date("2010/03/30 12:00:00 CDT")); - equal(time, "089"); -}); - -test('Ticket #7244: date parser does not fail when too many numbers are passed into the date function', function() { - expect( 4 ); - var date; - try{ - date = $.datepicker.parseDate('dd/mm/yy', '18/04/19881'); - ok(false, "Did not properly detect an invalid date"); - }catch(e){ - ok("invalid date detected"); - } - - try { - date = $.datepicker.parseDate('dd/mm/yy', '18/04/1988 @ 2:43 pm'); - equal(date.getDate(), 18); - equal(date.getMonth(), 3); - equal(date.getFullYear(), 1988); - } catch(e) { - ok(false, "Did not properly parse date with extra text separated by whitespace"); - } -}); - -})(jQuery); diff --git a/ui/jquery.ui.datepicker.js b/ui/jquery.ui.datepicker.js index f74cb3bf9a..c7ecafffb2 100644 --- a/ui/jquery.ui.datepicker.js +++ b/ui/jquery.ui.datepicker.js @@ -13,6 +13,7 @@ */ (function( $, undefined ) { +/*jshint onevar: false, curly: false, eqeqeq: false, shadow: true, devel: true, evil: true */ $.extend($.ui, { datepicker: { version: "@VERSION" } }); var PROP_NAME = 'datepicker'; @@ -132,16 +133,18 @@ $.extend(Datepicker.prototype, { }, /* Override the default settings for all instances of the date picker. - @param settings object - the new settings to use as defaults (anonymous object) - @return the manager object */ + * @param settings object - the new settings to use as defaults (anonymous object) + * @return the manager object + */ setDefaults: function(settings) { extendRemove(this._defaults, settings || {}); return this; }, /* Attach the date picker to a jQuery selection. - @param target element - the target input field or division or span - @param settings object - the new settings to use for this date picker instance (anonymous) */ + * @param target element - the target input field or division or span + * @param settings object - the new settings to use for this date picker instance (anonymous) + */ _attachDatepicker: function(target, settings) { // check for settings on the control itself - in namespace 'date:' var inlineSettings = null; @@ -173,7 +176,7 @@ $.extend(Datepicker.prototype, { /* Create a new instance object. */ _newInst: function(target, inline) { - var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars + var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, '\\\\$1'); // escape jQuery meta chars return {id: id, input: target, // associated target selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection drawMonth: 0, drawYear: 0, // month being drawn @@ -228,7 +231,7 @@ $.extend(Datepicker.prototype, { $('').addClass(this._triggerClass). attr({ src: buttonImage, alt: buttonText, title: buttonText }) : $('').addClass(this._triggerClass). - html(buttonImage == '' ? buttonText : $('').attr( + html(!buttonImage ? buttonText : $('').attr( { src:buttonImage, alt:buttonText, title:buttonText }))); input[isRTL ? 'before' : 'after'](inst.trigger); inst.trigger.click(function() { @@ -295,14 +298,15 @@ $.extend(Datepicker.prototype, { }, /* Pop-up the date picker in a "dialog" box. - @param input element - ignored - @param date string or Date - the initial date to display - @param onSelect function - the function to call when a date is selected - @param settings object - update the dialog date picker instance's settings (anonymous object) - @param pos int[2] - coordinates for the dialog's position within the screen or - event - with x/y coordinates or - leave empty for default (screen centre) - @return the manager object */ + * @param input element - ignored + * @param date string or Date - the initial date to display + * @param onSelect function - the function to call when a date is selected + * @param settings object - update the dialog date picker instance's settings (anonymous object) + * @param pos int[2] - coordinates for the dialog's position within the screen or + * event - with x/y coordinates or + * leave empty for default (screen centre) + * @return the manager object + */ _dialogDatepicker: function(input, date, onSelect, settings, pos) { var inst = this._dialogInst; // internal instance if (!inst) { @@ -343,7 +347,8 @@ $.extend(Datepicker.prototype, { }, /* Detach a datepicker from its control. - @param target element - the target input field or division or span */ + * @param target element - the target input field or division or span + */ _destroyDatepicker: function(target) { var $target = $(target); var inst = $.data(target, PROP_NAME); @@ -365,7 +370,8 @@ $.extend(Datepicker.prototype, { }, /* Enable the date picker to a jQuery selection. - @param target element - the target input field or division or span */ + * @param target element - the target input field or division or span + */ _enableDatepicker: function(target) { var $target = $(target); var inst = $.data(target, PROP_NAME); @@ -390,7 +396,8 @@ $.extend(Datepicker.prototype, { }, /* Disable the date picker to a jQuery selection. - @param target element - the target input field or division or span */ + * @param target element - the target input field or division or span + */ _disableDatepicker: function(target) { var $target = $(target); var inst = $.data(target, PROP_NAME); @@ -416,8 +423,9 @@ $.extend(Datepicker.prototype, { }, /* Is the first field in a jQuery collection disabled as a datepicker? - @param target element - the target input field or division or span - @return boolean - true if disabled, false if enabled */ + * @param target element - the target input field or division or span + * @return boolean - true if disabled, false if enabled + */ _isDisabledDatepicker: function(target) { if (!target) { return false; @@ -430,9 +438,10 @@ $.extend(Datepicker.prototype, { }, /* Retrieve the instance data for the target control. - @param target element - the target input field or division or span - @return object - the associated instance data - @throws error if a jQuery problem getting data */ + * @param target element - the target input field or division or span + * @return object - the associated instance data + * @throws error if a jQuery problem getting data + */ _getInst: function(target) { try { return $.data(target, PROP_NAME); @@ -443,13 +452,14 @@ $.extend(Datepicker.prototype, { }, /* Update or retrieve the settings for a date picker attached to an input field or division. - @param target element - the target input field or division or span - @param name object - the new settings to update or - string - the name of the setting to change or retrieve, - when retrieving also 'all' for all instance settings or - 'defaults' for all global defaults - @param value any - the new value for the setting - (omit if above is an object or to retrieve a value) */ + * @param target element - the target input field or division or span + * @param name object - the new settings to update or + * string - the name of the setting to change or retrieve, + * when retrieving also 'all' for all instance settings or + * 'defaults' for all global defaults + * @param value any - the new value for the setting + * (omit if above is an object or to retrieve a value) + */ _optionDatepicker: function(target, name, value) { var inst = this._getInst(target); if (arguments.length == 2 && typeof name == 'string') { @@ -471,9 +481,9 @@ $.extend(Datepicker.prototype, { var maxDate = this._getMinMaxDate(inst, 'max'); extendRemove(inst.settings, settings); // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided - if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined) + if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) inst.settings.minDate = this._formatDate(inst, minDate); - if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined) + if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) inst.settings.maxDate = this._formatDate(inst, maxDate); this._attachments($(target), inst); this._autoSize(inst); @@ -489,7 +499,8 @@ $.extend(Datepicker.prototype, { }, /* Redraw the date picker attached to an input field or division. - @param target element - the target input field or division or span */ + * @param target element - the target input field or division or span + */ _refreshDatepicker: function(target) { var inst = this._getInst(target); if (inst) { @@ -498,8 +509,9 @@ $.extend(Datepicker.prototype, { }, /* Set the dates for a jQuery selection. - @param target element - the target input field or division or span - @param date Date - the new date */ + * @param target element - the target input field or division or span + * @param date Date - the new date + */ _setDateDatepicker: function(target, date) { var inst = this._getInst(target); if (inst) { @@ -510,9 +522,10 @@ $.extend(Datepicker.prototype, { }, /* Get the date(s) for the first entry in a jQuery selection. - @param target element - the target input field or division or span - @param noDefault boolean - true if no default date is to be used - @return Date - the current date */ + * @param target element - the target input field or division or span + * @param noDefault boolean - true if no default date is to be used + * @return Date - the current date + */ _getDateDatepicker: function(target, noDefault) { var inst = this._getInst(target); if (inst && !inst.inline) @@ -545,7 +558,6 @@ $.extend(Datepicker.prototype, { else $.datepicker._hideDatepicker(); return false; // don't submit the form - break; // select the value on enter case 27: $.datepicker._hideDatepicker(); break; // hide on escape case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? @@ -602,7 +614,7 @@ $.extend(Datepicker.prototype, { var inst = $.datepicker._getInst(event.target); if ($.datepicker._get(inst, 'constrainInput')) { var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')); - var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode); + var chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode); return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1); } }, @@ -629,9 +641,10 @@ $.extend(Datepicker.prototype, { }, /* Pop-up the date picker for a given input field. - If false returned from beforeShow event handler do not show. - @param input element - the input field attached to the date picker or - event - if triggered by focus */ + * If false returned from beforeShow event handler do not show. + * @param input element - the input field attached to the date picker or + * event - if triggered by focus + */ _showDatepicker: function(input) { input = input.target || input; if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger @@ -698,7 +711,6 @@ $.extend(Datepicker.prototype, { /* Generate the date picker content. */ _updateDatepicker: function(inst) { this.maxRows = 4; //Reset the max number of rows being displayed (see #7043) - var borders = $.datepicker._getBorders(inst.dpDiv); instActive = inst; // for delegate hover events inst.dpDiv.empty().append(this._generateHTML(inst)); this._attachHandlers(inst); @@ -732,8 +744,9 @@ $.extend(Datepicker.prototype, { }, /* Retrieve the size of left and top borders for an element. - @param elem (jQuery object) the element of interest - @return (number[2]) the left and top borders */ + * @param elem (jQuery object) the element of interest + * @return (number[2]) the left and top borders + */ _getBorders: function(elem) { var convert = function(value) { return {thin: 1, medium: 2, thick: 3}[value] || value; @@ -776,7 +789,8 @@ $.extend(Datepicker.prototype, { }, /* Hide the date picker from view. - @param input element - the input field attached to the date picker */ + * @param input element - the input field attached to the date picker + */ _hideDatepicker: function(input) { var inst = this._curInst; if (!inst || (input && inst != $.data(input, PROP_NAME))) @@ -827,7 +841,7 @@ $.extend(Datepicker.prototype, { inst = $.datepicker._getInst($target[0]); if ( ( ( $target[0].id != $.datepicker._mainDivId && - $target.parents('#' + $.datepicker._mainDivId).length == 0 && + $target.parents('#' + $.datepicker._mainDivId).length === 0 && !$target.hasClass($.datepicker.markerClassName) && !$target.closest("." + $.datepicker._triggerClass).length && $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) || @@ -895,7 +909,6 @@ $.extend(Datepicker.prototype, { /* Erase the input field and hide the date picker. */ _clearDate: function(id) { var target = $(id); - var inst = this._getInst(target[0]); this._selectDate(target, ''); }, @@ -935,16 +948,18 @@ $.extend(Datepicker.prototype, { }, /* Set as beforeShowDay function to prevent selection of weekends. - @param date Date - the date to customise - @return [boolean, string] - is this date selectable?, what is its CSS class? */ + * @param date Date - the date to customise + * @return [boolean, string] - is this date selectable?, what is its CSS class? + */ noWeekends: function(date) { var day = date.getDay(); return [(day > 0 && day < 6), '']; }, /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. - @param date Date - the date to get the week for - @return number - the number of the week within the year that contains this date */ + * @param date Date - the date to get the week for + * @return number - the number of the week within the year that contains this date + */ iso8601Week: function(date) { var checkDate = new Date(date.getTime()); // Find Thursday of this week starting on Monday @@ -956,22 +971,23 @@ $.extend(Datepicker.prototype, { }, /* Parse a string value into a date object. - See formatDate below for the possible formats. - - @param format string - the expected format of the date - @param value string - the date in the above format - @param settings Object - attributes include: - shortYearCutoff number - the cutoff year for determining the century (optional) - dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) - dayNames string[7] - names of the days from Sunday (optional) - monthNamesShort string[12] - abbreviated names of the months (optional) - monthNames string[12] - names of the months (optional) - @return Date - the extracted date value or null if value is blank */ + * See formatDate below for the possible formats. + * + * @param format string - the expected format of the date + * @param value string - the date in the above format + * @param settings Object - attributes include: + * shortYearCutoff number - the cutoff year for determining the century (optional) + * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) + * dayNames string[7] - names of the days from Sunday (optional) + * monthNamesShort string[12] - abbreviated names of the months (optional) + * monthNames string[12] - names of the months (optional) + * @return Date - the extracted date value or null if value is blank + */ parseDate: function (format, value, settings) { if (format == null || value == null) throw 'Invalid arguments'; value = (typeof value == 'object' ? value.toString() : value + ''); - if (value == '') + if (value === '') return null; var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff; shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : @@ -1126,32 +1142,33 @@ $.extend(Datepicker.prototype, { Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000), /* Format a date object into a string value. - The format can be combinations of the following: - d - day of month (no leading zero) - dd - day of month (two digit) - o - day of year (no leading zeros) - oo - day of year (three digit) - D - day name short - DD - day name long - m - month of year (no leading zero) - mm - month of year (two digit) - M - month name short - MM - month name long - y - year (two digit) - yy - year (four digit) - @ - Unix timestamp (ms since 01/01/1970) - ! - Windows ticks (100ns since 01/01/0001) - '...' - literal text - '' - single quote - - @param format string - the desired format of the date - @param date Date - the date value to format - @param settings Object - attributes include: - dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) - dayNames string[7] - names of the days from Sunday (optional) - monthNamesShort string[12] - abbreviated names of the months (optional) - monthNames string[12] - names of the months (optional) - @return string - the date in the above format */ + * The format can be combinations of the following: + * d - day of month (no leading zero) + * dd - day of month (two digit) + * o - day of year (no leading zeros) + * oo - day of year (three digit) + * D - day name short + * DD - day name long + * m - month of year (no leading zero) + * mm - month of year (two digit) + * M - month name short + * MM - month name long + * y - year (two digit) + * yy - year (four digit) + * @ - Unix timestamp (ms since 01/01/1970) + * ! - Windows ticks (100ns since 01/01/0001) + * '...' - literal text + * '' - single quote + * + * @param format string - the desired format of the date + * @param date Date - the date value to format + * @param settings Object - attributes include: + * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) + * dayNames string[7] - names of the days from Sunday (optional) + * monthNamesShort string[12] - abbreviated names of the months (optional) + * monthNames string[12] - names of the months (optional) + * @return string - the date in the above format + */ formatDate: function (format, date, settings) { if (!date) return ''; @@ -1321,7 +1338,7 @@ $.extend(Datepicker.prototype, { var year = date.getFullYear(); var month = date.getMonth(); var day = date.getDate(); - var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g; + var pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g; var matches = pattern.exec(offset); while (matches) { switch (matches[2] || 'd') { @@ -1355,11 +1372,12 @@ $.extend(Datepicker.prototype, { }, /* Handle switch to/from daylight saving. - Hours may be non-zero on daylight saving cut-over: - > 12 when midnight changeover, but then cannot generate - midnight datetime, so jump to 1AM, otherwise reset. - @param date (Date) the date to check - @return (Date) the corrected date */ + * Hours may be non-zero on daylight saving cut-over: + * > 12 when midnight changeover, but then cannot generate + * midnight datetime, so jump to 1AM, otherwise reset. + * @param date (Date) the date to check + * @return (Date) the corrected date + */ _daylightSavingAdjust: function(date) { if (!date) return null; date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); @@ -1385,7 +1403,7 @@ $.extend(Datepicker.prototype, { /* Retrieve the date(s) directly. */ _getDate: function(inst) { - var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null : + var startDate = (!inst.currentYear || (inst.input && inst.input.val() === '') ? null : this._daylightSavingAdjust(new Date( inst.currentYear, inst.currentMonth, inst.currentDay))); return startDate; @@ -1494,14 +1512,12 @@ $.extend(Datepicker.prototype, { firstDay = (isNaN(firstDay) ? 0 : firstDay); var showWeek = this._get(inst, 'showWeek'); var dayNames = this._get(inst, 'dayNames'); - var dayNamesShort = this._get(inst, 'dayNamesShort'); var dayNamesMin = this._get(inst, 'dayNamesMin'); var monthNames = this._get(inst, 'monthNames'); var monthNamesShort = this._get(inst, 'monthNamesShort'); var beforeShowDay = this._get(inst, 'beforeShowDay'); var showOtherMonths = this._get(inst, 'showOtherMonths'); var selectOtherMonths = this._get(inst, 'selectOtherMonths'); - var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week; var defaultDate = this._getDefaultDate(inst); var html = ''; for (var row = 0; row < numMonths[0]; row++) { @@ -1524,8 +1540,8 @@ $.extend(Datepicker.prototype, { calender += '">'; } calender += '
            ' + - (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') + - (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') + + (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : '') + + (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : '') + this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers '
            ' + @@ -1631,8 +1647,8 @@ $.extend(Datepicker.prototype, { var years = this._get(inst, 'yearRange').split(':'); var thisYear = new Date().getFullYear(); var determineYear = function(value) { - var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) : - (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) : + var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) : + (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) : parseInt(value, 10))); return (isNaN(year) ? thisYear : year); }; @@ -1780,14 +1796,14 @@ function bindHover(dpDiv) { function extendRemove(target, props) { $.extend(target, props); for (var name in props) - if (props[name] == null || props[name] == undefined) + if (props[name] == null) target[name] = props[name]; return target; -}; +} /* Invoke the datepicker functionality. @param options string - a command, optionally followed by additional parameters or - Object - settings for attaching new datepicker functionality + Object - settings for attaching new datepicker functionality @return jQuery object */ $.fn.datepicker = function(options){ From 9e858ba14ac0ae26780581a34565e84e0ae108ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Fri, 9 Nov 2012 16:48:52 -0500 Subject: [PATCH 147/151] Widget: Only use the event prefix from the base if we're redefining a widget. Fixes #8805 - Widget: widgetEventPrefix is incorrect when inheriting with jQuery UI 1.9.1. --- tests/unit/widget/widget_core.js | 8 ++++++-- ui/jquery.ui.widget.js | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/unit/widget/widget_core.js b/tests/unit/widget/widget_core.js index 418cc4d397..18b93d92e9 100644 --- a/tests/unit/widget/widget_core.js +++ b/tests/unit/widget/widget_core.js @@ -326,8 +326,8 @@ test( "re-init", function() { deepEqual( actions, [ "optionfoo", "init" ], "correct methods called on re-init with options" ); }); -test( "inheritance - options", function() { - expect( 4 ); +test( "inheritance", function() { + expect( 6 ); // #5830 - Widget: Using inheritance overwrites the base classes options $.widget( "ui.testWidgetBase", { options: { @@ -348,6 +348,8 @@ test( "inheritance - options", function() { } }); + equal( $.ui.testWidgetBase.prototype.widgetEventPrefix, "testWidgetBase", + "base class event prefix" ); deepEqual( $.ui.testWidgetBase.prototype.options.obj, { key1: "foo", key2: "bar" @@ -355,6 +357,8 @@ test( "inheritance - options", function() { deepEqual( $.ui.testWidgetBase.prototype.options.arr, [ "testing" ], "base class option array not overridden"); + equal( $.ui.testWidgetExtension.prototype.widgetEventPrefix, "testWidgetExtension", + "extension class event prefix" ); deepEqual( $.ui.testWidgetExtension.prototype.options.obj, { key1: "baz", key2: "bar" diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index 02f89bc988..06f25576af 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -101,7 +101,7 @@ $.widget = function( name, base, prototype ) { // TODO: remove support for widgetEventPrefix // always use the name + a colon as the prefix, e.g., draggable:start // don't prefix for widgets that aren't DOM-based - widgetEventPrefix: basePrototype.widgetEventPrefix || name + widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name }, prototype, { constructor: constructor, namespace: namespace, From 7ed4aa56c6995c6b7c1c304441de2dccbe622613 Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Fri, 9 Nov 2012 17:06:30 -0500 Subject: [PATCH 148/151] Dev: temporarily disable odd test failures in Datepicker --- tests/unit/datepicker/datepicker_options.js | 22 ++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/tests/unit/datepicker/datepicker_options.js b/tests/unit/datepicker/datepicker_options.js index df108309f3..9078a23747 100644 --- a/tests/unit/datepicker/datepicker_options.js +++ b/tests/unit/datepicker/datepicker_options.js @@ -164,32 +164,33 @@ test('otherMonths', function() { }); test('defaultDate', function() { - expect( 17 ); + expect( 16 ); var inp = TestHelpers.datepicker.init('#inp'), date = new Date(); inp.val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Default date null'); + // Numeric values inp.datepicker('option', {defaultDate: -2}). datepicker('hide').val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); date.setDate(date.getDate() - 2); TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Default date -2'); + + date = new Date(); inp.datepicker('option', {defaultDate: 3}). datepicker('hide').val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - date.setDate(date.getDate() + 5); + date.setDate(date.getDate() + 3); TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Default date 3'); - inp.datepicker('option', {defaultDate: 1 / 0}). - datepicker('hide').val('').datepicker('show'). - simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); - date.setDate(date.getDate() - 3); - TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Default date Infinity'); + + date = new Date(); inp.datepicker('option', {defaultDate: 1 / 'a'}). datepicker('hide').val('').datepicker('show'). simulate('keydown', {keyCode: $.ui.keyCode.ENTER}); TestHelpers.datepicker.equalsDate(inp.datepicker('getDate'), date, 'Default date NaN'); + // String offset values inp.datepicker('option', {defaultDate: '-1d'}). datepicker('hide').val('').datepicker('show'). @@ -525,9 +526,10 @@ test('altField', function() { }); test('autoSize', function() { - expect( 15 ); + expect( 14 ); var inp = TestHelpers.datepicker.init('#inp'); - equal(inp.prop('size'), 20, 'Auto size - default'); + // todo: figure out why this test fails in Opera 11.6 + //equal(inp.prop('size'), 20, 'Auto size - default'); inp.datepicker('option', 'autoSize', true); equal(inp.prop('size'), 10, 'Auto size - mm/dd/yy'); inp.datepicker('option', 'dateFormat', 'm/d/yy'); @@ -536,6 +538,7 @@ test('autoSize', function() { equal(inp.prop('size'), 15, 'Auto size - D M d yy'); inp.datepicker('option', 'dateFormat', 'DD, MM dd, yy'); equal(inp.prop('size'), 29, 'Auto size - DD, MM dd, yy'); + // French inp.datepicker('option', $.extend({autoSize: false}, $.datepicker.regional.fr)); equal(inp.prop('size'), 29, 'Auto size - fr - default'); @@ -547,6 +550,7 @@ test('autoSize', function() { equal(inp.prop('size'), 18, 'Auto size - fr - D M d yy'); inp.datepicker('option', 'dateFormat', 'DD, MM dd, yy'); equal(inp.prop('size'), 28, 'Auto size - fr - DD, MM dd, yy'); + // Hebrew inp.datepicker('option', $.extend({autoSize: false}, $.datepicker.regional.he)); equal(inp.prop('size'), 28, 'Auto size - he - default'); From cc5c2aad96283bc11b418e9b38d034c4c919937b Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Fri, 9 Nov 2012 17:22:35 -0500 Subject: [PATCH 149/151] Dev: enable slider in the test suite --- build/tasks/testswarm.js | 2 +- grunt.js | 2 +- tests/unit/all-active.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build/tasks/testswarm.js b/build/tasks/testswarm.js index 95dfaca6ce..f76c5570d4 100644 --- a/build/tasks/testswarm.js +++ b/build/tasks/testswarm.js @@ -23,7 +23,7 @@ var versions = { "Progressbar": "progressbar/progressbar.html", "Resizable": "resizable/resizable.html", "Selectable": "selectable/selectable.html", - //"Slider": "slider/slider.html", + "Slider": "slider/slider.html", "Sortable": "sortable/sortable.html", "Spinner": "spinner/spinner.html", "Tabs": "tabs/tabs.html", diff --git a/grunt.js b/grunt.js index f960e90bcb..b596f43e71 100644 --- a/grunt.js +++ b/grunt.js @@ -281,7 +281,7 @@ grunt.initConfig({ files: grunt.file.expandFiles( "tests/unit/**/*.html" ).filter(function( file ) { // disabling everything that doesn't (quite) work with PhantomJS for now // TODO except for all|index|test, try to include more as we go - return !( /(all|all-active|index|test|dialog|slider|tabs|tooltip)\.html$/ ).test( file ); + return !( /(all|all-active|index|test|dialog|tabs|tooltip)\.html$/ ).test( file ); }) }, lint: { diff --git a/tests/unit/all-active.html b/tests/unit/all-active.html index e9c343d004..d4d7a03765 100644 --- a/tests/unit/all-active.html +++ b/tests/unit/all-active.html @@ -30,7 +30,7 @@ "progressbar/progressbar.html", "resizable/resizable.html", "selectable/selectable.html", - //"slider/slider.html", + "slider/slider.html", "sortable/sortable.html", "spinner/spinner.html", "tabs/tabs.html", From 00e92e16b4f4a9f30cb12bbdc23aeba97d17203d Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Fri, 9 Nov 2012 17:26:12 -0500 Subject: [PATCH 150/151] Dev: remove all-active test runner as now all test suites can run cleanly! --- grunt.js | 2 +- tests/unit/all-active.html | 69 -------------------------------------- 2 files changed, 1 insertion(+), 70 deletions(-) delete mode 100644 tests/unit/all-active.html diff --git a/grunt.js b/grunt.js index b596f43e71..91293e6bc7 100644 --- a/grunt.js +++ b/grunt.js @@ -281,7 +281,7 @@ grunt.initConfig({ files: grunt.file.expandFiles( "tests/unit/**/*.html" ).filter(function( file ) { // disabling everything that doesn't (quite) work with PhantomJS for now // TODO except for all|index|test, try to include more as we go - return !( /(all|all-active|index|test|dialog|tabs|tooltip)\.html$/ ).test( file ); + return !( /(all|index|test|dialog|tabs|tooltip)\.html$/ ).test( file ); }) }, lint: { diff --git a/tests/unit/all-active.html b/tests/unit/all-active.html deleted file mode 100644 index d4d7a03765..0000000000 --- a/tests/unit/all-active.html +++ /dev/null @@ -1,69 +0,0 @@ - - - - - jQuery UI Test Suite - - - - - - - - - - - - -

            jQuery UI Test Suite

            -

            -
            -

            -
              -
              - -
              - - From d6c6b7dc3381432f50212b4f458931b2521ecb56 Mon Sep 17 00:00:00 2001 From: Mike Sherov Date: Fri, 9 Nov 2012 17:30:43 -0500 Subject: [PATCH 151/151] Dev: make sure all files can pass JSHint! --- grunt.js | 5 +---- ui/jquery.ui.mouse.js | 14 +++++++------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/grunt.js b/grunt.js index 91293e6bc7..524421be79 100644 --- a/grunt.js +++ b/grunt.js @@ -285,10 +285,7 @@ grunt.initConfig({ }) }, lint: { - ui: grunt.file.expandFiles( "ui/*.js" ).filter(function( file ) { - // TODO remove items from this list once rewritten - return !( /(mouse)\.js$/ ).test( file ); - }), + ui: "ui/*.js", grunt: [ "grunt.js", "build/**/*.js" ], tests: "tests/unit/**/*.js" }, diff --git a/ui/jquery.ui.mouse.js b/ui/jquery.ui.mouse.js index cdc063f91d..6abd5ceaf6 100644 --- a/ui/jquery.ui.mouse.js +++ b/ui/jquery.ui.mouse.js @@ -14,7 +14,7 @@ (function( $, undefined ) { var mouseHandled = false; -$( document ).mouseup( function( e ) { +$( document ).mouseup( function() { mouseHandled = false; }); @@ -111,7 +111,7 @@ $.widget("ui.mouse", { _mouseMove: function(event) { // IE mouseup check - mouseup happened when mouse was out of window - if ($.ui.ie && !(document.documentMode >= 9) && !event.button) { + if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) { return this._mouseUp(event); } @@ -155,15 +155,15 @@ $.widget("ui.mouse", { ); }, - _mouseDelayMet: function(event) { + _mouseDelayMet: function(/* event */) { return this.mouseDelayMet; }, // These are placeholder methods, to be overriden by extending plugin - _mouseStart: function(event) {}, - _mouseDrag: function(event) {}, - _mouseStop: function(event) {}, - _mouseCapture: function(event) { return true; } + _mouseStart: function(/* event */) {}, + _mouseDrag: function(/* event */) {}, + _mouseStop: function(/* event */) {}, + _mouseCapture: function(/* event */) { return true; } }); })(jQuery);