mirror of
https://github.com/Hopiu/jquery-mobile.git
synced 2026-03-16 22:10:25 +00:00
Merge remote branch 'origin/master'
This commit is contained in:
commit
80e72addde
7 changed files with 136 additions and 73 deletions
|
|
@ -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 )
|
||||
|
|
|
|||
|
|
@ -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 #
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
24
tests/unit/select/select_core.js
Normal file
24
tests/unit/select/select_core.js
Normal 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);
|
||||
|
|
@ -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);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in a new issue