Merge remote branch 'origin/master'

This commit is contained in:
scottjehl 2011-03-13 17:21:45 -04:00
commit 80e72addde
7 changed files with 136 additions and 73 deletions

View file

@ -29,9 +29,9 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
select = this.element
.wrap( "<div class='ui-select'>" ),
selectID = select.attr( "id" ),
selectID = select.attr( "id" ),
label = $( "label[for="+ selectID +"]" ).addClass( "ui-select" ),
button = ( self.options.nativeMenu ? $( "<div/>" ) : $( "<a>", {
@ -52,31 +52,31 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
shadow: o.shadow,
iconshadow: o.iconshadow
}),
//multi select or not
isMultiple = self.isMultiple = select[0].multiple;
//Opera does not properly support opacity on select elements
//In Mini, it hides the element, but not its text
//On the desktop,it seems to do the opposite
//for these reasons, using the nativeMenu option results in a full native select in Opera
if( o.nativeMenu && window.opera && window.opera.version ){
select.addClass( "ui-select-nativeonly" );
}
//vars for non-native menus
if( !o.nativeMenu ){
}
//vars for non-native menus
if( !o.nativeMenu ){
var options = select.find("option"),
buttonId = selectID + "-button",
menuId = selectID + "-menu",
thisPage = select.closest( ".ui-page" ),
//button theme
theme = /ui-btn-up-([a-z])/.exec( button.attr("class") )[1],
menuPage = $( "<div data-role='dialog' data-theme='"+ o.menuPageTheme +"'>" +
"<div data-role='header'>" +
"<div class='ui-title'>" + label.text() + "</div>"+
@ -85,17 +85,17 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
"</div>" )
.appendTo( $.mobile.pageContainer )
.page(),
menuPageContent = menuPage.find( ".ui-content" ),
menuPageClose = menuPage.find( ".ui-header a" ),
screen = $( "<div>", {"class": "ui-selectmenu-screen ui-screen-hidden"})
.appendTo( thisPage ),
listbox = $( "<div>", { "class": "ui-selectmenu ui-selectmenu-hidden ui-overlay-shadow ui-corner-all pop ui-body-" + o.overlayTheme } )
.insertAfter(screen),
list = $( "<ul>", {
"class": "ui-selectmenu-list",
"id": menuId,
@ -104,17 +104,17 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
"data-theme": theme
})
.appendTo( listbox ),
header = $( "<div>", {
"class": "ui-header ui-bar-" + theme
})
.prependTo( listbox ),
headerTitle = $( "<h1>", {
"class": "ui-title"
})
.appendTo( header ),
headerClose = $( "<a>", {
"data-iconpos": "notext",
"data-icon": "delete",
@ -124,9 +124,9 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
})
.appendTo( header )
.buttonMarkup(),
menuType;
} //end non native vars
} //end non native vars
// add counter for multi selects
if( isMultiple ){
@ -144,7 +144,7 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
.change(function(){
self.refresh();
});
//expose to other methods
$.extend(self, {
select: select,
@ -165,7 +165,7 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
headerClose:headerClose,
headerTitle:headerTitle,
placeholder: ''
});
});
//support for using the native select menu with a custom button
if( o.nativeMenu ){
@ -191,7 +191,7 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
button.attr( "tabindex", "-1" );
} else {
//create list from select, update state
self.refresh();
@ -228,22 +228,22 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
$( this ).data( "moved", true );
}
});
//events for list items
list.delegate("li:not(.ui-disabled, .ui-li-divider)", "click", function(event){
// clicking on the list item fires click on the link in listview.js.
// to prevent this handler from firing twice if the link isn't clicked on,
// short circuit unless the target is the link
if( !$(event.target).is("a") ){ return; }
// index of option tag to be selected
var newIndex = list.find( "li:not(.ui-li-divider)" ).index( this ),
option = self.optionElems.eq( newIndex )[0];
// toggle selected status on the tag for multi selects
option.selected = isMultiple ? !option.selected : true;
// toggle checkbox class for multiple selects
if( isMultiple ){
$(this)
@ -251,18 +251,18 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
.toggleClass('ui-icon-checkbox-on', option.selected)
.toggleClass('ui-icon-checkbox-off', !option.selected);
}
// trigger change
select.trigger( "change" );
//hide custom select for single selects only
if( !isMultiple ){
self.close();
}
event.preventDefault();
});
//events on "screen" overlay + close button
screen
.add( headerClose )
@ -270,16 +270,16 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
.bind("click", function(event){
self.close();
event.preventDefault();
// if the dialog's close icon was clicked, prevent the dialog's close
// handler from firing. selectmenu's should take precedence
if( $.contains(menuPageClose[0], event.target) ){
event.stopImmediatePropagation();
}
});
}
}
},
_buildList: function(){
@ -311,7 +311,7 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
optgroups.push( optLabel );
}
}
//find placeholder text
if( !this.getAttribute('value') || text.length == 0 || $this.data('placeholder') ){
if( o.hidePlaceholderMenuItems ){
@ -328,7 +328,7 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
lis.push( "<li data-icon='"+ dataIcon +"' class='"+ classes.join(" ") + "' " + extraAttrs.join(" ") +">"+ anchor +"</li>" )
});
self.list.html( lis.join(" ") );
// hide header close link for single selects
@ -379,7 +379,7 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
if( isMultiple ){
self.buttonCount[ selected.length > 1 ? 'show' : 'hide' ]().text( selected.length );
}
if( !self.options.nativeMenu ){
self.list
.find( 'li:not(.ui-li-divider)' )
@ -388,25 +388,25 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
.each(function( i ){
if( $.inArray(i, indicies) > -1 ){
var item = $(this).addClass( $.mobile.activeBtnClass );
// aria selected attr
item.find( 'a' ).attr( 'aria-selected', true );
// multiple selects: add the "on" checkbox state to the icon
if( isMultiple ){
item.find('.ui-icon').removeClass('ui-icon-checkbox-off').addClass('ui-icon-checkbox-on');
}
}
});
}
}
},
open: function(){
if( this.options.disabled || this.options.nativeMenu ){ return; }
var self = this,
menuHeight = self.list.outerHeight(),
menuWidth = self.list.outerWidth(),
menuHeight = self.list.parent().outerHeight(),
menuWidth = self.list.parent().outerWidth(),
scrollTop = $(window).scrollTop(),
btnOffset = self.button.offset().top,
screenHeight = window.innerHeight,
@ -455,18 +455,29 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
var roomtop = btnOffset - scrollTop,
roombot = scrollTop + screenHeight - btnOffset,
halfheight = menuHeight / 2,
newtop,newleft;
if( roomtop > menuHeight / 2 && roombot > menuHeight / 2 ){
newtop = btnOffset + ( self.button.outerHeight() / 2 ) - halfheight;
}
else{
//30px tolerance off the edges
newtop = roomtop > roombot ? scrollTop + screenHeight - menuHeight - 30 : scrollTop + 30;
}
maxwidth = parseFloat(self.list.parent().css('max-width')),
newtop, newleft;
if( roomtop > menuHeight / 2 && roombot > menuHeight / 2 ){
newtop = btnOffset + ( self.button.outerHeight() / 2 ) - halfheight;
}
else{
//30px tolerance off the edges
newtop = roomtop > roombot ? scrollTop + screenHeight - menuHeight - 30 : scrollTop + 30;
}
// if the menuwidth is smaller than the screen center is
if (menuWidth < maxwidth) {
newleft = (screenWidth - menuWidth) / 2;
} else { //otherwise insure a >= 30px offset from the left
newleft = self.button.offset().left + self.button.outerWidth() / 2 - menuWidth / 2;
// 30px tolerance off the edges
if (newleft < 30) {
newleft = 30;
} else if ((newleft + menuWidth) > screenWidth) {
newleft = screenWidth - menuWidth - 30;
}
}
self.listbox
.append( self.list )

View file

@ -47,7 +47,10 @@
//return a url path with the window's location protocol/hostname removed
clean: function( url ){
return url.replace( location.protocol + "//" + location.host, "");
// Replace the protocol and host only once at the beginning of the url to avoid
// problems when it's included as a part of a param
var leadingUrlRootRegex = new RegExp("^" + location.protocol + "//" + location.host);
return url.replace(leadingUrlRootRegex, "");
},
//just return the url without an initial #

View file

@ -86,11 +86,13 @@
var localroot = location.href.split("/").slice(0, 3).join("/"),
remoteroot = "http://google.com/",
fakepath = "foo/bar/baz.html",
pathWithParam = localroot + "/bar?baz=" + localroot,
localpath = localroot + fakepath,
remotepath = remoteroot + fakepath;
same( $.mobile.path.clean( localpath ), fakepath, "removes location protocol, host, port from same-domain path");
same( $.mobile.path.clean( remotepath ), remotepath, "does nothing to an external domain path");
same( $.mobile.path.clean( pathWithParam ), "/bar?baz=" + localroot, "doesn't remove params with localroot value");
});
test( "path.stripHash is working properly", function(){
@ -242,7 +244,7 @@
function(){ $("#dup-history-second a:last").click(); },
function(){ $("#dup-history-dialog .ui-icon-delete").click(); },
function(){
// third page in the stack to account for first page being hash manipulation
same($.mobile.urlHistory.activeIndex, 3, "should be the third page in the stack");
start();

View file

@ -14,6 +14,7 @@
<script type="text/javascript" src="../../../external/qunit.js"></script>
<script type="text/javascript" src="select_events.js"></script>
<script type="text/javascript" src="select_core.js"></script>
</head>
<body>
@ -106,5 +107,25 @@
<option value="WY">Wyoming</option>
</select>
</div>
<div data-role="fieldcontain" id="select-offscreen-container">
<style>
/* keep the select small and close to the screen border to test rendering */
#select-offscreen-container {
width: 100px;
position: absolute;
left: 0px;
top: 0px;
}
</style>
<select name="select-choice-few" id="select-offscreen">
<option value="standard">Standard: 7 day</option>
<option value="rush">Rush: 3 days</option>
<option value="express">Express: next day</option>
<option value="overnight">Overnight</option>
</select>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,24 @@
/*
* mobile select unit tests
*/
(function($){
var libName = "jquery.mobile.forms.select.js";
module(libName, {
teardown: function(){ location.hash = ""; }
});
asyncTest( "custom select menu always renders screen from the left", function(){
expect( 1 );
var select = $("ul#select-offscreen-menu");
$('#select-offscreen-container a').trigger($.support.touch ? "touchend" : "mouseup");
setTimeout(function(){
ok(select.offset().left >= 30);
start();
}, 1000);
});
})(jQuery);

View file

@ -6,7 +6,9 @@
var mouseUpTouchEnd = $.support.touch ? "touchend" : "mouseup",
libName = "jquery.mobile.forms.select.js";
module(libName);
module(libName, {
teardown: function(){ location.hash = ""; }
});
test( "a large select menu should come up in a dialog many times", function(){
var menu, select = $("#select-choice-many-container a");
@ -45,7 +47,7 @@
stop();
});
test( "selects marked with data-native-menu=true should use a div as their button", function(){
same($("#select-choice-native-container div.ui-btn").length, 1);
});
@ -53,7 +55,7 @@
test( "selects marked with data-native-menu=true should not have a custom menu", function(){
same($("#select-choice-native-container ul").length, 0);
});
test( "selects marked with data-native-menu=true should sit inside the button", function(){
same($("#select-choice-native-container div.ui-btn select").length, 1);
});

View file

@ -21,7 +21,7 @@
background-image: -webkit-gradient(linear,left top,left bottom,
color-stop(0, #3c3c3c),
color-stop(1, #111111));
-msfilter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#3c3c3c', EndColorStr='#111111')";
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#3c3c3c', EndColorStr='#111111')";
}
.ui-bar-a,
.ui-bar-a input,
@ -352,7 +352,7 @@
background-image: -webkit-gradient(linear,left top,left bottom,
color-stop(0, #eeeeee),
color-stop(1, #fdfdfd));
-msfilter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#eeeeee', EndColorStr='#fdfdfd')";
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#eeeeee', EndColorStr='#fdfdfd')";
}
.ui-btn-down-c a.ui-link-inherit {
color: #2F3E46;
@ -439,7 +439,7 @@
background-image: -webkit-gradient(linear,left top,left bottom,
color-stop(0, #fdfdfd),
color-stop(1, #eeeeee));
-msfilter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fdfdfd', EndColorStr='#eeeeee')";
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fdfdfd', EndColorStr='#eeeeee')";
}
.ui-btn-hover-d a.ui-link-inherit {
color: #222;
@ -456,7 +456,7 @@
background-image: -webkit-gradient(linear,left top,left bottom,
color-stop(0, #eeeeee),
color-stop(1, #ffffff));
-msfilter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#eeeeee', EndColorStr='#ffffff')";
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#eeeeee', EndColorStr='#ffffff')";
}
.ui-btn-down-d a.ui-link-inherit {
border: 1px solid #808080;
@ -470,7 +470,7 @@
background-image: -webkit-gradient(linear,left top,left bottom,
color-stop(0, #cccccc),
color-stop(1, #eeeeee));
-msfilter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#cccccc', EndColorStr='#eeeeee')";
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#cccccc', EndColorStr='#eeeeee')";
}
.ui-btn-up-d,
.ui-btn-hover-d,
@ -493,7 +493,7 @@
background-image: -webkit-gradient(linear,left top,left bottom,
color-stop(0, #fceda7),
color-stop(1, #fadb4e));
-msfilter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fceda7', EndColorStr='#fadb4e')";
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fceda7', EndColorStr='#fadb4e')";
}
.ui-bar-e,
.ui-bar-e input,
@ -520,7 +520,7 @@
background-image: -webkit-gradient(linear,left top,left bottom,
color-stop(0, #fff),
color-stop(1, #faeb9e));
-msfilter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#ffffff', EndColorStr='#faeb9e')";
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#ffffff', EndColorStr='#faeb9e')";
}
.ui-body-e,
.ui-body-e input,
@ -569,7 +569,7 @@
background-image: -webkit-gradient(linear,left top,left bottom,
color-stop(0, #fcf0b5),
color-stop(1, #fbe26f));
-msfilter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fcf0b5', EndColorStr='#fbe26f')";
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fcf0b5', EndColorStr='#fbe26f')";
}
.ui-btn-hover-e a.ui-link-inherit {
@ -624,7 +624,7 @@ a.ui-link-inherit {
background-image: -webkit-gradient(linear,left top,left bottom,
color-stop(0, #85bae4),
color-stop(1, #5393c5));
-msfilter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#85bae4', EndColorStr='#5393c5')";
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#85bae4', EndColorStr='#5393c5')";
outline: none;
}
.ui-btn-active a.ui-link-inherit {