Tizen 2.0 Release
[platform/framework/web/web-ui-fw.git] / src / widgets / multimediaview / js / jquery.mobile.tizen.multimediaview.js
1 /* ***************************************************************************
2  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  * ***************************************************************************
22  *
23  * Authors: Yonghwi Park <yonghwi0324.park@samsung.com>
24  *               Wonseop Kim <wonseop.kim@samsung.com>
25 */
26
27 /**
28  *
29  * MultiMediaView is a widget that lets the user view and handle multimedia contents.
30  * Video and audio elements are coded as standard HTML elements and enhanced by the 
31  * MultiMediaview to make them attractive and usable on a mobile device.
32  *
33  * HTML Attributes:
34  *                      data-theme : Set a theme of widget.
35  *                              If this value is not defined, widget will use parent`s theme. (optional)
36  *                      data-controls : If this value is 'true', widget will use belonging controller.
37  *                              If this value is 'false', widget will use browser`s controller.
38  *                              Default value is 'true'.
39  *                      data-full-screen : Set a status that full-screen when inital start.
40  *                              Default value is 'false'.
41  *
42  * APIs:
43  *                      width( [number] )
44  *                                      : Get or set the width of widget.
45  *                                      The first argument is the width of widget.
46  *                                      If no first argument is specified, will act as a getter.
47  *                      height( [number] )
48  *                                      : Get or set the height of widget.
49  *                                      The first argument is the height of widget.
50  *                                      If no first argument is specified, will act as a getter.
51  *                      fullScreen( [boolean] )
52  *                                      : Get or Set the status of full-screen.
53  *                                      If no first argument is specified, will act as a getter.
54  *
55  * Events:
56  *
57  *                      create :  triggered when a multimediaview is created.
58  *
59  * Examples:
60  *
61  *                      VIDEO :
62  *                              <video data-controls="true" style="width:100%;">
63  *                                      <source src="media/oceans-clip.mp4" type="video/mp4" />
64  *                                      Your browser does not support the video tag.
65  *                              </video>
66  *
67  *                      AUDIO :
68  *                              <audio data-controls="true" style="width:100%;">
69  *                                      <source src="media/Over the horizon.mp3" type="audio/mp3" />
70  *                                      Your browser does not support the audio tag.
71  *                              </audio>
72  *
73  */
74 /**
75         @class MutimediaView
76         The multimedia view widget shows a player control that you can use to view and handle multimedia content. This widget uses the standard HTML video and audio elements, which have been enhanced for use on a mobile device.
77
78         To add a multimedia view widget to the application, use the following code:
79         
80                 // Video player control
81                 <video data-controls="true" style="width:100%;">
82                 <source src="<VIDEO_FILE_URL>" type="video/mp4" /> Your browser does not support the video tag. </video>
83                 // Audio player control
84                 <audio data-controls="true" style="width:100%;"> <source src="<AUDIO_FILE_URL>" type="audio/mp3" /> Your browser does not support the audio tag.
85                 </audio>
86
87         The multimedia view can define a callback for the create event, which is fired when the widget is created.
88                 $('.selector').multimediaview({
89                         create:function(event, u){...}
90                 });
91                 $(".selector").bind("create", function(event, ui)
92                 {
93                         // Respond to the multimedia view widget creation
94                 });
95 */
96 /**
97         @property {Boolean} data-control
98         Sets the controls for the widget.
99         The default value is true. If the value is set to true, the widget uses its own player controls. If the value is set to false, the widget uses the browser's player controls.
100 */
101 /**
102         @property {Boolean} data-full-screen
103         Defines whether the widget opens in the fullscreen view mode.
104         The default value is false.
105 */
106 /**
107         @property {String} data-theme
108         Sets the widget theme.
109         If the value is not set, the parent control's theme is used
110 */
111 /**
112         @method width
113         The width method is used to get (if no value is defined) or set the multimedia view widget width:
114                 <video>
115                          <source src="test.mp4" type="video/mp4" />
116                 </video>
117                 $(".selector").multimediaview("width", [value]);
118 */
119 /**
120         @method height
121         The height method is used to get (if no value is defined) or set the multimedia view widget height:
122                 <video>
123                         <source src="test.mp4" type="video/mp4" />
124                 </video>
125                 $(".selector").multimediaview("height", [value]);
126 */
127 /**
128         @method fullScreen
129         The fullScreen method is used to get (if no value is defined) or set the full-screen mode of the multimedia view widget. If the value is true, the full-screen mode is used; otherwise the multimedia view widget runs in the normal mode.
130
131                 <video>
132                         <source src="test.mp4" type="video/mp4" />
133                 </video>
134                 $(".selector").multimediaview("fullScreen", [value]);
135 */
136 ( function ( $, document, window, undefined ) {
137         $.widget( "tizen.multimediaview", $.mobile.widget, {
138                 options: {
139                         theme: null,
140                         controls: true,
141                         fullScreen: false,
142                         initSelector: "video, audio"
143                 },
144
145                 _create: function () {
146                         var self = this,
147                                 view = self.element,
148                                 viewElement = view[0],
149                                 option = self.options,
150                                 parentTheme = $.mobile.getInheritedTheme( view, "s" ),
151                                 theme = option.theme || parentTheme,
152                                 role = "multimediaview",
153                                 control = null;
154
155                         $.extend( this, {
156                                 role: null,
157                                 isControlHide: false,
158                                 controlTimer: null,
159                                 isVolumeHide: true,
160                                 isVertical: true,
161                                 backupView: null
162                         });
163
164                         self.role = role;
165                         view.addClass( "ui-multimediaview" );
166                         control = self._createControl();
167                         control.find( ".ui-button" ).each( function ( index ) {
168                                 $( this ).buttonMarkup( { corners: true, theme: theme, shadow: true } );
169                         });
170
171                         if ( view[0].nodeName === "VIDEO" ) {
172                                 control.addClass( "ui-" + role + "-video" );
173                         }
174
175                         control.hide();
176                         view.wrap( [ "<div class='ui-", role, "-wrap ui-", role , "-", theme, "'>" ].join( "" ) ).after( control );
177                         if ( option.controls && view.attr( "controls" ) ) {
178                                 view.removeAttr( "controls" );
179                         }
180
181                         self._addEvent();
182                 },
183
184                 _resize: function () {
185                         var view = this.element,
186                                 parent = view.parent(),
187                                 control = parent.find( ".ui-multimediaview-control" ),
188                                 viewWidth = 0,
189                                 viewHeight = 0,
190                                 viewOffset = null;
191
192                         this._resizeFullscreen( this.options.fullScreen );
193                         viewWidth = ( ( view[0].nodeName === "VIDEO" ) ? view.width() : parent.width() );
194                         viewHeight = ( ( view[0].nodeName === "VIDEO" ) ? view.height() : control.height() );
195                         viewOffset = view.offset();
196
197                         this._resizeControl( viewOffset, viewWidth, viewHeight );
198
199                         this._updateSeekBar();
200                         this._updateVolumeState();
201                 },
202
203                 _resizeControl: function ( offset, width, height ) {
204                         var self = this,
205                                 view = self.element,
206                                 viewElement = view[0],
207                                 control = view.parent().find( ".ui-multimediaview-control" ),
208                                 buttons = control.find( ".ui-button" ),
209                                 playpauseButton = control.find( ".ui-playpausebutton" ),
210                                 seekBar = control.find( ".ui-seekbar" ),
211                                 durationLabel = control.find( ".ui-durationlabel" ),
212                                 timestampLabel = control.find( ".ui-timestamplabel" ),
213                                 volumeControl = control.find( ".ui-volumecontrol" ),
214                                 volumeBar = volumeControl.find( ".ui-volumebar" ),
215                                 controlWidth = width,
216                                 controlHeight = control.outerHeight( true ),
217                                 availableWidth = 0,
218                                 controlOffset = null;
219
220                         if ( control ) {
221                                 if ( view[0].nodeName === "VIDEO" ) {
222                                         controlOffset = control.offset();
223                                         controlOffset.left = offset.left;
224                                         controlOffset.top = offset.top + height - controlHeight;
225                                         control.offset( controlOffset );
226                                 }
227
228                                 control.width( controlWidth );
229                         }
230
231                         if ( seekBar ) {
232                                 availableWidth = control.width() - ( buttons.outerWidth( true ) * buttons.length );
233                                 availableWidth -= ( parseInt( buttons.eq( 0 ).css( "margin-left" ), 10 ) + parseInt( buttons.eq( 0 ).css( "margin-right" ), 10 ) ) * buttons.length;
234                                 if ( !self.isVolumeHide ) {
235                                         availableWidth -= volumeControl.outerWidth( true );
236                                 }
237                                 seekBar.width( availableWidth );
238                         }
239
240                         if ( durationLabel && !isNaN( viewElement.duration ) ) {
241                                 durationLabel.find( "p" ).text( self._convertTimeFormat( viewElement.duration ) );
242                         }
243
244                         if ( viewElement.autoplay && viewElement.paused === false ) {
245                                 playpauseButton.removeClass( "ui-play-icon" ).addClass( "ui-pause-icon" );
246                         }
247
248                         if ( seekBar.width() < ( volumeBar.width() + timestampLabel.width() + durationLabel.width() ) ) {
249                                 durationLabel.hide();
250                         } else {
251                                 durationLabel.show();
252                         }
253                 },
254
255                 _resizeFullscreen: function ( isFullscreen ) {
256                         var self = this,
257                                 view = self.element,
258                                 parent = view.parent(),
259                                 control = view.parent().find( ".ui-multimediaview-control" ),
260                                 playpauseButton = control.find( ".ui-playpausebutton" ),
261                                 timestampLabel = control.find( ".ui-timestamplabel" ),
262                                 seekBar = control.find( ".ui-seekbar" ),
263                                 durationBar = seekBar.find( ".ui-duration" ),
264                                 currenttimeBar = seekBar.find( ".ui-currenttime" ),
265                                 docWidth = 0,
266                                 docHeight = 0;
267
268                         if ( isFullscreen ) {
269                                 if ( !self.backupView ) {
270                                         self.backupView = {
271                                                 width: view[0].style.getPropertyValue( "width" ) || "",
272                                                 height: view[0].style.getPropertyValue( "height" ) || "",
273                                                 position: view.css( "position" ),
274                                                 zindex: view.css( "z-index" )
275                                         };
276                                 }
277                                 docWidth = $( "body" )[0].clientWidth;
278                                 docHeight = $( "body" )[0].clientHeight;
279
280                                 view.width( docWidth ).height( docHeight - 1 );
281                                 view.closest(".ui-multimediaview-wrap").height( docHeight - 1 );
282                                 view.addClass( "ui-" + self.role + "-fullscreen" );
283                                 view.offset( {
284                                         top: 0,
285                                         left: 0
286                                 });
287                         } else {
288                                 if ( !self.backupView ) {
289                                         return;
290                                 }
291
292                                 view.removeClass( "ui-" + self.role + "-fullscreen" );
293                                 view.css( {
294                                         "width": self.backupView.width,
295                                         "height": self.backupView.height,
296                                         "position": self.backupView.position,
297                                         "z-index": self.backupView.zindex
298                                 });
299                                 view.closest(".ui-multimediaview-wrap").css( "height", "" );
300                                 self.backupView = null;
301                         }
302                         parent.show();
303                 },
304
305                 _addEvent: function () {
306                         var self = this,
307                                 view = self.element,
308                                 option = self.options,
309                                 viewElement = view[0],
310                                 control = view.parent().find( ".ui-multimediaview-control" ),
311                                 playpauseButton = control.find( ".ui-playpausebutton" ),
312                                 timestampLabel = control.find( ".ui-timestamplabel" ),
313                                 durationLabel = control.find( ".ui-durationlabel" ),
314                                 volumeButton = control.find( ".ui-volumebutton" ),
315                                 volumeControl = control.find( ".ui-volumecontrol" ),
316                                 volumeBar = volumeControl.find( ".ui-volumebar" ),
317                                 volumeGuide = volumeControl.find( ".ui-guide" ),
318                                 volumeHandle = volumeControl.find( ".ui-handler" ),
319                                 fullscreenButton = control.find( ".ui-fullscreenbutton" ),
320                                 seekBar = control.find( ".ui-seekbar" ),
321                                 durationBar = seekBar.find( ".ui-duration" ),
322                                 currenttimeBar = seekBar.find( ".ui-currenttime" );
323
324                         $( document ).unbind( ".multimediaview" ).bind( "pagechange.multimediaview", function ( e ) {
325                                 var $page = $( e.target );
326                                 if ( $page.find( view ).length > 0 && viewElement.autoplay ) {
327                                         viewElement.play();
328                                 }
329
330                                 if ( option.controls ) {
331                                         control.show();
332                                         self._resize();
333                                 }
334                         }).bind( "pagebeforechange.multimediaview", function ( e ) {
335                                 if ( viewElement.played.length !== 0 ) {
336                                         viewElement.pause();
337                                         control.hide();
338                                 }
339                         });
340
341                         $( window ).unbind( ".multimediaview" ).bind( "resize.multimediaview orientationchange.multimediaview", function ( e ) {
342                                 if ( !option.controls ) {
343                                         return;
344                                 }
345                                 var $page = $( e.target ),
346                                         $scrollview = view.parents( ".ui-scrollview-clip" );
347
348                                 $scrollview.each( function ( i ) {
349                                         if ( $.data( this, "scrollview" ) ) {
350                                                 $( this ).scrollview( "scrollTo", 0, 0 );
351                                         }
352                                 });
353
354                                 // for maintaining page layout
355                                 if ( !option.fullScreen ) {
356                                         $( ".ui-footer:visible" ).show();
357                                 } else {
358                                         $( ".ui-footer" ).hide();
359                                         self._fitContentArea( $page );
360                                 }
361
362                                 self._resize();
363                         });
364
365                         view.bind( "loadedmetadata.multimediaview", function ( e ) {
366                                 if ( !isNaN( viewElement.duration ) ) {
367                                         durationLabel.find( "p" ).text( self._convertTimeFormat( viewElement.duration ) );
368                                 }
369                                 self._resize();
370                         }).bind( "timeupdate.multimediaview", function ( e ) {
371                                 self._updateSeekBar();
372                         }).bind( "play.multimediaview", function ( e ) {
373                                 playpauseButton.removeClass( "ui-play-icon" ).addClass( "ui-pause-icon" );
374                         }).bind( "pause.multimediaview", function ( e ) {
375                                 playpauseButton.removeClass( "ui-pause-icon" ).addClass( "ui-play-icon" );
376                         }).bind( "ended.multimediaview", function ( e ) {
377                                 if ( typeof viewElement.loop == "undefined" || viewElement.loop === "" ) {
378                                         self.stop();
379                                 }
380                         }).bind( "volumechange.multimediaview", function ( e ) {
381                                 if ( viewElement.volume < 0.1 ) {
382                                         viewElement.muted = true;
383                                         volumeButton.removeClass( "ui-volume-icon" ).addClass( "ui-mute-icon" );
384                                 } else {
385                                         viewElement.muted = false;
386                                         volumeButton.removeClass( "ui-mute-icon" ).addClass( "ui-volume-icon" );
387                                 }
388
389                                 if ( !self.isVolumeHide ) {
390                                         self._updateVolumeState();
391                                 }
392                         }).bind( "durationchange.multimediaview", function ( e ) {
393                                 if ( !isNaN( viewElement.duration ) ) {
394                                         durationLabel.find( "p" ).text( self._convertTimeFormat( viewElement.duration ) );
395                                 }
396                                 self._resize();
397                         }).bind( "error.multimediaview", function ( e ) {
398                                 switch ( e.target.error.code ) {
399                                 case e.target.error.MEDIA_ERR_ABORTED:
400                                         window.alert( 'You aborted the video playback.' );
401                                         break;
402                                 case e.target.error.MEDIA_ERR_NETWORK:
403                                         window.alert( 'A network error caused the video download to fail part-way.' );
404                                         break;
405                                 case e.target.error.MEDIA_ERR_DECODE:
406                                         window.alert( 'The video playback was aborted due to a corruption problem or because the video used features your browser did not support.' );
407                                         break;
408                                 case e.target.error.MEDIA_ERR_SRC_NOT_SUPPORTED:
409                                         window.alert( 'The video could not be loaded, either because the server or network failed or because the format is not supported.' );
410                                         break;
411                                 default:
412                                         window.alert( 'An unknown error occurred.' );
413                                         break;
414                                 }
415                         }).bind( "vclick.multimediaview", function ( e ) {
416                                 if ( !self.options.controls ) {
417                                         return;
418                                 }
419
420                                 control.fadeToggle( "fast", function () {
421                                         var offset = control.offset();
422                                         self.isControlHide = !self.isControlHide;
423                                         if ( self.options.mediatype == "video" ) {
424                                                 self._startTimer();
425                                         }
426                                 });
427                                 self._resize();
428                         });
429
430                         playpauseButton.bind( "vclick.multimediaview", function () {
431                                 self._endTimer();
432
433                                 if ( viewElement.paused ) {
434                                         viewElement.play();
435                                 } else {
436                                         viewElement.pause();
437                                 }
438
439                                 if ( self.options.mediatype == "video" ) {
440                                         self._startTimer();
441                                 }
442                         });
443
444                         fullscreenButton.bind( "vclick.multimediaview", function ( e ) {
445                                 self.fullScreen( !self.options.fullScreen );
446                                 control.fadeIn( "fast" );
447                                 self._endTimer();
448                                 e.preventDefault();
449                                 e.stopPropagation();
450                         });
451
452                         seekBar.bind( "vmousedown.multimediaview", function ( e ) {
453                                 var x = e.clientX,
454                                         duration = viewElement.duration,
455                                         durationOffset = durationBar.offset(),
456                                         durationWidth = durationBar.width(),
457                                         timerate = ( x - durationOffset.left ) / durationWidth,
458                                         time = duration * timerate;
459
460                                 if ( !viewElement.played.length ) {
461                                         return;
462                                 }
463
464                                 viewElement.currentTime = time;
465
466                                 self._endTimer();
467
468                                 e.preventDefault();
469                                 e.stopPropagation();
470
471                                 $( document ).bind( "vmousemove.multimediaview", function ( e ) {
472                                         var x = e.clientX,
473                                                 timerate = ( x - durationOffset.left ) / durationWidth;
474
475                                         viewElement.currentTime = duration * timerate;
476
477                                         e.preventDefault();
478                                         e.stopPropagation();
479                                 }).bind( "vmouseup.multimediaview", function () {
480                                         $( document ).unbind( "vmousemove.multimediaview vmouseup.multimediaview" );
481                                         if ( viewElement.paused ) {
482                                                 viewElement.pause();
483                                         } else {
484                                                 viewElement.play();
485                                         }
486                                 });
487                         });
488
489                         volumeButton.bind( "vclick.multimediaview", function () {
490                                 if ( self.isVolumeHide ) {
491                                         var view = self.element,
492                                                 volume = viewElement.volume;
493
494                                         self.isVolumeHide = false;
495                                         self._resize();
496                                         volumeControl.fadeIn( "fast" );
497                                         self._updateVolumeState();
498                                         self._updateSeekBar();
499                                 } else {
500                                         self.isVolumeHide = true;
501                                         volumeControl.fadeOut( "fast", function () {
502                                                 self._resize();
503                                         });
504                                         self._updateSeekBar();
505                                 }
506                         });
507
508                         volumeBar.bind( "vmousedown.multimediaview", function ( e ) {
509                                 var baseX = e.clientX,
510                                         volumeGuideLeft = volumeGuide.offset().left,
511                                         volumeGuideWidth = volumeGuide.width(),
512                                         volumeBase = volumeGuideLeft + volumeGuideWidth,
513                                         handlerOffset = volumeHandle.offset(),
514                                         volumerate = ( baseX - volumeGuideLeft ) / volumeGuideWidth,
515                                         currentVolume = ( baseX - volumeGuideLeft ) / volumeGuideWidth;
516
517                                 self._endTimer();
518                                 self._setVolume( currentVolume.toFixed( 2 ) );
519
520                                 e.preventDefault();
521                                 e.stopPropagation();
522
523                                 $( document ).bind( "vmousemove.multimediaview", function ( e ) {
524                                         var currentX = e.clientX,
525                                                 currentVolume = ( currentX - volumeGuideLeft ) / volumeGuideWidth;
526
527                                         self._setVolume( currentVolume.toFixed( 2 ) );
528
529                                         e.preventDefault();
530                                         e.stopPropagation();
531                                 }).bind( "vmouseup.multimediaview", function () {
532                                         $( document ).unbind( "vmousemove.multimediaview vmouseup.multimediaview" );
533
534                                         if ( self.options.mediatype == "video" ) {
535                                                 self._startTimer();
536                                         }
537                                 });
538                         });
539                 },
540
541                 _removeEvent: function () {
542                         var self = this,
543                                 view = self.element,
544                                 control = view.parent().find( ".ui-multimediaview-control" ),
545                                 playpauseButton = control.find( ".ui-playpausebutton" ),
546                                 fullscreenButton = control.find( ".ui-fullscreenbutton" ),
547                                 seekBar = control.find( ".ui-seekbar" ),
548                                 volumeControl = control.find( ".ui-volumecontrol" ),
549                                 volumeBar = volumeControl.find( ".ui-volumebar" ),
550                                 volumeHandle = volumeControl.find( ".ui-handler" );
551
552                         view.unbind( ".multimediaview" );
553                         playpauseButton.unbind( ".multimediaview" );
554                         fullscreenButton.unbind( ".multimediaview" );
555                         seekBar.unbind( ".multimediaview" );
556                         volumeBar.unbind( ".multimediaview" );
557                         volumeHandle.unbind( ".multimediaview" );
558                 },
559
560                 _createControl: function () {
561                         var self = this,
562                                 view = self.element,
563                                 control = $( "<span></span>" ).addClass( "ui-" + self.role + "-control" ),
564                                 playpauseButton = $( "<span></span>" ).addClass( "ui-playpausebutton ui-button" ),
565                                 seekBar = $( "<span></span>" ).addClass( "ui-seekbar" ),
566                                 timestampLabel = $( "<span><p>00:00:00</p></span>" ).addClass( "ui-timestamplabel" ),
567                                 durationLabel = $( "<span><p>00:00:00</p></span>" ).addClass( "ui-durationlabel" ),
568                                 volumeButton = $( "<span></span>" ).addClass( "ui-volumebutton ui-button" ),
569                                 volumeControl = $( "<span></span>" ).addClass( "ui-volumecontrol" ),
570                                 volumeBar = $( "<div></div>" ).addClass( "ui-volumebar" ),
571                                 volumeGuide = $( "<span></span>" ).addClass( "ui-guide" ),
572                                 volumeValue = $( "<span></span>" ).addClass( "ui-value" ),
573                                 volumeHandle = $( "<span></span>" ).addClass( "ui-handler" ),
574                                 fullscreenButton = $( "<span></span>" ).addClass( "ui-fullscreenbutton ui-button" ),
575                                 durationBar = $( "<span></span>" ).addClass( "ui-duration" ),
576                                 currenttimeBar = $( "<span></span>" ).addClass( "ui-currenttime" );
577
578                         seekBar.append( durationBar ).append( currenttimeBar ).append( durationLabel ).append( timestampLabel );
579
580                         playpauseButton.addClass( "ui-play-icon" );
581                         volumeButton.addClass( view[0].muted ? "ui-mute-icon" : "ui-volume-icon" );
582                         volumeBar.append( volumeGuide ).append( volumeValue ).append( volumeHandle );
583                         volumeControl.append( volumeBar );
584
585                         control.append( playpauseButton ).append( seekBar ).append( volumeControl ).append( volumeButton );
586
587                         if ( self.element[0].nodeName === "VIDEO" ) {
588                                 $( fullscreenButton ).addClass( "ui-fullscreen-on" );
589                                 control.append( fullscreenButton );
590                         }
591                         volumeControl.hide();
592
593                         return control;
594                 },
595
596                 _startTimer: function ( duration ) {
597                         this._endTimer();
598
599                         if ( !duration ) {
600                                 duration = 3000;
601                         }
602
603                         var self = this,
604                                 view = self.element,
605                                 control = view.parent().find( ".ui-multimediaview-control" ),
606                                 volumeControl = control.find( ".ui-volumecontrol" );
607
608                         self.controlTimer = setTimeout( function () {
609                                 self.isVolumeHide = true;
610                                 self.isControlHide = true;
611                                 self.controlTimer = null;
612                                 volumeControl.hide();
613                                 control.fadeOut( "fast" );
614                         }, duration );
615                 },
616
617                 _endTimer: function () {
618                         if ( this.controlTimer ) {
619                                 clearTimeout( this.controlTimer );
620                                 this.controlTimer = null;
621                         }
622                 },
623
624                 _convertTimeFormat: function ( systime ) {
625                         var ss = parseInt( systime % 60, 10 ).toString(),
626                                 mm = parseInt( ( systime / 60 ) % 60, 10 ).toString(),
627                                 hh = parseInt( systime / 3600, 10 ).toString(),
628                                 time =  ( ( hh.length < 2  ) ? "0" + hh : hh ) + ":" +
629                                                 ( ( mm.length < 2  ) ? "0" + mm : mm ) + ":" +
630                                                 ( ( ss.length < 2  ) ? "0" + ss : ss );
631
632                         return time;
633                 },
634
635                 _updateSeekBar: function ( currenttime ) {
636                         var self = this,
637                                 view = self.element,
638                                 duration = view[0].duration,
639                                 control = view.parent().find( ".ui-multimediaview-control" ),
640                                 seekBar = control.find(  ".ui-seekbar"  ),
641                                 durationBar = seekBar.find( ".ui-duration" ),
642                                 currenttimeBar = seekBar.find( ".ui-currenttime" ),
643                                 timestampLabel = control.find( ".ui-timestamplabel" ),
644                                 durationOffset = durationBar.offset(),
645                                 durationWidth = durationBar.width(),
646                                 durationHeight = durationBar.height(),
647                                 timebarWidth = 0;
648
649                         if ( typeof currenttime == "undefined" ) {
650                                 currenttime = view[0].currentTime;
651                         }
652                         timebarWidth = parseInt( currenttime / duration * durationWidth, 10 );
653                         durationBar.offset( durationOffset );
654                         currenttimeBar.offset( durationOffset ).width( timebarWidth );
655                         timestampLabel.find( "p" ).text( self._convertTimeFormat( currenttime ) );
656                 },
657
658                 _updateVolumeState: function () {
659                         var self = this,
660                                 view = self.element,
661                                 control = view.parent().find( ".ui-multimediaview-control" ),
662                                 volumeControl = control.find( ".ui-volumecontrol" ),
663                                 volumeButton = control.find( ".ui-volumebutton" ),
664                                 volumeBar = volumeControl.find( ".ui-volumebar" ),
665                                 volumeGuide = volumeControl.find( ".ui-guide" ),
666                                 volumeValue = volumeControl.find( ".ui-value" ),
667                                 volumeHandle = volumeControl.find( ".ui-handler" ),
668                                 handlerWidth = volumeHandle.width(),
669                                 handlerHeight = volumeHandle.height(),
670                                 volumeGuideHeight = volumeGuide.height(),
671                                 volumeGuideWidth = volumeGuide.width(),
672                                 volumeGuideTop = 0,
673                                 volumeGuideLeft = 0,
674                                 volumeBase = 0,
675                                 handlerOffset = null,
676                                 volume = view[0].volume;
677
678                         volumeGuideTop = parseInt( volumeGuide.offset().top, 10 );
679                         volumeGuideLeft = parseInt( volumeGuide.offset().left, 10 );
680                         volumeBase = volumeGuideLeft;
681                         handlerOffset = volumeHandle.offset();
682                         handlerOffset.top = volumeGuideTop - parseInt( ( handlerHeight - volumeGuideHeight ) / 2, 10 );
683                         handlerOffset.left = volumeBase + parseInt( volumeGuideWidth * volume, 10 ) - parseInt( handlerWidth / 2, 10 );
684                         volumeHandle.offset( handlerOffset );
685                         volumeValue.width( parseInt( volumeGuideWidth * ( volume ), 10 ) );
686                 },
687
688                 _setVolume: function ( value ) {
689                         var viewElement = this.element[0];
690
691                         if ( value < 0.0 || value > 1.0 ) {
692                                 return;
693                         }
694
695                         viewElement.volume = value;
696                 },
697
698                 _fitContentArea: function ( page, parent ) {
699                         if ( typeof parent == "undefined" ) {
700                                 parent = window;
701                         }
702
703                         var $page = $( page ),
704                                 $content = $( ".ui-content:visible:first" ),
705                                 hh = $( ".ui-header:visible" ).outerHeight() || 0,
706                                 fh = $( ".ui-footer:visible" ).outerHeight() || 0,
707                                 pt = parseFloat( $content.css( "padding-top" ) ),
708                                 pb = parseFloat( $content.css( "padding-bottom" ) ),
709                                 wh = ( ( parent === window ) ? window.innerHeight : $( parent ).height() ),
710                                 height = wh - ( hh + fh ) - ( pt + pb );
711
712                         $content.offset( {
713                                 top: ( hh + pt )
714                         }).height( height );
715                 },
716
717                 width: function ( value ) {
718                         var self = this,
719                                 args = arguments,
720                                 view = self.element;
721
722                         if ( args.length === 0 ) {
723                                 return view.width();
724                         }
725                         if ( args.length === 1 ) {
726                                 view.width( value );
727                                 self._resize();
728                         }
729                 },
730
731                 height: function ( value ) {
732                         var self = this,
733                                 view = self.element,
734                                 args = arguments;
735
736                         if ( args.length === 0 ) {
737                                 return view.height();
738                         }
739                         if ( args.length === 1 ) {
740                                 view.height( value );
741                                 self._resize();
742                         }
743                 },
744
745                 fullScreen: function ( value ) {
746                         var self = this,
747                                 view = self.element,
748                                 control = view.parent().find( ".ui-multimediaview-control" ),
749                                 fullscreenButton = control.find( ".ui-fullscreenbutton" ),
750                                 args = arguments,
751                                 option = self.options,
752                                 currentPage = $( ".ui-page-active" );
753
754                         if ( args.length === 0 ) {
755                                 return option.fullScreen;
756                         }
757                         if ( args.length === 1 ) {
758                                 view.parents( ".ui-content" ).scrollview( "scrollTo", 0, 0 );
759
760                                 this.options.fullScreen = value;
761                                 if ( value ) {
762                                         currentPage.children( ".ui-header" ).hide();
763                                         currentPage.children( ".ui-footer" ).hide();
764                                         currentPage.addClass( "ui-fullscreen-page" );
765                                         this._fitContentArea( currentPage );
766                                         fullscreenButton.removeClass( "ui-fullscreen-on" ).addClass( "ui-fullscreen-off" );
767                                 } else {
768                                         currentPage.children( ".ui-header" ).show();
769                                         currentPage.children( ".ui-footer" ).show();
770                                         currentPage.removeClass( "ui-fullscreen-page" );
771                                         this._fitContentArea( currentPage );
772                                         fullscreenButton.removeClass( "ui-fullscreen-off" ).addClass( "ui-fullscreen-on" );
773                                 }
774                                 self._resize();
775                         }
776                 },
777
778                 refresh: function () {
779                         this._resize();
780                 }
781         });
782
783         $( document ).bind( "pagecreate create", function ( e ) {
784                 $.tizen.multimediaview.prototype.enhanceWithin( e.target );
785         });
786 } ( jQuery, document, window ) );