diff --git a/Makefile b/Makefile index a1705408..7c89afac 100644 --- a/Makefile +++ b/Makefile @@ -60,6 +60,7 @@ JSFILES = js/jquery.ui.widget.js \ js/jquery.mobile.forms.button.js \ js/jquery.mobile.forms.slider.js \ js/jquery.mobile.forms.textinput.js \ + js/jquery.mobile.forms.select.custom.js \ js/jquery.mobile.forms.select.js \ js/jquery.mobile.buttonMarkup.js \ js/jquery.mobile.controlGroup.js \ @@ -126,7 +127,7 @@ notify: @@echo "The files have been built and are in " $$(pwd)/${OUTPUT} # Pull the latest commits. This is used for the nightly build but can be used to save some keystrokes -pull: +pull: @@git pull --quiet # Zip the 4 files and the theme images into one convenient package @@ -161,7 +162,7 @@ nightly: pull zip # Change the empty paths to the location of this nightly file @@find ${VER} -type f -name '*.html' -exec sed -i 's|href="themes/default/"|href="${NIGHTLY_WEBPATH}/${DIR}.min.css"|g' {} \; @@find ${VER} -type f -name '*.html' -exec sed -i 's|src="js/jquery.js"|src="http://code.jquery.com/jquery-${JQUERY}.min.js"|' {} \; - @@find ${VER} -type f -name '*.html' -exec sed -i 's|src="js/"|src="${NIGHTLY_WEBPATH}/${DIR}.min.js"|g' {} \; + @@find ${VER} -type f -name '*.html' -exec sed -i 's|src="js/"|src="${NIGHTLY_WEBPATH}/${DIR}.min.js"|g' {} \; # Move the demos into the output folder @@mv ${VER} ${OUTPUT}/demos diff --git a/build.xml b/build.xml index 21baaabf..abe8aef2 100644 --- a/build.xml +++ b/build.xml @@ -30,7 +30,7 @@ js/jquery.mobile.core.js, js/jquery.mobile.navigation.js, js/jquery.mobile.transition.js, - js/jquery.mobile.degradeInputs.js, + js/jquery.mobile.degradeInputs.js, js/jquery.mobile.dialog.js, js/jquery.mobile.page.sections.js, js/jquery.mobile.collapsible.js, @@ -44,6 +44,7 @@ js/jquery.mobile.forms.button.js, js/jquery.mobile.forms.slider.js, js/jquery.mobile.forms.textinput.js, + js/jquery.mobile.forms.select.custom.js, js/jquery.mobile.forms.select.js, js/jquery.mobile.buttonMarkup.js, js/jquery.mobile.controlGroup.js, diff --git a/docs/lists/lists-split-purchase.html b/docs/lists/lists-split-purchase.html index 17e8c5ac..f62f2808 100755 --- a/docs/lists/lists-split-purchase.html +++ b/docs/lists/lists-split-purchase.html @@ -14,7 +14,7 @@ -
+

Purchase?

