Gallery: Images showing bug has been fixed
[platform/framework/web/web-ui-fw.git] / src / js / widgets / jquery.mobile.tizen.gallery.js
1 //>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
2 //>>description: Shows images one by one, and moves them by flicking
3 //>>label: Gallery
4 //>>group: Tizen:Widgets
5
6 define( [ ], function ( ) {
7 //>>excludeEnd("jqmBuildExclude");
8
9 /* ***************************************************************************
10  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
11  *
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:
18  *
19  * The above copyright notice and this permission notice shall be included in
20  * all copies or substantial portions of the Software.
21  *
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  * ***************************************************************************
30  *
31  *      Author: Minkyu Kang <mk7.kang@samsung.com>
32  */
33
34 /*
35  * Gallery widget
36  *
37  * HTML Attributes
38  *
39  *  data-role: set to 'gallery'
40  *  data-index: start index
41  *  data-vertical-align: set to top or middle or bottom.
42  *
43  * APIs
44  *
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)
51  *
52  * Events
53  *
54  *  N/A
55  *
56  * Example
57  *
58  * <div data-role="gallery" id="gallery" data-index="3" data-vertical-align="middle">
59  *      <img src="01.jpg">
60  *      <img src="02.jpg">
61  *      <img src="03.jpg">
62  *      <img src="04.jpg">
63  *      <img src="05.jpg">
64  * </div>
65  *
66  *
67  * $('#gallery-add').bind('vmouseup', function ( e ) {
68  *      $('#gallery').gallery('add', '9.jpg');
69  *      $('#gallery').gallery('add', '10.jpg');
70  *      $('#gallery').gallery('refresh');
71  * });
72  *
73  * $('#gallery-del').bind('vmouseup', function ( e ) {
74  *      $('#gallery').gallery('remove');
75  * });
76  *
77  */
78
79  /**
80         @class Gallery
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:
82
83                 <div data-role="gallery" id="gallery" data-vertical-align="middle" data-index="3">
84                         <img src="01.jpg">
85                         <img src="02.jpg">
86                         <img src="03.jpg">
87                         <img src="04.jpg">
88                         <img src="05.jpg">
89                 </div>
90 */
91 /**
92         @property {Integer} data-index
93         Defines the index number of the first image in the gallery.
94         <br/>The default value is 0.
95 */
96 /**
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.
100 */
101 /**
102         @method add
103         The add method is used to add an image to the gallery. The image_file attribute defines the image file URL.
104
105                 <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
106                 $("#gallery").gallery('add', [image_file]);
107 */
108 /**
109         @method remove
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.
111
112                 <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
113                 $("#gallery").gallery('remove', [image_index]);
114 */
115 /**
116         @method refresh
117         The refresh method is used to refresh the gallery. This method must be called after adding images to the gallery.
118
119                 <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
120                 $("#gallery").gallery('refresh');
121 */
122 /**
123         @method empty
124         The empty method is used to remove all of images from the gallery.
125
126                 <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
127                 $("#gallery").gallery('empty');
128 */
129 /**
130         @method length
131         The length method is used to get length of images.
132
133                 <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
134                 length = $("#gallery").gallery('length');
135 */
136 /**
137         @method value
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.
139
140                 <div id="gallery" data-role="gallery" data-vertical-align="middle"></div>
141                 value = $("#gallery").gallery('value');
142                 $("#gallery").gallery('value', [image_index]);
143 */
144 (function ( $, window, undefined ) {
145         $.widget( "tizen.gallery", $.mobile.widget, {
146                 options: {
147                         flicking: false,
148                         duration: 500
149                 },
150
151                 dragging: false,
152                 moving: false,
153                 max_width: 0,
154                 max_height: 0,
155                 org_x: 0,
156                 org_time: null,
157                 cur_img: null,
158                 prev_img: null,
159                 next_img: null,
160                 images: [],
161                 images_hold: [],
162                 index: 0,
163                 align_type: null,
164                 direction: 1,
165                 container: null,
166                 orientationEventFire: false,
167
168                 _resize: function ( index ) {
169                         var img = this.images[index],
170                                 width = this.images[index].width(),
171                                 height = this.images[index].height(),
172                                 margin = 0,
173                                 ratio,
174                                 img_max_width = this.max_width - margin,
175                                 img_max_height = this.max_height - margin;
176
177                         ratio = height / width;
178
179                         if ( width > img_max_width ) {
180                                 img.width( img_max_width );
181                                 img.height( img_max_width * ratio );
182                         }
183
184                         height = img.height();
185
186                         if ( height > img_max_height ) {
187                                 img.height( img_max_height );
188                                 img.width( img_max_height / ratio );
189                         }
190                 },
191
192                 _align: function ( index, obj ) {
193                         var img = this.images[index],
194                                 img_top = 0;
195
196                         if ( !obj ) {
197                                 return;
198                         }
199                         if ( !obj.length ) {
200                                 return;
201                         }
202
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();
207                         } else {
208                                 img_top = 0;
209                         }
210
211                         obj.css( 'top', img_top + 'px' );
212                 },
213
214                 _attach: function ( index, obj ) {
215                         var self = this,
216                                 processing = function () {
217                                         self._resize( index );
218                                         self._align( index, obj );
219
220                                 },
221                                 loading = function () {
222                                         if ( self.images[index] === undefined ) {
223                                                 return;
224                                         }
225
226                                         if ( !self.images[index].height() ) {
227                                                 setTimeout( loading, 10 );
228                                                 return;
229                                         }
230
231                                         processing();
232                                 };
233
234                         if ( !obj ) {
235                                 return;
236                         }
237                         if ( !obj.length ) {
238                                 return;
239                         }
240                         if ( index < 0 ) {
241                                 return;
242                         }
243                         if ( !this.images.length ) {
244                                 return;
245                         }
246                         if ( index >= this.images.length ) {
247                                 return;
248                         }
249
250                         obj.css( "display", "block" );
251                         obj.css( "visibility", "hidden" );
252                         obj.append( this.images[index] );
253                         loading();
254                 },
255
256                 _detach: function ( index, obj ) {
257                         if ( !obj ) {
258                                 return;
259                         }
260                         if ( !obj.length ) {
261                                 return;
262                         }
263                         if ( index < 0 ) {
264                                 return;
265                         }
266                         if ( index >= this.images.length ) {
267                                 return;
268                         }
269
270                         obj.css( "display", "none" );
271                         this.images[index].removeAttr("style");
272                         this.images[index].detach();
273                 },
274
275                 _detach_all: function () {
276                         var i;
277
278                         for ( i = 0; i < this.images.length; i++ ) {
279                                 this.images[i].detach();
280                         }
281                 },
282
283                 _drag: function ( _x ) {
284                         var delta,
285                                 coord_x;
286
287                         if ( !this.dragging ) {
288                                 return;
289                         }
290
291                         if ( this.options.flicking === false ) {
292                                 delta = this.org_x - _x;
293
294                                 // first image
295                                 if ( delta < 0 && !this.prev_img.length ) {
296                                         return;
297                                 }
298                                 // last image
299                                 if ( delta > 0 && !this.next_img.length ) {
300                                         return;
301                                 }
302                         }
303
304                         coord_x = _x - this.org_x;
305
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' );
309                         }
310                         if ( this.prev_img.length ) {
311                                 this._moveLeft( this.prev_img ,  coord_x - this.window_width + 'px' );
312                         }
313                 },
314
315                 _move: function ( _x ) {
316                         var delta = this.org_x - _x,
317                                 flip = 0,
318                                 drag_time,
319                                 sec,
320                                 self;
321
322                         if ( delta == 0 ) {
323                                 return;
324                         }
325
326                         if ( delta > 0 ) {
327                                 flip = delta < ( this.max_width * 0.45 ) ? 0 : 1;
328                         } else {
329                                 flip = -delta < ( this.max_width * 0.45 ) ? 0 : 1;
330                         }
331
332                         if ( !flip ) {
333                                 drag_time = Date.now() - this.org_time;
334
335                                 if ( Math.abs( delta ) / drag_time > 1 ) {
336                                         flip = 1;
337                                 }
338                         }
339
340                         if ( flip ) {
341                                 if ( delta > 0 && this.next_img.length ) {
342                                         /* next */
343                                         this._detach( this.index - 1, this.prev_img );
344
345                                         this.prev_img = this.cur_img;
346                                         this.cur_img = this.next_img;
347                                         this.next_img = this.next_img.next();
348
349                                         this.index++;
350
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 );
354                                         }
355
356                                         this.direction = 1;
357
358                                 } else if ( delta < 0 && this.prev_img.length ) {
359                                         /* prev */
360                                         this._detach( this.index + 1, this.next_img );
361
362                                         this.next_img = this.cur_img;
363                                         this.cur_img = this.prev_img;
364                                         this.prev_img = this.prev_img.prev();
365
366                                         this.index--;
367
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 );
371                                         }
372
373                                         this.direction = -1;
374                                 }
375                         }
376
377                         sec = this.options.duration;
378                         self = this;
379
380                         this.moving = true;
381
382                         setTimeout( function () {
383                                 self.moving = false;
384                         }, sec - 25 );
385
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 );
389                         }
390                         if ( this.prev_img.length ) {
391                                 this._moveLeft( this.prev_img, -this.window_width + 'px', sec );
392                         }
393                 },
394
395                 _add_event: function () {
396                         var self = this,
397                                 date;
398
399                         this.container.bind( 'vmousemove', function ( e ) {
400                                 e.preventDefault();
401
402                                 if ( self.moving ) {
403                                         return;
404                                 }
405                                 if ( !self.dragging ) {
406                                         return;
407                                 }
408
409                                 self._drag( e.pageX );
410                         } );
411
412                         this.container.bind( 'vmousedown', function ( e ) {
413                                 e.preventDefault();
414
415                                 if ( self.moving ) {
416                                         return;
417                                 }
418
419                                 self.dragging = true;
420
421                                 self.org_x = e.pageX;
422
423                                 self.org_time = Date.now();
424                         } );
425
426                         this.container.bind( 'vmouseup', function ( e ) {
427                                 if ( self.moving ) {
428                                         return;
429                                 }
430
431                                 self.dragging = false;
432
433                                 self._move( e.pageX );
434                         } );
435
436                         this.container.bind( 'vmouseout', function ( e ) {
437                                 if ( self.moving ) {
438                                         return;
439                                 }
440                                 if ( !self.dragging ) {
441                                         return;
442                                 }
443
444                                 if ( ( e.pageX < 20 ) ||
445                                                 ( e.pageX > ( self.max_width - 20 ) ) ) {
446                                         self._move( e.pageX );
447                                         self.dragging = false;
448                                 }
449                         } );
450                 },
451
452                 _del_event: function () {
453                         this.container.unbind( 'vmousemove' );
454                         this.container.unbind( 'vmousedown' );
455                         this.container.unbind( 'vmouseup' );
456                         this.container.unbind( 'vmouseout' );
457                 },
458                 _setTranslateposition : function ( $ele, value ) {
459                         var translate,
460                                 cssArray = null,
461                                 self = this;
462
463                         if ( $.support.cssTransform3d ) {
464                                 translate = "translate3d(" + value + ", 0px, 0px)";
465                         } else {
466                                 translate = "translate(" + value + ", 0px)";
467                         }
468                         cssArray = {"-moz-transform": translate,
469                                         "-webkit-transform": translate,
470                                         "-ms-transform": translate,
471                                         "-o-transform": translate,
472                                         "transform": translate};
473
474                         $ele.css(cssArray);
475                         return $ele;
476                 },
477                 _hidePrevNext : function() {
478                         var self = this;
479
480                         if( self.next_img )
481                                 self.next_img.css( "visibility", "hidden" );
482                         if( self.prev_img )
483                                 self.prev_img.css( "visibility", "hidden" );
484
485                 },
486                 _hideCur : function() {
487                         var self = this;
488                         if( self.cur_img )
489                                 self.cur_img.css( "visibility", "hidden" );
490                 },
491                 _moveLeft : function ( $ele , value , duration ) {
492                         var translate,
493                                 transition = "",
494                                 cssArray = null,
495                                 self = this;
496
497                         if ( $.support.cssTransform3d ) {
498                                 translate = "translate3d(" + value + ", 0px, 0px)";
499                         } else {
500                                 translate = "translate(" + value + ", 0px)";
501                         }
502                         if( duration !== undefined ) {
503                                 transition =  "-webkit-transform " + (duration / 1000)+ "s ease";
504                         }
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 ;
512                                 if( value == "0px" )
513                                         $ele.one( 'webkitTransitionEnd', self._hidePrevNext );
514                                 else
515                                         $ele.one( 'webkitTransitionEnd', self._hideCur );
516                         }
517                         if( value == "0px" ) {
518                                 $ele.css( "visibility", "visible" );
519                         }
520
521                         $ele.css(cssArray);
522                         return $ele;
523                 },
524                 _show: function () {
525                         /* resizing */
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 );
530
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();
534
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 );
538
539                         this.cur_img.css( 'visibility', 'visible' );
540                         if ( this.prev_img.length ) {
541                                 this._setTranslateposition( this.prev_img, -this.window_width + 'px');
542                         }
543
544                         this._moveLeft( this.cur_img, '0px');
545                         if ( this.next_img.length ) {
546                                 this._setTranslateposition( this.next_img, this.window_width + 'px' );
547                         }
548                 },
549
550                 show: function () {
551                         if ( !this.images.length ) {
552                                 return;
553                         }
554
555                         this._show();
556                         this._add_event();
557                 },
558
559                 _hide: function () {
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 );
563                 },
564
565                 hide: function () {
566                         this._hide();
567                         this._del_event();
568                 },
569
570                 _get_width: function () {
571                         return $( this.element ).width();
572                 },
573
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;
582
583                         return content_h;
584                 },
585
586                 _create: function () {
587                         var temp_img,
588                                 self = this,
589                                 index,
590                                 i = 0;
591
592                         $( this.element ).wrapInner( '<div class="ui-gallery"></div>' );
593                         $( this.element ).find( 'img' ).wrap( '<div class="ui-gallery-bg"></div>' );
594
595                         this.container = $( this.element ).find('.ui-gallery');
596
597                         temp_img = $( 'div' ).find( '.ui-gallery-bg:first' );
598
599                         while ( temp_img.length ) {
600                                 this.images[i] = temp_img.find( 'img' );
601                                 temp_img = temp_img.next();
602                                 i++;
603                         }
604
605                         this._detach_all();
606
607                         index = parseInt( $( this.element ).jqmData( 'index' ), 10 );
608                         if ( !index ) {
609                                 index = 0;
610                         }
611                         if ( index < 0 ) {
612                                 index = 0;
613                         }
614                         if ( index >= this.images.length ) {
615                                 index = this.images.length - 1;
616                         }
617
618                         this.index = index;
619
620                         this.align_type = $( this.element ).jqmData( 'vertical-align' );
621
622                         $.extend( this, {
623                                 _globalHandlers: [
624                                         {
625                                                 src: $( window ),
626                                                 handler: {
627                                                         orientationchange: $.proxy( this, "_orientationHandler" ),
628                                                         resize: $.proxy( this, "_resizeHandler" )
629                                                 }
630                                         }
631                                 ]
632                         });
633
634                         $.each( this._globalHandlers, function( idx, value ) {
635                                 value.src.bind( value.handler );
636                         });
637                 },
638
639                 _update: function () {
640                         var image_file,
641                                 bg_html,
642                                 temp_img;
643
644                         while ( this.images_hold.length ) {
645                                 image_file = this.images_hold.shift();
646
647                                 bg_html = $( '<div class="ui-gallery-bg"></div>' );
648                                 temp_img = $( '<img src="' + image_file + '"></div>' );
649
650                                 bg_html.append( temp_img );
651                                 this.container.append( bg_html );
652                                 this.images.push( temp_img );
653                         }
654
655                         this._detach_all();
656                 },
657                 _resizeHandler: function() {
658                         var self = this;
659                         if( self.orientationEventFire ) {
660                                 self.refresh();
661                                 self.orientationEventFire = false;
662                         }
663                 },
664                 _orientationHandler: function() {
665                         var self = this;
666                         self.refresh();
667                         self.orientationEventFire = true;
668                 },
669                 refresh: function ( start_index ) {
670                         this._update();
671
672                         this._hide();
673
674                         if ( start_index === undefined ) {
675                                 start_index = this.index;
676                         }
677                         if ( start_index < 0 ) {
678                                 start_index = 0;
679                         }
680                         if ( start_index >= this.images.length ) {
681                                 start_index = this.images.length - 1;
682                         }
683
684                         this.index = start_index;
685
686                         this._show();
687
688                         return this.index;
689                 },
690
691                 add: function ( file ) {
692                         this.images_hold.push( file );
693                 },
694
695                 remove: function ( index ) {
696                         var temp_img;
697
698                         if ( index === undefined ) {
699                                 index = this.index;
700                         }
701
702                         if ( index < 0 || index >= this.images.length ) {
703                                 return;
704                         }
705
706                         if ( index == this.index ) {
707                                 temp_img = this.cur_img;
708
709                                 if ( this.index == 0 ) {
710                                         this.direction = 1;
711                                 } else if ( this.index == this.images.length - 1 ) {
712                                         this.direction = -1;
713                                 }
714
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 );
721                                         }
722                                         this.index--;
723                                 } else {
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 );
729                                         }
730                                 }
731                                 this._moveLeft( this.cur_img, '0px', this.options.duration );
732
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 );
739                                 }
740                                 this.index--;
741
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 );
748                                 }
749
750                         } else {
751                                 temp_img = $( 'div' ).find( '.ui-gallery-bg:eq(' + index + ')' );
752                         }
753
754                         this.images.splice( index, 1 );
755                         temp_img.detach();
756                 },
757
758                 empty: function () {
759                         this.images.splice( 0, this.images.length );
760                         this.container.find('.ui-gallery-bg').detach();
761                 },
762
763                 length: function () {
764                         return this.images.length;
765                 },
766
767                 value: function ( index ) {
768                         if ( index === undefined ) {
769                                 return this.index;
770                         }
771
772                         this.refresh( index );
773                 },
774
775                 destory: function() {
776                         $( window ).unbind( 'resize', this._resizeHandler );
777                         $( window ).unbind( 'orientationchange' , this._orientationHandler );
778                 }
779
780         }); /* End of widget */
781
782         // auto self-init widgets
783         $( document ).bind( "pagecreate create", function ( e ) {
784                 $( e.target ).find( ":jqmData(role='gallery')" ).gallery();
785         });
786
787         $( document ).bind( "pageshow", function ( e ) {
788                 $( e.target ).find( ":jqmData(role='gallery')" ).gallery( 'show' );
789         });
790
791         $( document ).bind( "pagebeforehide", function ( e ) {
792                 $( e.target ).find( ":jqmData(role='gallery')" ).gallery( 'hide' );
793         } );
794
795 }( jQuery, this ) );
796
797 //>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
798 } );
799 //>>excludeEnd("jqmBuildExclude");