You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by pp...@apache.org on 2013/08/26 17:33:46 UTC

[12/52] [abbrv] [cordova-tizen] tizen SDK 2.2 support

http://git-wip-us.apache.org/repos/asf/cordova-tizen/blob/e21e0780/templates/CordovaTizenWebUIFrameworkTemplate/project/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.multimediaview.js
----------------------------------------------------------------------
diff --git a/templates/CordovaTizenWebUIFrameworkTemplate/project/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.multimediaview.js b/templates/CordovaTizenWebUIFrameworkTemplate/project/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.multimediaview.js
new file mode 100644
index 0000000..229f5fc
--- /dev/null
+++ b/templates/CordovaTizenWebUIFrameworkTemplate/project/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.multimediaview.js
@@ -0,0 +1,787 @@
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+//>>description: Shows multimedia and its controls
+//>>label: Multimedia view
+//>>group: Tizen:Widgets
+
+define( [ 
+	'jquery',
+	'../jquery.mobile.tizen.scrollview'
+	], function ( jQuery ) {
+
+//>>excludeEnd("jqmBuildExclude");
+
+/* ***************************************************************************
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * ***************************************************************************
+ *
+ * Authors: Yonghwi Park <yo...@samsung.com>
+ *		 Wonseop Kim <wo...@samsung.com>
+*/
+
+/**
+ *
+ * MultiMediaView is a widget that lets the user view and handle multimedia contents.
+ * Video and audio elements are coded as standard HTML elements and enhanced by the 
+ * MultiMediaview to make them attractive and usable on a mobile device.
+ *
+ * HTML Attributes:
+ *			data-theme : Set a theme of widget.
+ *				If this value is not defined, widget will use parent`s theme. (optional)
+ *			data-controls : If this value is 'true', widget will use belonging controller.
+ *				If this value is 'false', widget will use browser`s controller.
+ *				Default value is 'true'.
+ *			data-full-screen : Set a status that full-screen when inital start.
+ *				Default value is 'false'.
+ *
+ * APIs:
+ *			width( [number] )
+ *					: Get or set the width of widget.
+ *					The first argument is the width of widget.
+ *					If no first argument is specified, will act as a getter.
+ *			height( [number] )
+ *					: Get or set the height of widget.
+ *					The first argument is the height of widget.
+ *					If no first argument is specified, will act as a getter.
+ *			fullScreen( [boolean] )
+ *					: Get or Set the status of full-screen.
+ *					If no first argument is specified, will act as a getter.
+ *
+ * Events:
+ *
+ *			N/A
+ *
+ * Examples:
+ *
+ *			VIDEO :
+ *				<video data-controls="true" style="width:100%;">
+ *					<source src="media/oceans-clip.mp4" type="video/mp4" />
+ *					Your browser does not support the video tag.
+ *				</video>
+ *
+ *			AUDIO :
+ *				<audio data-controls="true" style="width:100%;">
+ *					<source src="media/Over the horizon.mp3" type="audio/mp3" />
+ *					Your browser does not support the audio tag.
+ *				</audio>
+ *
+ */
+/**
+	@class MutimediaView
+	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.
+
+	To add a multimedia view widget to the application, use the following code:
+	
+		// Video player control
+		<video data-controls="true" style="width:100%;">
+		<source src="<VIDEO_FILE_URL>" type="video/mp4" /> Your browser does not support the video tag. </video>
+		// Audio player control
+		<audio data-controls="true" style="width:100%;"> <source src="<AUDIO_FILE_URL>" type="audio/mp3" /> Your browser does not support the audio tag.
+		</audio>
+*/
+/**
+	@property {Boolean} data-control
+	Sets the controls for the widget.
+	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.
+*/
+/**
+	@property {Boolean} data-full-screen
+	Defines whether the widget opens in the fullscreen view mode.
+	The default value is false.
+*/
+/**
+	@property {String} data-theme
+	Sets the widget theme.
+	If the value is not set, the parent control's theme is used
+*/
+/**
+	@method width
+	The width method is used to get (if no value is defined) or set the multimedia view widget width:
+		<video>
+			 <source src="test.mp4" type="video/mp4" />
+		</video>
+		$(".selector").multimediaview("width", [value]);
+*/
+/**
+	@method height
+	The height method is used to get (if no value is defined) or set the multimedia view widget height:
+		<video>
+			<source src="test.mp4" type="video/mp4" />
+		</video>
+		$(".selector").multimediaview("height", [value]);
+*/
+/**
+	@method fullScreen
+	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.
+
+		<video>
+			<source src="test.mp4" type="video/mp4" />
+		</video>
+		$(".selector").multimediaview("fullScreen", [value]);
+*/
+( function ( $, document, window, undefined ) {
+	$.widget( "tizen.multimediaview", $.mobile.widget, {
+		options: {
+			theme: null,
+			controls: true,
+			fullScreen: false,
+			initSelector: "video, audio"
+		},
+
+		_create: function () {
+			var self = this,
+				view = self.element,
+				viewElement = view[0],
+				isVideo = ( viewElement.nodeName === "VIDEO" ),
+				option = self.options,
+				parentTheme = $.mobile.getInheritedTheme( view, "s" ),
+				theme = option.theme || parentTheme,
+				width = viewElement.style.getPropertyValue( "width" ) || "",
+				wrap = $( "<div class='ui-multimediaview-wrap ui-multimediaview-" + theme + "'>" ),
+				control = null;
+
+			$.extend( this, {
+				role: null,
+				controlTimer: null,
+				isVolumeHide: true,
+				backupView: null,
+				_reserveVolume: -1,
+				_isVideo: isVideo
+			});
+
+			view.addClass( "ui-multimediaview" );
+			control = self._createControl();
+			control.hide();
+
+			$( ".ui-button", control ).addClass( "ui-shadow ui-btn-corner-all" );
+			$( ".ui-volumecontrol .ui-handle", control ).addClass( "ui-shadow ui-btn-corner-circle" );
+
+			view.wrap( wrap ).after( control );
+
+			if ( isVideo ) {
+				control.addClass( "ui-multimediaview-video" );
+			} else {
+				self.width( width );
+				self.options.fullScreen = false;
+			}
+
+			if ( option.controls && view.attr( "controls" ) ) {
+				view.removeAttr( "controls" );
+			}
+
+			self._addEvent();
+		},
+
+		_resize: function () {
+			this._resizeFullscreen( this.options.fullScreen );
+			this._resizeControl();
+			this._updateSeekBar();
+			this._updateVolumeState();
+		},
+
+		_resizeControl: function () {
+			var self = this,
+				view = self.element,
+				viewElement = view[0],
+				isVideo = self._isVideo,
+				wrap = view.parent( ".ui-multimediaview-wrap" ),
+				control = wrap.find( ".ui-multimediaview-control" ),
+				buttons = control.find( ".ui-button" ),
+				playpauseButton = control.find( ".ui-playpausebutton" ),
+				seekBar = control.find( ".ui-seekbar" ),
+				durationLabel = control.find( ".ui-durationlabel" ),
+				timestampLabel = control.find( ".ui-timestamplabel" ),
+				volumeControl = control.find( ".ui-volumecontrol" ),
+				volumeBar = volumeControl.find( ".ui-volumebar" ),
+				width = ( isVideo ? view.width() : wrap.width() ),
+				height = ( isVideo ? view.height() : control.height() ),
+				offset = view.offset(),
+				controlHeight = control.height(),
+				availableWidth = 0,
+				controlOffset = null;
+
+			if ( control ) {
+				if ( isVideo ) {
+					controlOffset = control.offset();
+					controlOffset.left = offset.left;
+					controlOffset.top = offset.top + height - controlHeight;
+					control.offset( controlOffset );
+				}
+				control.width( width );
+			}
+
+			if ( seekBar ) {
+				availableWidth = control.width() - ( buttons.outerWidth( true ) * buttons.length );
+				availableWidth -= ( parseInt( buttons.eq( 0 ).css( "margin-left" ), 10 ) + parseInt( buttons.eq( 0 ).css( "margin-right" ), 10 ) ) * buttons.length;
+				if ( !self.isVolumeHide ) {
+					availableWidth -= volumeControl.outerWidth( true );
+				}
+				seekBar.width( availableWidth );
+			}
+
+			if ( durationLabel && !isNaN( viewElement.duration ) ) {
+				durationLabel.find( "p" ).text( self._convertTimeFormat( viewElement.duration ) );
+			}
+
+			if ( viewElement.autoplay && viewElement.paused === false ) {
+				playpauseButton.removeClass( "ui-play-icon" ).addClass( "ui-pause-icon" );
+			}
+
+			if ( seekBar.width() < ( volumeBar.width() + timestampLabel.width() + durationLabel.width() ) ) {
+				durationLabel.hide();
+			} else {
+				durationLabel.show();
+			}
+		},
+
+		_resizeFullscreen: function ( isFullscreen ) {
+			if ( !this._isVideo ) {
+				return;
+			}
+
+			var self = this,
+				view = self.element,
+				viewElement = view[0],
+				wrap = view.parent( ".ui-multimediaview-wrap" ),
+				control = wrap.find( ".ui-multimediaview-control" ),
+				fullscreenButton = control.find( ".ui-fullscreenbutton" ),
+				currentPage = $( ".ui-page-active" ),
+				playpauseButton = control.find( ".ui-playpausebutton" ),
+				timestampLabel = control.find( ".ui-timestamplabel" ),
+				seekBar = control.find( ".ui-seekbar" ),
+				durationBar = seekBar.find( ".ui-duration" ),
+				currenttimeBar = seekBar.find( ".ui-currenttime" ),
+				body = $( "body" )[0],
+				header = currentPage.children( ".ui-header" ),
+				footer = currentPage.children( ".ui-footer" ),
+				docWidth = 0,
+				docHeight = 0;
+
+			if ( isFullscreen ) {
+				if ( !self.backupView ) {
+					self.backupView = {
+						width: viewElement.style.getPropertyValue( "width" ) || "",
+						height: viewElement.style.getPropertyValue( "height" ) || "",
+						position: view.css( "position" ),
+						zindex: view.css( "z-index" ),
+						wrapHeight: wrap[0].style.getPropertyValue( "height" ) || ""
+					};
+				}
+				docWidth = body.clientWidth;
+				docHeight = body.clientHeight - 1;
+
+				header.hide();
+				footer.hide();
+				view.parents().each( function ( e ) {
+					var element = $( this );
+					element.addClass( "ui-fullscreen-parents" )
+						.siblings()
+						.addClass( "ui-multimediaview-siblings-off" );
+				});
+				fullscreenButton.removeClass( "ui-fullscreen-on" ).addClass( "ui-fullscreen-off" );
+
+				wrap.height( docHeight );
+				view.width( docWidth ).height( docHeight );
+			} else {
+				if ( !self.backupView ) {
+					return;
+				}
+
+				header.show();
+				footer.show();
+				view.parents().each( function ( e ) {
+					var element = $( this );
+					element.removeClass( "ui-fullscreen-parents" )
+						.siblings()
+						.removeClass( "ui-multimediaview-siblings-off" );
+				});
+
+				fullscreenButton.removeClass( "ui-fullscreen-off" ).addClass( "ui-fullscreen-on" );
+
+				wrap.css( "height", self.backupView.wrapHeight );
+				view.css( {
+					"width": self.backupView.width,
+					"height": self.backupView.height,
+					"position": self.backupView.position,
+					"z-index": self.backupView.zindex
+				});
+				self.backupView = null;
+
+				$( window ).trigger( "throttledresize" );
+			}
+		},
+
+		_addEvent: function () {
+			var self = this,
+				view = self.element,
+				option = self.options,
+				viewElement = view[0],
+				isVideo = self._isVideo,
+				control = view.parent( ".ui-multimediaview-wrap" ).find( ".ui-multimediaview-control" ),
+				playpauseButton = control.find( ".ui-playpausebutton" ),
+				timestampLabel = control.find( ".ui-timestamplabel" ),
+				durationLabel = control.find( ".ui-durationlabel" ),
+				volumeButton = control.find( ".ui-volumebutton" ),
+				volumeControl = control.find( ".ui-volumecontrol" ),
+				volumeBar = volumeControl.find( ".ui-volumebar" ),
+				volumeGuide = volumeControl.find( ".ui-guide" ),
+				volumeHandle = volumeControl.find( ".ui-handle" ),
+				fullscreenButton = control.find( ".ui-fullscreenbutton" ),
+				seekBar = control.find( ".ui-seekbar" ),
+				durationBar = seekBar.find( ".ui-duration" ),
+				currenttimeBar = seekBar.find( ".ui-currenttime" ),
+				touchStartEvt = ( $.support.touch ? "touchstart" : "mousedown" ),
+				touchMoveEvt = ( $.support.touch ? "touchmove" : "mousemove" ) + ".multimediaview",
+				touchEndEvt = ( $.support.touch ? "touchend" : "mouseup" ) + ".multimediaview",
+				$document = $( document );
+
+			view.bind( "loadedmetadata.multimediaview", function ( e ) {
+				if ( !isNaN( viewElement.duration ) ) {
+					durationLabel.find( "p" ).text( self._convertTimeFormat( viewElement.duration ) );
+				}
+				self._resize();
+			}).bind( "timeupdate.multimediaview", function ( e ) {
+				self._updateSeekBar();
+			}).bind( "play.multimediaview", function ( e ) {
+				playpauseButton.removeClass( "ui-play-icon" ).addClass( "ui-pause-icon" );
+			}).bind( "pause.multimediaview", function ( e ) {
+				playpauseButton.removeClass( "ui-pause-icon" ).addClass( "ui-play-icon" );
+			}).bind( "ended.multimediaview", function ( e ) {
+				if ( typeof viewElement.loop == "undefined" || viewElement.loop === "" ) {
+					self.stop();
+				}
+			}).bind( "volumechange.multimediaview", function ( e ) {
+				if ( viewElement.muted && viewElement.volume > 0.1 ) {
+					volumeButton.removeClass( "ui-volume-icon" ).addClass( "ui-mute-icon" );
+					self._reserveVolume = viewElement.volume;
+					viewElement.volume = 0;
+				} else if ( self._reserveVolume !== -1 && !viewElement.muted ) {
+					volumeButton.removeClass( "ui-mute-icon" ).addClass( "ui-volume-icon" );
+					viewElement.volume = self._reserveVolume;
+					self._reserveVolume = -1;
+				} else if ( viewElement.volume < 0.1 ) {
+					volumeButton.removeClass( "ui-volume-icon" ).addClass( "ui-mute-icon" );
+				} else {
+					volumeButton.removeClass( "ui-mute-icon" ).addClass( "ui-volume-icon" );
+				}
+
+				if ( !self.isVolumeHide ) {
+					self._updateVolumeState();
+				}
+			}).bind( "durationchange.multimediaview", function ( e ) {
+				if ( !isNaN( viewElement.duration ) ) {
+					durationLabel.find( "p" ).text( self._convertTimeFormat( viewElement.duration ) );
+				}
+				self._resize();
+			}).bind( "click.multimediaview", function ( e ) {
+				if ( !self.options.controls ) {
+					return;
+				}
+
+				control.fadeToggle( "fast" );
+				self._resize();
+			}).bind( "multimediaviewinit", function ( e ) {
+				if ( option.controls ) {
+					control.show();
+				}
+				self._resize();
+			});
+
+			$( ".ui-button", control ).bind( touchStartEvt, function () {
+				var button = $( this ).addClass( "ui-button-down" );
+
+				$document.bind( touchMoveEvt, function () {
+					button.trigger( touchEndEvt );
+				});
+			}).bind( touchEndEvt, function () {
+				$( this ).removeClass( "ui-button-down" );
+				$document.unbind( touchMoveEvt );
+			});
+
+			playpauseButton.bind( "click.multimediaview", function () {
+				self._endTimer();
+
+				if ( viewElement.paused ) {
+					viewElement.play();
+				} else {
+					viewElement.pause();
+				}
+
+				if ( isVideo ) {
+					self._startTimer();
+				}
+			});
+
+			fullscreenButton.bind( "click.multimediaview", function ( e ) {
+				e.preventDefault();
+				self.fullScreen( !self.options.fullScreen );
+				self._resize();
+				self._endTimer();
+				e.stopPropagation();
+			});
+
+			seekBar.bind( touchStartEvt, function ( e ) {
+				var x = $.support.touch ? e.originalEvent.changedTouches[0].pageX : e.pageX,
+					duration = viewElement.duration,
+					durationOffset = durationBar.offset(),
+					durationWidth = durationBar.width(),
+					timerate = ( x - durationOffset.left ) / durationWidth,
+					time = duration * timerate;
+
+				if ( !viewElement.played.length ) {
+					return;
+				}
+
+				viewElement.currentTime = time;
+
+				self._endTimer();
+
+				e.preventDefault();
+
+				control.bind( touchMoveEvt, function ( e ) {
+					var x = $.support.touch ? e.originalEvent.changedTouches[0].pageX : e.pageX,
+						timerate = ( x - durationOffset.left ) / durationWidth;
+
+					viewElement.currentTime = duration * timerate;
+
+					e.stopPropagation();
+				}).bind( touchEndEvt, function () {
+					control.unbind( ".multimediaview" );
+					$document.unbind( touchMoveEvt );
+					if ( viewElement.paused ) {
+						viewElement.pause();
+					} else {
+						viewElement.play();
+					}
+					e.stopPropagation();
+				});
+
+				$document.bind( touchMoveEvt, function () {
+					control.trigger( touchEndEvt );
+				});
+			});
+
+			volumeButton.bind( "click.multimediaview", function () {
+				if ( self.isVolumeHide ) {
+					var view = self.element,
+						volume = viewElement.volume;
+
+					self.isVolumeHide = false;
+					volumeControl.fadeIn( "fast", function () {
+						self._updateVolumeState();
+						self._updateSeekBar();
+					});
+					self._resize();
+				} else {
+					self.isVolumeHide = true;
+					volumeControl.fadeOut( "fast", function () {
+						self._resize();
+					});
+				}
+			});
+
+			volumeBar.bind( touchStartEvt, function ( e ) {
+				var baseX = $.support.touch ? e.originalEvent.changedTouches[0].pageX : e.pageX,
+					volumeGuideLeft = volumeGuide.offset().left,
+					volumeGuideWidth = volumeGuide.width(),
+					volumeBase = volumeGuideLeft + volumeGuideWidth,
+					handlerOffset = volumeHandle.offset(),
+					volumerate = ( baseX - volumeGuideLeft ) / volumeGuideWidth,
+					currentVolume = ( baseX - volumeGuideLeft ) / volumeGuideWidth;
+
+				self._endTimer();
+				volumeHandle.addClass( "ui-button-down" );
+				self._setVolume( currentVolume.toFixed( 2 ) );
+
+				e.preventDefault();
+
+				control.bind( touchMoveEvt, function ( e ) {
+					var x = $.support.touch ? e.originalEvent.changedTouches[0].pageX : e.pageX,
+						currentVolume = ( x - volumeGuideLeft );
+					currentVolume = ( currentVolume < 0 ) ? 0 : currentVolume / volumeGuideWidth;
+					self._setVolume( ( currentVolume > 1 ) ? 1 : currentVolume.toFixed( 2 ) );
+
+					e.stopPropagation();
+				}).bind( touchEndEvt, function () {
+					control.unbind( ".multimediaview" );
+					$document.unbind( touchMoveEvt );
+					volumeHandle.removeClass( "ui-button-down" );
+					e.stopPropagation();
+				});
+
+				$document.bind( touchMoveEvt, function () {
+					control.trigger( touchEndEvt );
+				});
+			});
+		},
+
+		_removeEvent: function () {
+			var view = this.element,
+				control = view.parent( ".ui-multimediaview-wrap" ).find( ".ui-multimediaview-control" ),
+				playpauseButton = control.find( ".ui-playpausebutton" ),
+				fullscreenButton = control.find( ".ui-fullscreenbutton" ),
+				seekBar = control.find( ".ui-seekbar" ),
+				volumeControl = control.find( ".ui-volumecontrol" ),
+				volumeBar = volumeControl.find( ".ui-volumebar" ),
+				volumeHandle = volumeControl.find( ".ui-handle" );
+
+			view.unbind( ".multimediaview" );
+			playpauseButton.unbind( ".multimediaview" );
+			fullscreenButton.unbind( ".multimediaview" );
+			seekBar.unbind( ".multimediaview" );
+			volumeBar.unbind( ".multimediaview" );
+			volumeHandle.unbind( ".multimediaview" );
+		},
+
+		_createControl: function () {
+			var view = this.element,
+				viewElement = view[0],
+				control = $( "<span></span>" ).addClass( "ui-multimediaview-control" ),
+				playpauseButton = $( "<span></span>" ).addClass( "ui-playpausebutton ui-button ui-play-icon" ),
+				seekBar = $( "<span></span>" ).addClass( "ui-seekbar ui-multimediaview-bar" ),
+				timestampLabel = $( "<span><p>00:00:00</p></span>" ).addClass( "ui-timestamplabel" ),
+				durationLabel = $( "<span><p>00:00:00</p></span>" ).addClass( "ui-durationlabel" ),
+				volumeButton = $( "<span></span>" ).addClass( "ui-volumebutton ui-button" ),
+				volumeControl = $( "<span></span>" ).addClass( "ui-volumecontrol" ),
+				volumeBar = $( "<div></div>" ).addClass( "ui-volumebar ui-multimediaview-bar" ),
+				volumeGuide = $( "<span></span>" ).addClass( "ui-guide ui-multimediaview-bar-bg" ),
+				volumeValue = $( "<span></span>" ).addClass( "ui-value ui-multimediaview-bar-highlight" ),
+				volumeHandle = $( "<span></span>" ).addClass( "ui-handle" ),
+				fullscreenButton = $( "<span></span>" ).addClass( "ui-fullscreenbutton ui-button" ),
+				durationBar = $( "<span></span>" ).addClass( "ui-duration ui-multimediaview-bar-bg" ),
+				currenttimeBar = $( "<span></span>" ).addClass( "ui-currenttime ui-multimediaview-bar-highlight" );
+
+			seekBar.append( durationBar ).append( currenttimeBar ).append( durationLabel ).append( timestampLabel );
+
+			volumeButton.addClass( viewElement.muted ? "ui-mute-icon" : "ui-volume-icon" );
+			volumeBar.append( volumeGuide ).append( volumeValue ).append( volumeHandle );
+			volumeControl.append( volumeBar );
+
+			control.append( playpauseButton ).append( seekBar ).append( volumeControl ).append( volumeButton );
+
+			if ( this._isVideo ) {
+				$( fullscreenButton ).addClass( "ui-fullscreen-on" );
+				control.append( fullscreenButton );
+			}
+			volumeControl.hide();
+
+			return control;
+		},
+
+		_startTimer: function ( duration ) {
+			this._endTimer();
+
+			if ( !duration ) {
+				duration = 3000;
+			}
+
+			var self = this,
+				view = self.element,
+				control = view.parent( ".ui-multimediaview-wrap" ).find( ".ui-multimediaview-control" ),
+				volumeControl = control.find( ".ui-volumecontrol" );
+
+			self.controlTimer = setTimeout( function () {
+				self.isVolumeHide = true;
+				self.controlTimer = null;
+				volumeControl.hide();
+				control.fadeOut( "fast" );
+			}, duration );
+		},
+
+		_endTimer: function () {
+			if ( this.controlTimer ) {
+				clearTimeout( this.controlTimer );
+				this.controlTimer = null;
+			}
+		},
+
+		_convertTimeFormat: function ( systime ) {
+			if ( !$.isNumeric( systime ) ) {
+				return "Playback Error";
+			}
+
+			var ss = parseInt( systime % 60, 10 ).toString(),
+				mm = parseInt( ( systime / 60 ) % 60, 10 ).toString(),
+				hh = parseInt( systime / 3600, 10 ).toString(),
+				time =	( ( hh.length < 2  ) ? "0" + hh : hh ) + ":" +
+						( ( mm.length < 2  ) ? "0" + mm : mm ) + ":" +
+						( ( ss.length < 2  ) ? "0" + ss : ss );
+
+			return time;
+		},
+
+		_updateSeekBar: function ( currenttime ) {
+			var view = this.element,
+				viewElement = view[0],
+				duration = viewElement.duration,
+				control = view.parent( ".ui-multimediaview-wrap" ).find( ".ui-multimediaview-control" ),
+				seekBar = control.find(  ".ui-seekbar"  ),
+				durationBar = seekBar.find( ".ui-duration" ),
+				currenttimeBar = seekBar.find( ".ui-currenttime" ),
+				timestampLabel = control.find( ".ui-timestamplabel" ),
+				durationOffset = durationBar.offset(),
+				durationWidth = durationBar.width(),
+				durationHeight = durationBar.height(),
+				timebarWidth = 0;
+
+			if ( typeof currenttime === "undefined" ) {
+				currenttime = viewElement.currentTime;
+			}
+			timebarWidth = parseInt( currenttime / duration * durationWidth, 10 );
+			durationBar.offset( durationOffset );
+			currenttimeBar.offset( durationOffset ).width( timebarWidth );
+			timestampLabel.find( "p" ).text( this._convertTimeFormat( currenttime ) );
+		},
+
+		_updateVolumeState: function () {
+			var view = this.element,
+				control = view.parent( ".ui-multimediaview-wrap" ).find( ".ui-multimediaview-control" ),
+				volumeControl = control.find( ".ui-volumecontrol" ),
+				volumeButton = control.find( ".ui-volumebutton" ),
+				volumeBar = volumeControl.find( ".ui-volumebar" ),
+				volumeGuide = volumeControl.find( ".ui-guide" ),
+				volumeValue = volumeControl.find( ".ui-value" ),
+				volumeHandle = volumeControl.find( ".ui-handle" ),
+				handlerWidth = volumeHandle.width(),
+				handlerHeight = volumeHandle.height(),
+				volumeGuideHeight = volumeGuide.height(),
+				volumeGuideWidth = volumeGuide.width(),
+				volumeGuideTop = 0,
+				volumeGuideLeft = 0,
+				volumeBase = 0,
+				handlerOffset = null,
+				volume = view[0].volume;
+
+			volumeGuideTop = parseInt( volumeGuide.offset().top, 10 );
+			volumeGuideLeft = parseInt( volumeGuide.offset().left, 10 );
+			volumeBase = volumeGuideLeft;
+			handlerOffset = volumeHandle.offset();
+			handlerOffset.top = volumeGuideTop - parseInt( ( handlerHeight - volumeGuideHeight ) / 2, 10 );
+			handlerOffset.left = volumeBase + parseInt( volumeGuideWidth * volume, 10 ) - parseInt( handlerWidth / 2, 10 );
+			volumeHandle.offset( handlerOffset );
+			volumeValue.offset( volumeGuide.offset() ).width( parseInt( volumeGuideWidth * ( volume ), 10 ) );
+		},
+
+		_setVolume: function ( value ) {
+			var viewElement = this.element[0];
+
+			if ( value < 0.0 || value > 1.0 ) {
+				return;
+			}
+
+			viewElement.volume = value;
+		},
+
+		width: function ( value ) {
+			if ( this.options.fullScreen ) {
+				return;
+			}
+
+			var view = this.element,
+				wrap = view.parent( ".ui-multimediaview-wrap" );
+
+			if ( arguments.length === 0 ) {
+				return view.width();
+			}
+
+			if ( !this._isVideo ) {
+				wrap.width( value );
+			}
+
+			view.width( value );
+			this._resize();
+		},
+
+		height: function ( value ) {
+			if ( !this._isVideo || this.options.fullScreen ) {
+				return;
+			}
+
+			var view = this.element;
+
+			if ( arguments.length === 0 ) {
+				return view.height();
+			}
+
+			view.height( value );
+			this._resize();
+		},
+
+		fullScreen: function ( value ) {
+			if ( !this._isVideo ) {
+				return;
+			}
+
+			var view = this.element,
+				option = this.options;
+
+			if ( arguments.length === 0 ) {
+				return option.fullScreen;
+			}
+
+			view.parents( ".ui-scrollview-clip" ).scrollview( "scrollTo", 0, 0 );
+
+			this.options.fullScreen = value;
+
+			this._resize();
+		},
+
+		refresh: function () {
+			this._resize();
+		}
+	});
+
+	$( document ).bind( "pagecreate create", function ( e ) {
+		$.tizen.multimediaview.prototype.enhanceWithin( e.target );
+	}).bind( "pagechange", function ( e ) {
+		$( e.target ).find( ".ui-multimediaview" ).each( function () {
+			var view = $( this ),
+				viewElement = view[0];
+
+			if ( viewElement.autoplay ) {
+				viewElement.play();
+			}
+			view.multimediaview( "refresh" );
+		});
+	}).bind( "pagebeforechange", function ( e ) {
+		$( e.target ).find( ".ui-multimediaview" ).each( function () {
+			var view = $( this ),
+				viewElement = view[0],
+				isFullscreen = view.multimediaview( "fullScreen" );
+
+			if ( isFullscreen ) {
+				view.multimediaview( "fullScreen", !isFullscreen );
+			}
+
+			if ( viewElement.played.length !== 0 ) {
+				viewElement.pause();
+			}
+		});
+	});
+
+	$( window ).bind( "resize orientationchange", function ( e ) {
+		$( ".ui-page-active" ).find( ".ui-multimediaview" ).multimediaview( "refresh" );
+	});
+
+} ( jQuery, document, window ) );
+
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+} );
+//>>excludeEnd("jqmBuildExclude");

