764220154b4e1b38cf67419af95e468de5716149
[platform/framework/web/web-ui-fw.git] / src / js / widgets / jquery.mobile.tizen.fastscroll.js
1 //>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
2 //>>description: Shows list index and scroll to the index directly
3 //>>label: Fastscroll
4 //>>group: Tizen:Widgets
5
6 define( [ '../jquery.mobile.tizen.scrollview' ], function ( ) {
7 //>>excludeEnd("jqmBuildExclude");
8
9 /*
10  * jQuery Mobile Widget @VERSION
11  *
12  * This software is licensed under the MIT licence (as defined by the OSI at
13  * http://www.opensource.org/licenses/mit-license.php)
14  *
15  * ***************************************************************************
16  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
17  * Copyright (c) 2011 by Intel Corporation Ltd.
18  *
19  * Permission is hereby granted, free of charge, to any person obtaining a
20  * copy of this software and associated documentation files (the "Software"),
21  * to deal in the Software without restriction, including without limitation
22  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
23  * and/or sell copies of the Software, and to permit persons to whom the
24  * Software is furnished to do so, subject to the following conditions:
25  *
26  * The above copyright notice and this permission notice shall be included in
27  * all copies or substantial portions of the Software.
28  *
29  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
34  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
35  * DEALINGS IN THE SOFTWARE.
36  * ***************************************************************************
37  *
38  * Authors: Elliot Smith <elliot.smith@intel.com>
39  *               Yonghwi Park <yonghwi0324.park@samsung.com>
40  */
41
42 // fastscroll is a scrollview controller, which binds
43 // a scrollview to a a list of short cuts; the shortcuts are built
44 // from the text on dividers in the list. Clicking on a shortcut
45 // instantaneously jumps the scrollview to the selected list divider;
46 // mouse movements on the shortcut column move the scrollview to the
47 // list divider matching the text currently under the touch; a popup
48 // with the text currently under the touch is also displayed.
49 //
50 // To apply, add the attribute data-fastscroll="true" to a listview
51 // (a <ul> or <ol> element inside a page). Alternatively, call
52 // fastscroll() on an element.
53 //
54 // The closest element with class ui-scrollview-clip is used as the
55 // scrollview to be controlled.
56 //
57 // If a listview has no dividers or a single divider, the widget won't
58 // display.
59
60 /**
61         @class fastscroll
62         The shortcut scroll widget shows a shortcut list that is bound to its parent scroll bar and respective list view. This widget is displayed as a text pop-up representing shortcuts to different list dividers in the list view. If you select a shortcut text from the shortcut scroll, the parent list view is moved to the location representing the selected shortcut.
63
64         To add a shortcut scroll widget to the application, use the following code:
65
66                 <div class="content" data-role="content" data-scroll="y">
67                         <ul id="contacts" data-role="listview" data-fastscroll="true">
68                                 <li>Anton</li>
69                         </ul>
70                 </div>
71
72         For the shortcut scroll widget to be visible, the parent list view must have multiple list dividers.
73 */
74
75 /**
76         @property {Boolean}  data-fastscroll
77         When set to true, creates a shortcut scroll using the HTML unordered list (&lt;ul&gt;) element.
78 */
79 /**
80         @method fastscroll
81         The shortcut scroll is created for the closest list view with the ui-scrollview-clip class.
82 */
83 /**
84         @method indexString
85         The indexString method is used to get (if no value is defined) or set the string to present the index.
86
87                 <div class="content" data-role="content" data-scroll="y">
88                         ul id="contacts" data-role="listview" data-fastscroll="true">
89                                 <li data-role="list-divider">A</li>
90                                 <li>Anton</li>
91                         </ul>
92                 </div>
93
94                 $(".selector").fastscroll( "indexString" [, indexAlphabet] );
95 */
96 (function ( $, undefined ) {
97
98         $.widget( "tizen.fastscroll", $.mobile.widget, {
99                 options: {
100                         initSelector: ":jqmData(fastscroll)"
101                 },
102
103                 _primaryLanguage: null,
104                 _secondLanguage: null,
105                 _dividerMap: {},
106                 _defaultTime: 500,
107                 _defaultDuration: 500,
108                 _timer: null,
109                 _isFadeOut: false,
110
111                 _create: function () {
112                         var $el = this.element,
113                                 self = this,
114                                 $popup,
115                                 page = $el.closest( ':jqmData(role="page")' ),
116                                 jumpToDivider;
117
118                         this.scrollview = $el.addClass( 'ui-fastscroll-target' ).closest( '.ui-scrollview-clip' );
119                         this.shortcutsContainer = $( '<div class="ui-fastscroll" aria-label="Fast scroll bar, double tap to fast scroll mode" tabindex="0"/>' );
120                         this.shortcutsList = $( '<ul aria-hidden="true"></ul>' );
121
122                         // popup for the hovering character
123                         this.scrollview.append($( '<div class="ui-fastscroll-popup"></div>' ) );
124                         $popup = this.scrollview.find( '.ui-fastscroll-popup' );
125
126                         this.shortcutsContainer.append( this.shortcutsList );
127                         this.scrollview.append( this.shortcutsContainer );
128
129                         // find the bottom of the last item in the listview
130                         this.lastListItem = $el.children().last();
131
132                         // remove scrollbars from scrollview
133                         this.scrollview.find( '.ui-scrollbar' ).hide();
134
135                         this.jumpToDivider = function ( divider ) {
136                                 // get the vertical position of the divider (so we can scroll to it)
137                                 var dividerY = $( divider ).position().top,
138                                         // find the bottom of the last list item
139                                         bottomOffset = self.lastListItem.outerHeight( true ) + self.lastListItem.position().top,
140                                         scrollviewHeight = self.scrollview.height(),
141
142                                 // check that after the candidate scroll, the bottom of the
143                                 // last item will still be at the bottom of the scroll view
144                                 // and not some way up the page
145                                         maxScroll = bottomOffset - scrollviewHeight,
146                                         dstOffset;
147
148                                 dividerY = ( dividerY > maxScroll ? maxScroll : dividerY );
149
150                                 // don't apply a negative scroll, as this means the
151                                 // divider should already be visible
152                                 dividerY = Math.max( dividerY, 0 );
153
154                                 // apply the scroll
155                                 self.scrollview.scrollview( 'scrollTo', 0, -dividerY );
156
157                                 dstOffset = self.scrollview.offset();
158                         };
159
160                         this.shortcutsList
161                         // bind mouse over so it moves the scroller to the divider
162                                 .bind( 'touchstart mousedown vmousedown touchmove vmousemove vmouseover', function ( e ) {
163                                         // Get coords relative to the element
164                                         var coords = $.mobile.tizen.targetRelativeCoordsFromEvent( e ),
165                                                 shortcutsListOffset = self.shortcutsList.offset();
166
167                                         if ( self._isFadeOut === true ) {
168                                                 return;
169                                         }
170
171                                         // If the element is a list item, get coordinates relative to the shortcuts list
172                                         if ( e.target.tagName.toLowerCase() === "li" ) {
173                                                 coords.x += $( e.target ).offset().left - shortcutsListOffset.left;
174                                                 coords.y += $( e.target ).offset().top  - shortcutsListOffset.top;
175                                         }
176
177                                         if ( e.target.tagName.toLowerCase() === "span" ) {
178                                                 coords.x += $( e.target ).parent().offset().left - shortcutsListOffset.left;
179                                                 coords.y += $( e.target ).parent().offset().top  - shortcutsListOffset.top;
180                                         }
181
182                                         self.shortcutsList.find( 'li' ).each( function () {
183                                                 var listItem = $( this );
184                                                 $( listItem )
185                                                         .removeClass( "ui-fastscroll-hover" )
186                                                         .removeClass( "ui-fastscroll-hover-up" )
187                                                         .removeClass( "ui-fastscroll-hover-down" );
188                                         });
189                                         // Hit test each list item
190                                         self.shortcutsList.find( 'li' ).each( function () {
191                                                 var listItem = $( this ),
192                                                         l = listItem.offset().left - shortcutsListOffset.left,
193                                                         t = listItem.offset().top  - shortcutsListOffset.top,
194                                                         r = l + Math.abs(listItem.outerWidth( true ) ),
195                                                         b = t + Math.abs(listItem.outerHeight( true ) ),
196                                                         unit,
197                                                         baseTop,
198                                                         baseBottom,
199                                                         omitSet,
200                                                         i;
201
202                                                 if ( coords.x >= l && coords.x <= r && coords.y >= t && coords.y <= b ) {
203                                                         if ( listItem.text() !== "." ) {
204                                                                 self._hitItem( listItem );
205                                                         } else {
206                                                                 omitSet = listItem.data( "omitSet" );
207                                                                 unit = ( b - t ) / omitSet.length;
208                                                                 for ( i = 0; i < omitSet.length; i++ ) {
209                                                                         baseTop = t + ( i * unit );
210                                                                         baseBottom = baseTop + unit;
211                                                                         if ( coords.y >= baseTop && coords.y <= baseBottom ) {
212                                                                                 self._hitOmitItem( listItem, omitSet.charAt( i ) );
213                                                                         }
214                                                                 }
215                                                         }
216                                                         return false;
217                                                 }
218                                                 return true;
219                                         } );
220
221                                         self._setTimer( false );
222
223                                         e.preventDefault();
224                                         e.stopPropagation();
225                                 } )
226                                 // bind mouseout of the fastscroll container to remove popup
227                                 .bind( 'touchend mouseup vmouseup vmouseout', function () {
228                                         $popup.hide();
229                                         $( ".ui-fastscroll-hover" ).removeClass( "ui-fastscroll-hover" );
230                                         $( ".ui-fastscroll-hover-first-item" ).removeClass( "ui-fastscroll-hover-first-item" );
231                                         $( ".ui-fastscroll-hover-up" ).removeClass( "ui-fastscroll-hover-up" );
232                                         $( ".ui-fastscroll-hover-down" ).removeClass( "ui-fastscroll-hover-down" );
233                                         self._setTimer( true );
234                                 } );
235
236                         if ( page && !( page.is( ':visible' ) ) ) {
237                                 page.bind( 'pageshow', function () { self.refresh(); } );
238                         } else {
239                                 self.refresh();
240                         }
241
242                         // refresh the list when dividers are filtered out
243                         $el.bind( 'updatelayout', function () {
244                                 self.refresh();
245                         } );
246
247                         self.scrollview.bind( "scrollstart", function ( e ) {
248                                 self._setTimer( false );
249                         }).bind( "scrollstop", function ( e ) {
250                                 self._setTimer( true );
251                         });
252                 },
253
254                 _hitOmitItem: function ( listItem, text ) {
255                         var self = this,
256                                 $popup = self.scrollview.find( '.ui-fastscroll-popup' ),
257                                 divider = self._dividerMap[ text ];
258
259                         if ( typeof divider !== "undefined" ) {
260                                 self.jumpToDivider( $( divider ) );
261                         }
262
263                         $popup.text( text )
264                                 .css( { marginLeft: -( $popup.width() / 2 ),
265                                         marginTop: -( $popup.height() / 2 ),
266                                         padding: $popup.css( "paddingTop" ) } )
267                                 .width( $popup.height() )
268                                 .show();
269
270                         $( listItem ).addClass( "ui-fastscroll-hover" );
271                         if ( listItem.index() === 0 ) {
272                                 $( listItem ).addClass( "ui-fastscroll-hover-first-item" );
273                         }
274                         if ( listItem.index() > 0 ) {
275                                 $( listItem ).siblings().eq( listItem.index() - 1 ).addClass( "ui-fastscroll-hover-up" );
276                         }
277                         $( listItem ).siblings().eq( listItem.index() ).addClass( "ui-fastscroll-hover-down" );
278                 },
279
280                 _hitItem: function ( listItem  ) {
281                         var self = this,
282                                 $popup = self.scrollview.find( '.ui-fastscroll-popup' ),
283                                 text = listItem.text(),
284                                 divider;
285
286                         if ( text === "#" ) {
287                                 divider = self._dividerMap.number;
288                         } else {
289                                 divider = self._dividerMap[ text ];
290                         }
291
292                         if ( typeof divider !== "undefined" ) {
293                                 self.jumpToDivider( $( divider ) );
294                         }
295
296                         $popup.text( text )
297                                 .css( { marginLeft: -( $popup.width() / 2 ),
298                                         marginTop: -( $popup.height() / 2 ),
299                                         padding: $popup.css( "paddingTop" ) } )
300                                 .width( $popup.height() )
301                                 .show();
302
303                         $( listItem ).addClass( "ui-fastscroll-hover" );
304                         if ( listItem.index() === 0 ) {
305                                 $( listItem ).addClass( "ui-fastscroll-hover-first-item" );
306                         }
307                         if ( listItem.index() > 0 ) {
308                                 $( listItem ).siblings().eq( listItem.index() - 1 ).addClass( "ui-fastscroll-hover-up" );
309                         }
310                         $( listItem ).siblings().eq( listItem.index() ).addClass( "ui-fastscroll-hover-down" );
311                 },
312
313                 _focusItem: function ( listItem ) {
314                         var self = this,
315                                 $popup = self.scrollview.find( '.ui-fastscroll-popup' );
316
317                         listItem.focusin( function ( e ) {
318                                 self.shortcutsList.attr( "aria-hidden", false );
319                                 self._hitItem( listItem );
320                                 self._setTimer( false );
321                         }).focusout( function ( e ) {
322                                 self.shortcutsList.attr( "aria-hidden", true );
323                                 $popup.hide();
324                                 $( ".ui-fastscroll-hover" ).removeClass( "ui-fastscroll-hover" );
325                                 $( ".ui-fastscroll-hover-first-item" ).removeClass( "ui-fastscroll-hover-first-item" );
326                                 $( ".ui-fastscroll-hover-up" ).removeClass( "ui-fastscroll-hover-up" );
327                                 $( ".ui-fastscroll-hover-down" ).removeClass( "ui-fastscroll-hover-down" );
328                                 self._setTimer( true );
329                         });
330                 },
331
332                 _contentHeight: function () {
333                         var self = this,
334                                 $content = $( '.ui-scrollview-clip' ),
335                                 header = null,
336                                 footer = null,
337                                 paddingValue = 0,
338                                 clipSize = $( window ).height();
339
340                         if ( $content.hasClass( "ui-content" ) ) {
341                                 paddingValue = parseInt( $content.css( "padding-top" ), 10 );
342                                 clipSize = clipSize - ( paddingValue || 0 );
343                                 paddingValue = parseInt( $content.css( "padding-bottom" ), 10 );
344                                 clipSize = clipSize - ( paddingValue || 0 );
345                                 header = $content.siblings( ".ui-header:visible" );
346                                 footer = $content.siblings( ".ui-footer:visible" );
347
348                                 if ( header ) {
349                                         if ( header.outerHeight( true ) === null ) {
350                                                 clipSize = clipSize - ( $( ".ui-header" ).outerHeight() || 0 );
351                                         } else {
352                                                 clipSize = clipSize - header.outerHeight( true );
353                                         }
354                                 }
355                                 if ( footer ) {
356                                         clipSize = clipSize - footer.outerHeight( true );
357                                 }
358                         } else {
359                                 clipSize = $content.height();
360                         }
361                         return clipSize;
362                 },
363
364                 _omit: function ( numOfItems, maxNumOfItems ) {
365                         var maxGroupNum = parseInt( ( maxNumOfItems - 1 ) / 2, 10 ),
366                                 numOfExtraItems = numOfItems - maxNumOfItems,
367                                 groupPos = [],
368                                 omitInfo = [],
369                                 groupPosLength,
370                                 group,
371                                 size,
372                                 i;
373
374                         if ( ( maxNumOfItems < 3 ) || ( numOfItems <= maxNumOfItems ) ) {
375                                 return;
376                         }
377
378                         if ( numOfExtraItems >= maxGroupNum ) {
379                                 size = 2;
380                                 group = 1;
381                                 groupPosLength = maxGroupNum;
382                         } else {
383                                 size = maxNumOfItems / ( numOfExtraItems + 1 );
384                                 group = size;
385                                 groupPosLength = numOfExtraItems;
386                         }
387
388                         for ( i = 0; i < groupPosLength; i++ ) {
389                                 groupPos.push( parseInt( group, 10 ) );
390                                 group += size;
391                         }
392
393                         for ( i = 0; i < maxNumOfItems; i++ ) {
394                                 omitInfo.push( 1 );
395                         }
396
397                         for ( i = 0; i < numOfExtraItems; i++ ) {
398                                 omitInfo[ groupPos[ i % maxGroupNum ] ]++;
399                         }
400
401                         return omitInfo;
402                 },
403
404                 _createDividerMap: function () {
405                         var self = this,
406                                 primaryCharacterSet = self._primaryLanguage ? self._primaryLanguage.replace( /,/g, "" ) : null,
407                                 secondCharacterSet = self._secondLanguage ? self._secondLanguage.replace( /,/g, "" ) : null,
408                                 numberSet = "0123456789",
409                                 dividers = self.element.find( '.ui-li-divider' ),
410                                 map = {},
411                                 matchToDivider,
412                                 makeCharacterSet,
413                                 indexChar,
414                                 i;
415
416                         matchToDivider = function ( index, divider ) {
417                                 if ( $( divider ).text() === indexChar ) {
418                                         map[ indexChar ] = divider;
419                                 }
420                         };
421
422                         makeCharacterSet = function ( index, divider ) {
423                                 primaryCharacterSet += $( divider ).text();
424                         };
425
426                         if ( primaryCharacterSet === null ) {
427                                 primaryCharacterSet = "";
428                                 dividers.each( makeCharacterSet );
429                         }
430
431                         for ( i = 0; i < primaryCharacterSet.length; i++ ) {
432                                 indexChar = primaryCharacterSet.charAt( i );
433                                 dividers.each( matchToDivider );
434                         }
435
436                         if ( secondCharacterSet !== null ) {
437                                 for ( i = 0; i < secondCharacterSet.length; i++ ) {
438                                         indexChar = secondCharacterSet.charAt( i );
439                                         dividers.each( matchToDivider );
440                                 }
441                         }
442
443                         dividers.each( function ( index, divider ) {
444                                 if (  numberSet.search( $( divider ).text() ) !== -1  ) {
445                                         map.number = divider;
446                                         return false;
447                                 }
448                         });
449
450                         self._dividerMap = map;
451                 },
452
453                 _setTimer: function ( start ) {
454                         var self = this;
455
456                         if ( start === true ) {
457                                 self._timer = setTimeout( function () {
458                                         self._isFadeOut = true;
459                                         self.shortcutsContainer.fadeOut( self._defaultDuration, function () {
460                                                 self._isFadeOut = false;
461                                         });
462                                 }, self._defaultTime );
463                         } else {
464                                 if ( self._timer !== null ) {
465                                         clearTimeout( self._timer );
466                                 }
467                                 self.shortcutsContainer.show();
468                         }
469                 },
470
471                 indexString: function ( indexAlphabet ) {
472                         var self = this,
473                                 characterSet = [];
474
475                         if ( typeof indexAlphabet === "undefined" ) {
476                                 return self._primaryLanguage + ":" + self._secondLanguage;
477                         }
478
479                         characterSet = indexAlphabet.split( ":" );
480                         self._primaryLanguage = characterSet[ 0 ];
481                         if ( characterSet.length === 2 ) {
482                                 self._secondLanguage = characterSet[ 1 ];
483                         }
484                 },
485
486                 refresh: function () {
487                         var self = this,
488                                 primaryCharacterSet = self._primaryLanguage ? self._primaryLanguage.replace( /,/g, "" ) : null,
489                                 secondCharacterSet = self._secondLanguage ? self._secondLanguage.replace( /,/g, "" ) : null,
490                                 contentHeight = self._contentHeight(),
491                                 shapItem = $( '<li tabindex="0" aria-label="double to move Number list"><span aria-hidden="true">#</span><span aria-label="Number"/></li>' ),
492                                 omitIndex = 0,
493                                 makeCharacterSet,
494                                 makeOmitSet,
495                                 itemHandler,
496                                 containerHeight,
497                                 shortcutsItems,
498                                 shortcutItem,
499                                 shortcutsTop,
500                                 minClipHeight,
501                                 maxNumOfItems,
502                                 numOfItems,
503                                 minHeight,
504                                 padding,
505                                 omitInfo,
506                                 dividers,
507                                 listItems,
508                                 emptySize,
509                                 correction,
510                                 indexChar,
511                                 lastIndex,
512                                 seconds,
513                                 height,
514                                 size,
515                                 i;
516
517                         makeCharacterSet = function ( index, divider ) {
518                                 primaryCharacterSet += $( divider ).text();
519                         };
520
521                         makeOmitSet = function ( index, length ) {
522                                 var count,
523                                         omitSet = "";
524
525                                 for ( count = 0; count < length; count++ ) {
526                                         omitSet += primaryCharacterSet[ index + count ];
527                                 }
528
529                                 return omitSet;
530                         };
531
532                         itemHandler = function ( e ) {
533                                 var text = $( this ).text(),
534                                         matchDivider = self._dividerMap[ text ];
535
536                                 if ( typeof matchDivider !== "undefined" ) {
537                                         $( matchDivider ).next().focus();
538                                 }
539                         };
540
541                         self._createDividerMap();
542
543                         self.shortcutsList.find( 'li' ).remove();
544
545                         // get all the dividers from the list and turn them into shortcuts
546                         dividers = self.element.find( '.ui-li-divider' );
547
548                         // get all the list items
549                         listItems = self.element.find('li').not('.ui-li-divider');
550
551                         // only use visible dividers
552                         dividers = dividers.filter( ':visible' );
553                         listItems = listItems.filter( ':visible' );
554
555                         if ( dividers.length < 2 ) {
556                                 self.shortcutsList.hide();
557                                 return;
558                         }
559
560                         self.shortcutsList.show();
561                         self.lastListItem = listItems.last();
562                         self.shortcutsList.append( shapItem );
563                         self._focusItem( shapItem );
564
565                         if ( primaryCharacterSet === null ) {
566                                 primaryCharacterSet = "";
567                                 dividers.each( makeCharacterSet );
568                         }
569
570                         padding = parseInt( shapItem.css( "padding" ), 10 );
571                         minHeight = shapItem.height() + ( padding * 2 );
572                         maxNumOfItems = parseInt( ( contentHeight / minHeight ) - 1, 10 );
573                         numOfItems = primaryCharacterSet.length;
574
575                         maxNumOfItems = secondCharacterSet ? maxNumOfItems - 2 : maxNumOfItems;
576
577                         if ( maxNumOfItems < 3 ) {
578                                 shapItem.remove();
579                                 return;
580                         }
581
582                         omitInfo = self._omit( numOfItems, maxNumOfItems );
583
584                         for ( i = 0; i < primaryCharacterSet.length; i++ ) {
585                                 indexChar = primaryCharacterSet.charAt( i );
586                                 shortcutItem = $( '<li tabindex="0" aria-label="double to move ' + indexChar + ' list">' + indexChar + '</li>' );
587
588                                 self._focusItem( shortcutItem );
589
590                                 if ( typeof omitInfo !== "undefined" && omitInfo[ omitIndex ] > 1 ) {
591                                         shortcutItem = $( '<li>.</li>' );
592                                         shortcutItem.data( "omitSet",  makeOmitSet( i, omitInfo[ omitIndex ] ) );
593                                         i += omitInfo[ omitIndex ] - 1;
594                                 } else {
595                                         shortcutItem.bind( 'vclick', itemHandler );
596                                 }
597
598                                 shapItem.before( shortcutItem );
599                                 omitIndex++;
600                         }
601
602                         if ( secondCharacterSet !== null ) {
603                                 lastIndex = secondCharacterSet.length - 1;
604                                 seconds = [];
605
606                                 seconds.push( secondCharacterSet.charAt( 0 ) );
607                                 seconds.push( secondCharacterSet.charAt( lastIndex ) );
608
609                                 for ( i = 0; i < seconds.length; i++ ) {
610                                         indexChar = seconds[ i ];
611                                         shortcutItem = $( '<li tabindex="0" aria-label="double to move ' + indexChar + ' list">' + indexChar + '</li>' );
612
613                                         self._focusItem( shortcutItem );
614                                         shortcutItem.bind( 'vclick', itemHandler );
615                                         shapItem.before( shortcutItem );
616                                 }
617                         }
618
619                         containerHeight = self.shortcutsContainer.outerHeight();
620                         emptySize = contentHeight - containerHeight;
621                         shortcutsItems = self.shortcutsList.children();
622                         size = parseInt( emptySize / shortcutsItems.length, 10 );
623                         correction = emptySize - ( shortcutsItems.length * size );
624
625                         if ( emptySize > 0 ) {
626                                 shortcutsItems.each( function ( index, item ) {
627                                         height = $( item ).height() + size;
628                                         if ( correction !== 0 ) {
629                                                 height += 1;
630                                                 correction -= 1;
631                                         }
632                                         $( item ).css( {
633                                                 height: height,
634                                                 lineHeight: height + "px"
635                                         } );
636                                 } );
637                         }
638
639                         // position the shortcut flush with the top of the first list divider
640                         shortcutsTop = dividers.first().position().top;
641                         self.shortcutsContainer.css( 'top', shortcutsTop );
642
643                         // make the scrollview clip tall enough to show the whole of the shortcutslist
644                         minClipHeight = shortcutsTop + self.shortcutsContainer.outerHeight() + 'px';
645                         self.scrollview.css( 'min-height', minClipHeight );
646
647                         self._setTimer( false );
648                         self._setTimer( true );
649                 }
650         } );
651
652         $( document ).bind( "pagecreate create", function ( e ) {
653                 $( $.tizen.fastscroll.prototype.options.initSelector, e.target )
654                         .not( ":jqmData(role='none'), :jqmData(role='nojs')" )
655                         .fastscroll();
656         } );
657
658         $( window ).bind( "resize orientationchange", function ( e ) {
659                 $( ".ui-page-active .ui-fastscroll-target" ).fastscroll( "refresh" );
660         } );
661 } ( jQuery ) );
662
663 //>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
664 } );
665 //>>excludeEnd("jqmBuildExclude");