1 //>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
2 //>>description: Shows images one by one, and moves them by flicking
4 //>>group: Tizen:Widgets
6 define( [ ], function ( ) {
7 //>>excludeEnd("jqmBuildExclude");
9 /* ***************************************************************************
10 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 * DEALINGS IN THE SOFTWARE.
29 * ***************************************************************************
31 * Author: Minkyu Kang <mk7.kang@samsung.com>
39 * data-role: set to 'gallery'
40 * data-index: start index
41 * data-vertical-align: set to top or middle or bottom.
45 * add(file): add the image (parameter: url of iamge)
46 * remove(index): remove the image (parameter: index of image)
47 * refresh(index): refresh the widget, should be called after add or remove. (parameter: start index)
48 * empty: remove all of images from the gallery
49 * length: get length of images
50 * value(index): get or set current index of gallery (parameter: index of image)
58 * <div data-role="gallery" id="gallery" data-index="3" data-vertical-align="middle">
67 * $('#gallery-add').bind('vmouseup', function ( e ) {
68 * $('#gallery').gallery('add', '9.jpg');
69 * $('#gallery').gallery('add', '10.jpg');
70 * $('#gallery').gallery('refresh');
73 * $('#gallery-del').bind('vmouseup', function ( e ) {
74 * $('#gallery').gallery('remove');
81 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:
83 <div data-role="gallery" id="gallery" data-vertical-align="middle" data-index="3">
92 @property {Integer} data-index
93 Defines the index number of the first image in the gallery.
94 <br/>The default value is 0.
97 @property {String} data-vertical-align
98 Defines the image alignment. The alignment options are top, middle, and bottom.
99 <br/>The default value is top.
103 The add method is used to add an image to the gallery. The image_file attribute defines the image file URL.
105 <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
106 $("#gallery").gallery('add', [image_file]);
110 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.
112 <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
113 $("#gallery").gallery('remove', [image_index]);
117 The refresh method is used to refresh the gallery. This method must be called after adding images to the gallery.
119 <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
120 $("#gallery").gallery('refresh');
124 The empty method is used to remove all of images from the gallery.
126 <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
127 $("#gallery").gallery('empty');
131 The length method is used to get length of images.
133 <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
134 length = $("#gallery").gallery('length');
138 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.
140 <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
141 value = $("#gallery").gallery('value');
142 $("#gallery").gallery('value', [image_index]);
144 (function ( $, window, undefined ) {
145 $.widget( "tizen.gallery", $.mobile.widget, {
166 orientationEventFire: false,
168 _resize: function ( index ) {
169 var img = this.images[index],
170 width = this.images[index].width(),
171 height = this.images[index].height(),
174 img_max_width = this.max_width - margin,
175 img_max_height = this.max_height - margin;
177 ratio = height / width;
179 if ( width > img_max_width ) {
180 img.width( img_max_width );
181 img.height( img_max_width * ratio );
184 height = img.height();
186 if ( height > img_max_height ) {
187 img.height( img_max_height );
188 img.width( img_max_height / ratio );
192 _align: function ( index, obj ) {
193 var img = this.images[index],
203 if ( this.align_type == "middle" ) {
204 img_top = ( this.max_height - img.height() ) / 2;
205 } else if ( this.align_type == "bottom" ) {
206 img_top = this.max_height - img.height();
211 obj.css( 'top', img_top + 'px' );
214 _attach: function ( index, obj ) {
216 processing = function () {
217 self._resize( index );
218 self._align( index, obj );
221 loading = function () {
222 if ( self.images[index] === undefined ) {
226 if ( !self.images[index].height() ) {
227 setTimeout( loading, 10 );
243 if ( !this.images.length ) {
246 if ( index >= this.images.length ) {
250 obj.css( "display", "block" );
251 obj.css( "visibility", "hidden" );
252 obj.append( this.images[index] );
256 _detach: function ( index, obj ) {
266 if ( index >= this.images.length ) {
270 obj.css( "display", "none" );
271 this.images[index].removeAttr("style");
272 this.images[index].detach();
275 _detach_all: function () {
278 for ( i = 0; i < this.images.length; i++ ) {
279 this.images[i].detach();
283 _drag: function ( _x ) {
287 if ( !this.dragging ) {
291 if ( this.options.flicking === false ) {
292 delta = this.org_x - _x;
295 if ( delta < 0 && !this.prev_img.length ) {
299 if ( delta > 0 && !this.next_img.length ) {
304 coord_x = _x - this.org_x;
306 this._moveLeft( this.cur_img , coord_x + 'px' );
307 if ( this.next_img.length ) {
308 this._moveLeft( this.next_img , coord_x + this.window_width + 'px' );
310 if ( this.prev_img.length ) {
311 this._moveLeft( this.prev_img , coord_x - this.window_width + 'px' );
315 _move: function ( _x ) {
316 var delta = this.org_x - _x,
327 flip = delta < ( this.max_width * 0.45 ) ? 0 : 1;
329 flip = -delta < ( this.max_width * 0.45 ) ? 0 : 1;
333 drag_time = Date.now() - this.org_time;
335 if ( Math.abs( delta ) / drag_time > 1 ) {
341 if ( delta > 0 && this.next_img.length ) {
343 this._detach( this.index - 1, this.prev_img );
345 this.prev_img = this.cur_img;
346 this.cur_img = this.next_img;
347 this.next_img = this.next_img.next();
351 if ( this.next_img.length ) {
352 this._moveLeft( this.next_img , this.window_width + 'px' );
353 this._attach( this.index + 1, this.next_img );
358 } else if ( delta < 0 && this.prev_img.length ) {
360 this._detach( this.index + 1, this.next_img );
362 this.next_img = this.cur_img;
363 this.cur_img = this.prev_img;
364 this.prev_img = this.prev_img.prev();
368 if ( this.prev_img.length ) {
369 this._moveLeft( this.prev_img , -this.window_width + 'px' );
370 this._attach( this.index - 1, this.prev_img );
377 sec = this.options.duration;
382 setTimeout( function () {
386 this._moveLeft( this.cur_img, 0 + 'px', sec );
387 if ( this.next_img.length ) {
388 this._moveLeft( this.next_img, this.window_width + 'px', sec );
390 if ( this.prev_img.length ) {
391 this._moveLeft( this.prev_img, -this.window_width + 'px', sec );
395 _add_event: function () {
399 this.container.bind( 'vmousemove', function ( e ) {
405 if ( !self.dragging ) {
409 self._drag( e.pageX );
412 this.container.bind( 'vmousedown', function ( e ) {
419 self.dragging = true;
421 self.org_x = e.pageX;
423 self.org_time = Date.now();
426 this.container.bind( 'vmouseup', function ( e ) {
431 self.dragging = false;
433 self._move( e.pageX );
436 this.container.bind( 'vmouseout', function ( e ) {
440 if ( !self.dragging ) {
444 if ( ( e.pageX < 20 ) ||
445 ( e.pageX > ( self.max_width - 20 ) ) ) {
446 self._move( e.pageX );
447 self.dragging = false;
452 _del_event: function () {
453 this.container.unbind( 'vmousemove' );
454 this.container.unbind( 'vmousedown' );
455 this.container.unbind( 'vmouseup' );
456 this.container.unbind( 'vmouseout' );
458 _setTranslateposition : function ( $ele, value ) {
463 if ( $.support.cssTransform3d ) {
464 translate = "translate3d(" + value + ", 0px, 0px)";
466 translate = "translate(" + value + ", 0px)";
468 cssArray = {"-moz-transform": translate,
469 "-webkit-transform": translate,
470 "-ms-transform": translate,
471 "-o-transform": translate,
472 "transform": translate};
477 _hidePrevNext : function() {
481 self.next_img.css( "visibility", "hidden" );
483 self.prev_img.css( "visibility", "hidden" );
486 _hideCur : function() {
489 self.cur_img.css( "visibility", "hidden" );
491 _moveLeft : function ( $ele , value , duration ) {
497 if ( $.support.cssTransform3d ) {
498 translate = "translate3d(" + value + ", 0px, 0px)";
500 translate = "translate(" + value + ", 0px)";
502 if( duration !== undefined ) {
503 transition = "-webkit-transform " + (duration / 1000)+ "s ease";
505 cssArray = {"-moz-transform": translate,
506 "-webkit-transform": translate,
507 "-ms-transform": translate,
508 "-o-transform": translate,
509 "transform": translate};
510 if( transition !== "" ) {
511 cssArray["-webkit-transition"] = transition ;
513 $ele.one( 'webkitTransitionEnd', self._hidePrevNext );
515 $ele.one( 'webkitTransitionEnd', self._hideCur );
517 if( value == "0px" ) {
518 $ele.css( "visibility", "visible" );
526 this.window_width = $( window ).width();
527 this.max_width = this._get_width();
528 this.max_height = this._get_height();
529 this.container.css( 'height', this.max_height );
531 this.cur_img = $( 'div' ).find( '.ui-gallery-bg:eq(' + this.index + ')' );
532 this.prev_img = this.cur_img.prev();
533 this.next_img = this.cur_img.next();
535 this._attach( this.index - 1, this.prev_img );
536 this._attach( this.index, this.cur_img );
537 this._attach( this.index + 1, this.next_img );
539 this.cur_img.css( 'visibility', 'visible' );
540 if ( this.prev_img.length ) {
541 this._setTranslateposition( this.prev_img, -this.window_width + 'px');
544 this._moveLeft( this.cur_img, '0px');
545 if ( this.next_img.length ) {
546 this._setTranslateposition( this.next_img, this.window_width + 'px' );
551 if ( !this.images.length ) {
560 this._detach( this.index - 1, this.prev_img );
561 this._detach( this.index, this.cur_img );
562 this._detach( this.index + 1, this.next_img );
570 _get_width: function () {
571 return $( this.element ).width();
574 _get_height: function () {
575 var $page = $( this.element ).parentsUntil( 'ui-page' ),
576 $content = $page.children( '.ui-content' ),
577 header_h = $page.children( '.ui-header' ).outerHeight() || 0,
578 footer_h = $page.children( '.ui-footer' ).outerHeight() || 0,
579 padding = parseFloat( $content.css( 'padding-top' ) )
580 + parseFloat( $content.css( 'padding-bottom' ) ),
581 content_h = $( window ).height() - header_h - footer_h - padding;
586 _create: function () {
592 $( this.element ).wrapInner( '<div class="ui-gallery"></div>' );
593 $( this.element ).find( 'img' ).wrap( '<div class="ui-gallery-bg"></div>' );
595 this.container = $( this.element ).find('.ui-gallery');
597 temp_img = $( 'div' ).find( '.ui-gallery-bg:first' );
599 while ( temp_img.length ) {
600 this.images[i] = temp_img.find( 'img' );
601 temp_img = temp_img.next();
607 index = parseInt( $( this.element ).jqmData( 'index' ), 10 );
614 if ( index >= this.images.length ) {
615 index = this.images.length - 1;
620 this.align_type = $( this.element ).jqmData( 'vertical-align' );
627 orientationchange: $.proxy( this, "_orientationHandler" ),
628 resize: $.proxy( this, "_resizeHandler" )
634 $.each( this._globalHandlers, function( idx, value ) {
635 value.src.bind( value.handler );
639 _update: function () {
644 while ( this.images_hold.length ) {
645 image_file = this.images_hold.shift();
647 bg_html = $( '<div class="ui-gallery-bg"></div>' );
648 temp_img = $( '<img src="' + image_file + '"></div>' );
650 bg_html.append( temp_img );
651 this.container.append( bg_html );
652 this.images.push( temp_img );
657 _resizeHandler: function() {
659 if( self.orientationEventFire ) {
661 self.orientationEventFire = false;
664 _orientationHandler: function() {
667 self.orientationEventFire = true;
669 refresh: function ( start_index ) {
674 if ( start_index === undefined ) {
675 start_index = this.index;
677 if ( start_index < 0 ) {
680 if ( start_index >= this.images.length ) {
681 start_index = this.images.length - 1;
684 this.index = start_index;
691 add: function ( file ) {
692 this.images_hold.push( file );
695 remove: function ( index ) {
698 if ( index === undefined ) {
702 if ( index < 0 || index >= this.images.length ) {
706 if ( index == this.index ) {
707 temp_img = this.cur_img;
709 if ( this.index == 0 ) {
711 } else if ( this.index == this.images.length - 1 ) {
715 if ( this.direction < 0 ) {
716 this.cur_img = this.prev_img;
717 this.prev_img = this.prev_img.prev();
718 if ( this.prev_img.length ) {
719 this._moveLeft( this.prev_img, -this.window_width + 'px' );
720 this._attach( index - 2, this.prev_img );
724 this.cur_img = this.next_img;
725 this.next_img = this.next_img.next();
726 if ( this.next_img.length ) {
727 this._moveLeft( this.next_img, this.window_width + 'px' );
728 this._attach( index + 2, this.next_img );
731 this._moveLeft( this.cur_img, '0px', this.options.duration );
733 } else if ( index == this.index - 1 ) {
734 temp_img = this.prev_img;
735 this.prev_img = this.prev_img.prev();
736 if ( this.prev_img.length ) {
737 this._moveLeft( this.prev_img, -this.window_width + 'px' );
738 this._attach( index - 1, this.prev_img );
742 } else if ( index == this.index + 1 ) {
743 temp_img = this.next_img;
744 this.next_img = this.next_img.next();
745 if ( this.next_img.length ) {
746 this._moveLeft( this.next_img, this.window_width + 'px' );
747 this._attach( index + 1, this.next_img );
751 temp_img = $( 'div' ).find( '.ui-gallery-bg:eq(' + index + ')' );
754 this.images.splice( index, 1 );
759 this.images.splice( 0, this.images.length );
760 this.container.find('.ui-gallery-bg').detach();
763 length: function () {
764 return this.images.length;
767 value: function ( index ) {
768 if ( index === undefined ) {
772 this.refresh( index );
775 destory: function() {
776 $( window ).unbind( 'resize', this._resizeHandler );
777 $( window ).unbind( 'orientationchange' , this._orientationHandler );
780 }); /* End of widget */
782 // auto self-init widgets
783 $( document ).bind( "pagecreate create", function ( e ) {
784 $( e.target ).find( ":jqmData(role='gallery')" ).gallery();
787 $( document ).bind( "pageshow", function ( e ) {
788 $( e.target ).find( ":jqmData(role='gallery')" ).gallery( 'show' );
791 $( document ).bind( "pagebeforehide", function ( e ) {
792 $( e.target ).find( ":jqmData(role='gallery')" ).gallery( 'hide' );
797 //>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
799 //>>excludeEnd("jqmBuildExclude");