gallery: show the widget after pageshow
[platform/framework/web/web-ui-fw.git] / src / widgets / gallery / js / jquery.mobile.tizen.gallery.js
1 /* ***************************************************************************
2  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  * ***************************************************************************
22  *
23  *      Author: Minkyu Kang <mk7.kang@samsung.com>
24  */
25
26 /*
27  * Gallery widget
28  *
29  * HTML Attributes
30  *
31  *  data-role: set to 'gallery'
32  *  data-index: start index
33  *  data-vertical-align: set to top or middle or bottom.
34  *
35  * APIs
36  *
37  *  add(file): add the image (parameter: url of iamge)
38  *  remove(index): remove the image (parameter: index of image)
39  *  refresh(index): refresh the widget, should be called after add or remove. (parameter: start index)
40  *  empty: remove all of images from the gallery
41  *  length: get length of images
42  *  value(index): get or set current index of gallery (parameter: index of image)
43  *
44  * Events
45  *
46  *  N/A
47  *
48  * Example
49  *
50  * <div data-role="gallery" id="gallery" data-index="3" data-vertical-align="middle">
51  *      <img src="01.jpg">
52  *      <img src="02.jpg">
53  *      <img src="03.jpg">
54  *      <img src="04.jpg">
55  *      <img src="05.jpg">
56  * </div>
57  *
58  *
59  * $('#gallery-add').bind('vmouseup', function ( e ) {
60  *      $('#gallery').gallery('add', '9.jpg');
61  *      $('#gallery').gallery('add', '10.jpg');
62  *      $('#gallery').gallery('refresh');
63  * });
64  *
65  * $('#gallery-del').bind('vmouseup', function ( e ) {
66  *      $('#gallery').gallery('remove');
67  * });
68  *
69  */
70
71  /**
72         @class Gallery
73         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:
74
75                 <div data-role="gallery" id="gallery" data-vertical-align="middle" data-index="3">
76                         <img src="01.jpg">
77                         <img src="02.jpg">
78                         <img src="03.jpg">
79                         <img src="04.jpg">
80                         <img src="05.jpg">
81                 </div>
82 */
83 /**
84         @property {Integer} data-index
85         Defines the index number of the first image in the gallery.
86         <br/>The default value is 0.
87 */
88 /**
89         @property {String} data-vertical-align
90         Defines the image alignment. The alignment options are top, middle, and bottom.
91         <br/>The default value is top.
92 */
93 /**
94         @method add
95         The add method is used to add an image to the gallery. The image_file attribute defines the image file URL.
96
97                 <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
98                 $("#gallery").gallery('add', [image_file]);
99 */
100 /**
101         @method remove
102         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.
103
104                 <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
105                 $("#gallery").gallery('remove', [image_index]);
106 */
107 /**
108         @method refresh
109         The refresh method is used to refresh the gallery. This method must be called after adding images to the gallery.
110
111                 <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
112                 $("#gallery").gallery('refresh');
113 */
114 /**
115         @method empty
116         The empty method is used to remove all of images from the gallery.
117
118                 <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
119                 $("#gallery").gallery('empty');
120 */
121 /**
122         @method length
123         The length method is used to get length of images.
124
125                 <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
126                 length = $("#gallery").gallery('length');
127 */
128 /**
129         @method value
130         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.
131
132                 <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
133                 value = $("#gallery").gallery('value');
134                 $("#gallery").gallery('value', [image_index]);
135 */
136 (function ( $, window, undefined ) {
137         $.widget( "tizen.gallery", $.mobile.widget, {
138                 options: {
139                         flicking: false,
140                         duration: 500
141                 },
142
143                 dragging: false,
144                 moving: false,
145                 max_width: 0,
146                 max_height: 0,
147                 org_x: 0,
148                 org_time: null,
149                 cur_img: null,
150                 prev_img: null,
151                 next_img: null,
152                 images: [],
153                 images_hold: [],
154                 index: 0,
155                 align_type: null,
156                 direction: 1,
157                 container: null,
158                 loader: [],
159
160                 _resize: function ( index ) {
161                         var img = this.images[index],
162                                 width = this.images[index].width(),
163                                 height = this.images[index].height(),
164                                 margin = 0,
165                                 ratio,
166                                 img_max_width = this.max_width - margin,
167                                 img_max_height = this.max_height - margin;
168
169                         ratio = height / width;
170
171                         if ( width > img_max_width ) {
172                                 img.width( img_max_width );
173                                 img.height( img_max_width * ratio );
174                         }
175
176                         height = img.height();
177
178                         if ( height > img_max_height ) {
179                                 img.height( img_max_height );
180                                 img.width( img_max_height / ratio );
181                         }
182                 },
183
184                 _align: function ( index, obj ) {
185                         var img = this.images[index],
186                                 img_top = 0;
187
188                         if ( !obj ) {
189                                 return;
190                         }
191                         if ( !obj.length ) {
192                                 return;
193                         }
194
195                         if ( this.align_type == "middle" ) {
196                                 img_top = ( this.max_height - img.height() ) / 2;
197                         } else if ( this.align_type == "bottom" ) {
198                                 img_top = this.max_height - img.height();
199                         } else {
200                                 img_top = 0;
201                         }
202
203                         obj.css( 'top', img_top + 'px' );
204                 },
205
206                 _attach: function ( index, obj ) {
207                         var self = this,
208                                 processing = function () {
209                                         self._resize( index );
210                                         self._align( index, obj );
211                                 };
212
213                         if ( !obj ) {
214                                 return;
215                         }
216                         if ( !obj.length ) {
217                                 return;
218                         }
219                         if ( index < 0 ) {
220                                 return;
221                         }
222                         if ( index >= this.images.length ) {
223                                 return;
224                         }
225
226                         obj.css( "display", "block" );
227                         obj.append( this.images[index] );
228
229                         if ( this.images[index].height() ) {
230                                 processing();
231                         } else {
232                                 this.loader[index] = setInterval( function () {
233                                         if ( !self.images[index].height() ) {
234                                                 return;
235                                         }
236
237                                         processing();
238                                         clearInterval( self.loader[index] );
239                                 }, 10);
240                         }
241                 },
242
243                 _detach: function ( index, obj ) {
244                         if ( !obj ) {
245                                 return;
246                         }
247                         if ( !obj.length ) {
248                                 return;
249                         }
250                         if ( index < 0 ) {
251                                 return;
252                         }
253                         if ( index >= this.images.length ) {
254                                 return;
255                         }
256
257                         obj.css( "display", "none" );
258                         this.images[index].removeAttr("style");
259                         this.images[index].detach();
260
261                         clearInterval( this.loader[index] );
262                 },
263
264                 _detach_all: function () {
265                         var i;
266
267                         for ( i = 0; i < this.images.length; i++ ) {
268                                 this.images[i].detach();
269                         }
270                 },
271
272                 _drag: function ( _x ) {
273                         var delta,
274                                 coord_x;
275
276                         if ( !this.dragging ) {
277                                 return;
278                         }
279
280                         if ( this.options.flicking === false ) {
281                                 delta = this.org_x - _x;
282
283                                 // first image
284                                 if ( delta < 0 && !this.prev_img.length ) {
285                                         return;
286                                 }
287                                 // last image
288                                 if ( delta > 0 && !this.next_img.length ) {
289                                         return;
290                                 }
291                         }
292
293                         coord_x = _x - this.org_x;
294
295                         this.cur_img.css( 'left', coord_x + 'px' );
296                         if ( this.next_img.length ) {
297                                 this.next_img.css( 'left', coord_x + this.window_width + 'px' );
298                         }
299                         if ( this.prev_img.length ) {
300                                 this.prev_img.css( 'left', coord_x - this.window_width + 'px' );
301                         }
302                 },
303
304                 _move: function ( _x ) {
305                         var delta = this.org_x - _x,
306                                 flip = 0,
307                                 drag_time,
308                                 sec,
309                                 self;
310
311                         if ( delta == 0 ) {
312                                 return;
313                         }
314
315                         if ( delta > 0 ) {
316                                 flip = delta < ( this.max_width * 0.45 ) ? 0 : 1;
317                         } else {
318                                 flip = -delta < ( this.max_width * 0.45 ) ? 0 : 1;
319                         }
320
321                         if ( !flip ) {
322                                 drag_time = Date.now() - this.org_time;
323
324                                 if ( Math.abs( delta ) / drag_time > 1 ) {
325                                         flip = 1;
326                                 }
327                         }
328
329                         if ( flip ) {
330                                 if ( delta > 0 && this.next_img.length ) {
331                                         /* next */
332                                         this._detach( this.index - 1, this.prev_img );
333
334                                         this.prev_img = this.cur_img;
335                                         this.cur_img = this.next_img;
336                                         this.next_img = this.next_img.next();
337
338                                         this.index++;
339
340                                         if ( this.next_img.length ) {
341                                                 this.next_img.css( 'left', this.window_width + 'px' );
342                                                 this._attach( this.index + 1, this.next_img );
343                                         }
344
345                                         this.direction = 1;
346
347                                 } else if ( delta < 0 && this.prev_img.length ) {
348                                         /* prev */
349                                         this._detach( this.index + 1, this.next_img );
350
351                                         this.next_img = this.cur_img;
352                                         this.cur_img = this.prev_img;
353                                         this.prev_img = this.prev_img.prev();
354
355                                         this.index--;
356
357                                         if ( this.prev_img.length ) {
358                                                 this.prev_img.css( 'left', -this.window_width + 'px' );
359                                                 this._attach( this.index - 1, this.prev_img );
360                                         }
361
362                                         this.direction = -1;
363                                 }
364                         }
365
366                         sec = this.options.duration;
367                         self = this;
368
369                         this.moving = true;
370
371                         setTimeout( function () {
372                                 self.moving = false;
373                         }, sec - 50 );
374
375                         this.cur_img.animate( { left: 0 }, sec );
376                         if ( this.next_img.length ) {
377                                 this.next_img.animate( { left: this.window_width }, sec );
378                         }
379                         if ( this.prev_img.length ) {
380                                 this.prev_img.animate( { left: -this.window_width }, sec );
381                         }
382                 },
383
384                 _add_event: function () {
385                         var self = this,
386                                 date;
387
388                         this.container.bind( 'vmousemove', function ( e ) {
389                                 e.preventDefault();
390
391                                 if ( self.moving ) {
392                                         return;
393                                 }
394                                 if ( !self.dragging ) {
395                                         return;
396                                 }
397
398                                 self._drag( e.pageX );
399                         } );
400
401                         this.container.bind( 'vmousedown', function ( e ) {
402                                 e.preventDefault();
403
404                                 if ( self.moving ) {
405                                         return;
406                                 }
407
408                                 self.dragging = true;
409
410                                 self.org_x = e.pageX;
411
412                                 self.org_time = Date.now();
413                         } );
414
415                         this.container.bind( 'vmouseup', function ( e ) {
416                                 if ( self.moving ) {
417                                         return;
418                                 }
419
420                                 self.dragging = false;
421
422                                 self._move( e.pageX );
423                         } );
424
425                         this.container.bind( 'vmouseout', function ( e ) {
426                                 if ( self.moving ) {
427                                         return;
428                                 }
429                                 if ( !self.dragging ) {
430                                         return;
431                                 }
432
433                                 if ( ( e.pageX < 20 ) ||
434                                                 ( e.pageX > ( self.max_width - 20 ) ) ) {
435                                         self._move( e.pageX );
436                                         self.dragging = false;
437                                 }
438                         } );
439                 },
440
441                 _del_event: function () {
442                         this.container.unbind( 'vmousemove' );
443                         this.container.unbind( 'vmousedown' );
444                         this.container.unbind( 'vmouseup' );
445                         this.container.unbind( 'vmouseout' );
446                 },
447
448                 _show: function () {
449                         /* resizing */
450                         this.window_width = $( window ).width();
451                         this.max_width = this._get_width();
452                         this.max_height = this._get_height();
453                         this.container.css( 'height', this.max_height );
454
455                         this.cur_img = $( 'div' ).find( '.ui-gallery-bg:eq(' + this.index + ')' );
456                         this.prev_img = this.cur_img.prev();
457                         this.next_img = this.cur_img.next();
458
459                         this._attach( this.index - 1, this.prev_img );
460                         this._attach( this.index, this.cur_img );
461                         this._attach( this.index + 1, this.next_img );
462
463                         if ( this.prev_img.length ) {
464                                 this.prev_img.css( 'left', -this.window_width + 'px' );
465                         }
466
467                         this.cur_img.css( 'left', '0px' );
468
469                         if ( this.next_img.length ) {
470                                 this.next_img.css( 'left', this.window_width + 'px' );
471                         }
472                 },
473
474                 show: function () {
475                         this._show();
476                         this._add_event();
477                 },
478
479                 _hide: function () {
480                         this._detach( this.index - 1, this.prev_img );
481                         this._detach( this.index, this.cur_img );
482                         this._detach( this.index + 1, this.next_img );
483                 },
484
485                 hide: function () {
486                         this._hide();
487                         this._del_event();
488                 },
489
490                 _get_width: function () {
491                         return $( this.element ).width();
492                 },
493
494                 _get_height: function () {
495                         var $page = $( this.element ).parentsUntil( 'ui-page' ),
496                                 $content = $page.children( '.ui-content' ),
497                                 header_h = $page.children( '.ui-header' ).outerHeight() || 0,
498                                 footer_h = $page.children( '.ui-footer' ).outerHeight() || 0,
499                                 padding = parseFloat( $content.css( 'padding-top' ) )
500                                         + parseFloat( $content.css( 'padding-bottom' ) ),
501                                 content_h = $( window ).height() - header_h - footer_h - padding;
502
503                         return content_h;
504                 },
505
506                 _create: function () {
507                         var temp_img,
508                                 self = this,
509                                 index,
510                                 i = 0;
511
512                         $( this.element ).wrapInner( '<div class="ui-gallery"></div>' );
513                         $( this.element ).find( 'img' ).wrap( '<div class="ui-gallery-bg"></div>' );
514
515                         this.container = $( this.element ).find('.ui-gallery');
516
517                         temp_img = $( 'div' ).find( '.ui-gallery-bg:first' );
518
519                         while ( temp_img.length ) {
520                                 this.images[i] = temp_img.find( 'img' );
521                                 temp_img = temp_img.next();
522                                 i++;
523                         }
524
525                         this._detach_all();
526
527                         index = parseInt( $( this.element ).jqmData( 'index' ), 10 );
528                         if ( !index ) {
529                                 index = 0;
530                         }
531                         if ( index < 0 ) {
532                                 index = 0;
533                         }
534                         if ( index >= this.images.length ) {
535                                 index = this.images.length - 1;
536                         }
537
538                         this.index = index;
539
540                         this.align_type = $( this.element ).jqmData( 'vertical-align' );
541
542                         $( window ).bind( 'resize', function () {
543                                 self.refresh();
544                         });
545                 },
546
547                 _update: function () {
548                         var image_file,
549                                 bg_html,
550                                 temp_img;
551
552                         while ( this.images_hold.length ) {
553                                 image_file = this.images_hold.shift();
554
555                                 bg_html = $( '<div class="ui-gallery-bg"></div>' );
556                                 temp_img = $( '<img src="' + image_file + '"></div>' );
557
558                                 bg_html.append( temp_img );
559                                 this.container.append( bg_html );
560                                 this.images.push( temp_img );
561                         }
562
563                         this._detach_all();
564                 },
565
566                 refresh: function ( start_index ) {
567                         this._update();
568
569                         this._hide();
570
571                         if ( start_index === undefined ) {
572                                 start_index = this.index;
573                         }
574                         if ( start_index < 0 ) {
575                                 start_index = 0;
576                         }
577                         if ( start_index >= this.images.length ) {
578                                 start_index = this.images.length - 1;
579                         }
580
581                         this.index = start_index;
582
583                         this._show();
584
585                         return this.index;
586                 },
587
588                 add: function ( file ) {
589                         this.images_hold.push( file );
590                 },
591
592                 remove: function ( index ) {
593                         var temp_img;
594
595                         if ( index === undefined ) {
596                                 index = this.index;
597                         }
598
599                         if ( index < 0 || index >= this.images.length ) {
600                                 return;
601                         }
602
603                         if ( index == this.index ) {
604                                 temp_img = this.cur_img;
605
606                                 if ( this.index == 0 ) {
607                                         this.direction = 1;
608                                 } else if ( this.index == this.images.length - 1 ) {
609                                         this.direction = -1;
610                                 }
611
612                                 if ( this.direction < 0 ) {
613                                         this.cur_img = this.prev_img;
614                                         this.prev_img = this.prev_img.prev();
615                                         if ( this.prev_img.length ) {
616                                                 this.prev_img.css( 'left', -this.window_width );
617                                                 this._attach( index - 2, this.prev_img );
618                                         }
619                                         this.index--;
620                                 } else {
621                                         this.cur_img = this.next_img;
622                                         this.next_img = this.next_img.next();
623                                         if ( this.next_img.length ) {
624                                                 this.next_img.css( 'left', this.window_width );
625                                                 this._attach( index + 2, this.next_img );
626                                         }
627                                 }
628
629                                 this.cur_img.animate( { left: 0 }, this.options.duration );
630
631                         } else if ( index == this.index - 1 ) {
632                                 temp_img = this.prev_img;
633                                 this.prev_img = this.prev_img.prev();
634                                 if ( this.prev_img.length ) {
635                                         this.prev_img.css( 'left', -this.window_width );
636                                         this._attach( index - 1, this.prev_img );
637                                 }
638                                 this.index--;
639
640                         } else if ( index == this.index + 1 ) {
641                                 temp_img = this.next_img;
642                                 this.next_img = this.next_img.next();
643                                 if ( this.next_img.length ) {
644                                         this.next_img.css( 'left', this.window_width );
645                                         this._attach( index + 1, this.next_img );
646                                 }
647
648                         } else {
649                                 temp_img = $( 'div' ).find( '.ui-gallery-bg:eq(' + index + ')' );
650                         }
651
652                         this.images.splice( index, 1 );
653                         temp_img.detach();
654                 },
655
656                 empty: function () {
657                         this.images.splice( 0, this.images.length );
658                         this.container.find('.ui-gallery-bg').detach();
659                 },
660
661                 length: function () {
662                         return this.images.length;
663                 },
664
665                 value: function ( index ) {
666                         if ( index === undefined ) {
667                                 return this.index;
668                         }
669
670                         this.refresh( index );
671                 }
672         }); /* End of widget */
673
674         // auto self-init widgets
675         $( document ).bind( "pagecreate", function ( e ) {
676                 $( e.target ).find( ":jqmData(role='gallery')" ).gallery();
677         });
678
679         $( document ).bind( "pageshow", function ( e ) {
680                 $( e.target ).find( ":jqmData(role='gallery')" ).gallery( 'show' );
681         });
682
683         $( document ).bind( "pagebeforehide", function ( e ) {
684                 $( e.target ).find( ":jqmData(role='gallery')" ).gallery( 'hide' );
685         } );
686
687 }( jQuery, this ) );