1 /* ***************************************************************************
\r
2 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
\r
4 * Permission is hereby granted, free of charge, to any person obtaining a
\r
5 * copy of this software and associated documentation files (the "Software"),
\r
6 * to deal in the Software without restriction, including without limitation
\r
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
\r
8 * and/or sell copies of the Software, and to permit persons to whom the
\r
9 * Software is furnished to do so, subject to the following conditions:
\r
11 * The above copyright notice and this permission notice shall be included in
\r
12 * all copies or substantial portions of the Software.
\r
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
\r
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
\r
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
\r
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
\r
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
\r
20 * DEALINGS IN THE SOFTWARE.
\r
21 * ***************************************************************************
\r
23 * Author: Wongi Lee <wongi11.lee@samsung.com>
\r
27 * Virtual List Widget for unlimited data.
\r
28 * To support more then 1,000 items, special list widget developed.
\r
29 * Fast initialize and light DOM tree.
\r
30 * DB connection and works like DB cursor.
\r
34 * data-role: virtuallistview
\r
35 * data-template : jQuery.template ID that populate into virtual list
\r
36 * data-dbtable : DB Table name. It used as window[DB NAME]. Loaded data should be converted as window object.
\r
37 * data-dbkey : Unique key of DB Table. To sync each element on virtual list with DB table.
\r
38 * data-row : Optional. Set number of <li> elements that are used for data handling.
\r
40 * ID : <UL> element that has "data-role=virtuallist" must have ID attribute.
\r
41 * Class : <UL> element that has "data-role=virtuallist" should have "vlLoadSuccess" class to guaranty DB loading is completed.
\r
46 * : API to call _create method. API for AJAX or DB loading callback.
\r
48 * recreate ( Array )
\r
49 * : Update virtual list with new data array. For example, update with search result.
\r
53 * touchstart : Temporary preventDefault applied on touchstart event to avoid broken screen.
\r
57 * <script id="tmp-3-2-7" type="text/x-jquery-tmpl">
\r
58 * <li class="ui-li-3-2-7">
\r
59 * <span class="ui-li-text-main">${NAME}</span>
\r
60 * <img src="00_winset_icon_favorite_on.png" class="ui-li-icon-sub">
\r
61 * <span class="ui-li-text-sub">${ACTIVE}</span>
\r
62 * <span class="ui-li-text-sub2">${FROM}</span>
\r
66 * <ul id="virtuallist-normal_3_2_7_ul" data-role="virtuallistview" data-template="tmp-3-2-7" data-dbtable="JSON_DATA" data-row="100">
\r
72 (function ( $, undefined ) {
\r
74 /* Code for Virtual List Demo */
\r
75 var listCountPerPage = {}, /* 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 */
\r
80 NO_SCROLL = 0, /* ENUM */
\r
81 SCROLL_DOWN = 1, /* ENUM */
\r
82 SCROLL_UP = -1, /* ENUM */
\r
84 direction = NO_SCROLL,
\r
87 num_top_items = 0; //By scroll move, number of hidden elements.
\r
89 $.widget( "tizen.virtuallistview", $.mobile.widget, {
\r
95 splitIcon: "arrow-r",
\r
98 id: "", /* Virtual list UL elemet's ID */
\r
99 childSelector: " li", /* To support swipe list */
\r
102 dbkey: false, /* Data's unique Key */
\r
106 initSelector: ":jqmData(role='virtuallistview')"
\r
109 _stylerMouseUp: function () {
\r
110 $( this ).addClass( "ui-btn-up-s" );
\r
111 $( this ).removeClass( "ui-btn-down-s" );
\r
114 _stylerMouseDown: function () {
\r
115 $( this ).addClass( "ui-btn-down-s" );
\r
116 $( this ).removeClass( "ui-btn-up-s" );
\r
119 _stylerMouseOver: function () {
\r
120 $( this ).toggleClass( "ui-btn-hover-s" );
\r
123 _stylerMouseOut: function () {
\r
124 $( this ).toggleClass( "ui-btn-hover-s" );
\r
127 _pushData: function ( template, data ) {
\r
128 var o = this.options,
\r
131 myTemplate = $( "#" + template ),
\r
132 lastIndex = ( o.row > data.length ? data.length : o.row ),
\r
135 for ( i = 0; i < lastIndex; i++ ) {
\r
136 htmlData = myTemplate.tmpl( dataTable[i] );
\r
137 $( o.id ).append( $( htmlData ).attr( 'id', 'li_' + i ) );
\r
140 /* After push data, re-style virtuallist widget */
\r
141 $( o.id ).trigger( "create" );
\r
144 _reposition: function ( event ) {
\r
149 if ( event.data ) {
\r
155 if ( $( o.id + o.childSelector ).size() > 0 ) {
\r
156 TITLE_H = $( o.id + o.childSelector + ':first' ).position().top;
\r
157 LINE_H = $( o.id + o.childSelector + ':first' ).outerHeight();
\r
159 CONTAINER_W = $( o.id ).innerWidth();
\r
161 padding = parseInt( $( o.id + o.childSelector ).css( "padding-left" ), 10 ) + parseInt( $( o.id + o.childSelector ).css( "padding-right" ), 10 );
\r
164 $( o.id + ">" + o.childSelector ).addClass( "position_absolute" ).addClass( "ui-btn-up-s" )
\r
165 .bind( "mouseup", t._stylerMouseUp )
\r
166 .bind( "mousedown", t._stylerMouseDown )
\r
167 .bind( "mouseover", t._stylerMouseOver )
\r
168 .bind( "mouseout", t._stylerMouseOut );
\r
171 $( o.id + ">" + o.childSelector ).each( function ( index ) {
\r
172 $( this ).css( "top", TITLE_H + LINE_H * index + 'px' )
\r
173 .css( "width", CONTAINER_W - padding );
\r
176 /* Set Max List Height */
\r
177 $( o.id ).height( TOTAL_ITEMS * LINE_H );
\r
180 _resize: function ( event ) {
\r
185 if ( event.data ) {
\r
191 CONTAINER_W = $( o.id ).innerWidth();
\r
193 padding = parseInt( $( o.id + o.childSelector ).css( "padding-left" ), 10 ) + parseInt( $( o.id + o.childSelector ).css( "padding-right" ), 10 );
\r
195 $( o.id + o.childSelector ).each( function (index) {
\r
196 $( this ).css( "width", CONTAINER_W - padding );
\r
200 _scrollmove: function ( event ) {
\r
204 dataList = window[o.dbtable],
\r
205 _replace, /* Function */
\r
206 _moveTopBottom, /* Function */
\r
207 _moveBottomTop, /* Function */
\r
208 _matrixToArray, /* Function */
\r
214 /* Text & image src replace function */
\r
215 _replace = function ( oldItem, newItem, key ) {
\r
220 $( oldItem ).find( ".ui-li-text-main", ".ui-li-text-sub", "ui-btn-text" ).each( function ( index ) {
\r
221 oldObj = $( this );
\r
222 newText = $( newItem ).find( ".ui-li-text-main", ".ui-li-text-sub", "ui-btn-text" ).eq( index ).text();
\r
224 $( oldObj).contents().filter( function () {
\r
225 return ( this.nodeType == 3 );
\r
226 } ).get( 0 ).data = newText;
\r
229 $( oldItem ).find( "img" ).each( function ( imgIndex ) {
\r
230 oldObj = $( this );
\r
231 newImg = $( newItem ).find( "img" ).eq( imgIndex ).attr( "src" );
\r
233 $( oldObj ).attr( "src", newImg );
\r
237 $( oldItem ).data( key, $( newItem ).data( key ) );
\r
241 //Move older item to bottom
\r
242 _moveTopBottom = function ( v_firstIndex, v_lastIndex, num, key ) {
\r
247 if (v_firstIndex < 0) {
\r
251 for ( i = 0; i < num; i++ ) {
\r
252 if ( v_lastIndex + i > TOTAL_ITEMS ) {
\r
256 cur_item = $( '#li_' + ( v_firstIndex + i ) );
\r
259 /* Make New <LI> element from template. */
\r
260 myTemplate = $( "#" + o.template );
\r
261 htmlData = myTemplate.tmpl( dataList[ v_lastIndex + i ] );
\r
263 /* Copy all data to current item. */
\r
264 _replace( cur_item, htmlData, key );
\r
266 /* Set New Position */
\r
267 ( cur_item ).css( 'top', TITLE_H + LINE_H * ( v_lastIndex + 1 + i ) ).attr( 'id', 'li_' + ( v_lastIndex + 1 + i ) );
\r
274 // Move older item to bottom
\r
275 _moveBottomTop = function ( v_firstIndex, v_lastIndex, num, key ) {
\r
280 if ( v_firstIndex < 0 ) {
\r
284 for ( i = 0; i < num; i++ ) {
\r
285 cur_item = $( '#li_' + ( v_lastIndex - i ) );
\r
288 if ( v_firstIndex - 1 - i < 0 ) {
\r
292 /* Make New <LI> element from template. */
\r
293 myTemplate = $( "#" + o.template );
\r
294 htmlData = myTemplate.tmpl( dataList[ v_firstIndex - 1 - i ] );
\r
296 /* Copy all data to current item. */
\r
297 _replace( cur_item, htmlData, key );
\r
299 /* Set New Position */
\r
300 $( cur_item ).css( 'top', TITLE_H + LINE_H * ( v_firstIndex - 1 - i ) ).attr( 'id', 'li_' + ( v_firstIndex - 1 - i ) );
\r
307 /* Matrix to Array function written by Blender@stackoverflow.nnikishi@emich.edu*/
\r
308 _matrixToArray = function ( matrix ) {
\r
309 var contents = matrix.substr( 7 );
\r
311 contents = contents.substr( 0, contents.length - 1 );
\r
313 return contents.split( ', ' );
\r
316 // Get scroll direction and velocity
\r
317 /* with Scroll view */
\r
318 if ( o.scrollview ) {
\r
319 $el = $( o.id ).parentsUntil( ".ui-page" ).find( ".ui-scrollview-view" );
\r
320 transformValue = _matrixToArray( $el.css( "-webkit-transform" ) );
\r
321 curWindowTop = Math.abs( transformValue[ 5 ] ); /* Y vector */
\r
323 curWindowTop = $( window ).scrollTop() - LINE_H;
\r
326 cur_num_top_itmes = $( o.id + o.childSelector ).filter( function () {
\r
327 return (parseInt( $( this ).css( "top" ), 10 ) < curWindowTop );
\r
330 if ( num_top_items < cur_num_top_itmes ) {
\r
331 direction = SCROLL_DOWN;
\r
332 velocity = cur_num_top_itmes - num_top_items;
\r
333 num_top_items = cur_num_top_itmes;
\r
334 } else if ( num_top_items > cur_num_top_itmes ) {
\r
335 direction = SCROLL_UP;
\r
336 velocity = num_top_items - cur_num_top_itmes;
\r
337 num_top_items = cur_num_top_itmes;
\r
341 if ( direction == SCROLL_DOWN ) {
\r
342 if ( cur_num_top_itmes > o.page_buf ) {
\r
343 if ( last_index + velocity > TOTAL_ITEMS ) {
\r
344 velocity = TOTAL_ITEMS - last_index - 1;
\r
347 /* Prevent scroll touch event while DOM access */
\r
348 $(document).bind( "touchstart.virtuallist", function (event) {
\r
349 event.preventDefault();
\r
352 _moveTopBottom( first_index, last_index, velocity, o.dbkey );
\r
354 first_index += velocity;
\r
355 last_index += velocity;
\r
356 num_top_items -= velocity;
\r
358 /* Unset prevent touch event */
\r
359 $( document ).unbind( "touchstart.virtuallist" );
\r
361 } else if ( direction == SCROLL_UP ) {
\r
362 if ( cur_num_top_itmes <= o.page_buf ) {
\r
363 if ( first_index < velocity ) {
\r
364 velocity = first_index;
\r
367 /* Prevent scroll touch event while DOM access */
\r
368 $( document ).bind( "touchstart.virtuallist", function ( event ) {
\r
369 event.preventDefault();
\r
372 _moveBottomTop( first_index, last_index, velocity, o.dbkey );
\r
374 first_index -= velocity;
\r
375 last_index -= velocity;
\r
376 num_top_items += velocity;
\r
378 /* Unset prevent touch event */
\r
379 $( document ).unbind( "touchstart.virtuallist" );
\r
382 if ( first_index < o.page_buf ) {
\r
383 num_top_items = first_index;
\r
388 recreate: function ( newArray ) {
\r
394 TOTAL_ITEMS = newArray.length;
\r
395 direction = NO_SCROLL;
\r
397 last_index = o.row - 1;
\r
399 t._pushData( ( o.template ), newArray );
\r
401 if (o.childSelector == " ul" ) {
\r
402 $( o.id + " ul" ).swipelist();
\r
405 $( o.id ).virtuallistview();
\r
407 t._reposition( o );
\r
412 _initList: function () {
\r
416 /* After AJAX loading success */
\r
417 o.dbtable = t.element.data( "dbtable" );
\r
419 TOTAL_ITEMS = $(window[o.dbtable]).size();
\r
421 /* Make Gen list by template */
\r
422 t._pushData( (o.template), window[o.dbtable]);
\r
424 $( o.id ).parentsUntil( ".ui-page" ).parent().one( "pageshow", o, t._reposition);
\r
427 $( document ).bind( "scrollstop.virtuallist", t.options, t._scrollmove );
\r
429 $( window ).bind( "resize.virtuallist", t._resize );
\r
431 if ( o.childSelector == " ul" ) {
\r
432 $( o.id + " ul" ).swipelist();
\r
438 create: function () {
\r
439 var o = this.options;
\r
441 /* external API for AJAX callback */
\r
442 this._create( "create" );
\r
444 this._reposition( o );
\r
447 _create: function ( event ) {
\r
450 $el = this.element,
\r
451 shortcutsContainer = $('<div class="ui-virtuallist"/>'),
\r
452 shortcutsList = $('<ul></ul>'),
\r
453 dividers = $el.find(':jqmData(role="virtuallistview" )'),
\r
454 lastListItem = null,
\r
455 shortcutscroll = this;
\r
457 // create listview markup
\r
458 t.element.addClass( function ( i, orig ) {
\r
459 return orig + " ui-listview ui-virtual-list-container" + ( t.options.inset ? " ui-listview-inset ui-corner-all ui-shadow " : "" );
\r
462 o.id = "#" + $el.attr( "id" );
\r
464 $( o.id ).bind( "pagehide", function ( e ) {
\r
469 if ( $( ".ui-scrollview-clip" ).size() > 0 ) {
\r
470 o.scrollview = true;
\r
472 o.scrollview = false;
\r
475 /* Init list and page buf */
\r
476 if ( $el.data( "row" ) ) {
\r
477 o.row = $el.data( "row" );
\r
479 if ( o.row < MINIMUM_ROW ) {
\r
480 o.row = MINIMUM_ROW;
\r
483 o.page_buf = parseInt( ( o.row / 2 ), 10 );
\r
486 /* After DB Load complete, Init Vritual list */
\r
487 if ( $( o.id ).hasClass( "vlLoadSuccess" ) ) {
\r
490 if ( $el.data( "template" ) ) {
\r
491 o.template = $el.data( "template" );
\r
493 /* to support swipe list, <li> or <ul> can be main node of virtual list. */
\r
494 if ( $el.data( "swipelist" ) == true ) {
\r
495 o.childSelector = " ul";
\r
497 o.childSelector = " li";
\r
501 /* Set data's unique key */
\r
502 if ( $el.data( "dbkey" ) ) {
\r
503 o.datakey = $el.data( "dbkey" );
\r
506 first_index = 0; //first id of <li> element.
\r
507 last_index = o.row - 1; //last id of <li> element.
\r
513 destroy : function () {
\r
514 var o = this.options;
\r
516 $( document ).unbind( "scrollstop" );
\r
518 $( window ).unbind( "resize.virtuallist" );
\r
523 _itemApply: function ( $list, item ) {
\r
524 var $countli = item.find( ".ui-li-count" );
\r
526 if ( $countli.length ) {
\r
527 item.addClass( "ui-li-has-count" );
\r
530 $countli.addClass( "ui-btn-up-" + ( $list.jqmData( "counttheme" ) || this.options.countTheme ) + " ui-btn-corner-all" );
\r
532 // TODO class has to be defined in markup
\r
533 item.find( "h1, h2, h3, h4, h5, h6" ).addClass( "ui-li-heading" ).end()
\r
534 .find( "p, dl" ).addClass( "ui-li-desc" ).end()
\r
535 .find( ">img:eq(0), .ui-link-inherit>img:eq(0)" ).addClass( "ui-li-thumb" ).each( function () {
\r
536 item.addClass( $( this ).is( ".ui-li-icon" ) ? "ui-li-has-icon" : "ui-li-has-thumb" );
\r
538 .find( ".ui-li-aside" ).each(function () {
\r
539 var $this = $( this );
\r
540 $this.prependTo( $this.parent() ); //shift aside to front for css float
\r
544 _removeCorners: function ( li, which ) {
\r
545 var top = "ui-corner-top ui-corner-tr ui-corner-tl",
\r
546 bot = "ui-corner-bottom ui-corner-br ui-corner-bl";
\r
548 li = li.add( li.find( ".ui-btn-inner, .ui-li-link-alt, .ui-li-thumb" ) );
\r
550 if ( which === "top" ) {
\r
551 li.removeClass( top );
\r
552 } else if ( which === "bottom" ) {
\r
553 li.removeClass( bot );
\r
555 li.removeClass( top + " " + bot );
\r
559 _refreshCorners: function ( create ) {
\r
565 if ( this.options.inset ) {
\r
566 $li = this.element.children( "li" );
\r
567 // at create time the li are not visible yet so we need to rely on .ui-screen-hidden
\r
568 $visibleli = create ? $li.not( ".ui-screen-hidden" ) : $li.filter( ":visible" );
\r
570 this._removeCorners( $li );
\r
572 // Select the first visible li element
\r
573 $topli = $visibleli.first()
\r
574 .addClass( "ui-corner-top" );
\r
576 $topli.add( $topli.find( ".ui-btn-inner" ) )
\r
577 .find( ".ui-li-link-alt" )
\r
578 .addClass( "ui-corner-tr" )
\r
580 .find( ".ui-li-thumb" )
\r
581 .not( ".ui-li-icon" )
\r
582 .addClass( "ui-corner-tl" );
\r
584 // Select the last visible li element
\r
585 $bottomli = $visibleli.last()
\r
586 .addClass( "ui-corner-bottom" );
\r
588 $bottomli.add( $bottomli.find( ".ui-btn-inner" ) )
\r
589 .find( ".ui-li-link-alt" )
\r
590 .addClass( "ui-corner-br" )
\r
592 .find( ".ui-li-thumb" )
\r
593 .not( ".ui-li-icon" )
\r
594 .addClass( "ui-corner-bl" );
\r
598 refresh: function ( create ) {
\r
599 this.parentPage = this.element.closest( ".ui-page" );
\r
600 this._createSubPages();
\r
602 var o = this.options,
\r
603 $list = this.element,
\r
605 dividertheme = $list.jqmData( "dividertheme" ) || o.dividerTheme,
\r
606 listsplittheme = $list.jqmData( "splittheme" ),
\r
607 listspliticon = $list.jqmData( "spliticon" ),
\r
608 li = $list.children( "li" ),
\r
609 counter = $.support.cssPseudoElement || !$.nodeName( $list[ 0 ], "ol" ) ? 0 : 1,
\r
623 $list.find( ".ui-li-dec" ).remove();
\r
626 for ( pos = 0, numli = li.length; pos < numli; pos++ ) {
\r
627 item = li.eq( pos );
\r
628 itemClass = "ui-li";
\r
630 // If we're creating the element, we update it regardless
\r
631 if ( create || !item.hasClass( "ui-li" ) ) {
\r
632 itemTheme = item.jqmData( "theme" ) || o.theme;
\r
633 a = item.children( "a" );
\r
636 icon = item.jqmData( "icon" );
\r
638 item.buttonMarkup({
\r
643 /* icon: a.length > 1 || icon === false ? false : icon || "arrow-r",*/
\r
644 icon: false, /* Remove unnecessary arrow icon */
\r
648 if ( ( icon != false ) && ( a.length == 1 ) ) {
\r
649 item.addClass( "ui-li-has-arrow" );
\r
652 a.first().addClass( "ui-link-inherit" );
\r
654 if ( a.length > 1 ) {
\r
655 itemClass += " ui-li-has-alt";
\r
658 splittheme = listsplittheme || last.jqmData( "theme" ) || o.splitTheme;
\r
660 last.appendTo(item)
\r
661 .attr( "title", last.getEncodedText() )
\r
662 .addClass( "ui-li-link-alt" )
\r
671 .find( ".ui-btn-inner" )
\r
673 $( "<span />" ).buttonMarkup({
\r
678 icon: listspliticon || last.jqmData( "icon" ) || o.splitIcon
\r
682 } else if ( item.jqmData( "role" ) === "list-divider" ) {
\r
684 itemClass += " ui-li-divider ui-btn ui-bar-" + dividertheme;
\r
685 item.attr( "role", "heading" );
\r
687 //reset counter when a divider heading is encountered
\r
693 itemClass += " ui-li-static ui-body-" + itemTheme;
\r
697 if ( counter && itemClass.indexOf( "ui-li-divider" ) < 0 ) {
\r
698 countParent = item.is( ".ui-li-static:first" ) ? item : item.find( ".ui-link-inherit" );
\r
700 countParent.addClass( "ui-li-jsnumbering" )
\r
701 .prepend( "<span class='ui-li-dec'>" + (counter++) + ". </span>" );
\r
704 item.add( item.children( ".ui-btn-inner" ) ).addClass( itemClass );
\r
706 self._itemApply( $list, item );
\r
709 this._refreshCorners( create );
\r
712 //create a string for ID/subpage url creation
\r
713 _idStringEscape: function ( str ) {
\r
714 return str.replace(/\W/g , "-");
\r
717 _createSubPages: function () {
\r
718 var parentList = this.element,
\r
719 parentPage = parentList.closest( ".ui-page" ),
\r
720 parentUrl = parentPage.jqmData( "url" ),
\r
721 parentId = parentUrl || parentPage[ 0 ][ $.expando ],
\r
722 parentListId = parentList.attr( "id" ),
\r
724 dns = "data-" + $.mobile.ns,
\r
726 persistentFooterID = parentPage.find( ":jqmData(role='footer')" ).jqmData( "id" ),
\r
730 if ( typeof listCountPerPage[ parentId ] === "undefined" ) {
\r
731 listCountPerPage[ parentId ] = -1;
\r
734 parentListId = parentListId || ++listCountPerPage[ parentId ];
\r
736 $( parentList.find( "li>ul, li>ol" ).toArray().reverse() ).each(function ( i ) {
\r
739 listId = list.attr( "id" ) || parentListId + "-" + i,
\r
740 parent = list.parent(),
\r
742 title = nodeEls.first().getEncodedText(),//url limits to first 30 chars of text
\r
743 id = ( parentUrl || "" ) + "&" + $.mobile.subPageUrlKey + "=" + listId,
\r
744 theme = list.jqmData( "theme" ) || o.theme,
\r
745 countTheme = list.jqmData( "counttheme" ) || parentList.jqmData( "counttheme" ) || o.countTheme,
\r
749 nodeEls = $( list.prevAll().toArray().reverse() );
\r
750 nodeEls = nodeEls.length ? nodeEls : $( "<span>" + $.trim( parent.contents()[ 0 ].nodeValue ) + "</span>" );
\r
752 //define hasSubPages for use in later removal
\r
753 hasSubPages = true;
\r
755 newPage = list.detach()
\r
756 .wrap( "<div " + dns + "role='page' " + dns + "url='" + id + "' " + dns + "theme='" + theme + "' " + dns + "count-theme='" + countTheme + "'><div " + dns + "role='content'></div></div>" )
\r
758 .before( "<div " + dns + "role='header' " + dns + "theme='" + o.headerTheme + "'><div class='ui-title'>" + title + "</div></div>" )
\r
759 .after( persistentFooterID ? $( "<div " + dns + "role='footer' " + dns + "id='" + persistentFooterID + "'>" ) : "" )
\r
761 .appendTo( $.mobile.pageContainer );
\r
765 anchor = parent.find('a:first');
\r
767 if ( !anchor.length ) {
\r
768 anchor = $( "<a/>" ).html( nodeEls || title ).prependTo( parent.empty() );
\r
771 anchor.attr( "href", "#" + id );
\r
773 }).virtuallistview();
\r
775 // on pagehide, remove any nested pages along with the parent page, as long as they aren't active
\r
776 // and aren't embedded
\r
777 if ( hasSubPages &&
\r
778 parentPage.is( ":jqmData(external-page='true')" ) &&
\r
779 parentPage.data( "page" ).options.domCache === false ) {
\r
781 newRemove = function ( e, ui ) {
\r
782 var nextPage = ui.nextPage, npURL;
\r
784 if ( ui.nextPage ) {
\r
785 npURL = nextPage.jqmData( "url" );
\r
786 if ( npURL.indexOf( parentUrl + "&" + $.mobile.subPageUrlKey ) !== 0 ) {
\r
787 self.childPages().remove();
\r
788 parentPage.remove();
\r
793 // unbind the original page remove and replace with our specialized version
\r
795 .unbind( "pagehide.remove" )
\r
796 .bind( "pagehide.remove", newRemove );
\r
800 // TODO sort out a better way to track sub pages of the virtuallistview this is brittle
\r
801 childPages: function () {
\r
802 var parentUrl = this.parentPage.jqmData( "url" );
\r
804 return $( ":jqmData(url^='" + parentUrl + "&" + $.mobile.subPageUrlKey + "')" );
\r
808 //auto self-init widgets
\r
809 $( document ).bind( "pagecreate create", function ( e ) {
\r
810 $( $.tizen.virtuallistview.prototype.options.initSelector, e.target ).virtuallistview();
\r