You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by pp...@apache.org on 2013/09/10 20:04:16 UTC

[11/51] [partial] [cordova-tizen] Tizen SDK 2.2 support mores samples

http://git-wip-us.apache.org/repos/asf/cordova-tizen/blob/4ebce38e/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.datetimepicker.js
----------------------------------------------------------------------
diff --git a/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.datetimepicker.js b/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.datetimepicker.js
new file mode 100644
index 0000000..7328a11
--- /dev/null
+++ b/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.datetimepicker.js
@@ -0,0 +1,877 @@
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+//>>description: Shows date and time, and make them able to be changed by user
+//>>label: Datetime picker
+//>>group: Tizen:Widgets
+
+define( [ 
+	'jquery',
+	"libs/globalize",
+	'./jquery.mobile.tizen.widgetex',
+	'./jquery.mobile.tizen.popupwindow.ctxpopup',
+	], function ( jQuery, Globalize) {
+
+//>>excludeEnd("jqmBuildExclude");
+
+/*global Globalize:false, range:false, regexp:false*/
+/*
+ * jQuery Mobile Widget @VERSION
+ *
+ * This software is licensed under the MIT licence (as defined by the OSI at
+ * http://www.opensource.org/licenses/mit-license.php)
+ *
+ * ***************************************************************************
+ * Copyright (C) 2011 by Intel Corporation Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * ***************************************************************************
+ *
+ * Authors: Salvatore Iovene <sa...@intel.com>
+ *			Daehyon Jung <da...@samsung.com>
+ */
+
+/**
+ * datetimepicker is a widget that lets the user select a date and/or a 
+ * time. If you'd prefer use as auto-initialization of form elements, 
+ * use input elements with type=date/time/datetime within form tag
+ * as same as other form elements.
+ * 
+ * HTML Attributes:
+ * 
+ *	data-role: 'datetimepicker'
+ *	data-format: date format string. e.g) "MMM dd yyyy, HH:mm"
+ *	type: 'date', 'datetime', 'time'
+ *	value: pre-set value. only accepts ISO date string. e.g) "2012-05-04", "2012-05-04T01:02:03+09:00" 
+ *	data-date: any date/time string "new Date()" accepts.
+ *
+ * Options:
+ *	type: 'date', 'datetime', 'time'
+ *	format: see data-format in HTML Attributes.
+ *	value: see value in HTML Attributes.
+ *	date: preset value as JavaScript Date Object representation.
+ *
+ * APIs:
+ *	value( datestring )
+ *		: Set date/time to 'datestring'.
+ *	value()
+ *		: Get current selected date/time as W3C DTF style string.
+ *	getValue() - replaced with 'value()'
+ *		: same as value()
+ *	setValue( datestring ) - replaced with 'value(datestring)'
+ *		: same as value( datestring )
+ *	changeTypeFormat( type, format ) - deprecated
+ *		: Change Type and Format options. use datetimepicker( "option", "format" ) instead
+ *
+ * Events:
+ *	date-changed: Raised when date/time was changed. Date-changed event will be deprecated
+ *
+ * Examples:
+ *	<ul data-role="listview">
+ *		<li class="ui-li-3-2-2">
+ *			<span class="ui-li-text-main">
+ *				<input type="datetime" name="demo-date" id="demo-date" 
+ *					data-format="MMM dd yyyy hh:mm tt"/>
+ *			</span>
+ *			<span class="ui-li-text-sub">
+ *				Date/Time Picker - <span id="selected-date1"><em>(select a date first)</em></span>
+ *			</span>
+ *		</li>
+ *		<li class="ui-li-3-2-2">
+ *			<span class="ui-li-text-main">
+ *				<input type="date" name="demo-date2" id="demo-date2"/>
+ *			</span>
+ *			<span class="ui-li-text-sub">
+ *				Date Picker  - <span id="selected-date2"><em>(select a date first)</em></span>
+ *			</span>
+ *		</li>
+ *		<li class="ui-li-3-2-2">
+ *			<span class="ui-li-text-main">
+ *				<input type="time" name="demo-date3" id="demo-date3"/>
+ *			</span>
+ *			<span class="ui-li-text-sub">
+ *				Time Picker - <span id="selected-date3"><em>(select a date first)</em></span>
+ *			</span>
+ *		</li>
+ *	</ul>
+ * How to get a return value:
+ * ==========================
+ * Bind to the 'date-changed' event, e.g.:
+ *    $("#myDatetimepicker").bind("change", function() {
+ *			// your code
+ *    });
+ */
+
+/**
+	@class DateTimePicker
+	The picker widgets show a control that you can use to enter date and time values. <br/> To add a date time picker widget to the application, use the following code:
+
+			<li class="ui-li-dialogue ui-datetime">
+				<div class="ui-datetime-text-main">
+					<input type="datetime" data-format="MMM dd yyyy hh:mm:ss" name="demo-date" id="demo-date" />
+				</div>
+				<div class="ui-li-text-sub">Date/Time Picker
+					<span id="selected-date1"><em>(select a date first)</em></span>
+				</div>
+			</li>
+*/
+
+
+( function ( $, window, undefined ) {
+	$.widget( "tizen.datetimepicker", $.tizen.widgetex, {
+
+		options: {
+			type: null, // date, time, datetime applicable
+			format: null,
+			date: null,
+			initSelector: "input[type='date'], input[type='datetime'], input[type='time'], :jqmData(role='datetimepicker')"
+		},
+
+		container : null,
+
+		_calendar: function () {
+			return Globalize.culture().calendars.standard;
+		},
+
+		_value: {
+			attr: "data-" + ( $.mobile.ns || "" ) + "date",
+			signal: "date-changed"
+		},
+
+		_daysInMonth: [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ],
+
+		_isLeapYear: function ( year ) {
+			return year % 4 ? 0 : ( year % 100 ? 1 : ( year % 400 ? 0 : 1 ) );
+		},
+
+		_makeTwoDigits: function ( val ) {
+			var ret = val.toString(10);
+			if ( val < 10 ) {
+				ret = "0" + ret;
+			}
+			return ret;
+		},
+
+		_setType: function ( type ) {
+			//datetime, date, time
+			switch (type) {
+			case 'datetime':
+			case 'date':
+			case 'time':
+				this.options.type = type;
+				break;
+			default:
+				this.options.type = 'datetime';
+				break;
+			}
+
+			this.element.attr( "data-" + ( $.mobile.ns ? $.mobile.ns + "-" : "" ) + "type", this.options.type );
+			return this.options.type;
+		},
+
+		_setFormat: function ( format ) {
+			if ( this.options.format != format ) {
+				this.options.format = format;
+			} else {
+				return;
+			}
+
+			this.ui.children().remove();
+
+			var token = this._parsePattern( format ),
+				div = document.createElement('div'),
+				pat,
+				tpl,
+				tpl2,
+				period,
+				btn,
+				obj = this;
+
+			while ( token.length > 0 ) {
+				pat = token.shift();
+				tpl = '<span class="ui-btn-picker ui-datefield-%1"' +
+					'data-role="button" data-inline="true" data-pat="' + pat + '">%2</span>';
+				tpl2= '<span class="ui-datefield-%1" data-pat="' + pat + '">%2</span>';
+				switch ( pat ) {
+				case 'H': //0 1 2 3 ... 21 22 23
+				case 'HH': //00 01 02 ... 21 22 23
+				case 'h': //0 1 2 3 ... 11 12
+				case 'hh': //00 01 02 ... 11 12
+					$(div).append( tpl.replace('%1', 'hour') );
+					break;
+				case 'mm': //00 01 ... 59
+				case 'm': //0 1 2 ... 59
+					if ( this.options.type == 'date' ) {
+						$(div).append( tpl.replace('%1', 'month') );
+					} else {
+						$(div).append( tpl.replace('%1', 'min') );
+					}
+					break;
+				case 'ss':
+				case 's':
+					$(div).append( tpl.replace('%1', 'sec') );
+					break;
+				case 'd': // day of month 5
+				case 'dd': // day of month(leading zero) 05
+					$(div).append( tpl.replace('%1', 'day') );
+					break;
+				case 'M': // Month of year 9
+				case 'MM': // Month of year(leading zero) 09
+				case 'MMM':
+				case 'MMMM':
+					$(div).append( tpl.replace('%1', 'month') );
+					break;
+				case 'yy':	// year two digit
+				case 'yyyy': // year four digit
+					$(div).append( tpl.replace('%1', 'year') );
+					break;
+				case 't': //AM / PM indicator(first letter) A, P
+					// add button
+				case 'tt': //AM / PM indicator AM/PM
+					// add button
+					btn = '<a href="#" class="ui-datefield-period"' +
+						' data-role="button" data-inline="true">period</a>';
+					$(div).append( btn );
+					break;
+				case 'g':
+				case 'gg':
+					$(div).append( tpl.replace('%1', 'era').replace('%2', this._calendar().eras.name) );
+					break;
+				case '\t':
+					$(div).append( tpl2.replace('%1', 'tab')
+							.replace('%2', "<div class='ui-divider-1st'>&nbsp;</div>" +
+								"<div class='ui-divider-2nd'>&nbsp;</div>") );
+					break;
+				default : // string or any non-clickable object
+					$(div).append( tpl2.replace('%1', 'seperator').replace('%2', pat.split(/[\-\/]/).join("") ) );
+					break;
+				}
+			}
+
+			this.ui.append( div );
+			if ( this.options.date ) {
+				this._setDate( this.options.date );
+			}
+
+			this.ui.find('.ui-btn-picker').buttonMarkup();
+			this.ui.find('.ui-datefield-period').buttonMarkup().bind( 'vclick', function ( e ) {
+				obj._switchAmPm( obj );
+				return false;
+			});
+
+			this.element.attr( "data-" + ( $.mobile.ns ? $.mobile.ns + "-" : "" ) + "format", this.options.format );
+			return this.options.format;
+		},
+
+		_setDate: function ( newdate ) {
+			if ( typeof ( newdate ) == "string" ) {
+				newdate = new Date( newdate );
+			}
+
+			var fields = $('span,a', this.ui),
+				type,
+				fn,
+				$field,
+				btn,
+				i;
+
+			function getMonth() {
+				return newdate.getMonth() + 1;
+			}
+
+			for ( i = 0; i < fields.length; i++ ) {
+				$field = $(fields[i]);
+				type = $field.attr("class").match(/ui-datefield-([\w]*)/);
+				if ( !type ) {
+					type = "";
+				}
+				switch ( type[1] ) {
+				case 'hour':
+					fn = newdate.getHours;
+					break;
+				case 'min':
+					fn = newdate.getMinutes;
+					break;
+				case 'sec':
+					fn = newdate.getSeconds;
+					break;
+				case 'year':
+					fn = newdate.getFullYear;
+					break;
+				case 'month':
+					fn = getMonth;
+					break;
+				case 'day':
+					fn = newdate.getDate;
+					break;
+				case 'period':
+					fn = newdate.getHours() < 12 ? this._calendar().AM[0] : this._calendar().PM[0];
+					btn = $field.find( '.ui-btn-text' );
+					if ( btn.length == 0 ) {
+						$field.text(fn);
+					} else if ( btn.text() != fn ) {
+						btn.text( fn );
+					}
+					fn = null;
+					break;
+				default:
+					fn = null;
+					break;
+				}
+				if ( fn ) {
+					this._updateField( $field, fn.call( newdate ) );
+				}
+			}
+
+			this.options.date = newdate;
+
+			this._setValue( newdate );
+
+			this.element.attr( "data-" + ( $.mobile.ns ? $.mobile.ns + "-" : "" ) + "date", this.options.date );
+			return this.options.date;
+		},
+
+		destroy: function () {
+			if ( this.ui ) {
+				this.ui.remove();
+			}
+
+			if ( this.element ) {
+				this.element.show();
+			}
+		},
+
+		value: function ( val ) {
+			function timeStr( t, obj ) {
+				return obj._makeTwoDigits( t.getHours() ) + ':' +
+					obj._makeTwoDigits( t.getMinutes() ) + ':' +
+					obj._makeTwoDigits( t.getSeconds() );
+			}
+
+			function dateStr( d, obj ) {
+				return ( ( d.getFullYear() % 10000 ) + 10000 ).toString().substr(1) + '-' +
+					obj._makeTwoDigits( d.getMonth() + 1 ) + '-' +
+					obj._makeTwoDigits( d.getDate() );
+			}
+
+			var rvalue = null;
+			if ( val ) {
+				rvalue = this._setDate( val );
+			} else {
+				switch ( this.options.type ) {
+				case 'time':
+					rvalue = timeStr( this.options.date, this );
+					break;
+				case 'date':
+					rvalue = dateStr( this.options.date, this );
+					break;
+				default:
+					rvalue = dateStr( this.options.date, this ) + 'T' + timeStr( this.options.date, this );
+					break;
+				}
+			}
+			return rvalue;
+		},
+
+		setValue: function ( newdate ) {
+			console.warn( "setValue was deprecated. use datetimepicker('option', 'date', value) instead." );
+			return this.value( newdate );
+		},
+
+		/**
+		 * return W3C DTF string
+		 */
+		getValue: function () {
+			console.warn("getValue() was deprecated. use datetimepicker('value') instead.");
+			return this.value();
+		},
+
+		_updateField: function ( target, value ) {
+			if ( !target || target.length == 0 ) {
+				return;
+			}
+
+			if ( value == 0 ) {
+				value = "0";
+			}
+
+			var pat = target.jqmData( 'pat' ),
+				hour,
+				text,
+				self = this;
+
+			switch ( pat ) {
+			case 'H':
+			case 'HH':
+			case 'h':
+			case 'hh':
+				hour = value;
+				if ( pat.charAt(0) == 'h' ) {
+					if ( hour > 12 ) {
+						hour -= 12;
+					} else if ( hour == 0 ) {
+						hour = 12;
+					}
+				}
+				hour = this._makeTwoDigits( hour );
+				text = hour;
+				break;
+			case 'm':
+			case 'M':
+			case 'd':
+			case 's':
+				text = value;
+				break;
+			case 'mm':
+			case 'dd':
+			case 'MM':
+			case 'ss':
+				text = this._makeTwoDigits( value );
+				break;
+			case 'MMM':
+				text = this._calendar().months.namesAbbr[ value - 1];
+				break;
+			case 'MMMM':
+				text = this._calendar().months.names[ value - 1 ];
+				break;
+			case 'yy':
+				text = this._makeTwoDigits( value % 100 );
+				break;
+			case 'yyyy':
+				if ( value < 10 ) {
+					value = '000' + value;
+				} else if ( value < 100 ) {
+					value = '00' + value;
+				} else if ( value < 1000 ) {
+					value = '0' + value;
+				}
+				text = value;
+				break;
+			}
+
+			// to avoid reflow where its value isn't out-dated
+			if ( target.text() != text ) {
+				if ( target.hasClass("ui-datefield-selected") ) {
+					target.addClass("out");
+					this._new_value = text;
+
+					target.animationComplete( function () {
+						target.text( self._new_value);
+						target.addClass("in")
+							.removeClass("out");
+
+						target.animationComplete( function () {
+							target.removeClass("in").
+								removeClass("ui-datefield-selected");
+						});
+					});
+				} else {
+					target.text( text );
+				}
+			}
+		},
+
+		_switchAmPm: function ( obj ) {
+			if ( this._calendar().AM != null ) {
+				var date = new Date( this.options.date ),
+					text,
+					change = 1000 * 60 * 60 * 12;
+				if ( date.getHours() > 11 ) {
+					change = -change;
+				}
+				date.setTime( date.getTime() + change );
+				this._setDate( date );
+			}
+		},
+
+		_parsePattern: function ( pattern ) {
+			var regex = /\/|\s|dd|d|MMMM|MMM|MM|M|yyyy|yy|y|hh|h|HH|H|mm|m|ss|s|tt|t|f|gg|g|\'[\w\W]*\'$|[\w\W]/g,
+				matches,
+				i;
+
+			matches = pattern.match( regex );
+
+			for ( i = 0; i < matches.length; i++ ) {
+				if ( matches[i].charAt(0) == "'" ) {
+					matches[i] = matches[i].substr( 1, matches[i].length - 2 );
+				}
+			}
+
+			return matches;
+		},
+
+		changeTypeFormat: function ( type, format ) {
+			console.warn('changeTypeFormat() was deprecated. use datetimepicker("option", "type"|"format", value) instead');
+			if ( type ) {
+				this._setType( type );
+			}
+
+			if ( format ) {
+				this._setFormat( format );
+			}
+		},
+
+		_create: function () {
+			var obj = this;
+
+			if ( this.element.is( "input" ) ) {
+				( function ( obj ) {
+					var type, value, format;
+
+					type = obj.element.get(0).getAttribute( "type" );
+					obj.options.type = type;
+
+					value = obj.element.get(0).getAttribute( "value" );
+					if ( value ) {
+						obj.options.date = new Date( value );
+					}
+				}( this ) );
+			}
+
+			if ( !this.options.format ) {
+				switch ( this.options.type ) {
+				case 'datetime':
+					this.options.format = this._calendar().patterns.d + "\t" + this._calendar().patterns.t;
+					break;
+				case 'date':
+					this.options.format = this._calendar().patterns.d;
+					break;
+				case 'time':
+					this.options.format = this._calendar().patterns.t;
+					break;
+				}
+			}
+
+			if ( !this.options.date ) {
+				this.options.date = new Date();
+			}
+
+			this.element.hide();
+			this.ui = $('<div class="ui-datefield"></div>');
+			$(this.element).after( this.ui );
+
+			this._popup_open = false;
+			this.ui.bind('vclick', function ( e ) {
+				obj._showDataSelector( obj, this, e.target );
+			});
+
+			$.extend( this, {
+				_globalHandlers: [
+					{
+						src: $( window ),
+						handler: {
+							orientationchange: $.proxy( this, "_orientationHandler" )
+						}
+					}
+				]
+			});
+
+			$.each( this._globalHandlers, function( idx, value ) {
+				value.src.bind( value.handler );
+			});
+		},
+		_orientationHandler: function() {
+			var self = this;
+			if( self._popup_open ) {
+				self._popup_open = false;
+				self.container.popupwindow( 'close' );
+			}
+			return false;
+		},
+		_populateDataSelector: function ( field, pat ) {
+			var values,
+				numItems,
+				current,
+				data,
+				range = window.range,
+				local,
+				yearlb,
+				yearhb,
+				day;
+
+			switch ( field ) {
+			case 'hour':
+				if ( pat == 'H' || pat == 'HH' ) {
+					// twentyfour
+					values = range( 0, 23 );
+					data = range( 0, 23 );
+					current = this.options.date.getHours();
+				} else {
+					values = range( 1, 12 );
+					current = this.options.date.getHours() - 1;//11
+					if ( current >= 11 ) {
+						current = current - 12;
+						data = range( 13, 23 );
+						data.push( 12 ); // consider 12:00 am as 00:00
+					} else {
+						data = range( 1, 11 );
+						data.push( 0 );
+					}
+					if ( current < 0 ) {
+						current = 11; // 12:00 or 00:00
+					}
+				}
+				if ( pat.length == 2 ) {
+					// two digit
+					values = values.map( this._makeTwoDigits );
+				}
+				numItems = values.length;
+				break;
+			case 'min':
+			case 'sec':
+				values = range( 0, 59 );
+				if ( pat.length == 2 ) {
+					values = values.map( this._makeTwoDigits );
+				}
+				data = range( 0, 59 );
+				current = ( field == 'min' ? this.options.date.getMinutes() : this.options.date.getSeconds() );
+				numItems = values.length;
+				break;
+			case 'year':
+				yearlb = 1900;
+				yearhb = 2100;
+				data = range( yearlb, yearhb );
+				current = this.options.date.getFullYear() - yearlb;
+				values = range( yearlb, yearhb );
+				numItems = values.length;
+				break;
+			case 'month':
+				switch ( pat.length ) {
+				case 1:
+					values = range( 1, 12 );
+					break;
+				case 2:
+					values = range( 1, 12 ).map( this._makeTwoDigits );
+					break;
+				case 3:
+					values = this._calendar().months.namesAbbr.slice();
+					break;
+				case 4:
+					values = this._calendar().months.names.slice();
+					break;
+				}
+				if ( values.length == 13 ) { // @TODO Lunar calendar support
+					if ( values[12] == "" ) { // to remove lunar calendar reserved space
+						values.pop();
+					}
+				}
+				data = range( 1, values.length );
+				current = this.options.date.getMonth();
+				numItems = values.length;
+				break;
+			case 'day':
+				day = this._daysInMonth[ this.options.date.getMonth() ];
+				if ( day == 28 ) {
+					day += this._isLeapYear( this.options.date.getFullYear() );
+				}
+				values = range( 1, day );
+				if ( pat.length == 2 ) {
+					values = values.map( this._makeTwoDigits );
+				}
+				data = range( 1, day );
+				current = this.options.date.getDate() - 1;
+				numItems = day;
+				break;
+			}
+
+			return {
+				values: values,
+				data: data,
+				numItems: numItems,
+				current: current
+			};
+
+		},
+
+		_showDataSelector: function ( obj, ui, target ) {
+			target = $(target);
+
+			var attr = target.attr("class"),
+				field = attr ? attr.match(/ui-datefield-([\w]*)/) : undefined,
+				pat,
+				data,
+				values,
+				numItems,
+				current,
+				valuesData,
+				html,
+				datans,
+				$ul,
+				$div,
+				$ctx,
+				$li,
+				i,
+				newLeft = 10,
+				self = this;
+
+			if ( !attr ) {
+				return;
+			}
+			if ( !field ) {
+				return;
+			}
+			if ( this._popup_open ) {
+				return;
+			}
+
+			target.not('.ui-datefield-seperator').addClass('ui-datefield-selected');
+
+			pat = target.jqmData('pat');
+			data = obj._populateDataSelector.call( obj, field[1], pat );
+
+			values = data.values;
+			numItems = data.numItems;
+			current = data.current;
+			valuesData = data.data;
+
+			if ( values ) {
+				datans = "data-" + ($.mobile.ns ? ($.mobile.ns + '-') : "") + 'val="';
+				for ( i = 0; i < values.length; i++ ) {
+					html += '<li><a class="ui-link" ' + datans + valuesData[i] + '">' + values[i] + '</a></li>';
+				}
+
+				$ul = $("<ul></ul>");
+				$div = $('<div class="ui-datetimepicker-selector" data-transition="fade" data-fade="false"></div>');
+				$div.append( $ul ).appendTo( ui );
+				$ctx = $div.ctxpopup();
+				$ctx.parents('.ui-popupwindow').addClass('ui-datetimepicker');
+				$li = $(html);
+				$( $li[current] ).addClass("current");
+				$div.jqmData( "list", $li );
+				$div.circularview();
+				if( !obj._reflow ) {
+					obj._reflow = function() {
+						$div.circularview( "reflow" );
+						$div.circularview( 'centerTo', '.current', 0 );
+					}
+					$(window).bind( "resize" , obj._reflow );
+				}
+				if( !obj._close ) {
+					obj._close = function() {
+						$div.trigger( "popupafterclose" );
+					}
+					$(window).bind( "navigate", obj._close );
+				}
+				$ctx.popupwindow( 'open',
+						target.offset().left + ( target.width() / 2 ) - window.pageXOffset ,
+						target.offset().top + target.height() - window.pageYOffset, target.width(), target.height() );
+
+				this.container = $ctx;
+				this._popup_open = true;
+
+				$div.bind('popupafterclose', function ( e ) {
+					if ( obj._reflow ) {
+						$(window).unbind( "resize", obj._reflow );
+						obj._reflow = null;
+					}
+
+					if ( obj._close ) {
+						$(window).unbind( "navigate", obj._close );
+						obj._close = null;
+					}
+
+					if ( !( target.hasClass("in") || target.hasClass("out") ) ) {
+						target.removeClass("ui-datefield-selected");
+					}
+
+					$div.unbind( 'popupafterclose' );
+					$ul.unbind( 'vclick' );
+					$(obj).unbind( 'update' );
+					$ctx.popupwindow( 'destroy' );
+					$div.remove();
+
+					self._popup_open = false;
+				});
+
+				$(obj).bind( 'update', function ( e, val ) {
+					var date = new Date( this.options.date ),
+						month,
+						date_calibration = function () {
+							date.setDate( 1 );
+							date.setDate( date.getDate() - 1 );
+						};
+
+					switch ( field[1] ) {
+					case 'min':
+						date.setMinutes( val );
+						break;
+					case 'hour':
+						date.setHours( val );
+						break;
+					case 'sec':
+						date.setSeconds( val );
+						break;
+					case 'year':
+						month = date.getMonth();
+						date.setFullYear( val );
+
+						if ( date.getMonth() != month ) {
+							date_calibration();
+						}
+						break;
+					case 'month':
+						date.setMonth( val - 1 );
+
+						if ( date.getMonth() == val ) {
+							date_calibration();
+						}
+						break;
+					case 'day':
+						date.setDate( val );
+						break;
+					}
+
+					obj._setDate( date );
+
+					$ctx.popupwindow( 'close' );
+				});
+
+				$ul.bind( 'click', function ( e ) {
+					if ( $(e.target).is('a') ) {
+						$ul.find(".current").removeClass("current");
+						$(e.target).parent().addClass('current');
+						var val = $(e.target).jqmData("val");
+						$(obj).trigger( 'update', val ); // close popup, unselect field
+					}
+				});
+
+				$div.circularview( 'centerTo', '.current', 500 );
+				$div.bind( 'scrollend' , function ( e ) {
+					if ( !obj._reflow ) {
+						obj._reflow = function () {
+							$div.circularview("reflow");
+						};
+						$(window).bind("resize", obj._reflow);
+					}
+				});
+			}
+			return ui;
+		}
+
+	});
+
+	$(document).bind("pagecreate create", function ( e ) {
+		$($.tizen.datetimepicker.prototype.options.initSelector, e.target)
+			.not(":jqmData(role='none'), :jqmData(role='nojs')")
+			.datetimepicker();
+	});
+
+} ( jQuery, this ) );
+
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+} );
+//>>excludeEnd("jqmBuildExclude");