diff --git a/js/jquery.mobile.forms.select.custom.js b/js/jquery.mobile.forms.select.custom.js index e00bf114..3ec6882b 100644 --- a/js/jquery.mobile.forms.select.custom.js +++ b/js/jquery.mobile.forms.select.custom.js @@ -248,9 +248,11 @@ // rebind the page remove that was unbound in the open function // to allow for the parent page removal from actions other than the use // of a dialog sized custom select - self.thisPage.bind( "pagehide.remove", function() { - $(this).remove(); - }); + if( !self.thisPage.data("page").options.domCache ){ + self.thisPage.bind( "pagehide.remove", function() { + $(this).remove(); + }); + } // doesn't solve the possible issue with calling change page // where the objects don't define data urls which prevents dialog key @@ -459,9 +461,11 @@ }); }; - $( "select:jqmData(native-menu='false')" ).live( "selectmenubeforecreate", function(){ + $( "select" ).live( "selectmenubeforecreate", function(){ var selectmenuWidget = $( this ).data( "selectmenu" ); - extendSelect( selectmenuWidget ); + if( !selectmenuWidget.options.nativeMenu ){ + extendSelect( selectmenuWidget ); + } }); })( jQuery ); diff --git a/tests/unit/index.php b/tests/unit/index.php index 35dbb90e..2ecb3ba5 100644 --- a/tests/unit/index.php +++ b/tests/unit/index.php @@ -3,20 +3,38 @@ + + + + -
+ - - - - - diff --git a/tests/unit/ls.php b/tests/unit/ls.php index 6bcd1d72..2108b544 100644 --- a/tests/unit/ls.php +++ b/tests/unit/ls.php @@ -13,6 +13,8 @@ closedir($handle); } - sort($directories); - echo json_encode( array('directories' => $directories )); + $test_pages = array_merge($directories, glob("**/*-tests.html")); + sort($test_pages); + + echo json_encode( array('testPages' => $test_pages)); ?> \ No newline at end of file diff --git a/tests/unit/navigation/base-tests/content/content-page-2.html b/tests/unit/navigation/base-tests/content/content-page-2.html index 871a74f3..76c9bbd5 100644 --- a/tests/unit/navigation/base-tests/content/content-page-2.html +++ b/tests/unit/navigation/base-tests/content/content-page-2.html @@ -8,7 +8,7 @@ Base Page 1 Internal Page 1 Internal Page 2 - +
diff --git a/tests/unit/navigation/navigation_base.js b/tests/unit/navigation/navigation_base.js index 025d1fb8..db8a81f6 100644 --- a/tests/unit/navigation/navigation_base.js +++ b/tests/unit/navigation/navigation_base.js @@ -21,7 +21,7 @@ $.testHelper.pageSequence([ function(){ // Navigate from default internal page to another internal page. - $.testHelper.openPage("#internal-page-2"); + $.testHelper.openPage("#internal-page-2"); }, function(){ @@ -93,8 +93,8 @@ // Verify that we are on the expected page. same(location.hash, "#" + contentDir + "content-page-2.html", "call changePage() with a relative path should resolve relative to current page"); - // Try calling changePage() with an id - $.mobile.changePage("#internal-page-2"); + // test that an internal page works + $("a.ip2").click(); }, function(){ diff --git a/tests/unit/runner.js b/tests/unit/runner.js index 2f36e1ed..aa956e4c 100644 --- a/tests/unit/runner.js +++ b/tests/unit/runner.js @@ -1,58 +1,82 @@ -(function(){ - var test = function(data){ - var $frameElem = $("#testFrame"), - template = $frameElem.attr("data-src"), - updateFrame = function(dir){ - return $frameElem.attr("src", template.replace("{{testdir}}", dir)); - }; +$(function() { + var Runner = function( ) { + var self = this; - $.each(data.directories, function(i, dir){ - asyncTest( dir, function(){ - var testTimeout = 3 * 60 * 1000, checkInterval = 2000; + $.extend( self, { + frame: window.frames[ "testFrame" ], + testTimeout: 3 * 60 * 1000, + + $frameElem: $( "#testFrame" ), + + assertionResultPrefix: "assertion result for test:", + + onTimeout: QUnit.start, + + onFrameLoad: function() { // establish a timeout for a given suite in case of async tests hanging - var testTimer = setTimeout( function(){ - // prevent any schedule checks for completion - clearTimeouts(); - start(); - }, testTimeout ), + self.testTimer = setTimeout( self.onTimeout, self.testTimeout ); - checkTimer = setInterval( check, checkInterval ), + // when the QUnit object reports done in the iframe + // run the onFrameDone method + self.frame.QUnit.done = self.onFrameDone; + self.frame.QUnit.testDone = self.onTestDone; + }, - clearTimeouts = function(){ - // prevent the next interval of the check function and the test timeout - clearTimeout( checkTimer ); - clearTimeout( testTimer ); - }; + onTestDone: function( name, bad, assertCount ) { + QUnit.ok( !bad, name ); + self.recordAssertions( assertCount - 1, name ); + }, - // check the iframe for success or failure and respond accordingly - function check(){ - // check for the frames jquery object each time - var framejQuery = window.frames["testFrame"].jQuery; + onFrameDone: function( failed, passed, total, runtime ){ + // make sure we don't time out the tests + clearTimeout( self.testTimer ); - // if the iframe hasn't loaded (ie loaded jQuery) check back again shortly - if( !framejQuery ) return; + // TODO decipher actual cause of multiple test results firing twice + // clear the done call to prevent early completion of other test cases + self.frame.QUnit.done = $.noop; + self.frame.QUnit.testDone = $.noop; - // grab the result of the iframe test suite - // TODO strip extra white space - var result = framejQuery( "#qunit-banner" ).attr( "class" ); + // hide the extra assertions made to propogate the count + // to the suite level test + self.hideAssertionResults(); - // if we have a result check it, otherwise check back shortly - if( result ){ - ok( result === "qunit-pass" ); - clearTimeouts(); - start(); - } - }; + // continue on to the next suite + QUnit.start(); + }, - expect( 1 ); + recordAssertions: function( count, parentTest ) { + for( var i = 0; i < count; i++ ) { + ok( true, self.assertionResultPrefix + parentTest ); + } + }, - // set the test suite page on the iframe - updateFrame( dir ); - }); + hideAssertionResults: function() { + $( "li:not([id]):contains('" + self.assertionResultPrefix + "')" ).hide(); + }, + + exec: function( data ) { + var template = self.$frameElem.attr( "data-src" ); + + $.each( data.testPages, function(i, dir) { + QUnit.asyncTest( dir, function() { + self.dir = dir; + self.$frameElem.one( "load", self.onFrameLoad ); + self.$frameElem.attr( "src", template.replace("{{testdir}}", dir) ); + }); + }); + + // having defined all suite level tests let QUnit run + QUnit.start(); + } }); }; + // prevent qunit from starting the test suite until all tests are defined + QUnit.begin = function( ) { + this.config.autostart = false; + }; + // get the test directories - $.get("ls.php", test); -})(); + $.get( "ls.php", (new Runner()).exec ); +}); diff --git a/tests/unit/select/cached-dom-cache-true.html b/tests/unit/select/cached-dom-cache-true.html new file mode 100755 index 00000000..b5e719d3 --- /dev/null +++ b/tests/unit/select/cached-dom-cache-true.html @@ -0,0 +1,65 @@ + + + + + + +
+
+ + +
+
+ + diff --git a/tests/unit/select/cached-tests.html b/tests/unit/select/cached-tests.html index 0ca8691a..5fd212b5 100644 --- a/tests/unit/select/cached-tests.html +++ b/tests/unit/select/cached-tests.html @@ -1,65 +1,27 @@ - + - - - - -
-
- - -
-
- + + + + jQuery Mobile Select Events Test Suite + + + + + + + + + + + + + +

jQuery Mobile Select Event Test Suite

+

+

+
    +
+
+ diff --git a/tests/unit/select/cached.html b/tests/unit/select/cached.html new file mode 100644 index 00000000..0ca8691a --- /dev/null +++ b/tests/unit/select/cached.html @@ -0,0 +1,65 @@ + + + + + + +
+
+ + +
+
+ + diff --git a/tests/unit/select/select_cached.js b/tests/unit/select/select_cached.js new file mode 100644 index 00000000..1dfc54dd --- /dev/null +++ b/tests/unit/select/select_cached.js @@ -0,0 +1,101 @@ +/* + * mobile select unit tests + */ + +(function($){ + var resetHash; + + resetHash = function(timeout){ + $.testHelper.openPage( location.hash.indexOf("#default") >= 0 ? "#" : "#default" ); + }; + + // https://github.com/jquery/jquery-mobile/issues/2181 + asyncTest( "dialog sized select should alter the value of its parent select", function(){ + var selectButton, value; + + $.testHelper.pageSequence([ + resetHash, + + function(){ + $.mobile.changePage( "cached.html" ); + }, + + function(){ + selectButton = $( "#cached-page-select" ).siblings( 'a' ); + selectButton.click(); + }, + + function(){ + ok( $.mobile.activePage.hasClass('ui-dialog'), "the dialog came up" ); + var option = $.mobile.activePage.find( "li a" ).not(":contains('" + selectButton.text() + "')").last(); + value = option.text(); + option.click(); + }, + + function(){ + same( value, selectButton.text(), "the selected value is propogated back to the button text" ); + start(); + } + ]); + }); + + // https://github.com/jquery/jquery-mobile/issues/2181 + asyncTest( "dialog sized select should prevent the removal of its parent page from the dom", function(){ + var selectButton, parentPageId; + + expect( 2 ); + + $.testHelper.pageSequence([ + resetHash, + + function(){ + $.mobile.changePage( "cached.html" ); + }, + + function(){ + selectButton = $.mobile.activePage.find( "#cached-page-select" ).siblings( 'a' ); + parentPageId = $.mobile.activePage.attr( 'id' ); + same( $("#" + parentPageId).length, 1, "establish the parent page exists" ); + selectButton.click(); + }, + + function(){ + same( $( "#" + parentPageId).length, 1, "make sure parent page is still there after opening the dialog" ); + $.mobile.activePage.find( "li a" ).last().click(); + }, + + start + ]); + }); + + asyncTest( "dialog sized select shouldn't rebind its parent page remove handler when closing, if the parent page domCache option is true", function(){ + expect( 3 ); + + $.testHelper.pageSequence([ + resetHash, + + function(){ + $.mobile.changePage( "cached-dom-cache-true.html" ); + }, + + function(){ + $.mobile.activePage.find( "#domcache-page-select" ).siblings( 'a' ).click(); + }, + + function(){ + ok( $.mobile.activePage.hasClass('ui-dialog'), "the dialog came up" ); + $.mobile.activePage.find( "li a" ).last().click(); + }, + + function(){ + ok( $.mobile.activePage.is( "#dialog-select-parent-domcache-test" ), "the dialog closed" ); + $.mobile.changePage( $( "#default" ) ); + }, + + function(){ + same( $("#dialog-select-parent-domcache-test").length, 1, "make sure the select parent page is still cached in the dom after changing page" ); + start(); + } + ]); + }); +})(jQuery); \ No newline at end of file diff --git a/tests/unit/select/select_core.js b/tests/unit/select/select_core.js index 7a1d91c9..f32c345c 100644 --- a/tests/unit/select/select_core.js +++ b/tests/unit/select/select_core.js @@ -71,41 +71,6 @@ ]); }); - asyncTest( "a large select menu should come up in a dialog many times", function(){ - var menu, select; - - // if the second test doesn't run the dialog didn't come back up - expect( 2 ); - - $.testHelper.pageSequence([ - resetHash, - - function(){ - select = $("#select-choice-many-container a"); - - // bring up the dialog - select.trigger("click"); - }, - - function(){ - ok( $.mobile.activePage.is( ".ui-dialog "), "current page is a dialog" ); - closeDialog(); - }, - - function(){ - //bring up the dialog again - select.trigger("click"); - }, - - function(){ - ok( $.mobile.activePage.is( ".ui-dialog "), "current page is a dialog" ); - closeDialog(); - }, - - start - ]); - }); - asyncTest( "custom select menu always renders screen from the left", function(){ var select; @@ -204,65 +169,6 @@ ], 500); }); - // https://github.com/jquery/jquery-mobile/issues/2181 - asyncTest( "dialog sized select should alter the value of its parent select", function(){ - var selectButton, value; - - $.testHelper.pageSequence([ - resetHash, - - function(){ - $.mobile.changePage( "cached-tests.html" ); - }, - - function(){ - selectButton = $( "#cached-page-select" ).siblings( 'a' ); - selectButton.click(); - }, - - function(){ - ok( $.mobile.activePage.hasClass('ui-dialog'), "the dialog came up" ); - var option = $.mobile.activePage.find( "li a" ).not(":contains('" + selectButton.text() + "')").last(); - value = option.text(); - option.click(); - }, - - function(){ - same( value, selectButton.text(), "the selected value is propogated back to the button text" ); - start(); - } - ]); - }); - - // https://github.com/jquery/jquery-mobile/issues/2181 - asyncTest( "dialog sized select should prevent the removal of its parent page from the dom", function(){ - var selectButton, parentPageId; - - expect( 2 ); - - $.testHelper.pageSequence([ - resetHash, - - function(){ - $.mobile.changePage( "cached-tests.html" ); - }, - - function(){ - selectButton = $.mobile.activePage.find( "#cached-page-select" ).siblings( 'a' ); - parentPageId = $.mobile.activePage.attr( 'id' ); - same( $("#" + parentPageId).length, 1, "establish the parent page exists" ); - selectButton.click(); - }, - - function(){ - same( $( "#" + parentPageId).length, 1, "make sure parent page is still there after opening the dialog" ); - $.mobile.activePage.find( "li a" ).last().click(); - }, - - start - ]); - }); - asyncTest( "using custom refocuses the button after close", function() { var select, button, triggered = false; @@ -290,11 +196,13 @@ ok(triggered, "focus is triggered"); start(); } - ], 1000); + ], 5000); }); asyncTest( "selected items are highlighted", function(){ $.testHelper.sequence([ + resetHash, + function(){ // bring up the smaller choice menu ok($("#select-choice-few-container a").length > 0, "there is in fact a button in the page"); @@ -344,4 +252,5 @@ same( button.attr('aria-disabled'), "false", "select is disabled" ); same( select.selectmenu( 'option', 'disabled' ), false, "disbaled option set" ); }); + })(jQuery);