2010-09-15 20:51:15 +00:00
|
|
|
/*
|
2010-11-10 00:55:52 +00:00
|
|
|
* jQuery Mobile Framework : "listview" plugin
|
2010-09-15 20:51:15 +00:00
|
|
|
* Copyright (c) jQuery Project
|
2010-11-20 03:47:47 +00:00
|
|
|
* Dual licensed under the MIT or GPL Version 2 licenses.
|
|
|
|
|
* http://jquery.org/license
|
2010-09-15 20:51:15 +00:00
|
|
|
*/
|
2011-06-29 13:02:01 +00:00
|
|
|
|
|
|
|
|
(function( $, undefined ) {
|
This commit decouples all widgets from the page plugin so that they can be used ad-hoc.
- Internally, each plugin self-initializes by binding to the pagecreate event.
- Unit tests have been added and adjusted to support some internal changes involved in this commit.
- In the process, the portions of the page plugin that were used to enhance the header,content,and footer sections of a native-app style page layout are now located in jquery.mobile.page.sections.js.
- No public API options have changed, except that the page plugin no longer has options for keepNative, and degradeInputs, as plugins now handle these internally (keepNative was never documented, and degradeInputs only affected slider, so it lives there now. Page options related to the page sections are now located in the page.sections script, but they are still configurable via the page plugin's options api.
- Make, Ant, and index files are updated with a new load order for all JS files.
2011-07-19 23:05:35 +00:00
|
|
|
|
2011-06-03 15:08:18 +00:00
|
|
|
//Keeps track of the number of lists per page UID
|
|
|
|
|
//This allows support for multiple nested list in the same page
|
|
|
|
|
//https://github.com/jquery/jquery-mobile/issues/1617
|
|
|
|
|
var listCountPerPage = {};
|
2010-09-16 18:55:46 +00:00
|
|
|
|
2010-11-11 15:49:15 +00:00
|
|
|
$.widget( "mobile.listview", $.mobile.widget, {
|
2010-10-06 19:14:59 +00:00
|
|
|
options: {
|
2010-10-11 22:59:03 +00:00
|
|
|
theme: "c",
|
|
|
|
|
countTheme: "c",
|
2010-10-06 19:14:59 +00:00
|
|
|
headerTheme: "b",
|
2010-10-11 01:28:22 +00:00
|
|
|
dividerTheme: "b",
|
2010-10-12 20:35:31 +00:00
|
|
|
splitIcon: "arrow-r",
|
2010-10-06 19:14:59 +00:00
|
|
|
splitTheme: "b",
|
2011-07-26 18:22:08 +00:00
|
|
|
inset: false,
|
2011-07-27 22:42:16 +00:00
|
|
|
initSelector: ":jqmData(role='listview')"
|
2010-10-06 19:14:59 +00:00
|
|
|
},
|
2011-06-29 13:02:01 +00:00
|
|
|
|
2010-10-06 19:14:59 +00:00
|
|
|
_create: function() {
|
2011-04-21 21:33:49 +00:00
|
|
|
var t = this;
|
2010-10-22 18:31:24 +00:00
|
|
|
|
2011-06-29 13:02:01 +00:00
|
|
|
// create listview markup
|
2011-04-21 21:33:49 +00:00
|
|
|
t.element.addClass(function( i, orig ) {
|
|
|
|
|
return orig + " ui-listview " + ( t.options.inset ? " ui-listview-inset ui-corner-all ui-shadow " : "" );
|
|
|
|
|
});
|
2010-10-21 18:07:28 +00:00
|
|
|
|
2011-08-17 19:09:07 +00:00
|
|
|
t.refresh( true );
|
2010-10-20 04:28:35 +00:00
|
|
|
},
|
2010-10-21 18:07:28 +00:00
|
|
|
|
|
|
|
|
_itemApply: function( $list, item ) {
|
2011-08-11 23:59:51 +00:00
|
|
|
var $countli = item.find( ".ui-li-count" );
|
|
|
|
|
if ( $countli.length ) {
|
|
|
|
|
item.addClass( "ui-li-has-count" );
|
|
|
|
|
}
|
|
|
|
|
$countli.addClass( "ui-btn-up-" + ( $list.jqmData( "counttheme" ) || this.options.countTheme ) + " ui-btn-corner-all" );
|
|
|
|
|
|
2010-10-21 18:07:28 +00:00
|
|
|
// TODO class has to be defined in markup
|
2011-08-11 23:59:51 +00:00
|
|
|
item.find( "h1, h2, h3, h4, h5, h6" ).addClass( "ui-li-heading" ).end()
|
2011-08-24 17:48:13 +00:00
|
|
|
.find( "p, dl" ).addClass( "ui-li-desc" ).end()
|
|
|
|
|
.find( ">img:eq(0), .ui-link-inherit>img:eq(0)" ).addClass( "ui-li-thumb" ).each(function() {
|
|
|
|
|
item.addClass( $(this).is( ".ui-li-icon" ) ? "ui-li-has-icon" : "ui-li-has-thumb" );
|
|
|
|
|
}).end()
|
|
|
|
|
.find( ".ui-li-aside" ).each(function() {
|
|
|
|
|
var $this = $(this);
|
|
|
|
|
$this.prependTo( $this.parent() ); //shift aside to front for css float
|
|
|
|
|
});
|
2010-10-21 18:07:28 +00:00
|
|
|
},
|
2011-06-29 13:02:01 +00:00
|
|
|
|
2011-05-18 21:59:00 +00:00
|
|
|
_removeCorners: function( li, which ) {
|
2011-07-10 22:07:12 +00:00
|
|
|
var top = "ui-corner-top ui-corner-tr ui-corner-tl",
|
|
|
|
|
bot = "ui-corner-bottom ui-corner-br ui-corner-bl";
|
2011-07-26 21:42:48 +00:00
|
|
|
|
2011-07-10 22:07:12 +00:00
|
|
|
li = li.add( li.find( ".ui-btn-inner, .ui-li-link-alt, .ui-li-thumb" ) );
|
2011-07-26 21:42:48 +00:00
|
|
|
|
2011-07-10 22:07:12 +00:00
|
|
|
if ( which === "top" ) {
|
|
|
|
|
li.removeClass( top );
|
2011-07-27 18:22:13 +00:00
|
|
|
} else if ( which === "bottom" ) {
|
2011-07-10 22:07:12 +00:00
|
|
|
li.removeClass( bot );
|
2011-07-27 18:22:13 +00:00
|
|
|
} else {
|
2011-07-10 22:07:12 +00:00
|
|
|
li.removeClass( top + " " + bot );
|
|
|
|
|
}
|
2010-11-20 02:07:34 +00:00
|
|
|
},
|
2011-06-29 13:02:01 +00:00
|
|
|
|
2011-08-17 19:09:07 +00:00
|
|
|
_refreshCorners: function( create ) {
|
2011-08-11 06:15:38 +00:00
|
|
|
var $li,
|
|
|
|
|
$visibleli,
|
|
|
|
|
$topli,
|
|
|
|
|
$bottomli;
|
|
|
|
|
|
|
|
|
|
if ( this.options.inset ) {
|
|
|
|
|
$li = this.element.children( "li" );
|
2011-08-17 19:09:07 +00:00
|
|
|
// at create time the li are not visible yet so we need to rely on .ui-screen-hidden
|
|
|
|
|
$visibleli = create?$li.not( ".ui-screen-hidden" ):$li.filter( ":visible" );
|
2011-09-12 20:58:24 +00:00
|
|
|
|
2011-08-11 23:22:11 +00:00
|
|
|
this._removeCorners( $li );
|
2011-08-11 06:15:38 +00:00
|
|
|
|
|
|
|
|
// Select the first visible li element
|
|
|
|
|
$topli = $visibleli.first()
|
|
|
|
|
.addClass( "ui-corner-top" );
|
|
|
|
|
|
|
|
|
|
$topli.add( $topli.find( ".ui-btn-inner" ) )
|
|
|
|
|
.find( ".ui-li-link-alt" )
|
|
|
|
|
.addClass( "ui-corner-tr" )
|
|
|
|
|
.end()
|
|
|
|
|
.find( ".ui-li-thumb" )
|
2011-10-04 22:02:52 +00:00
|
|
|
.not(".ui-li-icon")
|
2011-08-11 06:15:38 +00:00
|
|
|
.addClass( "ui-corner-tl" );
|
|
|
|
|
|
|
|
|
|
// Select the last visible li element
|
|
|
|
|
$bottomli = $visibleli.last()
|
|
|
|
|
.addClass( "ui-corner-bottom" );
|
|
|
|
|
|
|
|
|
|
$bottomli.add( $bottomli.find( ".ui-btn-inner" ) )
|
|
|
|
|
.find( ".ui-li-link-alt" )
|
|
|
|
|
.addClass( "ui-corner-br" )
|
|
|
|
|
.end()
|
|
|
|
|
.find( ".ui-li-thumb" )
|
2011-10-04 22:02:52 +00:00
|
|
|
.not(".ui-li-icon")
|
2011-08-11 06:15:38 +00:00
|
|
|
.addClass( "ui-corner-bl" );
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2010-10-21 18:07:28 +00:00
|
|
|
refresh: function( create ) {
|
2011-07-27 19:54:29 +00:00
|
|
|
this.parentPage = this.element.closest( ".ui-page" );
|
2010-10-20 13:55:05 +00:00
|
|
|
this._createSubPages();
|
2011-06-29 13:02:01 +00:00
|
|
|
|
2010-10-20 04:28:35 +00:00
|
|
|
var o = this.options,
|
2010-10-21 18:07:28 +00:00
|
|
|
$list = this.element,
|
2010-10-25 13:14:08 +00:00
|
|
|
self = this,
|
2011-03-25 21:50:40 +00:00
|
|
|
dividertheme = $list.jqmData( "dividertheme" ) || o.dividerTheme,
|
2011-04-12 20:51:27 +00:00
|
|
|
listsplittheme = $list.jqmData( "splittheme" ),
|
|
|
|
|
listspliticon = $list.jqmData( "spliticon" ),
|
2010-10-21 18:56:10 +00:00
|
|
|
li = $list.children( "li" ),
|
2011-06-29 13:02:01 +00:00
|
|
|
counter = $.support.cssPseudoElement || !$.nodeName( $list[ 0 ], "ol" ) ? 0 : 1,
|
2011-06-29 06:15:12 +00:00
|
|
|
item, itemClass, itemTheme,
|
2011-06-29 13:02:01 +00:00
|
|
|
a, last, splittheme, countParent, icon;
|
2010-10-21 18:56:10 +00:00
|
|
|
|
|
|
|
|
if ( counter ) {
|
|
|
|
|
$list.find( ".ui-li-dec" ).remove();
|
|
|
|
|
}
|
2010-10-20 04:28:35 +00:00
|
|
|
|
2011-06-29 13:02:01 +00:00
|
|
|
for ( var pos = 0, numli = li.length; pos < numli; pos++ ) {
|
2011-06-29 06:15:12 +00:00
|
|
|
item = li.eq( pos );
|
|
|
|
|
itemClass = "ui-li";
|
2010-10-20 13:55:05 +00:00
|
|
|
|
2010-10-21 18:07:28 +00:00
|
|
|
// If we're creating the element, we update it regardless
|
2011-05-19 06:46:46 +00:00
|
|
|
if ( create || !item.hasClass( "ui-li" ) ) {
|
2011-06-29 13:02:01 +00:00
|
|
|
itemTheme = item.jqmData("theme") || o.theme;
|
|
|
|
|
a = item.children( "a" );
|
|
|
|
|
|
|
|
|
|
if ( a.length ) {
|
|
|
|
|
icon = item.jqmData("icon");
|
|
|
|
|
|
|
|
|
|
item.buttonMarkup({
|
|
|
|
|
wrapperEls: "div",
|
|
|
|
|
shadow: false,
|
|
|
|
|
corners: false,
|
|
|
|
|
iconpos: "right",
|
|
|
|
|
icon: a.length > 1 || icon === false ? false : icon || "arrow-r",
|
|
|
|
|
theme: itemTheme
|
|
|
|
|
});
|
|
|
|
|
|
2011-08-24 20:54:03 +00:00
|
|
|
if ( ( icon != false ) && ( a.length == 1 ) ) {
|
|
|
|
|
item.addClass( "ui-li-has-arrow" );
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-29 13:02:01 +00:00
|
|
|
a.first().addClass( "ui-link-inherit" );
|
|
|
|
|
|
|
|
|
|
if ( a.length > 1 ) {
|
|
|
|
|
itemClass += " ui-li-has-alt";
|
|
|
|
|
|
|
|
|
|
last = a.last();
|
|
|
|
|
splittheme = listsplittheme || last.jqmData( "theme" ) || o.splitTheme;
|
|
|
|
|
|
|
|
|
|
last.appendTo(item)
|
2011-10-04 22:48:05 +00:00
|
|
|
.attr( "title", last.getEncodedText() )
|
2011-06-29 13:02:01 +00:00
|
|
|
.addClass( "ui-li-link-alt" )
|
|
|
|
|
.empty()
|
|
|
|
|
.buttonMarkup({
|
|
|
|
|
shadow: false,
|
|
|
|
|
corners: false,
|
|
|
|
|
theme: itemTheme,
|
|
|
|
|
icon: false,
|
|
|
|
|
iconpos: false
|
|
|
|
|
})
|
|
|
|
|
.find( ".ui-btn-inner" )
|
|
|
|
|
.append(
|
|
|
|
|
$( "<span />" ).buttonMarkup({
|
|
|
|
|
shadow: true,
|
|
|
|
|
corners: true,
|
|
|
|
|
theme: splittheme,
|
|
|
|
|
iconpos: "notext",
|
|
|
|
|
icon: listspliticon || last.jqmData( "icon" ) || o.splitIcon
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
} else if ( item.jqmData( "role" ) === "list-divider" ) {
|
|
|
|
|
|
|
|
|
|
itemClass += " ui-li-divider ui-btn ui-bar-" + dividertheme;
|
|
|
|
|
item.attr( "role", "heading" );
|
|
|
|
|
|
|
|
|
|
//reset counter when a divider heading is encountered
|
|
|
|
|
if ( counter ) {
|
|
|
|
|
counter = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
itemClass += " ui-li-static ui-body-" + itemTheme;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-21 22:36:17 +00:00
|
|
|
if ( counter && itemClass.indexOf( "ui-li-divider" ) < 0 ) {
|
2011-06-29 06:15:12 +00:00
|
|
|
countParent = item.is( ".ui-li-static:first" ) ? item : item.find( ".ui-link-inherit" );
|
2011-06-29 13:02:01 +00:00
|
|
|
|
|
|
|
|
countParent.addClass( "ui-li-jsnumbering" )
|
2010-10-21 22:36:17 +00:00
|
|
|
.prepend( "<span class='ui-li-dec'>" + (counter++) + ". </span>" );
|
2010-10-21 18:56:10 +00:00
|
|
|
}
|
|
|
|
|
|
2011-04-28 20:09:02 +00:00
|
|
|
item.add( item.children( ".ui-btn-inner" ) ).addClass( itemClass );
|
2010-10-21 22:36:17 +00:00
|
|
|
|
2011-08-17 19:09:07 +00:00
|
|
|
self._itemApply( $list, item );
|
2011-04-12 20:51:27 +00:00
|
|
|
}
|
2011-09-12 20:58:24 +00:00
|
|
|
|
2011-08-17 19:09:07 +00:00
|
|
|
this._refreshCorners( create );
|
2010-10-07 02:45:52 +00:00
|
|
|
},
|
2011-06-29 13:02:01 +00:00
|
|
|
|
2010-11-20 04:21:16 +00:00
|
|
|
//create a string for ID/subpage url creation
|
2011-06-29 13:02:01 +00:00
|
|
|
_idStringEscape: function( str ) {
|
2010-11-20 04:21:16 +00:00
|
|
|
return str.replace(/[^a-zA-Z0-9]/g, '-');
|
|
|
|
|
},
|
2011-06-03 15:08:18 +00:00
|
|
|
|
2010-10-07 02:45:52 +00:00
|
|
|
_createSubPages: function() {
|
2010-10-21 18:56:10 +00:00
|
|
|
var parentList = this.element,
|
|
|
|
|
parentPage = parentList.closest( ".ui-page" ),
|
2011-06-03 15:08:18 +00:00
|
|
|
parentUrl = parentPage.jqmData( "url" ),
|
2011-06-29 13:02:01 +00:00
|
|
|
parentId = parentUrl || parentPage[ 0 ][ $.expando ],
|
2011-06-03 15:08:18 +00:00
|
|
|
parentListId = parentList.attr( "id" ),
|
2010-10-12 17:36:50 +00:00
|
|
|
o = this.options,
|
2011-04-12 21:33:20 +00:00
|
|
|
dns = "data-" + $.mobile.ns,
|
2010-11-25 11:13:51 +00:00
|
|
|
self = this,
|
2011-07-26 21:19:37 +00:00
|
|
|
persistentFooterID = parentPage.find( ":jqmData(role='footer')" ).jqmData( "id" ),
|
|
|
|
|
hasSubPages;
|
2010-10-21 18:56:10 +00:00
|
|
|
|
2011-06-29 13:19:19 +00:00
|
|
|
if ( typeof listCountPerPage[ parentId ] === "undefined" ) {
|
2011-06-04 02:02:13 +00:00
|
|
|
listCountPerPage[ parentId ] = -1;
|
|
|
|
|
}
|
2011-06-29 13:02:01 +00:00
|
|
|
|
2011-06-03 15:08:18 +00:00
|
|
|
parentListId = parentListId || ++listCountPerPage[ parentId ];
|
|
|
|
|
|
2011-03-27 20:18:24 +00:00
|
|
|
$( parentList.find( "li>ul, li>ol" ).toArray().reverse() ).each(function( i ) {
|
2011-07-27 20:01:02 +00:00
|
|
|
var self = this,
|
|
|
|
|
list = $( this ),
|
2011-06-03 15:08:18 +00:00
|
|
|
listId = list.attr( "id" ) || parentListId + "-" + i,
|
2010-10-07 02:45:52 +00:00
|
|
|
parent = list.parent(),
|
2011-03-27 20:18:24 +00:00
|
|
|
nodeEls = $( list.prevAll().toArray().reverse() ),
|
|
|
|
|
nodeEls = nodeEls.length ? nodeEls : $( "<span>" + $.trim(parent.contents()[ 0 ].nodeValue) + "</span>" ),
|
2011-10-04 22:48:05 +00:00
|
|
|
title = nodeEls.first().getEncodedText(),//url limits to first 30 chars of text
|
2011-06-29 06:15:12 +00:00
|
|
|
id = ( parentUrl || "" ) + "&" + $.mobile.subPageUrlKey + "=" + listId,
|
2011-03-25 21:50:40 +00:00
|
|
|
theme = list.jqmData( "theme" ) || o.theme,
|
|
|
|
|
countTheme = list.jqmData( "counttheme" ) || parentList.jqmData( "counttheme" ) || o.countTheme,
|
2011-06-29 13:02:01 +00:00
|
|
|
newPage, anchor;
|
2011-07-26 21:42:48 +00:00
|
|
|
|
2011-07-26 21:19:37 +00:00
|
|
|
//define hasSubPages for use in later removal
|
|
|
|
|
hasSubPages = true;
|
2011-06-29 13:02:01 +00:00
|
|
|
|
|
|
|
|
newPage = list.detach()
|
|
|
|
|
.wrap( "<div " + dns + "role='page' " + dns + "url='" + id + "' " + dns + "theme='" + theme + "' " + dns + "count-theme='" + countTheme + "'><div " + dns + "role='content'></div></div>" )
|
|
|
|
|
.parent()
|
|
|
|
|
.before( "<div " + dns + "role='header' " + dns + "theme='" + o.headerTheme + "'><div class='ui-title'>" + title + "</div></div>" )
|
|
|
|
|
.after( persistentFooterID ? $( "<div " + dns + "role='footer' " + dns + "id='"+ persistentFooterID +"'>") : "" )
|
2010-10-09 03:32:41 +00:00
|
|
|
.parent()
|
2011-06-29 13:02:01 +00:00
|
|
|
.appendTo( $.mobile.pageContainer );
|
|
|
|
|
|
|
|
|
|
newPage.page();
|
|
|
|
|
|
|
|
|
|
anchor = parent.find('a:first');
|
2011-03-27 20:18:24 +00:00
|
|
|
|
2011-04-21 21:33:49 +00:00
|
|
|
if ( !anchor.length ) {
|
2011-06-29 13:02:01 +00:00
|
|
|
anchor = $( "<a/>" ).html( nodeEls || title ).prependTo( parent.empty() );
|
2010-12-15 14:52:25 +00:00
|
|
|
}
|
2011-06-29 13:02:01 +00:00
|
|
|
|
|
|
|
|
anchor.attr( "href", "#" + id );
|
|
|
|
|
|
2010-10-07 02:45:52 +00:00
|
|
|
}).listview();
|
2011-07-26 21:42:48 +00:00
|
|
|
|
2011-09-12 21:06:47 +00:00
|
|
|
// on pagehide, remove any nested pages along with the parent page, as long as they aren't active
|
|
|
|
|
// and aren't embedded
|
|
|
|
|
if( hasSubPages &&
|
2011-09-23 16:55:17 +00:00
|
|
|
parentPage.is( ":jqmData(external-page='true')" ) &&
|
2011-09-12 21:06:47 +00:00
|
|
|
parentPage.data("page").options.domCache === false ) {
|
|
|
|
|
|
2011-07-29 19:55:40 +00:00
|
|
|
var newRemove = function( e, ui ){
|
|
|
|
|
var nextPage = ui.nextPage, npURL;
|
|
|
|
|
|
|
|
|
|
if( ui.nextPage ){
|
|
|
|
|
npURL = nextPage.jqmData( "url" );
|
|
|
|
|
if( npURL.indexOf( parentUrl + "&" + $.mobile.subPageUrlKey ) !== 0 ){
|
|
|
|
|
self.childPages().remove();
|
|
|
|
|
parentPage.remove();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// unbind the original page remove and replace with our specialized version
|
2011-07-26 21:19:37 +00:00
|
|
|
parentPage
|
|
|
|
|
.unbind( "pagehide.remove" )
|
2011-07-29 19:55:40 +00:00
|
|
|
.bind( "pagehide.remove", newRemove);
|
2011-07-26 21:19:37 +00:00
|
|
|
}
|
2011-07-27 19:54:29 +00:00
|
|
|
},
|
|
|
|
|
|
2011-07-27 20:08:09 +00:00
|
|
|
// TODO sort out a better way to track sub pages of the listview this is brittle
|
2011-07-27 19:54:29 +00:00
|
|
|
childPages: function(){
|
|
|
|
|
var parentUrl = this.parentPage.jqmData( "url" );
|
|
|
|
|
|
|
|
|
|
return $( ":jqmData(url^='"+ parentUrl + "&" + $.mobile.subPageUrlKey +"')");
|
2010-10-06 19:14:59 +00:00
|
|
|
}
|
|
|
|
|
});
|
2010-09-16 18:55:46 +00:00
|
|
|
|
2011-07-27 22:42:16 +00:00
|
|
|
//auto self-init widgets
|
|
|
|
|
$( document ).bind( "pagecreate create", function( e ){
|
|
|
|
|
$( $.mobile.listview.prototype.options.initSelector, e.target ).listview();
|
|
|
|
|
});
|
|
|
|
|
|
2010-09-16 18:55:46 +00:00
|
|
|
})( jQuery );
|