From 69c9ca4c81969bcbf1fa0b054e22b127dff74216 Mon Sep 17 00:00:00 2001
From: dotnetwise
Date: Tue, 24 Jan 2012 17:14:02 +0200
Subject: [PATCH] Added support for data-filter and data-filter-placeholder on
regular selects when data-native-menu="false"
---
js/jquery.mobile.forms.select.custom.js | 63 +++++++++++++++++--------
1 file changed, 43 insertions(+), 20 deletions(-)
diff --git a/js/jquery.mobile.forms.select.custom.js b/js/jquery.mobile.forms.select.custom.js
index 3fd6137e0e8..c9b930e3251 100644
--- a/js/jquery.mobile.forms.select.custom.js
+++ b/js/jquery.mobile.forms.select.custom.js
@@ -29,21 +29,28 @@ define( [
isMultiple = widget.isMultiple = widget.select[ 0 ].multiple,
buttonId = selectID + "-button",
menuId = selectID + "-menu",
- menuPage = $( "" +
- "
" +
- "
" + label.getEncodedText() + "
"+
- "
"+
- "
"+
- "
" ).appendTo( $.mobile.pageContainer ).page(),
+ data = "data-" + $.mobile.ns,
+ menuPage = $( ["",
+ "
",
+ "
", label.getEncodedText(), "
",
+ "
",
+ "
",
+ "
"].join("") ).appendTo( $.mobile.pageContainer ).page(),
listbox = $("", { "class": "ui-selectmenu ui-selectmenu-hidden ui-overlay-shadow ui-corner-all ui-body-" + widget.options.overlayTheme + " " + $.mobile.defaultDialogTransition } ).insertAfter(screen),
+ listContainer = $("
")
+ .appendTo( listbox ),
list = $( "
", {
"class": "ui-selectmenu-list",
"id": menuId,
- "role": "listbox",
+ "class": "ui-selectmenu-list " + select.attr("class"),
"aria-labelledby": buttonId
- }).attr( "data-" + $.mobile.ns + "theme", widget.options.theme ).appendTo( listbox ),
+ }).attr( data + "theme", widget.options.theme )
+ .attr( data + "role", "listview" )
+ .attr( data + "filter", select.attr( data + "filter" ) || false)
+ .attr( data + "filter-placeholder", select.attr( data + "filter-placeholder" ) || null)
+ .appendTo( listContainer ),
header = $( "", {
"class": "ui-header ui-bar-" + widget.options.theme
@@ -77,6 +84,7 @@ define( [
isMultiple: isMultiple,
theme: widget.options.theme,
listbox: listbox,
+ listContainer: listContainer,
list: list,
header: header,
headerTitle: headerTitle,
@@ -108,7 +116,8 @@ define( [
});
// Events for list items
- self.list.attr( "role", "listbox" )
+ self.list
+ .data("role", "listview")
.delegate( ".ui-li>a", "focusin", function() {
$( this ).attr( "tabindex", "0" );
})
@@ -134,6 +143,7 @@ define( [
// trigger change if value changed
if ( self.isMultiple || oldIndex !== newIndex ) {
+ self.select[0].selectedIndex = newIndex;
self.select.trigger( "change" );
}
@@ -196,7 +206,7 @@ define( [
// button refocus ensures proper height calculation
// by removing the inline style and ensuring page inclusion
self.menuPage.bind( "pagehide", function() {
- self.list.appendTo( self.listbox );
+ self.listContainer.appendTo( self.listbox );
self._focusButton();
// TODO centralize page removal binding / handling in the page plugin.
@@ -233,13 +243,19 @@ define( [
},
_isRebuildRequired: function() {
- var list = this.list.find( "li" ),
- options = this._selectOptions();
+ //var list = this.list.find( "li" ),
+ // options = this._selectOptions();
// TODO exceedingly naive method to determine difference
// ignores value changes etc in favor of a forcedRebuild
// from the user in the refresh method
- return options.text() !== list.text();
+ //return options.text() !== list.text();
+
+ //the above is completly rubbish if you use optgroup as their label attribute won't be serialized, but instead they will appear on li as text
+ //we don't really care about our text/html, but about select's html
+ var rebuildRequired = this.select.html() != this.selectHTML; // for better memory performance in detriment of CPU we should store the MD5 version of the html
+ return rebuildRequired;
+
},
refresh: function( forceRebuild , foo ){
@@ -294,7 +310,7 @@ define( [
} else {
self.screen.addClass( "ui-screen-hidden" );
self.listbox.addClass( "ui-selectmenu-hidden" ).removeAttr( "style" ).removeClass( "in" );
- self.list.appendTo( self.listbox );
+ self.listContainer.appendTo( self.listbox );
self._focusButton();
}
@@ -331,7 +347,7 @@ define( [
self.list.find( $.mobile.activeBtnClass ).focus();
}
- if ( menuHeight > screenHeight - 80 || !$.support.scrollTop ) {
+ if (self.list.data($.mobile.ns + "filter") || menuHeight > screenHeight - 80 || !$.support.scrollTop ) {
// prevent the parent page from being removed from the DOM,
// otherwise the results of selecting a list item in the dialog
// fall into a black hole
@@ -358,7 +374,8 @@ define( [
});
self.menuType = "page";
- self.menuPageContent.append( self.list );
+ self.refresh();//refresh select's active item to be 'up to date' and maybe select's items if they have changed since last time
+ self.listContainer.appendTo(self.menuPageContent);
self.menuPage.find("div .ui-title").text(self.label.text());
$.mobile.changePage( self.menuPage, {
transition: $.mobile.defaultDialogTransition
@@ -399,7 +416,7 @@ define( [
}
}
- self.listbox.append( self.list )
+ self.listbox.append( self.listContainer )
.removeClass( "ui-selectmenu-hidden" )
.css({
top: newtop,
@@ -423,13 +440,16 @@ define( [
dataIcon = self.isMultiple ? "checkbox-off" : "false";
self.list.empty().filter( ".ui-listview" ).listview( "destroy" );
+ self.selectHTML = self.select.html();// for better memory performance in detriment of CPU we should store the MD5 version of the html
// Populate menu with options from select element
self.select.find( "option" ).each( function( i ) {
var $this = $( this ),
$parent = $this.parent(),
text = $this.getEncodedText(),
- anchor = "
"+ text +"",
+ anchorStart = "
added in the concatenation
+ anchorEnd = "",
+ optClass = $this.attr("class"),//forward any css class the option might have
classes = [],
extraAttrs = [];
@@ -439,7 +459,7 @@ define( [
// has this optgroup already been built yet?
if ( $.inArray( optLabel, optgroups ) === -1 ) {
- lis.push( "
- "+ optLabel +"
" );
+ lis.push( "
- ", optLabel, "
" );
optgroups.push( optLabel );
}
}
@@ -459,7 +479,8 @@ define( [
extraAttrs.push( "aria-disabled='true'" );
}
- lis.push( "
- "+ anchor +"
" );
+ //optimized concatenation rather than string building!
+ lis.push( "
- ", anchorStart, optClass && "class='", optClass, optClass && "'", ">", text, anchorEnd, "
" );
});
self.list.html( lis.join(" ") );
@@ -482,6 +503,8 @@ define( [
// Now populated, create listview
self.list.listview();
+ self.list.attr("data-role", null);//remove the attribute, so on next refresh the filter won't be recreated
+ self.listContainer.find("input").change();//triger the filering to preserve the items
},
_button: function(){