http://git-wip-us.apache.org/repos/asf/cordova-tizen/blob/4ebce38e/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.extendablelist.js
----------------------------------------------------------------------
diff --git a/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.extendablelist.js b/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.extendablelist.js
new file mode 100644
index 0000000..ff9b927
--- /dev/null
+++ b/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.extendablelist.js
@@ -0,0 +1,681 @@
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+//>>description: Listview which can be extended more and more
+//>>label: Extendable list
+//>>group: Tizen:Widgets
+
+define( [ 
+	'jquery',
+	'../jquery.mobile.tizen.scrollview',
+	'libs/jquery.tmpl'
+	], function ( jQuery ) {
+
+//>>excludeEnd("jqmBuildExclude");
+
+/****************************************************************************
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * ***************************************************************************
+ *
+ *	Author: Wongi Lee <wo...@samsung.com>
+*/
+
+/**
+ *	Extendable List Widget for unlimited data.
+ *	To support more then 1,000 items, special list widget developed.
+ *	Fast initialize and append some element into the DOM tree repeatedly.
+ *	DB connection and works like DB cursor.
+ *
+ * HTML Attributes:
+ *
+ *		data-role:	extendablelist
+ *		data-template : jQuery.template ID that populate into extendable list. A button : a <DIV> element with "data-role : button" should be included on data-template.
+ *		data-dbtable : DB Table name. It used as window[DB NAME]. Loaded data should be converted as window object.
+ *		data-extenditems : Number of elements to extend at once.
+ *		
+ *		ID : <UL> element that has "data-role=extendablelist" must have ID attribute.
+ *		Class : <UL> element that has "data-role=extendablelist" should have "vlLoadSuccess" class to guaranty DB loading is completed.
+ *		tmp_load_more : Template ID for "load more" message and button.
+ *
+ *
+ *APIs:
+ *		create ( {
+ *				itemData: function ( idx ) { return json_obj; },
+ *				numItemData: number or function () { return number; },
+ *				cacheItemData: function ( minIdx, maxIdx ) {}
+ *				} )
+ *			: Create a extendable list widget. At this moment, _create method is called.
+ *			args : A collection of options
+ *				itemData: A function that returns JSON object for given index. Mandatory.
+ *				numItemData: Total number of itemData. Mandatory.
+ *				cacheItemData: Extendable list will ask itemData between minIdx and maxIdx.
+ *				    Developers can implement this function for preparing data.
+ *				    Optional.
+ *
+ *Examples:
+ *
+ *		<script id="tmp-3-1-1" type="text/x-jquery-tmpl">
+ *			<li class="ui-li-3-1-1"><span class="ui-li-text-main">${NAME}</span></li>
+ *		</script>
+ *
+ *		<script id="tmp_load_more" type="text/x-jquery-tmpl"> 
+ *			<li class="ui-li-3-1-1" style="text-align:center; margin:0 auto">
+ *				<div data-role="button">Load ${NUM_MORE_ITEMS} more items</div>
+ *			</li>
+ *		</script>
+ *	
+ *		<ul id = "extendable_list_main" data-role="extendablelist" data-extenditems="50" data-template="tmp-3-1-1">
+ *		</ul>
+ *
+ */
+
+/**
+	@class Extendablelist
+	In the Web environment, it is challenging to display a large amount of data in a list, such as displaying a contact list of over 1000 list items. It takes time to display the entire list in HTML and the DOM manipulation is complex.
+	The extendable list widget is used to display a list of unlimited data elements on the screen for better performance. The list is extended if you click the button at the bottom of the list to load more data elements. Extendable lists are based on the jQuery.template plugin as described in the jQuery documentation for jQuery.template plugin.<br/>
+	To add a extendable list widget to the application, use the following code:
+
+			<script id="tmp-3-1-1" type="text/x-jquery-tmpl">
+				<li class="ui-li-3-1-1"><span class="ui-li-text-main">${NAME}</span></li>
+			</script>
+			<script id="tmp_load_more" type="text/x-jquery-tmpl">
+				<li class="ui-li-3-1-1" style="text-align:center; margin:0 auto">
+				<div data-role="button">Load ${NUM_MORE_ITEMS} more items</div>
+				</li>
+			</script>
+			<ul id="extendable_list_main" data-role="extendablelist" data-extenditems="50" data-template="tmp-3-1-1">
+			</ul>
+*/
+/**
+	@property {String} data-role
+	Creates the extendable list view. The value must be set to extendablelist. Only the &lt;ul&gt; element, which a id attribute defined, supports this option. Also, the elLoadSuccess class attribute must be defined in the &lt;ul&gt; element to ensure that loading data from the database is complete.
+*/
+/**
+	@property {String} data-template
+	Specifies the jQuery.template element ID. The jQuery.template must be defined. The template style can use rem units to support scalability. For using the button at the bottom of the list to load more data elements, there must be list view template with the button. The attribute ID must be tmp_load_more.
+*/
+/**
+	@property {Integer} data-extenditems
+	Defines the number of data elements to be extended at a time.
+*/
+( function ( $, undefined ) {
+
+	//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 = {};
+
+	$.widget( "tizen.extendablelist", $.mobile.widget, {
+		options: {
+			theme: "s",
+			countTheme: "c",
+			headerTheme: "b",
+			dividerTheme: "b",
+			splitIcon: "arrow-r",
+			splitTheme: "b",
+			inset: false,
+			id:	"",						/* Extendable list UL elemet's ID */
+			extenditems: 50,			/* Number of append items */
+			childSelector: " li",		/* To support swipe list */
+			dbtable: "",
+			template : "",				/* Template for each list item */
+			loadmore : "tmp_load_more",	/* Template for "Load more" message */
+			scrollview: false,
+			initSelector: ":jqmData(role='extendablelist')"
+		},
+
+		_stylerMouseUp: function () {
+			$( this ).addClass( "ui-btn-up-s" );
+			$( this ).removeClass( "ui-btn-down-s" );
+		},
+
+		_stylerMouseDown: function () {
+			$( this ).addClass( "ui-btn-down-s" );
+			$( this ).removeClass( "ui-btn-up-s" );
+		},
+
+		_stylerMouseOver: function () {
+			$( this ).toggleClass( "ui-btn-hover-s" );
+		},
+
+		_stylerMouseOut: function () {
+			$( this ).toggleClass( "ui-btn-hover-s" );
+			$( this ).addClass( "ui-btn-up-s" );
+			$( this ).removeClass( "ui-btn-down-s" );
+		},
+
+		_pushData: function ( template ) {
+			var o = this.options,
+				t = this,
+				i = 0,
+				myTemplate = $( "#" + template ),
+				loadMoreItems = ( o.extenditems > t._numItemData - t._lastIndex ? t._numItemData - t.lastIndex : o.extenditems ),
+				htmlData;
+
+			for (i = 0; i < loadMoreItems; i++ ) {
+				htmlData = myTemplate.tmpl( t._itemData( i ) );
+				$( o.id ).append( $( htmlData ).attr( 'id', 'li_' + i ) );
+
+				/* Add style */
+				$( o.id + ">" + o.childSelector )
+					.addClass( "ui-btn-up-s" )
+					.bind( "mouseup", t._stylerMouseUp )
+					.bind( "mousedown", t._stylerMouseDown )
+					.bind( "mouseover", t._stylerMouseOver )
+					.bind( "mouseout", t._stylerMouseOut );
+
+				t._lastIndex += 1;
+			}
+
+			/* After push data, re-style extendable list widget */
+			$( o.id ).trigger( "create" );
+		},
+
+		_loadmore: function ( event ) {
+			var t = event.data,	// <li> element
+				o = t.options,
+				i = 0,
+				myTemplate = $( "#" + o.template ),
+				loadMoreItems = ( o.extenditems > t._numItemData - t._lastIndex ? t._numItemData - t._lastIndex : o.extenditems ),
+				htmlData,
+				more_items_to_load,
+				num_next_load_items;
+
+			/* Remove load more message */
+			$( "#load_more_message" ).remove();
+
+			/* Append More Items */
+			for ( i = 0; i < loadMoreItems; i++ ) {
+				htmlData = myTemplate.tmpl( t._itemData( t._lastIndex ) );
+				$( o.id ).append( $( htmlData ).attr( 'id', 'li_' + t._lastIndex ) );
+				t._lastIndex += 1;
+			}
+
+			/* Append "Load more" message on the last of list */
+			if ( t._numItemData > t._lastIndex ) {
+				myTemplate = $( "#" + o.loadmore );
+				more_items_to_load = t._numItemData - t._lastIndex;
+				num_next_load_items = ( o.extenditems <= more_items_to_load ) ? o.extenditems : more_items_to_load;
+				htmlData = myTemplate.tmpl( { NUM_MORE_ITEMS : num_next_load_items } );
+				// Button minimum height(37px)
+				$( o.id ).append( $( htmlData ).attr( 'id', "load_more_message" ).css( 'min-height' , "37px") );
+			}
+
+			$( o.id ).trigger( "create" );
+			$( o.id ).extendablelist( "refresh" );
+		},
+
+		recreate: function ( newArray ) {
+			this._create( {
+				itemData: function ( idx ) { return newArray[ idx ]; },
+				numItemData: newArray.length
+			} );
+		},
+
+		_initList: function (args ) {
+			var t = this,
+				o = this.options,
+				myTemplate,
+				more_items_to_load,
+				num_next_load_items,
+				htmlData;
+
+			/* Make Gen list by template */
+			if ( t._lastIndex <= 0 ) {
+				t._pushData( o.template );
+
+				/* Append "Load more" message on the last of list */
+				if ( t._numItemData > t._lastIndex ) {
+					myTemplate = $( "#" + o.loadmore );
+					more_items_to_load = t._numItemData - t._lastIndex;
+					num_next_load_items = ( o.extenditems <= more_items_to_load) ? o.extenditems : more_items_to_load;
+					htmlData = myTemplate.tmpl( { NUM_MORE_ITEMS : num_next_load_items } );
+					// Button minimum height(37px)
+					$( o.id ).append( $( htmlData ).attr( 'id', "load_more_message" ).css( 'min-height' , "37px") );
+
+					$( "#load_more_message" ).live( "click", t, t._loadmore );
+				} else {
+					/* No more items to load */
+					$( "#load_more_message" ).die();
+					$( "#load_more_message" ).remove();
+				}
+			}
+
+			if ( o.childSelector == " ul" ) {
+				$( o.id + " ul" ).swipelist();
+			}
+
+			$( o.id ).trigger( "create" );
+
+			t.refresh( true );
+		},
+
+		create: function () {
+			var o = this.options;
+
+			/* external API for AJAX callback */
+			this._create.apply( this, arguments );
+		},
+
+		_create: function ( args ) {
+			var t = this,
+				o = this.options,
+				$el = this.element,
+				dbtable_name;
+
+
+			t.destroy();
+
+			$.extend(this, {
+				_itemData: function ( idx ) { return null; },
+				_numItemData: 0,
+				_cacheItemData: function ( minIdx, maxIdx ) { },
+				_lastIndex: 0
+			});
+
+
+			// create listview markup
+			t.element.addClass( function ( i, orig ) {
+				return orig + " ui-listview ui-extendable-list-container" + ( t.options.inset ? " ui-listview-inset ui-corner-all ui-shadow " : "" );
+			});
+
+			o.id = "#" + $el.attr( "id" );
+
+			if ( $el.data( "extenditems" ) ) {
+				o.extenditems = parseInt( $el.data( "extenditems" ), 10 );
+			}
+
+			$( o.id ).bind( "pagehide", function (e) {
+				$( o.id ).empty();
+			});
+
+			/* Scroll view */
+			if ( $( ".ui-scrollview-clip" ).size() > 0) {
+				o.scrollview = true;
+			} else {
+				o.scrollview = false;
+			}
+
+			if ( args ) {
+				if ( !t._loadData( args ) ) {
+					return;
+				}
+			} else {
+				// Legacy support: dbtable
+				console.warn("WARNING: The data interface of extendable list is changed. \nOld data interface(data-dbtable) is still supported, but will be removed in next version. \nPlease fix your code soon!");
+
+				if ( $( o.id ).hasClass( "elLoadSuccess" ) ) {
+					dbtable_name = $el.jqmData('dbtable');
+					o.dbtable = window[ dbtable_name ];
+					if ( !(o.dbtable) ) {
+						o.dbtable = { };
+					}
+					t._itemData = function ( idx ) {
+						return o.dbtable[ idx ];
+					};
+					t._numItemData = o.dbtable.length;
+
+				} else {
+					console.warn("No elLoadSuccess class");
+					return;
+				}
+			}
+
+			if ( $el.data( "template" ) ) {
+				o.template = $el.data( "template" );
+
+				/* to support swipe list, <li> or <ul> can be main node of extendable list. */
+				if ( $el.data( "swipelist" ) == true ) {
+					o.childSelector = " ul";
+				} else {
+					o.shildSelector = " li";
+				}
+			}
+			t._initList( args );
+		},
+
+		_loadData : function ( args ) {
+			var self = this;
+
+			if ( args.itemData && typeof args.itemData == 'function'  ) {
+				self._itemData = args.itemData;
+			} else {
+				return false;
+			}
+			if ( args.numItemData ) {
+				if ( typeof args.numItemData == 'function' ) {
+					self._numItemData = args.numItemData( );
+				} else if ( typeof args.numItemData == 'number' ) {
+					self._numItemData = args.numItemData;
+				} else {
+					return false;
+				}
+			} else {
+				return false;
+			}
+			return true;
+		},
+
+
+		destroy : function () {
+			var o = this.options,
+				eOTAL_ITEMS = 0,
+				last_index = 0;
+
+			$( o.id ).empty();
+
+			$( "#load_more_message" ).die();
+		},
+
+		_itemApply: function ( $list, item ) {
+			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" );
+
+			// TODO class has to be defined in markup
+			item.find( "h1, h2, h3, h4, h5, h6" ).addClass( "ui-li-heading" ).end()
+				.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
+				});
+		},
+
+		_removeCorners: function ( li, which ) {
+			var top = "ui-corner-top ui-corner-tr ui-corner-tl",
+				bot = "ui-corner-bottom ui-corner-br ui-corner-bl";
+
+			li = li.add( li.find( ".ui-btn-inner, .ui-li-link-alt, .ui-li-thumb" ) );
+
+			if ( which === "top" ) {
+				li.removeClass( top );
+			} else if ( which === "bottom" ) {
+				li.removeClass( bot );
+			} else {
+				li.removeClass( top + " " + bot );
+			}
+		},
+
+		_refreshCorners: function ( create ) {
+			var $li,
+				$visibleli,
+				$topli,
+				$bottomli;
+
+			if ( this.options.inset ) {
+				$li = this.element.children( "li" );
+				// 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" );
+
+				this._removeCorners( $li );
+
+				// 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" )
+						.not( ".ui-li-icon" )
+						.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" )
+						.not( ".ui-li-icon" )
+						.addClass( "ui-corner-bl" );
+			}
+			this.element.trigger( "updatelayout" );
+		},
+
+		refresh: function ( create ) {
+			this.parentPage = this.element.closest( ".ui-page" );
+			this._createSubPages();
+
+			var o = this.options,
+				$list = this.element,
+				self = this,
+				dividertheme = $list.jqmData( "dividertheme" ) || o.dividerTheme,
+				listsplittheme = $list.jqmData( "splittheme" ),
+				listspliticon = $list.jqmData( "spliticon" ),
+				li = $list.children( "li" ),
+				counter = $.support.cssPseudoElement || !$.nodeName( $list[ 0 ], "ol" ) ? 0 : 1,
+				item,
+				itemClass,
+				itemTheme,
+				a,
+				last,
+				splittheme,
+				countParent,
+				icon,
+				pos,
+				numli;
+
+			if ( counter ) {
+				$list.find( ".ui-li-dec" ).remove();
+			}
+
+			for ( pos = 0, numli = li.length; pos < numli; pos++ ) {
+				item = li.eq( pos );
+				itemClass = "ui-li";
+
+				// If we're creating the element, we update it regardless
+				if ( create || !item.hasClass( "ui-li" ) ) {
+					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",*/
+							icon: false,	/* Remove unnecessary arrow icon */
+							theme: itemTheme
+						});
+
+						if ( ( icon != false ) && ( a.length == 1 ) ) {
+							item.addClass( "ui-li-has-arrow" );
+						}
+
+						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)
+								.attr( "title", last.getEncodedText() )
+								.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;
+					}
+				}
+
+				if ( counter && itemClass.indexOf( "ui-li-divider" ) < 0 ) {
+					countParent = item.is( ".ui-li-static:first" ) ? item : item.find( ".ui-link-inherit" );
+
+					countParent.addClass( "ui-li-jsnumbering" )
+						.prepend( "<span class='ui-li-dec'>" + (counter++) + ". </span>" );
+				}
+
+				item.add( item.children( ".ui-btn-inner" ) ).addClass( itemClass );
+
+				self._itemApply( $list, item );
+			}
+
+			this._refreshCorners( create );
+		},
+
+		//create a string for ID/subpage url creation
+		_idStringEscape: function ( str ) {
+			return str.replace(/\W/g , "-");
+
+		},
+
+		_createSubPages: function () {
+			var parentList = this.element,
+				parentPage = parentList.closest( ".ui-page" ),
+				parentUrl = parentPage.jqmData( "url" ),
+				parentId = parentUrl || parentPage[ 0 ][ $.expando ],
+				parentListId = parentList.attr( "id" ),
+				o = this.options,
+				dns = "data-" + $.mobile.ns,
+				self = this,
+				persistentFooterID = parentPage.find( ":jqmData(role='footer')" ).jqmData( "id" ),
+				hasSubPages,
+				newRemove;
+
+			if ( typeof listCountPerPage[ parentId ] === "undefined" ) {
+				listCountPerPage[ parentId ] = -1;
+			}
+
+			parentListId = parentListId || ++listCountPerPage[ parentId ];
+
+			$( parentList.find( "li>ul, li>ol" ).toArray().reverse() ).each(function ( i ) {
+				var self = this,
+					list = $( this ),
+					listId = list.attr( "id" ) || parentListId + "-" + i,
+					parent = list.parent(),
+					nodeEls,
+					title = nodeEls.first().getEncodedText(),//url limits to first 30 chars of text
+					id = ( parentUrl || "" ) + "&" + $.mobile.subPageUrlKey + "=" + listId,
+					theme = list.jqmData( "theme" ) || o.theme,
+					countTheme = list.jqmData( "counttheme" ) || parentList.jqmData( "counttheme" ) || o.countTheme,
+					newPage,
+					anchor;
+
+				nodeEls = $( list.prevAll().toArray().reverse() );
+				nodeEls = nodeEls.length ? nodeEls : $( "<span>" + $.trim(parent.contents()[ 0 ].nodeValue) + "</span>" );
+
+				//define hasSubPages for use in later removal
+				hasSubPages = true;
+
+				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 + "'>" ) : "" )
+								.parent()
+									.appendTo( $.mobile.pageContainer );
+
+				newPage.page();
+
+				anchor = parent.find('a:first');
+
+				if ( !anchor.length ) {
+					anchor = $( "<a/>" ).html( nodeEls || title ).prependTo( parent.empty() );
+				}
+
+				anchor.attr( "href", "#" + id );
+
+			}).extendablelist();
+
+			// on pagehide, remove any nested pages along with the parent page, as long as they aren't active
+			// and aren't embedded
+			if ( hasSubPages &&
+					parentPage.is( ":jqmData(external-page='true')" ) &&
+					parentPage.data( "page" ).options.domCache === false ) {
+
+				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
+				parentPage
+					.unbind( "pagehide.remove" )
+					.bind( "pagehide.remove", newRemove);
+			}
+		},
+
+		// TODO sort out a better way to track sub pages of the extendable listview this is brittle
+		childPages: function () {
+			var parentUrl = this.parentPage.jqmData( "url" );
+
+			return $( ":jqmData(url^='" +  parentUrl + "&" + $.mobile.subPageUrlKey + "')" );
+		}
+	});
+
+	//auto self-init widgets
+	$( document ).bind( "pagecreate create", function ( e ) {
+		$( $.tizen.extendablelist.prototype.options.initSelector, e.target ).extendablelist();
+	});
+
+}( jQuery ));
+
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+} );
+//>>excludeEnd("jqmBuildExclude");

