upload tizen1.0 source
[framework/web/web-ui-fw.git] / src / widgets / imageslider / js / jquery.mobile.tizen.imageslider.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  * Notification widget
28  *
29  * HTML Attributes
30  *
31  *  data-role: set to 'imageslider'
32  *  data-start-index: start index
33  *  data-vertical-align: set to top or middle or bottom.
34  *
35  * APIs
36  *
37  *  add(image_file): add the image (parameter: url of iamge)
38  *  del(image_index): delete the image (parameter: index of image)
39  *  refresh(): refresh the widget, should be called after add or del.
40  *
41  * Events
42  *
43  *  N/A
44  *
45  * Example
46  *
47  * <div data-role="imageslider" id="imageslider" data-start-index="3" data-vertical-align="middle">
48  *      <img src="01.jpg">
49  *      <img src="02.jpg">
50  *      <img src="03.jpg">
51  *      <img src="04.jpg">
52  *      <img src="05.jpg">
53  * </div>
54  *
55  *
56  * $('#imageslider-add').bind('vmouseup', function ( e ) {
57  *      $('#imageslider').imageslider('add', '9.jpg');
58  *      $('#imageslider').imageslider('add', '10.jpg');
59  *      $('#imageslider').imageslider('refresh');
60  * });
61  *
62  * $('#imageslider-del').bind('vmouseup', function ( e ) {
63  *      $('#imageslider').imageslider('del');
64  * });
65  *
66  */
67
68 (function ( $, window, undefined ) {
69         $.widget( "tizen.imageslider", $.mobile.widget, {
70                 options: {
71                         photoFlicking: false
72                 },
73
74                 dragging: false,
75                 moving: false,
76                 max_width: 0,
77                 max_height: 0,
78                 org_x: 0,
79                 org_time: null,
80                 cur_img: null,
81                 prev_img: null,
82                 next_img: null,
83                 images: [],
84                 images_hold: [],
85                 index: 0,
86                 align_type: null,
87                 direction: 1,
88                 container: null,
89                 interval: null,
90
91                 _resize: function ( obj ) {
92                         var width,
93                                 height,
94                                 margin = 40,
95                                 ratio,
96                                 img_max_width = this.max_width - margin,
97                                 img_max_height = this.max_height - margin;
98
99                         height = obj.height();
100                         width = obj.width();
101
102                         ratio = height / width;
103
104                         if ( width > img_max_width ) {
105                                 obj.width( img_max_width );
106                                 obj.height( img_max_width * ratio );
107                         }
108
109                         height = obj.height();
110
111                         if ( height > img_max_height ) {
112                                 obj.height( img_max_height );
113                                 obj.width( img_max_height / ratio );
114                         }
115                 },
116
117                 _align: function ( obj, img ) {
118                         var img_top = 0;
119
120                         if ( !obj.length ) {
121                                 return;
122                         }
123
124                         if ( this.align_type == "middle" ) {
125                                 img_top = ( this.max_height - img.height() ) / 2;
126                         } else if ( this.align_type == "bottom" ) {
127                                 img_top = this.max_height - img.height();
128                         } else {
129                                 img_top = 0;
130                         }
131
132                         obj.css( 'top', img_top + 'px' );
133                 },
134
135                 _detach: function ( image_index, obj ) {
136                         if ( !obj.length ) {
137                                 return;
138                         }
139                         if ( image_index < 0 ) {
140                                 return;
141                         }
142                         if ( image_index >= this.images.length ) {
143                                 return;
144                         }
145
146                         this.images[image_index].detach();
147                         obj.css( "display", "none" );
148                 },
149
150                 _attach: function ( image_index, obj ) {
151                         if ( !obj.length ) {
152                                 return;
153                         }
154                         if ( image_index < 0 ) {
155                                 return;
156                         }
157                         if ( image_index >= this.images.length ) {
158                                 return;
159                         }
160
161                         obj.css( "display", "block" );
162                         obj.append( this.images[image_index] );
163                         this._resize( this.images[image_index] );
164                         this._align( obj, this.images[image_index] );
165                 },
166
167                 _drag: function ( _x ) {
168                         var delta,
169                                 coord_x;
170
171                         if ( !this.dragging ) {
172                                 return;
173                         }
174
175                         if ( this.options.photoFlicking === false ) {
176                                 delta = this.org_x - _x;
177
178                                 // first image
179                                 if ( delta < 0 && !this.prev_img.length ) {
180                                         return;
181                                 }
182                                 // last image
183                                 if ( delta > 0 && !this.next_img.length ) {
184                                         return;
185                                 }
186                         }
187
188                         coord_x = _x - this.org_x;
189
190                         this.cur_img.css( 'left', coord_x + 'px' );
191                         if ( this.next_img.length ) {
192                                 this.next_img.css( 'left', coord_x + this.max_width + 'px' );
193                         }
194                         if ( this.prev_img.length ) {
195                                 this.prev_img.css( 'left', coord_x - this.max_width + 'px' );
196                         }
197                 },
198
199                 _move: function ( _x ) {
200                         var delta = this.org_x - _x,
201                                 flip = 0,
202                                 date,
203                                 drag_time,
204                                 sec,
205                                 self;
206
207                         if ( delta == 0 ) {
208                                 return;
209                         }
210
211                         if ( delta > 0 ) {
212                                 flip = delta < ( this.max_width * 0.45 ) ? 0 : 1;
213                         } else {
214                                 flip = -delta < ( this.max_width * 0.45 ) ? 0 : 1;
215                         }
216
217                         if ( !flip ) {
218                                 date = new Date();
219                                 drag_time = date.getTime() - this.org_time;
220
221                                 if ( Math.abs( delta ) / drag_time > 1 ) {
222                                         flip = 1;
223                                 }
224                         }
225
226                         if ( flip ) {
227                                 if ( delta > 0 && this.next_img.length ) {
228                                         /* next */
229                                         this._detach( this.index - 1, this.prev_img );
230
231                                         this.prev_img = this.cur_img;
232                                         this.cur_img = this.next_img;
233                                         this.next_img = this.next_img.next();
234
235                                         this.index++;
236
237                                         if ( this.next_img.length ) {
238                                                 this.next_img.css( 'left', this.max_width + 'px' );
239                                                 this._attach( this.index + 1, this.next_img );
240                                         }
241
242                                         this.direction = 1;
243
244                                 } else if ( delta < 0 && this.prev_img.length ) {
245                                         /* prev */
246                                         this._detach( this.index + 1, this.next_img );
247
248                                         this.next_img = this.cur_img;
249                                         this.cur_img = this.prev_img;
250                                         this.prev_img = this.prev_img.prev();
251
252                                         this.index--;
253
254                                         if ( this.prev_img.length ) {
255                                                 this.prev_img.css( 'left', -this.max_width + 'px' );
256                                                 this._attach( this.index - 1, this.prev_img );
257                                         }
258
259                                         this.direction = -1;
260                                 }
261                         }
262
263                         sec = 500;
264                         self = this;
265
266                         this.moving = true;
267
268                         this.interval = setInterval( function () {
269                                 self.moving = false;
270                                 clearInterval( self.interval );
271                         }, sec - 50 );
272
273                         this.cur_img.animate( { left: 0 }, sec );
274                         if ( this.next_img.length ) {
275                                 this.next_img.animate( { left: this.max_width }, sec );
276                         }
277                         if ( this.prev_img.length ) {
278                                 this.prev_img.animate( { left: -this.max_width }, sec );
279                         }
280                 },
281
282                 _add_event: function () {
283                         var self = this,
284                                 date;
285
286                         this.container.bind( 'vmousemove', function ( e ) {
287                                 e.preventDefault();
288
289                                 if ( self.moving ) {
290                                         return;
291                                 }
292                                 if ( !self.dragging ) {
293                                         return;
294                                 }
295
296                                 self._drag( e.pageX );
297                         } );
298
299                         this.container.bind( 'vmousedown', function ( e ) {
300                                 e.preventDefault();
301
302                                 if ( self.moving ) {
303                                         return;
304                                 }
305
306                                 self.dragging = true;
307
308                                 self.org_x = e.pageX;
309
310                                 date = new Date();
311                                 self.org_time = date.getTime();
312                         } );
313
314                         this.container.bind( 'vmouseup', function ( e ) {
315                                 if ( self.moving ) {
316                                         return;
317                                 }
318
319                                 self.dragging = false;
320
321                                 self._move( e.pageX );
322                         } );
323
324                         this.container.bind( 'vmouseout', function ( e ) {
325                                 if ( self.moving ) {
326                                         return;
327                                 }
328                                 if ( !self.dragging ) {
329                                         return;
330                                 }
331
332                                 if ( ( e.pageX < 20 ) ||
333                                                 ( e.pageX > ( self.max_width - 20 ) ) ) {
334                                         self._move( e.pageX );
335                                         self.dragging = false;
336                                 }
337                         } );
338                 },
339
340                 _del_event: function () {
341                         this.container.unbind( 'vmousemove' );
342                         this.container.unbind( 'vmousedown' );
343                         this.container.unbind( 'vmouseup' );
344                         this.container.unbind( 'vmouseout' );
345                 },
346
347                 _show: function () {
348                         this.cur_img = $( 'div' ).find( '.ui-imageslider-bg:eq(' + this.index + ')' );
349                         this.prev_img = this.cur_img.prev();
350                         this.next_img = this.cur_img.next();
351
352                         this._attach( this.index - 1, this.prev_img );
353                         this._attach( this.index, this.cur_img );
354                         this._attach( this.index + 1, this.next_img );
355
356                         if ( this.prev_img.length ) {
357                                 this.prev_img.css( 'left', -this.max_width + 'px' );
358                         }
359
360                         this.cur_img.css( 'left', '0px' );
361
362                         if ( this.next_img.length ) {
363                                 this.next_img.css( 'left', this.max_width + 'px' );
364                         }
365                 },
366
367                 show: function () {
368                         this._show();
369                         this._add_event();
370                 },
371
372                 _hide: function () {
373                         this._detach( this.index - 1, this.prev_img );
374                         this._detach( this.index, this.cur_img );
375                         this._detach( this.index + 1, this.next_img );
376                 },
377
378                 hide: function () {
379                         this._hide();
380                         this._del_event();
381                 },
382
383                 _get_height: function () {
384                         var $page = $( '.ui-page' ),
385                                 $content = $page.children( '.ui-content' ),
386                                 $header = $page.children( '.ui-header' ),
387                                 $footer = $page.children( '.ui-footer' ),
388                                 header_h = $header.outerHeight(),
389                                 footer_h = $footer.outerHeight(),
390                                 padding = parseFloat( $content.css( 'padding-top' ) ) + parseFloat( $content.css( 'padding-bottom' ) ),
391                                 content_h = $( window ).height() - header_h - footer_h - padding * 2;
392
393                         return content_h;
394                 },
395
396                 _create: function () {
397                         var temp_img,
398                                 start_index,
399                                 i = 0;
400
401                         $( this.element ).wrapInner( '<div class="ui-imageslider"></div>' );
402                         $( this.element ).find( 'img' ).wrap( '<div class="ui-imageslider-bg"></div>' );
403
404                         this.container = $( this.element ).find('.ui-imageslider');
405
406                         this.max_width = $( window ).width();
407                         this.max_height = this._get_height();
408                         this.container.css( 'height', this.max_height );
409
410                         temp_img = $( 'div' ).find( '.ui-imageslider-bg:first' );
411
412                         while ( temp_img.length ) {
413                                 this.images[i] = temp_img.find( 'img' );
414                                 temp_img = temp_img.next();
415                                 i++;
416                         }
417
418                         for ( i = 0; i < this.images.length; i++ ) {
419                                 this.images[i].detach();
420                         }
421
422                         start_index = parseInt( $( this.element ).attr( 'data-start-index' ), 10 );
423                         if ( start_index === undefined ) {
424                                 start_index = 0;
425                         }
426                         if ( start_index < 0 ) {
427                                 start_index = 0;
428                         }
429                         if ( start_index >= this.images.length ) {
430                                 start_index = this.images.length - 1;
431                         }
432
433                         this.index = start_index;
434
435                         this.align_type = $( this.element ).attr( 'data-vertical-align' );
436                 },
437
438                 _update: function () {
439                         var image_file,
440                                 bg_html,
441                                 temp_img;
442
443                         while ( this.images_hold.length ) {
444                                 image_file = this.images_hold.shift();
445
446                                 bg_html = $( '<div class="ui-imageslider-bg"></div>' );
447                                 temp_img = $( '<img src="' + image_file + '"></div>' );
448
449                                 bg_html.append( temp_img );
450                                 this.container.append( bg_html );
451                                 this.images.push( temp_img );
452                         }
453                 },
454
455                 refresh: function ( start_index ) {
456                         this._update();
457
458                         this._hide();
459
460                         if ( start_index === undefined ) {
461                                 start_index = this.index;
462                         }
463                         if ( start_index < 0 ) {
464                                 start_index = 0;
465                         }
466                         if ( start_index >= this.images.length ) {
467                                 start_index = this.images.length - 1;
468                         }
469
470                         this.index = start_index;
471
472                         this._show();
473                 },
474
475                 add: function ( image_file ) {
476                         this.images_hold.push( image_file );
477                 },
478
479                 del: function ( image_index ) {
480                         var temp_img;
481
482                         if ( image_index === undefined ) {
483                                 image_index = this.index;
484                         }
485
486                         if ( image_index < 0 || image_index >= this.images.length ) {
487                                 return;
488                         }
489
490                         if ( image_index == this.index ) {
491                                 temp_img = this.cur_img;
492
493                                 if ( this.index == 0 ) {
494                                         this.direction = 1;
495                                 } else if ( this.index == this.images.length - 1 ) {
496                                         this.direction = -1;
497                                 }
498
499                                 if ( this.direction < 0 ) {
500                                         this.cur_img = this.prev_img;
501                                         this.prev_img = this.prev_img.prev();
502                                         if ( this.prev_img.length ) {
503                                                 this.prev_img.css( 'left', -this.max_width );
504                                                 this._attach( image_index - 2, this.prev_img );
505                                         }
506                                         this.index--;
507                                 } else {
508                                         this.cur_img = this.next_img;
509                                         this.next_img = this.next_img.next();
510                                         if ( this.next_img.length ) {
511                                                 this.next_img.css( 'left', this.max_width );
512                                                 this._attach( image_index + 2, this.next_img );
513                                         }
514                                 }
515
516                                 this.cur_img.animate( { left: 0 }, 500 );
517
518                         } else if ( image_index == this.index - 1 ) {
519                                 temp_img = this.prev_img;
520                                 this.prev_img = this.prev_img.prev();
521                                 if ( this.prev_img.length ) {
522                                         this.prev_img.css( 'left', -this.max_width );
523                                         this._attach( image_index - 1, this.prev_img );
524                                 }
525                                 this.index--;
526
527                         } else if ( image_index == this.index + 1 ) {
528                                 temp_img = this.next_img;
529                                 this.next_img = this.next_img.next();
530                                 if ( this.next_img.length ) {
531                                         this.next_img.css( 'left', this.max_width );
532                                         this._attach( image_index + 1, this.next_img );
533                                 }
534
535                         } else {
536                                 temp_img = $( 'div' ).find( '.ui-imageslider-bg:eq(' + image_index + ')' );
537                         }
538
539                         this.images.splice( image_index, 1 );
540                         temp_img.detach();
541                 }
542         }); /* End of widget */
543
544         // auto self-init widgets
545         $( document ).bind( "pagecreate", function ( e ) {
546                 $( e.target ).find( ":jqmData(role='imageslider')" ).imageslider();
547         });
548
549         $( document ).bind( "pageshow", function ( e ) {
550                 $( e.target ).find( ":jqmData(role='imageslider')" ).imageslider( 'show' );
551         });
552
553         $( document ).bind( "pagebeforehide", function ( e ) {
554                 $( e.target ).find( ":jqmData(role='imageslider')" ).imageslider( 'hide' );
555         } );
556
557 }( jQuery, this ) );