http://git-wip-us.apache.org/repos/asf/cordova-tizen/blob/e21e0780/templates/CordovaTizenWebUIFrameworkTemplate/project/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.notification.js
----------------------------------------------------------------------
diff --git a/templates/CordovaTizenWebUIFrameworkTemplate/project/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.notification.js b/templates/CordovaTizenWebUIFrameworkTemplate/project/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.notification.js
new file mode 100644
index 0000000..271abf2
--- /dev/null
+++ b/templates/CordovaTizenWebUIFrameworkTemplate/project/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.notification.js
@@ -0,0 +1,381 @@
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+//>>description: Shows notification popup over header/footer
+//>>label: Notification
+//>>group: Tizen:Widgets
+
+define( [
+	'jquery',
+	'../jquery.mobile.tizen.core'
+	], function ( jQuery ) {
+
+//>>excludeEnd("jqmBuildExclude");
+
+/* ***************************************************************************
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * ***************************************************************************
+ *
+ *	Author: Minkyu Kang <mk...@samsung.com>
+ */
+
+/*
+ * Notification widget
+ *
+ * HTML Attributes
+ *
+ *  data-role: set to 'notification'.
+ *  data-type: 'ticker' or 'popup'.
+ *  data-interval: time to showing. If don't set, will show infinitely.
+ *
+ * APIs
+ *
+ *  open(): open the notification.
+ *  close(): close the notification.
+ *  text(text0, text1): set texts or get texts
+ *  icon(src): set the icon (tickernoti only)
+ *
+ * Events
+ *
+ *  N/A
+ *
+ * Examples
+ *
+ * // tickernoti
+ * <div data-role="notification" id="notification" data-type="ticker" data-interval="3000">
+ *	<img src="icon01.png">
+ *	<p>Hello World</p>
+ *	<p>Denis</p>
+ * </div>
+ *
+ * // smallpopup
+ * <div data-role="notification" id="notification" data-type="popup" data-interval="3000">
+ *	<p>Hello World</p>
+ * </div>
+ *
+ */
+
+/**
+	@class Notification
+	The notification widget shows a pop-up window on the screen to provide notifications.
+	To add a notification widget to the application, use the following code:
+
+		<div data-role="page">
+			<div data-role="notification" data-type="smallpopup">
+				<p>text1</p>
+			</div>
+			<div data-role="header"></div>
+			<div data-role="content"></div>
+			<div data-role="footer"></div>
+		</div>
+*/
+/**
+	@property {String} data-type
+	Defines the notification type. The type options are tickernoti and smallpopup. <br/>The default value is smallpopup.
+
+*/
+/**
+	@property {Integer} data-interval
+	Defines the time to showing a notification widget. <br/>The default is infinitely.
+
+*/
+/**
+	@method open
+	The open method is used to open the notification widget:
+
+		<div data-role="notification" data-type="smallpopup" data-interval="3000"></div>
+		$('#notification').notification('open');
+*/
+/**
+	@method close
+	The close method is used to close the notification widget:
+
+		<div data-role="notification" data-type="smallpopup" data-interval="3000"></div>
+		$('#notification').notification('close');
+*/
+/**
+	@method text
+	The text method is used to set or get the notification text:
+
+		<div data-role="notification" data-type="smallpopup" data-interval="3000"></div>
+		// Set notification text
+		$('#notification').notification('text', 'setThisText');
+		// Get notification text
+		texts = $('#notification').notification('text');
+	@since Tizen2.0
+*/
+/**
+	@method icon
+	The setIcon method is used to set the ticker notification icon. The icon can be set only if the notification type is set to tickernoti.
+
+		<div data-role="notification" data-type="ticker" data-interval="3000"></div>
+		$('#notification').notification('icon', './test.png');
+*/
+(function ( $, window ) {
+	$.widget( "tizen.notification", $.mobile.widget, {
+		btn: null,
+		text_bg: [],
+		icon_img: [],
+		interval: null,
+		seconds: null,
+		running: false,
+
+		_get_text: function () {
+			var text = new Array( 2 );
+
+			if ( this.type === 'ticker' ) {
+				text[0] = $( this.text_bg[0] ).text();
+				text[1] = $( this.text_bg[1] ).text();
+			} else {
+				text[0] = $( this.text_bg[0] ).text();
+			}
+
+			return text;
+		},
+
+		_set_text: function ( text0, text1 ) {
+			var _set = function ( elem, text ) {
+				if ( !text ) {
+					return;
+				}
+				elem.text( text );
+			};
+
+			if ( this.type === 'ticker' ) {
+				_set( $( this.text_bg[0] ), text0 );
+				_set( $( this.text_bg[1] ), text1 );
+			} else {
+				_set( $( this.text_bg[0] ), text0 );
+			}
+		},
+
+		text: function ( text0, text1 ) {
+			if ( text0 === undefined && text1 === undefined ) {
+				return this._get_text();
+			}
+
+			this._set_text( text0, text1 );
+		},
+
+		icon: function ( src ) {
+			if ( src === undefined ) {
+				return;
+			}
+
+			this.icon_img.detach();
+			this.icon_img = $( "<img src='" + src + "' class='ui-ticker-icon'>" );
+			$( this.element ).find(".ui-ticker").append( this.icon_img );
+		},
+
+		_refresh: function () {
+			var container = this._get_container();
+
+			$( container ).addClass("fix")
+					.removeClass("show")
+					.removeClass("hide");
+
+			this._set_interval();
+		},
+
+		open: function () {
+			var container = this._get_container();
+
+			if ( this.running ) {
+				this._refresh();
+				return;
+			}
+
+			$( container ).addClass("show")
+					.removeClass("hide")
+					.removeClass("fix");
+
+			this.running = true;
+
+			if ( this.type === 'popup' ) {
+				this._set_position();
+			}
+
+			this._set_interval();
+		},
+
+		close: function () {
+			var container = this._get_container();
+
+			if ( !this.running ) {
+				return;
+			}
+
+			$( container ).addClass("hide")
+					.removeClass("show")
+					.removeClass("fix");
+
+			this.running = false;
+			clearInterval( this.interval );
+		},
+
+		destroy: function () {
+			var container = this._get_container();
+
+			$( container ).removeClass("show")
+					.removeClass("hide")
+					.removeClass("fix");
+
+			this._del_event();
+
+			this.running = false;
+		},
+
+		_get_container: function () {
+			if ( this.type === 'ticker' ) {
+				return $( this.element ).find(".ui-ticker");
+			}
+
+			return $( this.element ).find(".ui-smallpopup");
+		},
+
+		_set_interval: function () {
+			var self = this;
+
+			clearInterval( this.interval );
+
+			if ( this.seconds !== undefined && this.second !== 0 ) {
+				this.interval = setInterval( function () {
+					self.close();
+				}, this.seconds );
+			}
+		},
+
+		_add_event: function () {
+			var self = this,
+				container = this._get_container();
+
+			if ( this.type === 'ticker' ) {
+				container.find(".ui-ticker-btn").append( this.btn ).trigger("create");
+
+				this.btn.bind( "vmouseup", function () {
+					self.close();
+				});
+			}
+
+			container.bind( 'vmouseup', function () {
+				self.close();
+			});
+		},
+
+		_del_event: function () {
+			var container = this._get_container();
+
+			if ( this.type === 'ticker' ) {
+				this.btn.unbind("vmouseup");
+			}
+			container.unbind('vmouseup');
+			clearInterval( this.interval );
+		},
+
+		_set_position: function () {
+			var container = this._get_container(),
+				$footer = $('.ui-page-active').children('.ui-footer'),
+				footer_h = $footer.outerHeight() || 0;
+
+			container.css( 'bottom', footer_h);
+		},
+
+		_create: function () {
+			var self = this,
+				elem = $( this.element ),
+				i;
+
+			this.btn = $('<div data-role="button" data-inline="true">Close</div>');
+
+			this.seconds = elem.jqmData('interval');
+			this.type = elem.jqmData('type') || 'popup';
+
+			if ( this.type === 'ticker' ) {
+				elem.wrapInner("<div class='ui-ticker'></div>");
+				elem.find(".ui-ticker").append("<div class='ui-ticker-body'></div>" +
+							"<div class='ui-ticker-btn'></div>");
+				this.text_bg = elem.find("p");
+
+				if ( this.text_bg.length < 2 ) {
+					elem.find(".ui-ticker").append("<p></p><p></p>");
+					this.text_bg = elem.find("p");
+				} else if ( this.text_bg.length > 2 ) {
+					for ( i = 2; i < this.text_bg.length; i++ ) {
+						$( this.text_bg[i] ).css( "display", "none" );
+					}
+				}
+
+				$( this.text_bg[0] ).addClass("ui-ticker-text1-bg");
+				$( this.text_bg[1] ).addClass("ui-ticker-text2-bg");
+
+				this.icon_img = elem.find("img");
+
+				if ( this.icon_img.length ) {
+					$( this.icon_img ).addClass("ui-ticker-icon");
+
+					for ( i = 1; i < this.icon_img.length; i++ ) {
+						$( this.icon_img[i] ).css( "display", "none" );
+					}
+				}
+			} else {
+				elem.wrapInner("<div class='ui-smallpopup'></div>");
+				this.text_bg = elem.find("p").addClass("ui-smallpopup-text-bg");
+
+				if ( this.text_bg.length < 1 ) {
+					elem.find(".ui-smallpopup")
+						.append("<p class='ui-smallpopup-text-bg'></p>");
+					this.text_bg = elem.find("p");
+				} else if ( this.text_bg.length > 1 ) {
+					for ( i = 1; i < this.text_bg.length; i++ ) {
+						$( this.text_bg[i] ).css( "display", "none" );
+					}
+				}
+
+				this._set_position();
+			}
+
+			this._add_event();
+
+			$( window ).bind( "resize", function () {
+				if ( !self.running ) {
+					return;
+				}
+
+				self._refresh();
+
+				if ( self.type === 'popup' ) {
+					self._set_position();
+				}
+			});
+		}
+	}); // End of widget
+
+	// auto self-init widgets
+	$( document ).bind( "pagecreate create", function ( e ) {
+		$( e.target ).find(":jqmData(role='notification')").notification();
+	});
+
+	$( document ).bind( "pagebeforehide", function ( e ) {
+		$( e.target ).find(":jqmData(role='notification')").notification('destroy');
+	});
+}( jQuery, this ));
+
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+} );
+//>>excludeEnd("jqmBuildExclude");

