Export 0.2.3
[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.addClass( "ui-" + self.role + "-fullscreen" );
282                                 view.offset( {
283                                         top: 0,
284                                         left: 0
285                                 });
286                         } else {
287                                 if ( !self.backupView ) {
288                                         return;
289                                 }
290
291                                 view.removeClass( "ui-" + self.role + "-fullscreen" );
292                                 view.css( {
293                                         "width": self.backupView.width,
294                                         "height": self.backupView.height,
295                                         "position": self.backupView.position,
296                                         "z-index": self.backupView.zindex
297                                 });
298                                 self.backupView = null;
299                         }
300                         parent.show();
301                 },
302
303                 _addEvent: function () {
304                         var self = this,
305                                 view = self.element,
306                                 option = self.options,
307                                 viewElement = view[0],
308                                 control = view.parent().find( ".ui-multimediaview-control" ),
309                                 playpauseButton = control.find( ".ui-playpausebutton" ),
310                                 timestampLabel = control.find( ".ui-timestamplabel" ),
311                                 durationLabel = control.find( ".ui-durationlabel" ),
312                                 volumeButton = control.find( ".ui-volumebutton" ),
313                                 volumeControl = control.find( ".ui-volumecontrol" ),
314                                 volumeBar = volumeControl.find( ".ui-volumebar" ),
315                                 volumeGuide = volumeControl.find( ".ui-guide" ),
316                                 volumeHandle = volumeControl.find( ".ui-handler" ),
317                                 fullscreenButton = control.find( ".ui-fullscreenbutton" ),
318                                 seekBar = control.find( ".ui-seekbar" ),
319                                 durationBar = seekBar.find( ".ui-duration" ),
320                                 currenttimeBar = seekBar.find( ".ui-currenttime" );
321
322                         $( document ).unbind( ".multimediaview" ).bind( "pagechange.multimediaview", function ( e ) {
323                                 var $page = $( e.target );
324                                 if ( $page.find( view ).length > 0 && viewElement.autoplay ) {
325                                         viewElement.play();
326                                 }
327
328                                 if ( option.controls ) {
329                                         control.show();
330                                         self._resize();
331                                 }
332                         }).bind( "pagebeforechange.multimediaview", function ( e ) {
333                                 if ( viewElement.played.length !== 0 ) {
334                                         viewElement.pause();
335                                         control.hide();
336                                 }
337                         });
338
339                         $( window ).unbind( ".multimediaview" ).bind( "resize.multimediaview orientationchange.multimediaview", function ( e ) {
340                                 if ( !option.controls ) {
341                                         return;
342                                 }
343                                 var $page = $( e.target ),
344                                         $scrollview = view.parents( ".ui-scrollview-clip" );
345
346                                 $scrollview.each( function ( i ) {
347                                         if ( $.data( this, "scrollview" ) ) {
348                                                 $( this ).scrollview( "scrollTo", 0, 0 );
349                                         }
350                                 });
351
352                                 // for maintaining page layout
353                                 if ( !option.fullScreen ) {
354                                         $( ".ui-footer:visible" ).show();
355                                 } else {
356                                         $( ".ui-footer" ).hide();
357                                         self._fitContentArea( $page );
358                                 }
359
360                                 self._resize();
361                         });
362
363                         view.bind( "loadedmetadata.multimediaview", function ( e ) {
364                                 if ( !isNaN( viewElement.duration ) ) {
365                                         durationLabel.find( "p" ).text( self._convertTimeFormat( viewElement.duration ) );
366                                 }
367                                 self._resize();
368                         }).bind( "timeupdate.multimediaview", function ( e ) {
369                                 self._updateSeekBar();
370                         }).bind( "play.multimediaview", function ( e ) {
371                                 playpauseButton.removeClass( "ui-play-icon" ).addClass( "ui-pause-icon" );
372                         }).bind( "pause.multimediaview", function ( e ) {
373                                 playpauseButton.removeClass( "ui-pause-icon" ).addClass( "ui-play-icon" );
374                         }).bind( "ended.multimediaview", function ( e ) {
375                                 if ( typeof viewElement.loop == "undefined" || viewElement.loop === "" ) {
376                                         self.stop();
377                                 }
378                         }).bind( "volumechange.multimediaview", function ( e ) {
379                                 if ( viewElement.volume < 0.1 ) {
380                                         viewElement.muted = true;
381                                         volumeButton.removeClass( "ui-volume-icon" ).addClass( "ui-mute-icon" );
382                                 } else {
383                                         viewElement.muted = false;
384                                         volumeButton.removeClass( "ui-mute-icon" ).addClass( "ui-volume-icon" );
385                                 }
386
387                                 if ( !self.isVolumeHide ) {
388                                         self._updateVolumeState();
389                                 }
390                         }).bind( "durationchange.multimediaview", function ( e ) {
391                                 if ( !isNaN( viewElement.duration ) ) {
392                                         durationLabel.find( "p" ).text( self._convertTimeFormat( viewElement.duration ) );
393                                 }
394                                 self._resize();
395                         }).bind( "error.multimediaview", function ( e ) {
396                                 switch ( e.target.error.code ) {
397                                 case e.target.error.MEDIA_ERR_ABORTED:
398                                         window.alert( 'You aborted the video playback.' );
399                                         break;
400                                 case e.target.error.MEDIA_ERR_NETWORK:
401                                         window.alert( 'A network error caused the video download to fail part-way.' );
402                                         break;
403                                 case e.target.error.MEDIA_ERR_DECODE:
404                                         window.alert( 'The video playback was aborted due to a corruption problem or because the video used features your browser did not support.' );
405                                         break;
406                                 case e.target.error.MEDIA_ERR_SRC_NOT_SUPPORTED:
407                                         window.alert( 'The video could not be loaded, either because the server or network failed or because the format is not supported.' );
408                                         break;
409                                 default:
410                                         window.alert( 'An unknown error occurred.' );
411                                         break;
412                                 }
413                         }).bind( "vclick.multimediaview", function ( e ) {
414                                 if ( !self.options.controls ) {
415                                         return;
416                                 }
417
418                                 control.fadeToggle( "fast", function () {
419                                         var offset = control.offset();
420                                         self.isControlHide = !self.isControlHide;
421                                         if ( self.options.mediatype == "video" ) {
422                                                 self._startTimer();
423                                         }
424                                 });
425                                 self._resize();
426                         });
427
428                         playpauseButton.bind( "vclick.multimediaview", function () {
429                                 self._endTimer();
430
431                                 if ( viewElement.paused ) {
432                                         viewElement.play();
433                                 } else {
434                                         viewElement.pause();
435                                 }
436
437                                 if ( self.options.mediatype == "video" ) {
438                                         self._startTimer();
439                                 }
440                         });
441
442                         fullscreenButton.bind( "vclick.multimediaview", function ( e ) {
443                                 self.fullScreen( !self.options.fullScreen );
444                                 control.fadeIn( "fast" );
445                                 self._endTimer();
446                                 e.preventDefault();
447                                 e.stopPropagation();
448                         });
449
450                         seekBar.bind( "vmousedown.multimediaview", function ( e ) {
451                                 var x = e.clientX,
452                                         duration = viewElement.duration,
453                                         durationOffset = durationBar.offset(),
454                                         durationWidth = durationBar.width(),
455                                         timerate = ( x - durationOffset.left ) / durationWidth,
456                                         time = duration * timerate;
457
458                                 viewElement.currentTime = time;
459
460                                 self._endTimer();
461
462                                 e.preventDefault();
463                                 e.stopPropagation();
464
465                                 $( document ).bind( "vmousemove.multimediaview", function ( e ) {
466                                         var x = e.clientX,
467                                                 timerate = ( x - durationOffset.left ) / durationWidth;
468
469                                         viewElement.currentTime = duration * timerate;
470
471                                         e.preventDefault();
472                                         e.stopPropagation();
473                                 }).bind( "vmouseup.multimediaview", function () {
474                                         $( document ).unbind( "vmousemove.multimediaview vmouseup.multimediaview" );
475                                         if ( viewElement.paused ) {
476                                                 viewElement.pause();
477                                         } else {
478                                                 viewElement.play();
479                                         }
480                                 });
481                         });
482
483                         volumeButton.bind( "vclick.multimediaview", function () {
484                                 if ( self.isVolumeHide ) {
485                                         var view = self.element,
486                                                 volume = viewElement.volume;
487
488                                         self.isVolumeHide = false;
489                                         self._resize();
490                                         volumeControl.fadeIn( "fast" );
491                                         self._updateVolumeState();
492                                         self._updateSeekBar();
493                                 } else {
494                                         self.isVolumeHide = true;
495                                         volumeControl.fadeOut( "fast", function () {
496                                                 self._resize();
497                                         });
498                                         self._updateSeekBar();
499                                 }
500                         });
501
502                         volumeBar.bind( "vmousedown.multimediaview", function ( e ) {
503                                 var baseX = e.clientX,
504                                         volumeGuideLeft = volumeGuide.offset().left,
505                                         volumeGuideWidth = volumeGuide.width(),
506                                         volumeBase = volumeGuideLeft + volumeGuideWidth,
507                                         handlerOffset = volumeHandle.offset(),
508                                         volumerate = ( baseX - volumeGuideLeft ) / volumeGuideWidth,
509                                         currentVolume = ( baseX - volumeGuideLeft ) / volumeGuideWidth;
510
511                                 self._endTimer();
512                                 self._setVolume( currentVolume.toFixed( 2 ) );
513
514                                 e.preventDefault();
515                                 e.stopPropagation();
516
517                                 $( document ).bind( "vmousemove.multimediaview", function ( e ) {
518                                         var currentX = e.clientX,
519                                                 currentVolume = ( currentX - volumeGuideLeft ) / volumeGuideWidth;
520
521                                         self._setVolume( currentVolume.toFixed( 2 ) );
522
523                                         e.preventDefault();
524                                         e.stopPropagation();
525                                 }).bind( "vmouseup.multimediaview", function () {
526                                         $( document ).unbind( "vmousemove.multimediaview vmouseup.multimediaview" );
527
528                                         if ( self.options.mediatype == "video" ) {
529                                                 self._startTimer();
530                                         }
531                                 });
532                         });
533                 },
534
535                 _removeEvent: function () {
536                         var self = this,
537                                 view = self.element,
538                                 control = view.parent().find( ".ui-multimediaview-control" ),
539                                 playpauseButton = control.find( ".ui-playpausebutton" ),
540                                 fullscreenButton = control.find( ".ui-fullscreenbutton" ),
541                                 seekBar = control.find( ".ui-seekbar" ),
542                                 volumeControl = control.find( ".ui-volumecontrol" ),
543                                 volumeBar = volumeControl.find( ".ui-volumebar" ),
544                                 volumeHandle = volumeControl.find( ".ui-handler" );
545
546                         view.unbind( ".multimediaview" );
547                         playpauseButton.unbind( ".multimediaview" );
548                         fullscreenButton.unbind( ".multimediaview" );
549                         seekBar.unbind( ".multimediaview" );
550                         volumeBar.unbind( ".multimediaview" );
551                         volumeHandle.unbind( ".multimediaview" );
552                 },
553
554                 _createControl: function () {
555                         var self = this,
556                                 view = self.element,
557                                 control = $( "<span></span>" ),
558                                 playpauseButton = $( "<span></span>" ),
559                                 seekBar = $( "<span></span>" ),
560                                 timestampLabel = $( "<span><p>00:00:00</p></span>" ),
561                                 durationLabel = $( "<span><p>00:00:00</p></span>" ),
562                                 volumeButton = $( "<span></span>" ),
563                                 volumeControl = $( "<span></span>" ),
564                                 volumeBar = $( "<div></div>" ),
565                                 volumeGuide = $( "<span></span>" ),
566                                 volumeValue = $( "<span></span>" ),
567                                 volumeHandle = $( "<span></span>" ),
568                                 fullscreenButton = $( "<span></span>" ),
569                                 durationBar = $( "<span></span>" ),
570                                 currenttimeBar = $( "<span></span>" );
571
572                         control.addClass( "ui-" + self.role + "-control" );
573                         playpauseButton.addClass( "ui-playpausebutton ui-button" );
574                         seekBar.addClass( "ui-seekbar" );
575                         timestampLabel.addClass( "ui-timestamplabel" );
576                         durationLabel.addClass( "ui-durationlabel" );
577                         volumeButton.addClass( "ui-volumebutton ui-button" );
578                         fullscreenButton.addClass( "ui-fullscreenbutton ui-button" );
579                         durationBar.addClass( "ui-duration" );
580                         currenttimeBar.addClass( "ui-currenttime" );
581                         volumeControl.addClass( "ui-volumecontrol" );
582                         volumeBar.addClass( "ui-volumebar" );
583                         volumeGuide.addClass( "ui-guide" );
584                         volumeValue.addClass( "ui-value" );
585                         volumeHandle.addClass( "ui-handler" );
586
587                         seekBar.append( durationBar ).append( currenttimeBar ).append( durationLabel ).append( timestampLabel );
588
589                         playpauseButton.addClass( "ui-play-icon" );
590                         volumeButton.addClass( view[0].muted ? "ui-mute-icon" : "ui-volume-icon" );
591                         volumeBar.append( volumeGuide ).append( volumeValue ).append( volumeHandle );
592                         volumeControl.append( volumeBar );
593
594                         control.append( playpauseButton ).append( seekBar ).append( volumeControl ).append( volumeButton );
595
596                         if ( self.element[0].nodeName === "VIDEO" ) {
597                                 $( fullscreenButton ).addClass( "ui-fullscreen-on" );
598                                 control.append( fullscreenButton );
599                         }
600                         volumeControl.hide();
601
602                         return control;
603                 },
604
605                 _startTimer: function ( duration ) {
606                         this._endTimer();
607
608                         if ( !duration ) {
609                                 duration = 3000;
610                         }
611
612                         var self = this,
613                                 view = self.element,
614                                 control = view.parent().find( ".ui-multimediaview-control" ),
615                                 volumeControl = control.find( ".ui-volumecontrol" );
616
617                         self.controlTimer = setTimeout( function () {
618                                 self.isVolumeHide = true;
619                                 self.isControlHide = true;
620                                 self.controlTimer = null;
621                                 volumeControl.hide();
622                                 control.fadeOut( "fast" );
623                         }, duration );
624                 },
625
626                 _endTimer: function () {
627                         if ( this.controlTimer ) {
628                                 clearTimeout( this.controlTimer );
629                                 this.controlTimer = null;
630                         }
631                 },
632
633                 _convertTimeFormat: function ( systime ) {
634                         var ss = parseInt( systime % 60, 10 ).toString(),
635                                 mm = parseInt( ( systime / 60 ) % 60, 10 ).toString(),
636                                 hh = parseInt( systime / 3600, 10 ).toString(),
637                                 time =  ( ( hh.length < 2  ) ? "0" + hh : hh ) + ":" +
638                                                 ( ( mm.length < 2  ) ? "0" + mm : mm ) + ":" +
639                                                 ( ( ss.length < 2  ) ? "0" + ss : ss );
640
641                         return time;
642                 },
643
644                 _updateSeekBar: function ( currenttime ) {
645                         var self = this,
646                                 view = self.element,
647                                 duration = view[0].duration,
648                                 control = view.parent().find( ".ui-multimediaview-control" ),
649                                 seekBar = control.find(  ".ui-seekbar"  ),
650                                 durationBar = seekBar.find( ".ui-duration" ),
651                                 currenttimeBar = seekBar.find( ".ui-currenttime" ),
652                                 timestampLabel = control.find( ".ui-timestamplabel" ),
653                                 durationOffset = durationBar.offset(),
654                                 durationWidth = durationBar.width(),
655                                 durationHeight = durationBar.height(),
656                                 timebarWidth = 0;
657
658                         if ( typeof currenttime == "undefined" ) {
659                                 currenttime = view[0].currentTime;
660                         }
661                         timebarWidth = parseInt( currenttime / duration * durationWidth, 10 );
662                         durationBar.offset( durationOffset );
663                         currenttimeBar.offset( durationOffset ).width( timebarWidth );
664                         timestampLabel.find( "p" ).text( self._convertTimeFormat( currenttime ) );
665                 },
666
667                 _updateVolumeState: function () {
668                         var self = this,
669                                 view = self.element,
670                                 control = view.parent().find( ".ui-multimediaview-control" ),
671                                 volumeControl = control.find( ".ui-volumecontrol" ),
672                                 volumeButton = control.find( ".ui-volumebutton" ),
673                                 volumeBar = volumeControl.find( ".ui-volumebar" ),
674                                 volumeGuide = volumeControl.find( ".ui-guide" ),
675                                 volumeValue = volumeControl.find( ".ui-value" ),
676                                 volumeHandle = volumeControl.find( ".ui-handler" ),
677                                 handlerWidth = volumeHandle.width(),
678                                 handlerHeight = volumeHandle.height(),
679                                 volumeGuideHeight = volumeGuide.height(),
680                                 volumeGuideWidth = volumeGuide.width(),
681                                 volumeGuideTop = 0,
682                                 volumeGuideLeft = 0,
683                                 volumeBase = 0,
684                                 handlerOffset = null,
685                                 volume = view[0].volume;
686
687                         volumeGuideTop = parseInt( volumeGuide.offset().top, 10 );
688                         volumeGuideLeft = parseInt( volumeGuide.offset().left, 10 );
689                         volumeBase = volumeGuideLeft;
690                         handlerOffset = volumeHandle.offset();
691                         handlerOffset.top = volumeGuideTop - parseInt( ( handlerHeight - volumeGuideHeight ) / 2, 10 );
692                         handlerOffset.left = volumeBase + parseInt( volumeGuideWidth * volume, 10 ) - parseInt( handlerWidth / 2, 10 );
693                         volumeHandle.offset( handlerOffset );
694                         volumeValue.width( parseInt( volumeGuideWidth * ( volume ), 10 ) );
695                 },
696
697                 _setVolume: function ( value ) {
698                         var viewElement = this.element[0];
699
700                         if ( value < 0.0 || value > 1.0 ) {
701                                 return;
702                         }
703
704                         viewElement.volume = value;
705                 },
706
707                 _fitContentArea: function ( page, parent ) {
708                         if ( typeof parent == "undefined" ) {
709                                 parent = window;
710                         }
711
712                         var $page = $( page ),
713                                 $content = $( ".ui-content:visible:first" ),
714                                 hh = $( ".ui-header:visible" ).outerHeight() || 0,
715                                 fh = $( ".ui-footer:visible" ).outerHeight() || 0,
716                                 pt = parseFloat( $content.css( "padding-top" ) ),
717                                 pb = parseFloat( $content.css( "padding-bottom" ) ),
718                                 wh = ( ( parent === window ) ? window.innerHeight : $( parent ).height() ),
719                                 height = wh - ( hh + fh ) - ( pt + pb );
720
721                         $content.offset( {
722                                 top: ( hh + pt )
723                         }).height( height );
724                 },
725
726                 width: function ( value ) {
727                         var self = this,
728                                 args = arguments,
729                                 view = self.element;
730
731                         if ( args.length === 0 ) {
732                                 return view.width();
733                         }
734                         if ( args.length === 1 ) {
735                                 view.width( value );
736                                 self._resize();
737                         }
738                 },
739
740                 height: function ( value ) {
741                         var self = this,
742                                 view = self.element,
743                                 args = arguments;
744
745                         if ( args.length === 0 ) {
746                                 return view.height();
747                         }
748                         if ( args.length === 1 ) {
749                                 view.height( value );
750                                 self._resize();
751                         }
752                 },
753
754                 fullScreen: function ( value ) {
755                         var self = this,
756                                 view = self.element,
757                                 control = view.parent().find( ".ui-multimediaview-control" ),
758                                 fullscreenButton = control.find( ".ui-fullscreenbutton" ),
759                                 args = arguments,
760                                 option = self.options,
761                                 currentPage = $( ".ui-page-active" );
762
763                         if ( args.length === 0 ) {
764                                 return option.fullScreen;
765                         }
766                         if ( args.length === 1 ) {
767                                 view.parents( ".ui-content" ).scrollview( "scrollTo", 0, 0 );
768
769                                 this.options.fullScreen = value;
770                                 if ( value ) {
771                                         currentPage.children( ".ui-header" ).hide();
772                                         currentPage.children( ".ui-footer" ).hide();
773                                         this._fitContentArea( currentPage );
774                                         fullscreenButton.removeClass( "ui-fullscreen-on" ).addClass( "ui-fullscreen-off" );
775                                 } else {
776                                         currentPage.children( ".ui-header" ).show();
777                                         currentPage.children( ".ui-footer" ).show();
778                                         this._fitContentArea( currentPage );
779                                         fullscreenButton.removeClass( "ui-fullscreen-off" ).addClass( "ui-fullscreen-on" );
780                                 }
781                                 self._resize();
782                         }
783                 },
784
785                 refresh: function () {
786                         this._resize();
787                 }
788         });
789
790         $( document ).bind( "pagecreate create", function ( e ) {
791                 $.tizen.multimediaview.prototype.enhanceWithin( e.target );
792         });
793 } ( jQuery, document, window ) );