2 * Author: Wongi Lee <wongi11.lee@samsung.com>
\r
6 * Virtual List Widget for unlimited data.
\r
7 * To support more then 1,000 items, special list widget developed.
\r
8 * Fast initialize and light DOM tree.
\r
9 * DB connection and works like DB cursor.
\r
13 * data-role: virtuallistview
\r
14 * data-template : jQuery.template ID that populate into virtual list
\r
15 * data-dbtable : DB Table name. It used as window[DB NAME]. Loaded data should be converted as window object.
\r
16 * data-dbkey : Unique key of DB Table. To sync each element on virtual list with DB table.
\r
18 * ID : <UL> element that has "data-role=virtuallist" must have ID attribute.
\r
19 * Class : <UL> element that has "data-role=virtuallist" should have "vlLoadSuccess" class to guaranty DB loading is completed.
\r
25 * : API to call _create method. API for AJAX or DB loading callback.
\r
27 * recreate ( Array )
\r
28 * : Update virtual list with new data array. For example, update with search result.
\r
32 * touchstart : Temporary preventDefault applied on touchstart event to avoid broken screen.
\r
36 * <script id="tmp-3-2-7" type="text/x-jquery-tmpl">
\r
37 * <li class="ui-li-3-2-7">
\r
38 * <span class="ui-li-text-main">${NAME}</span>
\r
39 * <img src="00_winset_icon_favorite_on.png" class="ui-li-icon-sub">
\r
40 * <span class="ui-li-text-sub">${ACTIVE}</span>
\r
41 * <span class="ui-li-text-sub2">${FROM}</span>
\r
45 * <ul id="virtuallist-normal_3_2_7_ul" data-role="virtuallistview" data-template="tmp-3-2-7" data-dbtable="JSON_DATA">
\r
51 (function( $, undefined ) {
\r
53 //Keeps track of the number of lists per page UID
\r
54 //This allows support for multiple nested list in the same page
\r
55 //https://github.com/jquery/jquery-mobile/issues/1617
\r
56 var listCountPerPage = {};
\r
58 /* Code for Virtual List Demo */
\r
59 var INIT_LIST_NUM = 100;
\r
60 var PAGE_BUF = (INIT_LIST_NUM/2);
\r
61 var TOTAL_ITEMS = 0;
\r
64 var CONTAINER_W = 0;
\r
68 var SCROLL_DOWN = 1;
\r
72 var direction = NO_SCROLL;
\r
73 var first_index = 0; //first id of <li> element.
\r
74 var last_index = INIT_LIST_NUM -1; //last id of <li> element.
\r
76 var num_top_items = 0; //By scroll move, number of hidden elements.
\r
78 $.widget( "tizen.virtuallistview", $.mobile.widget, {
\r
84 splitIcon: "arrow-r",
\r
87 id: "", /* Virtual list UL elemet's ID */
\r
88 childSelector: " li", /* To support swipe list */
\r
91 dbkey: false, /* Data's unique Key */
\r
93 initSelector: ":jqmData(role='virtuallistview')"
\r
96 _stylerMouseUp: function()
\r
98 $( this ).addClass( "ui-btn-up-s" );
\r
99 $( this ).removeClass( "ui-btn-down-s" );
\r
102 _stylerMouseDown: function()
\r
104 $( this ).addClass( "ui-btn-down-s" );
\r
105 $( this ).removeClass( "ui-btn-up-s" );
\r
108 _stylerMouseOver: function()
\r
110 $( this ).toggleClass( "ui-btn-hover-s" );
\r
113 _stylerMouseOut: function()
\r
115 $( this ).toggleClass( "ui-btn-hover-s" );
\r
118 _pushData: function ( template, data ) {
\r
119 var o = this.options;
\r
121 var dataTable = data;
\r
123 var myTemplate = $( "#" + template );
\r
125 var lastIndex = ( INIT_LIST_NUM > data.length ? data.length : INIT_LIST_NUM );
\r
127 for ( i = 0; i < lastIndex; i++ )
\r
129 var htmlData = myTemplate.tmpl( dataTable[i] );
\r
130 $( o.id ).append( $(htmlData).attr( 'id', 'li_'+i ) );
\r
133 /* After push data, re-style virtuallist widget */
\r
134 $( o.id ).trigger( "create" );
\r
137 _reposition: function( event ) {
\r
140 if ( event.data ) {
\r
149 if ($(o.id + o.childSelector).size() > 0){
\r
150 TITLE_H = $( o.id + o.childSelector + ':first' ).position().top;
\r
151 LINE_H = $( o.id + o.childSelector + ':first' ).outerHeight();
\r
153 CONTAINER_W = $( o.id ).innerWidth();
\r
155 var padding = parseInt( $( o.id + o.childSelector ).css( "padding-left" )) + parseInt( $(o.id + o.childSelector).css( "padding-right" ) );
\r
158 $( o.id + ">" + o.childSelector ).addClass( "position_absolute" ).addClass( "ui-btn-up-s" )
\r
159 .bind( "mouseup", t._stylerMouseUp )
\r
160 .bind( "mousedown", t._stylerMouseDown )
\r
161 .bind( "mouseover", t._stylerMouseOver )
\r
162 .bind( "mouseout", t._stylerMouseOut );
\r
165 $( o.id + ">" + o.childSelector ).each( function( index ) {
\r
166 $( this ).css( "top", TITLE_H + LINE_H*index + 'px' )
\r
167 .css( "width", CONTAINER_W - padding );
\r
170 /* Set Max List Height */
\r
171 $( o.id ).height( TOTAL_ITEMS * LINE_H );
\r
174 _resize: function( event ) {
\r
177 if ( event.data ) {
\r
186 CONTAINER_W = $( o.id ).innerWidth();
\r
188 var padding = parseInt( $( o.id + o.childSelector ).css( "padding-left" )) + parseInt( $( o.id + o.childSelector ).css( "padding-right" ) );
\r
190 $( o.id + o.childSelector ).each( function(index){
\r
191 $( this ).css( "width", CONTAINER_W - padding );
\r
195 _scrollmove: function( event ) {
\r
197 var o = event.data;
\r
198 var dataList = window[o.dbtable];
\r
200 /* Text & image src replace function */
\r
201 var _replace= function( oldItem, newItem, key ) {
\r
202 $( oldItem ).find( ".ui-li-text-main",".ui-li-text-sub","ui-btn-text" ).each( function( index ) {
\r
203 var oldObj = $( this );
\r
204 var newText = $( newItem ).find( ".ui-li-text-main",".ui-li-text-sub","ui-btn-text" ).eq( index ).text();
\r
206 $( oldObj).contents().filter( function(){
\r
207 return( this.nodeType == 3 );
\r
208 } ).get( 0 ).data = newText;
\r
211 $( oldItem ).find( "img" ).each( function( imgIndex ) {
\r
212 var oldObj = $( this );
\r
214 var newImg = $( newItem ).find( "img" ).eq( imgIndex ).attr( "src" );
\r
216 $( oldObj ).attr( "src", newImg );
\r
220 $( oldItem ).data(key, $( newItem ).data(key));
\r
224 //Move older item to bottom
\r
225 var _moveTopBottom= function( v_firstIndex, v_lastIndex, num, key ) {
\r
226 if (v_firstIndex < 0) {
\r
230 for (i=0; i<num; i++)
\r
232 if (v_lastIndex + i > TOTAL_ITEMS)
\r
235 var cur_item = $('#li_' + (v_firstIndex + i));
\r
238 /* Make New <LI> element from template. */
\r
239 var myTemplate = $( "#" + o.template );
\r
240 var htmlData = myTemplate.tmpl( dataList[ v_lastIndex + i ] );
\r
242 /* Copy all data to current item. */
\r
243 _replace( cur_item, htmlData, key );
\r
245 /* Set New Position */
\r
246 ( cur_item ).css( 'top', TITLE_H + LINE_H*( v_lastIndex + 1 + i ) ).attr( 'id', 'li_' +( v_lastIndex + 1+ i ) );
\r
254 // Move older item to bottom
\r
255 var _moveBottomTop= function( v_firstIndex, v_lastIndex, num, key ) {
\r
256 if ( v_firstIndex < 0 ) {
\r
260 for ( i=0; i<num; i++ )
\r
262 var cur_item = $( '#li_' + ( v_lastIndex - i ) );
\r
265 if ( v_firstIndex-1-i < 0 ) {
\r
269 /* Make New <LI> element from template. */
\r
270 var myTemplate = $( "#" + o.template );
\r
271 var htmlData = myTemplate.tmpl( dataList[ v_firstIndex - 1 - i ] );
\r
273 /* Copy all data to current item. */
\r
274 _replace( cur_item, htmlData, key );
\r
276 /* Set New Position */
\r
277 $( cur_item ).css( 'top', TITLE_H + LINE_H * ( v_firstIndex - 1 - i )).attr( 'id', 'li_' +( v_firstIndex - 1 - i ));
\r
285 /* Matrix to Array function written by Blender@stackoverflow.nnikishi@emich.edu*/
\r
286 var matrixToArray = function( matrix ) {
\r
287 var contents = matrix.substr( 7 );
\r
288 contents = contents.substr( 0, contents.length - 1 );
\r
290 return contents.split( ', ' );
\r
293 // Get scroll direction and velocity
\r
294 /* with Scroll view */
\r
295 if ( o.scrollview ) {
\r
296 var $el = $( o.id ).parentsUntil( ".ui-page" ).find( ".ui-scrollview-view" );
\r
297 var transformValue = matrixToArray( $el.css( "-webkit-transform" ) );
\r
299 var curWindowTop = Math.abs( transformValue[ 5 ] ); /* Y vector */
\r
302 var curWindowTop = $( window ).scrollTop() - LINE_H;
\r
305 var cur_num_top_itmes = $( o.id + o.childSelector ).filter( function(){
\r
306 return (parseInt($( this ).css( "top" )) < curWindowTop);
\r
309 if ( num_top_items < cur_num_top_itmes ) {
\r
310 direction = SCROLL_DOWN;
\r
311 velocity = cur_num_top_itmes - num_top_items;
\r
312 num_top_items = cur_num_top_itmes;
\r
314 else if ( num_top_items > cur_num_top_itmes ) {
\r
315 direction = SCROLL_UP;
\r
316 velocity = num_top_items - cur_num_top_itmes;
\r
317 num_top_items = cur_num_top_itmes;
\r
321 if( direction == SCROLL_DOWN )
\r
323 if ( cur_num_top_itmes > PAGE_BUF ) {
\r
324 if ( last_index + velocity > TOTAL_ITEMS ) {
\r
325 velocity = TOTAL_ITEMS - last_index -1;
\r
328 /* Prevent scroll touch event while DOM access */
\r
329 $(document).bind( "touchstart.virtuallist", function(event) {
\r
330 event.preventDefault();
\r
333 _moveTopBottom( first_index, last_index, velocity, o.dbkey );
\r
335 first_index += velocity;
\r
336 last_index += velocity;
\r
337 num_top_items -= velocity;
\r
339 /* Unset prevent touch event */
\r
340 $( document ).unbind( "touchstart.virtuallist" );
\r
343 else if( direction == SCROLL_UP ) {
\r
344 if ( cur_num_top_itmes <= PAGE_BUF ) {
\r
345 if ( first_index < velocity ) {
\r
346 velocity = first_index;
\r
349 /* Prevent scroll touch event while DOM access */
\r
350 $( document ).bind( "touchstart.virtuallist", function( event ) {
\r
351 event.preventDefault();
\r
354 _moveBottomTop( first_index, last_index, velocity, o.dbkey );
\r
356 first_index -= velocity;
\r
357 last_index -= velocity;
\r
358 num_top_items += velocity;
\r
360 /* Unset prevent touch event */
\r
361 $( document ).unbind( "touchstart.virtuallist" );
\r
364 if ( first_index < PAGE_BUF ) {
\r
365 num_top_items = first_index;
\r
370 recreate: function( newArray ){
\r
372 var o = this.options;
\r
376 TOTAL_ITEMS = newArray.length;
\r
377 direction = NO_SCROLL;
\r
379 last_index = INIT_LIST_NUM -1;
\r
381 t._pushData( ( o.template ), newArray );
\r
383 if (o.childSelector == " ul" ) {
\r
384 $( o.id + " ul" ).swipelist();
\r
387 $( o.id ).virtuallistview();
\r
389 t._reposition( o );
\r
394 _initList: function() {
\r
396 var o = this.options;
\r
398 /* After AJAX loading success */
\r
399 o.dbtable = t.element.data( "dbtable" );
\r
401 TOTAL_ITEMS = $(window[o.dbtable]).size();
\r
403 /* Make Gen list by template */
\r
404 t._pushData((o.template), window[o.dbtable]);
\r
406 $( o.id ).parentsUntil( ".ui-page" ).parent().one( "pageshow", o, t._reposition);
\r
409 $( document ).bind( "scrollstop.virtuallist", t.options, t._scrollmove );
\r
411 $( window ).bind( "resize.virtuallist", t._resize );
\r
413 if ( o.childSelector == " ul" ) {
\r
414 $( o.id + " ul" ).swipelist();
\r
420 create: function() {
\r
421 var o = this.options;
\r
423 /* external API for AJAX callback */
\r
424 this._create( "create" );
\r
426 this._reposition( o );
\r
429 _create: function( event ) {
\r
431 var o = this.options;
\r
433 // create listview markup
\r
434 t.element.addClass( function( i, orig ) {
\r
435 return orig + " ui-listview ui-virtual-list-container" + ( t.options.inset ? " ui-listview-inset ui-corner-all ui-shadow " : "" );
\r
438 var $el = this.element,
\r
439 shortcutsContainer = $('<div class="ui-virtuallist"/>'),
\r
440 shortcutsList = $('<ul></ul>'),
\r
441 dividers = $el.find(':jqmData(role="virtuallistview" )'),
\r
442 lastListItem = null,
\r
443 shortcutscroll = this;
\r
445 o.id = "#" + $el.attr( "id" );
\r
447 $( o.id ).bind( "pagehide", function( e ){
\r
452 ( $( ".ui-scrollview-clip" ).size()>0 ) ? o.scrollview = true : o.scrollview = false;
\r
454 /* After DB Load complete, Init Vritual list */
\r
455 if ($( o.id ).hasClass( "vlLoadSuccess" )) {
\r
456 $( o.id ).empty();
\r
458 if ($el.data( "template" )) {
\r
459 o.template = $el.data( "template" );
\r
461 /* to support swipe list, <li> or <ul> can be main node of virtual list. */
\r
462 if ( $el.data( "swipelist" ) == true ) {
\r
463 o.childSelector = " ul";
\r
466 o.shildSelector = " li";
\r
470 /* Set data's unique key */
\r
471 if ( $el.data( "dbkey" ) ) {
\r
472 o.datakey = $el.data( "dbkey" );
\r
479 destroy : function(){
\r
480 var o = this.options;
\r
482 $( document ).unbind( "scrollstop" );
\r
484 $( window ).unbind( "resize.virtuallist" );
\r
489 _itemApply: function( $list, item ) {
\r
490 var $countli = item.find( ".ui-li-count" );
\r
492 if ( $countli.length ) {
\r
493 item.addClass( "ui-li-has-count" );
\r
496 $countli.addClass( "ui-btn-up-" + ( $list.jqmData( "counttheme" ) || this.options.countTheme ) + " ui-btn-corner-all" );
\r
498 // TODO class has to be defined in markup
\r
499 item.find( "h1, h2, h3, h4, h5, h6" ).addClass( "ui-li-heading" ).end()
\r
500 .find( "p, dl" ).addClass( "ui-li-desc" ).end()
\r
501 .find( ">img:eq(0), .ui-link-inherit>img:eq(0)" ).addClass( "ui-li-thumb" ).each( function() {
\r
502 item.addClass( $( this ).is( ".ui-li-icon" ) ? "ui-li-has-icon" : "ui-li-has-thumb" );
\r
504 .find( ".ui-li-aside" ).each(function() {
\r
505 var $this = $( this );
\r
506 $this.prependTo( $this.parent() ); //shift aside to front for css float
\r
510 _removeCorners: function( li, which ) {
\r
511 var top = "ui-corner-top ui-corner-tr ui-corner-tl",
\r
512 bot = "ui-corner-bottom ui-corner-br ui-corner-bl";
\r
514 li = li.add( li.find( ".ui-btn-inner, .ui-li-link-alt, .ui-li-thumb" ) );
\r
516 if ( which === "top" ) {
\r
517 li.removeClass( top );
\r
518 } else if ( which === "bottom" ) {
\r
519 li.removeClass( bot );
\r
521 li.removeClass( top + " " + bot );
\r
525 _refreshCorners: function( create ) {
\r
531 if ( this.options.inset ) {
\r
532 $li = this.element.children( "li" );
\r
533 // at create time the li are not visible yet so we need to rely on .ui-screen-hidden
\r
534 $visibleli = create?$li.not( ".ui-screen-hidden" ):$li.filter( ":visible" );
\r
536 this._removeCorners( $li );
\r
538 // Select the first visible li element
\r
539 $topli = $visibleli.first()
\r
540 .addClass( "ui-corner-top" );
\r
542 $topli.add( $topli.find( ".ui-btn-inner" ) )
\r
543 .find( ".ui-li-link-alt" )
\r
544 .addClass( "ui-corner-tr" )
\r
546 .find( ".ui-li-thumb" )
\r
547 .not( ".ui-li-icon" )
\r
548 .addClass( "ui-corner-tl" );
\r
550 // Select the last visible li element
\r
551 $bottomli = $visibleli.last()
\r
552 .addClass( "ui-corner-bottom" );
\r
554 $bottomli.add( $bottomli.find( ".ui-btn-inner" ) )
\r
555 .find( ".ui-li-link-alt" )
\r
556 .addClass( "ui-corner-br" )
\r
558 .find( ".ui-li-thumb" )
\r
559 .not( ".ui-li-icon" )
\r
560 .addClass( "ui-corner-bl" );
\r
564 refresh: function( create ) {
\r
565 this.parentPage = this.element.closest( ".ui-page" );
\r
566 this._createSubPages();
\r
568 var o = this.options,
\r
569 $list = this.element,
\r
571 dividertheme = $list.jqmData( "dividertheme" ) || o.dividerTheme,
\r
572 listsplittheme = $list.jqmData( "splittheme" ),
\r
573 listspliticon = $list.jqmData( "spliticon" ),
\r
574 li = $list.children( "li" ),
\r
575 counter = $.support.cssPseudoElement || !$.nodeName( $list[ 0 ], "ol" ) ? 0 : 1,
\r
576 item, itemClass, itemTheme,
\r
577 a, last, splittheme, countParent, icon;
\r
580 $list.find( ".ui-li-dec" ).remove();
\r
583 for ( var pos = 0, numli = li.length; pos < numli; pos++ ) {
\r
584 item = li.eq( pos );
\r
585 itemClass = "ui-li";
\r
587 // If we're creating the element, we update it regardless
\r
588 if ( create || !item.hasClass( "ui-li" ) ) {
\r
589 itemTheme = item.jqmData( "theme" ) || o.theme;
\r
590 a = item.children( "a" );
\r
593 icon = item.jqmData( "icon" );
\r
595 item.buttonMarkup({
\r
600 /* icon: a.length > 1 || icon === false ? false : icon || "arrow-r",*/
\r
601 icon: false, /* Remove unnecessary arrow icon */
\r
605 if ( ( icon != false ) && ( a.length == 1 ) ) {
\r
606 item.addClass( "ui-li-has-arrow" );
\r
609 a.first().addClass( "ui-link-inherit" );
\r
611 if ( a.length > 1 ) {
\r
612 itemClass += " ui-li-has-alt";
\r
615 splittheme = listsplittheme || last.jqmData( "theme" ) || o.splitTheme;
\r
617 last.appendTo(item)
\r
618 .attr( "title", last.getEncodedText() )
\r
619 .addClass( "ui-li-link-alt" )
\r
628 .find( ".ui-btn-inner" )
\r
630 $( "<span />" ).buttonMarkup({
\r
635 icon: listspliticon || last.jqmData( "icon" ) || o.splitIcon
\r
639 } else if ( item.jqmData( "role" ) === "list-divider" ) {
\r
641 itemClass += " ui-li-divider ui-btn ui-bar-" + dividertheme;
\r
642 item.attr( "role", "heading" );
\r
644 //reset counter when a divider heading is encountered
\r
650 itemClass += " ui-li-static ui-body-" + itemTheme;
\r
654 if ( counter && itemClass.indexOf( "ui-li-divider" ) < 0 ) {
\r
655 countParent = item.is( ".ui-li-static:first" ) ? item : item.find( ".ui-link-inherit" );
\r
657 countParent.addClass( "ui-li-jsnumbering" )
\r
658 .prepend( "<span class='ui-li-dec'>" + (counter++) + ". </span>" );
\r
661 item.add( item.children( ".ui-btn-inner" ) ).addClass( itemClass );
\r
663 self._itemApply( $list, item );
\r
666 this._refreshCorners( create );
\r
669 //create a string for ID/subpage url creation
\r
670 _idStringEscape: function( str ) {
\r
671 return str.replace(/[^a-zA-Z0-9]/g, '-');
\r
674 _createSubPages: function() {
\r
675 var parentList = this.element,
\r
676 parentPage = parentList.closest( ".ui-page" ),
\r
677 parentUrl = parentPage.jqmData( "url" ),
\r
678 parentId = parentUrl || parentPage[ 0 ][ $.expando ],
\r
679 parentListId = parentList.attr( "id" ),
\r
681 dns = "data-" + $.mobile.ns,
\r
683 persistentFooterID = parentPage.find( ":jqmData(role='footer')" ).jqmData( "id" ),
\r
686 if ( typeof listCountPerPage[ parentId ] === "undefined" ) {
\r
687 listCountPerPage[ parentId ] = -1;
\r
690 parentListId = parentListId || ++listCountPerPage[ parentId ];
\r
692 $( parentList.find( "li>ul, li>ol" ).toArray().reverse() ).each(function( i ) {
\r
695 listId = list.attr( "id" ) || parentListId + "-" + i,
\r
696 parent = list.parent(),
\r
697 nodeEls = $( list.prevAll().toArray().reverse() ),
\r
698 nodeEls = nodeEls.length ? nodeEls : $( "<span>" + $.trim(parent.contents()[ 0 ].nodeValue) + "</span>" ),
\r
699 title = nodeEls.first().getEncodedText(),//url limits to first 30 chars of text
\r
700 id = ( parentUrl || "" ) + "&" + $.mobile.subPageUrlKey + "=" + listId,
\r
701 theme = list.jqmData( "theme" ) || o.theme,
\r
702 countTheme = list.jqmData( "counttheme" ) || parentList.jqmData( "counttheme" ) || o.countTheme,
\r
705 //define hasSubPages for use in later removal
\r
706 hasSubPages = true;
\r
708 newPage = list.detach()
\r
709 .wrap( "<div " + dns + "role='page' " + dns + "url='" + id + "' " + dns + "theme='" + theme + "' " + dns + "count-theme='" + countTheme + "'><div " + dns + "role='content'></div></div>" )
\r
711 .before( "<div " + dns + "role='header' " + dns + "theme='" + o.headerTheme + "'><div class='ui-title'>" + title + "</div></div>" )
\r
712 .after( persistentFooterID ? $( "<div " + dns + "role='footer' " + dns + "id='"+ persistentFooterID +"'>" ) : "" )
\r
714 .appendTo( $.mobile.pageContainer );
\r
718 anchor = parent.find('a:first');
\r
720 if ( !anchor.length ) {
\r
721 anchor = $( "<a/>" ).html( nodeEls || title ).prependTo( parent.empty() );
\r
724 anchor.attr( "href", "#" + id );
\r
726 }).virtuallistview();
\r
728 // on pagehide, remove any nested pages along with the parent page, as long as they aren't active
\r
729 // and aren't embedded
\r
731 parentPage.is( ":jqmData(external-page='true')" ) &&
\r
732 parentPage.data( "page" ).options.domCache === false ) {
\r
734 var newRemove = function( e, ui ){
\r
735 var nextPage = ui.nextPage, npURL;
\r
738 npURL = nextPage.jqmData( "url" );
\r
739 if( npURL.indexOf( parentUrl + "&" + $.mobile.subPageUrlKey ) !== 0 ){
\r
740 self.childPages().remove();
\r
741 parentPage.remove();
\r
746 // unbind the original page remove and replace with our specialized version
\r
748 .unbind( "pagehide.remove" )
\r
749 .bind( "pagehide.remove", newRemove);
\r
753 // TODO sort out a better way to track sub pages of the virtuallistview this is brittle
\r
754 childPages: function(){
\r
755 var parentUrl = this.parentPage.jqmData( "url" );
\r
757 return $( ":jqmData(url^='"+ parentUrl + "&" + $.mobile.subPageUrlKey +"')" );
\r
761 //auto self-init widgets
\r
762 $( document ).bind( "pagecreate create", function( e ){
\r
763 $( $.tizen.virtuallistview.prototype.options.initSelector, e.target ).virtuallistview();
\r