http://git-wip-us.apache.org/repos/asf/cordova-tizen/blob/e21e0780/templates/CordovaTizenWebUIFrameworkTemplate/project/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.pagelayout.js
----------------------------------------------------------------------
diff --git a/templates/CordovaTizenWebUIFrameworkTemplate/project/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.pagelayout.js b/templates/CordovaTizenWebUIFrameworkTemplate/project/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.pagelayout.js
new file mode 100644
index 0000000..7ccf4cd
--- /dev/null
+++ b/templates/CordovaTizenWebUIFrameworkTemplate/project/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.pagelayout.js
@@ -0,0 +1,684 @@
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+//>>description: Set a layout of pages
+//>>label: Pagelayout
+//>>group: Tizen:Widgets
+
+define( [ 
+	'jquery',
+	'../jquery.mobile.tizen.core',
+	'../jquery.mobile.tizen.scrollview',
+	"jqm/widgets/page",
+	"jqm/widgets/page.sections",
+	"jqm/widgets/popup",
+	"jqm/jquery.mobile.zoom"
+	], function ( jQuery ) {
+
+//>>excludeEnd("jqmBuildExclude");
+
+/* ***************************************************************************
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * ***************************************************************************
+ *
+ *	Author: Jinhyuk Jun <ji...@samsung.com>
+ */
+
+(function ( $, undefined ) {
+
+	$.widget( "mobile.pagelayout", $.mobile.widget, {
+		options: {
+			visibleOnPageShow: true,
+			disablePageZoom: true,
+			transition: "slide", //can be none, fade, slide (slide maps to slideup or slidedown)
+			fullscreen: false,
+			tapToggle: true,
+			tapToggleBlacklist: "a, input, select, textarea, .ui-header-fixed, .ui-footer-fixed",
+			hideDuringFocus: "input, textarea, select",
+			updatePagePadding: true,
+			// Browser detection! Weeee, here we go...
+			// Unfortunately, position:fixed is costly, not to mention probably impossible, to feature-detect accurately.
+			// Some tests exist, but they currently return false results in critical devices and browsers, which could lead to a broken experience.
+			// Testing fixed positioning is also pretty obtrusive to page load, requiring injected elements and scrolling the window
+			// The following function serves to rule out some popular browsers with known fixed-positioning issues
+			// This is a plugin option like any other, so feel free to improve or overwrite it
+			supportBlacklist: function () {
+				var w = window,
+					ua = navigator.userAgent,
+					platform = navigator.platform,
+					// Rendering engine is Webkit, and capture major version
+					wkmatch = ua.match( /AppleWebKit\/([0-9]+)/ ),
+					wkversion = !!wkmatch && wkmatch[ 1 ],
+					ffmatch = ua.match( /Fennec\/([0-9]+)/ ),
+					ffversion = !!ffmatch && ffmatch[ 1 ],
+					operammobilematch = ua.match( /Opera Mobi\/([0-9]+)/ ),
+					omversion = !!operammobilematch && operammobilematch[ 1 ];
+
+				if (
+					// iOS 4.3 and older : Platform is iPhone/Pad/Touch and Webkit version is less than 534 (ios5)
+					( ( platform.indexOf( "iPhone" ) > -1 || platform.indexOf( "iPad" ) > -1  || platform.indexOf( "iPod" ) > -1 ) && wkversion && wkversion < 534 ) ||
+						// Opera Mini
+						( w.operamini && ({}).toString.call( w.operamini ) === "[object OperaMini]" ) ||
+						( operammobilematch && omversion < 7458 ) ||
+						//Android lte 2.1: Platform is Android and Webkit version is less than 533 (Android 2.2)
+						( ua.indexOf( "Android" ) > -1 && wkversion && wkversion < 533 ) ||
+						// Firefox Mobile before 6.0 -
+						( ffversion && ffversion < 6 ) ||
+						// WebOS less than 3
+						( window.palmGetResource !== undefined && wkversion && wkversion < 534 ) ||
+						// MeeGo
+						( ua.indexOf( "MeeGo" ) > -1 && ua.indexOf( "NokiaBrowser/8.5.0" ) > -1 )
+				) {
+					return true;
+				}
+
+				return false;
+			},
+			initSelector: ":jqmData(role='content')"
+		},
+
+		_create: function () {
+
+			var self = this,
+				o = self.options,
+				$el = self.element;
+
+			// Feature detecting support for
+			if ( o.supportBlacklist() ) {
+				self.destroy();
+				return;
+			}
+
+			self._addFixedClass();
+			self._addTransitionClass();
+			self._bindPageEvents();
+
+			// only content
+			self._bindContentControlEvents();
+
+			// Store back-button, to show again
+			self._backBtnQueue = [];
+		},
+
+		/* add minimum fixed css style to bar(header/footer) and content
+		*  it need to update when core source modified(jquery.mobile.page.section.js)
+		*  modified from core source cuz initSelector different */
+		_addFixedClass: function () {
+			var self = this,
+				o = self.options,
+				$el = self.element,
+				$elHeader = $el.siblings( ":jqmData(role='header')" ),
+				$elFooter = $el.siblings( ":jqmData(role='footer')" ),
+				$elPage = $el.closest(".ui-page");
+
+			$elHeader.addClass( "ui-header-fixed" );
+			$elFooter.addClass( "ui-footer-fixed" );
+
+			// "fullscreen" overlay positioning
+			if ( o.fullscreen ) {
+				$elHeader.addClass( "ui-header-fullscreen" );
+				$elFooter.addClass( "ui-footer-fullscreen" );
+				$elPage
+					.addClass( "ui-page-header-fullscreen" )
+					.addClass( "ui-page-footer-fullscreen" );
+			} else {
+			// If not fullscreen, add class to page to set top or bottom padding
+				$elPage.addClass( "ui-page-header-fixed" )
+					.addClass( "ui-page-footer-fixed" );
+			}
+		},
+
+		/* original core source(jquery.mobile.fixedToolbar.js)
+		* never changed */
+		_addTransitionClass: function () {
+			var tclass = this.options.transition;
+
+			if ( tclass && tclass !== "none" ) {
+				// use appropriate slide for header or footer
+				if ( tclass === "slide" ) {
+					tclass = this.element.is( ".ui-header" ) ? "slidedown" : "slideup";
+				}
+
+				this.element.addClass( tclass );
+			}
+		},
+
+
+		/* Set default page positon
+		* 1. add title style to header
+		* 2. Set default header/footer position */
+		setHeaderFooter: function ( thisPage ) {
+			var $elPage = $( thisPage ),
+				$elHeader = $elPage.find( ":jqmData(role='header')" ).length ? $elPage.find( ":jqmData(role='header')") : $elPage.siblings( ":jqmData(role='header')"),
+				$elContent = $elPage.find( ".ui-content" ),
+				$elFooter = $elPage.find( ":jqmData(role='footer')" ),
+				$elFooterGroup = $elFooter.find( ":jqmData(role='fieldcontain')" ),
+				$elFooterControlGroup = $elFooter.find( ".ui-controlgroup" );
+
+			// divide content mode scrollview and non-scrollview
+			if ( !$elPage.is( ".ui-dialog" ) ) {
+				if ( $elHeader.jqmData("position") == "fixed" || ( $.support.scrollview && $.tizen.frameworkData.theme.match(/tizen/) ) ) {
+					$elHeader
+						.css( "position", "fixed" )
+						.css( "top", "0px" );
+				} else if ( !$.support.scrollview && $elHeader.jqmData("position") != "fixed" ) {
+					$elHeader.css( "position", "relative" );
+				}
+			}
+
+			/* set Title style */
+			if ( $elHeader.find("span.ui-title-text-sub").length ) {
+				$elHeader.addClass( "ui-title-multiline");
+			}
+
+			if ( $elFooterGroup.find( "div" ).is( ".ui-controlgroup-label" ) ) {
+				$elFooterGroup.find( "div.ui-controlgroup-label" ).remove();
+			}
+
+			if ( $elFooterControlGroup.length ) {
+				var anchorPer = 100 / $elFooterControlGroup.find( "a" ).length;
+				$elFooterControlGroup.find( "a" ).each( function ( i ) {
+					$elFooterControlGroup.find( "a" ).eq( i ).width( anchorPer + "%" );
+				});
+			}
+		},
+
+		_bindPageEvents: function () {
+			var self = this,
+				o = self.options,
+				$el = self.element,
+				$elCurrentFooter;
+
+			//page event bindings
+			// Fixed toolbars require page zoom to be disabled, otherwise usability issues crop up
+			// This method is meant to disable zoom while a fixed-positioned toolbar page is visible
+			$el.closest( ".ui-page" )
+				.bind( "pagebeforeshow", function ( event ) {
+					var thisPage = this;
+					if ( o.disablePageZoom ) {
+						$.mobile.zoom.disable( true );
+					}
+					if ( !o.visibleOnPageShow ) {
+						self.hide( true );
+					}
+					self.setHeaderFooter( thisPage );
+					self._setContentMinHeight( thisPage );
+					self._updateHeaderArea( thisPage );
+					self._updateFooterArea( thisPage );
+				} )
+				.bind( "webkitAnimationStart animationstart updatelayout", function ( e, data ) {
+					var thisPage = this;
+					if ( o.updatePagePadding ) {
+						self.updatePagePadding(thisPage);
+						self.updatePageLayout( thisPage, data);
+					}
+				})
+
+				.bind( "pageshow", function ( event ) {
+					var thisPage = this;
+					self._setContentMinHeight( thisPage );
+					self.updatePagePadding( thisPage );
+					self._updateHeaderArea( thisPage );
+					self._updateFooterArea( thisPage );
+
+					// check device api : HW key existance
+					// TODO: remove these functions, because the HW key is mandatory.
+					if ( false ) {
+						self._bindHWkeyOnSWBtn();
+						self._setHWKeyLayout( thisPage );
+					}
+					self._setHWKeySupport( thisPage );
+					//self._setMenuPopupLayout( thisPage );
+
+					if ( o.updatePagePadding ) {
+						$( window ).bind( "throttledresize." + self.widgetName, function () {
+							self.updatePagePadding(thisPage);
+							self.updatePageLayout( thisPage, true);
+							self._updateHeaderArea( thisPage );
+							self._updateFooterArea( thisPage );
+							self._setContentMinHeight( thisPage );
+						});
+					}
+				})
+
+				.bind( "pagebeforehide", function ( e, ui ) {
+					self._unsetHWKeySupport( );
+					if ( o.disablePageZoom ) {
+						$.mobile.zoom.enable( true );
+					}
+					if ( o.updatePagePadding ) {
+						$( window ).unbind( "throttledresize." + self.widgetName );
+					}
+				});
+
+			window.addEventListener( "softkeyboardchange", function ( e ) {
+				var $elDownBtn = $( "<div class='ui-btn-footer-down'></div>" ),
+					$elPage = $( ".ui-page-active" ),
+					backBtn,
+					backBtnPosition = "footer";
+				// N_SE-42987 : If self._backBtnQueue.length has value is not 0, this means .ui-btn-back button is still hidden.
+				//		So, condition that check self._backBtnQueue value add.
+				if ( $elPage.data( "addBackBtn" ) || self._backBtnQueue.length ) {
+					$elPage.data( "addBackBtn" ) == "header" ? backBtnPosition = "header" : backBtnPosition = "footer";
+
+					if ( e.state == "on" ) {
+						if ( !$elPage.find( ".ui-" + backBtnPosition + " .ui-btn-footer-down" ).length ) {
+							$elDownBtn.buttonMarkup( { icon: "down" } ).appendTo( $elPage.find( ".ui-" + backBtnPosition ) );
+						}
+
+						// N_SE-32900: If an app moves a page when the pop is shown, the .ui-page-active page
+						//             is changed.
+						//             In this case, the '.ui-page-active .ui-btn-back' selector indicates a
+						//             new page's one, and the old page's .ui-btn-back button is still hidden.
+						//             So, the current back button is remembered to be shown at the
+						//             softkeyboardchange.off event.
+						if ( true ) {
+							backBtn = $( ".ui-page-active .ui-btn-back" );
+							backBtn.hide();
+							self._backBtnQueue.push( backBtn );	// Store hidden backBtn
+						}
+					} else if ( e.state == "off" ) {
+						if ( true ) {
+							self._backBtnQueue.forEach( function ( b ) {
+								b.show();	// Show each backBtn,
+							} );
+							self._backBtnQueue.length = 0;	// and clear queue.
+						}
+						$( ".ui-btn-footer-down" ).remove();
+					}
+				}
+			});
+		},
+
+		_bindContentControlEvents: function () {
+			var self = this,
+				o = self.options,
+				$el = self.element;
+
+			$el.closest( ".ui-page" )
+				.bind( "pagebeforeshow", function ( event ) {
+
+				});
+		},
+
+		_HWKeyHandler: function ( ev ) {
+			var $openedpopup = $.mobile.popup.active,
+				$page,
+				$focused;
+			// NOTE: The 'tizenhwkey' event is passed only document -> window objects.
+			//       Other DOM elements does not receive 'tizenhwkey' event.
+
+			// menu key
+			if( ev.originalEvent.keyName == "menu" ) {
+				// Blur focused element to turn off SIP(IME)
+				$page = $( ev.data ); 	// page object, passed by _setHWKeySupport()
+				$focused = $page.find( ".ui-focus" );
+				if( $focused[0] ) {	// Focused element is found
+					$focused.blur();
+					// NOTE: If a popup is opened and focused element exists in it,
+					//       do not close that popup.
+					//       'false' is returned here, hence popup close routine is not run.
+					return false;
+				}
+				// Close opened popup
+				if( $openedpopup ) {
+					$openedpopup.close();
+					return false;
+				}
+			}
+			// back key
+			else if( ev.originalEvent.keyName == "back" ) {
+				// Close opened popup
+				if( $openedpopup ) {
+					$openedpopup.close();
+					return false;
+				}
+			}
+			return true;	// Otherwise, propagate tizenhwkey event to window object
+		},
+
+		_setHWKeySupport: function( thisPage ) {
+			$( document ).on( "tizenhwkey", thisPage, this._HWKeyHandler );
+		},
+
+		_unsetHWKeySupport: function () {
+			$( document ).off( "tizenhwkey", this._HWKeyHandler );
+		},
+
+		_bindHWkeyOnSWBtn: function () {
+			// if HW key not exist
+			// return true
+			// else
+			$( document ).on( "tizenhwkey", function( e ) {
+				var openedpopup = $.mobile.popup.active,
+					$elPage = $( ".ui-page-active" ),
+					$elFooter = $elPage.find( ":jqmData(role='footer')" ),
+					$elMoreKey = $elFooter.children(":jqmData(icon='naviframe-more')"),
+					morePopup;
+
+				if ( $( ".ui-page-active .ui-footer" ).hasClass( "ui-footer-force-btn-show" ) ) {
+					return true;
+				}
+
+				if ( e.originalEvent.keyName === "back" ) {
+					// need to change back button
+					if( openedpopup ) {
+						openedpopup.close();
+						return false;
+					}
+					//Click trigger
+					 $( ".ui-page-active .ui-footer .ui-btn-back" ).trigger( "click" );
+					return false;
+				} else if ( e.originalEvent.keyName === "menu" ) {
+					// if more button was clicked, all kinds of popups will be closed
+					if ( openedpopup ) {
+						openedpopup.close();
+						return false;
+					}
+
+					// need to change more key trigger
+					if ( $elMoreKey.get(0) ) {
+						$elMoreKey.trigger( "click" );
+					}
+					return false;
+				}
+			} );
+
+		},
+
+		_setContentMinHeight : function ( thisPage ) {
+			var $elPage = $( thisPage ),
+				$elHeader = $elPage.find( ":jqmData(role='header')" ),
+				$elFooter = $elPage.find( ":jqmData(role='footer')" ),
+				$elContent = $elPage.find( ":jqmData(role='content')" ),
+				footerHeight,
+				resultMinHeight,
+				dpr = 1,
+				layoutInnerHeight = window.innerHeight;
+
+			if ( !$.support.scrollview || ($.support.scrollview && $elContent.jqmData("scroll") === "none") ) {
+					dpr = window.outerWidth / window.innerWidth;
+					layoutInnerHeight = Math.floor( window.outerHeight / dpr );
+			} else {
+				layoutInnerHeight = window.innerHeight;
+			}
+
+			if ( $elFooter.css( "display" ) === "none" ) {
+				footerHeight = 0;
+			} else {
+				footerHeight = $elFooter.height();
+			}
+			resultMinHeight = layoutInnerHeight - $elHeader.height() - footerHeight;
+
+			if ( $.support.scrollview && $elContent.jqmData("scroll") !== "none" ) {
+				$elContent.css( "min-height", resultMinHeight - parseFloat( $elContent.css("padding-top") ) - parseFloat( $elContent.css("padding-bottom") ) + "px" );
+				$elContent.children( ".ui-scrollview-view" ).css( "min-height", $elContent.css( "min-height" ) );
+			}
+		},
+
+		_updateHeaderArea : function ( thisPage ) {
+			var $elPage = $( thisPage ),
+				$elHeader = $elPage.find( ":jqmData(role='header')" ).length ? $elPage.find( ":jqmData(role='header')") : $elPage.siblings( ":jqmData(role='header')"),
+				$headerBtn = $elHeader.children("a,[data-"+$.mobile.ns+"role=button]"),
+				headerBtnWidth = $headerBtn.width() + parseInt( $headerBtn.css("padding-left") ) + parseInt( $headerBtn.css("padding-right") ),
+				headerBtnNum = $headerBtn.length,
+				$headerSrc = $elHeader.children("img"),
+				headerSrcNum = $headerSrc.length,
+				headerSrcWidth = $headerSrc.width() + parseInt( $headerSrc.css("margin-left") ),
+				h1width;
+
+			if ( !$elPage.is( ".ui-dialog" ) ) {
+				h1width = window.innerWidth - parseInt( $elHeader.find( "h1" ).css( "margin-left" ), 10 ) * 2 - headerBtnWidth * headerBtnNum - headerSrcWidth * headerSrcNum;
+				$elHeader.find( "h1" ).css( "width", h1width );
+				$elHeader.find( '.ui-title-text-sub' ).css( "width", h1width );
+			}
+			/* add half width for default space between text and button, and img tag area is too narrow, so multiply three for img width*/
+		},
+
+		_updateFooterArea : function ( thisPage ) {
+			var $elPage = $( thisPage ),
+				$elFooter = $elPage.find( ".ui-footer" ),
+				$elMoreKey = $elFooter.children( ":jqmData(icon='naviframe-more')" ),
+				$elBackKey = $elFooter.children( ".ui-btn-back, .ui-btn-footer-down" ),
+				footerBtn = $elFooter.children( "div.ui-btn, a.ui-btn" ),
+				btnLength = footerBtn.length,
+				btnWidth = window.innerWidth,
+				realBtnIndex = 0,
+				idx, moreWidth = 0;
+
+			if ( !btnLength ) {
+				return;
+			}
+
+			if ( $elMoreKey.length ) {
+				moreWidth = $elMoreKey.width();
+				btnWidth -= moreWidth;
+			}
+
+			if ( $elBackKey.length ) {
+				btnWidth -= $elBackKey.width();
+				$elBackKey.addClass( "ui-footer-btn-border" );
+			}
+
+			btnWidth /= btnLength - $elMoreKey.length - $elBackKey.length;
+
+			for ( idx = 0; idx < btnLength; idx++ ) {
+				if ( footerBtn.eq( idx ).hasClass( "ui-btn-back" ) ) {
+					continue;
+				}
+				if ( footerBtn.eq( idx ).is( ":jqmData(icon='naviframe-more')" ) ){
+					continue;
+				}
+				footerBtn.eq( idx )
+					.addClass( "ui-footer-btn-border" )
+					.width( btnWidth )
+					.css( "position", "absolute" )
+					.css( "left", realBtnIndex * btnWidth + moreWidth );
+				realBtnIndex++;
+			}
+			$elFooter.find( ".ui-footer-btn-border" ).eq( 0 ).removeClass( "ui-footer-btn-border" );
+		},
+
+		_setHWKeyLayout : function ( thisPage ) {
+			var $elPage = $( thisPage ),
+				$elFooter = $elPage.find( ":jqmData(role='footer')" ),
+				$elBackKey = $elFooter.children( ".ui-btn-back" ),
+				$elMoreKey = $elFooter.children(":jqmData(icon='naviframe-more')"),
+				$elTabBar = $elFooter.children( ".ui-tabbar" ),
+				$elControlGroup = $elFooter.children( ".ui-controlgroup" );
+				//cntMore = 0,
+			
+				// Check HW Key option
+			if ( $elFooter.hasClass("ui-footer-force-btn-show") ) {
+				return true;
+			}
+
+			/*
+			if ( $elMoreKey.length ) {
+				cntMore = $elMoreKey.length + 1;
+			} else {
+				cntMore = 0;
+			}
+
+			// need to add device api to check HW key exist
+			// Case 1 : footer - BackKey/MoreKey/Button - hide BackKey/MoreKey
+			if ( $elFooter.children().length - $elBackKey.length - cntMore > 0 ) {
+				$elBackKey.hide();
+				$elMoreKey.hide();
+			// Case 2 : footer - BackKey/MoreKey - more, back hide depend on OSP
+			} else {
+				$elBackKey.hide();
+				$elMoreKey.hide();
+			}
+			*/
+
+			if( $elMoreKey ) {
+				$elMoreKey.hide();
+			}
+			if( $elBackKey ) {
+				$elBackKey.hide();
+			}
+			if( $elTabBar ) {
+				$elTabBar.removeClass( "ui-tabbar-margin-more ui-tabbar-margin-back" );
+			}
+			if ( $elControlGroup ) {
+				$elControlGroup.removeClass( "ui-controlgroup-padding-more ui-controlgroup-padding-back" );
+			}
+			// Case 3 : no footer - do nothing
+
+			return true;
+		},
+		_setMenuPopupLayout: function ( thisPage ) {
+			var $page = $( thisPage ),
+				$footer = $page.find( ":jqmData(role='footer')" ),
+				moreKey = $page.find( ":jqmData(icon='naviframe-more')" )[0],
+				//cntMore = 0,
+				$morePopup;
+
+			if( moreKey && moreKey.hash ) {	// moreKey.hash = #morePopupID (from <a href="">)
+				$morePopup =  $( moreKey.hash );
+				$morePopup.addClass ( "ui-ctxpopup-optionmenu" );
+			}
+		 },
+
+		_visible: true,
+
+		// This will set the content element's top or bottom padding equal to the toolbar's height
+		updatePagePadding: function ( tbPage ) {
+			var $el = this.element,
+				header = $el.siblings( ".ui-header" ).length,
+				footer = $el.siblings( ".ui-footer" ).length;
+
+			// This behavior only applies to "fixed", not "fullscreen"
+			if ( this.options.fullscreen ) {
+				return;
+			}
+
+			tbPage = tbPage || $el.closest( ".ui-page" );
+
+			if ( $el.siblings( ".ui-header" ).jqmData("position") == "fixed" || ($.support.scrollview && $el.jqmData("scroll") !== "none" )) {
+				$( tbPage ).css( "padding-top", ( header ? $el.siblings( ".ui-header" ).outerHeight() : 0 ) );
+			}
+			$( tbPage ).css( "padding-bottom", (( footer && $el.siblings( ".ui-footer" ).css( "display" ) !== "none" ) ? $el.siblings( ".ui-footer" ).outerHeight() : 0 ) );
+		},
+
+		/* 1. Calculate and update content height   */
+		updatePageLayout: function ( thisPage, receiveType ) {
+			var $elFooter,
+				$elPage = $( thisPage ),
+				$elHeader = $elPage.find( ":jqmData(role='header')" ),
+				$elContent = $elPage.find( ":jqmData(role='content')" ),
+				resultContentHeight = 0,
+				resultFooterHeight = 0,
+				resultHeaderHeight = 0,
+				layoutInnerHeight = window.innerHeight,
+				dpr = 1;
+
+			if ( $elPage.length ) {
+				$elFooter = $elPage.find( ":jqmData(role='footer')" );
+			} else {
+				$elFooter = $( document ).find( ":jqmData(role='footer')" ).eq( 0 );
+			}
+
+			// calculate footer height
+			resultFooterHeight = ( $elFooter.css( "display" ) == "none" || $elFooter.length == 0 ) ? 0 : $elFooter.height();
+			resultHeaderHeight = ( $elHeader.css( "display" ) == "none" || $elHeader.length == 0 ) ? 0 : $elHeader.height();
+
+			if (resultFooterHeight != 0 ) {
+				$elFooter.css( "bottom", 0 );
+			}
+
+			if ( !$.support.scrollview || ($.support.scrollview && $elContent.jqmData("scroll") === "none") ) {
+				dpr = window.outerWidth / window.innerWidth;
+				layoutInnerHeight = Math.floor( window.outerHeight / dpr );
+			} else {
+				//#N_SE-43092: window.innerHeight returns incorrect size
+				layoutInnerHeight = $.mobile.$window.height();
+			}
+
+			resultContentHeight = layoutInnerHeight - resultFooterHeight - resultHeaderHeight;
+
+			if ( $.support.scrollview && $elContent.jqmData("scroll") !== "none" ) {
+				$elContent.height( resultContentHeight -
+						parseFloat( $elContent.css("padding-top") ) -
+						parseFloat( $elContent.css("padding-bottom") ) );
+			}
+
+			// External call page( "refresh") - in case title changed
+			if ( receiveType ) {
+				$elPage
+					.css( "min-height", resultContentHeight )
+					.css( "padding-top", resultHeaderHeight )
+					.css( "padding-bottom", resultFooterHeight );
+			}
+		},
+
+		show: function ( notransition ) {
+			/* blank function: deprecated */
+		},
+
+		hide: function ( notransition ) {
+			/* blank function: deprecated */
+		},
+
+		toggle: function () {
+			this[ this._visible ? "hide" : "show" ]();
+		},
+
+		destroy: function () {
+			this.element.removeClass( "ui-header-fixed ui-footer-fixed ui-header-fullscreen ui-footer-fullscreen in out fade slidedown slideup ui-fixed-hidden" );
+			this.element.closest( ".ui-page" ).removeClass( "ui-page-header-fixed ui-page-footer-fixed ui-page-header-fullscreen ui-page-footer-fullscreen" );
+		},
+
+		refresh: function () {
+			var $elPage = $( ".ui-page-active" );
+			this.setHeaderFooter( $elPage );
+			this._updateHeaderArea( $elPage );
+		}
+	});
+
+	//auto self-init widgets
+	$( document )
+		.bind( "pagecreate create", function ( e ) {
+			// DEPRECATED in 1.1: support for data-fullscreen=true|false on the page element.
+			// This line ensures it still works, but we recommend moving the attribute to the toolbars themselves.
+			if ( $( e.target ).jqmData( "fullscreen" ) ) {
+				$( $.mobile.pagelayout.prototype.options.initSelector, e.target ).not( ":jqmData(fullscreen)" ).jqmData( "fullscreen", true );
+			}
+			$.mobile.pagelayout.prototype.enhanceWithin( e.target );
+		})
+		.bind( "pagebeforeshow", function ( event, ui ) {
+			var footer_filter = $( event.target ).find( ":jqmData(role='footer')" ),
+				controlgroup_filter = footer_filter.find( ":jqmData(role='controlgroup')" ),
+				$elFooterMore = controlgroup_filter.siblings( ":jqmData(icon='naviframe-more')" ),
+				$elFooterBack = controlgroup_filter.siblings( ".ui-btn-back" );
+
+			if ( $elFooterMore.length ) {
+				controlgroup_filter.addClass( "ui-controlgroup-padding-more" );
+			}
+			if ( $elFooterBack.length ) {
+				controlgroup_filter.addClass( "ui-controlgroup-padding-back" );
+			}
+		});
+
+}( jQuery ));
+
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+} );
+//>>excludeEnd("jqmBuildExclude");

