[TemporaryStorage] add files required for SDK build
[samples/web/TemporaryStorage.git] / tizen-web-ui-fw / latest / js / src / widgets / jquery.mobile.tizen.datetimepicker.js
1
2 /*global Globalize:false, range:false, regexp:false*/
3 /*
4  * jQuery Mobile Widget @VERSION
5  *
6  * This software is licensed under the MIT licence (as defined by the OSI at
7  * http://www.opensource.org/licenses/mit-license.php)
8  *
9  * ***************************************************************************
10  * Copyright (C) 2011 by Intel Corporation Ltd.
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a
13  * copy of this software and associated documentation files (the "Software"),
14  * to deal in the Software without restriction, including without limitation
15  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16  * and/or sell copies of the Software, and to permit persons to whom the
17  * Software is furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included in
20  * all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28  * DEALINGS IN THE SOFTWARE.
29  * ***************************************************************************
30  *
31  * Authors: Salvatore Iovene <salvatore.iovene@intel.com>
32  *                      Daehyon Jung <darrenh.jung@samsung.com>
33  */
34
35 /**
36  * datetimepicker is a widget that lets the user select a date and/or a 
37  * time. If you'd prefer use as auto-initialization of form elements, 
38  * use input elements with type=date/time/datetime within form tag
39  * as same as other form elements.
40  * 
41  * HTML Attributes:
42  * 
43  *      data-role: 'datetimepicker'
44  *      data-format: date format string. e.g) "MMM dd yyyy, HH:mm"
45  *      type: 'date', 'datetime', 'time'
46  *      value: pre-set value. only accepts ISO date string. e.g) "2012-05-04", "2012-05-04T01:02:03+09:00" 
47  *      data-date: any date/time string "new Date()" accepts.
48  *
49  * Options:
50  *      type: 'date', 'datetime', 'time'
51  *      format: see data-format in HTML Attributes.
52  *      value: see value in HTML Attributes.
53  *      date: preset value as JavaScript Date Object representation.
54  *
55  * APIs:
56  *      value( datestring )
57  *              : Set date/time to 'datestring'.
58  *      value()
59  *              : Get current selected date/time as W3C DTF style string.
60  *      getValue() - replaced with 'value()'
61  *              : same as value()
62  *      setValue( datestring ) - replaced with 'value(datestring)'
63  *              : same as value( datestring )
64  *      changeTypeFormat( type, format ) - deprecated
65  *              : Change Type and Format options. use datetimepicker( "option", "format" ) instead
66  *
67  * Events:
68  *      date-changed: Raised when date/time was changed. Date-changed event will be deprecated
69  *
70  * Examples:
71  *      <ul data-role="listview">
72  *              <li class="ui-li-3-2-2">
73  *                      <span class="ui-li-text-main">
74  *                              <input type="datetime" name="demo-date" id="demo-date" 
75  *                                      data-format="MMM dd yyyy hh:mm tt"/>
76  *                      </span>
77  *                      <span class="ui-li-text-sub">
78  *                              Date/Time Picker - <span id="selected-date1"><em>(select a date first)</em></span>
79  *                      </span>
80  *              </li>
81  *              <li class="ui-li-3-2-2">
82  *                      <span class="ui-li-text-main">
83  *                              <input type="date" name="demo-date2" id="demo-date2"/>
84  *                      </span>
85  *                      <span class="ui-li-text-sub">
86  *                              Date Picker  - <span id="selected-date2"><em>(select a date first)</em></span>
87  *                      </span>
88  *              </li>
89  *              <li class="ui-li-3-2-2">
90  *                      <span class="ui-li-text-main">
91  *                              <input type="time" name="demo-date3" id="demo-date3"/>
92  *                      </span>
93  *                      <span class="ui-li-text-sub">
94  *                              Time Picker - <span id="selected-date3"><em>(select a date first)</em></span>
95  *                      </span>
96  *              </li>
97  *      </ul>
98  * How to get a return value:
99  * ==========================
100  * Bind to the 'date-changed' event, e.g.:
101  *    $("#myDatetimepicker").bind("change", function() {
102  *                      // your code
103  *    });
104  */
105
106 /**
107         @class DateTimePicker
108         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:
109
110                         <li class="ui-li-dialogue ui-datetime">
111                                 <div class="ui-datetime-text-main">
112                                         <input type="datetime" data-format="MMM dd yyyy hh:mm:ss" name="demo-date" id="demo-date" />
113                                 </div>
114                                 <div class="ui-li-text-sub">Date/Time Picker
115                                         <span id="selected-date1"><em>(select a date first)</em></span>
116                                 </div>
117                         </li>
118 */
119
120
121 ( function ( $, window, undefined ) {
122         $.widget( "tizen.datetimepicker", $.tizen.widgetex, {
123
124                 options: {
125                         type: null, // date, time, datetime applicable
126                         format: null,
127                         date: null,
128                         initSelector: "input[type='date'], input[type='datetime'], input[type='time'], :jqmData(role='datetimepicker')"
129                 },
130
131                 container : null,
132
133                 _calendar: function () {
134                         return window.Globalize.culture().calendars.standard;
135                 },
136
137                 _value: {
138                         attr: "data-" + ( $.mobile.ns || "" ) + "date",
139                         signal: "date-changed"
140                 },
141
142                 _daysInMonth: [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ],
143
144                 _isLeapYear: function ( year ) {
145                         return year % 4 ? 0 : ( year % 100 ? 1 : ( year % 400 ? 0 : 1 ) );
146                 },
147
148                 _makeTwoDigits: function ( val ) {
149                         var ret = val.toString(10);
150                         if ( val < 10 ) {
151                                 ret = "0" + ret;
152                         }
153                         return ret;
154                 },
155
156                 _setType: function ( type ) {
157                         //datetime, date, time
158                         switch (type) {
159                         case 'datetime':
160                         case 'date':
161                         case 'time':
162                                 this.options.type = type;
163                                 break;
164                         default:
165                                 this.options.type = 'datetime';
166                                 break;
167                         }
168
169                         this.element.attr( "data-" + ( $.mobile.ns ? $.mobile.ns + "-" : "" ) + "type", this.options.type );
170                         return this.options.type;
171                 },
172
173                 _setFormat: function ( format ) {
174                         if ( this.options.format != format ) {
175                                 this.options.format = format;
176                         } else {
177                                 return;
178                         }
179
180                         this.ui.children().remove();
181
182                         var token = this._parsePattern( format ),
183                                 div = document.createElement('div'),
184                                 pat,
185                                 tpl,
186                                 period,
187                                 btn,
188                                 obj = this;
189
190                         while ( token.length > 0 ) {
191                                 pat = token.shift();
192                                 tpl = '<span class="ui-datefield-%1" data-pat="' + pat + '">%2</span>';
193                                 switch ( pat ) {
194                                 case 'H': //0 1 2 3 ... 21 22 23
195                                 case 'HH': //00 01 02 ... 21 22 23
196                                 case 'h': //0 1 2 3 ... 11 12
197                                 case 'hh': //00 01 02 ... 11 12
198                                         $(div).append( tpl.replace('%1', 'hour') );
199                                         break;
200                                 case 'mm': //00 01 ... 59
201                                 case 'm': //0 1 2 ... 59
202                                         if ( this.options.type == 'date' ) {
203                                                 $(div).append( tpl.replace('%1', 'month') );
204                                         } else {
205                                                 $(div).append( tpl.replace('%1', 'min') );
206                                         }
207                                         break;
208                                 case 'ss':
209                                 case 's':
210                                         $(div).append( tpl.replace('%1', 'sec') );
211                                         break;
212                                 case 'd': // day of month 5
213                                 case 'dd': // day of month(leading zero) 05
214                                         $(div).append( tpl.replace('%1', 'day') );
215                                         break;
216                                 case 'M': // Month of year 9
217                                 case 'MM': // Month of year(leading zero) 09
218                                 case 'MMM':
219                                 case 'MMMM':
220                                         $(div).append( tpl.replace('%1', 'month') );
221                                         break;
222                                 case 'yy':      // year two digit
223                                 case 'yyyy': // year four digit
224                                         $(div).append( tpl.replace('%1', 'year') );
225                                         break;
226                                 case 't': //AM / PM indicator(first letter) A, P
227                                         // add button
228                                 case 'tt': //AM / PM indicator AM/PM
229                                         // add button
230                                         btn = '<a href="#" class="ui-datefield-period"' +
231                                                 ' data-role="button" data-inline="true">period</a>';
232                                         $(div).append( btn );
233                                         break;
234                                 case 'g':
235                                 case 'gg':
236                                         $(div).append( tpl.replace('%1', 'era').replace('%2', this._calendar().eras.name) );
237                                         break;
238                                 case '\t':
239                                         $(div).append( tpl.replace('%1', 'tab').replace('%2', pat) );
240                                         break;
241                                 default : // string or any non-clickable object
242                                         $(div).append( tpl.replace('%1', 'seperator').replace('%2', pat) );
243                                         break;
244                                 }
245                         }
246
247                         this.ui.append( div );
248                         if ( this.options.date ) {
249                                 this._setDate( this.options.date );
250                         }
251
252                         this.ui.find('.ui-datefield-period').buttonMarkup().bind( 'vclick', function ( e ) {
253                                 obj._switchAmPm( obj );
254                                 return false;
255                         });
256
257                         this.element.attr( "data-" + ( $.mobile.ns ? $.mobile.ns + "-" : "" ) + "format", this.options.format );
258                         return this.options.format;
259                 },
260
261                 _setDate: function ( newdate ) {
262                         if ( typeof ( newdate ) == "string" ) {
263                                 newdate = new Date( newdate );
264                         }
265
266                         var fields = $('span,a', this.ui),
267                                 type,
268                                 fn,
269                                 $field,
270                                 btn,
271                                 i;
272
273                         function getMonth() {
274                                 return newdate.getMonth() + 1;
275                         }
276
277                         for ( i = 0; i < fields.length; i++ ) {
278                                 $field = $(fields[i]);
279                                 type = $field.attr("class").match(/ui-datefield-([\w]*)/);
280                                 if ( !type ) {
281                                         type = "";
282                                 }
283                                 switch ( type[1] ) {
284                                 case 'hour':
285                                         fn = newdate.getHours;
286                                         break;
287                                 case 'min':
288                                         fn = newdate.getMinutes;
289                                         break;
290                                 case 'sec':
291                                         fn = newdate.getSeconds;
292                                         break;
293                                 case 'year':
294                                         fn = newdate.getFullYear;
295                                         break;
296                                 case 'month':
297                                         fn = getMonth;
298                                         break;
299                                 case 'day':
300                                         fn = newdate.getDate;
301                                         break;
302                                 case 'period':
303                                         fn = newdate.getHours() < 12 ? this._calendar().AM[0] : this._calendar().PM[0];
304                                         btn = $field.find( '.ui-btn-text' );
305                                         if ( btn.length == 0 ) {
306                                                 $field.text(fn);
307                                         } else if ( btn.text() != fn ) {
308                                                 btn.text( fn );
309                                         }
310                                         fn = null;
311                                         break;
312                                 default:
313                                         fn = null;
314                                         break;
315                                 }
316                                 if ( fn ) {
317                                         this._updateField( $field, fn.call( newdate ) );
318                                 }
319                         }
320
321                         this.options.date = newdate;
322
323                         this._setValue( newdate );
324
325                         this.element.attr( "data-" + ( $.mobile.ns ? $.mobile.ns + "-" : "" ) + "date", this.options.date );
326                         return this.options.date;
327                 },
328
329                 destroy: function () {
330                         if ( this.ui ) {
331                                 this.ui.remove();
332                         }
333
334                         if ( this.element ) {
335                                 this.element.show();
336                         }
337                 },
338
339                 value: function ( val ) {
340                         function timeStr( t, obj ) {
341                                 return obj._makeTwoDigits( t.getHours() ) + ':' +
342                                         obj._makeTwoDigits( t.getMinutes() ) + ':' +
343                                         obj._makeTwoDigits( t.getSeconds() );
344                         }
345
346                         function dateStr( d, obj ) {
347                                 return ( ( d.getFullYear() % 10000 ) + 10000 ).toString().substr(1) + '-' +
348                                         obj._makeTwoDigits( d.getMonth() + 1 ) + '-' +
349                                         obj._makeTwoDigits( d.getDate() );
350                         }
351
352                         var rvalue = null;
353                         if ( val ) {
354                                 rvalue = this._setDate( val );
355                         } else {
356                                 switch ( this.options.type ) {
357                                 case 'time':
358                                         rvalue = timeStr( this.options.date, this );
359                                         break;
360                                 case 'date':
361                                         rvalue = dateStr( this.options.date, this );
362                                         break;
363                                 default:
364                                         rvalue = dateStr( this.options.date, this ) + 'T' + timeStr( this.options.date, this );
365                                         break;
366                                 }
367                         }
368                         return rvalue;
369                 },
370
371                 setValue: function ( newdate ) {
372                         console.warn( "setValue was deprecated. use datetimepicker('option', 'date', value) instead." );
373                         return this.value( newdate );
374                 },
375
376                 /**
377                  * return W3C DTF string
378                  */
379                 getValue: function () {
380                         console.warn("getValue() was deprecated. use datetimepicker('value') instead.");
381                         return this.value();
382                 },
383
384                 _updateField: function ( target, value ) {
385                         if ( !target || target.length == 0 ) {
386                                 return;
387                         }
388
389                         if ( value == 0 ) {
390                                 value = "0";
391                         }
392
393                         var pat = target.jqmData( 'pat' ),
394                                 hour,
395                                 text,
396                                 self = this;
397
398                         switch ( pat ) {
399                         case 'H':
400                         case 'HH':
401                         case 'h':
402                         case 'hh':
403                                 hour = value;
404                                 if ( pat.charAt(0) == 'h' ) {
405                                         if ( hour > 12 ) {
406                                                 hour -= 12;
407                                         } else if ( hour == 0 ) {
408                                                 hour = 12;
409                                         }
410                                 }
411                                 hour = this._makeTwoDigits( hour );
412                                 text = hour;
413                                 break;
414                         case 'm':
415                         case 'M':
416                         case 'd':
417                         case 's':
418                                 text = value;
419                                 break;
420                         case 'mm':
421                         case 'dd':
422                         case 'MM':
423                         case 'ss':
424                                 text = this._makeTwoDigits( value );
425                                 break;
426                         case 'MMM':
427                                 text = this._calendar().months.namesAbbr[ value - 1];
428                                 break;
429                         case 'MMMM':
430                                 text = this._calendar().months.names[ value - 1 ];
431                                 break;
432                         case 'yy':
433                                 text = this._makeTwoDigits( value % 100 );
434                                 break;
435                         case 'yyyy':
436                                 if ( value < 10 ) {
437                                         value = '000' + value;
438                                 } else if ( value < 100 ) {
439                                         value = '00' + value;
440                                 } else if ( value < 1000 ) {
441                                         value = '0' + value;
442                                 }
443                                 text = value;
444                                 break;
445                         }
446
447                         // to avoid reflow where its value isn't out-dated
448                         if ( target.text() != text ) {
449                                 if ( target.hasClass("ui-datefield-selected") ) {
450                                         target.addClass("out");
451                                         this._new_value = text;
452
453                                         target.animationComplete( function () {
454                                                 target.text( self._new_value);
455                                                 target.addClass("in")
456                                                         .removeClass("out");
457
458                                                 target.animationComplete( function () {
459                                                         target.removeClass("in").
460                                                                 removeClass("ui-datefield-selected");
461                                                 });
462                                         });
463                                 } else {
464                                         target.text( text );
465                                 }
466                         }
467                 },
468
469                 _switchAmPm: function ( obj ) {
470                         if ( this._calendar().AM != null ) {
471                                 var date = new Date( this.options.date ),
472                                         text,
473                                         change = 1000 * 60 * 60 * 12;
474                                 if ( date.getHours() > 11 ) {
475                                         change = -change;
476                                 }
477                                 date.setTime( date.getTime() + change );
478                                 this._setDate( date );
479                         }
480                 },
481
482                 _parsePattern: function ( pattern ) {
483                         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,
484                                 matches,
485                                 i;
486
487                         matches = pattern.match( regex );
488
489                         for ( i = 0; i < matches.length; i++ ) {
490                                 if ( matches[i].charAt(0) == "'" ) {
491                                         matches[i] = matches[i].substr( 1, matches[i].length - 2 );
492                                 }
493                         }
494
495                         return matches;
496                 },
497
498                 changeTypeFormat: function ( type, format ) {
499                         console.warn('changeTypeFormat() was deprecated. use datetimepicker("option", "type"|"format", value) instead');
500                         if ( type ) {
501                                 this._setType( type );
502                         }
503
504                         if ( format ) {
505                                 this._setFormat( format );
506                         }
507                 },
508
509                 _create: function () {
510                         var obj = this;
511
512                         if ( this.element.is( "input" ) ) {
513                                 ( function ( obj ) {
514                                         var type, value, format;
515
516                                         type = obj.element.get(0).getAttribute( "type" );
517                                         obj.options.type = type;
518
519                                         value = obj.element.get(0).getAttribute( "value" );
520                                         if ( value ) {
521                                                 obj.options.date = new Date( value );
522                                         }
523                                 }( this ) );
524                         }
525
526                         if ( !this.options.format ) {
527                                 switch ( this.options.type ) {
528                                 case 'datetime':
529                                         this.options.format = this._calendar().patterns.d + "\t" + this._calendar().patterns.t;
530                                         break;
531                                 case 'date':
532                                         this.options.format = this._calendar().patterns.d;
533                                         break;
534                                 case 'time':
535                                         this.options.format = this._calendar().patterns.t;
536                                         break;
537                                 }
538                         }
539
540                         if ( !this.options.date ) {
541                                 this.options.date = new Date();
542                         }
543
544                         this.element.hide();
545                         this.ui = $('<div class="ui-datefield"></div>');
546                         $(this.element).after( this.ui );
547
548                         this._popup_open = false;
549                         this.ui.bind('vclick', function ( e ) {
550                                 obj._showDataSelector( obj, this, e.target );
551                                 return false;
552                         });
553
554                         $.extend( this, {
555                                 _globalHandlers: [
556                                         {
557                                                 src: $( window ),
558                                                 handler: {
559                                                         orientationchange: $.proxy( this, "_orientationHandler" )
560                                                 }
561                                         }
562                                 ]
563                         });
564
565                         $.each( this._globalHandlers, function( idx, value ) {
566                                 value.src.bind( value.handler );
567                         });
568                 },
569                 _orientationHandler: function() {
570                         var self = this;
571                         if( self._popup_open ) {
572                                 self._popup_open = false;
573                                 self.container.popupwindow( 'close' );
574                         }
575                         return false;
576                 },
577                 _populateDataSelector: function ( field, pat ) {
578                         var values,
579                                 numItems,
580                                 current,
581                                 data,
582                                 range = window.range,
583                                 local,
584                                 yearlb,
585                                 yearhb,
586                                 day;
587
588                         switch ( field ) {
589                         case 'hour':
590                                 if ( pat == 'H' || pat == 'HH' ) {
591                                         // twentyfour
592                                         values = range( 0, 23 );
593                                         data = range( 0, 23 );
594                                         current = this.options.date.getHours();
595                                 } else {
596                                         values = range( 1, 12 );
597                                         current = this.options.date.getHours() - 1;//11
598                                         if ( current >= 11 ) {
599                                                 current = current - 12;
600                                                 data = range( 13, 23 );
601                                                 data.push( 12 ); // consider 12:00 am as 00:00
602                                         } else {
603                                                 data = range( 1, 11 );
604                                                 data.push( 0 );
605                                         }
606                                         if ( current < 0 ) {
607                                                 current = 11; // 12:00 or 00:00
608                                         }
609                                 }
610                                 if ( pat.length == 2 ) {
611                                         // two digit
612                                         values = values.map( this._makeTwoDigits );
613                                 }
614                                 numItems = values.length;
615                                 break;
616                         case 'min':
617                         case 'sec':
618                                 values = range( 0, 59 );
619                                 if ( pat.length == 2 ) {
620                                         values = values.map( this._makeTwoDigits );
621                                 }
622                                 data = range( 0, 59 );
623                                 current = ( field == 'min' ? this.options.date.getMinutes() : this.options.date.getSeconds() );
624                                 numItems = values.length;
625                                 break;
626                         case 'year':
627                                 yearlb = 1900;
628                                 yearhb = 2100;
629                                 data = range( yearlb, yearhb );
630                                 current = this.options.date.getFullYear() - yearlb;
631                                 values = range( yearlb, yearhb );
632                                 numItems = values.length;
633                                 break;
634                         case 'month':
635                                 switch ( pat.length ) {
636                                 case 1:
637                                         values = range( 1, 12 );
638                                         break;
639                                 case 2:
640                                         values = range( 1, 12 ).map( this._makeTwoDigits );
641                                         break;
642                                 case 3:
643                                         values = this._calendar().months.namesAbbr.slice();
644                                         break;
645                                 case 4:
646                                         values = this._calendar().months.names.slice();
647                                         break;
648                                 }
649                                 if ( values.length == 13 ) { // @TODO Lunar calendar support
650                                         if ( values[12] == "" ) { // to remove lunar calendar reserved space
651                                                 values.pop();
652                                         }
653                                 }
654                                 data = range( 1, values.length );
655                                 current = this.options.date.getMonth();
656                                 numItems = values.length;
657                                 break;
658                         case 'day':
659                                 day = this._daysInMonth[ this.options.date.getMonth() ];
660                                 if ( day == 28 ) {
661                                         day += this._isLeapYear( this.options.date.getFullYear() );
662                                 }
663                                 values = range( 1, day );
664                                 if ( pat.length == 2 ) {
665                                         values = values.map( this._makeTwoDigits );
666                                 }
667                                 data = range( 1, day );
668                                 current = this.options.date.getDate() - 1;
669                                 numItems = day;
670                                 break;
671                         }
672
673                         return {
674                                 values: values,
675                                 data: data,
676                                 numItems: numItems,
677                                 current: current
678                         };
679
680                 },
681
682                 _showDataSelector: function ( obj, ui, target ) {
683                         target = $(target);
684
685                         var attr = target.attr("class"),
686                                 field = attr ? attr.match(/ui-datefield-([\w]*)/) : undefined,
687                                 pat,
688                                 data,
689                                 values,
690                                 numItems,
691                                 current,
692                                 valuesData,
693                                 html,
694                                 datans,
695                                 $ul,
696                                 $div,
697                                 $ctx,
698                                 $li,
699                                 i,
700                                 newLeft = 10,
701                                 self = this;
702
703                         if ( !attr ) {
704                                 return;
705                         }
706                         if ( !field ) {
707                                 return;
708                         }
709                         if ( this._popup_open ) {
710                                 return;
711                         }
712
713                         target.not('.ui-datefield-seperator').addClass('ui-datefield-selected');
714
715                         pat = target.jqmData('pat');
716                         data = obj._populateDataSelector.call( obj, field[1], pat );
717
718                         values = data.values;
719                         numItems = data.numItems;
720                         current = data.current;
721                         valuesData = data.data;
722
723                         if ( values ) {
724                                 datans = "data-" + ($.mobile.ns ? ($.mobile.ns + '-') : "") + 'val="';
725                                 for ( i = 0; i < values.length; i++ ) {
726                                         html += '<li><a class="ui-link" ' + datans + valuesData[i] + '">' + values[i] + '</a></li>';
727                                 }
728
729                                 $ul = $("<ul></ul>");
730                                 $div = $('<div class="ui-datetimepicker-selector" data-transition="fade" data-fade="false"></div>');
731                                 $div.append( $ul ).appendTo( ui );
732                                 $ctx = $div.ctxpopup();
733                                 $ctx.parents('.ui-popupwindow').addClass('ui-datetimepicker');
734                                 $li = $(html);
735                                 $( $li[current] ).addClass("current");
736                                 $div.jqmData( "list", $li );
737                                 $div.circularview();
738                                 if( !obj._reflow ) {
739                                         obj._reflow = function() {
740                                                 $div.circularview( "reflow" );
741                                                 $div.circularview( 'centerTo', '.current', 0 );
742                                         }
743                                         $(window).bind( "resize" , obj._reflow );
744                                 }
745                                 // cause ctxpopup forced to subtract 10
746                                 if ( $( window ).width() / 2 < target.offset().left ) {
747                                         newLeft = -10;
748                                 }
749                                 $ctx.popupwindow( 'open',
750                                                 target.offset().left + ( target.width() / 2 ) + newLeft - window.pageXOffset ,
751                                                 target.offset().top + target.height() - window.pageYOffset );
752
753                                 this.container = $ctx;
754                                 this._popup_open = true;
755
756                                 $div.bind('popupafterclose', function ( e ) {
757                                         if ( obj._reflow ) {
758                                                 $(window).unbind("resize", obj._reflow);
759                                                 obj._reflow = null;
760                                         }
761
762                                         if ( !( target.hasClass("in") || target.hasClass("out") ) ) {
763                                                 target.removeClass("ui-datefield-selected");
764                                         }
765
766                                         $div.unbind( 'popupafterclose' );
767                                         $ul.unbind( 'vclick' );
768                                         $(obj).unbind( 'update' );
769                                         $ctx.popupwindow( 'destroy' );
770                                         $div.remove();
771
772                                         self._popup_open = false;
773                                 });
774
775                                 $(obj).bind( 'update', function ( e, val ) {
776                                         var date = new Date( this.options.date ),
777                                                 month,
778                                                 date_calibration = function () {
779                                                         date.setDate( 1 );
780                                                         date.setDate( date.getDate() - 1 );
781                                                 };
782
783                                         switch ( field[1] ) {
784                                         case 'min':
785                                                 date.setMinutes( val );
786                                                 break;
787                                         case 'hour':
788                                                 date.setHours( val );
789                                                 break;
790                                         case 'sec':
791                                                 date.setSeconds( val );
792                                                 break;
793                                         case 'year':
794                                                 month = date.getMonth();
795                                                 date.setFullYear( val );
796
797                                                 if ( date.getMonth() != month ) {
798                                                         date_calibration();
799                                                 }
800                                                 break;
801                                         case 'month':
802                                                 date.setMonth( val - 1 );
803
804                                                 if ( date.getMonth() == val ) {
805                                                         date_calibration();
806                                                 }
807                                                 break;
808                                         case 'day':
809                                                 date.setDate( val );
810                                                 break;
811                                         }
812
813                                         obj._setDate( date );
814
815                                         $ctx.popupwindow( 'close' );
816                                 });
817
818                                 $ul.bind( 'click', function ( e ) {
819                                         if ( $(e.target).is('a') ) {
820                                                 $ul.find(".current").removeClass("current");
821                                                 $(e.target).parent().addClass('current');
822                                                 var val = $(e.target).jqmData("val");
823                                                 $(obj).trigger( 'update', val ); // close popup, unselect field
824                                         }
825                                 });
826
827                                 $div.circularview( 'centerTo', '.current', 500 );
828                                 $div.bind( 'scrollend' , function ( e ) {
829                                         if ( !obj._reflow ) {
830                                                 obj._reflow = function () {
831                                                         $div.circularview("reflow");
832                                                 };
833                                                 $(window).bind("resize", obj._reflow);
834                                         }
835                                 });
836                         }
837                         return ui;
838                 }
839
840         });
841
842         $(document).bind("pagecreate create", function ( e ) {
843                 $($.tizen.datetimepicker.prototype.options.initSelector, e.target)
844                         .not(":jqmData(role='none'), :jqmData(role='nojs')")
845                         .datetimepicker();
846         });
847
848 } ( jQuery, this ) );
849