You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by pp...@apache.org on 2013/09/10 20:04:15 UTC
[10/51] [partial] [cordova-tizen] Tizen SDK 2.2 support mores samples
http://git-wip-us.apache.org/repos/asf/cordova-tizen/blob/4ebce38e/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.gallery.js
----------------------------------------------------------------------
diff --git a/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.gallery.js b/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.gallery.js
new file mode 100644
index 0000000..08afe90
--- /dev/null
+++ b/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.gallery.js
@@ -0,0 +1,828 @@
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+//>>description: Shows images one by one, and moves them by flicking
+//>>label: Gallery
+//>>group: Tizen:Widgets
+
+define( [
+ 'jquery',
+ "jqm/jquery.mobile.widget"
+ ], 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>
+ */
+
+/*
+ * Gallery widget
+ *
+ * HTML Attributes
+ *
+ * data-role: set to 'gallery'
+ * data-index: start index
+ * data-vertical-align: set to top or middle or bottom.
+ *
+ * APIs
+ *
+ * add(file): add the image (parameter: url of iamge)
+ * remove(index): remove the image (parameter: index of image)
+ * refresh(index): refresh the widget, should be called after add or remove. (parameter: start index)
+ * empty: remove all of images from the gallery
+ * length: get length of images
+ * value(index): get or set current index of gallery (parameter: index of image)
+ *
+ * Events
+ *
+ * N/A
+ *
+ * Example
+ *
+ * <div data-role="gallery" id="gallery" data-index="3" data-vertical-align="middle">
+ * <img src="01.jpg">
+ * <img src="02.jpg">
+ * <img src="03.jpg">
+ * <img src="04.jpg">
+ * <img src="05.jpg">
+ * </div>
+ *
+ *
+ * $('#gallery-add').bind('vmouseup', function ( e ) {
+ * $('#gallery').gallery('add', '9.jpg');
+ * $('#gallery').gallery('add', '10.jpg');
+ * $('#gallery').gallery('refresh');
+ * });
+ *
+ * $('#gallery-del').bind('vmouseup', function ( e ) {
+ * $('#gallery').gallery('remove');
+ * });
+ *
+ */
+
+ /**
+ @class Gallery
+ The gallery widget shows images in a gallery on the screen. <br/><br/> To add an gallery widget to the application, use the following code:
+
+ <div data-role="gallery" id="gallery" data-vertical-align="middle" data-index="3">
+ <img src="01.jpg">
+ <img src="02.jpg">
+ <img src="03.jpg">
+ <img src="04.jpg">
+ <img src="05.jpg">
+ </div>
+*/
+/**
+ @property {Integer} data-index
+ Defines the index number of the first image in the gallery.
+ <br/>The default value is 0.
+*/
+/**
+ @property {String} data-vertical-align
+ Defines the image alignment. The alignment options are top, middle, and bottom.
+ <br/>The default value is top.
+*/
+/**
+ @method add
+ The add method is used to add an image to the gallery. The image_file attribute defines the image file URL.
+
+ <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
+ $("#gallery").gallery('add', [image_file]);
+*/
+/**
+ @method remove
+ The remove method is used to delete an image from the gallery. The image_index attribute defines the index of the image to be deleted. If not set removes current image.
+
+ <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
+ $("#gallery").gallery('remove', [image_index]);
+*/
+/**
+ @method refresh
+ The refresh method is used to refresh the gallery. This method must be called after adding images to the gallery.
+
+ <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
+ $("#gallery").gallery('refresh');
+*/
+/**
+ @method empty
+ The empty method is used to remove all of images from the gallery.
+
+ <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
+ $("#gallery").gallery('empty');
+*/
+/**
+ @method length
+ The length method is used to get length of images.
+
+ <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
+ length = $("#gallery").gallery('length');
+*/
+/**
+ @method value
+ The value method is used to get or set current index of gallery. The image_index attribute defines the index of the image to be set. If not get current index.
+
+ <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
+ value = $("#gallery").gallery('value');
+ $("#gallery").gallery('value', [image_index]);
+*/
+(function ( $, window, undefined ) {
+ $.widget( "tizen.gallery", $.mobile.widget, {
+ options: {
+ flicking: false,
+ duration: 500
+ },
+
+ dragging: false,
+ moving: false,
+ max_width: 0,
+ max_height: 0,
+ org_x: 0,
+ org_time: null,
+ cur_img: null,
+ prev_img: null,
+ next_img: null,
+ images: [],
+ images_hold: [],
+ index: 0,
+ align_type: null,
+ direction: 1,
+ container: null,
+ orientationEventFire: false,
+
+ _resize: function ( index ) {
+ var img = this.images[index],
+ width = this.images[index].width(),
+ height = this.images[index].height(),
+ margin = 0,
+ ratio,
+ img_max_width = this.max_width - margin,
+ img_max_height = this.max_height - margin;
+
+ ratio = height / width;
+
+ if( img_max_width == 0 && isNaN( img_max_height ) ) {
+ /*
+ Exception : When image max width and height has incorrect value.
+ This exception is occured when this.max_width value is 0 and this.max_height value is NaN when page transition like rotation.
+ This exception affect that image width and height values are 0.
+ */
+ img.width( width );
+ img.height( width * ratio );
+ } else {
+ if ( width > img_max_width ) {
+ img.width( img_max_width );
+ img.height( img_max_width * ratio );
+ }
+
+ height = img.height();
+
+ if ( height > img_max_height ) {
+ img.height( img_max_height );
+ img.width( img_max_height / ratio );
+ }
+ }
+ },
+
+ _align: function ( index, obj ) {
+ var img = this.images[index],
+ img_top = 0;
+
+ if ( !obj ) {
+ return;
+ }
+ if ( !obj.length ) {
+ return;
+ }
+
+ if ( this.align_type == "middle" ) {
+ img_top = ( this.max_height - img.height() ) / 2;
+ } else if ( this.align_type == "bottom" ) {
+ img_top = this.max_height - img.height();
+ } else {
+ img_top = 0;
+ }
+
+ obj.css( 'top', img_top + 'px' );
+ },
+
+ _attach: function ( index, obj ) {
+ var self = this,
+ processing = function () {
+ self._resize( index );
+ self._align( index, obj );
+
+ },
+ loading = function () {
+ if ( self.images[index] === undefined ) {
+ return;
+ }
+
+ if ( !self.images[index].height() ) {
+ setTimeout( loading, 10 );
+ return;
+ }
+
+ processing();
+ };
+
+ if ( !obj ) {
+ return;
+ }
+ if ( !obj.length ) {
+ return;
+ }
+ if ( index < 0 ) {
+ return;
+ }
+ if ( !this.images.length ) {
+ return;
+ }
+ if ( index >= this.images.length ) {
+ return;
+ }
+
+ obj.css( "display", "block" );
+ obj.css( "visibility", "hidden" );
+ obj.append( this.images[index] );
+ loading();
+ },
+
+ _detach: function ( index, obj ) {
+ if ( !obj ) {
+ return;
+ }
+ if ( !obj.length ) {
+ return;
+ }
+ if ( index < 0 ) {
+ return;
+ }
+ if ( index >= this.images.length ) {
+ return;
+ }
+
+ obj.css( "display", "none" );
+ this.images[index].removeAttr("style");
+ this.images[index].detach();
+ },
+
+ _detach_all: function () {
+ var i;
+
+ for ( i = 0; i < this.images.length; i++ ) {
+ this.images[i].detach();
+ }
+ },
+
+ _drag: function ( _x ) {
+ var delta,
+ coord_x;
+
+ if ( !this.dragging ) {
+ return;
+ }
+
+ if ( this.options.flicking === false ) {
+ delta = this.org_x - _x;
+
+ // first image
+ if ( delta < 0 && !this.prev_img.length ) {
+ return;
+ }
+ // last image
+ if ( delta > 0 && !this.next_img.length ) {
+ return;
+ }
+ }
+
+ coord_x = _x - this.org_x;
+
+ this._moveLeft( this.cur_img , coord_x + 'px' );
+ if ( this.next_img.length ) {
+ this._moveLeft( this.next_img , coord_x + this.window_width + 'px' );
+ }
+ if ( this.prev_img.length ) {
+ this._moveLeft( this.prev_img , coord_x - this.window_width + 'px' );
+ }
+ },
+
+ _move: function ( _x ) {
+ var delta = this.org_x - _x,
+ flip = 0,
+ drag_time,
+ sec,
+ self;
+
+ if ( delta == 0 ) {
+ return;
+ }
+
+ if ( delta > 0 ) {
+ flip = delta < ( this.max_width * 0.45 ) ? 0 : 1;
+ } else {
+ flip = -delta < ( this.max_width * 0.45 ) ? 0 : 1;
+ }
+
+ if ( !flip ) {
+ drag_time = Date.now() - this.org_time;
+
+ if ( Math.abs( delta ) / drag_time > 1 ) {
+ flip = 1;
+ }
+ }
+
+ if ( flip ) {
+ if ( delta > 0 && this.next_img.length ) {
+ /* next */
+ this._detach( this.index - 1, this.prev_img );
+
+ this.prev_img = this.cur_img;
+ this.cur_img = this.next_img;
+ this.next_img = this.next_img.next();
+
+ this.index++;
+
+ if ( this.next_img.length ) {
+ this._moveLeft( this.next_img , this.window_width + 'px' );
+ this._attach( this.index + 1, this.next_img );
+ }
+
+ this.direction = 1;
+
+ } else if ( delta < 0 && this.prev_img.length ) {
+ /* prev */
+ this._detach( this.index + 1, this.next_img );
+
+ this.next_img = this.cur_img;
+ this.cur_img = this.prev_img;
+ this.prev_img = this.prev_img.prev();
+
+ this.index--;
+
+ if ( this.prev_img.length ) {
+ this._moveLeft( this.prev_img , -this.window_width + 'px' );
+ this._attach( this.index - 1, this.prev_img );
+ }
+
+ this.direction = -1;
+ }
+ }
+
+ sec = this.options.duration;
+ self = this;
+
+ this.moving = true;
+
+ setTimeout( function () {
+ self.moving = false;
+ }, sec - 25 );
+
+ this._moveLeft( this.cur_img, 0 + 'px', sec );
+ if ( this.next_img.length ) {
+ this._moveLeft( this.next_img, this.window_width + 'px', sec );
+ }
+ if ( this.prev_img.length ) {
+ this._moveLeft( this.prev_img, -this.window_width + 'px', sec );
+ }
+ },
+
+ _add_event: function () {
+ var self = this,
+ date;
+
+ this.container.bind( 'vmousemove', function ( e ) {
+ e.preventDefault();
+
+ if ( self.moving ) {
+ return;
+ }
+ if ( !self.dragging ) {
+ return;
+ }
+
+ self._drag( e.pageX );
+ } );
+
+ this.container.bind( 'vmousedown', function ( e ) {
+ e.preventDefault();
+
+ if ( self.moving ) {
+ return;
+ }
+
+ self.dragging = true;
+
+ self.org_x = e.pageX;
+
+ self.org_time = Date.now();
+ } );
+
+ this.container.bind( 'vmouseup', function ( e ) {
+ if ( self.moving ) {
+ return;
+ }
+
+ self.dragging = false;
+
+ self._move( e.pageX );
+ } );
+
+ this.container.bind( 'vmouseout', function ( e ) {
+ if ( self.moving ) {
+ return;
+ }
+ if ( !self.dragging ) {
+ return;
+ }
+
+ if ( ( e.pageX < 20 ) ||
+ ( e.pageX > ( self.max_width - 20 ) ) ) {
+ self._move( e.pageX );
+ self.dragging = false;
+ }
+ } );
+ },
+
+ _del_event: function () {
+ this.container.unbind( 'vmousemove' );
+ this.container.unbind( 'vmousedown' );
+ this.container.unbind( 'vmouseup' );
+ this.container.unbind( 'vmouseout' );
+ },
+ _setTranslateposition : function ( $ele, value ) {
+ var translate,
+ cssArray = null,
+ self = this;
+
+ if ( $.support.cssTransform3d ) {
+ translate = "translate3d(" + value + ", 0px, 0px)";
+ } else {
+ translate = "translate(" + value + ", 0px)";
+ }
+ cssArray = {"-moz-transform": translate,
+ "-webkit-transform": translate,
+ "-ms-transform": translate,
+ "-o-transform": translate,
+ "transform": translate};
+
+ $ele.css(cssArray);
+ return $ele;
+ },
+ _hidePrevNext : function() {
+ var self = this;
+
+ if( self.next_img ) {
+ self.next_img.css( "visibility", "hidden" );
+ }
+ if( self.prev_img ) {
+ self.prev_img.css( "visibility", "hidden" );
+ }
+
+ },
+ _hideCur : function() {
+ var self = this;
+ if( self.cur_img ) {
+ self.cur_img.css( "visibility", "hidden" );
+ }
+ },
+ _moveLeft : function ( $ele , value , duration ) {
+ var translate,
+ transition = "",
+ cssArray = null,
+ self = this;
+
+ if ( $.support.cssTransform3d ) {
+ translate = "translate3d(" + value + ", 0px, 0px)";
+ } else {
+ translate = "translate(" + value + ", 0px)";
+ }
+ if( duration !== undefined ) {
+ transition = "-webkit-transform " + (duration / 1000)+ "s ease";
+ }
+ cssArray = {"-moz-transform": translate,
+ "-webkit-transform": translate,
+ "-ms-transform": translate,
+ "-o-transform": translate,
+ "transform": translate};
+ if( transition !== "" ) {
+ cssArray["-webkit-transition"] = transition ;
+ if( value == "0px" ) {
+ $ele.one( 'webkitTransitionEnd', self._hidePrevNext );
+ } else {
+ $ele.one( 'webkitTransitionEnd', self._hideCur );
+ }
+ }
+ if( value == "0px" ) {
+ $ele.css( "visibility", "visible" );
+ }
+
+ $ele.css(cssArray);
+ return $ele;
+ },
+ _show: function () {
+ /* resizing */
+ this.window_width = $( window ).width();
+ this.max_width = this._get_width();
+ this.max_height = this._get_height();
+ this.container.css( 'height', this.max_height );
+
+ this.cur_img = $( 'div' ).find( '.ui-gallery-bg:eq(' + this.index + ')' );
+ this.prev_img = this.cur_img.prev();
+ this.next_img = this.cur_img.next();
+
+ this._attach( this.index - 1, this.prev_img );
+ this._attach( this.index, this.cur_img );
+ this._attach( this.index + 1, this.next_img );
+
+ this.cur_img.css( 'visibility', 'visible' );
+ if ( this.prev_img.length ) {
+ this._setTranslateposition( this.prev_img, -this.window_width + 'px');
+ }
+
+ this._moveLeft( this.cur_img, '0px');
+ if ( this.next_img.length ) {
+ this._setTranslateposition( this.next_img, this.window_width + 'px' );
+ }
+ },
+
+ show: function () {
+ if ( !this.images.length ) {
+ return;
+ }
+
+ this._show();
+ this._add_event();
+ },
+
+ _hide: function () {
+ this._detach( this.index - 1, this.prev_img );
+ this._detach( this.index, this.cur_img );
+ this._detach( this.index + 1, this.next_img );
+ },
+
+ hide: function () {
+ this._hide();
+ this._del_event();
+ },
+
+ _get_width: function () {
+ return $( this.element ).width();
+ },
+
+ _get_height: function () {
+ var $page = $( this.element ).parentsUntil( 'ui-page' ),
+ $content = $page.children( '.ui-content' ),
+ header_h = $page.children( '.ui-header' ).outerHeight() || 0,
+ footer_h = $page.children( '.ui-footer' ).outerHeight() || 0,
+ padding = parseFloat( $content.css( 'padding-top' ) )
+ + parseFloat( $content.css( 'padding-bottom' ) ),
+ content_h = $( window ).height() - header_h - footer_h - padding;
+
+ return content_h;
+ },
+
+ _create: function () {
+ var temp_img,
+ self = this,
+ index,
+ i = 0;
+
+ $( this.element ).wrapInner( '<div class="ui-gallery"></div>' );
+ $( this.element ).find( 'img' ).wrap( '<div class="ui-gallery-bg"></div>' );
+
+ this.container = $( this.element ).find('.ui-gallery');
+
+ temp_img = $( 'div' ).find( '.ui-gallery-bg:first' );
+
+ while ( temp_img.length ) {
+ this.images[i] = temp_img.find( 'img' );
+ temp_img = temp_img.next();
+ i++;
+ }
+
+ this._detach_all();
+
+ index = parseInt( $( this.element ).jqmData( 'index' ), 10 );
+ if ( !index ) {
+ index = 0;
+ }
+ if ( index < 0 ) {
+ index = 0;
+ }
+ if ( index >= this.images.length ) {
+ index = this.images.length - 1;
+ }
+
+ this.index = index;
+
+ this.align_type = $( this.element ).jqmData( 'vertical-align' );
+
+ $.extend( this, {
+ _globalHandlers: [
+ {
+ src: $( window ),
+ handler: {
+ orientationchange: $.proxy( this, "_orientationHandler" ),
+ resize: $.proxy( this, "_resizeHandler" )
+ }
+ }
+ ]
+ });
+
+ $.each( this._globalHandlers, function( idx, value ) {
+ value.src.bind( value.handler );
+ });
+ },
+
+ _update: function () {
+ var image_file,
+ bg_html,
+ temp_img;
+
+ while ( this.images_hold.length ) {
+ image_file = this.images_hold.shift();
+
+ bg_html = $( '<div class="ui-gallery-bg"></div>' );
+ temp_img = $( '<img src="' + image_file + '"></div>' );
+
+ bg_html.append( temp_img );
+ this.container.append( bg_html );
+ this.images.push( temp_img );
+ }
+
+ this._detach_all();
+ },
+ _resizeHandler: function() {
+ var self = this;
+ if( self.orientationEventFire ) {
+ self.refresh();
+ $( event.target ).trigger( "galleryorientationchanged", this );
+ self.orientationEventFire = false;
+ }
+ },
+ _orientationHandler: function() {
+ var self = this;
+ self.refresh();
+ self.orientationEventFire = true;
+ },
+ refresh: function ( start_index ) {
+ this._update();
+
+ this._hide();
+
+ if ( start_index === undefined ) {
+ start_index = this.index;
+ }
+ if ( start_index < 0 ) {
+ start_index = 0;
+ }
+ if ( start_index >= this.images.length ) {
+ start_index = this.images.length - 1;
+ }
+
+ this.index = start_index;
+
+ this._show();
+
+ return this.index;
+ },
+
+ add: function ( file ) {
+ this.images_hold.push( file );
+ },
+
+ remove: function ( index ) {
+ var temp_img;
+
+ if ( index === undefined ) {
+ index = this.index;
+ }
+
+ if ( index < 0 || index >= this.images.length ) {
+ return;
+ }
+
+ if ( index == this.index ) {
+ temp_img = this.cur_img;
+
+ if ( this.index == 0 ) {
+ this.direction = 1;
+ } else if ( this.index == this.images.length - 1 ) {
+ this.direction = -1;
+ }
+
+ if ( this.direction < 0 ) {
+ this.cur_img = this.prev_img;
+ this.prev_img = this.prev_img.prev();
+ if ( this.prev_img.length ) {
+ this._moveLeft( this.prev_img, -this.window_width + 'px' );
+ this._attach( index - 2, this.prev_img );
+ }
+ this.index--;
+ } else {
+ this.cur_img = this.next_img;
+ this.next_img = this.next_img.next();
+ if ( this.next_img.length ) {
+ this._moveLeft( this.next_img, this.window_width + 'px' );
+ this._attach( index + 2, this.next_img );
+ }
+ }
+ this._moveLeft( this.cur_img, '0px', this.options.duration );
+
+ } else if ( index == this.index - 1 ) {
+ temp_img = this.prev_img;
+ this.prev_img = this.prev_img.prev();
+ if ( this.prev_img.length ) {
+ this._moveLeft( this.prev_img, -this.window_width + 'px' );
+ this._attach( index - 1, this.prev_img );
+ }
+ this.index--;
+
+ } else if ( index == this.index + 1 ) {
+ temp_img = this.next_img;
+ this.next_img = this.next_img.next();
+ if ( this.next_img.length ) {
+ this._moveLeft( this.next_img, this.window_width + 'px' );
+ this._attach( index + 1, this.next_img );
+ }
+
+ } else {
+ temp_img = $( 'div' ).find( '.ui-gallery-bg:eq(' + index + ')' );
+ }
+
+ this.images.splice( index, 1 );
+ temp_img.detach();
+ },
+
+ empty: function () {
+ this.images.splice( 0, this.images.length );
+ this.container.find('.ui-gallery-bg').detach();
+ },
+
+ length: function () {
+ return this.images.length;
+ },
+
+ value: function ( index ) {
+ if ( index === undefined ) {
+ return this.index;
+ }
+
+ this.refresh( index );
+ },
+
+ unbind: function() {
+ $.each( this._globalHandlers, function( idx, value ) {
+ value.src.unbind( value.handler );
+ });
+ },
+
+ destory: function() {
+ this.unbind();
+ }
+
+ }); /* End of widget */
+
+ // auto self-init widgets
+ $( document ).bind( "pagecreate create", function ( e ) {
+ $( e.target ).find( ":jqmData(role='gallery')" ).gallery();
+ });
+
+ $( document ).bind( "pageshow", function ( e ) {
+ $( e.target ).find( ":jqmData(role='gallery')" ).gallery( 'show' );
+ });
+
+ $( document ).bind( "pagebeforehide", function ( e ) {
+ $( e.target ).find( ":jqmData(role='gallery')" ).gallery( 'hide' );
+ } );
+
+ $( document ).bind( "pageremove", function ( e ) {
+ //unbind resize and orientationchange events
+ $( e.target ).find( ":jqmData(role='gallery')" ).gallery( 'unbind' );
+ });
+
+}( jQuery, this ) );
+
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+} );
+//>>excludeEnd("jqmBuildExclude");
http://git-wip-us.apache.org/repos/asf/cordova-tizen/blob/4ebce38e/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.gallery3d.js
----------------------------------------------------------------------
diff --git a/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.gallery3d.js b/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.gallery3d.js
new file mode 100644
index 0000000..cded9f4
--- /dev/null
+++ b/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.gallery3d.js
@@ -0,0 +1,1503 @@
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+//>>description: 3D photo gallery widget.
+//>>label: Gallery3d
+//>>group: Tizen:Widgets
+
+define( [
+ 'jquery',
+ "jqm/jquery.mobile.widget",
+ 'libs/jquery.easing.1.3',
+ "libs/gl-matrix",
+ "./components/imageloader",
+ "./components/motionpath",
+ "./components/webgl"
+ ], function ( jQuery ) {
+
+//>>excludeEnd("jqmBuildExclude");
+
+/* ***************************************************************************
+ Flora License
+
+ Version 1.1, April, 2013
+
+ http://floralicense.org/license/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and
+ all other entities that control, are controlled by, or are
+ under common control with that entity. For the purposes of
+ this definition, "control" means (i) the power, direct or indirect,
+ to cause the direction or management of such entity,
+ whether by contract or otherwise, or (ii) ownership of fifty percent (50%)
+ or more of the outstanding shares, or (iii) beneficial ownership of
+ such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation source,
+ and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or Object form,
+ made available under the License, as indicated by a copyright notice
+ that is included in or attached to the work (an example is provided
+ in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object form,
+ that is based on (or derived from) the Work and for which the editorial
+ revisions, annotations, elaborations, or other modifications represent,
+ as a whole, an original work of authorship. For the purposes of this License,
+ Derivative Works shall not include works that remain separable from,
+ or merely link (or bind by name) to the interfaces of, the Work and
+ Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including the original
+ version of the Work and any modifications or additions to that Work or
+ Derivative Works thereof, that is intentionally submitted to Licensor
+ for inclusion in the Work by the copyright owner or by an individual or
+ Legal Entity authorized to submit on behalf of the copyright owner.
+ For the purposes of this definition, "submitted" means any form of
+ electronic, verbal, or written communication sent to the Licensor or
+ its representatives, including but not limited to communication on
+ electronic mailing lists, source code control systems, and issue
+ tracking systems that are managed by, or on behalf of, the Licensor
+ for the purpose of discussing and improving the Work, but excluding
+ communication that is conspicuously marked or otherwise designated
+ in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ "Tizen Certified Platform" shall mean a software platform that complies
+ with the standards set forth in the Tizen Compliance Specification
+ and passes the Tizen Compliance Tests as defined from time to time
+ by the Tizen Technical Steering Group and certified by the Tizen
+ Association or its designated agent.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work
+ solely as incorporated into a Tizen Certified Platform, where such
+ license applies only to those patent claims licensable by such
+ Contributor that are necessarily infringed by their Contribution(s)
+ alone or by combination of their Contribution(s) with the Work solely
+ as incorporated into a Tizen Certified Platform to which such
+ Contribution(s) was submitted. If You institute patent litigation
+ against any entity (including a cross-claim or counterclaim
+ in a lawsuit) alleging that the Work or a Contribution incorporated
+ within the Work constitutes direct or contributory patent infringement,
+ then any patent licenses granted to You under this License for that
+ Work shall terminate as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof pursuant to the copyright license
+ above, in any medium, with or without modifications, and in Source or
+ Object form, provided that You meet the following conditions:
+
+ 1. You must give any other recipients of the Work or Derivative Works
+ a copy of this License; and
+ 2. You must cause any modified files to carry prominent notices stating
+ that You changed the files; and
+ 3. You must retain, in the Source form of any Derivative Works that
+ You distribute, all copyright, patent, trademark, and attribution
+ notices from the Source form of the Work, excluding those notices
+ that do not pertain to any part of the Derivative Works; and
+ 4. If the Work includes a "NOTICE" text file as part of its distribution,
+ then any Derivative Works that You distribute must include a readable
+ copy of the attribution notices contained within such NOTICE file,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works, in at least one of the following places:
+ within a NOTICE text file distributed as part of the Derivative Works;
+ within the Source form or documentation, if provided along with the
+ Derivative Works; or, within a display generated by the Derivative Works,
+ if and wherever such third-party notices normally appear.
+ The contents of the NOTICE file are for informational purposes only
+ and do not modify the License.
+
+ You may add Your own attribution notices within Derivative Works
+ that You distribute, alongside or as an addendum to the NOTICE text
+ from the Work, provided that such additional attribution notices
+ cannot be construed as modifying the License. You may add Your own
+ copyright statement to Your modifications and may provide additional or
+ different license terms and conditions for use, reproduction, or
+ distribution of Your modifications, or for any such Derivative Works
+ as a whole, provided Your use, reproduction, and distribution of
+ the Work otherwise complies with the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Flora License to your work
+
+ To apply the Flora License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Flora License, Version 1.1 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://floralicense.org/license/
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+ * Authors: Hyunsook Park <hy...@samsung.com>
+ * Wonseop Kim <wo...@samsung.com>
+ */
+
+/**
+ * The gallery3d widget displays images along a curved path on a 3-dimensional coordinate system.
+ * To improve performance, the size of image(s) displayed on the screen should be a square(under
+ * 128X128 pixel) as possible. But if a user can't resize the images, this widget supports an image
+ * resizing feature and he/she can use it with "data-thumbnail-cache" option. ("data-thumbnail-cache"
+ * option resizes the gallery images under 128x128 pixels and stores the images on a local storage.
+ * So when a gallery3D widget is re-launched, the widget reuse the storage and a user can improve
+ * launching time. A browser or web runtime engine should support "Web Storage" feature to use that
+ * option.)
+ *
+ * HTML Attributes:
+ *
+ * data-thumbnail-cache : Determines whether to cache and resize images.
+ *
+ * APIs:
+ *
+ * next ( void )
+ * : This method moves each image forward one by one.
+ * prev ( void )
+ * : This method moves each image backward one by one.
+ * select ( [number] )
+ * : When the "select" method is called with an argument, the method selects the image of given index.
+ * If the method is called with no argument, it will return the Javascript object having "src"
+ * attribute having the selected image's URL.
+ * add ( object or string [, number] )
+ * This method adds an image to Gallery3D widget.
+ * If the second argument isn't inputted, the image is added at the 0th position.
+ * remove ( [number] )
+ * : This method deletes an image from Gallery3d widget.
+ * The argument defines the index of the image to be deleted.
+ * If an argument isn't inputted, it removes current image.
+ * clearThumbnailCache ( void )
+ * : This method clears the cache data of all images when thumbnailCache option is set as 'true'.
+ * refresh ( void )
+ * : This method updates and redraws current widget.
+ * empty ( void )
+ * : This method removes all of images from Gallery3D widget.
+ * length ( void )
+ * : This method gets the number of images.
+ *
+ * Events:
+ *
+ * select : Triggered when an image is selected.
+ *
+ * Examples:
+ *
+ * <script>
+ * $( "#gallery3d" ).on( "gallery3dcreate", function () {
+ * $( "#gallery3d" ).gallery3d( "add", "01.jpg" );
+ * });
+ * </script>
+ * <div id="gallery3d" data-role="gallery3d"></div>
+ */
+
+/**
+ @class Gallery3D
+ The gallery3d widget displays images along a curved path on a 3-dimensional coordinate system.
+ <br/><br/>To add an gallery3d widget to the application, use the following code:
+
+ <script>
+ $( "#gallery3d" ).on( "gallery3dcreate", function () {
+ $( "#gallery3d" ).gallery3d( "add", "01.jpg" );
+ });
+ </script>
+ <div id="gallery3d" data-role="gallery3d"></div>
+*/
+/**
+ @property {Boolean} data-thumbnail-cache
+ Determines whether to cache and resize images.
+ To improve performance, the size of image(s) displayed on the screen should be a square (under 128X128 pixels).
+ "data-thumbnail-cache" option resizes the gallery images under 128x128 pixels and stores the images on a local storage.
+ So when a gallery3D widget is re-launched, the widget reuses the storage and the launching time can be improved.
+ A browser or web runtime engine must support "Web Storage" feature to use this option.
+*/
+/**
+ @event select
+ Triggered when an image is selected.
+
+ <script>
+ $( "#gallery3d" ).on( "gallery3dcreate", function () {
+ $( "#gallery3d" ).gallery3d( "add", { src: "1.jpg" } )
+ .gallery3d( "add", { src: "2.jpg" } )
+ .gallery3d( "add", { src: "3.jpg" } );
+ }).on( "select", function ( event, data, index ) {
+ // Handle the select event
+ var urlOfImage = data.src, indexOfImage = index;
+ });
+ </script>
+ <div id="gallery3d" data-role="gallery3d"></div>
+*/
+/**
+ @method next
+ This method moves each image forward one by one.
+
+ <script>
+ $( "#gallery3d" ).on( "gallery3dcreate", function () {
+ $( "#gallery3d" ).gallery3d( "add", { src: "1.jpg" } )
+ .gallery3d( "add", { src: "2.jpg" } )
+ .gallery3d( "add", { src: "3.jpg" } )
+ .gallery3d( "next" );
+ });
+ </script>
+ <div id="gallery3d" data-role="gallery3d"></div>
+*/
+/**
+ @method prev
+ This method moves each image backward one by one.
+
+ <script>
+ $( "#gallery3d" ).on( "gallery3dcreate", function () {
+ $( "#gallery3d" ).gallery3d( "add", { src: "1.jpg" } )
+ .gallery3d( "add", { src: "2.jpg" } )
+ .gallery3d( "add", { src: "3.jpg" } )
+ .gallery3d( "prev" );
+ });
+ </script>
+ <div id="gallery3d" data-role="gallery3d"></div>
+*/
+/**
+ @method select
+ When the "select" method is called with an argument, the method selects the image of given index.
+ If the method is called with no argument, it will return the Javascript object having "src" attribute having the selected image's URL.
+
+ <script>
+ $( "#gallery3d" ).on( "gallery3dcreate", function () {
+ $( "#gallery3d" ).gallery3d( "add", { src: "1.jpg" } )
+ .gallery3d( "add", { src: "2.jpg" } )
+ .gallery3d( "add", { src: "3.jpg" } );
+ var selectedImage = $("#gallery3d"). gallery3d( "select" );
+ // selectedImage = { src: "3.jpg" };
+ });
+ </script>
+ <div id="gallery3d" data-role="gallery3d"></div>
+*/
+/**
+ @method add
+ This method adds an image to Gallery3D widget.
+ The first argument is a Javascript object having a "src" attribute or a string of image's path.
+ The second argument is an index of images.
+ If second argument isn't inputted, the image is added at the 0th position.
+
+ <script>
+ $( "#gallery3d" ).on( "gallery3dcreate", function () {
+ $( "#gallery3d" ).gallery3d( "add", { src: "1.jpg" } )
+ .gallery3d( "add", "2.jpg", 1 );
+ });
+ </script>
+ <div id="gallery3d" data-role="gallery3d"></div>
+*/
+/**
+ @method remove
+ This method deletes an image from Gallery3d widget.
+ The argument defines the index of the image to be deleted.
+ If an argument isn't inputted, it removes current image.
+
+ <script>
+ $( "#gallery3d" ).on( "gallery3dcreate", function () {
+ $( "#gallery3d" ).gallery3d( "add", { src: "1.jpg" } )
+ .gallery3d( "add", { src: "2.jpg" } )
+ .gallery3d( "add", { src: "3.jpg" } );
+
+ $( "#gallery3d" ).gallery3d( "remove" );
+ $( "#gallery3d" ).gallery3d( "remove", 1 );
+ });
+ </script>
+ <div id="gallery3d" data-role="gallery3d"></div>
+*/
+/**
+ @method clearThumbnailCache
+ This method clears the cache data of all images when thumbnailCache option is set as 'true'
+
+ <script>
+ $( "#gallery3d" ).on( "gallery3dcreate", function () {
+ $( "#gallery3d" ).gallery3d( "add", { src: "1.jpg" } )
+ .gallery3d( "add", { src: "2.jpg" } )
+ .gallery3d( "add", { src: "3.jpg" } );
+
+ $( "#gallery3d" ).gallery3d( "clearThumbnailCache" );
+ });
+ </script>
+ <div id="gallery3d" data-role="gallery3d" data-thumbnail-cache="true"></div>
+*/
+/**
+ @method refresh
+ This method updates and redraws current widget.
+
+ <script>
+ $( "#gallery3d" ).on( "gallery3dcreate", function () {
+ $( "#gallery3d" ).gallery3d( "add", { src: "1.jpg" } )
+ .gallery3d( "add", { src: "2.jpg" } )
+ .gallery3d( "add", { src: "3.jpg" } );
+
+ $( "#gallery3d" ).gallery3d( "refresh" );
+ });
+ </script>
+ <div id="gallery3d" data-role="gallery3d"></div>
+*/
+/**
+ @method empty
+ This method removes all of images from Gallery3D widget.
+
+ <script>
+ $( "#gallery3d" ).on( "gallery3dcreate", function () {
+ $( "#gallery3d" ).gallery3d( "add", { src: "1.jpg" } )
+ .gallery3d( "add", { src: "2.jpg" } )
+ .gallery3d( "add", { src: "3.jpg" } );
+
+ $( "#gallery3d" ).gallery3d( "empty" );
+ });
+ </script>
+ <div id="gallery3d" data-role="gallery3d"></div>
+*/
+/**
+ @method length
+ This method gets the number of images.
+
+ <script>
+ $( "#gallery3d" ).on( "gallery3dcreate", function () {
+ $( "#gallery3d" ).gallery3d( "add", { src: "1.jpg" } )
+ .gallery3d( "add", { src: "2.jpg" } )
+ .gallery3d( "add", { src: "3.jpg" } );
+
+ var imagesLength = $( "#gallery3d" ).gallery3d( "length" );
+ // imagesLength = 3;
+ });
+ </script>
+ <div id="gallery3d" data-role="gallery3d"></div>
+*/
+
+( function ( $, document, window, undefined ) {
+ function Node() {
+ this.vertices = [
+ -1.0, -1.0, 0.0,
+ 1.0, -1.0, 0.0,
+ 1.0, 1.0, 0.0,
+ -1.0, 1.0, 0.0
+ ];
+ this.textureCoords = [
+ 1.0, 0.0,
+ 0.0, 0.0,
+ 0.0, 1.0,
+ 1.0, 1.0
+ ];
+ this.normalVectors = [
+ 0.0, 0.0, 1.0,
+ 0.0, 0.0, 1.0,
+ 0.0, 0.0, 1.0,
+ 0.0, 0.0, 1.0
+ ];
+ this.texture = null;
+ this.textureBuffer = null;
+ this.textureBufferItemSize = 0;
+ this.mashOrder = [];
+ this.mvMatrix = null;
+ this.level = -1;
+ this.targetLevel = 0;
+ this.drawable = false;
+ this.image = null;
+ this.imageID = 0;
+ }
+
+ var isPreInitailization = false,
+ glMatrix = {},
+ VERTEX_SHADER,
+ FRAGMENT_SHADER,
+ GlArray32,
+ GlArray16,
+ preInitialize = function () {
+ if ( isPreInitailization ) {
+ return;
+ }
+
+ window.initGlMatrix( glMatrix );
+
+ VERTEX_SHADER = [
+ "attribute vec3 aVertexPosition;",
+ "attribute vec2 aTextureCoord;",
+ "attribute vec3 aVertexNormal;",
+ "uniform mat4 uMoveMatrix;",
+ "uniform mat4 uPerspectiveMatrix;",
+ "uniform mat3 nNormalMatrix;",
+ "uniform vec3 uAmbientColor;",
+ "uniform vec3 uLightDirection;",
+ "uniform vec3 uDirectionColor;",
+ "uniform vec3 uLightDirection_first;",
+ "uniform vec3 uLightDirection_second;",
+ "varying vec2 vTextureCoord;",
+ "varying vec3 vLightWeight;",
+ "varying vec4 vFogWeight;",
+
+ "void main(void) {",
+ " vec4 v_Position = uMoveMatrix * vec4(aVertexPosition, 1.0);",
+ " gl_Position = uPerspectiveMatrix * v_Position;",
+ " vTextureCoord = aTextureCoord;",
+ " float fog = 1.0 - ((gl_Position.z + 1.5) / 60.0);",
+ " vFogWeight = clamp( vec4( fog, fog, fog, 1.0), 0.6, 1.0);",
+ " vec3 transNormalVector = nNormalMatrix * aVertexNormal;",
+
+ " float vLightWeightFirst = 0.0;",
+ " float vLightWeightSecond = max( dot(transNormalVector, uLightDirection_second), 0.0 );",
+
+ " vLightWeight = uAmbientColor + uDirectionColor * vLightWeightSecond;",
+ "}"
+ ].join( "\n" );
+
+ FRAGMENT_SHADER = [
+ "precision mediump float;",
+ "varying vec2 vTextureCoord;",
+ "varying vec3 vLightWeight;",
+ "uniform sampler2D uSampler;",
+ "varying vec4 vFogWeight;",
+
+ "void main(void) {",
+ " vec4 TextureColor;",
+ " if ( vTextureCoord.s <= 0.01 || vTextureCoord.s >= 0.99 || vTextureCoord.t <= 0.01 || vTextureCoord.t >= 0.99 ) {",
+ " TextureColor = vec4(1.0, 1.0, 1.0, 0.5);",
+ " } else {",
+ " TextureColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));",
+ " }",
+ " TextureColor *= vFogWeight;",
+ " gl_FragColor = vec4(TextureColor.rgb * vLightWeight, TextureColor.a);",
+ "}"
+ ].join( "\n" );
+
+ GlArray32 = ( typeof window.Float32Array !== "undefined" ?
+ window.Float32Array :
+ ( typeof window.WebGLFloatArray !== "undefined" ? window.WebGLFloatArray : Array ) );
+
+ GlArray16 = ( typeof window.Uint16Array !== "undefined" ? window.Uint16Array : Array );
+
+ isPreInitailization = true;
+ },
+ degreeToRadian = function ( degree ) {
+ return degree * Math.PI / 180;
+ },
+ getContext3D = function ( canvas ) {
+ var gl, i,
+ contextNames = [ "experimental-webgl", "webkit-3d", "webgl", "moz-webgl" ];
+
+ for ( i = 0; i < contextNames.length; i += 1 ) {
+ try {
+ gl = canvas.getContext( contextNames[i] );
+ if ( gl ) {
+ break;
+ }
+ } catch ( e ) {
+ $( canvas ).html( "Unfortunately, there's a WebGL compatibility problem. </br> You may want to check your system settings." );
+ return;
+ }
+ }
+ return gl;
+ },
+ requestAnimationFrame = function ( callback ) {
+ var id = window.setTimeout( callback, 1000 / 60 );
+ return id;
+ },
+ cancelAnimationFrame = function ( id ) {
+ window.clearTimeout( id );
+ };
+
+ $.widget( "tizen.gallery3d", $.mobile.widget, {
+ options: {
+ thumbnailCache: false
+ },
+
+ _MAX_ITEM_COUNT: 28,
+ _ANIMATION_END: 999,
+ _DURATION_DEFAULT: 300,
+ _DURATION_FIRST: 1600,
+ _VIEWPORT_WIDTH: 1024,
+ _VIEWPORT_HEIGHT: 456,
+ _DIRECTION_LEFT: -1,
+ _DIRECTION_RIGHT: +1,
+
+ _gl: null,
+ _shaderProgram : null,
+ _positionBuffer : null,
+ _textureCoordBuffer : null,
+ _normalVectorBuffer : null,
+ _nodes: null,
+ _pMatrix : null,
+ _animationID: 0,
+ _dragInterval : 0,
+ _startTime : 0,
+ _sumTime : 0,
+ _lightsPositionStack : [
+ [0.0, 0.0, -1.0], // back
+ [-0.2, 0.0, 0.7] // front
+ ],
+ _path: null,
+ _swipeThresholdOfBasetimeGap: ( $.support.touch ? 30 : 70 ),
+ _swipeThresholdOfSensitivity: ( $.support.touch ? 2.0 : 10.0 ),
+ _canvas: null,
+ _imageList: [],
+ _maxDrawLength: 0,
+ _firstImageNumber: 0,
+ _lastImageNumber: 0,
+ _operationQueue: [],
+
+ _create: function () {
+ var self = this,
+ view = self.element,
+ option = self.options;
+
+ preInitialize();
+
+ self._canvas = $( "<canvas class='ui-gallery3d-canvas'></canvas>" );
+
+ view.addClass( "ui-gallery3d" ).append( self._canvas );
+ self._addBehavier();
+
+ self._dragInterval = 1000 / 30; // 30fps
+
+ $.each( self.options, function ( key, value ) {
+ self.options[ key ] = undefined;
+ self._setOption( key, value );
+ });
+ },
+
+ destroy: function () {
+ this._final();
+ $.mobile.widget.prototype.destroy.call( this );
+ },
+
+ _setOption: function ( key, value ) {
+ switch ( key ) {
+ case "thumbnailCache" :
+ if ( typeof value === "string" ) {
+ value = ( value === "true" ) ? true : false;
+ } else {
+ value = !!value;
+ }
+ this._reset();
+ break;
+ }
+
+ $.mobile.widget.prototype._setOption.call( this, key, value );
+ },
+
+ _init: function ( canvas ) {
+ var self = this,
+ pathPoints = [
+ [40, 0, -48],
+ [-12, 0, -40], // contorl Point of Point1
+ [24, 0, -9], // contorl Point of Point2
+ [-5, 0, -5]
+ ],
+ i;
+
+ canvas = canvas || self._canvas;
+
+ if ( !canvas ) {
+ return;
+ }
+
+ self._gl = self._gl || self._initGL( canvas[0] );
+ if ( !self._gl ) {
+ return;
+ }
+
+ if ( !self._imageList ) {
+ return;
+ }
+
+ self._shaderProgram = self._shaderProgram || self._initShader( self._gl );
+ if ( !self._shaderProgram ) {
+ return;
+ }
+
+ if ( self._imageList.length > self._MAX_ITEM_COUNT ) {
+ self._firstImageNumber = self._imageList.length - 1;
+ self._lastImageNumber = self._MAX_ITEM_COUNT - 1;
+ }
+
+ self._nodes = self._initBuffers( self._gl, self._shaderProgram );
+
+ self._initTextures( self._gl, self._nodes );
+
+ self._path = $.motionpath( "bezier2d", {
+ points: pathPoints,
+ maxLevel: self._MAX_ITEM_COUNT
+ } );
+
+ for ( i = 0; i < self._nodes.length; i += 1 ) {
+ self._path.levels[i] = self._path.levels[i + 1] || 0;
+ self._nodes[i].level = i;
+ }
+
+ this._setPosition( self._ANIMATION_END, this._DIRECTION_RIGHT );
+
+ while ( this._operationQueue.length ) {
+ this._setPosition( self._ANIMATION_END, this._operationQueue.shift() );
+ }
+ },
+
+ _final: function ( canvas ) {
+ var self = this,
+ gl = self._gl;
+
+ if ( !gl ) {
+ return;
+ }
+
+ self._stop();
+
+ canvas = canvas || self._canvas;
+
+ $( self._nodes ).each( function ( i ) {
+ var node = self._nodes[i];
+ gl.deleteTexture( node.texture );
+ node.texture = null;
+ });
+ self._nodes = null;
+
+ gl.deleteBuffer( self._positionBuffer );
+ self._positionBuffer = null;
+ gl.deleteBuffer( self._textureCoordBuffer );
+ self._textureCoordBuffer = null;
+ gl.deleteBuffer( self._normalVectorBuffer );
+ self._normalVectorBuffer = null;
+
+ $.webgl.shader.deleteShaders( gl );
+ gl.deleteProgram( self._shaderProgram );
+ self._shaderProgram = null;
+
+ self._gl = gl = null;
+ },
+
+ _addBehavier : function () {
+ var self = this,
+ view = self.element,
+ canvas = self._canvas,
+ touchStartEvt = ( $.support.touch ? "touchstart" : "mousedown" ),
+ touchMoveEvt = ( $.support.touch ? "touchmove" : "mousemove" ) + ".gallery3d",
+ touchEndEvt = ( $.support.touch ? "touchend" : "mouseup" ) + ".gallery3d",
+ $document = $( document );
+
+ canvas.on( "webglcontextlost", function ( e ) {
+ e.preventDefault();
+ }).on( "webglcontextrestored", function ( e ) {
+ self._init();
+ }).on( touchStartEvt, function ( e ) {
+ var i = 0,
+ startX = 0,
+ deltaMaxSteps = 20,
+ deltas = [ deltaMaxSteps ],
+ deltaTimes = [ deltaMaxSteps ],
+ deltaIndex = 0,
+ dragValue = 0,
+ dragDirection = false,
+ prevTime = 0;
+
+ e.preventDefault();
+ e.stopPropagation();
+
+ if ( self._imageList.length <= 1 ) {
+ return;
+ }
+
+ self._stop();
+
+ startX = $.support.touch ? e.originalEvent.changedTouches[0].pageX : e.pageX;
+ prevTime = $.now();
+
+ for ( i = 0; i < deltaMaxSteps; i += 1 ) {
+ deltas[i] = startX;
+ deltaTimes[i] = $.now();
+ }
+
+ deltaIndex += 1;
+
+ view.on( touchMoveEvt, function ( e ) {
+ var x, dx, interval;
+
+ e.preventDefault();
+ e.stopPropagation();
+
+ x = $.support.touch ? e.originalEvent.changedTouches[0].pageX : e.pageX;
+ dx = startX - x;
+
+ deltas[deltaIndex] = x;
+ deltaTimes[deltaIndex] = $.now();
+ interval = deltaTimes[deltaIndex] - prevTime;
+
+ deltaIndex = ( deltaIndex + 1 ) % deltaMaxSteps;
+
+ // Validation of drag
+ if ( Math.abs( dx ) >= 10 && interval >= self._dragInterval ) {
+ if ( dragDirection !== ( ( dx < 0 ) ? self._DIRECTION_RIGHT : self._DIRECTION_LEFT ) ) {
+ dragValue = 0;
+ dragDirection = ( dx < 0 ) ? self._DIRECTION_RIGHT : self._DIRECTION_LEFT;
+ }
+
+ dragValue += Math.abs( dx ) / 100;
+ if ( dragValue >= 1 ) {
+ self._setPosition( self._ANIMATION_END, dragDirection );
+ dragValue = 0;
+ } else {
+ self._setPosition( dragValue, dragDirection );
+ }
+ self._drawScene();
+ startX = x;
+ prevTime = $.now();
+ }
+ }).on( touchEndEvt, function ( e ) {
+ var baseTime = 0,
+ recent = -1,
+ index = 0,
+ previous = 0,
+ baseTimeRatio = 0,
+ fx = 0,
+ lastX = 0,
+ velocityX = 0,
+ dx = 0,
+ isSwipe = true,
+ direction;
+
+ e.preventDefault();
+ e.stopPropagation();
+
+ // Validation of swipe
+ baseTime = $.now() - self._swipeThresholdOfBasetimeGap;
+ lastX = $.support.touch ? e.originalEvent.changedTouches[0].pageX : e.pageX;
+ dx = startX - lastX;
+ startX = 0;
+ for ( i = 0; i < deltaMaxSteps; i += 1 ) {
+ index = ( deltaIndex + i ) % deltaMaxSteps;
+ if ( deltaTimes[index] > baseTime ) {
+ recent = index;
+ break;
+ }
+ }
+ if ( recent < 0 ) {
+ isSwipe = false;
+ }
+
+ if ( isSwipe ) {
+ previous = recent;
+ for ( i = 0; i < deltaMaxSteps; i += 1 ) {
+ previous = ( previous - 1 + deltaMaxSteps ) % deltaMaxSteps;
+ if ( deltaTimes[previous] < deltaTimes[recent] ) {
+ break;
+ }
+ }
+ // too slow or too fast
+ if ( i === deltaMaxSteps || baseTime < deltaTimes[previous] ) {
+ isSwipe = false;
+ }
+ }
+
+ if ( isSwipe ) {
+ baseTimeRatio = ( baseTime - deltaTimes[previous] ) / ( deltaTimes[recent] - deltaTimes[previous] );
+ fx = ( 1.0 - baseTimeRatio ) * deltas[previous] + baseTimeRatio * deltas[recent];
+ if ( Math.abs( fx - lastX ) < self._swipeThresholdOfSensitivity ) {
+ fx = lastX;
+ }
+ velocityX = parseInt( ( lastX - fx ) / ( $.now() - baseTime ), 10 );
+ }
+
+ if ( isSwipe && velocityX ) {
+ direction = ( velocityX < 0 ) ? self._DIRECTION_LEFT : self._DIRECTION_RIGHT;
+ self._run( direction, Math.abs( velocityX ), dragValue );
+ } else if ( dragDirection !== 0 && dragValue ) {
+ self._animate( null, self._DURATION_DEFAULT * ( 1 - dragValue ), dragDirection, 0, dragValue );
+ }
+
+ view.off( ".gallery3d" );
+ $document.off( ".gallery3d" );
+ });
+
+ $document.on( touchMoveEvt + " " + touchEndEvt, function () {
+ view.trigger( touchEndEvt );
+ });
+ });
+ },
+
+ // ----------------------------------------------------------
+ // WebGL
+ // ----------------------------------------------------------
+ _initGL: function ( canvas ) {
+ var self = this,
+ mat4 = glMatrix.mat4,
+ gl;
+
+ gl = getContext3D( canvas );
+ if ( !gl ) {
+ return null;
+ }
+
+ gl.enable( gl.BLEND );
+ gl.blendFunc( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA );
+
+ gl.enable( gl.DEPTH_TEST );
+ gl.depthFunc( gl.LEQUAL );
+
+ canvas.width = self._VIEWPORT_WIDTH;
+ canvas.height = self._VIEWPORT_HEIGHT;
+ gl.viewportWidth = canvas.width;
+ gl.viewportHeight = canvas.height;
+ gl.viewport( 0, 0, gl.viewportWidth, gl.viewportHeight );
+ self._pMatrix = mat4.create();
+ mat4.perspective( 40, gl.viewportWidth / gl.viewportHeight, 0.1, 10000.0, self._pMatrix );
+
+ gl.clearColor( 0.15, 0.15, 0.15, 1.0 );
+ gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );
+
+ return gl;
+ },
+
+ _initShader : function ( gl ) {
+ var self = this,
+ shaderProgram;
+
+ shaderProgram = $.webgl.shader.addShaderProgram( self._gl, VERTEX_SHADER, FRAGMENT_SHADER );
+ gl.useProgram( shaderProgram );
+
+ shaderProgram.vertexPositionAttr = gl.getAttribLocation( shaderProgram, "aVertexPosition" );
+ gl.enableVertexAttribArray( shaderProgram.vertexPositionAttr );
+
+ shaderProgram.textureCoordAttr = gl.getAttribLocation( shaderProgram, "aTextureCoord" );
+ gl.enableVertexAttribArray( shaderProgram.textureCoordAttr );
+
+ // Set light normal vectors for lighting~
+ shaderProgram.vertexNormalAttr = gl.getAttribLocation( shaderProgram, "aVertexNormal" );
+ gl.enableVertexAttribArray( shaderProgram.vertexNormalAttr );
+
+ shaderProgram.perspectiveMU = gl.getUniformLocation( shaderProgram, "uPerspectiveMatrix");
+ shaderProgram.transformMU = gl.getUniformLocation( shaderProgram, "uMoveMatrix");
+ shaderProgram.sampleUniform = gl.getUniformLocation( shaderProgram, "uSampler");
+
+ // Set light variables~
+ shaderProgram.normalMU = gl.getUniformLocation( shaderProgram, "nNormalMatrix");
+ shaderProgram.ambientColorU = gl.getUniformLocation( shaderProgram, "uAmbientColor");
+ shaderProgram.lightDirU_first = gl.getUniformLocation( shaderProgram, "uLightDirection_first");
+ shaderProgram.lightDirU_second = gl.getUniformLocation( shaderProgram, "uLightDirection_second");
+ shaderProgram.directionColorU = gl.getUniformLocation( shaderProgram, "uDirectionColor");
+
+ return shaderProgram;
+ },
+
+ _initBuffers: function ( gl, shaderProgram ) {
+ var self = this,
+ i = 0,
+ mashBase = 0,
+ vertices = [],
+ textureCoords = [],
+ normalVectors = [],
+ nodes = [],
+ maxDrawLength = self._MAX_ITEM_COUNT;
+
+ for ( i = 0; i < self._imageList.length + 1; i += 1 ) {
+ nodes[i] = new Node();
+ $.merge( vertices, nodes[i].vertices );
+ $.merge( textureCoords, nodes[i].textureCoords );
+ $.merge( normalVectors, nodes[i].normalVectors );
+
+ nodes[i].textureBuffer = gl.createBuffer();
+ gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, nodes[i].textureBuffer );
+ mashBase = i * 4;
+ nodes[i].meshOrder = [
+ mashBase, mashBase + 1, mashBase + 2,
+ mashBase + 2, mashBase + 3, mashBase
+ ];
+ gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, new GlArray16( nodes[i].meshOrder ), gl.STATIC_DRAW );
+ gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, null ); // release buffer memory
+ nodes[i].textureBufferItemSize = 6;
+ }
+
+ self._positionBuffer = $.webgl.buffer.attribBufferData( gl, new GlArray32( vertices ) );
+ self._positionBuffer.itemSize = 3;
+
+ self._textureCoordBuffer = $.webgl.buffer.attribBufferData( gl, new GlArray32( textureCoords ) );
+ self._textureCoordBuffer.itemSize = 2;
+
+ self._normalVectorBuffer = $.webgl.buffer.attribBufferData( gl, new GlArray32( normalVectors ) ); // Vertex's normal vector for Direction light
+ self._normalVectorBuffer.itemSize = 3;
+
+ // Ambient light
+ gl.uniform3f( shaderProgram.ambientColorU, 0.1, 0.1, 0.1 );
+ // Direcntion light
+ gl.uniform3f( shaderProgram.directionColorU, 1.0, 1.0, 1.0 );
+
+ return nodes;
+ },
+
+ // ----------------------------------------------------------
+ // Texture
+ // ----------------------------------------------------------
+ _initTextures: function ( gl, nodes ) {
+ var self = this;
+
+ $( nodes ).each( function ( i ) {
+ var node = nodes[i],
+ url;
+
+ if ( !self._imageList[i] ) {
+ return false;
+ }
+
+ url = self._imageList[i].src;
+ node.texture = gl.createTexture();
+ self._loadImage( url, i, i, gl, nodes );
+ });
+ },
+
+ _loadImage: function ( url, i, imageID, gl, nodes ) {
+ var self = this,
+ isMipmap = false,
+ image,
+ node;
+
+ gl = gl || self._gl;
+ nodes = nodes || self._nodes;
+ isMipmap = isMipmap || false;
+ node = nodes[i];
+ node.image = node.image || new Image();
+ node.imageID = imageID;
+
+ $( node.image ).one( "load", function ( e ) {
+ self._bindTexture( gl, node, this, isMipmap );
+
+ if ( !self._animationID ) {
+ self._setPosition( 0, 0 );
+ }
+ });
+
+ if ( self.options.thumbnailCache ) {
+ $.imageloader.getThumbnail( url, function ( result ) {
+ if ( result === "NOT_FOUND_ERR" ) {
+ $.imageloader.setThumbnail( url, function ( result ) {
+ if ( result && result.length > 30 ) {
+ node.image.src = result;
+ isMipmap = true;
+ } else {
+ node.image.src = url;
+ }
+ });
+ } else if ( result && result.length > 30 ) {
+ node.image.src = result;
+ isMipmap = true;
+ } else {
+ node.image.src = url;
+ }
+ });
+ } else {
+ node.image.src = url;
+ }
+ },
+
+ _bindTexture: function ( gl, node, image, isMipmap ) {
+ if ( !node || !node.texture ) {
+ return;
+ }
+
+ gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, true );
+
+ gl.bindTexture( gl.TEXTURE_2D, node.texture );
+ gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image );
+
+ if ( isMipmap ) {
+ gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR );
+ gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST );
+ gl.generateMipmap( gl.TEXTURE_2D );
+ } else {
+ gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR );
+ gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR );
+ }
+
+ gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE );
+ gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE );
+
+ node.texture.loaded = true;
+
+ // release texture memory
+ gl.bindTexture( gl.TEXTURE_2D, null );
+ },
+
+ // ----------------------------------------------------------
+ // rendering
+ // ----------------------------------------------------------
+ _setPosition: function ( progress, direction ) {
+ var self = this,
+ mat4 = glMatrix.mat4,
+ nodes = self._nodes,
+ imageList = self._imageList,
+ imageListLength = imageList.length,
+ itemCount = self._MAX_ITEM_COUNT,
+ displayLength = ( imageListLength > itemCount ) ? itemCount : imageListLength,
+ nextLevelLenth = 0,
+ i = 0,
+ t = 0,
+ position = 0,
+ angle = 0,
+ current = 0,
+ next = 0,
+ nextLevel = 0,
+ path = self._path,
+ nextImageID = 0;
+
+ nextLevelLenth = ( direction >= 0 ) ? displayLength + 1 : displayLength;
+
+ if ( !nodes[i].level ) {
+ nodes[i].level = displayLength;
+ }
+
+ for ( i = 0; i < displayLength; i += 1 ) {
+ if ( !nodes[i].mvMatrix ) {
+ nodes[i].mvMatrix = mat4.create();
+ }
+
+ if ( direction > 0 && nodes[i].level >= displayLength ) {
+ nodes[i].level = 0;
+ }
+
+ current = path.levels[nodes[i].level];
+ nextLevel = ( nodes[i].level + nextLevelLenth + direction ) % nextLevelLenth;
+ next = path.levels[nextLevel];
+
+ if ( imageListLength > itemCount ) {
+ if ( direction > 0 && nextLevel === 1
+ && self._firstImageNumber !== nodes[i].imageID ) {
+ self._loadImage( imageList[self._firstImageNumber].src, i, self._firstImageNumber );
+ } else if ( direction < 0 && nextLevel === nextLevelLenth - 1
+ && self._lastImageNumber !== nodes[i].imageID ) {
+ self._loadImage( imageList[self._lastImageNumber].src, i, self._lastImageNumber );
+ }
+ }
+
+ mat4.identity( nodes[i].mvMatrix );
+ mat4.translate( nodes[i].mvMatrix, [-2.0, -2.0, 1.0] );
+ mat4.rotate( nodes[i].mvMatrix, degreeToRadian( 19 ), [1, 0, 0] );
+
+ t = ( current + ( next - current ) * ( ( progress > 1 ) ? 1 : progress ) );
+
+ if ( progress >= self._ANIMATION_END ) {
+ nodes[i].level = nextLevel || displayLength;
+ t = path.levels[nodes[i].level];
+ }
+
+ if ( ( progress < self._ANIMATION_END )
+ && ( direction <= 0 && nodes[i].level < 1 ) ) {
+ nodes[i].drawable = false;
+ } else {
+ nodes[i].drawable = true;
+ }
+
+ if ( progress === self._ANIMATION_END && nodes[i].level === 1 ) {
+ self.element.trigger( "select", [imageList[nodes[i].imageID], nodes[i].imageID] );
+ }
+
+ position = path.getPosition( t );
+ angle = path.getAngle( t );
+
+ mat4.translate( nodes[i].mvMatrix, position );
+ mat4.rotate( nodes[i].mvMatrix, angle, [0, 1, 0] );
+ }
+
+ if ( imageListLength > itemCount && progress >= self._ANIMATION_END ) {
+ self._firstImageNumber = ( self._firstImageNumber - direction ) % imageListLength;
+ if ( self._firstImageNumber < 0 ) {
+ self._firstImageNumber = imageListLength - 1;
+ }
+
+ self._lastImageNumber = ( self._lastImageNumber - direction ) % imageListLength;
+ if ( self._lastImageNumber < 0 ) {
+ self._lastImageNumber = imageListLength - 1;
+ }
+ }
+ self._drawScene();
+ },
+
+ _drawScene: function () {
+ if ( !this._gl || !this._shaderProgram ) {
+ return;
+ }
+
+ var self = this,
+ gl = self._gl,
+ shaderProgram = self._shaderProgram,
+ nodes = self._nodes,
+ nodesLength = nodes.length,
+ i;
+
+ gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );
+
+ gl.bindBuffer( gl.ARRAY_BUFFER, self._positionBuffer );
+ gl.vertexAttribPointer( shaderProgram.vertexPositionAttr, self._positionBuffer.itemSize, gl.FLOAT, false, 0, 0 );
+
+ gl.bindBuffer( gl.ARRAY_BUFFER, self._textureCoordBuffer );
+ gl.vertexAttribPointer( shaderProgram.textureCoordAttr, self._textureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0 );
+
+ gl.bindBuffer( gl.ARRAY_BUFFER, self._normalVectorBuffer );
+ gl.vertexAttribPointer( shaderProgram.vertexNormalAttr, self._normalVectorBuffer.itemSize, gl.FLOAT, false, 0, 0 );
+
+ for ( i = 0; i < nodesLength; i += 1 ) {
+ if ( nodes[i].drawable ) {
+ self._drawElement( self._pMatrix, nodes[i] );
+ }
+ }
+ },
+
+ _drawElement: function ( perspectiveMatrix, targetNode ) {
+ var self = this,
+ gl = self._gl,
+ vec3 = glMatrix.vec3,
+ mat3 = glMatrix.mat3,
+ mat4 = glMatrix.mat4,
+ shaderProgram = self._shaderProgram,
+ moveMatrix = targetNode.mvMatrix,
+ texture = targetNode.texture,
+ meshIndexBuffer = targetNode.textureBuffer,
+ meshIndexBufferItemSize = targetNode.textureBufferItemSize,
+ lightPositions = self._lightsPositionStack,
+ LightDir,
+ normalMatrix;
+
+ if ( !moveMatrix ) {
+ return;
+ }
+
+ gl.activeTexture( gl.TEXTURE0 );
+ if ( texture && texture.loaded ) {
+ gl.bindTexture( gl.TEXTURE_2D, texture );
+ }
+ gl.uniform1i( shaderProgram.sampleUniform, 0 );
+
+ LightDir = vec3.create();
+ vec3.normalize( lightPositions[0], LightDir );
+ vec3.scale( LightDir, -8 );
+ gl.uniform3fv( shaderProgram.lightDirU_first, LightDir );
+
+ vec3.normalize( lightPositions[1], LightDir );
+ vec3.scale( LightDir, -1 );
+ gl.uniform3fv( shaderProgram.lightDirU_second, LightDir );
+ gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, meshIndexBuffer );
+
+ gl.uniformMatrix4fv( shaderProgram.perspectiveMU, false, perspectiveMatrix );
+ gl.uniformMatrix4fv( shaderProgram.transformMU, false, moveMatrix );
+
+ normalMatrix = mat3.create();
+ mat4.toInverseMat3( moveMatrix, normalMatrix );
+ mat3.transpose( normalMatrix );
+ gl.uniformMatrix3fv( shaderProgram.normalMU, false, normalMatrix );
+
+ gl.drawElements( gl.TRIANGLES, meshIndexBufferItemSize, gl.UNSIGNED_SHORT, 0 );
+
+ // release buffer memory
+ gl.bindBuffer( gl.ARRAY_BUFFER, null );
+ gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, null );
+
+ // release texture memory
+ gl.bindTexture( gl.TEXTURE_2D, null );
+ },
+
+ // ----------------------------------------------------------
+ // Animation
+ // ----------------------------------------------------------
+ _animate: function ( easingType, duration, direction, repeatCount, startValue, _removeCount ) {
+ var self = this,
+ timeNow = $.now(),
+ progress,
+ removeCount = 0;
+
+ easingType = easingType || "linear";
+ startValue = startValue || 0;
+ _removeCount = _removeCount || 0;
+
+ if ( self._sumTime >= duration ) {
+ self._setPosition( self._ANIMATION_END, direction );
+ self._stop();
+ return;
+ }
+
+ if ( self._startTime === 0 ) {
+ self._startTime = timeNow;
+ } else {
+ self._sumTime = timeNow - self._startTime;
+ progress = $.easing[ easingType ]( self._sumTime / duration, self._sumTime, startValue, repeatCount + 1, duration );
+ removeCount = parseInt( Math.abs( progress ), 10 );
+
+ if ( _removeCount !== removeCount ) {
+ self._setPosition( self._ANIMATION_END, direction );
+ _removeCount = removeCount;
+
+ if ( ( repeatCount - _removeCount ) >= 0 ) {
+ self._animate( easingType, duration, direction, repeatCount, startValue, _removeCount );
+ } else {
+ self._stop();
+ }
+ return;
+ }
+
+ self._setPosition( progress - _removeCount, direction );
+ }
+
+ self._animationID = requestAnimationFrame( function () {
+ self._animate( easingType, duration, direction, repeatCount, startValue, _removeCount );
+ });
+ },
+
+ _run: function ( direction, repeatCount, startValue ) {
+ var self = this,
+ repeat = repeatCount || 0,
+ duration = self._DURATION_DEFAULT * ( repeat + 1 );
+
+ if ( !self._gl ) {
+ self._operationQueue.push( direction );
+ return;
+ }
+
+ if ( self._imageList.length <= 1 ) {
+ return;
+ }
+
+ startValue = startValue || 0;
+ duration = ( duration >= 0 ) ? duration : 0;
+
+ if ( self._animationID ) {
+ self._setPosition( self._ANIMATION_END, direction );
+ self._stop();
+ }
+
+ self._animate( "easeOutExpo", duration, direction, repeat, startValue );
+ },
+
+ _reset: function () {
+ if ( !this._canvas || !this._gl ) {
+ return;
+ }
+
+ this._final();
+ this._init();
+ this.refresh();
+ },
+
+ _stop: function () {
+ if ( this._animationID ) {
+ cancelAnimationFrame( this._animationID );
+ }
+ this._animationID = 0;
+
+ this._startTime = 0;
+ this._sumTime = 0;
+ },
+
+ next: function () {
+ this._run( this._DIRECTION_LEFT , 0 );
+ },
+
+ prev: function () {
+ this._run( this._DIRECTION_RIGHT, 0 );
+ },
+
+ refresh: function () {
+ var view = this.element,
+ canvas = view.find( "canvas.ui-gallery3d-canvas" );
+
+ if ( canvas.width() !== view.width() ) {
+ canvas.width( view.width() );
+ }
+
+ if ( !this._animationID ) {
+ this._setPosition( 0, 0 );
+ }
+ },
+
+ select: function ( index ) {
+ var nodes = this._nodes,
+ repeat,
+ i,
+ imageID,
+ object = null,
+ target = 0,
+ direction = 0;
+
+ if ( index && this._animationID ) {
+ this._stop();
+ }
+
+ for ( i in nodes ) {
+ if ( nodes[i].level === 1 ) {
+ object = this._imageList[ nodes[i].imageID ];
+ imageID = nodes[i].imageID;
+ break;
+ }
+ }
+
+ if ( !index ) {
+ return object;
+ }
+
+ if ( index < 0 && index >= this._imageList.length ) {
+ return;
+ }
+
+ target = index - imageID;
+ direction = ( target > 0 ) ? this._DIRECTION_LEFT
+ : ( ( target < 0 ) ? this._DIRECTION_RIGHT : 0 );
+ if ( direction ) {
+ this._run( direction, Math.abs( target ) - 1 );
+ }
+ },
+
+ add: function ( item, index ) {
+ if ( !item ) {
+ return;
+ }
+
+ if ( typeof item === "string" ) {
+ item = { "src" : item };
+ }
+
+ index = index || 0;
+ if ( typeof index !== "number" && index < 0
+ && index >= this._imageList.length ) {
+ return;
+ }
+
+ this._imageList.splice( index, 0, item );
+ if ( this._gl ) {
+ this._reset();
+ }
+ },
+
+ remove: function ( index ) {
+ index = index || 0;
+ if ( typeof index !== "number" && index < 0
+ && index >= this._imageList.length ) {
+ return;
+ }
+
+ this._imageList.splice( index, 1 );
+ if ( this._gl ) {
+ this._reset();
+ }
+ },
+
+ clearThumbnailCache: function () {
+ if ( !this._nodes || ( this._nodes.length <= 0 ) ) {
+ return;
+ }
+
+ var i, url;
+ for ( i = 0; i < this._imageList.length; i += 1 ) {
+ url = this._imageList[i].src;
+ $.imageloader.removeThumbnail( url );
+ }
+ },
+
+ empty: function () {
+ this._imageList = [];
+ this._reset();
+ },
+
+ length: function () {
+ return this._imageList.length;
+ }
+ });
+
+ $( document ).on( "pagecreate create", function ( e ) {
+ $( ":jqmData(role='gallery3d')" ).gallery3d();
+ }).on( "pagechange", function ( e ) {
+ $( e.target ).find( ".ui-gallery3d" ).gallery3d( "refresh" );
+ });
+
+ $( window ).on( "resize orientationchange", function ( e ) {
+ $( ".ui-page-active" ).find( ".ui-gallery3d" ).gallery3d( "refresh" );
+ });
+
+} ( jQuery, document, window ) );
+
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+} );
+//>>excludeEnd("jqmBuildExclude");
http://git-wip-us.apache.org/repos/asf/cordova-tizen/blob/4ebce38e/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.listdivider.js
----------------------------------------------------------------------
diff --git a/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.listdivider.js b/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.listdivider.js
new file mode 100644
index 0000000..1ad61cb
--- /dev/null
+++ b/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/widgets/jquery.mobile.tizen.listdivider.js
@@ -0,0 +1,91 @@
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+//>>description: Divider listitem in listview
+//>>label: List divider
+//>>group: Tizen:Widgets
+
+define( [
+ 'jquery',
+ "jqm/jquery.mobile.widget"
+ ], function ( jQuery ) {
+
+//>>excludeEnd("jqmBuildExclude");
+
+/* ***************************************************************************
+* style : normal, check
+* option :
+* - folded : decide to show divider press effect or not
+* - line : decide to draw divider line or not
+*/
+/**
+ @class ListDivider
+ The list divider widget is used as a list separator for grouping lists. List dividers can be used in Tizen as described in the jQueryMobile documentation for list dividers.<br/>
+ To add a list divider widget to the application, use the following code:
+
+ <li data-role="list-divider" data-style="check">
+ <form><input type="checkbox" name="c2line-check1" /></form></li>
+
+ The list divider can define callbacks for events as described in the jQueryMobile documentation for list events. <br/> You can use methods with the list divider as described in the jQueryMobile documentation for list methods.
+
+ @since tizen2.0
+*/
+/**
+ @property {String} data-style
+ Sets the style of the list divider. The style options are dialogue, check, expandable, and checkexpandable.
+*/
+
+(function ( $, undefined ) {
+ $.widget( "tizen.listdivider", $.mobile.widget, {
+ options: {
+ initSelector: ":jqmData(role='list-divider')",
+ folded : false,
+ listDividerLine : true
+ },
+
+ _create: function () {
+
+ var $listdivider = this.element,
+ openStatus = true,
+ expandSrc,
+ listDividerLine = true,
+ style = $listdivider.attr( "data-style" );
+
+ if ( $listdivider.data("line") === false ) {
+ this.options.listDividerLine = false;
+ }
+
+ if ( $listdivider.data("folded") === true ) {
+ this.options.folded = true;
+ }
+
+ if ( style == undefined || style === "normal" || style === "check" ) {
+ if ( this.options.folded ) {
+ $listdivider.buttonMarkup();
+ } else {
+ $listdivider.wrapInner("<span class='ui-btn-text'></span>");
+ }
+
+ if ( this.options.listDividerLine ) {
+ expandSrc = "<span class='ui-divider-normal-line'></span>";
+ if ( this.options.folded ) {
+ $( expandSrc ).appendTo( $listdivider.children( ".ui-btn-inner" ) );
+ } else {
+ $( expandSrc ).appendTo( $listdivider);
+ }
+ }
+ }
+
+ $listdivider.bind( "vclick", function ( event, ui ) {
+ /* need to implement expand/collapse divider */
+ });
+ }
+ });
+
+ //auto self-init widgets
+ $( document ).bind( "pagecreate create", function ( e ) {
+ $( $.tizen.listdivider.prototype.options.initSelector, e.target ).listdivider();
+ });
+}( jQuery ) );
+
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+} );
+//>>excludeEnd("jqmBuildExclude");