http://git-wip-us.apache.org/repos/asf/cordova-tizen/blob/e21e0780/templates/CordovaTizenWebUIFrameworkTemplate/project/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.popupwindow.ctxpopup.js
----------------------------------------------------------------------
diff --git a/templates/CordovaTizenWebUIFrameworkTemplate/project/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.popupwindow.ctxpopup.js b/templates/CordovaTizenWebUIFrameworkTemplate/project/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.popupwindow.ctxpopup.js
new file mode 100644
index 0000000..3619d8a
--- /dev/null
+++ b/templates/CordovaTizenWebUIFrameworkTemplate/project/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.popupwindow.ctxpopup.js
@@ -0,0 +1,341 @@
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+//>>description: Shows popup at any place in the page content, with various styles
+//>>label: Context popup
+//>>group: Tizen:Widgets
+
+define( [ 
+	'jquery',
+	'../jquery.mobile.tizen.core',
+	'./jquery.mobile.tizen.popupwindow',
+	'./jquery.mobile.tizen.triangle'
+	], function ( jQuery ) {
+
+//>>excludeEnd("jqmBuildExclude");
+
+/*
+ * jQuery Mobile Widget @VERSION
+ *
+ * This software is licensed under the MIT licence (as defined by the OSI at
+ * http://www.opensource.org/licenses/mit-license.php)
+ *
+ * ***************************************************************************
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2011 by Intel Corporation Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * ***************************************************************************
+ *
+ * Authors: Gabriel Schulhof <ga...@intel.com>
+ *			Hyunjung Kim <hj...@samsung.com>
+ */
+
+/*
+ * % ContextPopup widget do not use anymore(will be deprecated, internal use only)
+ */
+// This widget is implemented in an extremely ugly way. It should derive from $.tizen.popupwindow, but it doesn't
+// because there's a bug in jquery.ui.widget.js which was fixed in jquery-ui commit
+// b9153258b0f0edbff49496ed16d2aa93bec07d95. Once a version of jquery-ui containing that commit is released
+// (probably >= 1.9m5), and jQuery Mobile picks up the widget from there, this widget needs to be rewritten properly.
+// The problem is that, when a widget inherits from a superclass and declares an object in its prototype identical in key
+// to one in the superclass, upon calling $.widget the object is overwritten in both the prototype of the superclass and
+// the prototype of the subclass. The prototype of the superclass should remain unchanged.
+
+/**
+	class ContextPopup
+		The context pop-up widget shows a list of options and automatically optimizes its size within the screen. This widget is intended for a small list of options for a larger list, use the List widget. <br/>The context pop-up widget requires a target button, which must be clicked to open the context pop-up. In the default application theme, an arrow pointer is displayed at the top-left corner of the context pop-up widget when it is opened.<br/><br/> To add a context pop-up widget to the application, use the following code:
+
+			// Target button
+			<a href="#pop_3_icons" id="btn_3_icons" data-role="button" data-inline="true" data-rel="popupwindow">3 Icons</a>
+			// Context pop-up
+				<div class="horizontal" id="pop_3_icons" data-role="popupwindow" data-show-arrow="true">
+				<ul>
+					<li class="icon">
+						<a href="#" data-role="button" data-icon="call"></a>
+					</li>
+					<li class="icon">
+						<a href="#" data-role="button" data-icon="favorite"></a>
+					</li>
+					<li class="text">
+						<a href="#">Function</a>
+					</li>
+				</ul>
+			</div>
+	The context pop-up can define callbacks for events as described in the [jQueryMobile documentation for pop-up events.][1]
+	You can use methods with the context pop-up as described in the [jQueryMobile documentation for pop-up methods.][2]
+	[1]: http://jquerymobile.com/demos/1.2.0-alpha.1/docs/pages/popup/events.html
+	[2]: http://jquerymobile.com/demos/1.2.0-alpha.1/docs/pages/popup/methods.html
+
+	@deprecated 2.0 verisons
+*/
+
+(function ( $, undefined ) {
+	$.widget( "tizen.ctxpopup", $.tizen.widgetex, {
+		options: $.extend( {}, $.tizen.popupwindow.prototype.options, {
+			initSelector: ":jqmData(show-arrow)"
+		} ),
+
+		_htmlProto: {
+source:
+
+ [ "<div><div id='outer' class='ui-ctxpopup'>" ,
+  "    <div id='top' class='ui-ctxpopup-row' data-role='triangle' data-location='top'></div>" ,
+  "    <div class='ui-ctxpopup-row'>" ,
+  "        <div id='left' class='ui-ctxpopup-cell' data-role='triangle' data-location='left'></div>" ,
+  "        <div id='container' class='ui-ctxpopup-cell'></div>" ,
+  "        <div id='right' class='ui-ctxpopup-cell' data-role='triangle' data-location='right'></div>" ,
+  "    </div>" ,
+  "    <div id='bottom' class='ui-ctxpopup-row' data-role='triangle' data-location='bottom'></div>" ,
+  "</div>" ,
+  "</div>" ].join("")
+,			ui: {
+				outer		: "#outer",
+				container	: "#container", // the key has to have the name "container"
+				arrow		: {
+					all		: ":jqmData(role='triangle')",
+					l		: "#left",
+					t		: "#top",
+					r		: "#right",
+					b		: "#bottom"
+				}
+			}
+		},
+
+		_create: function () {
+			console.warn("ctxpopup() was deprecated. use popup() instead.");
+			if ( !this.element.data( "popupwindow" ) ) {
+				this.element.popupwindow();
+			}
+
+			this.element.data( "popupwindow" )
+				._ui.container
+				.removeClass( "ui-popupwindow-padding" )
+				.append( this._ui.outer );
+			this._ui.outer.trigger( "create" ); // Creates the triangle widgets
+			this._ui.container
+				.addClass( "ui-popupwindow-padding" )
+				.append( this.element );
+		},
+
+		_setOption: function ( key, value ) {
+			$.tizen.popupwindow.prototype._setOption.apply( this.element.data( "popupwindow" ), arguments );
+			this.options[key] = value;
+		}
+	} );
+
+	var origOpen = $.tizen.popupwindow.prototype.open,
+		orig_setOption = $.tizen.popupwindow.prototype._setOption,
+		orig_placementCoords = $.tizen.popupwindow.prototype._placementCoords;
+
+	$.tizen.popupwindow.prototype._setOption = function ( key, value ) {
+		var ctxpopup = this.element.data( "ctxpopup" ),
+			needsApplying = true,
+			origContainer;
+		if ( ctxpopup ) {
+			if ( "shadow" === key || "overlayTheme" === key || "corners" === key ) {
+				origContainer = this._ui.container;
+
+				this._ui.container = ctxpopup._ui.container;
+				orig_setOption.apply( this, arguments );
+				this._ui.container = origContainer;
+				needsApplying = false;
+			}
+			ctxpopup.options[key] = value;
+		}
+
+		if ( needsApplying ) {
+			orig_setOption.apply(this, arguments);
+		}
+	};
+
+	$.tizen.popupwindow.prototype._placementCoords = function ( x, y, cx, cy ) {
+		var ctxpopup = this.element.data( "ctxpopup" ),
+			self = this,
+			coords = {},
+			minDiff,
+			minDiffIdx;
+
+		function getCoords( arrow, x_factor, y_factor ) {
+			// Unhide the arrow we want to test to take it into account
+			ctxpopup._ui.arrow.all.hide();
+			ctxpopup._ui.arrow[arrow].show();
+
+			var isHorizontal = ( "b" === arrow || "t" === arrow ),
+			// Names of keys used in calculations depend on whether things are horizontal or not
+				coord = ( isHorizontal
+						? { point: "x", size: "cx", beg: "left", outerSize: "outerWidth",  niceSize: "width", triangleSize : "height" }
+						: { point: "y", size: "cy", beg: "top",  outerSize: "outerHeight", niceSize: "height", triangleSize : "width" } ),
+				size = {
+					cx : self._ui.container.width(),
+					cy : self._ui.container.height()
+				},
+				halfSize = {
+					cx : size.cx / 2,
+					cy : size.cy / 2
+				},
+				desired = {
+					"x" : x + halfSize.cx * x_factor,
+					"y" : y + halfSize.cy * y_factor
+				},
+				orig = orig_placementCoords.call( self, desired.x, desired.y, size.cx, size.cy ),
+
+			// The triangleOffset must be clamped to the range described below:
+			//
+			//                          +-------...
+			//                          |   /\
+			//                          |  /  \
+			//                   ----+--+-,-----...
+			//lowerDiff       -->____|  |/ <-- possible rounded corner
+			//triangle size   -->    | /|
+			//                   ____|/ |
+			//                    ^  |\ | <-- lowest possible offset for triangle
+			// actual range of    |  | \| 
+			// arrow offset       |  |  | 
+			// values due to      |  .  . Payload table cell looks like
+			// possible rounded   |  .  . a popup window, and it may have
+			// corners and arrow  |  .  . arbitrary things like borders,
+			// triangle size -    |  |  | shadows, and rounded corners.
+			// our clamp range    |  | /|
+			//                   _v__|/ |
+			//triangle size   -->    |\ | <-- highest possible offset for triangle
+			//                   ____| \|
+			//upperDiff       -->    |  |\ <-- possible rounded corner
+			//                   ----+--+-'-----...
+			//                          |  \  /
+			//                          |   \/
+			//                          +-------...
+			//
+			// We calculate lowerDiff and upperDiff by considering the offset and width of the payload (this.element)
+			// versus the offset and width of the element enclosing the triangle, because the payload is inside
+			// whatever decorations (such as borders, shadow, rounded corners) and thus can give a reliable indication
+			// of the thickness of the combined decorations
+
+				arrowBeg = ctxpopup._ui.arrow[arrow].offset()[coord.beg],
+				arrowSize = ctxpopup._ui.arrow[arrow][coord.outerSize]( true ),
+				payloadBeg = self.element.offset()[coord.beg],
+				payloadSize = self.element[coord.outerSize]( true ),
+				triangleSize = ctxpopup._ui.arrow[arrow][coord.triangleSize](),
+				triangleOffset,
+				finalposition,
+				ret;
+			if (isHorizontal) {
+				orig.x = 0;
+			} else {
+				orig.y = 0;
+			}
+			if (arrow == 'b' && self._target_height) {
+				orig.y -= self._target_height;
+			}
+			if (arrow == 'r' && self._target_width) {
+				orig.x -= self._target_width;
+			}
+			triangleOffset =
+				Math.max(
+					triangleSize // triangle size
+						+ Math.max( 0, payloadBeg - arrowBeg ), // lowerDiff
+					Math.min(
+							arrowSize // bottom
+								- triangleSize // triangle size
+								- Math.max( 0, arrowBeg + arrowSize - ( payloadBeg + payloadSize ) ), // upperDiff
+							arrowSize / 2 // arrow unrestricted offset
+								+ desired[coord.point]
+								- orig[coord.point]
+								- halfSize[coord.size]
+						)
+				);
+					// Triangle points here
+			finalposition = {
+				"x": orig.x + ( isHorizontal ? triangleOffset : 0) + ("r" === arrow ? size.cx : 0),
+				"y": orig.y + (!isHorizontal ? triangleOffset : 0) + ("b" === arrow ? size.cy : 0)
+			};
+			ret = {
+				actual			: orig,
+				triangleOffset	: triangleOffset,
+				absDiff			: Math.abs( x - finalposition.x ) + Math.abs( y - finalposition.y )
+			};
+
+			// Hide it back
+			ctxpopup._ui.arrow[arrow].hide();
+
+			return ret;
+		}
+
+		if ( ctxpopup ) {
+			// Returns:
+			// {
+			//    absDiff: int
+			//    triangleOffset: int
+			//    actual: { x: int, y: int }
+			// }
+
+			coords = {
+				l : getCoords( "l", 1, 0 ),
+				r : getCoords( "r", -1, 0 ),
+				t : getCoords( "t", 0, 1 ),
+				b : getCoords( "b", 0, -1 )
+			};
+
+			$.each( coords, function ( key, value ) {
+				if ( minDiff === undefined || value.absDiff < minDiff ) {
+					minDiff = value.absDiff;
+					minDiffIdx = key;
+				}
+			} );
+
+			// Side-effect: show the appropriate arrow and move it to the right offset
+			ctxpopup._ui.arrow[minDiffIdx]
+				.show()
+				.triangle( "option", "offset", coords[minDiffIdx].triangleOffset );
+			this.element.parents( ".ui-popupwindow" ).addClass( "ui-arrow-" + minDiffIdx );
+			return coords[minDiffIdx].actual;
+		}
+
+		return orig_placementCoords.call( this, x, y, cx, cy );
+	};
+
+	$.tizen.popupwindow.prototype.open = function ( x, y, target_width, target_height ) {
+		var ctxpopup = this.element.data( "ctxpopup" );
+
+		this._target_width = target_width;
+		this._target_height = target_height;
+
+		if ( ctxpopup ) {
+			this._setFade( false );
+			this._setShadow( false );
+			this._setCorners( false );
+			this._setOverlayTheme( null );
+			this._setOption( "overlayTheme", ctxpopup.options.overlayTheme );
+			ctxpopup._ui.arrow.all.triangle( "option", "color", ctxpopup._ui.container.css( "background-color" ) );
+
+			// temporary
+			$( '.ui-popupwindow' ).css( 'background', 'none' );
+		}
+
+		origOpen.call( this, x, y, true );
+	};
+
+	//auto self-init widgets
+	$( document ).bind( "pagecreate create", function ( e ) {
+		var ctxpopups = $( $.tizen.ctxpopup.prototype.options.initSelector, e.target );
+		$.tizen.ctxpopup.prototype.enhanceWithin( e.target );
+	} );
+}( jQuery ) );
+
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+} );
+//>>excludeEnd("jqmBuildExclude");