namespaced data- attrs to $.mobile.ns (defaults to "jq-") throughout the JS

This commit is contained in:
scottjehl 2011-02-20 12:12:01 -05:00
parent 62043a8a2e
commit ce34ece257
13 changed files with 163 additions and 52 deletions

View file

@ -63,7 +63,7 @@ $.fn.buttonMarkup = function( options ){
}
el
.attr( "data-theme", o.theme )
.attr( "data-" + $.mobile.ns + "theme", o.theme )
.addClass( buttonClass );
var wrap = ("<D class='" + innerClass + "'><D class='ui-btn-text'></D>" +
@ -84,19 +84,19 @@ $.fn.buttonMarkup.defaults = {
var attachEvents = function() {
$(".ui-btn:not(.ui-disabled)").live({
"touchstart mousedown": function() {
var theme = $(this).attr( "data-theme" );
var theme = $(this).attr( "data-" + $.mobile.ns + "theme" );
$(this).removeClass( "ui-btn-up-" + theme ).addClass( "ui-btn-down-" + theme );
},
"touchmove touchend mouseup": function() {
var theme = $(this).attr( "data-theme" );
var theme = $(this).attr( "data-" + $.mobile.ns + "theme" );
$(this).removeClass( "ui-btn-down-" + theme ).addClass( "ui-btn-up-" + theme );
},
"mouseover focus": function() {
var theme = $(this).attr( "data-theme" );
var theme = $(this).attr( "data-" + $.mobile.ns + "theme" );
$(this).removeClass( "ui-btn-up-" + theme ).addClass( "ui-btn-hover-" + theme );
},
"mouseout blur": function() {
var theme = $(this).attr( "data-theme" );
var theme = $(this).attr( "data-" + $.mobile.ns + "theme" );
$(this).removeClass( "ui-btn-hover-" + theme ).addClass( "ui-btn-up-" + theme );
}
});

View file

@ -21,7 +21,7 @@ $.widget( "mobile.collapsible", $.mobile.widget, {
collapsibleContain = $el.addClass('ui-collapsible-contain'),
collapsibleHeading = $el.find(o.heading).eq(0),
collapsibleContent = collapsibleContain.wrapInner('<div class="ui-collapsible-content"></div>').find('.ui-collapsible-content'),
collapsibleParent = $el.closest('[data-role="collapsible-set"]').addClass('ui-collapsible-set');
collapsibleParent = $el.closest( "[data-" + $.mobile.ns + "role='collapsible-set']" ).addClass('ui-collapsible-set');
//replace collapsibleHeading if it's a legend
if(collapsibleHeading.is('legend')){
@ -121,7 +121,7 @@ $.widget( "mobile.collapsible", $.mobile.widget, {
.not( "> .ui-collapsible-contain .ui-collapsible-contain" )
.trigger( "collapse" );
})
var set = collapsibleParent.find('[data-role=collapsible]')
var set = collapsibleParent.find( "[data-" + $.mobile.ns + "role=collapsible]" )
set.first()
.find('a:eq(0)')

View file

@ -8,8 +8,12 @@
*/
(function( $, window, undefined ) {
//jQuery.mobile configurable options
$.extend( $.mobile, {
//namespace used framework-wide for data-attrs, widget naming, and CSS classes
ns: "jq-",
//define the url parameter used for referencing widget-generated sub-pages.
//Translates to to example.html&ui-page=subpageIdentifier
@ -89,8 +93,79 @@
TAB: 9,
UP: 38,
WINDOWS: 91 // COMMAND
}
});
//trigger mobileinit event - useful hook for configuring $.mobile settings before they're used
$( window.document ).trigger( "mobileinit" );
//support conditions
//if device support condition(s) aren't met, leave things as they are -> a basic, usable experience,
//otherwise, proceed with the enhancements
if ( !$.mobile.gradeA() ) {
return;
}
//extend data() to treat namespaced data-attrs the same as non-namespaced ones
var jqd = $.fn.data;
$.fn.data = function( prop, value ){
if( !value && !this.attr( "[data-" + prop + "]" ) && this.attr( "[data-" $.mobile.ns + prop + "]" ) ){
prop = $.mobile.ns + prop;
return jqd.call( this, prop );
}
};
//define vars for interal use
var $window = $(window),
$html = $( "html" ),
$head = $( "head" ),
//loading div which appears during Ajax requests
//will not appear if $.mobile.loadingMessage is false
$loader = $.mobile.loadingMessage ?
$( "<div class='ui-loader ui-body-a ui-corner-all'>" +
"<span class='ui-icon ui-icon-loading spin'></span>" +
"<h1>" + $.mobile.loadingMessage + "</h1>" +
"</div>" )
: undefined;
//add mobile, initial load "rendering" classes to docEl
$html.addClass( "ui-mobile ui-mobile-rendering" );
//define & prepend meta viewport tag, if content is defined
$.mobile.metaViewportContent ? $( "<meta>", { name: "viewport", content: $.mobile.metaViewportContent}).prependTo( $head ) : undefined;
//expose some core utilities
$.extend($.mobile, {
// turn on/off page loading message.
pageLoading: function ( done ) {
if ( done ) {
$html.removeClass( "ui-loading" );
} else {
if( $.mobile.loadingMessage ){
var activeBtn =$( "." + $.mobile.activeBtnClass ).first();
$loader
.appendTo( $.mobile.pageContainer )
//position at y center (if scrollTop supported), above the activeBtn (if defined), or just 100px from top
.css( {
top: $.support.scrollTop && $(window).scrollTop() + $(window).height() / 2 ||
activeBtn.length && activeBtn.offset().top || 100
} );
}
$html.addClass( "ui-loading" );
}
},
//scroll page vertically: scroll to 0 to hide iOS address bar, or pass a Y value
silentScroll: function( ypos ) {
ypos = ypos || 0;
// prevent scrollstart and scrollstop events
@ -104,6 +179,42 @@
setTimeout(function() {
$.event.special.scrollstart.enabled = true;
}, 150 );
},
// find and enhance the pages in the dom and transition to the first page.
initializePage: function(){
//find present pages
var $pages = $( "[data-" + $.mobile.ns + "role='page']" );
//add dialogs, set data-url attrs
$pages.add( "[data-" + $.mobile.ns + "role='dialog']" ).each(function(){
$(this).attr( "data-" + $.mobile.ns + "url", $(this).attr( "id" ));
});
//define first page in dom case one backs out to the directory root (not always the first page visited, but defined as fallback)
$.mobile.firstPage = $pages.first();
//define page container
$.mobile.pageContainer = $pages.first().parent().addClass( "ui-mobile-viewport" );
//cue page loading message
$.mobile.pageLoading();
// if hashchange listening is disabled or there's no hash deeplink, change to the first page in the DOM
if( !$.mobile.hashListeningEnabled || !$.mobile.path.stripHash( location.hash ) ){
$.mobile.changePage( $.mobile.firstPage, false, true, false, true );
}
// otherwise, trigger a hashchange to load a deeplink
else {
$window.trigger( "hashchange", [ true ] );
}
}
});
//dom-ready inits
$($.mobile.initializePage);
//window load event
//hide iOS browser chrome on load
$window.load( $.mobile.silentScroll );
})( jQuery, this );

View file

@ -16,14 +16,14 @@ $.widget( "mobile.dialog", $.mobile.widget, {
//add ARIA role
.attr("role","dialog")
.addClass('ui-page ui-dialog ui-body-a')
.find('[data-role=header]')
.find( "[data-" + $.mobile.ns + "role=header]" )
.addClass('ui-corner-top ui-overlay-shadow')
.prepend( '<a href="#" data-icon="delete" data-rel="back" data-iconpos="notext">Close</a>' )
.prepend( "<a href='#' data-" + $.mobile.ns + "icon='delete' data-" + $.mobile.ns + "rel='back' data-" + $.mobile.ns + "iconpos='notext'>Close</a>" )
.end()
.find('.ui-content:not([class*="ui-body-"])')
.addClass('ui-body-c')
.end()
.find('.ui-content,[data-role=footer]')
.find( ".ui-content,[data-" + $.mobile.ns + "role='footer']" )
.last()
.addClass('ui-corner-bottom ui-overlay-shadow');
@ -44,8 +44,8 @@ $.widget( "mobile.dialog", $.mobile.widget, {
if( $targetel.length && !$targetel.data("transition") ){
$targetel
.attr("data-transition", $.mobile.urlHistory.getActive().transition )
.attr("data-direction", "reverse");
.attr("data-" + $.mobile.ns + "transition", $.mobile.urlHistory.getActive().transition )
.attr("data-" + $.mobile.ns + "direction", "reverse");
}
});

View file

@ -12,8 +12,8 @@ $.fn.fixHeaderFooter = function(options){
var $this = $(this);
if( $this.data('fullscreen') ){ $this.addClass('ui-page-fullscreen'); }
$this.find('.ui-header[data-position="fixed"]').addClass('ui-header-fixed ui-fixed-inline fade'); //should be slidedown
$this.find('.ui-footer[data-position="fixed"]').addClass('ui-footer-fixed ui-fixed-inline fade'); //should be slideup
$this.find ".ui-header[data-" + $.mobile.ns + "position='fixed']" ).addClass('ui-header-fixed ui-fixed-inline fade'); //should be slidedown
$this.find( ".ui-footer[data-" + $.mobile.ns + "position='fixed']" ).addClass('ui-footer-fixed ui-fixed-inline fade'); //should be slideup
});
};
@ -104,12 +104,12 @@ $.fixedToolbars = (function(){
//before page is shown, check for duplicate footer
$('.ui-page').live('pagebeforeshow', function(event, ui){
var page = $(event.target),
footer = page.find('[data-role="footer"]:not(.ui-sticky-footer)'),
footer = page.find( "[data-" + $.mobile.ns + "role='footer']:not(.ui-sticky-footer)" ),
id = footer.data('id');
stickyFooter = null;
if (id)
{
stickyFooter = $('.ui-footer[data-id="' + id + '"].ui-sticky-footer');
stickyFooter = $( ".ui-footer[data-" + $.mobile.ns + "id='" + id + "'].ui-sticky-footer" );
if (stickyFooter.length == 0) {
// No sticky footer exists for this data-id. We'll use this
// footer as the sticky footer for the group and then create

View file

@ -12,7 +12,7 @@ $.widget( "mobile.checkboxradio", $.mobile.widget, {
_create: function(){
var self = this,
input = this.element,
label = input.closest("form,fieldset,[data-role='page']").find("label[for='" + input.attr( "id" ) + "']"),
label = input.closest("form,fieldset,[data-" + $.mobile.ns + "role='page']").find("label[for='" + input.attr( "id" ) + "']"),
inputtype = input.attr( "type" ),
checkedicon = "ui-icon-" + inputtype + "-on",
uncheckedicon = "ui-icon-" + inputtype + "-off";
@ -27,7 +27,7 @@ $.widget( "mobile.checkboxradio", $.mobile.widget, {
label
.buttonMarkup({
theme: this.options.theme,
icon: this.element.parents( "[data-type='horizontal']" ).length ? undefined : uncheckedicon,
icon: this.element.parents( "[data-" + $.mobile.ns + "type='horizontal']" ).length ? undefined : uncheckedicon,
shadow: false
});
@ -110,7 +110,7 @@ $.widget( "mobile.checkboxradio", $.mobile.widget, {
//returns either a set of radios with the same name attribute, or a single checkbox
_getInputSet: function(){
return this.element.closest( "form,fieldset,[data-role='page']" )
return this.element.closest( "form,fieldset,[data-" + $.mobile.ns + "role='page']" )
.find( "input[name='"+ this.element.attr( "name" ) +"'][type='"+ this.element.attr( "type" ) +"']" );
},
@ -126,7 +126,7 @@ $.widget( "mobile.checkboxradio", $.mobile.widget, {
refresh: function( ){
var input = this.element,
label = input.closest("form,fieldset,[data-role='page']").find("label[for='" + input.attr( "id" ) + "']"),
label = input.closest("form,fieldset,[data-" + $.mobile.ns + "role='page']").find("label[for='" + input.attr( "id" ) + "']"),
inputtype = input.attr( "type" ),
icon = label.find( ".ui-icon" ),
checkedicon = "ui-icon-" + inputtype + "-on",

View file

@ -77,11 +77,11 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
//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'>" +
menuPage = $( "<div data-" + $.mobile.ns + "role='dialog' data-theme='"+ o.menuPageTheme +"'>" +
"<div data-" + $.mobile.ns + "role='header'>" +
"<div class='ui-title'>" + label.text() + "</div>"+
"</div>"+
"<div data-role='content'></div>"+
"<div data-" + $.mobile.ns + "role='content'></div>"+
"</div>" )
.appendTo( $.mobile.pageContainer )
.page(),
@ -101,7 +101,7 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
"id": menuId,
"role": "listbox",
"aria-labelledby": buttonId,
"data-theme": theme
"data-" + $.mobile.ns + "theme": theme
})
.appendTo( listbox ),
@ -116,8 +116,8 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
.appendTo( header ),
headerClose = $( "<a>", {
"data-iconpos": "notext",
"data-icon": "delete",
"data-" + $.mobile.ns + "iconpos": "notext",
"data-" + $.mobile.ns + "icon": "delete",
"text": o.closeText,
"href": "#",
"class": "ui-btn-left"
@ -307,7 +307,7 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
// has this optgroup already been built yet?
if( $.inArray(optLabel, optgroups) === -1 ){
lis.push( "<li data-role='list-divider'>"+ optLabel +"</li>" );
lis.push( "<li data-" + $.mobile.ns + "role='list-divider'>"+ optLabel +"</li>" );
optgroups.push( optLabel );
}
}
@ -326,7 +326,7 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
extraAttrs.push( "aria-disabled='true'" );
}
lis.push( "<li data-icon='"+ dataIcon +"' class='"+ classes.join(" ") + "' " + extraAttrs.join(" ") +">"+ anchor +"</li>" )
lis.push( "<li data-" + $.mobile.ns + "icon='"+ dataIcon +"' class='"+ classes.join(" ") + "' " + extraAttrs.join(" ") +">"+ anchor +"</li>" )
});
self.list.html( lis.join(" ") );

View file

@ -31,7 +31,7 @@ $.widget( "mobile.textinput", $.mobile.widget, {
var focusedEl = input;
//"search" input widget
if( input.is('[type="search"],[data-type="search"]') ){
if( input.is( "[type='search'],[data-" + $.mobile.ns + "type='search']" ) ){
focusedEl = input.wrap('<div class="ui-input-search ui-shadow-inset ui-btn-corner-all ui-btn-shadow ui-icon-searchfield'+ themeclass +'"></div>').parent();
var clearbtn = $('<a href="#" class="ui-input-clear" title="clear text">clear text</a>')
.tap(function( e ){
@ -87,11 +87,11 @@ $.widget( "mobile.textinput", $.mobile.widget, {
},
disable: function(){
( this.element.attr("disabled",true).is('[type="search"],[data-type="search"]') ? this.element.parent() : this.element ).addClass("ui-disabled");
( this.element.attr("disabled",true).is( "[type='search'],[data-" + $.mobile.ns + "type='search']" ) ? this.element.parent() : this.element ).addClass("ui-disabled");
},
enable: function(){
( this.element.attr("disabled", false).is('[type="search"],[data-type="search"]') ? this.element.parent() : this.element ).removeClass("ui-disabled");
( this.element.attr("disabled", false).is( "[type='search'],[data-" + $.mobile.ns + "type='search']" ) ? this.element.parent() : this.element ).removeClass("ui-disabled");
}
});
})( jQuery );

View file

@ -8,7 +8,7 @@
$.mobile.listview.prototype.options.filter = false;
$( "[data-role='listview']" ).live( "listviewcreate", function() {
$( "[data-" + $.mobile.ns + "role='listview']" ).live( "listviewcreate", function() {
var list = $( this ),
listview = list.data( "listview" );
if ( !listview.options.filter ) {
@ -19,7 +19,7 @@ $( "[data-role='listview']" ).live( "listviewcreate", function() {
search = $( "<input>", {
placeholder: "Filter results...",
"data-type": "search"
"data-" + $.mobile.ns + "type": "search"
})
.bind( "keyup change", function() {
var val = this.value.toLowerCase(),

View file

@ -299,7 +299,7 @@ $.widget( "mobile.listview", $.mobile.widget, {
parentId = parentPage.data( "url" ),
o = this.options,
self = this,
persistentFooterID = parentPage.find( "[data-role='footer']" ).data( "id" );
persistentFooterID = parentPage.find( "[data-" + $.mobile.ns + "role='footer']" ).data( "id" );
$( parentList.find( "ul, ol" ).toArray().reverse() ).each(function( i ) {
var list = $( this ),

View file

@ -13,7 +13,7 @@ $.widget( "mobile.navbar", $.mobile.widget, {
_create: function(){
var $navbar = this.element,
$navbtns = $navbar.find("a"),
iconpos = $navbtns.filter('[data-icon]').length ? this.options.iconpos : undefined;
iconpos = $navbtns.filter( "[data-" + $.mobile.ns + "icon]").length ? this.options.iconpos : undefined;
$navbar
.addClass('ui-navbar')

View file

@ -364,7 +364,7 @@
//support deep-links to generated sub-pages
if( url.indexOf( "&" + $.mobile.subPageUrlKey ) > -1 ){
to = $( "[data-url='" + url + "']" );
to = $( "[data-" + $.mobile.ns + "url='" + url + "']" );
}
if( from ){
@ -473,7 +473,7 @@
if ( nextPageRole || to.data('role') === 'dialog' ) {
url = urlHistory.getActive().url + dialogHashKey;
if(nextPageRole){
to.attr( "data-role", nextPageRole );
to.attr( "data-" + $.mobile.ns + "role", nextPageRole );
nextPageRole = null;
}
}
@ -484,11 +484,11 @@
//if url is a string
if( url ){
to = $( "[data-url='" + url + "']" );
to = $( "[data-" + $.mobile.ns + "url='" + url + "']" );
fileUrl = path.getFilePath(url);
}
else{ //find base url of element, if avail
var toID = to.attr('data-url'),
var toID = to.attr('data-" + $.mobile.ns + "url'),
toIDfileurl = path.getFilePath(toID);
if(toID !== toIDfileurl){
@ -527,7 +527,7 @@
redirectLoc,
// TODO handle dialogs again
pageElemRegex = /.*(<[^>]*\bdata-role=["']?page["']?[^>]*>).*/,
dataUrlRegex = /\bdata-url=["']?([^"'>]*)["']?/;
dataUrlRegex = new RegExp("\bdata-" + $.mobile.ns + "url=[\"']?([^\"'>]*)[\"']?");
// data-url must be provided for the base tag so resource requests can be directed to the
// correct url. loading into a temprorary element makes these requests immediately

View file

@ -32,7 +32,7 @@ $.widget( "mobile.page", $.mobile.widget, {
var $elem = this.element,
o = this.options;
this.keepNative = "[data-role='none'], [data-role='nojs']" + (o.keepNative ? ", " + o.keepNative : "");
this.keepNative = "[data-" + $.mobile.ns + "role='none'], [data-" + $.mobile.ns + "role='nojs']" + (o.keepNative ? ", " + o.keepNative : "");
if ( this._trigger( "beforeCreate" ) === false ) {
return;
@ -41,21 +41,21 @@ $.widget( "mobile.page", $.mobile.widget, {
//some of the form elements currently rely on the presence of ui-page and ui-content
// classes so we'll handle page and content roles outside of the main role processing
// loop below.
$elem.find( "[data-role='page'], [data-role='content']" ).andSelf().each(function() {
$(this).addClass( "ui-" + $(this).data( "role" ) );
$elem.find( "[data-" + $.mobile.ns + "role='page'], [data-" + $.mobile.ns + "role='content']" ).andSelf().each(function() {
$(this).addClass( "ui-" + $.mobile.ns + $(this).data( "role" ) );
});
$elem.find( "[data-role='nojs']" ).addClass( "ui-nojs" );
$elem.find( "[data-" + $.mobile.ns + "role='nojs']" ).addClass( "ui-nojs" );
// pre-find data els
var $dataEls = $elem.find( "[data-role]" ).andSelf().each(function() {
var $dataEls = $elem.find( "[data-" + $.mobile.ns + "role]" ).andSelf().each(function() {
var $this = $( this ),
role = $this.data( "role" ),
theme = $this.data( "theme" );
//apply theming and markup modifications to page,header,content,footer
if ( role === "header" || role === "footer" ) {
$this.addClass( "ui-bar-" + (theme || $this.parent('[data-role=page]').data( "theme" ) || "a") );
$this.addClass( "ui-bar-" + (theme || $this.parent( "[data-" + $.mobile.ns + "role='page']" ).data( "theme" ) || "a") );
// add ARIA role
$this.attr( "role", role === "header" ? "banner" : "contentinfo" );
@ -79,7 +79,7 @@ $.widget( "mobile.page", $.mobile.widget, {
$elem.data( "url" ) !== $.mobile.path.stripHash( location.hash ) &&
!leftbtn && $this.data( "backbtn" ) !== false ) {
$( "<a href='#' class='ui-btn-left' data-rel='back' data-icon='arrow-l'>"+ o.backBtnText +"</a>" ).prependTo( $this );
$( "<a href='#' class='ui-btn-left' data-" + $.mobile.ns + "rel='back' data-" + $.mobile.ns + "icon='arrow-l'>"+ o.backBtnText +"</a>" ).prependTo( $this );
}
//page title
@ -121,13 +121,13 @@ $.widget( "mobile.page", $.mobile.widget, {
this._enhanceControls();
//links in bars, or those with data-role become buttons
$elem.find( "[data-role='button'], .ui-bar > a, .ui-header > a, .ui-footer > a" )
$elem.find( "[data-" + $.mobile.ns + "role='button'], .ui-bar > a, .ui-header > a, .ui-footer > a" )
.not( ".ui-btn" )
.not(this.keepNative)
.buttonMarkup();
$elem
.find("[data-role='controlgroup']")
.find("[data-" + $.mobile.ns + "role='controlgroup']")
.controlgroup();
//links within content areas
@ -150,7 +150,7 @@ $.widget( "mobile.page", $.mobile.widget, {
if ( o.degradeInputs[ type ] ) {
$( this ).replaceWith(
$( "<div>" ).html( $(this).clone() ).html()
.replace( /type="([a-zA-Z]+)"/, "type="+ optType +" data-type='$1'" ) );
.replace( /type="([a-zA-Z]+)"/, "type="+ optType +" data-" + $.mobile.ns + "type='$1'" ) );
}
});
@ -192,11 +192,11 @@ $.widget( "mobile.page", $.mobile.widget, {
nonNativeControls
.filter( "input, select" )
.filter( "[data-role='slider'], [data-type='range']" )
.filter( "[data-" + $.mobile.ns + "role='slider'], [data-" + $.mobile.ns + "type='range']" )
.slider();
nonNativeControls
.filter( "select:not([data-role='slider'])" )
.filter( "select:not([data-" + $.mobile.ns + "role='slider'])" )
.selectmenu();
}
});