http://git-wip-us.apache.org/repos/asf/cordova-tizen/blob/4ebce38e/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.fastscroll.js
----------------------------------------------------------------------
diff --git a/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.fastscroll.js b/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.fastscroll.js
new file mode 100644
index 0000000..939cac0
--- /dev/null
+++ b/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.fastscroll.js
@@ -0,0 +1,633 @@
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+//>>description: Shows list index and scroll to the index directly
+//>>label: Fastscroll
+//>>group: Tizen:Widgets
+
+define( [ 
+	'jquery',
+	'../jquery.mobile.tizen.scrollview'
+	], function ( jQuery ) {
+
+//>>excludeEnd("jqmBuildExclude");
+
+/*
+ * jQuery Mobile Widget @VERSION
+ *
+ * This software is licensed under the MIT licence (as defined by the OSI at
+ * http://www.opensource.org/licenses/mit-license.php)
+ *
+ * ***************************************************************************
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2011 by Intel Corporation Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * ***************************************************************************
+ *
+ * Authors: Elliot Smith <el...@intel.com>
+ *		 Yonghwi Park <yo...@samsung.com>
+ */
+
+// fastscroll is a scrollview controller, which binds
+// a scrollview to a a list of short cuts; the shortcuts are built
+// from the text on dividers in the list. Clicking on a shortcut
+// instantaneously jumps the scrollview to the selected list divider;
+// mouse movements on the shortcut column move the scrollview to the
+// list divider matching the text currently under the touch; a popup
+// with the text currently under the touch is also displayed.
+//
+// To apply, add the attribute data-fastscroll="true" to a listview
+// (a <ul> or <ol> element inside a page). Alternatively, call
+// fastscroll() on an element.
+//
+// The closest element with class ui-scrollview-clip is used as the
+// scrollview to be controlled.
+//
+// If a listview has no dividers or a single divider, the widget won't
+// display.
+
+/**
+	@class fastscroll
+	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.
+
+	To add a shortcut scroll widget to the application, use the following code:
+
+		<div class="content" data-role="content" data-scroll="y">
+			<ul id="contacts" data-role="listview" data-fastscroll="true">
+				<li>Anton</li>
+			</ul>
+		</div>
+
+	For the shortcut scroll widget to be visible, the parent list view must have multiple list dividers.
+*/
+
+/**
+	@property {Boolean}  data-fastscroll
+	When set to true, creates a shortcut scroll using the HTML unordered list (&lt;ul&gt;) element.
+*/
+/**
+	@method fastscroll
+	The shortcut scroll is created for the closest list view with the ui-scrollview-clip class.
+*/
+/**
+	@method indexString
+	The indexString method is used to get (if no value is defined) or set the string to present the index.
+
+		<div class="content" data-role="content" data-scroll="y">
+			ul id="contacts" data-role="listview" data-fastscroll="true">
+				<li data-role="list-divider">A</li>
+				<li>Anton</li>
+			</ul>
+		</div>
+
+		$(".selector").fastscroll( "indexString" [, indexAlphabet] );
+*/
+(function ( $, undefined ) {
+
+	$.widget( "tizen.fastscroll", $.mobile.widget, {
+		options: {
+			initSelector: ":jqmData(fastscroll)"
+		},
+
+		_primaryLanguage: null,
+		_secondLanguage: null,
+		_dividerMap: {},
+		_charSet: null,
+
+		_create: function () {
+			var $el = this.element,
+				self = this,
+				$popup,
+				page = $el.closest( ':jqmData(role="page")' ),
+				jumpToDivider;
+
+			this.scrollview = $el.addClass( 'ui-fastscroll-target' ).closest( '.ui-scrollview-clip' );
+			this.shortcutsContainer = $( '<div class="ui-fastscroll" aria-label="Fast scroll bar, double tap to fast scroll mode" tabindex="0"/>' );
+			this.shortcutsList = $( '<ul aria-hidden="true"></ul>' );
+
+			// popup for the hovering character
+			this.scrollview.append($( '<div class="ui-fastscroll-popup"></div>' ) );
+			$popup = this.scrollview.find( '.ui-fastscroll-popup' );
+
+			this.shortcutsContainer.append( this.shortcutsList );
+			this.scrollview.append( this.shortcutsContainer );
+
+			// find the bottom of the last item in the listview
+			this.lastListItem = $el.children().last();
+
+			// remove scrollbars from scrollview
+			this.scrollview.find( '.ui-scrollbar' ).hide();
+
+			this.jumpToDivider = function ( divider ) {
+				// get the vertical position of the divider (so we can scroll to it)
+				var dividerY = $( divider ).position().top,
+					// find the bottom of the last list item
+					bottomOffset = self.lastListItem.outerHeight( true ) + self.lastListItem.position().top,
+					scrollviewHeight = self.scrollview.height(),
+
+				// check that after the candidate scroll, the bottom of the
+				// last item will still be at the bottom of the scroll view
+				// and not some way up the page
+					maxScroll = bottomOffset - scrollviewHeight,
+					dstOffset;
+
+				dividerY = ( dividerY > maxScroll ? maxScroll : dividerY );
+
+				// don't apply a negative scroll, as this means the
+				// divider should already be visible
+				dividerY = Math.max( dividerY, 0 );
+
+				// apply the scroll
+				self.scrollview.scrollview( 'scrollTo', 0, -dividerY );
+
+				dstOffset = self.scrollview.offset();
+			};
+
+			this.shortcutsList
+			// bind mouse over so it moves the scroller to the divider
+				.bind( 'touchstart mousedown vmousedown touchmove vmousemove vmouseover', function ( e ) {
+					// Get coords relative to the element
+					var coords = $.mobile.tizen.targetRelativeCoordsFromEvent( e ),
+						shortcutsListOffset = self.shortcutsList.offset();
+
+					self.shortcutsContainer.addClass( "ui-fastscroll-hover" );
+
+					// If the element is a list item, get coordinates relative to the shortcuts list
+					if ( e.target.tagName.toLowerCase() === "li" ) {
+						coords.x += $( e.target ).offset().left - shortcutsListOffset.left;
+						coords.y += $( e.target ).offset().top  - shortcutsListOffset.top;
+					}
+
+					if ( e.target.tagName.toLowerCase() === "span" ) {
+						coords.x += $( e.target ).parent().offset().left - shortcutsListOffset.left;
+						coords.y += $( e.target ).parent().offset().top  - shortcutsListOffset.top;
+					}
+
+					self.shortcutsList.find( 'li' ).each( function () {
+						var listItem = $( this );
+						$( listItem )
+							.removeClass( "ui-fastscroll-hover" )
+							.removeClass( "ui-fastscroll-hover-down" );
+					});
+					// Hit test each list item
+					self.shortcutsList.find( 'li' ).each( function () {
+						var listItem = $( this ),
+							l = listItem.offset().left - shortcutsListOffset.left,
+							t = listItem.offset().top  - shortcutsListOffset.top,
+							r = l + Math.abs(listItem.outerWidth( true ) ),
+							b = t + Math.abs(listItem.outerHeight( true ) ),
+							unit,
+							baseTop,
+							baseBottom,
+							omitSet,
+							i;
+
+						if ( coords.x >= l && coords.x <= r && coords.y >= t && coords.y <= b ) {
+							if ( listItem.text() !== "." ) {
+								self._hitItem( listItem );
+							} else {
+								omitSet = listItem.data( "omitSet" );
+								unit = ( b - t ) / omitSet.length;
+								for ( i = 0; i < omitSet.length; i++ ) {
+									baseTop = t + ( i * unit );
+									baseBottom = baseTop + unit;
+									if ( coords.y >= baseTop && coords.y <= baseBottom ) {
+										self._hitOmitItem( listItem, omitSet.charAt( i ) );
+									}
+								}
+							}
+							return false;
+						}
+						return true;
+					} );
+
+					e.preventDefault();
+					e.stopPropagation();
+				} )
+				// bind mouseout of the fastscroll container to remove popup
+				.bind( 'touchend mouseup vmouseup vmouseout', function () {
+					$popup.hide();
+					$( ".ui-fastscroll-hover" ).removeClass( "ui-fastscroll-hover" );
+					$( ".ui-fastscroll-hover-first-item" ).removeClass( "ui-fastscroll-hover-first-item" );
+					$( ".ui-fastscroll-hover-down" ).removeClass( "ui-fastscroll-hover-down" );
+					self.shortcutsContainer.removeClass( "ui-fastscroll-hover" );
+				} );
+
+			if ( page && !( page.is( ':visible' ) ) ) {
+				page.bind( 'pageshow', function () { self.refresh(); } );
+			} else {
+				self.refresh();
+			}
+
+			// refresh the list when dividers are filtered out
+			$el.bind( 'updatelayout', function () {
+				self.refresh();
+			} );
+		},
+
+		_findClosestDivider: function ( targetChar ) {
+			var i,
+				dividerMap = this._dividerMap,
+				charSet = this._charSet,
+				charSetLen = charSet.length,
+				targetIdx = charSet.indexOf( targetChar ),
+				lastDivider,
+				subDivider = null;
+
+			for ( i = 0; i < targetIdx; ++i ) {
+				lastDivider = dividerMap[ charSet.charAt( i ) ];
+				if ( lastDivider !== undefined ) {
+					subDivider = lastDivider;
+				}
+			}
+			if ( !subDivider ) {
+				for ( ++i; i < charSetLen; ++i ) {
+					lastDivider = dividerMap[ charSet.charAt( i ) ];
+					if ( lastDivider !== undefined ) {
+						subDivider = lastDivider;
+						break;
+					}
+				}
+			}
+			return subDivider;
+		},
+
+		_hitOmitItem: function ( listItem, text ) {
+			var $popup = this.scrollview.find( '.ui-fastscroll-popup' ),
+				divider;
+
+			divider = this._dividerMap[ text ] || this._findClosestDivider( text );
+			if ( typeof divider !== "undefined" ) {
+				this.jumpToDivider( $( divider ) );
+			}
+
+			$popup.text( text ).show();
+
+			$( listItem ).addClass( "ui-fastscroll-hover" );
+			if ( listItem.index() === 0 ) {
+				$( listItem ).addClass( "ui-fastscroll-hover-first-item" );
+			}
+			$( listItem ).siblings().eq( listItem.index() ).addClass( "ui-fastscroll-hover-down" );
+		},
+
+		_hitItem: function ( listItem  ) {
+			var $popup = this.scrollview.find( '.ui-fastscroll-popup' ),
+				text = listItem.text(),
+				divider;
+
+			if ( text === "#" ) {
+				divider = this._dividerMap.number;
+			} else {
+				divider = this._dividerMap[ text ] || this._findClosestDivider( text );
+			}
+
+			if ( typeof divider !== "undefined" ) {
+				this.jumpToDivider( $( divider ) );
+			}
+
+			$popup.text( text ).show();
+
+			$( listItem ).addClass( "ui-fastscroll-hover" );
+			if ( listItem.index() === 0 ) {
+				$( listItem ).addClass( "ui-fastscroll-hover-first-item" );
+			}
+			$( listItem ).siblings().eq( listItem.index() ).addClass( "ui-fastscroll-hover-down" );
+		},
+
+		_focusItem: function ( listItem ) {
+			var self = this,
+				$popup = self.scrollview.find( '.ui-fastscroll-popup' );
+
+			listItem.focusin( function ( e ) {
+				self.shortcutsList.attr( "aria-hidden", false );
+				self._hitItem( listItem );
+			}).focusout( function ( e ) {
+				self.shortcutsList.attr( "aria-hidden", true );
+				$popup.hide();
+				$( ".ui-fastscroll-hover" ).removeClass( "ui-fastscroll-hover" );
+				$( ".ui-fastscroll-hover-first-item" ).removeClass( "ui-fastscroll-hover-first-item" );
+				$( ".ui-fastscroll-hover-down" ).removeClass( "ui-fastscroll-hover-down" );
+			});
+		},
+
+		_contentHeight: function () {
+			var self = this,
+				$content = $( '.ui-scrollview-clip' ),
+				header = null,
+				footer = null,
+				paddingValue = 0,
+				clipSize = $( window ).height();
+
+			if ( $content.hasClass( "ui-content" ) ) {
+				paddingValue = parseInt( $content.css( "padding-top" ), 10 );
+				clipSize = clipSize - ( paddingValue || 0 );
+				paddingValue = parseInt( $content.css( "padding-bottom" ), 10 );
+				clipSize = clipSize - ( paddingValue || 0 );
+				header = $content.siblings( ".ui-header:visible" );
+				footer = $content.siblings( ".ui-footer:visible" );
+
+				if ( header ) {
+					if ( header.outerHeight( true ) === null ) {
+						clipSize = clipSize - ( $( ".ui-header" ).outerHeight() || 0 );
+					} else {
+						clipSize = clipSize - header.outerHeight( true );
+					}
+				}
+				if ( footer ) {
+					clipSize = clipSize - footer.outerHeight( true );
+				}
+			} else {
+				clipSize = $content.height();
+			}
+			return clipSize;
+		},
+
+		_omit: function ( numOfItems, maxNumOfItems ) {
+			var maxGroupNum = parseInt( ( maxNumOfItems - 1 ) / 2, 10 ),
+				numOfExtraItems = numOfItems - maxNumOfItems,
+				groupPos = [],
+				omitInfo = [],
+				groupPosLength,
+				group,
+				size,
+				i;
+
+			if ( ( maxNumOfItems < 3 ) || ( numOfItems <= maxNumOfItems ) ) {
+				return;
+			}
+
+			if ( numOfExtraItems >= maxGroupNum ) {
+				size = 2;
+				group = 1;
+				groupPosLength = maxGroupNum;
+			} else {
+				size = maxNumOfItems / ( numOfExtraItems + 1 );
+				group = size;
+				groupPosLength = numOfExtraItems;
+			}
+
+			for ( i = 0; i < groupPosLength; i++ ) {
+				groupPos.push( parseInt( group, 10 ) );
+				group += size;
+			}
+
+			for ( i = 0; i < maxNumOfItems; i++ ) {
+				omitInfo.push( 1 );
+			}
+
+			for ( i = 0; i < numOfExtraItems; i++ ) {
+				omitInfo[ groupPos[ i % maxGroupNum ] ]++;
+			}
+
+			return omitInfo;
+		},
+
+		_createDividerMap: function () {
+			var primaryCharacterSet = this._primaryLanguage ? this._primaryLanguage.replace( /,/g, "" ) : null,
+				secondCharacterSet = this._secondLanguage ? this._secondLanguage.replace( /,/g, "" ) : null,
+				numberSet = "0123456789",
+				dividers = this.element.find( '.ui-li-divider' ),
+				map = {},
+				matchToDivider,
+				makeCharacterSet,
+				indexChar,
+				i;
+
+			matchToDivider = function ( index, divider ) {
+				if ( $( divider ).text() === indexChar ) {
+					map[ indexChar ] = divider;
+				}
+			};
+
+			makeCharacterSet = function ( index, divider ) {
+				primaryCharacterSet += $( divider ).text();
+			};
+
+			if ( primaryCharacterSet === null ) {
+				primaryCharacterSet = "";
+				dividers.each( makeCharacterSet );
+			}
+
+			for ( i = 0; i < primaryCharacterSet.length; i++ ) {
+				indexChar = primaryCharacterSet.charAt( i );
+				dividers.each( matchToDivider );
+			}
+
+			if ( secondCharacterSet !== null ) {
+				for ( i = 0; i < secondCharacterSet.length; i++ ) {
+					indexChar = secondCharacterSet.charAt( i );
+					dividers.each( matchToDivider );
+				}
+			}
+
+			dividers.each( function ( index, divider ) {
+				if ( numberSet.search( $( divider ).text() ) !== -1  ) {
+					map.number = divider;
+					return false;
+				}
+			});
+
+			this._dividerMap = map;
+			this._charSet = primaryCharacterSet + secondCharacterSet;
+		},
+
+		indexString: function ( indexAlphabet ) {
+			var self = this,
+				characterSet = [];
+
+			if ( typeof indexAlphabet === "undefined" ) {
+				return self._primaryLanguage + ":" + self._secondLanguage;
+			}
+
+			characterSet = indexAlphabet.split( ":" );
+			self._primaryLanguage = characterSet[ 0 ];
+			if ( characterSet.length === 2 ) {
+				self._secondLanguage = characterSet[ 1 ];
+			}
+		},
+
+		refresh: function () {
+			var self = this,
+				primaryCharacterSet = self._primaryLanguage ? self._primaryLanguage.replace( /,/g, "" ) : null,
+				secondCharacterSet = self._secondLanguage ? self._secondLanguage.replace( /,/g, "" ) : null,
+				contentHeight = self._contentHeight(),
+				shapItem = $( '<li tabindex="0" aria-label="double to move Number list"><span aria-hidden="true">#</span><span aria-label="Number"/></li>' ),
+				$popup = this.scrollview.find( '.ui-fastscroll-popup' ),
+				omitIndex = 0,
+				makeCharacterSet,
+				makeOmitSet,
+				itemHandler,
+				containerHeight,
+				shortcutsItems,
+				shortcutItem,
+				shortcutsTop,
+				minClipHeight,
+				maxNumOfItems,
+				numOfItems,
+				minHeight,
+				omitInfo,
+				dividers,
+				listItems,
+				emptySize,
+				correction,
+				indexChar,
+				lastIndex,
+				seconds,
+				height,
+				size,
+				i;
+
+			makeCharacterSet = function ( index, divider ) {
+				primaryCharacterSet += $( divider ).text();
+			};
+
+			makeOmitSet = function ( index, length ) {
+				var count,
+					omitSet = "";
+
+				for ( count = 0; count < length; count++ ) {
+					omitSet += primaryCharacterSet[ index + count ];
+				}
+
+				return omitSet;
+			};
+
+			self._createDividerMap();
+
+			self.shortcutsList.find( 'li' ).remove();
+
+			// get all the dividers from the list and turn them into shortcuts
+			dividers = self.element.find( '.ui-li-divider' );
+
+			// get all the list items
+			listItems = self.element.find('li').not('.ui-li-divider');
+
+			// only use visible dividers
+			dividers = dividers.filter( ':visible' );
+			listItems = listItems.filter( ':visible' );
+
+			if ( dividers.length < 2 ) {
+				self.shortcutsList.hide();
+				return;
+			}
+
+			self.shortcutsList.show();
+			self.lastListItem = listItems.last();
+			self.shortcutsList.append( shapItem );
+			self._focusItem( shapItem );
+
+			if ( primaryCharacterSet === null ) {
+				primaryCharacterSet = "";
+				dividers.each( makeCharacterSet );
+			}
+
+			minHeight = shapItem.outerHeight( true );
+			maxNumOfItems = parseInt( contentHeight / minHeight - 1, 10 );
+			numOfItems = primaryCharacterSet.length;
+
+			maxNumOfItems = secondCharacterSet ? maxNumOfItems - 2 : maxNumOfItems;
+
+			if ( maxNumOfItems < 3 ) {
+				shapItem.remove();
+				return;
+			}
+
+			omitInfo = self._omit( numOfItems, maxNumOfItems );
+
+			for ( i = 0; i < primaryCharacterSet.length; i++ ) {
+				indexChar = primaryCharacterSet.charAt( i );
+				shortcutItem = $( '<li tabindex="0" aria-label="double to move ' + indexChar + ' list">' + indexChar + '</li>' );
+
+				self._focusItem( shortcutItem );
+
+				if ( typeof omitInfo !== "undefined" && omitInfo[ omitIndex ] > 1 ) {
+					shortcutItem = $( '<li>.</li>' );
+					shortcutItem.data( "omitSet",  makeOmitSet( i, omitInfo[ omitIndex ] ) );
+					i += omitInfo[ omitIndex ] - 1;
+				}
+
+				self.shortcutsList.append( shortcutItem );
+				omitIndex++;
+			}
+
+			if ( secondCharacterSet !== null ) {
+				lastIndex = secondCharacterSet.length - 1;
+				seconds = [];
+
+				seconds.push( secondCharacterSet.charAt( 0 ) );
+				seconds.push( secondCharacterSet.charAt( lastIndex ) );
+
+				for ( i = 0; i < seconds.length; i++ ) {
+					indexChar = seconds[ i ];
+					shortcutItem = $( '<li tabindex="0" aria-label="double to move ' + indexChar + ' list">' + indexChar + '</li>' );
+
+					self._focusItem( shortcutItem );
+					shortcutItem.bind( 'vclick', itemHandler );
+					self.shortcutsList.append( shortcutItem );
+				}
+			}
+
+			containerHeight = self.shortcutsContainer.outerHeight( true );
+			emptySize = contentHeight - containerHeight;
+			shortcutsItems = self.shortcutsList.children();
+			size = parseInt( emptySize / shortcutsItems.length, 10 );
+			correction = emptySize - ( shortcutsItems.length * size );
+
+			if ( emptySize > 0 ) {
+				shortcutsItems.each( function ( index, item ) {
+					height = $( item ).height() + size;
+					if ( correction !== 0 ) {
+						height += 1;
+						correction -= 1;
+					}
+					$( item ).css( {
+						height: height,
+						lineHeight: height + "px"
+					} );
+				} );
+			}
+
+			// position the shortcut flush with the top of the first list divider
+			shortcutsTop = dividers.first().position().top;
+			self.shortcutsContainer.css( 'top', shortcutsTop );
+
+			// make the scrollview clip tall enough to show the whole of the shortcutslist
+			minClipHeight = shortcutsTop + self.shortcutsContainer.outerHeight() + 'px';
+			self.scrollview.css( 'min-height', minClipHeight );
+
+			$popup.text( "M" ) // Popup size is determined based on "M".
+				.width( $popup.height() )
+				.css( { marginLeft: -( $popup.outerWidth() / 2 ),
+					marginTop: -( $popup.outerHeight() / 2 ) } );
+		}
+	} );
+
+	$( document ).bind( "pagecreate create", function ( e ) {
+		$( $.tizen.fastscroll.prototype.options.initSelector, e.target )
+			.not( ":jqmData(role='none'), :jqmData(role='nojs')" )
+			.fastscroll();
+	} );
+
+	$( window ).bind( "resize orientationchange", function ( e ) {
+		$( ".ui-page-active .ui-fastscroll-target" ).fastscroll( "refresh" );
+	} );
+} ( jQuery ) );
+
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+} );
+//>>excludeEnd("jqmBuildExclude");