mirror of
https://github.com/Hopiu/jquery-mobile.git
synced 2026-03-16 22:10:25 +00:00
Refactored select plugin.
This commit is contained in:
parent
01b9924f0b
commit
effbaa9f58
2 changed files with 180 additions and 190 deletions
|
|
@ -12,15 +12,10 @@
|
|||
label.ui-select { font-size: 16px; line-height: 1.4; font-weight: normal; margin: 0 0 .3em; display: block; }
|
||||
|
||||
/*listbox*/
|
||||
.ui-listbox { position: relative; margin: 8px; padding: 0; z-index: 100; }
|
||||
.ui-page-content-hidden, .ui-listbox-hidden { display: none; }
|
||||
.ui-listbox-screen { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
|
||||
.ui-listbox-overlay { position: absolute; z-index: 999; width: 300px; margin-left: -150px; }
|
||||
.ui-listbox-header { background: none; border: 0; }
|
||||
.ui-listbox-overlay .ui-listbox-header { display: none; }
|
||||
.ui-listbox-list { list-style: none; margin: 5px; padding: 0; }
|
||||
.ui-listbox .ui-listbox-option { margin: 0; text-align: left; }
|
||||
.ui-li .ui-icon { display: none; }
|
||||
.ui-listbox { position: absolute; padding: 0; z-index: 100; width: 80%; padding: 10px; }
|
||||
.ui-listbox-hidden { top: -999999px; left: -99999px; }
|
||||
.ui-listbox-screen { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 99; }
|
||||
.ui-screen-hidden, .ui-li .ui-icon { display: none; }
|
||||
.ui-btn-active .ui-icon { display: block; }
|
||||
|
||||
/*used in listbox - to be removed/replaced with page-style hiding*/
|
||||
|
|
|
|||
|
|
@ -7,210 +7,205 @@
|
|||
(function($){
|
||||
$.fn.customSelect = function(options){
|
||||
return $(this).each(function(){
|
||||
var select = $(this)
|
||||
.attr( "tabindex", "-1" )
|
||||
.wrap( "<div class='ui-select'>" ),
|
||||
selectID = select.attr( "id" ),
|
||||
label = $( "label[for="+ selectID +"]" )
|
||||
.addClass( "ui-select" ),
|
||||
|
||||
//extendable options
|
||||
var o = $.extend({
|
||||
closeText: 'close',
|
||||
chooseText: 'Choose one:'
|
||||
}, options);
|
||||
|
||||
var select = $(this),
|
||||
label = $('label[for='+ select.attr('id') +']').addClass('ui-select'),
|
||||
buttonId = select.attr('id')+'-button',
|
||||
menuId = select.attr('id')+'-menu',
|
||||
thisPage = $(this).closest('.ui-page'),
|
||||
//create menu button
|
||||
button = $('<a href="#">'+ $(this.options.item(this.selectedIndex)).text() +'</a>')
|
||||
.buttonMarkup({
|
||||
iconpos: 'right',
|
||||
icon: 'arrow-d'
|
||||
})
|
||||
.attr({
|
||||
'role': 'button',
|
||||
'title': 'select menu',
|
||||
'id': buttonId,
|
||||
'aria-haspopup': 'true',
|
||||
'aria-owns': menuId
|
||||
})
|
||||
// FIXME why mousedown? doesn't seem to work on desktop browsers
|
||||
.mousedown(function(){
|
||||
select.trigger('showmenu');
|
||||
return false;
|
||||
})
|
||||
.insertBefore(select),
|
||||
menuPage = $( "<div data-role='dialog'>"+
|
||||
"<div data-role='header' data-theme='b'>"+
|
||||
"<a href='#' class='ui-btn-left' data-icon='delete' data-iconpos='notext'>"+ o.closeText +"</a><div class='ui-title'>" + o.chooseText + "</div></div>"+
|
||||
"<div data-role='content'></div></div>"+
|
||||
"</div>" )
|
||||
.appendTo( "body" )
|
||||
.page(),
|
||||
menuPageContent = menuPage.find('.ui-content'),
|
||||
listbox = $('<div class="ui-listbox ui-listbox-overlay ui-body-a ui-overlay-shadow ui-corner-all pop"></div>'),
|
||||
list = $('<ul class="ui-listbox-list" id="'+ menuId +'" role="listbox" aria-labelledby="'+ buttonId +'"></ul>')
|
||||
.appendTo(listbox);
|
||||
|
||||
o = $.extend({
|
||||
closeText: "close",
|
||||
chooseText: label.text()
|
||||
}, options),
|
||||
|
||||
buttonId = selectID + "-button",
|
||||
menuId = selectID + "-menu",
|
||||
thisPage = select.closest( ".ui-page" ),
|
||||
menuType,
|
||||
currScroll,
|
||||
button = $( "<a>", {
|
||||
"href": "#",
|
||||
"role": "button",
|
||||
"title": "select menu",
|
||||
"id": buttonId,
|
||||
"aria-haspopup": "true",
|
||||
"aria-owns": menuId
|
||||
})
|
||||
.text( $( this.options.item(this.selectedIndex) ).text() )
|
||||
.insertBefore( select )
|
||||
.buttonMarkup({
|
||||
iconpos: 'right',
|
||||
icon: 'arrow-d'
|
||||
}),
|
||||
menuPage = $( "<div data-role='dialog' data-theme='a'>" +
|
||||
"<div data-role='header' data-theme='b'>" +
|
||||
"<a href='#' class='ui-btn-left' data-icon='delete' data-iconpos='notext'>"+ o.closeText +"</a>"+
|
||||
"<div class='ui-title'>" + o.chooseText + "</div>"+
|
||||
"</div>"+
|
||||
"<div data-role='content'></div>"+
|
||||
"</div>" )
|
||||
.appendTo( "body" )
|
||||
.page(),
|
||||
menuPageContent = menuPage.find( ".ui-content" ),
|
||||
screen = $( "<div>", {
|
||||
"class": "ui-listbox-screen ui-overlay ui-screen-hidden fade"
|
||||
})
|
||||
.appendTo( thisPage ),
|
||||
listbox = $( "<div>", { "class": "ui-listbox ui-listbox-hidden ui-body-a ui-overlay-shadow ui-corner-all pop"} )
|
||||
.insertAfter(screen),
|
||||
list = $( "<ul>", {
|
||||
"class": "ui-listbox-list",
|
||||
"id": menuId,
|
||||
"role": "listbox",
|
||||
"aria-labelledby": buttonId
|
||||
})
|
||||
.appendTo( listbox );
|
||||
|
||||
//populate menu
|
||||
select.find('option').each(function(i){
|
||||
var thisclass = select[0].selectedIndex == i ? 'ui-btn-active' : '';
|
||||
var thisselected = select[0].selectedIndex == i ? ' aria-selected="true"' : '';
|
||||
$('<li></li>')
|
||||
.addClass(thisclass)
|
||||
.attr("data-icon","checkbox-on")
|
||||
.append( $('<a href="#" class="ui-listbox-option"'+thisselected+' role="option">'+ $(this).text() +'</a>') )
|
||||
.appendTo(list);
|
||||
select.find( "option" ).each(function( i ){
|
||||
var selected = (select[0].selectedIndex == i),
|
||||
anchor = $("<a>", {
|
||||
"aria-selected": selected,
|
||||
"role": "option",
|
||||
"href": "#"
|
||||
})
|
||||
.text( $(this).text() );
|
||||
|
||||
$( "<li>", {
|
||||
"class": selected ? "ui-btn-active" : '',
|
||||
"data-icon": "checkbox-on"
|
||||
})
|
||||
.append( anchor )
|
||||
.appendTo( list );
|
||||
});
|
||||
|
||||
|
||||
//now populated, create listview
|
||||
list.listview();
|
||||
|
||||
|
||||
//select properties,events
|
||||
|
||||
function showmenu(){
|
||||
var menuHeight = list.outerHeight();
|
||||
currScroll = [ $(window).scrollLeft(), $(window).scrollTop() ];
|
||||
|
||||
if( menuHeight > window.innerHeight - 80 ){
|
||||
menuType = "page";
|
||||
$.changePage(thisPage, menuPage, "slideup", false);
|
||||
menuPageContent.append( list );
|
||||
}
|
||||
else {
|
||||
menuType = "overlay";
|
||||
|
||||
screen
|
||||
.height( $(document).height() )
|
||||
.removeClass('ui-screen-hidden');
|
||||
|
||||
listbox
|
||||
.append( list )
|
||||
.removeClass( "ui-listbox-hidden" )
|
||||
.css({
|
||||
top: $(window).scrollTop() + (window.innerHeight/2),
|
||||
"margin-top": -menuHeight/2,
|
||||
left: window.innerWidth/2,
|
||||
"margin-left": -1* listbox.outerWidth() / 2
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function hidemenu(){
|
||||
if(menuType == "page"){
|
||||
$.changePage(menuPage, thisPage, "slideup", true);
|
||||
}
|
||||
else{
|
||||
screen.addClass( "ui-screen-hidden" );
|
||||
listbox.addClass( "ui-listbox-hidden" ).removeAttr( "style" );
|
||||
}
|
||||
};
|
||||
|
||||
//page show/hide events
|
||||
menuPage
|
||||
.bind("pageshow", function(){
|
||||
list.find( ".ui-btn-active" ).focus();
|
||||
return false;
|
||||
})
|
||||
.bind("pagehide", function(){
|
||||
window.scrollTo(currScroll[0], currScroll[1]);
|
||||
//select.focus();
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
//select properties,events
|
||||
select
|
||||
.change(function(){
|
||||
var ele = select.get(0);
|
||||
button.find('.ui-btn-text').text($(ele.options.item(ele.selectedIndex)).text());
|
||||
var $el = select.get(0);
|
||||
button.find( ".ui-btn-text" ).text( $($el.options.item($el.selectedIndex)).text() );
|
||||
})
|
||||
.focus(function(){
|
||||
$(this).blur();
|
||||
button.focus();
|
||||
});
|
||||
|
||||
//button events
|
||||
button
|
||||
.tap(function(){
|
||||
showmenu();
|
||||
return false;
|
||||
})
|
||||
.wrap('<div class="ui-select"></div>')
|
||||
.attr('tabindex','-1')
|
||||
.bind('showmenu',function(){
|
||||
$(document).data('currScroll', [$(window).scrollLeft(), $(window).scrollTop()]);
|
||||
if(menuHeight > window.innerHeight - 80){
|
||||
menuType = "page";
|
||||
}
|
||||
else {
|
||||
menuType = "overlay";
|
||||
listbox.css({
|
||||
top: $(window).scrollTop() + (window.innerHeight/2),
|
||||
'margin-top': -menuHeight/2,
|
||||
left: window.innerWidth/2
|
||||
});
|
||||
}
|
||||
|
||||
screen.css({width: $(window).width(), height: $(document).height()}).removeClass('ui-helper-hidden out').addClass('in');
|
||||
listbox.removeClass('ui-listbox-hidden');
|
||||
var selectedLI = list.find('.ui-btn-active').focus();
|
||||
|
||||
if(menuType == "page"){
|
||||
list.appendTo(menuPageContent);
|
||||
$.changePage(thisPage, menuPage, 'slideup', false);
|
||||
}
|
||||
else{
|
||||
list.appendTo(listbox).addClass('in');
|
||||
}
|
||||
|
||||
})
|
||||
.bind('hidemenu',function(){
|
||||
if(menuType == "page"){
|
||||
$.changePage(menuPage, thisPage, 'slideup', true);
|
||||
}
|
||||
else{
|
||||
screen.addClass('ui-helper-hidden out');
|
||||
listbox.removeClass('in').addClass('ui-listbox-hidden out');
|
||||
}
|
||||
|
||||
setTimeout(function(){
|
||||
button.focus();
|
||||
if(menuType == "page"){
|
||||
$(window)[0].scrollTo($(document).data('currScroll')[0], $(document).data('currScroll')[1]);
|
||||
if(button.offset().top > window.innerHeight){
|
||||
$(window)[0].scrollTo(0, button.offset().top);
|
||||
}
|
||||
}
|
||||
}, 50);
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
//apply click events for items
|
||||
list.find('a')
|
||||
.click(function(){
|
||||
list.find('[aria-selected=true]').removeClass('ui-btn-active').attr('aria-selected',false);
|
||||
$(this).addClass('ui-btn-active').attr('aria-selected', true);
|
||||
var newIndex = list.find('a').index(this),
|
||||
prevIndex = select[0].selectedIndex;
|
||||
select[0].selectedIndex = list.find('a').index(this);
|
||||
if(newIndex != prevIndex){
|
||||
select.trigger('change');
|
||||
}
|
||||
select.trigger('hidemenu');
|
||||
return false;
|
||||
});
|
||||
|
||||
//back button
|
||||
menuPage.find('.ui-header a').click(function(){
|
||||
select.trigger('hidemenu');
|
||||
//apply click events for items
|
||||
list
|
||||
.click(function(e){
|
||||
e.stopImmediatePropagation();
|
||||
})
|
||||
.find("li")
|
||||
.click(function(e){
|
||||
return false; //prevent listview click behavior
|
||||
})
|
||||
.tap(function(){
|
||||
//deselect active
|
||||
list.find( "li" )
|
||||
.removeClass( "ui-btn-active" )
|
||||
.children(0)
|
||||
.attr( "aria-selected", "false");
|
||||
|
||||
//select this one
|
||||
$(this)
|
||||
.addClass( "ui-btn-active" )
|
||||
.find( "a" )
|
||||
.attr( "aria-selected", "true");
|
||||
|
||||
//update select
|
||||
var newIndex = list.find( "li" ).index( this ),
|
||||
prevIndex = select[0].selectedIndex;
|
||||
|
||||
select[0].selectedIndex = newIndex;
|
||||
|
||||
//trigger change event
|
||||
if(newIndex !== prevIndex){
|
||||
select.trigger( "change" );
|
||||
}
|
||||
|
||||
//hide custom select
|
||||
hidemenu();
|
||||
return false;
|
||||
});
|
||||
|
||||
//menu page back button
|
||||
menuPage.find( ".ui-btn-left" ).click(function(){
|
||||
hidemenu();
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//keyboard events for menu items
|
||||
list.keydown(function(event){
|
||||
if( !$(this).is('.ui-btn') ){
|
||||
//switch logic based on which key was pressed
|
||||
switch(event.keyCode){
|
||||
//up or left arrow keys
|
||||
case 37:
|
||||
case 38:
|
||||
//if there's a previous option, focus it
|
||||
if( $(event.target).parent().prev().length ){
|
||||
$(event.target).blur().parent().prev().find('a').eq(0).focus();
|
||||
}
|
||||
//prevent native scroll
|
||||
return false;
|
||||
break;
|
||||
//down or right arrow keys
|
||||
case 39:
|
||||
case 40:
|
||||
//if there's a next option, focus it
|
||||
if( $(event.target).parent().next().length ){
|
||||
$(event.target).blur().parent().next().find('a').eq(0).focus();
|
||||
}
|
||||
//prevent native scroll
|
||||
return false;
|
||||
break;
|
||||
//if enter or space is pressed in menu, trigger click
|
||||
case 13:
|
||||
case 32:
|
||||
$(event.target).trigger('click'); //should trigger select
|
||||
return false;
|
||||
break;
|
||||
//tab returns focus to the menu button, and then automatically shifts focus to the next focusable element on the page
|
||||
case 9:
|
||||
select.trigger('hidemenu');
|
||||
break;
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//add list to page
|
||||
|
||||
var screen = $('<div class="ui-listbox-screen ui-overlay ui-helper-hidden fadeto"></div>')
|
||||
.insertAfter(thisPage);
|
||||
listbox.insertAfter(screen);
|
||||
//get height for figuring out overlay vs. paged
|
||||
var menuHeight = list.outerHeight();
|
||||
|
||||
//menu type
|
||||
var menuType = "page";
|
||||
|
||||
//hide it
|
||||
listbox.addClass('ui-listbox-hidden');
|
||||
|
||||
|
||||
//hide on outside click
|
||||
screen.click(function(){
|
||||
listbox.addClass('ui-listbox-hidden out');
|
||||
screen.addClass('ui-helper-hidden out');
|
||||
hidemenu();
|
||||
return false;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue