PageSourceSearch

https://www.aizawa-group.co.jp/home/wp-content/themes/uncode/library/js/plugins.js?ver=926873759

js aizawa-group.co.jp collected 2026-09-25 05:34:48 UTC 533,190 bytes, 15,950 lines download raw bytes

1/* ----------------------------------------------------------
2 * Plugins
3 * ---------------------------------------------------------- */
4
5(function(window, $) {
6  'use strict';
7  var counter = 0,
8    $headCache = $('head'),
9    oldBigText = window.BigText,
10    oldjQueryMethod = $.fn.bigtext,
11    BigText = {
12      DEBUG_MODE: false,
13      DEFAULT_MIN_FONT_SIZE_PX: null,
14      DEFAULT_MAX_FONT_SIZE_PX: 528,
15      GLOBAL_STYLE_ID: 'bigtext-style',
16      STYLE_ID: 'bigtext-id',
17      LINE_CLASS_PREFIX: 'bigtext-line',
18      EXEMPT_CLASS: 'bigtext-exempt',
19      noConflict: function(restore)
20      {
21        if(restore) {
22          $.fn.bigtext = oldjQueryMethod;
23          window.BigText = oldBigText;
24        }
25        return BigText;
26      },
27      supports: {
28        wholeNumberFontSizeOnly: (function() {
29          if( !( 'getComputedStyle' in window ) ) {
30            return true;
31          }
32          var test = $('<div/>').css({
33              position: 'absolute',
34              'font-size': '14.1px'
35            }).insertBefore( $('script').eq(0) ),
36            computedStyle = window.getComputedStyle( test[0], null );
37
38          var ret = computedStyle && computedStyle.getPropertyValue( 'font-size' ) === '14px';
39          test.remove();
40          return ret;
41        })()
42      },
43      init: function() {
44        if(!$('#'+BigText.GLOBAL_STYLE_ID).length) {
45          $headCache.append(BigText.generateStyleTag(BigText.GLOBAL_STYLE_ID, ['.bigtext * { white-space: nowrap; } .bigtext > * { display: block; }',
46                                          '.bigtext .' + BigText.EXEMPT_CLASS + ', .bigtext .' + BigText.EXEMPT_CLASS + ' * { white-space: normal; }']));
47        }
48      },
49      bindResize: function(eventName, resizeFunction) {
50        var timeoutId;
51        $(window).unbind(eventName).bind(eventName, function() {
52          if( timeoutId ) {
53            clearTimeout( timeoutId );
54          }
55          timeoutId = setTimeout( resizeFunction, 300 );
56        });
57      },
58      getStyleId: function(id)
59      {
60        return BigText.STYLE_ID + '-' + id;
61      },
62      generateStyleTag: function(id, css)
63      {
64        return $('<style>' + css.join('\n') + '</style>').attr('id', id);
65      },
66      clearCss: function(id)
67      {
68        var styleId = BigText.getStyleId(id);
69        $('#' + styleId).remove();
70      },
71      generateCss: function(id, linesFontSizes, lineWordSpacings, minFontSizes)
72      {
73        var css = [];
74
75        BigText.clearCss(id);
76
77        for(var j=0, k=linesFontSizes.length; j<k; j++) {
78          css.push('#' + id + ' .' + BigText.LINE_CLASS_PREFIX + j + ' {' +
79            (minFontSizes[j] ? ' white-space: normal;' : '') +
80            (linesFontSizes[j] ? ' font-size: ' + linesFontSizes[j] + 'px;' : '') +
81            (lineWordSpacings[j] ? ' word-spacing: ' + lineWordSpacings[j] + 'px;' : '') +
82            '}');
83        }
84
85        return BigText.generateStyleTag(BigText.getStyleId(id), css);
86      },
87      jQueryMethod: function(options)
88      {
89        BigText.init();
90
91        options = $.extend({
92          minfontsize: BigText.DEFAULT_MIN_FONT_SIZE_PX,
93          maxfontsize: BigText.DEFAULT_MAX_FONT_SIZE_PX,
94          childSelector: '',
95          resize: true
96        }, options || {});
97
98        this.each(function()
99        {
100          var $t = $(this).addClass('bigtext'),
101            maxWidth = $t.width(),
102            id = $t.attr('id'),
103            $children = options.childSelector ? $t.find( options.childSelector ) : $t.children();
104
105          if(!id) {
106            id = 'bigtext-id' + (counter++);
107            $t.attr('id', id);
108          }
109
110          if(options.resize) {
111            BigText.bindResize('resize.bigtext-event-' + id, function()
112            {
113              // TODO only call this if the width has changed.
114              BigText.jQueryMethod.call($('#' + id), options);
115            });
116          }
117
118          BigText.clearCss(id);
119
120          $children.addClass(function(lineNumber, className)
121          {
122            // remove existing line classes.
123            return [className.replace(new RegExp('\\b' + BigText.LINE_CLASS_PREFIX + '\\d+\\b'), ''),
124                BigText.LINE_CLASS_PREFIX + lineNumber].join(' ');
125          });
126
127          var sizes = calculateSizes($t, $children, maxWidth, options.maxfontsize, options.minfontsize);
128          $headCache.append(BigText.generateCss(id, sizes.fontSizes, sizes.wordSpacings, sizes.minFontSizes));
129        });
130
131        return this.trigger('bigtext:complete');
132      }
133    };
134
135  function testLineDimensions($line, maxWidth, property, size, interval, units, previousWidth)
136  {
137    var width;
138    previousWidth = typeof previousWidth === 'number' ? previousWidth : 0;
139    $line.css(property, size + units);
140
141    width = $line.width();
142
143    if(width >= maxWidth) {
144
145      $line.css(property, '');
146
147      if(width === maxWidth) {
148        return {
149          match: 'exact',
150          size: parseFloat((parseFloat(size) - 0.1).toFixed(3))
151        };
152      }
153
154      // Since this is an estimate, we calculate how far over the width we went with the new value.
155      // If this is word-spacing (our last resort guess) and the over is less than the under, we keep the higher value.
156      // Otherwise, we revert to the underestimate.
157      var under = maxWidth - previousWidth,
158        over = width - maxWidth;
159
160      return {
161        match: 'estimate',
162        size: parseFloat((parseFloat(size) - (property === 'word-spacing' && previousWidth && ( over < under ) ? 0 : interval)).toFixed(3))
163      };
164    }
165
166    return width;
167  }
168
169  function calculateSizes($t, $children, maxWidth, maxFontSize, minFontSize)
170  {
171    var $c = $t.clone(true)
172      .addClass('bigtext-cloned')
173      .css({
174        fontFamily: $t.css('font-family'),
175        textTransform: $t.css('text-transform'),
176        wordSpacing: $t.css('word-spacing'),
177        letterSpacing: $t.css('letter-spacing'),
178        position: 'absolute',
179        left: BigText.DEBUG_MODE ? 0 : -9999,
180        top: BigText.DEBUG_MODE ? 0 : -9999
181      })
182      .appendTo(document.body);
183
184    // font-size isn't the only thing we can modify, we can also mess with:
185    // word-spacing and letter-spacing. WebKit does not respect subpixel
186    // letter-spacing, word-spacing, or font-size.
187    // TODO try -webkit-transform: scale() as a workaround.
188    var fontSizes = [],
189      wordSpacings = [],
190      minFontSizes = [],
191      ratios = [];
192
193    $children.css('float', 'left').each(function() {
194      var $line = $(this),
195        // TODO replace 8, 4 with a proportional size to the calculated font-size.
196        intervals = BigText.supports.wholeNumberFontSizeOnly ? [8, 4, 1] : [8, 4, 1, 0.1],
197        lineMax,
198        newFontSize;
199
200      if($line.hasClass(BigText.EXEMPT_CLASS)) {
201        fontSizes.push(null);
202        ratios.push(null);
203        minFontSizes.push(false);
204        return;
205      }
206
207      // TODO we can cache this ratio?
208      var autoGuessSubtraction = 32, // font size in px
209        currentFontSize = parseFloat($line.css('font-size')),
210        ratio = ( $line.width() / currentFontSize ).toFixed(6);
211
212      newFontSize = parseInt( maxWidth / ratio, 10 ) - autoGuessSubtraction;
213
214      outer: for(var m=0, n=intervals.length; m<n; m++) {
215        inner: for(var j=1, k=10; j<=k; j++) {
216          if(newFontSize + j*intervals[m] > maxFontSize) {
217            newFontSize = maxFontSize;
218            break outer;
219          }
220
221          lineMax = testLineDimensions($line, maxWidth, 'font-size', newFontSize + j*intervals[m], intervals[m], 'px', lineMax);
222          if(typeof lineMax !== 'number') {
223            newFontSize = lineMax.size;
224
225            if(lineMax.match === 'exact') {
226              break outer;
227            }
228            break inner;
229          }
230        }
231      }
232
233      ratios.push(maxWidth / newFontSize);
234
235      if(newFontSize > maxFontSize) {
236        fontSizes.push(maxFontSize);
237        minFontSizes.push(false);
238      } else if(!!minFontSize && newFontSize < minFontSize) {
239        fontSizes.push(minFontSize);
240        minFontSizes.push(true);
241      } else {
242        fontSizes.push(newFontSize);
243        minFontSizes.push(false);
244      }
245    }).each(function(lineNumber) {
246      var $line = $(this),
247        wordSpacing = 0,
248        interval = 1,
249        maxWordSpacing;
250
251      if($line.hasClass(BigText.EXEMPT_CLASS)) {
252        wordSpacings.push(null);
253        return;
254      }
255
256      // must re-use font-size, even though it was removed above.
257      $line.css('font-size', fontSizes[lineNumber] + 'px');
258
259      for(var m=1, n=3; m<n; m+=interval) {
260        maxWordSpacing = testLineDimensions($line, maxWidth, 'word-spacing', m, interval, 'px', maxWordSpacing);
261        if(typeof maxWordSpacing !== 'number') {
262          wordSpacing = maxWordSpacing.size;
263          break;
264        }
265      }
266
267      $line.css('font-size', '');
268      wordSpacings.push(wordSpacing);
269    }).removeAttr('style');
270
271    if( !BigText.DEBUG_MODE ) {
272      $c.remove();
273    } else {
274      $c.css({
275        'background-color': 'rgba(255,255,255,.4)'
276      });
277    }
278
279    return {
280      fontSizes: fontSizes,
281      wordSpacings: wordSpacings,
282      ratios: ratios,
283      minFontSizes: minFontSizes
284    };
285  }
286
287  $.fn.bigtext = BigText.jQueryMethod;
288  window.BigText = BigText;
289
290})(this, jQuery);
291
292/*!
293 * Isotope PACKAGED v2.2.2
294 *
295 * Licensed GPLv3 for open source use
296 * or Isotope Commercial License for commercial use
297 *
298 * http://isotope.metafizzy.co
299 * Copyright 2015 Metafizzy
300 */
301
302/**
303 * Bridget makes jQuery widgets
304 * v1.1.0
305 * MIT license
306 */
307
308( function( window ) {
309
310
311
312// -------------------------- utils -------------------------- //
313
314var slice = Array.prototype.slice;
315
316function noop() {}
317
318// -------------------------- definition -------------------------- //
319
320function defineBridget( $ ) {
321
322// bail if no jQuery
323if ( !$ ) {
324  return;
325}
326
327// -------------------------- addOptionMethod -------------------------- //
328
329/**
330 * adds option method -> $().plugin('option', {...})
331 * @param {Function} PluginClass - constructor class
332 */
333function addOptionMethod( PluginClass ) {
334  // don't overwrite original option method
335  if ( PluginClass.prototype.option ) {
336    return;
337  }
338
339  // option setter
340  PluginClass.prototype.option = function( opts ) {
341    // bail out if not an object
342    if ( !$.isPlainObject( opts ) ){
343      return;
344    }
345    this.options = $.extend( true, this.options, opts );
346  };
347}
348
349// -------------------------- plugin bridge -------------------------- //
350
351// helper function for logging errors
352// $.error breaks jQuery chaining
353var logError = typeof console === 'undefined' ? noop :
354  function( message ) {
355    console.error( message );
356  };
357
358/**
359 * jQuery plugin bridge, access methods like $elem.plugin('method')
360 * @param {String} namespace - plugin name
361 * @param {Function} PluginClass - constructor class
362 */
363function bridge( namespace, PluginClass ) {
364  // add to jQuery fn namespace
365  $.fn[ namespace ] = function( options ) {
366    if ( typeof options === 'string' ) {
367      // call plugin method when first argument is a string
368      // get arguments for method
369      var args = slice.call( arguments, 1 );
370
371      for ( var i=0, len = this.length; i < len; i++ ) {
372        var elem = this[i];
373        var instance = $.data( elem, namespace );
374        if ( !instance ) {
375          logError( "cannot call methods on " + namespace + " prior to initialization; " +
376            "attempted to call '" + options + "'" );
377          continue;
378        }
379        if ( !$.isFunction( instance[options] ) || options.charAt(0) === '_' ) {
380          logError( "no such method '" + options + "' for " + namespace + " instance" );
381          continue;
382        }
383
384        // trigger method with arguments
385        var returnValue = instance[ options ].apply( instance, args );
386
387        // break look and return first value if provided
388        if ( returnValue !== undefined ) {
389          return returnValue;
390        }
391      }
392      // return this if no return value
393      return this;
394    } else {
395      return this.each( function() {
396        var instance = $.data( this, namespace );
397        if ( instance ) {
398          // apply options & init
399          instance.option( options );
400          instance._init();
401        } else {
402          // initialize new instance
403          instance = new PluginClass( this, options );
404          $.data( this, namespace, instance );
405        }
406      });
407    }
408  };
409
410}
411
412// -------------------------- bridget -------------------------- //
413
414/**
415 * converts a Prototypical class into a proper jQuery plugin
416 *   the class must have a ._init method
417 * @param {String} namespace - plugin name, used in $().pluginName
418 * @param {Function} PluginClass - constructor class
419 */
420$.bridget = function( namespace, PluginClass ) {
421  addOptionMethod( PluginClass );
422  bridge( namespace, PluginClass );
423};
424
425return $.bridget;
426
427}
428
429// transport
430if ( typeof define === 'function' && define.amd ) {
431  // AMD
432  define( 'jquery-bridget/jquery.bridget',[ 'jquery' ], defineBridget );
433} else if ( typeof exports === 'object' ) {
434  defineBridget( require('jquery') );
435} else {
436  // get jquery from browser global
437  defineBridget( window.jQuery );
438}
439
440})( window );
441
442/*!
443 * eventie v1.0.6
444 * event binding helper
445 *   eventie.bind( elem, 'click', myFn )
446 *   eventie.unbind( elem, 'click', myFn )
447 * MIT license
448 */
449
450/*jshint browser: true, undef: true, unused: true */
451/*global define: false, module: false */
452
453( function( window ) {
454
455
456
457var docElem = document.documentElement;
458
459var bind = function() {};
460
461function getIEEvent( obj ) {
462  var event = window.event;
463  // add event.target
464  event.target = event.target || event.srcElement || obj;
465  return event;
466}
467
468if ( docElem.addEventListener ) {
469  bind = function( obj, type, fn ) {
470    obj.addEventListener( type, fn, false );
471  };
472} else if ( docElem.attachEvent ) {
473  bind = function( obj, type, fn ) {
474    obj[ type + fn ] = fn.handleEvent ?
475      function() {
476        var event = getIEEvent( obj );
477        fn.handleEvent.call( fn, event );
478      } :
479      function() {
480        var event = getIEEvent( obj );
481        fn.call( obj, event );
482      };
483    obj.attachEvent( "on" + type, obj[ type + fn ] );
484  };
485}
486
487var unbind = function() {};
488
489if ( docElem.removeEventListener ) {
490  unbind = function( obj, type, fn ) {
491    obj.removeEventListener( type, fn, false );
492  };
493} else if ( docElem.detachEvent ) {
494  unbind = function( obj, type, fn ) {
495    obj.detachEvent( "on" + type, obj[ type + fn ] );
496    try {
497      delete obj[ type + fn ];
498    } catch ( err ) {
499      // can't delete window object properties
500      obj[ type + fn ] = undefined;
501    }
502  };
503}
504
505var eventie = {
506  bind: bind,
507  unbind: unbind
508};
509
510// ----- module definition ----- //
511
512if ( typeof define === 'function' && define.amd ) {
513  // AMD
514  define( 'eventie/eventie',eventie );
515} else if ( typeof exports === 'object' ) {
516  // CommonJS
517  module.exports = eventie;
518} else {
519  // browser global
520  window.eventie = eventie;
521}
522
523})( window );
524
525/*!
526 * EventEmitter v4.2.11 - git.io/ee
527 * Unlicense - http://unlicense.org/
528 * Oliver Caldwell - http://oli.me.uk/
529 * @preserve
530 */
531
532;(function () {
533    'use strict';
534
535    /**
536     * Class for managing events.
537     * Can be extended to provide event functionality in other classes.
538     *
539     * @class EventEmitter Manages event registering and emitting.
540     */
541    function EventEmitter() {}
542
543    // Shortcuts to improve speed and size
544    var proto = EventEmitter.prototype;
545    var exports = this;
546    var originalGlobalValue = exports.EventEmitter;
547
548    /**
549     * Finds the index of the listener for the event in its storage array.
550     *
551     * @param {Function[]} listeners Array of listeners to search through.
552     * @param {Function} listener Method to look for.
553     * @return {Number} Index of the specified listener, -1 if not found
554     * @api private
555     */
556    function indexOfListener(listeners, listener) {
557        var i = listeners.length;
558        while (i--) {
559            if (listeners[i].listener === listener) {
560                return i;
561            }
562        }
563
564        return -1;
565    }
566
567    /**
568     * Alias a method while keeping the context correct, to allow for over
vendor: 16,384 bytes, lines 568-971
568writing of target method.
569     *
570     * @param {String} name The name of the target method.
571     * @return {Function} The aliased method
572     * @api private
573     */
574    function alias(name) {
575        return function aliasClosure() {
576            return this[name].apply(this, arguments);
577        };
578    }
579
580    /**
581     * Returns the listener array for the specified event.
582     * Will initialise the event object and listener arrays if required.
583     * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
584     * Each property in the object response is an array of listener functions.
585     *
586     * @param {String|RegExp} evt Name of the event to return the listeners from.
587     * @return {Function[]|Object} All listener functions for the event.
588     */
589    proto.getListeners = function getListeners(evt) {
590        var events = this._getEvents();
591        var response;
592        var key;
593
594        // Return a concatenated array of all matching events if
595        // the selector is a regular expression.
596        if (evt instanceof RegExp) {
597            response = {};
598            for (key in events) {
599                if (events.hasOwnProperty(key) && evt.test(key)) {
600                    response[key] = events[key];
601                }
602            }
603        }
604        else {
605            response = events[evt] || (events[evt] = []);
606        }
607
608        return response;
609    };
610
611    /**
612     * Takes a list of listener objects and flattens it into a list of listener functions.
613     *
614     * @param {Object[]} listeners Raw listener objects.
615     * @return {Function[]} Just the listener functions.
616     */
617    proto.flattenListeners = function flattenListeners(listeners) {
618        var flatListeners = [];
619        var i;
620
621        for (i = 0; i < listeners.length; i += 1) {
622            flatListeners.push(listeners[i].listener);
623        }
624
625        return flatListeners;
626    };
627
628    /**
629     * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
630     *
631     * @param {String|RegExp} evt Name of the event to return the listeners from.
632     * @return {Object} All listener functions for an event in an object.
633     */
634    proto.getListenersAsObject = function getListenersAsObject(evt) {
635        var listeners = this.getListeners(evt);
636        var response;
637
638        if (listeners instanceof Array) {
639            response = {};
640            response[evt] = listeners;
641        }
642
643        return response || listeners;
644    };
645
646    /**
647     * Adds a listener function to the specified event.
648     * The listener will not be added if it is a duplicate.
649     * If the listener returns true then it will be removed after it is called.
650     * If you pass a regular expression as the event name then the listener will be added to all events that match it.
651     *
652     * @param {String|RegExp} evt Name of the event to attach the listener to.
653     * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
654     * @return {Object} Current instance of EventEmitter for chaining.
655     */
656    proto.addListener = function addListener(evt, listener) {
657        var listeners = this.getListenersAsObject(evt);
658        var listenerIsWrapped = typeof listener === 'object';
659        var key;
660
661        for (key in listeners) {
662            if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
663                listeners[key].push(listenerIsWrapped ? listener : {
664                    listener: listener,
665                    once: false
666                });
667            }
668        }
669
670        return this;
671    };
672
673    /**
674     * Alias of addListener
675     */
676    proto.on = alias('addListener');
677
678    /**
679     * Semi-alias of addListener. It will add a listener that will be
680     * automatically removed after its first execution.
681     *
682     * @param {String|RegExp} evt Name of the event to attach the listener to.
683     * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
684     * @return {Object} Current instance of EventEmitter for chaining.
685     */
686    proto.addOnceListener = function addOnceListener(evt, listener) {
687        return this.addListener(evt, {
688            listener: listener,
689            once: true
690        });
691    };
692
693    /**
694     * Alias of addOnceListener.
695     */
696    proto.once = alias('addOnceListener');
697
698    /**
699     * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
700     * You need to tell it what event names should be matched by a regex.
701     *
702     * @param {String} evt Name of the event to create.
703     * @return {Object} Current instance of EventEmitter for chaining.
704     */
705    proto.defineEvent = function defineEvent(evt) {
706        this.getListeners(evt);
707        return this;
708    };
709
710    /**
711     * Uses defineEvent to define multiple events.
712     *
713     * @param {String[]} evts An array of event names to define.
714     * @return {Object} Current instance of EventEmitter for chaining.
715     */
716    proto.defineEvents = function defineEvents(evts) {
717        for (var i = 0; i < evts.length; i += 1) {
718            this.defineEvent(evts[i]);
719        }
720        return this;
721    };
722
723    /**
724     * Removes a listener function from the specified event.
725     * When passed a regular expression as the event name, it will remove the listener from all events that match it.
726     *
727     * @param {String|RegExp} evt Name of the event to remove the listener from.
728     * @param {Function} listener Method to remove from the event.
729     * @return {Object} Current instance of EventEmitter for chaining.
730     */
731    proto.removeListener = function removeListener(evt, listener) {
732        var listeners = this.getListenersAsObject(evt);
733        var index;
734        var key;
735
736        for (key in listeners) {
737            if (listeners.hasOwnProperty(key)) {
738                index = indexOfListener(listeners[key], listener);
739
740                if (index !== -1) {
741                    listeners[key].splice(index, 1);
742                }
743            }
744        }
745
746        return this;
747    };
748
749    /**
750     * Alias of removeListener
751     */
752    proto.off = alias('removeListener');
753
754    /**
755     * Adds listeners in bulk using the manipulateListeners method.
756     * If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
757     * You can also pass it a regular expression to add the array of listeners to all events that match it.
758     * Yeah, this function does quite a bit. That's probably a bad thing.
759     *
760     * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
761     * @param {Function[]} [listeners] An optional array of listener functions to add.
762     * @return {Object} Current instance of EventEmitter for chaining.
763     */
764    proto.addListeners = function addListeners(evt, listeners) {
765        // Pass through to manipulateListeners
766        return this.manipulateListeners(false, evt, listeners);
767    };
768
769    /**
770     * Removes listeners in bulk using the manipulateListeners method.
771     * If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
772     * You can also pass it an event name and an array of listeners to be removed.
773     * You can also pass it a regular expression to remove the listeners from all events that match it.
774     *
775     * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
776     * @param {Function[]} [listeners] An optional array of listener functions to remove.
777     * @return {Object} Current instance of EventEmitter for chaining.
778     */
779    proto.removeListeners = function removeListeners(evt, listeners) {
780        // Pass through to manipulateListeners
781        return this.manipulateListeners(true, evt, listeners);
782    };
783
784    /**
785     * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
786     * The first argument will determine if the listeners are removed (true) or added (false).
787     * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
788     * You can also pass it an event name and an array of listeners to be added/removed.
789     * You can also pass it a regular expression to manipulate the listeners of all events that match it.
790     *
791     * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
792     * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
793     * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
794     * @return {Object} Current instance of EventEmitter for chaining.
795     */
796    proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
797        var i;
798        var value;
799        var single = remove ? this.removeListener : this.addListener;
800        var multiple = remove ? this.removeListeners : this.addListeners;
801
802        // If evt is an object then pass each of its properties to this method
803        if (typeof evt === 'object' && !(evt instanceof RegExp)) {
804            for (i in evt) {
805                if (evt.hasOwnProperty(i) && (value = evt[i])) {
806                    // Pass the single listener straight through to the singular method
807                    if (typeof value === 'function') {
808                        single.call(this, i, value);
809                    }
810                    else {
811                        // Otherwise pass back to the multiple function
812                        multiple.call(this, i, value);
813                    }
814                }
815            }
816        }
817        else {
818            // So evt must be a string
819            // And listeners must be an array of listeners
820            // Loop over it and pass each one to the multiple method
821            i = listeners.length;
822            while (i--) {
823                single.call(this, evt, listeners[i]);
824            }
825        }
826
827        return this;
828    };
829
830    /**
831     * Removes all listeners from a specified event.
832     * If you do not specify an event then all listeners will be removed.
833     * That means every event will be emptied.
834     * You can also pass a regex to remove all events that match it.
835     *
836     * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
837     * @return {Object} Current instance of EventEmitter for chaining.
838     */
839    proto.removeEvent = function removeEvent(evt) {
840        var type = typeof evt;
841        var events = this._getEvents();
842        var key;
843
844        // Remove different things depending on the state of evt
845        if (type === 'string') {
846            // Remove all listeners for the specified event
847            delete events[evt];
848        }
849        else if (evt instanceof RegExp) {
850            // Remove all events matching the regex.
851            for (key in events) {
852                if (events.hasOwnProperty(key) && evt.test(key)) {
853                    delete events[key];
854                }
855            }
856        }
857        else {
858            // Remove all listeners in all events
859            delete this._events;
860        }
861
862        return this;
863    };
864
865    /**
866     * Alias of removeEvent.
867     *
868     * Added to mirror the node API.
869     */
870    proto.removeAllListeners = alias('removeEvent');
871
872    /**
873     * Emits an event of your choice.
874     * When emitted, every listener attached to that event will be executed.
875     * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
876     * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
877     * So they will not arrive within the array on the other side, they will be separate.
878     * You can also pass a regular expression to emit to all events that match it.
879     *
880     * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
881     * @param {Array} [args] Optional array of arguments to be passed to each listener.
882     * @return {Object} Current instance of EventEmitter for chaining.
883     */
884    proto.emitEvent = function emitEvent(evt, args) {
885        var listeners = this.getListenersAsObject(evt);
886        var listener;
887        var i;
888        var key;
889        var response;
890
891        for (key in listeners) {
892            if (listeners.hasOwnProperty(key)) {
893                i = listeners[key].length;
894
895                while (i--) {
896                    // If the listener returns true then it shall be removed from the event
897                    // The function is executed either with a basic call or an apply if there is an args array
898                    listener = listeners[key][i];
899
900                    if (listener.once === true) {
901                        this.removeListener(evt, listener.listener);
902                    }
903
904                    response = listener.listener.apply(this, args || []);
905
906                    if (response === this._getOnceReturnValue()) {
907                        this.removeListener(evt, listener.listener);
908                    }
909                }
910            }
911        }
912
913        return this;
914    };
915
916    /**
917     * Alias of emitEvent
918     */
919    proto.trigger = alias('emitEvent');
920
921    /**
922     * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
923     * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
924     *
925     * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
926     * @param {...*} Optional additional arguments to be passed to each listener.
927     * @return {Object} Current instance of EventEmitter for chaining.
928     */
929    proto.emit = function emit(evt) {
930        var args = Array.prototype.slice.call(arguments, 1);
931        return this.emitEvent(evt, args);
932    };
933
934    /**
935     * Sets the current value to check against when executing listeners. If a
936     * listeners return value matches the one set here then it will be removed
937     * after execution. This value defaults to true.
938     *
939     * @param {*} value The new value to check for when executing listeners.
940     * @return {Object} Current instance of EventEmitter for chaining.
941     */
942    proto.setOnceReturnValue = function setOnceReturnValue(value) {
943        this._onceReturnValue = value;
944        return this;
945    };
946
947    /**
948     * Fetches the current value to check against when executing listeners. If
949     * the listeners return value matches this one then it should be removed
950     * automatically. It will return true by default.
951     *
952     * @return {*|Boolean} The current value to check for or the default, true.
953     * @api private
954     */
955    proto._getOnceReturnValue = function _getOnceReturnValue() {
956        if (this.hasOwnProperty('_onceReturnValue')) {
957            return this._onceReturnValue;
958        }
959        else {
960            return true;
961        }
962    };
963
964    /**
965     * Fetches the events object and creates one if required.
966     *
967     * @return {Object} The events storage object.
968     * @api private
969     */
970    proto._getEvents = function _getEvents() {
971        return this._events || (this
971._events = {});
972    };
973
974    /**
975     * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
976     *
977     * @return {Function} Non conflicting EventEmitter class.
978     */
979    EventEmitter.noConflict = function noConflict() {
980        exports.EventEmitter = originalGlobalValue;
981        return EventEmitter;
982    };
983
984    // Expose the class either via AMD, CommonJS or the global object
985    if (typeof define === 'function' && define.amd) {
986        define('eventEmitter/EventEmitter',[],function () {
987            return EventEmitter;
988        });
989    }
990    else if (typeof module === 'object' && module.exports){
991        module.exports = EventEmitter;
992    }
993    else {
994        exports.EventEmitter = EventEmitter;
995    }
996}.call(this));
997
998/*!
999 * getStyleProperty v1.0.4
1000 * original by kangax
1001 * http://perfectionkills.com/feature-testing-css-properties/
1002 * MIT license
1003 */
1004
1005/*jshint browser: true, strict: true, undef: true */
1006/*global define: false, exports: false, module: false */
1007
1008( function( window ) {
1009
1010
1011
1012var prefixes = 'Webkit Moz ms Ms O'.split(' ');
1013var docElemStyle = document.documentElement.style;
1014
1015function getStyleProperty( propName ) {
1016  if ( !propName ) {
1017    return;
1018  }
1019
1020  // test standard property first
1021  if ( typeof docElemStyle[ propName ] === 'string' ) {
1022    return propName;
1023  }
1024
1025  // capitalize
1026  propName = propName.charAt(0).toUpperCase() + propName.slice(1);
1027
1028  // test vendor specific properties
1029  var prefixed;
1030  for ( var i=0, len = prefixes.length; i < len; i++ ) {
1031    prefixed = prefixes[i] + propName;
1032    if ( typeof docElemStyle[ prefixed ] === 'string' ) {
1033      return prefixed;
1034    }
1035  }
1036}
1037
1038// transport
1039if ( typeof define === 'function' && define.amd ) {
1040  // AMD
1041  define( 'get-style-property/get-style-property',[],function() {
1042    return getStyleProperty;
1043  });
1044} else if ( typeof exports === 'object' ) {
1045  // CommonJS for Component
1046  module.exports = getStyleProperty;
1047} else {
1048  // browser global
1049  window.getStyleProperty = getStyleProperty;
1050}
1051
1052})( window );
1053
1054/*!
1055 * getSize v1.2.2
1056 * measure size of elements
1057 * MIT license
1058 */
1059
1060/*jshint browser: true, strict: true, undef: true, unused: true */
1061/*global define: false, exports: false, require: false, module: false, console: false */
1062
1063( function( window, undefined ) {
1064
1065
1066
1067// -------------------------- helpers -------------------------- //
1068
1069// get a number from a string, not a percentage
1070function getStyleSize( value ) {
1071  var num = parseFloat( value );
1072  // not a percent like '100%', and a number
1073  var isValid = value.indexOf('%') === -1 && !isNaN( num );
1074  return isValid && num;
1075}
1076
1077function noop() {}
1078
1079var logError = typeof console === 'undefined' ? noop :
1080  function( message ) {
1081    console.error( message );
1082  };
1083
1084// -------------------------- measurements -------------------------- //
1085
1086var measurements = [
1087  'paddingLeft',
1088  'paddingRight',
1089  'paddingTop',
1090  'paddingBottom',
1091  'marginLeft',
1092  'marginRight',
1093  'marginTop',
1094  'marginBottom',
1095  'borderLeftWidth',
1096  'borderRightWidth',
1097  'borderTopWidth',
1098  'borderBottomWidth'
1099];
1100
1101function getZeroSize() {
1102  var size = {
1103    width: 0,
1104    height: 0,
1105    innerWidth: 0,
1106    innerHeight: 0,
1107    outerWidth: 0,
1108    outerHeight: 0
1109  };
1110  for ( var i=0, len = measurements.length; i < len; i++ ) {
1111    var measurement = measurements[i];
1112    size[ measurement ] = 0;
1113  }
1114  return size;
1115}
1116
1117
1118
1119function defineGetSize( getStyleProperty ) {
1120
1121// -------------------------- setup -------------------------- //
1122
1123var isSetup = false;
1124
1125var getStyle, boxSizingProp, isBoxSizeOuter;
1126
1127/**
1128 * setup vars and functions
1129 * do it on initial getSize(), rather than on script load
1130 * For Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=548397
1131 */
1132function setup() {
1133  // setup once
1134  if ( isSetup ) {
1135    return;
1136  }
1137  isSetup = true;
1138
1139  var getComputedStyle = window.getComputedStyle;
1140  getStyle = ( function() {
1141    var getStyleFn = getComputedStyle ?
1142      function( elem ) {
1143        return getComputedStyle( elem, null );
1144      } :
1145      function( elem ) {
1146        return elem.currentStyle;
1147      };
1148
1149      return function getStyle( elem ) {
1150        var style = getStyleFn( elem );
1151        if ( !style ) {
1152          logError( 'Style returned ' + style +
1153            '. Are you running this code in a hidden iframe on Firefox? ' +
1154            'See http://bit.ly/getsizebug1' );
1155        }
1156        return style;
1157      };
1158  })();
1159
1160  // -------------------------- box sizing -------------------------- //
1161
1162  boxSizingProp = getStyleProperty('boxSizing');
1163
1164  /**
1165   * WebKit measures the outer-width on style.width on border-box elems
1166   * IE & Firefox measures the inner-width
1167   */
1168  if ( boxSizingProp ) {
1169    var div = document.createElement('div');
1170    div.style.width = '200px';
1171    div.style.padding = '1px 2px 3px 4px';
1172    div.style.borderStyle = 'solid';
1173    div.style.borderWidth = '1px 2px 3px 4px';
1174    div.style[ boxSizingProp ] = 'border-box';
1175
1176    var body = document.body || document.documentElement;
1177    body.appendChild( div );
1178    var style = getStyle( div );
1179
1180    isBoxSizeOuter = getStyleSize( style.width ) === 200;
1181    body.removeChild( div );
1182  }
1183
1184}
1185
1186// -------------------------- getSize -------------------------- //
1187
1188function getSize( elem ) {
1189  setup();
1190
1191  // use querySeletor if elem is string
1192  if ( typeof elem === 'string' ) {
1193    elem = document.querySelector( elem );
1194  }
1195
1196  // do not proceed on non-objects
1197  if ( !elem || typeof elem !== 'object' || !elem.nodeType ) {
1198    return;
1199  }
1200
1201  var style = getStyle( elem );
1202
1203  // if hidden, everything is 0
1204  if ( style.display === 'none' ) {
1205    return getZeroSize();
1206  }
1207
1208  var size = {};
1209  size.width = elem.offsetWidth;
1210  size.height = elem.offsetHeight;
1211
1212  var isBorderBox = size.isBorderBox = !!( boxSizingProp &&
1213    style[ boxSizingProp ] && style[ boxSizingProp ] === 'border-box' );
1214
1215  // get all measurements
1216  for ( var i=0, len = measurements.length; i < len; i++ ) {
1217    var measurement = measurements[i];
1218    var value = style[ measurement ];
1219    value = mungeNonPixel( elem, value );
1220    var num = parseFloat( value );
1221    // any 'auto', 'medium' value will be 0
1222    size[ measurement ] = !isNaN( num ) ? num : 0;
1223  }
1224
1225  var paddingWidth = size.paddingLeft + size.paddingRight;
1226  var paddingHeight = size.paddingTop + size.paddingBottom;
1227  var marginWidth = size.marginLeft + size.marginRight;
1228  var marginHeight = size.marginTop + size.marginBottom;
1229  var borderWidth = size.borderLeftWidth + size.borderRightWidth;
1230  var borderHeight = size.borderTopWidth + size.borderBottomWidth;
1231
1232  var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;
1233
1234  // overwrite width and height if we can get it from style
1235  var styleWidth = getStyleSize( style.width );
1236  if ( styleWidth !== false ) {
1237    size.width = styleWidth +
1238      // add padding and border unless it's already including it
1239      ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth );
1240  }
1241
1242  var styleHeight = getStyleSize( style.height );
1243  if ( styleHeight !== false ) {
1244    size.height = styleHeight +
1245      // add padding and border unless it's already including it
1246      ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight );
1247  }
1248
1249  size.innerWidth = size.width - ( paddingWidth + borderWidth );
1250  size.innerHeight = size.height - ( paddingHeight + borderHeight );
1251
1252  size.outerWidth = size.width + marginWidth;
1253  size.outerHeight = size.height + marginHeight;
1254
1255  return size;
1256}
1257
1258// IE8 returns percent values, not pixels
1259// taken from jQuery's curCSS
1260function mungeNonPixel( elem, value ) {
1261  // IE8 and has percent value
1262  if ( window.getComputedStyle || value.indexOf('%') === -1 ) {
1263    return value;
1264  }
1265  var style = elem.style;
1266  // Remember the original values
1267  var left = style.left;
1268  var rs = elem.runtimeStyle;
1269  var rsLeft = rs && rs.left;
1270
1271  // Put in the new values to get a computed value out
1272  if ( rsLeft ) {
1273    rs.left = elem.currentStyle.left;
1274  }
1275  style.left = value;
1276  value = style.pixelLeft;
1277
1278  // Revert the changed values
1279  style.left = left;
1280  if ( rsLeft ) {
1281    rs.left = rsLeft;
1282  }
1283
1284  return value;
1285}
1286
1287return getSize;
1288
1289}
1290
1291// transport
1292if ( typeof define === 'function' && define.amd ) {
1293  // AMD for RequireJS
1294  define( 'get-size/get-size',[ 'get-style-property/get-style-property' ], defineGetSize );
1295} else if ( typeof exports === 'object' ) {
1296  // CommonJS for Component
1297  module.exports = defineGetSize( require('desandro-get-style-property') );
1298} else {
1299  // browser global
1300  window.getSize = defineGetSize( window.getStyleProperty );
1301}
1302
1303})( window );
1304
1305/*!
1306 * docReady v1.0.4
1307 * Cross browser DOMContentLoaded event emitter
1308 * MIT license
1309 */
1310
1311/*jshint browser: true, strict: true, undef: true, unused: true*/
1312/*global define: false, require: false, module: false */
1313
1314( function( window ) {
1315
1316
1317
1318var document = window.document;
1319// collection of functions to be triggered on ready
1320var queue = [];
1321
1322function docReady( fn ) {
1323  // throw out non-functions
1324  if ( typeof fn !== 'function' ) {
1325    return;
1326  }
1327
1328  if ( docReady.isReady ) {
1329    // ready now, hit it
1330    fn();
1331  } else {
1332    // queue function when ready
1333    queue.push( fn );
1334  }
1335}
1336
1337docReady.isReady = false;
1338
1339// triggered on various doc ready events
1340function onReady( event ) {
1341  // bail if already triggered or IE8 document is not ready just yet
1342  var isIE8NotReady = event.type === 'readystatechange' && document.readyState !== 'complete';
1343  if ( docReady.isReady || isIE8NotReady ) {
1344    return;
1345  }
1346
1347  trigger();
1348}
1349
1350function trigger() {
1351  docReady.isReady = true;
1352  // process queue
1353  for ( var i=0, len = queue.length; i < len; i++ ) {
1354    var fn = queue[i];
1355    fn();
1356  }
1357}
1358
1359function defineDocReady( eventie ) {
1360  // trigger ready if page is ready
1361  if ( document.readyState === 'complete' ) {
1362    trigger();
1363  } else {
1364    // listen for events
1365    eventie.bind( document, 'DOMContentLoaded', onReady );
1366    eventie.bind( document, 'readystatechange', onReady );
1367    eventie.bind( window, 'load', onReady );
1368  }
1369
1370  return docReady;
1371}
1372
1373// transport
1374if ( typeof define === 'function' && define.amd ) {
1375  // AMD
1376  define( 'doc-ready/doc-ready',[ 'eventie/eventie' ], defineDocReady );
1377} else if ( typeof exports === 'object' ) {
1378  module.exports = defineDocReady( require('eventie') );
1379} else {
1380  // browser global
1381  window.docReady = defineDocReady( window.eventie );
1382}
1383
1384})( window );
1385
1386/**
1387 * matchesSelector v1.0.3
1388 * matchesSelector( element, '.selector' )
1389 * MIT license
1390 */
1391
1392/*jshint browser: true, strict: true, undef: true, unused: true */
1393/*global define: false, module: false */
1394
1395( function( ElemProto ) {
1396
1397  'use strict';
1398
1399  var matchesMethod = ( function() {
1400    // check for the standard method name first
1401    if ( ElemProto.matches ) {
1402      return 'matches';
1403    }
1404    // check un-prefixed
1405    if ( ElemProto.matchesSelector ) {
1406      return 'matchesSelector';
1407    }
1408    // check vendor prefixes
1409    var prefixes = [ 'webkit', 'moz', 'ms', 'o' ];
1410
1411    for ( var i=0, len = prefixes.length; i < len; i++ ) {
1412      var prefix = prefixes[i];
1413      var method = prefix + 'MatchesSelector';
1414      if ( ElemProto[ method ] ) {
1415        return method;
1416      }
1417    }
1418  })();
1419
1420  // ----- match ----- //
1421
1422  function match( elem, selector ) {
1423    return elem[ matchesMethod ]( selector );
1424  }
1425
1426  // ----- appendToFragment ----- //
1427
1428  function checkParent( elem ) {
1429    // not needed if already has parent
1430    if ( elem.parentNode ) {
1431      return;
1432    }
1433    var fragment = document.createDocumentFragment();
1434    fragment.appendChild( elem );
1435  }
1436
1437  // ----- query ----- //
1438
1439  // fall back to using QSA
1440  // thx @jonathantneal https://gist.github.com/3062955
1441  function query( elem, selector ) {
1442    // append to fragment if no parent
1443    checkParent( elem );
1444
1445    // match elem with all selected elems of parent
1446    var elems = elem.parentNode.querySelectorAll( selector );
1447    for ( var i=0, len = elems.length; i < len; i++ ) {
1448      // return true if match
1449      if ( elems[i] === elem ) {
1450        return true;
1451      }
1452    }
1453    // otherwise return false
1454    return false;
1455  }
1456
1457  // ----- matchChild ----- //
1458
1459  function matchChild( elem, selector ) {
1460    checkParent( elem );
1461    return match( elem, selector );
1462  }
1463
1464  // ----- matchesSelector ----- //
1465
1466  var matchesSelector;
1467
1468  if ( matchesMethod ) {
1469    // IE9 supports matchesSelector, but doesn't work on orphaned elems
1470    // check for that
1471    var div = document.createElement('div');
1472    var supportsOrphans = match( div, 'div' );
1473    matchesSelector = supportsOrphans ? match : matchChild;
1474  } else {
1475    matchesSelector = query;
1476  }
1477
1478  // transport
1479  if ( typeof define === 'function' && define.amd ) {
1480    // AMD
1481    define( 'matches-selector/matches-selector',[],function() {
1482      return matchesSelector;
1483    });
1484  } else if ( typeof exports === 'object' ) {
1485    module.exports = matchesSelector;
1486  }
1487  else {
1488    // browser global
1489    window.matchesSelector = matchesSelector;
1490  }
1491
1492})( Element.prototype );
1493
1494/**
1495 * Fizzy UI utils v1.0.1
1496 * MIT license
1497 */
1498
1499/*jshint browser: true, undef: true, unused: true, strict: true */
1500
1501( function( window, factory ) {
1502  /*global define: false, module: false, require: false */
1503  'use strict';
1504  // universal module definition
1505
1506  if ( typeof define == 'function' && define.amd ) {
1507    // AMD
1508    define( 'fizzy-ui-utils/utils',[
1509      'doc-ready/doc-ready',
1510      'matches-selector/matches-selector'
1511    ], function( docReady, matchesSelector ) {
1512      return factory( window, docReady, matchesSelector );
1513    });
1514  } else if ( typeof exports == 'object' ) {
1515    // CommonJS
1516    module.exports = factory(
1517      window,
1518      require('doc-ready'),
1519      require('desandro-matches-selector')
1520    );
1521  } else {
1522    // browser global
1523    window.fizzyUIUtils = factory(
1524      window,
1525      window.docReady,
1526      window.matchesSelector
1527    );
1528  }
1529
1530}( window, function factory( window, docReady, matchesSelector ) {
1531
1532
1533
1534var utils = {};
1535
1536// ----- extend ----- //
1537
1538// extends objects
1539utils.extend = function( a, b ) {
1540  for ( var prop in b ) {
1541    a[ prop ] = b[ prop ];
1542  }
1543  return a;
1544};
1545
1546// ----- modulo ----- //
1547
1548utils.modulo = function( num, div ) {
1549  return ( ( num % div ) + div ) % div;
1550};
1551
1552// ----- isArray ----- //
1553  
1554var objToString = Object.prototype.toString;
1555utils.isArray = function( obj ) {
1556  return objToString.call( obj ) == '[object Array]';
1557};
1558
1559// ----- makeArray ----- //
1560
1561// turn element or nodeList into an array
1562utils.makeArray = function( obj ) {
1563  var ary = [];
1564  if ( utils.isArray( obj ) ) {
1565    // use object if already an array
1566    ary = obj;
1567  } else if ( obj && typeof obj.length == 'number' ) {
1568    // convert nodeList to array
1569    for ( var i=0, len = obj.length; i < len; i++ ) {
1570      ary.push( obj[i] );
1571    }
1572  } else {
1573    // array of single index
1574    ary.push( obj );
1575  }
1576  return ary;
1577};
1578
1579// ----- indexOf ----- //
1580
1581// index of helper cause IE8
1582utils.indexOf = Array.prototype.indexOf ? function( ary, obj ) {
1583    return ary.indexOf( obj );
1584  } : function( ary, obj ) {
1585    for ( var i=0, len = ary.length; i < len; i++ ) {
1586      if ( ary[i] === obj ) {
1587        return i;
1588      }
1589    }
1590    return -1;
1591  };
1592
1593// ----- removeFrom ----- //
1594
1595utils.removeFrom = function( ary, obj ) {
1596  var index = utils.indexOf( ary, obj );
1597  if ( index != -1 ) {
1598    ary.splice( index, 1 );
1599  }
1600};
1601
1602// ----- isElement ----- //
1603
1604// http://stackoverflow.com/a/384380/182183
1605utils.isElement = ( typeof HTMLElement == 'function' || typeof HTMLElement == 'object' ) ?
1606  function isElementDOM2( obj ) {
1607    return obj instanceof HTMLElement;
1608  } :
1609  function isElementQuirky( obj ) {
1610    return obj && typeof obj == 'object' &&
1611      obj.nodeType == 1 && typeof obj.nodeName == 'string';
1612  };
1613
1614// ----- setText ----- //
1615
1616utils.setText = ( function() {
1617  var setTextProperty;
1618  function setText( elem, text ) {
1619    // only check setTextProperty once
1620    setTextProperty = setTextProperty || ( document.documentElement.textContent !== undefined ? 'textContent' : 'innerText' );
1621    elem[ setTextProperty ] = text;
1622  }
1623  return setText;
1624})();
1625
1626// ----- getParent ----- //
1627
1628utils.getParent = function( elem, selector ) {
1629  while ( elem != document.body ) {
1630    elem = elem.parentNode;
1631    if ( matchesSelector( elem, selector ) ) {
1632      return elem;
1633    }
1634  }
1635};
1636
1637// ----- getQueryElement ----- //
1638
1639// use element as selector string
1640utils.getQueryElement = function( elem ) {
1641  if ( typeof elem == 'string' ) {
1642    return document.querySelector( elem );
1643  }
1644  return elem;
1645};
1646
1647// ----- handleEvent ----- //
1648
1649// enable .ontype to trigger from .addEventListener( elem, 'type' )
1650utils.handleEvent = function( event ) {
1651  var method = 'on' + event.type;
1652  if ( this[ method ] ) {
1653    this[ method ]( event );
1654  }
1655};
1656
1657// ----- filterFindElements ----- //
1658
1659utils.filterFindElements = function( elems, selector ) {
1660  // make array of elems
1661  elems = utils.makeArray( elems );
1662  var ffElems = [];
1663
1664  for ( var i=0, len = elems.length; i < len; i++ ) {
1665    var elem = elems[i];
1666    // check that elem is an actual element
1667    if ( !utils.isElement( elem ) ) {
1668      continue;
1669    }
1670    // filter & find items if we have a selector
1671    if ( selector ) {
1672      // filter siblings
1673      if ( matchesSelector( elem, selector ) ) {
1674        ffElems.push( elem );
1675      }
1676      // find children
1677      var childElems = elem.querySelectorAll( selector );
1678      // concat childElems to filterFound array
1679      for ( var j=0, jLen = childElems.length; j < jLen; j++ ) {
1680        ffElems.push( childElems[j] );
1681      }
1682    } else {
1683      ffElems.push( elem );
1684    }
1685  }
1686
1687  return ffElems;
1688};
1689
1690// ----- debounceMethod ----- //
1691
1692utils.debounceMethod = function( _class, methodName, threshold ) {
1693  // original method
1694  var method = _class.prototype[ methodName ];
1695  var timeoutName = methodName + 'Timeout';
1696
1697  _class.prototype[ methodName ] = function() {
1698    var timeout = this[ timeoutName ];
1699    if ( timeout ) {
1700      clearTimeout( timeout );
1701    }
1702    var args = arguments;
1703
1704    var _this = this;
1705    this[ timeoutName ] = setTimeout( function() {
1706      method.apply( _this, args );
1707      delete _this[ timeoutName ];
1708    }, threshold || 100 );
1709  };
1710};
1711
1712// ----- htmlInit ----- //
1713
1714// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/
1715utils.toDashed = function( str ) {
1716  return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {
1717    return $1 + '-' + $2;
1718  }).toLowerCase();
1719};
1720
1721var console = window.console;
1722/**
1723 * allow user to initialize classes via .js-namespace class
1724 * htmlInit( Widget, 'widgetName' )
1725 * options are parsed from data-namespace-option attribute
1726 */
1727utils.htmlInit = function( WidgetClass, namespace ) {
1728  docReady( function() {
1729    var dashedNamespace = utils.toDashed( namespace );
1730    var elems = document.querySelectorAll( '.js-' + dashedNamespace );
1731    var dataAttr = 'data-' + dashedNamespace + '-options';
1732
1733    for ( var i=0, len = elems.length; i < len; i++ ) {
1734      var elem = elems[i];
1735      var attr = elem.getAttribute( dataAttr );
1736      var options;
1737      try {
1738        options = attr && JSON.parse( attr );
1739      } catch ( error ) {
1740        // log error, do not initialize
1741        if ( console ) {
1742          console.error( 'Error parsing ' + dataAttr + ' on ' +
1743            elem.nodeName.toLowerCase() + ( elem.id ? '#' + elem.id : '' ) + ': ' +
1744            error );
1745        }
1746        continue;
1747      }
1748      // initialize
1749      var instance = new WidgetClass( elem, options );
1750      // make available via $().data('layoutname')
1751      var jQuery = window.jQuery;
1752      if ( jQuery ) {
1753        jQuery.data( elem, namespace, instance );
1754      }
1755    }
1756  });
1757};
1758
1759// -----  ----- //
1760
1761return utils;
1762
1763}));
1764
1765/**
1766 * Outlayer Item
1767 */
1768
1769( function( window, factory ) {
1770  'use strict';
1771  // universal module definition
1772  if ( typeof define === 'function' && define.amd ) {
1773    // AMD
1774    define( 'outlayer/item',[
1775        'eventEmitter/EventEmitter',
1776        'get-size/get-size',
1777        'get-style-property/get-style-property',
1778        'fizzy-ui-utils/utils'
1779      ],
1780      function( EventEmitter, getSize, getStyleProperty, utils ) {
1781        return factory( window, EventEmitter, getSize, getStyleProperty, utils );
1782      }
1783    );
1784  } else if (typeof exports === 'object') {
1785    // CommonJS
1786    module.exports = factory(
1787      window,
1788      require('wolfy87-eventemitter'),
1789      require('get-size'),
1790      require('desandro-get-style-property'),
1791      require('fizzy-ui-utils')
1792    );
1793  } else {
1794    // browser global
1795    window.Outlayer = {};
1796    window.Outlayer.Item = factory(
1797      window,
1798      window.EventEmitter,
1799      window.getSize,
1800      window.getStyleProperty,
1801      window.fizzyUIUtils
1802    );
1803  }
1804
1805}( window, function factory( window, EventEmitter, getSize, getStyleProperty, utils ) {
1806'use strict';
1807
1808// ----- helpers ----- //
1809
1810var getComputedStyle = window.getComputedStyle;
1811var getStyle = getComputedStyle ?
1812  function( elem ) {
1813    return getComputedStyle( elem, null );
1814  } :
1815  function( elem ) {
1816    return elem.currentStyle;
1817  };
1818
1819
1820function isEmptyObj( obj ) {
1821  for ( var prop in obj ) {
1822    return false;
1823  }
1824  prop = null;
1825  return true;
1826}
1827
1828// -------------------------- CSS3 support -------------------------- //
1829
1830var transitionProperty = getStyleProperty('transition');
1831var transformProperty = getStyleProperty('transform');
1832var supportsCSS3 = transitionProperty && transformProperty;
1833var is3d = !!getStyleProperty('perspective');
1834
1835var transitionEndEvent = {
1836  WebkitTransition: 'webkitTransitionEnd',
1837  MozTransition: 'transitionend',
1838  OTransition: 'otransitionend',
1839  transition: 'transitionend'
1840}[ transitionProperty ];
1841
1842// properties that could have vendor prefix
1843var prefixableProperties = [
1844  'transform',
1845  'transition',
1846  'transitionDuration',
1847  'transitionProperty'
1848];
1849
1850// cache all vendor properties
1851var vendorProperties = ( function() {
1852  var cache = {};
1853  for ( var i=0, len = prefixableProperties.length; i < len; i++ ) {
1854    var prop = prefixableProperties[i];
1855    var supportedProp = getStyleProperty( prop );
1856    if ( supportedProp && supportedProp !== prop ) {
1857      cache[ prop ] = supportedProp;
1858    }
1859  }
1860  return cache;
1861})();
1862
1863// -------------------------- Item -------------------------- //
1864
1865function Item( element, layout ) {
1866  if ( !element ) {
1867    return;
1868  }
1869
1870  this.element = element;
1871  // parent layout class, i.e. Masonry, Isotope, or Packery
1872  this.layout = layout;
1873  this.position = {
1874    x: 0,
1875    y: 0
1876  };
1877
1878  this._create();
1879}
1880
1881// inherit EventEmitter
1882utils.extend( Item.prototype, EventEmitter.prototype );
1883
1884Item.prototype._create = function() {
1885  // transition objects
1886  this._transn = {
1887    ingProperties: {},
1888    clean: {},
1889    onEnd: {}
1890  };
1891
1892  this.css({
1893    position: 'absolute'
1894  });
1895};
1896
1897// trigger specified handler for event type
1898Item.prototype.handleEvent = function( event ) {
1899  var method = 'on' + event.type;
1900  if ( this[ method ] ) {
1901    this[ method ]( event );
1902  }
1903};
1904
1905Item.prototype.getSize = function() {
1906  this.size = getSize( this.element );
1907};
1908
1909/**
1910 * apply CSS styles to element
1911 * @param {Object} style
1912 */
1913Item.prototype.css = function( style ) {
1914  var elemStyle = this.element.style;
1915
1916  for ( var prop in style ) {
1917    // use vendor property if available
1918    var supportedProp = vendorProperties[ prop ] || prop;
1919    elemStyle[ supportedProp ] = style[ prop ];
1920  }
1921};
1922
1923 // measure position, and sets it
1924Item.prototype.getPosition = function() {
1925  var style = getStyle( this.element );
1926  var layoutOptions = this.layout.options;
1927  var isOriginLeft = layoutOptions.isOriginLeft;
1928  var isOriginTop = layoutOptions.isOriginTop;
1929  var xValue = style[ isOriginLeft ? 'left' : 'right' ];
1930  var yValue = style[ isOriginTop ? 'top' : 'bottom' ];
1931  // convert percent to pixels
1932  var layoutSize = this.layout.size;
1933  var x = xValue.indexOf('%') != -1 ?
1934    ( parseFloat( xValue ) / 100 ) * layoutSize.width : parseInt( xValue, 10 );
1935  var y = yValue.indexOf('%') != -1 ?
1936    ( parseFloat( yValue ) / 100 ) * layoutSize.height : parseInt( yValue, 10 );
1937
1938  // clean up 'auto' or other non-integer values
1939  x = isNaN( x ) ? 0 : x;
1940  y = isNaN( y ) ? 0 : y;
1941  // remove padding from measurement
1942  x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight;
1943  y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom;
1944
1945  this.position.x = x;
1946  this.position.y = y;
1947};
1948
1949// set settled position, apply padding
1950Item.prototype.layoutPosition = function() {
1951  var layoutSize = this.layout.size;
1952  var layoutOptions = this.layout.options;
1953  var style = {};
1954
1955  // x
1956  var xPadding = layoutOptions.isOriginLeft ? 'paddingLeft' : 'paddingRight';
1957  var xProperty = layoutOptions.isOriginLeft ? 'left' : 'right';
1958  var xResetProperty = layoutOptions.isOriginLeft ? 'right' : 'left';
1959
1960  var x = this.position.x + layoutSize[ xPadding ];
1961  // set in percentage or pixels
1962  style[ xProperty ] = this.getXValue( x );
1963  // reset other property
1964  style[ xResetProperty ] = '';
1965
1966  // y
1967  var yPadding = layoutOptions.isOriginTop ? 'paddingTop' : 'paddingBottom';
1968  var yProperty = layoutOptions.isOriginTop ? 'top' : 'bottom';
1969  var yResetProperty = layoutOptions.isOriginTop ? 'bottom' : 'top';
1970
1971  var y = this.position.y + layoutSize[ yPadding ];
1972  // set in percentage or pixels
1973  style[ yProperty ] = this.getYValue( y );
1974  // reset other property
1975  style[ yResetProperty ] = '';
1976
1977  this.css( style );
1978  this.emitEvent( 'layout', [ this ] );
1979};
1980
1981Item.prototype.getXValue = function( x ) {
1982  var layoutOptions = this.layout.options;
1983  return layoutOptions.percentPosition && !layoutOptions.isHorizontal ?
1984    ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px';
1985};
1986
1987Item.prototype.getYValue = function( y ) {
1988  var layoutOptions = this.layout.options;
1989  return layoutOptions.percentPosition && layoutOptions.isHorizontal ?
1990    ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px';
1991};
1992
1993
1994Item.prototype._transitionTo = function( x, y ) {
1995  this.getPosition();
1996  // get current x & y from top/left
1997  var curX = this.position.x;
1998  var curY = this.position.y;
1999
2000  var compareX = parseInt( x, 10 );
2001  var compareY = parseInt( y, 10 );
2002  var didNotMove = compareX === this.position.x && compareY === this.position.y;
2003
2004  // save end position
2005  this.setPosition( x, y );
2006
2007  // if did not move and not transitioning, just go to layout
2008  if ( didNotMove && !this.isTransitioning ) {
2009    this.layoutPosition();
2010    return;
2011  }
2012
2013  var transX = x - curX;
2014  var transY = y - curY;
2015  var transitionStyle = {};
2016  transitionStyle.transform = this.getTranslate( transX, transY );
2017
2018  this.transition({
2019    to: transitionStyle,
2020    onTransitionEnd: {
2021      transform: this.layoutPosition
2022    },
2023    isCleaning: true
2024  });
2025};
2026
2027Item.prototype.getTranslate = function( x, y ) {
2028  // flip cooridinates if origin on right or bottom
2029  var layoutOptions = this.layout.options;
2030  x = layoutOptions.isOriginLeft ? x : -x;
2031  y = layoutOptions.isOriginTop ? y : -y;
2032
2033  if ( is3d ) {
2034    return 'translate3d(' + x + 'px, ' + y + 'px, 0)';
2035  }
2036
2037  return 'translate(' + x + 'px, ' + y + 'px)';
2038};
2039
2040// non transition + transform support
2041Item.prototype.goTo = function( x, y ) {
2042  this.setPosition( x, y );
2043  this.layoutPosition();
2044};
2045
2046// use transition and transforms if supported
2047Item.prototype.moveTo = supportsCSS3 ?
2048  Item.prototype._transitionTo : Item.prototype.goTo;
2049
2050Item.prototype.setPosition = function( x, y ) {
2051  this.position.x = parseInt( x, 10 );
2052  this.position.y = parseInt( y, 10 );
2053};
2054
2055// ----- transition ----- //
2056
2057/**
2058 * @param {Object} style - CSS
2059 * @param {Function} onTransitionEnd
2060 */
2061
2062// non transition, just trigger callback
2063Item.prototype._nonTransition = function( args ) {
2064  this.css( args.to );
2065  if ( args.isCleaning ) {
2066    this._removeStyles( args.to );
2067  }
2068  for ( var prop in args.onTransitionEnd ) {
2069    args.onTransitionEnd[ prop ].call( this );
2070  }
2071};
2072
2073/**
2074 * proper transition
2075 * @param {Object} args - arguments
2076 *   @param {Object} to - style to transition to
2077 *   @param {Object} from - style to start transition from
2078 *   @param {Boolean} isCleaning - removes transition styles after transition
2079 *   @param {Function} onTransitionEnd - callback
2080 */
2081Item.prototype._transition = function( args ) {
2082  // redirect to nonTransition if no transition duration
2083  if ( !parseFloat( this.layout.options.transitionDuration ) ) {
2084    this._nonTransition( args );
2085    return;
2086  }
2087
2088  var _transition = this._transn;
2089  // keep track of onTransitionEnd callback by css property
2090  for ( var prop in args.onTransitionEnd ) {
2091    _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ];
2092  }
2093  // keep track of properties that are transitioning
2094  for ( prop in args.to ) {
2095    _transition.ingProperties[ prop ] = true;
2096    // keep track of properties to clean up when transition is done
2097    if ( args.isCleaning ) {
2098      _transition.clean[ prop ] = true;
2099    }
2100  }
2101
2102  // set from styles
2103  if ( args.from ) {
2104    this.css( args.from );
2105    // force redraw. http://blog.alexmaccaw.com/css-transitions
2106    var h = this.element.offsetHeight;
2107    // hack for JSHint to hush about unused var
2108    h = null;
2109  }
2110  // enable transition
2111  this.enableTransition( args.to );
2112  // set styles that are transitioning
2113  this.css( args.to );
2114
2115  this.isTransitioning = true;
2116
2117};
2118
2119// dash before all cap letters, including first for
2120// WebkitTransform => -webkit-transform
2121function toDashedAll( str ) {
2122  return str.replace( /([A-Z])/g, function( $1 ) {
2123    return '-' + $1.toLowerCase();
2124  });
2125}
2126
2127var transitionProps = 'opacity,' +
vendor: 11,190 bytes, lines 2128-2574
2128  toDashedAll( vendorProperties.transform || 'transform' );
2129
2130Item.prototype.enableTransition = function(/* style */) {
2131  // HACK changing transitionProperty during a transition
2132  // will cause transition to jump
2133  if ( this.isTransitioning ) {
2134    return;
2135  }
2136
2137  // make `transition: foo, bar, baz` from style object
2138  // HACK un-comment this when enableTransition can work
2139  // while a transition is happening
2140  // var transitionValues = [];
2141  // for ( var prop in style ) {
2142  //   // dash-ify camelCased properties like WebkitTransition
2143  //   prop = vendorProperties[ prop ] || prop;
2144  //   transitionValues.push( toDashedAll( prop ) );
2145  // }
2146  // enable transition styles
2147  this.css({
2148    transitionProperty: transitionProps,
2149    transitionDuration: this.layout.options.transitionDuration
2150  });
2151  // listen for transition end event
2152  this.element.addEventListener( transitionEndEvent, this, false );
2153};
2154
2155Item.prototype.transition = Item.prototype[ transitionProperty ? '_transition' : '_nonTransition' ];
2156
2157// ----- events ----- //
2158
2159Item.prototype.onwebkitTransitionEnd = function( event ) {
2160  this.ontransitionend( event );
2161};
2162
2163Item.prototype.onotransitionend = function( event ) {
2164  this.ontransitionend( event );
2165};
2166
2167// properties that I munge to make my life easier
2168var dashedVendorProperties = {
2169  '-webkit-transform': 'transform',
2170  '-moz-transform': 'transform',
2171  '-o-transform': 'transform'
2172};
2173
2174Item.prototype.ontransitionend = function( event ) {
2175  // disregard bubbled events from children
2176  if ( event.target !== this.element ) {
2177    return;
2178  }
2179  var _transition = this._transn;
2180  // get property name of transitioned property, convert to prefix-free
2181  var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName;
2182
2183  // remove property that has completed transitioning
2184  delete _transition.ingProperties[ propertyName ];
2185  // check if any properties are still transitioning
2186  if ( isEmptyObj( _transition.ingProperties ) ) {
2187    // all properties have completed transitioning
2188    this.disableTransition();
2189  }
2190  // clean style
2191  if ( propertyName in _transition.clean ) {
2192    // clean up style
2193    this.element.style[ event.propertyName ] = '';
2194    delete _transition.clean[ propertyName ];
2195  }
2196  // trigger onTransitionEnd callback
2197  if ( propertyName in _transition.onEnd ) {
2198    var onTransitionEnd = _transition.onEnd[ propertyName ];
2199    onTransitionEnd.call( this );
2200    delete _transition.onEnd[ propertyName ];
2201  }
2202
2203  this.emitEvent( 'transitionEnd', [ this ] );
2204};
2205
2206Item.prototype.disableTransition = function() {
2207  this.removeTransitionStyles();
2208  this.element.removeEventListener( transitionEndEvent, this, false );
2209  this.isTransitioning = false;
2210};
2211
2212/**
2213 * removes style property from element
2214 * @param {Object} style
2215**/
2216Item.prototype._removeStyles = function( style ) {
2217  // clean up transition styles
2218  var cleanStyle = {};
2219  for ( var prop in style ) {
2220    cleanStyle[ prop ] = '';
2221  }
2222  this.css( cleanStyle );
2223};
2224
2225var cleanTransitionStyle = {
2226  transitionProperty: '',
2227  transitionDuration: ''
2228};
2229
2230Item.prototype.removeTransitionStyles = function() {
2231  // remove transition
2232  this.css( cleanTransitionStyle );
2233};
2234
2235// ----- show/hide/remove ----- //
2236
2237// remove element from DOM
2238Item.prototype.removeElem = function() {
2239  this.element.parentNode.removeChild( this.element );
2240  // remove display: none
2241  this.css({ display: '' });
2242  this.emitEvent( 'remove', [ this ] );
2243};
2244
2245Item.prototype.remove = function() {
2246  // just remove element if no transition support or no transition
2247  if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) {
2248    this.removeElem();
2249    return;
2250  }
2251
2252  // start transition
2253  var _this = this;
2254  this.once( 'transitionEnd', function() {
2255    _this.removeElem();
2256  });
2257  this.hide();
2258};
2259
2260Item.prototype.reveal = function() {
2261  delete this.isHidden;
2262  // remove display: none
2263  this.css({ display: '' });
2264
2265  var options = this.layout.options;
2266
2267  var onTransitionEnd = {};
2268  var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle');
2269  onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd;
2270
2271  this.transition({
2272    from: options.hiddenStyle,
2273    to: options.visibleStyle,
2274    isCleaning: true,
2275    onTransitionEnd: onTransitionEnd
2276  });
2277};
2278
2279Item.prototype.onRevealTransitionEnd = function() {
2280  // check if still visible
2281  // during transition, item may have been hidden
2282  if ( !this.isHidden ) {
2283    this.emitEvent('reveal');
2284  }
2285};
2286
2287/**
2288 * get style property use for hide/reveal transition end
2289 * @param {String} styleProperty - hiddenStyle/visibleStyle
2290 * @returns {String}
2291 */
2292Item.prototype.getHideRevealTransitionEndProperty = function( styleProperty ) {
2293  var optionStyle = this.layout.options[ styleProperty ];
2294  // use opacity
2295  if ( optionStyle.opacity ) {
2296    return 'opacity';
2297  }
2298  // get first property
2299  for ( var prop in optionStyle ) {
2300    return prop;
2301  }
2302};
2303
2304Item.prototype.hide = function() {
2305  // set flag
2306  this.isHidden = true;
2307  // remove display: none
2308  this.css({ display: '' });
2309
2310  var options = this.layout.options;
2311
2312  var onTransitionEnd = {};
2313  var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle');
2314  onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd;
2315
2316  this.transition({
2317    from: options.visibleStyle,
2318    to: options.hiddenStyle,
2319    // keep hidden stuff hidden
2320    isCleaning: true,
2321    onTransitionEnd: onTransitionEnd
2322  });
2323};
2324
2325Item.prototype.onHideTransitionEnd = function() {
2326  // check if still hidden
2327  // during transition, item may have been un-hidden
2328  if ( this.isHidden ) {
2329    this.css({ display: 'none' });
2330    this.emitEvent('hide');
2331  }
2332};
2333
2334Item.prototype.destroy = function() {
2335  this.css({
2336    position: '',
2337    left: '',
2338    right: '',
2339    top: '',
2340    bottom: '',
2341    transition: '',
2342    transform: ''
2343  });
2344};
2345
2346return Item;
2347
2348}));
2349
2350/*!
2351 * Outlayer v1.4.2
2352 * the brains and guts of a layout library
2353 * MIT license
2354 */
2355
2356( function( window, factory ) {
2357  'use strict';
2358  // universal module definition
2359
2360  if ( typeof define == 'function' && define.amd ) {
2361    // AMD
2362    define( 'outlayer/outlayer',[
2363        'eventie/eventie',
2364        'eventEmitter/EventEmitter',
2365        'get-size/get-size',
2366        'fizzy-ui-utils/utils',
2367        './item'
2368      ],
2369      function( eventie, EventEmitter, getSize, utils, Item ) {
2370        return factory( window, eventie, EventEmitter, getSize, utils, Item);
2371      }
2372    );
2373  } else if ( typeof exports == 'object' ) {
2374    // CommonJS
2375    module.exports = factory(
2376      window,
2377      require('eventie'),
2378      require('wolfy87-eventemitter'),
2379      require('get-size'),
2380      require('fizzy-ui-utils'),
2381      require('./item')
2382    );
2383  } else {
2384    // browser global
2385    window.Outlayer = factory(
2386      window,
2387      window.eventie,
2388      window.EventEmitter,
2389      window.getSize,
2390      window.fizzyUIUtils,
2391      window.Outlayer.Item
2392    );
2393  }
2394
2395}( window, function factory( window, eventie, EventEmitter, getSize, utils, Item ) {
2396'use strict';
2397
2398// ----- vars ----- //
2399
2400var console = window.console;
2401var jQuery = window.jQuery;
2402var noop = function() {};
2403
2404// -------------------------- Outlayer -------------------------- //
2405
2406// globally unique identifiers
2407var GUID = 0;
2408// internal store of all Outlayer intances
2409var instances = {};
2410
2411
2412/**
2413 * @param {Element, String} element
2414 * @param {Object} options
2415 * @constructor
2416 */
2417function Outlayer( element, options ) {
2418  var queryElement = utils.getQueryElement( element );
2419  if ( !queryElement ) {
2420    if ( console ) {
2421      console.error( 'Bad element for ' + this.constructor.namespace +
2422        ': ' + ( queryElement || element ) );
2423    }
2424    return;
2425  }
2426  this.element = queryElement;
2427  // add jQuery
2428  if ( jQuery ) {
2429    this.$element = jQuery( this.element );
2430  }
2431
2432  // options
2433  this.options = utils.extend( {}, this.constructor.defaults );
2434  this.option( options );
2435
2436  // add id for Outlayer.getFromElement
2437  var id = ++GUID;
2438  this.element.outlayerGUID = id; // expando
2439  instances[ id ] = this; // associate via id
2440
2441  // kick it off
2442  this._create();
2443
2444  if ( this.options.isInitLayout ) {
2445    this.layout();
2446  }
2447}
2448
2449// settings are for internal use only
2450Outlayer.namespace = 'outlayer';
2451Outlayer.Item = Item;
2452
2453// default options
2454Outlayer.defaults = {
2455  containerStyle: {
2456    position: 'relative'
2457  },
2458  isInitLayout: true,
2459  isOriginLeft: true,
2460  isOriginTop: true,
2461  isResizeBound: true,
2462  isResizingContainer: true,
2463  // item options
2464  transitionDuration: '0.4s',
2465  hiddenStyle: {
2466    opacity: 0,
2467    transform: 'scale(0.001)'
2468  },
2469  visibleStyle: {
2470    opacity: 1,
2471    transform: 'scale(1)'
2472  }
2473};
2474
2475// inherit EventEmitter
2476utils.extend( Outlayer.prototype, EventEmitter.prototype );
2477
2478/**
2479 * set options
2480 * @param {Object} opts
2481 */
2482Outlayer.prototype.option = function( opts ) {
2483  utils.extend( this.options, opts );
2484};
2485
2486Outlayer.prototype._create = function() {
2487  // get items from children
2488  this.reloadItems();
2489  // elements that affect layout, but are not laid out
2490  this.stamps = [];
2491  this.stamp( this.options.stamp );
2492  // set container style
2493  utils.extend( this.element.style, this.options.containerStyle );
2494
2495  // bind resize method
2496  if ( this.options.isResizeBound ) {
2497    this.bindResize();
2498  }
2499};
2500
2501// goes through all children again and gets bricks in proper order
2502Outlayer.prototype.reloadItems = function() {
2503  // collection of item elements
2504  this.items = this._itemize( this.element.children );
2505};
2506
2507
2508/**
2509 * turn elements into Outlayer.Items to be used in layout
2510 * @param {Array or NodeList or HTMLElement} elems
2511 * @returns {Array} items - collection of new Outlayer Items
2512 */
2513Outlayer.prototype._itemize = function( elems ) {
2514
2515  var itemElems = this._filterFindItemElements( elems );
2516  var Item = this.constructor.Item;
2517
2518  // create new Outlayer Items for collection
2519  var items = [];
2520  for ( var i=0, len = itemElems.length; i < len; i++ ) {
2521    var elem = itemElems[i];
2522    var item = new Item( elem, this );
2523    items.push( item );
2524  }
2525
2526  return items;
2527};
2528
2529/**
2530 * get item elements to be used in layout
2531 * @param {Array or NodeList or HTMLElement} elems
2532 * @returns {Array} items - item elements
2533 */
2534Outlayer.prototype._filterFindItemElements = function( elems ) {
2535  return utils.filterFindElements( elems, this.options.itemSelector );
2536};
2537
2538/**
2539 * getter method for getting item elements
2540 * @returns {Array} elems - collection of item elements
2541 */
2542Outlayer.prototype.getItemElements = function() {
2543  var elems = [];
2544  for ( var i=0, len = this.items.length; i < len; i++ ) {
2545    elems.push( this.items[i].element );
2546  }
2547  return elems;
2548};
2549
2550// ----- init & layout ----- //
2551
2552/**
2553 * lays out all items
2554 */
2555Outlayer.prototype.layout = function() {
2556  this._resetLayout();
2557  this._manageStamps();
2558
2559  // don't animate first layout
2560  var isInstant = this.options.isLayoutInstant !== undefined ?
2561    this.options.isLayoutInstant : !this._isLayoutInited;
2562  this.layoutItems( this.items, isInstant );
2563
2564  // flag for initalized
2565  this._isLayoutInited = true;
2566};
2567
2568// _init is alias for layout
2569Outlayer.prototype._init = Outlayer.prototype.layout;
2570
2571/**
2572 * logic before any new layout
2573 */
2574Outlayer.prototype._resetLayout = function() {
2575  this.getSize();
2576};
2577
2578
2579Outlayer.prototype.getSize = function() {
2580  this.size = getSize( this.element );
2581};
2582
2583/**
2584 * get measurement from option, for columnWidth, rowHeight, gutter
2585 * if option is String -> get element from selector string, & get size of element
2586 * if option is Element -> get size of element
2587 * else use option as a number
2588 *
2589 * @param {String} measurement
2590 * @param {String} size - width or height
2591 * @private
2592 */
2593Outlayer.prototype._getMeasurement = function( measurement, size ) {
2594  var option = this.options[ measurement ];
2595  var elem;
2596  if ( !option ) {
2597    // default to 0
2598    this[ measurement ] = 0;
2599  } else {
2600    // use option as an element
2601    if ( typeof option === 'string' ) {
2602      elem = this.element.querySelector( option );
2603    } else if ( utils.isElement( option ) ) {
2604      elem = option;
2605    }
2606    // use size of element, if element
2607    this[ measurement ] = elem ? getSize( elem )[ size ] : option;
2608  }
2609};
2610
2611/**
2612 * layout a collection of item elements
2613 * @api public
2614 */
2615Outlayer.prototype.layoutItems = function( items, isInstant ) {
2616  items = this._getItemsForLayout( items );
2617
2618  this._layoutItems( items, isInstant );
2619
2620  this._postLayout();
2621};
2622
2623/**
2624 * get the items to be laid out
2625 * you may want to skip over some items
2626 * @param {Array} items
2627 * @returns {Array} items
2628 */
2629Outlayer.prototype._getItemsForLayout = function( items ) {
2630  var layoutItems = [];
2631  for ( var i=0, len = items.length; i < len; i++ ) {
2632    var item = items[i];
2633    if ( !item.isIgnored ) {
2634      layoutItems.push( item );
2635    }
2636  }
2637  return layoutItems;
2638};
2639
2640/**
2641 * layout items
2642 * @param {Array} items
2643 * @param {Boolean} isInstant
2644 */
2645Outlayer.prototype._layoutItems = function( items, isInstant ) {
2646  this._emitCompleteOnItems( 'layout', items );
2647
2648  if ( !items || !items.length ) {
2649    // no items, emit event with empty array
2650    return;
2651  }
2652
2653  var queue = [];
2654
2655  for ( var i=0, len = items.length; i < len; i++ ) {
2656    var item = items[i];
2657    // get x/y object from method
2658    var position = this._getItemLayoutPosition( item );
2659    // enqueue
2660    position.item = item;
2661    position.isInstant = isInstant || item.isLayoutInstant;
2662    queue.push( position );
2663  }
2664
2665  this._processLayoutQueue( queue );
2666};
2667
2668/**
2669 * get item layout position
2670 * @param {Outlayer.Item} item
2671 * @returns {Object} x and y position
2672 */
2673Outlayer.prototype._getItemLayoutPosition = function( /* item */ ) {
2674  return {
2675    x: 0,
2676    y: 0
2677  };
2678};
2679
2680/**
2681 * iterate over array and position each item
2682 * Reason being - separating this logic prevents 'layout invalidation'
2683 * thx @paul_irish
2684 * @param {Array} queue
2685 */
2686Outlayer.prototype._processLayoutQueue = function( queue ) {
2687  for ( var i=0, len = queue.length; i < len; i++ ) {
2688    var obj = queue[i];
2689    this._positionItem( obj.item, obj.x, obj.y, obj.isInstant );
2690  }
2691};
2692
2693/**
2694 * Sets position of item in DOM
2695 * @param {Outlayer.Item} item
2696 * @param {Number} x - horizontal position
2697 * @param {Number} y - vertical position
2698 * @param {Boolean} isInstant - disables transitions
2699 */
2700Outlayer.prototype._positionItem = function( item, x, y, isInstant ) {
2701  if ( isInstant ) {
2702    // if not transition, just set CSS
2703    item.goTo( x, y );
2704  } else {
2705    item.moveTo( x, y );
2706  }
2707};
2708
2709/**
2710 * Any logic you want to do after each layout,
2711 * i.e. size the container
2712 */
2713Outlayer.prototype._postLayout = function() {
2714  this.resizeContainer();
2715};
2716
2717Outlayer.prototype.resizeContainer = function() {
2718  if ( !this.options.isResizingContainer ) {
2719    return;
2720  }
2721  var size = this._getContainerSize();
2722  if ( size ) {
2723    this._setContainerMeasure( size.width, true );
2724    this._setContainerMeasure( size.height, false );
2725  }
2726};
2727
2728/**
2729 * Sets width or height of container if returned
2730 * @returns {Object} size
2731 *   @param {Number} width
2732 *   @param {Number} height
2733 */
2734Outlayer.prototype._getContainerSize = noop;
2735
2736/**
2737 * @param {Number} measure - size of width or height
2738 * @param {Boolean} isWidth
2739 */
2740Outlayer.prototype._setContainerMeasure = function( measure, isWidth ) {
2741  if ( measure === undefined ) {
2742    return;
2743  }
2744
2745  var elemSize = this.size;
2746  // add padding and border width if border box
2747  if ( elemSize.isBorderBox ) {
2748    measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight +
2749      elemSize.borderLeftWidth + elemSize.borderRightWidth :
2750      elemSize.paddingBottom + elemSize.paddingTop +
2751      elemSize.borderTopWidth + elemSize.borderBottomWidth;
2752  }
2753
2754  measure = Math.max( measure, 0 );
2755  this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px';
2756};
2757
2758/**
2759 * emit eventComplete on a collection of items events
2760 * @param {String} eventName
2761 * @param {Array} items - Outlayer.Items
2762 */
2763Outlayer.prototype._emitCompleteOnItems = function( eventName, items ) {
2764  var _this = this;
2765  function onComplete() {
2766    _this.dispatchEvent( eventName + 'Complete', null, [ items ] );
2767  }
2768
2769  var count = items.length;
2770  if ( !items || !count ) {
2771    onComplete();
2772    return;
2773  }
2774
2775  var doneCount = 0;
2776  function tick() {
2777    doneCount++;
2778    if ( doneCount === count ) {
2779      onComplete();
2780    }
2781  }
2782
2783  // bind callback
2784  for ( var i=0, len = items.length; i < len; i++ ) {
2785    var item = items[i];
2786    item.once( eventName, tick );
2787  }
2788};
2789
2790/**
2791 * emits events via eventEmitter and jQuery events
2792 * @param {String} type - name of event
2793 * @param {Event} event - original event
2794 * @param {Array} args - extra arguments
2795 */
2796Outlayer.prototype.dispatchEvent = function( type, event, args ) {
2797  // add original event to arguments
2798  var emitArgs = event ? [ event ].concat( args ) : args;
2799  this.emitEvent( type, emitArgs );
2800
2801  if ( jQuery ) {
2802    // set this.$element
2803    this.$element = this.$element || jQuery( this.element );
2804    if ( event ) {
2805      // create jQuery event
2806      var $event = jQuery.Event( event );
2807      $event.type = type;
2808      this.$element.trigger( $event, args );
2809    } else {
2810      // just trigger with type if no event available
2811      this.$element.trigger( type, args );
2812    }
2813  }
2814};
2815
2816// -------------------------- ignore & stamps -------------------------- //
2817
2818
2819/**
2820 * keep item in collection, but do not lay it out
2821 * ignored items do not get skipped in layout
2822 * @param {Element} elem
2823 */
2824Outlayer.prototype.ignore = function( elem ) {
2825  var item = this.getItem( elem );
2826  if ( item ) {
2827    item.isIgnored = true;
2828  }
2829};
2830
2831/**
2832 * return item to layout collection
2833 * @param {Element} elem
2834 */
2835Outlayer.prototype.unignore = function( elem ) {
2836  var item = this.getItem( elem );
2837  if ( item ) {
2838    delete item.isIgnored;
2839  }
2840};
2841
2842/**
2843 * adds elements to stamps
2844 * @param {NodeList, Array, Element, or String} elems
2845 */
2846Outlayer.prototype.stamp = function( elems ) {
2847  elems = this._find( elems );
2848  if ( !elems ) {
2849    return;
2850  }
2851
2852  this.stamps = this.stamps.concat( elems );
2853  // ignore
2854  for ( var i=0, len = elems.length; i < len; i++ ) {
2855    var elem = elems[i];
2856    this.ignore( elem );
2857  }
2858};
2859
2860/**
2861 * removes elements to stamps
2862 * @param {NodeList, Array, or Element} elems
2863 */
2864Outlayer.prototype.unstamp = function( elems ) {
2865  elems = this._find( elems );
2866  if ( !elems ){
2867    return;
2868  }
2869
2870  for ( var i=0, len = elems.length; i < len; i++ ) {
2871    var elem = elems[i];
2872    // filter out removed stamp elements
2873    utils.removeFrom( this.stamps, elem );
2874    this.unignore( elem );
2875  }
2876
2877};
2878
2879/**
2880 * finds child elements
2881 * @param {NodeList, Array, Element, or String} elems
2882 * @returns {Array} elems
2883 */
2884Outlayer.prototype._find = function( elems ) {
2885  if ( !elems ) {
2886    return;
2887  }
2888  // if string, use argument as selector string
2889  if ( typeof elems === 'string' ) {
2890    elems = this.element.querySelectorAll( elems );
2891  }
2892  elems = utils.makeArray( elems );
2893  return elems;
2894};
2895
2896Outlayer.prototype._manageStamps = function() {
2897  if ( !this.stamps || !this.stamps.length ) {
2898    return;
2899  }
2900
2901  this._getBoundingRect();
2902
2903  for ( var i=0, len = this.stamps.length; i < len; i++ ) {
2904    var stamp = this.stamps[i];
2905    this._manageStamp( stamp );
2906  }
2907};
2908
2909// update boundingLeft / Top
2910Outlayer.prototype._getBoundingRect = function() {
2911  // get bounding rect for container element
2912  var boundingRect = this.element.getBoundingClientRect();
2913  var size = this.size;
2914  this._boundingRect = {
2915    left: boundingRect.left + size.paddingLeft + size.borderLeftWidth,
2916    top: boundingRect.top + size.paddingTop + size.borderTopWidth,
2917    right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ),
2918    bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth )
2919  };
2920};
2921
2922/**
2923 * @param {Element} stamp
2924**/
2925Outlayer.prototype._manageStamp = noop;
2926
2927/**
2928 * get x/y position of element relative to container element
2929 * @param {Element} elem
2930 * @returns {Object} offset - has left, top, right, bottom
2931 */
2932Outlayer.prototype._getElementOffset = function( elem ) {
2933  var boundingRect = elem.getBoundingClientRect();
2934  var thisRect = this._boundingRect;
2935  var size = getSize( elem );
2936  var offset = {
2937    left: boundingRect.left - thisRect.left - size.marginLeft,
2938    top: boundingRect.top - thisRect.top - size.marginTop,
2939    right: thisRect.right - boundingRect.right - size.marginRight,
2940    bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom
2941  };
2942  return offset;
2943};
2944
2945// -------------------------- resize -------------------------- //
2946
2947// enable event handlers for listeners
2948// i.e. resize -> onresize
2949Outlayer.prototype.handleEvent = function( event ) {
2950  var method = 'on' + event.type;
2951  if ( this[ method ] ) {
2952    this[ method ]( event );
2953  }
2954};
2955
2956/**
2957 * Bind layout to window resizing
2958 */
2959Outlayer.prototype.bindResize = function() {
2960  // bind just one listener
2961  if ( this.isResizeBound ) {
2962    return;
2963  }
2964  eventie.bind( window, 'resize', this );
2965  this.isResizeBound = true;
2966};
2967
2968/**
2969 * Unbind layout to window resizing
2970 */
2971Outlayer.prototype.unbindResize = function() {
2972  if ( this.isResizeBound ) {
2973    eventie.unbind( window, 'resize', this );
2974  }
2975  this.isResizeBound = false;
2976};
2977
2978// original debounce by John Hann
2979// http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
2980
2981// this fires every resize
2982Outlayer.prototype.onresize = function() {
2983  if ( this.resizeTimeout ) {
2984    clearTimeout( this.resizeTimeout );
2985  }
2986
2987  var _this = this;
2988  function delayed() {
2989    _this.resize();
2990    delete _this.resizeTimeout;
2991  }
2992
2993  this.resizeTimeout = setTimeout( delayed, 100 );
2994};
2995
2996// debounced, layout on resize
2997Outlayer.prototype.resize = function() {
2998  // don't trigger if size did not change
2999  // or if resize was unbound. See #9
3000  if ( !this.isResizeBound || !this.needsResizeLayout() ) {
3001    return;
3002  }
3003
3004  this.layout();
3005};
3006
3007/**
3008 * check if layout is needed post layout
3009 * @returns Boolean
3010 */
3011Outlayer.prototype.needsResizeLayout = function() {
3012  var size = getSize( this.element );
3013  // check that this.size and size are there
3014  // IE8 triggers resize on body size change, so they might not be
3015  var hasSizes = this.size && size;
3016  return hasSizes && size.innerWidth !== this.size.innerWidth;
3017};
3018
3019// -------------------------- methods -------------------------- //
3020
3021/**
3022 * add items to Outlayer instance
3023 * @param {Array or NodeList or Element} elems
3024 * @returns {Array} items - Outlayer.Items
3025**/
3026Outlayer.prototype.addItems = function( elems ) {
3027  var items = this._itemize( elems );
3028  // add items to collection
3029  if ( items.length ) {
3030    this.items = this.items.concat( items );
3031  }
3032  return items;
3033};
3034
3035/**
3036 * Layout newly-appended item elements
3037 * @param {Array or NodeList or Element} elems
3038 */
3039Outlayer.prototype.appended = function( elems ) {
3040  var items = this.addItems( elems );
3041  if ( !items.length ) {
3042    return;
3043  }
3044  // layout and reveal just the new items
3045  this.layoutItems( items, true );
3046  this.reveal( items );
3047};
3048
3049/**
3050 * Layout prepended elements
3051 * @param {Array or NodeList or Element} elems
3052 */
3053Outlayer.prototype.prepended = function( elems ) {
3054  var items = this._itemize( elems );
3055  if ( !items.length ) {
3056    return;
3057  }
3058  // add items to beginning of collection
3059  var previousItems = this.items.slice(0);
3060  this.items = items.concat( previousItems );
3061  // start new layout
3062  this._resetLayout();
3063  this._manageStamps();
3064  // layout new stuff without transition
3065  this.layoutItems( items, true );
3066  this.reveal( items );
3067  // layout previous items
3068  this.layoutItems( previousItems );
3069};
3070
3071/**
3072 * reveal a collection of items
3073 * @param {Array of Outlayer.Items} items
3074 */
3075Outlayer.prototype.reveal = function( items ) {
3076  this._emitCompleteOnItems( 'reveal', items );
3077
3078  var len = items && items.length;
3079  for ( var i=0; len && i < len; i++ ) {
3080    var item = items[i];
3081    item.reveal();
3082  }
3083};
3084
3085/**
3086 * hide a collection of items
3087 * @param {Array of Outlayer.Items} items
3088 */
3089Outlayer.prototype.hide = function( items ) {
3090  this._emitCompleteOnItems( 'hide', items );
3091
3092  var len = items && items.length;
3093  for ( var i=0; len && i < len; i++ ) {
3094    var item = items[i];
3095    item.hide();
3096  }
3097};
3098
3099/**
3100 * reveal item elements
3101 * @param {Array}, {Element}, {NodeList} items
3102 */
3103Outlayer.prototype.revealItemElements = function( elems ) {
3104  var items = this.getItems( elems );
3105  this.reveal( items );
3106};
3107
3108/**
3109 * hide item elements
3110 * @param {Array}, {Element}, {NodeList} items
3111 */
3112Outlayer.prototype.hideItemElements = function( elems ) {
3113  var items = this.getItems( elems );
3114  this.hide( items );
3115};
3116
3117/**
3118 * get Outlayer.Item, given an Element
3119 * @param {Element} elem
3120 * @param {Function} callback
3121 * @returns {Outlayer.Item} item
3122 */
3123Outlayer.prototype.getItem = function( elem ) {
3124  // loop through items to get the one that matches
3125  for ( var i=0, len = this.items.length; i < len; i++ ) {
3126    var item = this.items[i];
3127    if ( item.element === elem ) {
3128      // return item
3129      return item;
3130    }
3131  }
3132};
3133
3134/**
3135 * get collection of Outlayer.Items, given Elements
3136 * @param {Array} elems
3137 * @returns {Array} items - Outlayer.Items
3138 */
3139Outlayer.prototype.getItems = function( elems ) {
3140  elems = utils.makeArray( elems );
3141  var items = [];
3142  for ( var i=0, len = elems.length; i < len; i++ ) {
3143    var elem = elems[i];
3144    var item = this.getItem( elem );
3145    if ( item ) {
3146      items.push( item );
3147    }
3148  }
3149
3150  return items;
3151};
3152
3153/**
3154 * remove element(s) from instance and DOM
3155 * @param {Array or NodeList or Element} elems
3156 */
3157Outlayer.prototype.remove = function( elems ) {
3158  var removeItems = this.getItems( elems );
3159
3160  this._emitCompleteOnItems( 'remove', removeItems );
3161
3162  // bail if no items to remove
3163  if ( !removeItems || !removeItems.length ) {
3164    return;
3165  }
3166
3167  for ( var i=0, len = removeItems.length; i < len; i++ ) {
3168    var item = removeItems[i];
3169    item.remove();
3170    // remove item from collection
3171    utils.removeFrom( this.items, item );
3172  }
3173};
3174
3175// ----- destroy ----- //
3176
3177// remove and disable Outlayer instance
3178Outlayer.prototype.destroy = function() {
3179  // clean up dynamic styles
3180  var style = this.element.style;
3181  style.height = '';
3182  style.position = '';
3183  style.width = '';
3184  // destroy items
3185  for ( var i=0, len = this.items.length; i < len; i++ ) {
3186    var item = this.items[i];
3187    item.destroy();
3188  }
3189
3190  this.unbindResize();
3191
3192  var id = this.element.outlayerGUID;
3193  delete instances[ id ]; // remove reference to instance by id
3194  delete this.element.outlayerGUID;
3195  // remove data for jQuery
3196  if ( jQuery ) {
3197    jQuery.removeData( this.element, this.constructor.namespace );
3198  }
3199
3200};
3201
3202// -------------------------- data -------------------------- //
3203
3204/**
3205 * get Outlayer instance from element
3206 * @param {Element} elem
3207 * @returns {Outlayer}
3208 */
3209Outlayer.data = function( elem ) {
3210  elem = utils.getQueryElement( elem );
3211  var id = elem && elem.outlayerGUID;
3212  return id && instances[ id ];
3213};
3214
3215
3216// -------------------------- create Outlayer class -------------------------- //
3217
3218/**
3219 * create a layout class
3220 * @param {String} namespace
3221 */
3222Outlayer.create = function( namespace, options ) {
3223  // sub-class Outlayer
3224  function Layout() {
3225    Outlayer.apply( this, arguments );
3226  }
3227  // inherit Outlayer prototype, use Object.create if there
3228  if ( Object.create ) {
3229    Layout.prototype = Object.create( Outlayer.prototype );
3230  } else {
3231    utils.extend( Layout.prototype, Outlayer.prototype );
3232  }
3233  // set contructor, used for namespace and Item
3234  Layout.prototype.constructor = Layout;
3235
3236  Layout.defaults = utils.extend( {}, Outlayer.defaults );
3237  // apply new options
3238  utils.extend( Layout.defaults, options );
3239  // keep prototype.settings for backwards compatibility (Packery v1.2.0)
3240  Layout.prototype.settings = {};
3241
3242  Layout.namespace = namespace;
3243
3244  Layout.data = Outlayer.data;
3245
3246  // sub-class Item
3247  Layout.Item = function LayoutItem() {
3248    Item.apply( this, arguments );
3249  };
3250
3251  Layout.Item.prototype = new Item();
3252
3253  // -------------------------- declarative -------------------------- //
3254
3255  utils.htmlInit( Layout, namespace );
3256
3257  // -------------------------- jQuery bridge -------------------------- //
3258
3259  // make into jQuery plugin
3260  if ( jQuery && jQuery.bridget ) {
3261    jQuery.bridget( namespace, Layout );
3262  }
3263
3264  return Layout;
3265};
3266
3267// ----- fin ----- //
3268
3269// back in global
3270Outlayer.Item = Item;
3271
3272return Outlayer;
3273
3274}));
3275
3276
3277/**
3278 * Isotope Item
3279**/
3280
3281( function( window, factory ) {
3282'use strict';
3283  // universal module definition
3284  if ( typeof define == 'function' && define.amd ) {
3285    // AMD
3286    define( 'isotope/js/item',[
3287        'outlayer/outlayer'
3288      ],
3289      factory );
3290  } else if ( typeof exports == 'object' ) {
3291    // CommonJS
3292    module.exports = factory(
3293      require('outlayer')
3294    );
3295  } else {
3296    // browser global
3297    window.Isotope = window.Isotope || {};
3298    window.Isotope.Item = factory(
3299      window.Outlayer
3300    );
3301  }
3302
3303}( window, function factory( Outlayer ) {
3304'use strict';
3305
3306// -------------------------- Item -------------------------- //
3307
3308// sub-class Outlayer Item
3309function Item() {
3310  Outlayer.Item.apply( this, arguments );
3311}
3312
3313Item.prototype = new Outlayer.Item();
3314
3315Item.prototype._create = function() {
3316  // assign id, used for original-order sorting
3317  this.id = this.layout.itemGUID++;
3318  Outlayer.Item.prototype._create.call( this );
3319  this.sortData = {};
3320};
3321
3322Item.prototype.updateSortData = function() {
3323  if ( this.isIgnored ) {
3324    return;
3325  }
3326  // default sorters
3327  this.sortData.id = this.id;
3328  // for backward compatibility
3329  this.sortData['original-order'] = this.id;
3330  this.sortData.random = Math.random();
3331  // go thru getSortData obj and apply the sorters
3332  var getSortData = this.layout.options.getSortData;
3333  var sorters = this.layout._sorters;
3334  for ( var key in getSortData ) {
3335    var sorter = sorters[ key ];
3336    this.sortData[ key ] = sorter( this.element, this );
3337  }
3338};
3339
3340var _destroy = Item.prototype.destroy;
3341Item.prototype.destroy = function() {
3342  // call super
3343  _destroy.apply( this, arguments );
3344  // reset display, #741
3345  this.css({
3346    display: ''
3347  });
3348};
3349
3350return Item;
3351
3352}));
3353
3354/**
3355 * Isotope LayoutMode
3356 */
3357
3358( function( window, factory ) {
3359  'use strict';
3360  // universal module definition
3361
3362  if ( typeof define == 'function' && define.amd ) {
3363    // AMD
3364    define( 'isotope/js/layout-mode',[
3365        'get-size/get-size',
3366        'outlayer/outlayer'
3367      ],
3368      factory );
3369  } else if ( typeof exports == 'object' ) {
3370    // CommonJS
3371    module.exports = factory(
3372      require('get-size'),
3373      require('outlayer')
3374    );
3375  } else {
3376    // browser global
3377    window.Isotope = window.Isotope || {};
3378    window.Isotope.LayoutMode = factory(
3379      window.getSize,
3380      window.Outlayer
3381    );
3382  }
3383
3384}( window, function factory( getSize, Outlayer ) {
3385  'use strict';
3386
3387  // layout mode class
3388  function LayoutMode( isotope ) {
3389    this.isotope = isotope;
3390    // link properties
3391    if ( isotope ) {
3392      this.options = isotope.options[ this.namespace ];
3393      this.element = isotope.element;
3394      this.items = isotope.filteredItems;
3395      this.size = isotope.size;
3396    }
3397  }
3398
3399  /**
3400   * some methods should just defer to default Outlayer method
3401   * and reference the Isotope instance as `this`
3402  **/
3403  ( function() {
3404    var facadeMethods = [
3405      '_resetLayout',
3406      '_getItemLayoutPosition',
3407      '_manageStamp',
3408      '_getContainerSize',
3409      '_getElementOffset',
3410      'needsResizeLayout'
3411    ];
3412
3413    for ( var i=0, len = facadeMethods.length; i < len; i++ ) {
3414      var methodName = facadeMethods[i];
3415      LayoutMode.prototype[ methodName ] = getOutlayerMethod( methodName );
3416    }
3417
3418    function getOutlayerMethod( methodName ) {
3419      return function() {
3420        return Outlayer.prototype[ methodName ].apply( this.isotope, arguments );
3421      };
3422    }
3423  })();
3424
3425  // -----  ----- //
3426
3427  // for horizontal layout modes, check vertical size
3428  LayoutMode.prototype.needsVerticalResizeLayout = function() {
vendor: 20,029 bytes, lines 3429-4164
3429    // don't trigger if size did not change
3430    var size = getSize( this.isotope.element );
3431    // check that this.size and size are there
3432    // IE8 triggers resize on body size change, so they might not be
3433    var hasSizes = this.isotope.size && size;
3434    return hasSizes && size.innerHeight != this.isotope.size.innerHeight;
3435  };
3436
3437  // ----- measurements ----- //
3438
3439  LayoutMode.prototype._getMeasurement = function() {
3440    this.isotope._getMeasurement.apply( this, arguments );
3441  };
3442
3443  LayoutMode.prototype.getColumnWidth = function() {
3444    this.getSegmentSize( 'column', 'Width' );
3445  };
3446
3447  LayoutMode.prototype.getRowHeight = function() {
3448    this.getSegmentSize( 'row', 'Height' );
3449  };
3450
3451  /**
3452   * get columnWidth or rowHeight
3453   * segment: 'column' or 'row'
3454   * size 'Width' or 'Height'
3455  **/
3456  LayoutMode.prototype.getSegmentSize = function( segment, size ) {
3457    var segmentName = segment + size;
3458    var outerSize = 'outer' + size;
3459    // columnWidth / outerWidth // rowHeight / outerHeight
3460    this._getMeasurement( segmentName, outerSize );
3461    // got rowHeight or columnWidth, we can chill
3462    if ( this[ segmentName ] ) {
3463      return;
3464    }
3465    // fall back to item of first element
3466    var firstItemSize = this.getFirstItemSize();
3467    this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] ||
3468      // or size of container
3469      this.isotope.size[ 'inner' + size ];
3470  };
3471
3472  LayoutMode.prototype.getFirstItemSize = function() {
3473    var firstItem = this.isotope.filteredItems[0];
3474    return firstItem && firstItem.element && getSize( firstItem.element );
3475  };
3476
3477  // ----- methods that should reference isotope ----- //
3478
3479  LayoutMode.prototype.layout = function() {
3480    this.isotope.layout.apply( this.isotope, arguments );
3481  };
3482
3483  LayoutMode.prototype.getSize = function() {
3484    this.isotope.getSize();
3485    this.size = this.isotope.size;
3486  };
3487
3488  // -------------------------- create -------------------------- //
3489
3490  LayoutMode.modes = {};
3491
3492  LayoutMode.create = function( namespace, options ) {
3493
3494    function Mode() {
3495      LayoutMode.apply( this, arguments );
3496    }
3497
3498    Mode.prototype = new LayoutMode();
3499
3500    // default options
3501    if ( options ) {
3502      Mode.options = options;
3503    }
3504
3505    Mode.prototype.namespace = namespace;
3506    // register in Isotope
3507    LayoutMode.modes[ namespace ] = Mode;
3508
3509    return Mode;
3510  };
3511
3512  return LayoutMode;
3513
3514}));
3515
3516/*!
3517 * Masonry v3.3.1
3518 * Cascading grid layout library
3519 * http://masonry.desandro.com
3520 * MIT License
3521 * by David DeSandro
3522 */
3523
3524( function( window, factory ) {
3525  'use strict';
3526  // universal module definition
3527  if ( typeof define === 'function' && define.amd ) {
3528    // AMD
3529    define( 'masonry/masonry',[
3530        'outlayer/outlayer',
3531        'get-size/get-size',
3532        'fizzy-ui-utils/utils'
3533      ],
3534      factory );
3535  } else if ( typeof exports === 'object' ) {
3536    // CommonJS
3537    module.exports = factory(
3538      require('outlayer'),
3539      require('get-size'),
3540      require('fizzy-ui-utils')
3541    );
3542  } else {
3543    // browser global
3544    window.Masonry = factory(
3545      window.Outlayer,
3546      window.getSize,
3547      window.fizzyUIUtils
3548    );
3549  }
3550
3551}( window, function factory( Outlayer, getSize, utils ) {
3552
3553
3554
3555// -------------------------- masonryDefinition -------------------------- //
3556
3557  // create an Outlayer layout class
3558  var Masonry = Outlayer.create('masonry');
3559
3560  Masonry.prototype._resetLayout = function() {
3561    this.getSize();
3562    this._getMeasurement( 'columnWidth', 'outerWidth' );
3563    this._getMeasurement( 'gutter', 'outerWidth' );
3564    this.measureColumns();
3565
3566    // reset column Y
3567    var i = this.cols;
3568    this.colYs = [];
3569    while (i--) {
3570      this.colYs.push( 0 );
3571    }
3572
3573    this.maxY = 0;
3574  };
3575
3576  Masonry.prototype.measureColumns = function() {
3577    this.getContainerWidth();
3578    // if columnWidth is 0, default to outerWidth of first item
3579    if ( !this.columnWidth ) {
3580      var firstItem = this.items[0];
3581      var firstItemElem = firstItem && firstItem.element;
3582      // columnWidth fall back to item of first element
3583      this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth ||
3584        // if first elem has no width, default to size of container
3585        this.containerWidth;
3586    }
3587
3588    var columnWidth = this.columnWidth += this.gutter;
3589
3590    // calculate columns
3591    var containerWidth = this.containerWidth + this.gutter;
3592    var cols = containerWidth / columnWidth;
3593    // fix rounding errors, typically with gutters
3594    var excess = columnWidth - containerWidth % columnWidth;
3595    // if overshoot is less than a pixel, round up, otherwise floor it
3596    var mathMethod = excess && excess < 1 ? 'round' : 'floor';
3597    cols = Math[ mathMethod ]( cols );
3598    this.cols = Math.max( cols, 1 );
3599  };
3600
3601  Masonry.prototype.getContainerWidth = function() {
3602    // container is parent if fit width
3603    var container = this.options.isFitWidth ? this.element.parentNode : this.element;
3604    // check that this.size and size are there
3605    // IE8 triggers resize on body size change, so they might not be
3606    var size = getSize( container );
3607    this.containerWidth = size && size.innerWidth;
3608  };
3609
3610  Masonry.prototype._getItemLayoutPosition = function( item ) {
3611    item.getSize();
3612    // how many columns does this brick span
3613    var remainder = item.size.outerWidth % this.columnWidth;
3614    var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
3615    // round if off by 1 pixel, otherwise use ceil
3616    var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth );
3617    colSpan = Math.min( colSpan, this.cols );
3618
3619    var colGroup = this._getColGroup( colSpan );
3620    // get the minimum Y value from the columns
3621    var minimumY = Math.min.apply( Math, colGroup );
3622    var shortColIndex = utils.indexOf( colGroup, minimumY );
3623
3624    // position the brick
3625    var position = {
3626      x: this.columnWidth * shortColIndex,
3627      y: minimumY
3628    };
3629
3630    // apply setHeight to necessary columns
3631    var setHeight = minimumY + item.size.outerHeight;
3632    var setSpan = this.cols + 1 - colGroup.length;
3633    for ( var i = 0; i < setSpan; i++ ) {
3634      this.colYs[ shortColIndex + i ] = setHeight;
3635    }
3636
3637    return position;
3638  };
3639
3640  /**
3641   * @param {Number} colSpan - number of columns the element spans
3642   * @returns {Array} colGroup
3643   */
3644  Masonry.prototype._getColGroup = function( colSpan ) {
3645    if ( colSpan < 2 ) {
3646      // if brick spans only one column, use all the column Ys
3647      return this.colYs;
3648    }
3649
3650    var colGroup = [];
3651    // how many different places could this brick fit horizontally
3652    var groupCount = this.cols + 1 - colSpan;
3653    // for each group potential horizontal position
3654    for ( var i = 0; i < groupCount; i++ ) {
3655      // make an array of colY values for that one group
3656      var groupColYs = this.colYs.slice( i, i + colSpan );
3657      // and get the max value of the array
3658      colGroup[i] = Math.max.apply( Math, groupColYs );
3659    }
3660    return colGroup;
3661  };
3662
3663  Masonry.prototype._manageStamp = function( stamp ) {
3664    var stampSize = getSize( stamp );
3665    var offset = this._getElementOffset( stamp );
3666    // get the columns that this stamp affects
3667    var firstX = this.options.isOriginLeft ? offset.left : offset.right;
3668    var lastX = firstX + stampSize.outerWidth;
3669    var firstCol = Math.floor( firstX / this.columnWidth );
3670    firstCol = Math.max( 0, firstCol );
3671    var lastCol = Math.floor( lastX / this.columnWidth );
3672    // lastCol should not go over if multiple of columnWidth #425
3673    lastCol -= lastX % this.columnWidth ? 0 : 1;
3674    lastCol = Math.min( this.cols - 1, lastCol );
3675    // set colYs to bottom of the stamp
3676    var stampMaxY = ( this.options.isOriginTop ? offset.top : offset.bottom ) +
3677      stampSize.outerHeight;
3678    for ( var i = firstCol; i <= lastCol; i++ ) {
3679      this.colYs[i] = Math.max( stampMaxY, this.colYs[i] );
3680    }
3681  };
3682
3683  Masonry.prototype._getContainerSize = function() {
3684    this.maxY = Math.max.apply( Math, this.colYs );
3685    var size = {
3686      height: this.maxY
3687    };
3688
3689    if ( this.options.isFitWidth ) {
3690      size.width = this._getContainerFitWidth();
3691    }
3692
3693    return size;
3694  };
3695
3696  Masonry.prototype._getContainerFitWidth = function() {
3697    var unusedCols = 0;
3698    // count unused columns
3699    var i = this.cols;
3700    while ( --i ) {
3701      if ( this.colYs[i] !== 0 ) {
3702        break;
3703      }
3704      unusedCols++;
3705    }
3706    // fit container to columns that have been used
3707    return ( this.cols - unusedCols ) * this.columnWidth - this.gutter;
3708  };
3709
3710  Masonry.prototype.needsResizeLayout = function() {
3711    var previousWidth = this.containerWidth;
3712    this.getContainerWidth();
3713    return previousWidth !== this.containerWidth;
3714  };
3715
3716  return Masonry;
3717
3718}));
3719
3720/*!
3721 * Masonry layout mode
3722 * sub-classes Masonry
3723 * http://masonry.desandro.com
3724 */
3725
3726( function( window, factory ) {
3727  'use strict';
3728  // universal module definition
3729  if ( typeof define == 'function' && define.amd ) {
3730    // AMD
3731    define( 'isotope/js/layout-modes/masonry',[
3732        '../layout-mode',
3733        'masonry/masonry'
3734      ],
3735      factory );
3736  } else if ( typeof exports == 'object' ) {
3737    // CommonJS
3738    module.exports = factory(
3739      require('../layout-mode'),
3740      require('masonry-layout')
3741    );
3742  } else {
3743    // browser global
3744    factory(
3745      window.Isotope.LayoutMode,
3746      window.Masonry
3747    );
3748  }
3749
3750}( window, function factory( LayoutMode, Masonry ) {
3751'use strict';
3752
3753// -------------------------- helpers -------------------------- //
3754
3755// extend objects
3756function extend( a, b ) {
3757  for ( var prop in b ) {
3758    a[ prop ] = b[ prop ];
3759  }
3760  return a;
3761}
3762
3763// -------------------------- masonryDefinition -------------------------- //
3764
3765  // create an Outlayer layout class
3766  var MasonryMode = LayoutMode.create('masonry');
3767
3768  // save on to these methods
3769  var _getElementOffset = MasonryMode.prototype._getElementOffset;
3770  var layout = MasonryMode.prototype.layout;
3771  var _getMeasurement = MasonryMode.prototype._getMeasurement;
3772
3773  // sub-class Masonry
3774  extend( MasonryMode.prototype, Masonry.prototype );
3775
3776  // set back, as it was overwritten by Masonry
3777  MasonryMode.prototype._getElementOffset = _getElementOffset;
3778  MasonryMode.prototype.layout = layout;
3779  MasonryMode.prototype._getMeasurement = _getMeasurement;
3780
3781  var measureColumns = MasonryMode.prototype.measureColumns;
3782  MasonryMode.prototype.measureColumns = function() {
3783    // set items, used if measuring first item
3784    this.items = this.isotope.filteredItems;
3785    measureColumns.call( this );
3786  };
3787
3788  // HACK copy over isOriginLeft/Top options
3789  var _manageStamp = MasonryMode.prototype._manageStamp;
3790  MasonryMode.prototype._manageStamp = function() {
3791    this.options.isOriginLeft = this.isotope.options.isOriginLeft;
3792    this.options.isOriginTop = this.isotope.options.isOriginTop;
3793    _manageStamp.apply( this, arguments );
3794  };
3795
3796  return MasonryMode;
3797
3798}));
3799
3800/**
3801 * fitRows layout mode
3802 */
3803
3804( function( window, factory ) {
3805  'use strict';
3806  // universal module definition
3807  if ( typeof define == 'function' && define.amd ) {
3808    // AMD
3809    define( 'isotope/js/layout-modes/fit-rows',[
3810        '../layout-mode'
3811      ],
3812      factory );
3813  } else if ( typeof exports == 'object' ) {
3814    // CommonJS
3815    module.exports = factory(
3816      require('../layout-mode')
3817    );
3818  } else {
3819    // browser global
3820    factory(
3821      window.Isotope.LayoutMode
3822    );
3823  }
3824
3825}( window, function factory( LayoutMode ) {
3826'use strict';
3827
3828var FitRows = LayoutMode.create('fitRows');
3829
3830FitRows.prototype._resetLayout = function() {
3831  this.x = 0;
3832  this.y = 0;
3833  this.maxY = 0;
3834  this._getMeasurement( 'gutter', 'outerWidth' );
3835};
3836
3837FitRows.prototype._getItemLayoutPosition = function( item ) {
3838  item.getSize();
3839
3840  var itemWidth = item.size.outerWidth + this.gutter;
3841  // if this element cannot fit in the current row
3842  var containerWidth = this.isotope.size.innerWidth + this.gutter;
3843  if ( this.x !== 0 && itemWidth + this.x > containerWidth ) {
3844    this.x = 0;
3845    this.y = this.maxY;
3846  }
3847
3848  var position = {
3849    x: this.x,
3850    y: this.y
3851  };
3852
3853  this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight );
3854  this.x += itemWidth;
3855
3856  return position;
3857};
3858
3859FitRows.prototype._getContainerSize = function() {
3860  return { height: this.maxY };
3861};
3862
3863return FitRows;
3864
3865}));
3866
3867/**
3868 * vertical layout mode
3869 */
3870
3871( function( window, factory ) {
3872  'use strict';
3873  // universal module definition
3874  if ( typeof define == 'function' && define.amd ) {
3875    // AMD
3876    define( 'isotope/js/layout-modes/vertical',[
3877        '../layout-mode'
3878      ],
3879      factory );
3880  } else if ( typeof exports == 'object' ) {
3881    // CommonJS
3882    module.exports = factory(
3883      require('../layout-mode')
3884    );
3885  } else {
3886    // browser global
3887    factory(
3888      window.Isotope.LayoutMode
3889    );
3890  }
3891
3892}( window, function factory( LayoutMode ) {
3893'use strict';
3894
3895var Vertical = LayoutMode.create( 'vertical', {
3896  horizontalAlignment: 0
3897});
3898
3899Vertical.prototype._resetLayout = function() {
3900  this.y = 0;
3901};
3902
3903Vertical.prototype._getItemLayoutPosition = function( item ) {
3904  item.getSize();
3905  var x = ( this.isotope.size.innerWidth - item.size.outerWidth ) *
3906    this.options.horizontalAlignment;
3907  var y = this.y;
3908  this.y += item.size.outerHeight;
3909  return { x: x, y: y };
3910};
3911
3912Vertical.prototype._getContainerSize = function() {
3913  return { height: this.y };
3914};
3915
3916return Vertical;
3917
3918}));
3919
3920/*!
3921 * Isotope v2.2.2
3922 *
3923 * Licensed GPLv3 for open source use
3924 * or Isotope Commercial License for commercial use
3925 *
3926 * http://isotope.metafizzy.co
3927 * Copyright 2015 Metafizzy
3928 */
3929
3930( function( window, factory ) {
3931  'use strict';
3932  // universal module definition
3933
3934  if ( typeof define == 'function' && define.amd ) {
3935    // AMD
3936    define( [
3937        'outlayer/outlayer',
3938        'get-size/get-size',
3939        'matches-selector/matches-selector',
3940        'fizzy-ui-utils/utils',
3941        'isotope/js/item',
3942        'isotope/js/layout-mode',
3943        // include default layout modes
3944        'isotope/js/layout-modes/masonry',
3945        'isotope/js/layout-modes/fit-rows',
3946        'isotope/js/layout-modes/vertical'
3947      ],
3948      function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) {
3949        return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode );
3950      });
3951  } else if ( typeof exports == 'object' ) {
3952    // CommonJS
3953    module.exports = factory(
3954      window,
3955      require('outlayer'),
3956      require('get-size'),
3957      require('desandro-matches-selector'),
3958      require('fizzy-ui-utils'),
3959      require('./item'),
3960      require('./layout-mode'),
3961      // include default layout modes
3962      require('./layout-modes/masonry'),
3963      require('./layout-modes/fit-rows'),
3964      require('./layout-modes/vertical')
3965    );
3966  } else {
3967    // browser global
3968    window.Isotope = factory(
3969      window,
3970      window.Outlayer,
3971      window.getSize,
3972      window.matchesSelector,
3973      window.fizzyUIUtils,
3974      window.Isotope.Item,
3975      window.Isotope.LayoutMode
3976    );
3977  }
3978
3979}( window, function factory( window, Outlayer, getSize, matchesSelector, utils,
3980  Item, LayoutMode ) {
3981
3982
3983
3984// -------------------------- vars -------------------------- //
3985
3986var jQuery = window.jQuery;
3987
3988// -------------------------- helpers -------------------------- //
3989
3990var trim = String.prototype.trim ?
3991  function( str ) {
3992    return str.trim();
3993  } :
3994  function( str ) {
3995    return str.replace( /^\s+|\s+$/g, '' );
3996  };
3997
3998var docElem = document.documentElement;
3999
4000var getText = docElem.textContent ?
4001  function( elem ) {
4002    return elem.textContent;
4003  } :
4004  function( elem ) {
4005    return elem.innerText;
4006  };
4007
4008// -------------------------- isotopeDefinition -------------------------- //
4009
4010  // create an Outlayer layout class
4011  var Isotope = Outlayer.create( 'isotope', {
4012    layoutMode: "masonry",
4013    isJQueryFiltering: true,
4014    sortAscending: true
4015  });
4016
4017  Isotope.Item = Item;
4018  Isotope.LayoutMode = LayoutMode;
4019
4020  Isotope.prototype._create = function() {
4021    this.itemGUID = 0;
4022    // functions that sort items
4023    this._sorters = {};
4024    this._getSorters();
4025    // call super
4026    Outlayer.prototype._create.call( this );
4027
4028    // create layout modes
4029    this.modes = {};
4030    // start filteredItems with all items
4031    this.filteredItems = this.items;
4032    // keep of track of sortBys
4033    this.sortHistory = [ 'original-order' ];
4034    // create from registered layout modes
4035    for ( var name in LayoutMode.modes ) {
4036      this._initLayoutMode( name );
4037    }
4038  };
4039
4040  Isotope.prototype.reloadItems = function() {
4041    // reset item ID counter
4042    this.itemGUID = 0;
4043    // call super
4044    Outlayer.prototype.reloadItems.call( this );
4045  };
4046
4047  Isotope.prototype._itemize = function() {
4048    var items = Outlayer.prototype._itemize.apply( this, arguments );
4049    // assign ID for original-order
4050    for ( var i=0, len = items.length; i < len; i++ ) {
4051      var item = items[i];
4052      item.id = this.itemGUID++;
4053    }
4054    this._updateItemsSortData( items );
4055    return items;
4056  };
4057
4058
4059  // -------------------------- layout -------------------------- //
4060
4061  Isotope.prototype._initLayoutMode = function( name ) {
4062    var Mode = LayoutMode.modes[ name ];
4063    // set mode options
4064    // HACK extend initial options, back-fill in default options
4065    var initialOpts = this.options[ name ] || {};
4066    this.options[ name ] = Mode.options ?
4067      utils.extend( Mode.options, initialOpts ) : initialOpts;
4068    // init layout mode instance
4069    this.modes[ name ] = new Mode( this );
4070  };
4071
4072
4073  Isotope.prototype.layout = function() {
4074    // if first time doing layout, do all magic
4075    if ( !this._isLayoutInited && this.options.isInitLayout ) {
4076      this.arrange();
4077      return;
4078    }
4079    this._layout();
4080  };
4081
4082  // private method to be used in layout() & magic()
4083  Isotope.prototype._layout = function() {
4084    // don't animate first layout
4085    var isInstant = this._getIsInstant();
4086    // layout flow
4087    this._resetLayout();
4088    this._manageStamps();
4089    this.layoutItems( this.filteredItems, isInstant );
4090
4091    // flag for initalized
4092    this._isLayoutInited = true;
4093  };
4094
4095  // filter + sort + layout
4096  Isotope.prototype.arrange = function( opts ) {
4097    // set any options pass
4098    this.option( opts );
4099    this._getIsInstant();
4100    // filter, sort, and layout
4101
4102    // filter
4103    var filtered = this._filter( this.items );
4104    this.filteredItems = filtered.matches;
4105
4106    var _this = this;
4107    function hideReveal() {
4108      _this.reveal( filtered.needReveal );
4109      _this.hide( filtered.needHide );
4110    }
4111
4112    this._bindArrangeComplete();
4113
4114    if ( this._isInstant ) {
4115      this._noTransition( hideReveal );
4116    } else {
4117      hideReveal();
4118    }
4119
4120    this._sort();
4121    this._layout();
4122  };
4123  // alias to _init for main plugin method
4124  Isotope.prototype._init = Isotope.prototype.arrange;
4125
4126  // HACK
4127  // Don't animate/transition first layout
4128  // Or don't animate/transition other layouts
4129  Isotope.prototype._getIsInstant = function() {
4130    var isInstant = this.options.isLayoutInstant !== undefined ?
4131      this.options.isLayoutInstant : !this._isLayoutInited;
4132    this._isInstant = isInstant;
4133    return isInstant;
4134  };
4135
4136  // listen for layoutComplete, hideComplete and revealComplete
4137  // to trigger arrangeComplete
4138  Isotope.prototype._bindArrangeComplete = function() {
4139    // listen for 3 events to trigger arrangeComplete
4140    var isLayoutComplete, isHideComplete, isRevealComplete;
4141    var _this = this;
4142    function arrangeParallelCallback() {
4143      if ( isLayoutComplete && isHideComplete && isRevealComplete ) {
4144        _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] );
4145      }
4146    }
4147    this.once( 'layoutComplete', function() {
4148      isLayoutComplete = true;
4149      arrangeParallelCallback();
4150    });
4151    this.once( 'hideComplete', function() {
4152      isHideComplete = true;
4153      arrangeParallelCallback();
4154    });
4155    this.once( 'revealComplete', function() {
4156      isRevealComplete = true;
4157      arrangeParallelCallback();
4158    });
4159  };
4160
4161  // -------------------------- filter -------------------------- //
4162
4163  Isotope.prototype._filter = function( items ) {
4164    var filter = this.options.filter;
4165    filter = filter || '*';
4166    var matches = [];
4167    var hiddenMatched = [];
4168    var visibleUnmatched = [];
4169
4170    var test = this._getFilterTest( filter );
4171
4172    // test each item
4173    for ( var i=0, len = items.length; i < len; i++ ) {
4174      var item = items[i];
4175      if ( item.isIgnored ) {
4176        continue;
4177      }
4178      // add item to either matched or unmatched group
4179      var isMatched = test( item );
4180      // item.isFilterMatched = isMatched;
4181      // add to matches if its a match
4182      if ( isMatched ) {
4183        matches.push( item );
4184      }
4185      // add to additional group if item needs to be hidden or revealed
4186      if ( isMatched && item.isHidden ) {
4187        hiddenMatched.push( item );
4188      } else if ( !isMatched && !item.isHidden ) {
4189        visibleUnmatched.push( item );
4190      }
4191    }
4192
4193    // return collections of items to be manipulated
4194    return {
4195      matches: matches,
4196      needReveal: hiddenMatched,
4197      needHide: visibleUnmatched
4198    };
4199  };
4200
4201  // get a jQuery, function, or a matchesSelector test given the filter
4202  Isotope.prototype._getFilterTest = function( filter ) {
4203    if ( jQuery && this.options.isJQueryFiltering ) {
4204      // use jQuery
4205      return function( item ) {
4206        return jQuery( item.element ).is( filter );
4207      };
4208    }
4209    if ( typeof filter == 'function' ) {
4210      // use filter as function
4211      return function( item ) {
4212        return filter( item.element );
4213      };
4214    }
4215    // default, use filter as selector string
4216    return function( item ) {
4217      return matchesSelector( item.element, filter );
4218    };
4219  };
4220
4221  // -------------------------- sorting -------------------------- //
4222
4223  /**
4224   * @params {Array} elems
4225   * @public
4226   */
4227  Isotope.prototype.updateSortData = function( elems ) {
4228    // get items
4229    var items;
4230    if ( elems ) {
4231      elems = utils.makeArray( elems );
4232      items = this.getItems( elems );
4233    } else {
4234      // update all items if no elems provided
4235      items = this.items;
4236    }
4237
4238    this._getSorters();
4239    this._updateItemsSortData( items );
4240  };
4241
4242  Isotope.prototype._getSorters = function() {
4243    var getSortData = this.options.getSortData;
4244    for ( var key in getSortData ) {
4245      var sorter = getSortData[ key ];
4246      this._sorters[ key ] = mungeSorter( sorter );
4247    }
4248  };
4249
4250  /**
4251   * @params {Array} items - of Isotope.Items
4252   * @private
4253   */
4254  Isotope.prototype._updateItemsSortData = function( items ) {
4255    // do not update if no items
4256    var len = items && items.length;
4257
4258    for ( var i=0; len && i < len; i++ ) {
4259      var item = items[i];
4260      item.updateSortData();
4261    }
4262  };
4263
4264  // ----- munge sorter ----- //
4265
4266  // encapsulate this, as we just need mungeSorter
4267  // other functions in here are just for munging
4268  var mungeSorter = ( function() {
4269    // add a magic layer to sorters for convienent shorthands
4270    // `.foo-bar` will use the text of .foo-bar querySelector
4271    // `[foo-bar]` will use attribute
4272    // you can also add parser
4273    // `.foo-bar parseInt` will parse that as a number
4274    function mungeSorter( sorter ) {
4275      // if not a string, return function or whatever it is
4276      if ( typeof sorter != 'string' ) {
4277        return sorter;
4278      }
4279      // parse the sorter string
4280      var args = trim( sorter ).split(' ');
4281      var query = args[0];
4282      // check if query looks like [an-attribute]
4283      var attrMatch = query.match( /^\[(.+)\]$/ );
4284      var attr = attrMatch && attrMatch[1];
4285      var getValue = getValueGetter( attr, query );
4286      // use second argument as a parser
4287      var parser = Isotope.sortDataParsers[ args[1] ];
4288      // parse the value, if there was a parser
4289      sorter = parser ? function( elem ) {
4290        return elem && parser( getValue( elem ) );
4291      } :
4292      // otherwise just return value
4293      function( elem ) {
4294        return elem && getValue( elem );
4295      };
4296
4297      return sorter;
4298    }
4299
4300    // get an attribute getter, or get text of the querySelector
4301    function getValueGetter( attr, query ) {
4302      var getValue;
4303      // if query looks like [foo-bar], get attribute
4304      if ( attr ) {
4305        getValue = function( elem ) {
4306          return elem.getAttribute( attr );
4307        };
4308      } else {
4309        // otherwise, assume its a querySelector, and get its text
4310        getValue = function( elem ) {
4311          var child = elem.querySelector( query );
4312          return child && getText( child );
4313        };
4314      }
4315      return getValue;
4316    }
4317
4318    return mungeSorter;
4319  })();
4320
4321  // parsers used in getSortData shortcut strings
4322  Isotope.sortDataParsers = {
4323    'parseInt': function( val ) {
4324      return parseInt( val, 10 );
4325    },
4326    'parseFloat': function( val ) {
4327      return parseFloat( val );
4328    }
4329  };
4330
4331  // ----- sort method ----- //
4332
4333  // sort filteredItem order
4334  Isotope.prototype._sort = function() {
4335    var sortByOpt = this.options.sortBy;
4336    if ( !sortByOpt ) {
4337      return;
4338    }
4339    // concat all sortBy and sortHistory
4340    var sortBys = [].concat.apply( sortByOpt, this.sortHistory );
4341    // sort magic
4342    var itemSorter = getItemSorter( sortBys, this.options.sortAscending );
4343    this.filteredItems.sort( itemSorter );
4344    // keep track of sortBy History
4345    if ( sortByOpt != this.sortHistory[0] ) {
4346      // add to front, oldest goes in last
4347      this.sortHistory.unshift( sortByOpt );
4348    }
4349  };
4350
4351  // returns a function used for sorting
4352  function getItemSorter( sortBys, sortAsc ) {
4353    return function sorter( itemA, itemB ) {
4354      // cycle through all sortKeys
4355      for ( var i = 0, len = sortBys.length; i < len; i++ ) {
4356        var sortBy = sortBys[i];
4357        var a = itemA.sortData[ sortBy ];
4358        var b = itemB.sortData[ sortBy ];
4359        if ( a > b || a < b ) {
4360          // if sortAsc is an object, use the value given the sortBy key
4361          var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc;
4362          var direction = isAscending ? 1 : -1;
4363          return ( a > b ? 1 : -1 ) * direction;
4364        }
4365      }
4366      return 0;
4367    };
4368  }
4369
4370  // -------------------------- methods -------------------------- //
4371
4372  // get layout mode
4373  Isotope.prototype._mode = function() {
4374    var layoutMode = this.options.layoutMode;
4375    var mode = this.modes[ layoutMode ];
4376    if ( !mode ) {
4377      // TODO console.error
4378      throw new Error( 'No layout mode: ' + layoutMode );
4379    }
4380    // HACK sync mode's options
4381    // any options set after init for layout mode need to be synced
4382    mode.options = this.options[ layoutMode ];
4383    return mode;
4384  };
4385
4386  Isotope.prototype._resetLayout = function() {
4387    // trigger original reset layout
4388    Outlayer.prototype._resetLayout.call( this );
4389    this._mode()._resetLayout();
4390  };
4391
4392  Isotope.prototype._getItemLayoutPosition = function( item  ) {
4393    return this._mode()._getItemLayoutPosition( item );
4394  };
4395
4396  Isotope.prototype._manageStamp = function( stamp ) {
4397    this._mode()._manageStamp( stamp );
4398  };
4399
4400  Isotope.prototype._getContainerSize = function() {
4401    return this._mode()._getContainerSize();
4402  };
4403
4404  Isotope.prototype.needsResizeLayout = function() {
4405    return this._mode().needsResizeLayout();
4406  };
4407
4408  // -------------------------- adding & removing -------------------------- //
4409
4410  // HEADS UP overwrites default Outlayer appended
4411  Isotope.prototype.appended = function( elems ) {
4412    var items = this.addItems( elems );
4413    if ( !items.length ) {
4414      return;
4415    }
4416    // filter, layout, reveal new items
4417    var filteredItems = this._filterRevealAdded( items );
4418    // add to filteredItems
4419    this.filteredItems = this.filteredItems.concat( filteredItems );
4420  };
4421
4422  // HEADS UP overwrites default Outlayer prepended
4423  Isotope.prototype.prepended = function( elems ) {
4424    var items = this._itemize( elems );
4425    if ( !items.length ) {
4426      return;
4427    }
4428    // start new layout
4429    this._resetLayout();
4430    this._manageStamps();
4431    // filter, layout, reveal new items
4432    var filteredItems = this._filterRevealAdded( items );
4433    // layout previous items
4434    this.layoutItems( this.filteredItems );
4435    // add to items and filteredItems
4436    this.filteredItems = filteredItems.concat( this.filteredItems );
4437    this.items = items.concat( this.items );
4438  };
4439
4440  Isotope.prototype._filterRevealAdded = function( items ) {
4441    var filtered = this._filter( items );
4442    this.hide( filtered.needHide );
4443    // reveal all new items
4444    this.reveal( filtered.matches );
4445    // layout new items, no transition
4446    this.layoutItems( filtered.matches, true );
4447    return filtered.matches;
4448  };
4449
4450  /**
4451   * Filter, sort, and layout newly-appended item elements
4452   * @param {Array or NodeList or Element} elems
4453   */
4454  Isotope.prototype.insert = function( elems ) {
4455    var items = this.addItems( elems );
4456    if ( !items.length ) {
4457      return;
4458    }
4459    // append item elements
4460    var i, item;
4461    var len = items.length;
4462    for ( i=0; i < len; i++ ) {
4463      item = items[i];
4464      this.element.appendChild( item.element );
4465    }
4466    // filter new stuff
4467    var filteredInsertItems = this._filter( items ).matches;
4468    // set flag
4469    for ( i=0; i < len; i++ ) {
4470      items[i].isLayoutInstant = true;
4471    }
4472    this.arrange();
4473    // reset flag
4474    for ( i=0; i < len; i++ ) {
4475      delete items[i].isLayoutInstant;
4476    }
4477    this.reveal( filteredInsertItems );
4478  };
4479
4480  var _remove = Isotope.prototype.remove;
4481  Isotope.prototype.remove = function( elems ) {
4482    elems = utils.makeArray( elems );
4483    var removeItems = this.getItems( elems );
4484    // do regular thing
4485    _remove.call( this, elems );
4486    // bail if no items to remove
4487    var len = removeItems && removeItems.length;
4488    if ( !len ) {
4489      return;
4490    }
4491    // remove elems from filteredItems
4492    for ( var i=0; i < len; i++ ) {
4493      var item = removeItems[i];
4494      // remove item from collection
4495      utils.removeFrom( this.filteredItems, item );
4496    }
4497  };
4498
4499  Isotope.prototype.shuffle = function() {
4500    // update random sortData
4501    for ( var i=0, len = this.items.length; i < len; i++ ) {
4502      var item = this.items[i];
4503      item.sortData.random = Math.random();
4504    }
4505    this.options.sortBy = 'random';
4506    this._sort();
4507    this._layout();
4508  };
4509
4510  /**
4511   * trigger fn without transition
4512   * kind of hacky to have this in the first place
4513   * @param {Function} fn
4514   * @returns ret
4515   * @private
4516   */
4517  Isotope.prototype._noTransition = function( fn ) {
4518    // save transitionDuration before disabling
4519    var transitionDuration = this.options.transitionDuration;
4520    // disable transition
4521    this.options.transitionDuration = 0;
4522    // do it
4523    var returnValue = fn.call( this );
4524    // re-enable transition for reveal
4525    this.options.transitionDuration = transitionDuration;
4526    return returnValue;
4527  };
4528
4529  // ----- helper methods ----- //
4530
4531  /**
4532   * getter method for getting filtered item elements
4533   * @returns {Array} elems - collection of item elements
4534   */
4535  Isotope.prototype.getFilteredItemElements = function() {
4536    var elems = [];
4537    for ( var i=0, len = this.filteredItems.length; i < len; i++ ) {
4538      elems.push( this.filteredItems[i].element );
4539    }
4540    return elems;
4541  };
4542
4543  // -----  ----- //
4544
4545  return Isotope;
4546
4547}));
4548
4549
4550/*!
4551 * Packery layout mode PACKAGED v1.1.1
4552 * sub-classes Packery
4553 * http://packery.metafizzy.co
4554 */
4555
4556!function(a){function b(a){return new RegExp("(^|\\s+)"+a+"(\\s+|$)")}function c(a,b){var c=d(a,b)?f:e;c(a,b)}var d,e,f;"classList"in document.documentElement?(d=function(a,b){return a.classList.contains(b)}
4556,e=function(a,b){a.classList.add(b)},f=function(a,b){a.classList.remove(b)}):(d=function(a,c){return b(c).test(a.className)},e=function(a,b){d(a,b)||(a.className=a.className+" "+b)},f=function(a,c){a.className=a.className.replace(b(c)," ")});var g={hasClass:d,addClass:e,removeClass:f,toggleClass:c,has:d,add:e,remove:f,toggle:c};"function"==typeof define&&define.amd?define("classie/classie",g):"object"==typeof exports?module.exports=g:a.classie=g}(window),function(a){function b(){function a(b){for(var c in a.defaults)this[c]=a.defaults[c];for(c in b)this[c]=b[c]}return c.Rect=a,a.defaults={x:0,y:0,width:0,height:0},a.prototype.contains=function(a){var b=a.width||0,c=a.height||0;return this.x<=a.x&&this.y<=a.y&&this.x+this.width>=a.x+b&&this.y+this.height>=a.y+c},a.prototype.overlaps=function(a){var b=this.x+this.width,c=this.y+this.height,d=a.x+a.width,e=a.y+a.height;return this.x<d&&b>a.x&&this.y<e&&c>a.y},a.prototype.getMaximalFreeRects=function(b){if(!this.overlaps(b))return!1;var c,d=[],e=this.x+this.width,f=this.y+this.height,g=b.x+b.width,h=b.y+b.height;return this.y<b.y&&(c=new a({x:this.x,y:this.y,width:this.width,height:b.y-this.y}),d.push(c)),e>g&&(c=new a({x:g,y:this.y,width:e-g,height:this.height}),d.push(c)),f>h&&(c=new a({x:this.x,y:h,width:this.width,height:f-h}),d.push(c)),this.x<b.x&&(c=new a({x:this.x,y:this.y,width:b.x-this.x,height:this.height}),d.push(c)),d},a.prototype.canFit=function(a){return this.width>=a.width&&this.height>=a.height},a}var c=a.Packery=function(){};"function"==typeof define&&define.amd?define("packery/js/rect",b):"object"==typeof exports?module.exports=b():(a.Packery=a.Packery||{},a.Packery.Rect=b())}(window),function(a){function b(a){function b(a,b,c){this.width=a||0,this.height=b||0,this.sortDirection=c||"downwardLeftToRight",this.reset()}b.prototype.reset=function(){this.spaces=[],this.newSpaces=[];var b=new a({x:0,y:0,width:this.width,height:this.height});this.spaces.push(b),this.sorter=c[this.sortDirection]||c.downwardLeftToRight},b.prototype.pack=function(a){for(var b=0,c=this.spaces.length;c>b;b++){var d=this.spaces[b];if(d.canFit(a)){this.placeInSpace(a,d);break}}},b.prototype.placeInSpace=function(a,b){a.x=b.x,a.y=b.y,this.placed(a)},b.prototype.placed=function(a){for(var b=[],c=0,d=this.spaces.length;d>c;c++){var e=this.spaces[c],f=e.getMaximalFreeRects(a);f?b.push.apply(b,f):b.push(e)}this.spaces=b,this.mergeSortSpaces()},b.prototype.mergeSortSpaces=function(){b.mergeRects(this.spaces),this.spaces.sort(this.sorter)},b.prototype.addSpace=function(a){this.spaces.push(a),this.mergeSortSpaces()},b.mergeRects=function(a){for(var b=0,c=a.length;c>b;b++){var d=a[b];if(d){var e=a.slice(0);e.splice(b,1);for(var f=0,g=0,h=e.length;h>g;g++){var i=e[g],j=b>g?0:1;d.contains(i)&&(a.splice(g+j-f,1),f++)}}}return a};var c={downwardLeftToRight:function(a,b){return a.y-b.y||a.x-b.x},rightwardTopToBottom:function(a,b){return a.x-b.x||a.y-b.y}};return b}if("function"==typeof define&&define.amd)define("packery/js/packer",["./rect"],b);else if("object"==typeof exports)module.exports=b(require("./rect"));else{var c=a.Packery=a.Packery||{};c.Packer=b(c.Rect)}}(window),function(a){function b(a,b,c){var d=a("transform"),e=function(){b.Item.apply(this,arguments)};e.prototype=new b.Item;var f=e.prototype._create;return e.prototype._create=function(){f.call(this),this.rect=new c,this.placeRect=new c},e.prototype.dragStart=function(){this.getPosition(),this.removeTransitionStyles(),this.isTransitioning&&d&&(this.element.style[d]="none"),this.getSize(),this.isPlacing=!0,this.needsPositioning=!1,this.positionPlaceRect(this.position.x,this.position.y),this.isTransitioning=!1,this.didDrag=!1},e.prototype.dragMove=function(a,b){this.didDrag=!0;var c=this.layout.size;a-=c.paddingLeft,b-=c.paddingTop,this.positionPlaceRect(a,b)},e.prototype.dragStop=function(){this.getPosition();var a=this.position.x!==this.placeRect.x,b=this.position.y!==this.placeRect.y;this.needsPositioning=a||b,this.didDrag=!1},e.prototype.positionPlaceRect=function(a,b,c){this.placeRect.x=this.getPlaceRectCoord(a,!0),this.placeRect.y=this.getPlaceRectCoord(b,!1,c)},e.prototype.getPlaceRectCoord=function(a,b,c){var d=b?"Width":"Height",e=this.size["outer"+d],f=this.layout[b?"columnWidth":"rowHeight"],g=this.layout.size["inner"+d];b||(g=Math.max(g,this.layout.maxY),this.layout.rowHeight||(g-=this.layout.gutter));var h;if(f){f+=this.layout.gutter,g+=b?this.layout.gutter:0,a=Math.round(a/f);var i;i=this.layout.options.isHorizontal?b?"ceil":"floor":b?"floor":"ceil";var j=Math[i](g/f);j-=Math.ceil(e/f),h=j}else h=g-e;return a=c?a:Math.min(a,h),a*=f||1,Math.max(0,a)},e.prototype.copyPlaceRectPosition=function(){this.rect.x=this.placeRect.x,this.rect.y=this.placeRect.y},e.prototype.removeElem=function(){this.element.parentNode.removeChild(this.element),this.layout.packer.addSpace(this.rect),this.emitEvent("remove",[this])},e}"function"==typeof define&&define.amd?define("packery/js/item",["get-style-property/get-style-property","outlayer/outlayer","./rect"],b):"object"==typeof exports?module.exports=b(require("desandro-get-style-property"),require("outlayer"),require("./rect")):a.Packery.Item=b(a.getStyleProperty,a.Outlayer,a.Packery.Rect)}(window),function(a){function b(a,b,c,d,e,f){function g(a,b){return a.position.y-b.position.y||a.position.x-b.position.x}function h(a,b){return a.position.x-b.position.x||a.position.y-b.position.y}d.prototype.canFit=function(a){return this.width>=a.width-1&&this.height>=a.height-1};var i=c.create("packery");return i.Item=f,i.prototype._create=function(){c.prototype._create.call(this),this.packer=new e,this.stamp(this.options.stamped);var a=this;this.handleDraggabilly={dragStart:function(b){a.itemDragStart(b.element)},dragMove:function(b){a.itemDragMove(b.element,b.position.x,b.position.y)},dragEnd:function(b){a.itemDragEnd(b.element)}},this.handleUIDraggable={start:function(b){a.itemDragStart(b.currentTarget)},drag:function(b,c){a.itemDragMove(b.currentTarget,c.position.left,c.position.top)},stop:function(b){a.itemDragEnd(b.currentTarget)}}}
4556,i.prototype._resetLayout=function(){this.getSize(),this._getMeasurements();var a=this.packer;this.options.isHorizontal?(a.width=Number.POSITIVE_INFINITY,a.height=this.size.innerHeight+this.gutter,a.sortDirection="rightwardTopToBottom"):(a.width=this.size.innerWidth+this.gutter,a.height=Number.POSITIVE_INFINITY,a.sortDirection="downwardLeftToRight"),a.reset(),this.maxY=0,this.maxX=0},i.prototype._getMeasurements=function(){this._getMeasurement("columnWidth","width"),this._getMeasurement("rowHeight","height"),this._getMeasurement("gutter","width")},i.prototype._getItemLayoutPosition=function(a){return this._packItem(a),a.rect},i.prototype._packItem=function(a){this._setRectSize(a.element,a.rect),this.packer.pack(a.rect),this._setMaxXY(a.rect)},i.prototype._setMaxXY=function(a){this.maxX=Math.max(a.x+a.width,this.maxX),this.maxY=Math.max(a.y+a.height,this.maxY)},i.prototype._setRectSize=function(a,c){var d=b(a),e=d.outerWidth,f=d.outerHeight;(e||f)&&(e=this._applyGridGutter(e,this.columnWidth),f=this._applyGridGutter(f,this.rowHeight)),c.width=Math.min(e,this.packer.width),c.height=Math.min(f,this.packer.height)},i.prototype._applyGridGutter=function(a,b){if(!b)return a+this.gutter;b+=this.gutter;var c=a%b,d=c&&1>c?"round":"ceil";return a=Math[d](a/b)*b},i.prototype._getContainerSize=function(){return this.options.isHorizontal?{width:this.maxX-this.gutter}:{height:this.maxY-this.gutter}},i.prototype._manageStamp=function(a){var b,c=this.getItem(a);if(c&&c.isPlacing)b=c.placeRect;else{var e=this._getElementOffset(a);b=new d({x:this.options.isOriginLeft?e.left:e.right,y:this.options.isOriginTop?e.top:e.bottom})}this._setRectSize(a,b),this.packer.placed(b),this._setMaxXY(b)},i.prototype.sortItemsByPosition=function(){var a=this.options.isHorizontal?h:g;this.items.sort(a)},i.prototype.fit=function(a,b,c){var d=this.getItem(a);d&&(this._getMeasurements(),this.stamp(d.element),d.getSize(),d.isPlacing=!0,b=void 0===b?d.rect.x:b,c=void 0===c?d.rect.y:c,d.positionPlaceRect(b,c,!0),this._bindFitEvents(d),d.moveTo(d.placeRect.x,d.placeRect.y),this.layout(),this.unstamp(d.element),this.sortItemsByPosition(),d.isPlacing=!1,d.copyPlaceRectPosition())},i.prototype._bindFitEvents=function(a){function b(){d++,2===d&&c.emitEvent("fitComplete",[c,a])}var c=this,d=0;a.on("layout",function(){return b(),!0}),this.on("layoutComplete",function(){return b(),!0})},i.prototype.resize=function(){var a=b(this.element),c=this.size&&a,d=this.options.isHorizontal?"innerHeight":"innerWidth";c&&a[d]===this.size[d]||this.layout()},i.prototype.itemDragStart=function(a){this.stamp(a);var b=this.getItem(a);b&&b.dragStart()},i.prototype.itemDragMove=function(a,b,c){function d(){f.layout(),delete f.dragTimeout}var e=this.getItem(a);e&&e.dragMove(b,c);var f=this;this.clearDragTimeout(),this.dragTimeout=setTimeout(d,40)},i.prototype.clearDragTimeout=function(){this.dragTimeout&&clearTimeout(this.dragTimeout)},i.prototype.itemDragEnd=function(b){var c,d=this.getItem(b);if(d&&(c=d.didDrag,d.dragStop()),!d||!c&&!d.needsPositioning)return void this.unstamp(b);a.add(d.element,"is-positioning-post-drag");var e=this._getDragEndLayoutComplete(b,d);d.needsPositioning?(d.on("layout",e),d.moveTo(d.placeRect.x,d.placeRect.y)):d&&d.copyPlaceRectPosition(),this.clearDragTimeout(),this.on("layoutComplete",e),this.layout()},i.prototype._getDragEndLayoutComplete=function(b,c){var d=c&&c.needsPositioning,e=0,f=d?2:1,g=this;return function(){return e++,e!==f?!0:(c&&(a.remove(c.element,"is-positioning-post-drag"),c.isPlacing=!1,
4556c.copyPlaceRectPosition()),g.unstamp(b),g.sortItemsByPosition(),d&&g.emitEvent("dragItemPositioned",[g,c]),!0)}},i.prototype.bindDraggabillyEvents=function(a){a.on("dragStart",this.handleDraggabilly.dragStart),a.on("dragMove",this.handleDraggabilly.dragMove),a.on("dragEnd",this.handleDraggabilly.dragEnd)},i.prototype.bindUIDraggableEvents=function(a){a.on("dragstart",this.handleUIDraggable.start).on("drag",this.handleUIDraggable.drag).on("dragstop",this.handleUIDraggable.stop)},i.Rect=d,i.Packer=e,i}"function"==typeof define&&define.amd?define("packery/js/packery",["classie/classie","get-size/get-size","outlayer/outlayer","./rect","./packer","./item"],b):"object"==typeof exports?module.exports=b(require("desandro-classie"),require("get-size"),require("outlayer"),require("./rect"),require("./packer"),require("./item")):a.Packery=b(a.classie,a.getSize,a.Outlayer,a.Packery.Rect,a.Packery.Packer,a.Packery.Item)}(window),function(a){function b(a,b){for(var c in b)a[c]=b[c];return a}function c(a,c,d){var e=a.create("packery"),f=e.prototype._getElementOffset,g=e.prototype._getMeasurement;b(e.prototype,c.prototype),e.prototype._getElementOffset=f,e.prototype._getMeasurement=g;var h=e.prototype._resetLayout;e.prototype._resetLayout=function(){this.packer=this.packer||new c.Packer,h.apply(this,arguments)};var i=e.prototype._getItemLayoutPosition;e.prototype._getItemLayoutPosition=function(a){return a.rect=a.rect||new c.Rect,i.call(this,a)};var j=e.prototype._manageStamp;return e.prototype._manageStamp=function(){this.options.isOriginLeft=this.isotope.options.isOriginLeft,this.options.isOriginTop=this.isotope.options.isOriginTop,j.apply(this,arguments)},e.prototype.needsResizeLayout=function(){var a=d(this.element),b=this.size&&a,c=this.options.isHorizontal?"innerHeight":"innerWidth";return b&&a[c]!==this.size[c]},e}"function"==typeof define&&define.amd?define(["isotope/js/layout-mode","packery/js/packery","get-size/get-size"],c):"object"==typeof exports?module.exports=c(require("isotope-layout/js/layout-mode"),require("packery"),require("get-size")):c(a.Isotope.LayoutMode,a.Packery,a.getSize)}(window);
4557
4558/*!
4559 * cellsByRows layout mode for Isotope
4560 * v1.1.2
4561 * http://isotope.metafizzy.co/layout-modes/cellsbyrow.html
4562 */
4563
4564/*jshint browser: true, devel: false, strict: true, undef: true, unused: true */
4565
4566( function( window ) {
4567
4568'use strict';
4569
4570function cellsByRowDefinition( LayoutMode ) {
4571
4572  var CellsByRow = LayoutMode.create( 'cellsByRow' );
4573
4574  CellsByRow.prototype._resetLayout = function() {
4575    // reset properties
4576    this.itemIndex = 0;
4577    // measurements
4578    this.getColumnWidth();
4579    this.getRowHeight();
4580    // set cols
4581    this.cols = Math.floor( this.isotope.size.innerWidth / this.columnWidth );
4582    this.cols = Math.max( this.cols, 1 );
4583  };
4584
4585  CellsByRow.prototype._getItemLayoutPosition = function( item ) {
4586    item.getSize();
4587    var col = this.itemIndex % this.cols;
4588    var row = Math.floor( this.itemIndex / this.cols );
4589    // center item within cell
4590    var x = ( col + 0.5 ) * this.columnWidth - item.size.outerWidth / 2;
4591    var y = ( row + 0.5 ) * this.rowHeight - item.size.outerHeight / 2;
4592    this.itemIndex++;
4593    return { x: x, y: y };
4594  };
4595
4596  CellsByRow.prototype._getContainerSize = function() {
4597    return {
4598      height: Math.ceil( this.itemIndex / this.cols ) * this.rowHeight
4599    };
4600  };
4601
4602  return CellsByRow;
4603
4604}
4605
4606if ( typeof define === 'function' && define.amd ) {
4607  // AMD
4608  define( [
4609      'isotope/js/layout-mode'
4610    ],
4611    cellsByRowDefinition );
4612} else if ( typeof exports === 'object' ) {
4613  // CommonJS
4614  module.exports = cellsByRowDefinition(
4615    require('isotope-layout/js/layout-mode')
4616  );
4617} else {
4618  // browser global
4619  cellsByRowDefinition(
4620    window.Isotope.LayoutMode
4621  );
4622}
4623
4624})( window );
4625
4626/*!
4627   --------------------------------
4628   Infinite Scroll
4629   --------------------------------
4630   + https://github.com/paulirish/infinite-scroll
4631   + version 2.1.0
4632   + Copyright 2011/12 Paul Irish & Luke Shumard
4633   + Licensed under the MIT license
4634
4635   + Documentation: http://infinite-scroll.com/
4636*/
4637;(function(e){if(typeof define==="function"&&define.amd){define(["jquery"],e)}else{e(jQuery)}})(function(e,t){"use strict";e.infinitescroll=function(n,r,i){this.element=e(i);if(!this._create(n,r)){this.failed=true}};e.infinitescroll.defaults={loading:{finished:t,finishedMsg:"<em>Congratulations, you've reached the end of the internet.</em>",img:"data:image/gif;
4637base64,R0lGODlh3AATAPQeAPDy+MnQ6LW/4N3h8MzT6rjC4sTM5r/I5NHX7N7j8c7U6tvg8OLl8uXo9Ojr9b3G5MfP6Ovu9tPZ7PT1+vX2+tbb7vf4+8/W69jd7rC73vn5/O/x+K243ai02////wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQECgD/ACwAAAAA3AATAAAF/6AnjmRpnmiqrmzrvnAsz3Rt33iu73zv/8CgcEj0BAScpHLJbDqf0Kh0Sq1ar9isdioItAKGw+MAKYMFhbF63CW438f0mg1R2O8EuXj/aOPtaHx7fn96goR4hmuId4qDdX95c4+RBIGCB4yAjpmQhZN0YGYGXitdZBIVGAsLoq4BBKQDswm1CQRkcG6ytrYKubq8vbfAcMK9v7q7EMO1ycrHvsW6zcTKsczNz8HZw9vG3cjTsMIYqQkCLBwHCgsMDQ4RDAYIqfYSFxDxEfz88/X38Onr16+Bp4ADCco7eC8hQYMAEe57yNCew4IVBU7EGNDiRn8Z831cGLHhSIgdFf9chIeBg7oA7gjaWUWTVQAGE3LqBDCTlc9WOHfm7PkTqNCh54rePDqB6M+lR536hCpUqs2gVZM+xbrTqtGoWqdy1emValeXKzggYBBB5y1acFNZmEvXAoN2cGfJrTv3bl69Ffj2xZt3L1+/fw3XRVw4sGDGcR0fJhxZsF3KtBTThZxZ8mLMgC3fRatCbYMNFCzwLEqLgE4NsDWs/tvqdezZf13Hvk2A9Szdu2X3pg18N+68xXn7rh1c+PLksI/Dhe6cuO3ow3NfV92bdArTqC2Ebd3A8vjf5QWfH6Bg7Nz17c2fj69+fnq+8N2Lty+fuP78/eV2X13neIcCeBRwxorbZrA1ANoCDGrgoG8RTshahQ9iSKEEzUmYIYfNWViUhheCGJyIP5E4oom7WWjgCeBFAJNv1DVV01MAdJhhjdkplWNzO/5oXI846njjVEIqR2OS2B1pE5PVscajkxhMycqLJghQSwT40PgfAl4GqNSXYdZXJn5gSkmmmmJu1aZYb14V51do+pTOCmA40AqVCIhG5IJ9PvYnhIFOxmdqhpaI6GeHCtpooisuutmg+Eg62KOMKuqoTaXgicQWoIYq6qiklmoqFV0UoeqqrLbq6quwxirrrLTWauutJ4QAACH5BAUKABwALAcABADOAAsAAAX/IPd0D2dyRCoUp/k8gpHOKtseR9yiSmGbuBykler9XLAhkbDavXTL5k2oqFqNOxzUZPU5YYZd1XsD72rZpBjbeh52mSNnMSC8lwblKZGwi+0QfIJ8CncnCoCDgoVnBHmKfByGJimPkIwtiAeBkH6ZHJaKmCeVnKKTHIihg5KNq4uoqmEtcRUtEREMBggtEr4QDrjCuRC8h7/BwxENeicSF8DKy82pyNLMOxzWygzFmdvD2L3P0dze4+Xh1Arkyepi7dfFvvTtLQkZBC0T/FX3CRgCMOBHsJ+EHYQY7OinAGECgQsB+Lu3AOK+CewcWjwxQeJBihtNGHSoQOE+iQ3//4XkwBBhRZMcUS6YSXOAwIL8PGqEaSJCiYt9SNoCmnJPAgUVLChdaoFBURN8MAzl2PQphwQLfDFd6lTowglHve6rKpbjhK7/pG5VinZP1qkiz1rl4+tr2LRwWU64cFEihwEtZgbgR1UiHaMVvxpOSwBA37kzGz9e8G+B5MIEKLutOGEsAH2ATQwYfTmuX8aETWdGPZmiZcccNSzeTCA1Sw0bdiitC7LBWgu8jQr8HRzqgpK6gX88QbrB14z/kF+ELpwB8eVQj/JkqdylAudji/+ts3039vEEfK8Vz2dlvxZKG0CmbkKDBvllRd6fCzDvBLKBDSCeffhRJEFebFk1k/Mv9jVIoIJZSeBggwUaNeB+Qk34IE0cXlihcfRxkOAJFFhwGmKlmWDiakZhUJtnLBpnWWcnKaAZcxI0piFGGLBm1mc90kajSCveeBVWKeYEoU2wqeaQi0PetoE+rr14EpVC7oAbAUHqhYExbn2XHHsVqbcVew9tx8+XJKk5AZsqqdlddGpqAKdbAYBn1pcczmSTdWvdmZ17c1b3FZ99vnTdCRFM8OEcAhLwm1NdXnWcBBSMRWmfkWZqVlsmLIiAp/o1gGV2vpS4lalGYsUOqXrddcKCmK61aZ8SjEpUpVFVoCpTj4r661Km7kBHjrDyc1RAIQAAIfkEBQoAGwAsBwAEAM4ACwAABf/gtmUCd4goQQgFKj6PYKi0yrrbc8i4ohQt12EHcal+MNSQiCP8gigdz7iCioaCIvUmZLp8QBzW0EN2vSlCuDtFKaq4RyHzQLEKZNdiQDhRDVooCwkbfm59EAmKi4SGIm+AjIsKjhsqB4mSjT2IOIOUnICeCaB/mZKFNTSRmqVpmJqklSqskq6PfYYCDwYHDC4REQwGCBLGxxIQDsHMwhAIX8bKzcENgSLGF9PU1j3Sy9zX2NrgzQziChLk1BHWxcjf7N046tvN82715czn9Pryz6Ilc4ACj4EBOCZM8KEnAYYADBRKnACAYUMFv1wotIhCEcaJCisqwJFgAUSQGyX/kCSVUUTIdKMwJlyo0oXHlhskwrTJciZHEXsgaqS4s6PJiCAr1uzYU8kBBSgnWFqpoMJMUjGtDmUwkmfVmVypakWhEKvXsS4nhLW5wNjVroJIoc05wSzTr0PtiigpYe4EC2vj4iWrFu5euWIMRBhacaVJhYQBEFjA9jHjyQ0xEABwGceGAZYjY0YBOrRLCxUp29QM+bRkx5s7ZyYgVbTqwwti2ybJ+vLtDYpycyZbYOlptxdx0kV+V7lC5iJAyyRrwYKxAdiz82ng0/jnAdMJFz0cPi104Ec1Vj9/M6F173vKL/feXv156dw11tlqeMMnv4V5Ap53GmjQQH97nFfg+IFiucfgRX5Z8KAgbUlQ4IULIlghhhdOSB6AgX0IVn8eReghen3NRIBsRgnH4l4LuEidZBjwRpt6NM5WGwoW0KSjCwX6yJSMab2GwwAPDXfaBCtWpluRTQqC5JM5oUZAjUNS+VeOLWpJEQ7VYQANW0INJSZVDFSnZphjSikfmzE5N4EEbQI1QJmnWXCmHulRp2edwDXF43txukenJwvI9xyg9Q26Z3MzGUcBYFEChZh6DVTq34AU8Iflh51Sd+CnKFYQ6mmZkhqfBKfSxZWqA9DZanWjxmhrWwi0qtCrt/43K6WqVjjpmhIqgEGvculaGKklKstAACEAACH5BAUKABwALAcABADOAAsAAAX/ICdyQmaMYyAUqPgIBiHPxNpy79kqRXH8wAPsRmDdXpAWgWdEIYm2llCHqjVHU+jjJkwqBTecwItShMXkEfNWSh8e1NGAcLgpDGlRgk7EJ/6Ae3VKfoF/fDuFhohVeDeCfXkcCQqDVQcQhn+VNDOYmpSWaoqBlUSfmowjEA+iEAEGDRGztAwGCDcXEA60tXEiCrq8vREMEBLIyRLCxMWSH
4637MzExnbRvQ2Sy7vN0zvVtNfU2tLY3rPgLdnDvca4VQS/Cpk3ABwSLQkYAQwT/P309vcI7OvXr94jBQMJ/nskkGA/BQBRLNDncAIAiDcG6LsxAWOLiQzmeURBKWSLCQbv/1F0eDGinJUKR47YY1IEgQASKk7Yc7ACRwZm7mHweRJoz59BJUogisKCUaFMR0x4SlJBVBFTk8pZivTR0K73rN5wqlXEAq5Fy3IYgHbEzQ0nLy4QSoCjXLoom96VOJEeCosK5n4kkFfqXjl94wa+l1gvAcGICbewAOAxY8l/Ky/QhAGz4cUkGxu2HNozhwMGBnCUqUdBg9UuW9eUynqSwLHIBujePef1ZGQZXcM+OFuEBeBhi3OYgLyqcuaxbT9vLkf4SeqyWxSQpKGB2gQpm1KdWbu72rPRzR9Ne2Nu9Kzr/1Jqj0yD/fvqP4aXOt5sW/5qsXXVcv1Nsp8IBUAmgswGF3llGgeU1YVXXKTN1FlhWFXW3gIE+DVChApysACHHo7Q4A35lLichh+ROBmLKAzgYmYEYDAhCgxKGOOMn4WR4kkDaoBBOxJtdNKQxFmg5JIWIBnQc07GaORfUY4AEkdV6jHlCEISSZ5yTXpp1pbGZbkWmcuZmQCaE6iJ0FhjMaDjTMsgZaNEHFRAQVp3bqXnZED1qYcECOz5V6BhSWCoVJQIKuKQi2KFKEkEFAqoAo7uYSmO3jk61wUUMKmknJ4SGimBmAa0qVQBhAAAIfkEBQoAGwAsBwAEAM4ACwAABf/gJm5FmRlEqhJC+bywgK5pO4rHI0D3pii22+Mg6/0Ej96weCMAk7cDkXf7lZTTnrMl7eaYoy10JN0ZFdco0XAuvKI6qkgVFJXYNwjkIBcNBgR8TQoGfRsJCRuCYYQQiI+ICosiCoGOkIiKfSl8mJkHZ4U9kZMbKaI3pKGXmJKrngmug4WwkhA0lrCBWgYFCCMQFwoQDRHGxwwGCBLMzRLEx8iGzMMO0cYNeCMKzBDW19lnF9DXDIY/48Xg093f0Q3s1dcR8OLe8+Y91OTv5wrj7o7B+7VNQqABIoRVCMBggsOHE36kSoCBIcSH3EbFangxogJYFi8CkJhqQciLJEf/LDDJEeJIBT0GsOwYUYJGBS0fjpQAMidGmyVP6sx4Y6VQhzs9VUwkwqaCCh0tmKoFtSMDmBOf9phg4SrVrROuasRQAaxXpVUhdsU6IsECZlvX3kwLUWzRt0BHOLTbNlbZG3vZinArge5Dvn7wbqtQkSYAAgtKmnSsYKVKo2AfW048uaPmG386i4Q8EQMBAIAnfB7xBxBqvapJ9zX9WgRS2YMpnvYMGdPK3aMjt/3dUcNI4blpj7iwkMFWDXDvSmgAlijrt9RTR78+PS6z1uAJZIe93Q8g5zcsWCi/4Y+C8bah5zUv3vv89uft30QP23punGCx5954oBBwnwYaNCDY/wYrsYeggnM9B2Fpf8GG2CEUVWhbWAtGouEGDy7Y4IEJVrbSiXghqGKIo7z1IVcXIkKWWR361QOLWWnIhwERpLaaCCee5iMBGJQmJGyPFTnbkfHVZGRtIGrg5HALEJAZbu39BuUEUmq1JJQIPtZilY5hGeSWsSk52G9XqsmgljdIcABytq13HyIM6RcUA+r1qZ4EBF3WHWB29tBgAzRhEGhig8KmqKFv8SeCeo+mgsF7YFXa1qWSbkDpom/mqR1PmHCqJ3fwNRVXjC7S6CZhFVCQ2lWvZiirhQq42SACt25IK2hv8TprriUV1usGgeka7LFcNmCldMLi6qZMgFLgpw16Cipb7bC1knXsBiEAACH5BAUKABsALAcABADOAAsAAAX/4FZsJPkUmUGsLCEUTywXglFuSg7fW1xAvNWLF6sFFcPb42C8EZCj24EJdCp2yoegWsolS0Uu6fmamg8n8YYcLU2bXSiRaXMGvqV6/KAeJAh8VgZqCX+BexCFioWAYgqNi4qAR4ORhRuHY408jAeUhAmYYiuVlpiflqGZa5CWkzc5fKmbbhIpsAoQDRG8vQwQCBLCwxK6vb5qwhfGxxENahvCEA7NzskSy7vNzzzK09W/PNHF1NvX2dXcN8K55cfh69Luveol3vO8zwi4Yhj+AQwmCBw4IYclDAAJDlQggVOChAoLKkgFkSCAHDwWLKhIEOONARsDKryogFPIiAUb/95gJNIiw4wnI778GFPhzBKFOAq8qLJEhQpiNArjMcHCmlTCUDIouTKBhApELSxFWiGiVKY4E2CAekPgUphDu0742nRrVLJZnyrFSqKQ2ohoSYAMW6IoDpNJ4bLdILTnAj8KUF7UeENjAKuDyxIgOuGiOI0EBBMgLNew5AUrDTMGsFixwBIaNCQuAXJB57qNJ2OWm2Aj4skwCQCIyNkhhtMkdsIuodE0AN4LJDRgfLPtn5YDLdBlraAByuUbBgxQwICxMOnYpVOPej074OFdlfc0TqC62OIbcppHjV4o+LrieWhfT8JC/I/T6W8oCl29vQ0XjLdBaA3s1RcPBO7lFvpX8BVoG4O5jTXRQRDuJ6FDTzEWF1/BCZhgbyAKE9qICYLloQYOFtahVRsWYlZ4KQJHlwHS/IYaZ6sZd9tmu5HQm2xi1UaTbzxYwJk/wBF5g5EEYOBZeEfGZmNdFyFZmZIR4jikbLThlh5kUUVJGmRT7sekkziRWUIACABk3T4qCsedgO4xhgGcY7q5pHJ4klBBTQRJ0CeHcoYHHUh6wgfdn9uJdSdMiebGJ0zUPTcoS286FCkrZxnYoYYKWLkBowhQoBeaOlZAgVhLidrXqg2G
4637iqpQpZ4apwSwRtjqrB3muoF9BboaXKmshlqWqsWiGt2wphJkQbAU5hoCACH5BAUKABsALAcABADOAAsAAAX/oGFw2WZuT5oZROsSQnGaKjRvilI893MItlNOJ5v5gDcFrHhKIWcEYu/xFEqNv6B1N62aclysF7fsZYe5aOx2yL5aAUGSaT1oTYMBwQ5VGCAJgYIJCnx1gIOBhXdwiIl7d0p2iYGQUAQBjoOFSQR/lIQHnZ+Ue6OagqYzSqSJi5eTpTxGcjcSChANEbu8DBAIEsHBChe5vL13G7fFuscRDcnKuM3H0La3EA7Oz8kKEsXazr7Cw9/Gztar5uHHvte47MjktznZ2w0G1+D3BgirAqJmJMAQgMGEgwgn5Ei0gKDBhBMALGRYEOJBb5QcWlQo4cbAihZz3GgIMqFEBSM1/4ZEOWPAgpIIJXYU+PIhRG8ja1qU6VHlzZknJNQ6UanCjQkWCIGSUGEjAwVLjc44+DTqUQtPPS5gejUrTa5TJ3g9sWCr1BNUWZI161StiQUDmLYdGfesibQ3XMq1OPYthrwuA2yU2LBs2cBHIypYQPPlYAKFD5cVvNPtW8eVGbdcQADATsiNO4cFAPkvHpedPzc8kUcPgNGgZ5RNDZG05reoE9s2vSEP79MEGiQGy1qP8LA4ZcdtsJE48ONoLTBtTV0B9LsTnPceoIDBDQvS7W7vfjVY3q3eZ4A339J4eaAmKqU/sV58HvJh2RcnIBsDUw0ABqhBA5aV5V9XUFGiHfVeAiWwoFgJJrIXRH1tEMiDFV4oHoAEGlaWhgIGSGBO2nFomYY3mKjVglidaNYJGJDkWW2xxTfbjCbVaOGNqoX2GloR8ZeTaECS9pthRGJH2g0b3Agbk6hNANtteHD2GJUucfajCQBy5OOTQ25ZgUPvaVVQmbKh9510/qQpwXx3SQdfk8tZJOd5b6JJFplT3ZnmmX3qd5l1eg5q00HrtUkUn0AKaiGjClSAgKLYZcgWXwocGRcCFGCKwSB6ceqphwmYRUFYT/1WKlOdUpipmxW0mlCqHjYkAaeoZlqrqZ4qd+upQKaapn/AmgAegZ8KUtYtFAQQAgAh+QQFCgAbACwHAAQAzgALAAAF/+C2PUcmiCiZGUTrEkKBis8jQEquKwU5HyXIbEPgyX7BYa5wTNmEMwWsSXsqFbEh8DYs9mrgGjdK6GkPY5GOeU6ryz7UFopSQEzygOGhJBjoIgMDBAcBM0V/CYqLCQqFOwobiYyKjn2TlI6GKC2YjJZknouaZAcQlJUHl6eooJwKooobqoewrJSEmyKdt59NhRKFMxLEEA4RyMkMEAjDEhfGycqAG8TQx9IRDRDE3d3R2ctD1RLg0ttKEnbY5wZD3+zJ6M7X2RHi9Oby7u/r9g38UFjTh2xZJBEBMDAboogAgwkQI07IMUORwocSJwCgWDFBAIwZOaJIsOBjRogKJP8wTODw5ESVHVtm3AhzpEeQElOuNDlTZ0ycEUWKWFASqEahGwYUPbnxoAgEdlYSqDBkgoUNClAlIHbSAoOsqCRQnQHxq1axVb06FWFxLIqyaze0Tft1JVqyE+pWXMD1pF6bYl3+HTqAWNW8cRUFzmih0ZAAB2oGKukSAAGGRHWJgLiR6AylBLpuHKKUMlMCngMpDSAa9QIUggZVVvDaJobLeC3XZpvgNgCmtPcuwP3WgmXSq4do0DC6o2/guzcseECtUoO0hmcsGKDgOt7ssBd07wqesAIGZC1YIBa7PQHvb1+SFo+++HrJSQfB33xfav3i5eX3Hnb4CTJgegEq8tH/YQEOcIJzbm2G2EoYRLgBXFpVmFYDcREV4HIcnmUhiGBRouEMJGJGzHIspqgdXxK0yCKHRNXoIX4uorCdTyjkyNtdPWrA4Up82EbAbzMRxxZRR54WXVLDIRmRcag5d2R6ugl3ZXzNhTecchpMhIGVAKAYpgJjjsSklBEd99maZoo535ZvdamjBEpusJyctg3h4X8XqodBMx0tiNeg/oGJaKGABpogS40KSqiaEgBqlQWLUtqoVQnytekEjzo0hHqhRorppOZt2p923M2AAV+oBtpAnnPNoB6HaU6mAAIU+IXmi3j2mtFXuUoHKwXpzVrsjcgGOauKEjQrwq157hitGq2NoWmjh7z6Wmxb0m5w66+2VRAuXN/yFUAIACH5BAUKABsALAcABADOAAsAAAX/4CZuRiaM45MZqBgIRbs9AqTcuFLE7VHLOh7KB5ERdjJaEaU4ClO/lgKWjKKcMiJQ8KgumcieVdQMD8cbBeuAkkC6LYLhOxoQ2PF5Ys9PKPBMen17f0CCg4VSh32JV4t8jSNqEIOEgJKPlkYBlJWRInKdiJdkmQlvKAsLBxdABA4RsbIMBggtEhcQsLKxDBC2TAS6vLENdJLDxMZAubu8vjIbzcQRtMzJz79S08oQEt/guNiyy7fcvMbh4OezdAvGrakLAQwyABsELQkY9BP+//ckyPDD4J9BfAMh1GsBoImMeQUN+lMgUJ9CiRMa5msxoB9Gh/o8GmxYMZXIgxtR/yQ46S/gQAURR0pDwYDfywoyLPip5AdnCwsMFPBU4BPFhKBDi444quCmDKZOfwZ9KEGpCKgcN1jdALSpPqIYsabS+nSqvqplvYqQYAeDPgwKwjaMtiDl0oaqUAyo+3TuWwUAMPpVCfee0cEjVBGQq2ABx7oTWmQk4FglZMGN9fGVDMCuiH2AOVOu/PmyxM630gwM0CCn6q8LjVJ8GXvpa5Uwn95OTC/nNxkda1/dLSK475IjCD6dHbK1ZOa4hXP9DXs5chJ00UpVm5xo2qRpoxptwF2E4/IbJpB/SDz9+q9b1aNfQH08+p4a8uvX8B53fLP+ycAfemjsRUBgp1H20K+BghHgVgt1GXZXZpZ5lt4ECjxYR4ScUWiShEtZqBiIInRGWnERNnjiBglw+JyGnxUmGowsyiiZg189lNtPGACjV2+S9UjbU0JWF6SPvEk3QZEqsZYTk3UAaRSUnznJI5LmESCdBVSyaOWUWLK4I5gDUYVeV1T9l+FZClCAUVA09uSmRHBCKAECFEhW51ht6rnmWBXkaR+NjuHpJ40D3DmnQXt2F+ihZxlqVKOfQRACACH5BAUKABwALAcABADOAAsAAAX/ICdyUCkUo/g8mUG8MCGkKgspeC6j6XEIEBpBUeCNfECaglBcOVfJFK7YQwZHQ6JRZBUqTrSuVEuD3nI45pYjFuWKvjjSkCoRaBUMWxkwBGgJCXspQ36Bh4EEB0oKhoiBgyNLjo8Ki4QElIiWfJqHnISNEI+Ql5J9o6SgkqKkgqYihamPkW6oNBgSfiMMDQkGCBLCwxIQDhHIyQwQCGMKxsnKVyPCF9DREQ3MxMPX0cu4wt7J2uHWx9jlKd3o39MiuefYEcvNkuLt5O8c1ePI2tyELXGQwoGDAQf+iEC2xByDCRAjTlAgIUWCBRgCPJQ4AQBFXAs0coT40WLIjRxL/47AcHLkxIomRXL0CHPERZkpa4q4iVKiyp0tR/7kwHMkTUBBJR5dOCEBAVcKKtCAyOHpowXCpk7goABqBZdcvWploACpBKkpIJI1q5OD2rIWE0R1uTZu1LFwbWL9OlKuWb4c6+o9i3dEgw0RCGDUG9KlRw56gDY2qmCByZBaASi+TACA0TucAaTteCcy0ZuOK3N2vJlx58+LRQyY3Xm0ZsgjZg+oPQLi7dUcNXi0LOJw1pgNtB7XG6CBy+U75SYfPTSQAgZTNUDnQHt67wnbZyvwLgKiMN3oCZB3C76tdewpLFgIP2C88rbi4Y+QT3+8S5USMICZXWj1pkEDeUU3lOYGB3alSoEiMIjgX4WlgNF2EibIwQIXauWXSRg2SAOHIU5IIIMoZkhhWiJaiFVbKo6AQEgQXrTAazO1JhkBrBG3Y2Y6EsUhaGn95hprSN0oWpFE7rhkeaQBchGOEWnwEmc0uKWZj0LeuNV3W4Y2lZHFlQCSRjTIl8uZ+kG5HU/3sRlnTG2ytyadytnD3HrmuRcSn+0h1dycexIK1KCjYaCnjCCVqOFFJTZ5GkUUjESWaUIKU2lgCmAKKQIUjHapXRKE+t2og1VgankNYnohqKJ2CmKplso6GKz7WYCgqxeuyoF8u9IQAgA7",msg:null,msgText:"<em>Loading the next set of posts...</em>",selector:null,speed:"fast",start:t},state:{isDuringAjax:false,isInvalidPage:false,isDestroyed:false,isDone:false,isPaused:false,isBeyondMaxPage:false,currPage:1},debug:false,behavior:t,binder:e(window),nextSelector:"div.navigation a:first",navSelector:"div.navigation",contentSelector:null,extraScrollPx:150,itemSelector:"div.post",animate:false,pathParse:t,dataType:"html",appendCallback:true,bufferPx:40,errorCallback:function(){},infid:0,pixelsFromNavToBottom:t,path:t,prefill:false,maxPage:t};e.infinitescroll.prototype={_binding:function(n){var r=this,i=r.options;i.v="2.0b2.120520";if(!!i.behavior&&this["_binding_"+i.behavior]!==t){this["_binding_"+i.behavior].call(this);return}if(n!=="bind"&&n!=="unbind"){this._debug("Binding value  "+n+" not valid");return false}if(n==="unbind"){this.options.binder.unbind("smartscroll.infscr."+r.options.infid)}else{this.options.binder[n]("smartscroll.infscr."+r.options.infid,function(){r.scroll()})}this._debug("Binding",n)},_create:function(r,i){var s=e.extend(true,{},e.infinitescroll.defaults,r);this.options=s;var o=e(window);var u=this;if(!u._validate(r)){return false}var a=e(s.nextSelector).attr("href");if(!a){this._debug("Navigation selector not found");return false}s.path=s.path||this._determinepath(a);s.contentSelector=s.contentSelector||this.element;s.loading.selector=s.loading.selector||s.contentSelector;s.loading.msg=s.loading.msg||e('<div id="infscr-loading"><img alt="Loading..." src="'+s.loading.img+'" /><div>'+s.loading.msgText+"</div></div>");(new Image).src=s.loading.img;if(s.pixelsFromNavToBottom===t){s.pixelsFromNavToBottom=e(document).height()-e(s.navSelector).offset().top;this._debug("pixelsFromNavToBottom: "+s.pixelsFromNavToBottom)}var f=this;s.loading.start=s.loading.start||function(){e(s.navSelector).hide();s.loading.msg.appendTo(s.loading.selector).show(s.loading.speed,e.proxy(function(){this.beginAjax(s)},f))};s.loading.finished=s.loading.finished||function(){if(!s.state.isBeyondMaxPage)s.loading.msg.fadeOut(s.loading.speed)};s.callback=function(n,r,u){if(!!s.behavior&&n["_callback_"+s.behavior]!==t){n["_callback_"+s.behavior].call(e(s.contentSelector)[0],r,u)}if(i){i.call(e(s.contentSelector)[0],r,s,u)}if(s.prefill){o.bind("resize.infinite-scroll",n._prefill)}};if(r.debug){if(Function.prototype.bind&&(typeof console==="object"||typeof console==="function")&&typeof console.log==="object"){["log","info","warn","error","assert","dir","clear","profile","profileEnd"].forEach(function(e){console[e]=this.call(console[e],console)},Function.prototype.bind)}}this._setup();if(s.prefill){this._prefill()}return true},_prefill:function(){function i(){return e(n.options.contentSelector).height()<=r.height()}var n=this;var r=e(window);this._prefill=function(){if(i()){n.scroll()}r.bind("resize.infinite-scroll",function(){if(i()){r.unbind("resize.infinite-scroll");n.scroll()}})};this._prefill()},_debug:function(){if(true!==this.options.debug){return}if(typeof console!=="undefined"&&typeof console.log==="function"){if(Array.prototype.slice.call(arguments).length===1&&typeof Array.prototype.slice.call(arguments)[0]==="str
4637ing"){console.log(Array.prototype.slice.call(arguments).toString())}else{console.log(Array.prototype.slice.call(arguments))}}else if(!Function.prototype.bind&&typeof console!=="undefined"&&typeof console.log==="object"){Function.prototype.call.call(console.log,console,Array.prototype.slice.call(arguments))}},_determinepath:function(n){var r=this.options;if(!!r.behavior&&this["_determinepath_"+r.behavior]!==t){return this["_determinepath_"+r.behavior].call(this,n)}if(!!r.pathParse){this._debug("pathParse manual");return r.pathParse(n,this.options.state.currPage+1)}else if(n.match(/^(.*?)\b2\b(.*?$)/)){n=n.match(/^(.*?)\b2\b(.*?$)/).slice(1)}else if(n.match(/^(.*?)2(.*?$)/)){if(n.match(/^(.*?page=)2(\/.*|$)/)){n=n.match(/^(.*?page=)2(\/.*|$)/).slice(1);return n}n=n.match(/^(.*?)2(.*?$)/).slice(1)}else{if(n.match(/^(.*?page=)1(\/.*|$)/)){n=n.match(/^(.*?page=)1(\/.*|$)/).slice(1);return n}else{this._debug("Sorry, we couldn't parse your Next (Previous Posts) URL. Verify your the css selector points to the correct A tag. If you still get this error: yell, scream, and kindly ask for help at infinite-scroll.com.");r.state.isInvalidPage=true}}this._debug("determinePath",n);return n},_error:function(n){var r=this.options;if(!!r.behavior&&this["_error_"+r.behavior]!==t){this["_error_"+r.behavior].call(this,n);return}if(n!=="destroy"&&n!=="end"){n="unknown"}this._debug("Error",n);if(n==="end"||r.state.isBeyondMaxPage){this._showdonemsg()}r.state.isDone=true;r.state.currPage=1;
4637r.state.isPaused=false;r.state.isBeyondMaxPage=false;this._binding("unbind")},_loadcallback:function(r,i,s){var o=this.options,u=this.options.callback,a=o.state.isDone?"done":!o.appendCallback?"no-append":"append",f;if(!!o.behavior&&this["_loadcallback_"+o.behavior]!==t){this["_loadcallback_"+o.behavior].call(this,r,i);return}switch(a){case"done":this._showdonemsg();return false;case"no-append":if(o.dataType==="html"){i="<div>"+i+"</div>";i=e(i).find(o.itemSelector)}if(i.length===0){return this._error("end")}break;case"append":var l=r.children();if(l.length===0){return this._error("end")}f=document.createDocumentFragment();while(r[0].firstChild){f.appendChild(r[0].firstChild)}this._debug("contentSelector",e(o.contentSelector)[0]);e(o.contentSelector)[0].appendChild(f);i=l.get();break}o.loading.finished.call(e(o.contentSelector)[0],o);if(o.animate){var c=e(window).scrollTop()+e(o.loading.msg).height()+o.extraScrollPx+"px";e("html,body").animate({scrollTop:c},800,function(){o.state.isDuringAjax=false})}if(!o.animate){o.state.isDuringAjax=false}u(this,i,s);if(o.prefill){this._prefill()}},_nearbottom:function(){var r=this.options,i=0+e(document).height()-r.binder.scrollTop()-e(window).height();if(!!r.behavior&&this["_nearbottom_"+r.behavior]!==t){return this["_nearbottom_"+r.behavior].call(this)}this._debug("math:",i,r.pixelsFromNavToBottom);return i-r.bufferPx<r.pixelsFromNavToBottom},_pausing:function(n){var r=this.options;if(!!r.behavior&&this["_pausing_"+r.behavior]!==t){this["_pausing_"+r.behavior].call(this,n);return}if(n!=="pause"&&n!=="resume"&&n!==null){this._debug("Invalid argument. Toggling pause value instead")}n=n&&(n==="pause"||n==="resume")?n:"toggle";
4637switch(n){case"pause":r.state.isPaused=true;break;case"resume":r.state.isPaused=false;break;case"toggle":r.state.isPaused=!r.state.isPaused;break}this._debug("Paused",r.state.isPaused);return false},_setup:function(){var n=this.options;if(!!n.behavior&&this["_setup_"+n.behavior]!==t){this["_setup_"+n.behavior].call(this);return}this._binding("bind");return false},_showdonemsg:function(){var r=this.options;if(!!r.behavior&&this["_showdonemsg_"+r.behavior]!==t){this["_showdonemsg_"+r.behavior].call(this);return}r.loading.msg.find("img").hide().parent().find("div").html(r.loading.finishedMsg).animate({opacity:1},2e3,function(){e(this).parent().fadeOut(r.loading.speed)});r.errorCallback.call(e(r.contentSelector)[0],"done")},_validate:function(n){for(var r in n){if(r.indexOf&&r.indexOf("Selector")>-1&&e(n[r]).length===0){this._debug("Your "+r+" found no elements.");return false}}return true},bind:function(){this._binding("bind")},destroy:function(){this.options.state.isDestroyed=true;this.options.loading.finished();return this._error("destroy")},pause:function(){this._pausing("pause")},resume:function(){this._pausing("resume")},beginAjax:function(r){var i=this,s=r.path,o,u,a,f;r.state.currPage++;if(r.maxPage!==t&&r.state.currPage>r.maxPage){r.state.isBeyondMaxPage=true;this.destroy();return}o=e(r.contentSelector).is("table, tbody")?e("<tbody/>"):e("<div/>");u=typeof s==="function"?s(r.state.currPage):s.join(r.state.currPage);i._debug("heading into ajax",u);a=r.dataType==="html"||r.dataType==="json"?r.dataType:"html+callback";if(r.appendCallback&&r.dataType==="html"){a+="+callback"}switch(a){case"html+callback":i._debug("Using HTML via .load() method");o.load(u+" "+r.itemSelector,t,function(t){i._loadcallback(o,t,u)});break;case"html":i._debug("Using "+a.toUpperCase()+" via $.ajax() method");e.ajax({url:u,dataType:r.dataType,complete:function(t,n){f=typeof t.isResolved!=="undefined"?t.isResolved():n==="success"||n==="notmodified";if(f){i._loadcallback(o,t.responseText,u)}else{i._error("end")}}});break;case"json":i._debug("Using "+a.toUpperCase()+" via $.ajax() method");e.ajax({dataType:"json",type:"GET",url:u,success:function(e,n,s){f=typeof s.isResolved!=="undefined"?s.isResolved():n==="success"||n==="notmodified";if(r.appendCallback){if(r.template!==t){var a=r.template(e);o.append(a);if(f){i._loadcallback(o,a)}else{i._error("end")}}else{i._debug("template must be defined.");i._error("end")}}else{if(f){i._loadcallback(o,e,u)}else{i._error("end")}}},error:function(){i._debug("JSON ajax request failed.");i._error("end")}});break}},retrieve:function(r){r=r||null;var i=this,s=i.options;if(!!s.behavior&&this["retrieve_"+s.behavior]!==t){this["retrieve_"+s.behavior].call(this,r);return}if(s.state.isDestroyed){this._debug("Instance is destroyed");return false}s.state.isDuringAjax=true;s.loading.start.call(e(s.contentSelector)[0],s)},scroll:function(){var n=this.options,r=n.state;if(!!n.behavior&&this["scroll_"+n.behavior]!==t){this["scroll_"+n.behavior].call(this);return}if(r.isDuringAjax||r.isInvalidPage||r.isDone||r.isDestroyed||r.isPaused){return}if(!this._nearbottom()){return}this.retrieve()},toggle:function(){this._pausing()},unbind:function(){this._binding("unbind")},update:function(n){if(e.isPlainObject(n)){this.options=e.extend(true,this.options,n)}}};e.fn.infinitescroll=function(n,r){var i=typeof n;switch(i){case"string":var s=Array.prototype.slice.call(arguments,1);this.each(function(){var t=e.data(this,"infinitescroll");if(!t){return false}if(!e.isFunction(t[n])||n.charAt(0)==="_"){return false}t[n].apply(t,s)});break;case"object":this.each(function(){var t=e.data(this,"infinitescroll");if(t){t.update(n)}else{t=new e.infinitescroll(n,r,this);if(!t.failed){e.data(this,"infinitescroll",t)}}});break}return this};var n=e.event,r;n.special.smartscroll={setup:function(){e(this).bind("scroll",n.special.smartscroll.handler)},teardown:function(){e(this).unbind("scroll",n.special.smartscroll.handler)},handler:function(t,n){var i=this,s=arguments;t.type="smartscroll";if(r){clearTimeout(r)}r=setTimeout(function(){e(i).trigger("smartscroll",s)},n==="execAsap"?0:100)}};e.fn.smartscroll=function(e){return e?this.bind("smartscroll",e):this.trigger("smartscroll",["execAsap"])}});
4638
4639/*!
4640Waypoints - 4.0.0
4641Copyright © 2011-2015 Caleb Troughton
4642Licensed under the MIT license.
4643https://github.com/imakewebthings/waypoints/blob/master/licenses.txt
4644*/
4645(function() {
4646  'use strict'
4647
4648  var keyCounter = 0
4649  var allWaypoints = {}
4650
4651  /* http://imakewebthings.com/waypoints/api/waypoint */
4652  function Waypoint(options) {
4653    if (!options) {
4654      throw new Error('No options passed to Waypoint constructor')
4655    }
4656    if (!options.element) {
4657      throw new Error('No element option passed to Waypoint constructor')
4658    }
4659    if (!options.handler) {
4660      throw new Error('No handler option passed to Waypoint constructor')
4661    }
4662
4663    this.key = 'waypoint-' + keyCounter
4664    this.options = Waypoint.Adapter.extend({}, Waypoint.defaults, options)
4665    this.element = this.options.element
4666    this.adapter = new Waypoint.Adapter(this.element)
4667    this.callback = options.handler
4668    this.axis = this.options.horizontal ? 'horizontal' : 'vertical'
4669    this.enabled = this.options.enabled
4670    this.triggerPoint = null
4671    this.group = Waypoint.Group.findOrCreate({
4672      name: this.options.group,
4673      axis: this.axis
4674    })
4675    this.context = Waypoint.Context.findOrCreateByElement(this.options.context)
4676
4677    if (Waypoint.offsetAliases[this.options.offset]) {
4678      this.options.offset = Waypoint.offsetAliases[this.options.offset]
4679    }
4680    this.group.add(this)
4681    this.context.add(this)
4682    allWaypoints[this.key] = this
4683    keyCounter += 1
4684  }
4685
4686  /* Private */
4687  Waypoint.prototype.queueTrigger = function(direction) {
4688    this.group.queueTrigger(this, direction)
4689  }
4690
4691  /* Private */
4692  Waypoint.prototype.trigger = function(args) {
4693    if (!this.enabled) {
4694      return
4695    }
4696    if (this.callback) {
4697      this.callback.apply(this, args)
4698    }
4699  }
4700
4701  /* Public */
4702  /* http://imakewebthings.com/waypoints/api/destroy */
4703  Waypoint.prototype.destroy = function() {
4704    this.context.remove(this)
4705    this.group.remove(this)
4706    delete allWaypoints[this.key]
4707  }
4708
4709  /* Public */
4710  /* http://imakewebthings.com/waypoints/api/disable */
4711  Waypoint.prototype.disable = function() {
4712    this.enabled = false
4713    return this
4714  }
4715
4716  /* Public */
4717  /* http://imakewebthings.com/waypoints/api/enable */
4718  Waypoint.prototype.enable = function() {
4719    this.context.refresh()
4720    this.enabled = true
4721    return this
4722  }
4723
4724  /* Public */
4725  /* http://imakewebthings.com/waypoints/api/next */
4726  Waypoint.prototype.next = function() {
4727    return this.group.next(this)
4728  }
4729
4730  /* Public */
4731  /* http://imakewebthings.com/waypoints/api/previous */
4732  Waypoint.prototype.previous = function() {
4733    return this.group.previous(this)
4734  }
4735
4736  /* Private */
4737  Waypoint.invokeAll = function(method) {
4738    var allWaypointsArray = []
4739    for (var waypointKey in allWaypoints) {
4740      allWaypointsArray.push(allWaypoints[waypointKey])
4741    }
4742    for (var i = 0, end = allWaypointsArray.length; i < end; i++) {
4743      allWaypointsArray[i][method]()
4744    }
4745  }
4746
4747  /* Public */
4748  /* http://imakewebthings.com/waypoints/api/destroy-all */
4749  Waypoint.destroyAll = function() {
4750    Waypoint.invokeAll('destroy')
4751  }
4752
4753  /* Public */
4754  /* http://imakewebthings.com/waypoints/api/disable-all */
4755  Waypoint.disableAll = function() {
4756    Waypoint.invokeAll('disable')
4757  }
4758
4759  /* Public */
4760  /* http://imakewebthings.com/waypoints/api/enable-all */
4761  Waypoint.enableAll = function() {
4762    Waypoint.invokeAll('enable')
4763  }
4764
4765  /* Public */
4766  /* http://imakewebthings.com/waypoints/api/refresh-all */
4767  Waypoint.refreshAll = function() {
4768    Waypoint.Context.refreshAll()
4769  }
4770
4771  /* Public */
4772  /* http://imakewebthings.com/waypoints/api/viewport-height */
4773  Waypoint.viewportHeight = function() {
4774    return window.innerHeight || document.documentElement.clientHeight
4775  }
4776
4777  /* Public */
4778  /* http://imakewebthings.com/waypoints/api/viewport-width */
4779  Waypoint.viewportWidth = function() {
4780    return document.documentElement.clientWidth
4781  }
4782
4783  Waypoint.adapters = []
4784
4785  Waypoint.defaults = {
4786    context: window,
4787    continuous: true,
4788    enabled: true,
4789    group: 'default',
4790    horizontal: false,
4791    offset: 0
4792  }
4793
4794  Waypoint.offsetAliases = {
4795    'bottom-in-view': function() {
4796      return this.context.innerHeight() - this.adapter.outerHeight()
4797    },
4798    'right-in-view': function() {
4799      return this.context.innerWidth() - this.adapter.outerWidth()
4800    }
4801  }
4802
4803  window.Waypoint = Waypoint
4804}())
4805;(function() {
4806  'use strict'
4807
4808  function requestAnimationFrameShim(callback) {
4809    window.setTimeout(callback, 1000 / 60)
4810  }
4811
4812  var keyCounter = 0
4813  var contexts = {}
4814  var Waypoint = window.Waypoint
4815  var oldWindowLoad = window.onload
4816
4817  /* http://imakewebthings.com/waypoints/api/context */
4818  function Context(element) {
4819    this.element = element
4820    this.Adapter = Waypoint.Adapter
4821    this.adapter = new this.Adapter(element)
4822    this.key = 'waypoint-context-' + keyCounter
4823    this.didScroll = false
4824    this.didResize = false
4825    this.oldScroll = {
4826      x: this.adapter.scrollLeft(),
4827      y: this.adapter.scrollTop()
4828    }
4829    this.waypoints = {
4830      vertical: {},
4831      horizontal: {}
4832    }
4833
4834    element.waypointContextKey = this.key
4835    contexts[element.waypointContextKey] = this
4836    keyCounter += 1
4837
4838    this.createThrottledScrollHandler()
4839    this.createThrottledResizeHandler()
4840  }
4841
4842  /* Private */
4843  Context.prototype.add = function(waypoint) {
4844    var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical'
4845    this.waypoints[axis][waypoint.key] = waypoint
4846    this.refresh()
4847  }
4848
4849  /* Private */
4850  Context.prototype.checkEmpty = function() {
4851    var horizontalEmpty = this.Adapter.isEmptyObject(this.waypoints.horizontal)
4852    var verticalEmpty = this.Adapter.isEmptyObject(this.waypoints.vertical)
4853    if (horizontalEmpty && verticalEmpty) {
4854      this.adapter.off('.waypoints')
4855      delete contexts[this.key]
4856    }
4857  }
4858
4859  /* Private */
4860  Context.prototype.createThrottledResizeHandler = function() {
4861    var self = this
4862
4863    function resizeHandler() {
4864      self.handleResize()
4865      self.didResize = false
4866    }
4867
4868    this.adapter.on('resize.waypoints', function() {
4869      if (!self.didResize) {
4870        self.didResize = true
4871        Waypoint.requestAnimationFrame(resizeHandler)
4872      }
4873    })
4874  }
4875
4876  /* Private */
4877  Context.prototype.createThrottledScrollHandler = function() {
4878    var self = this
4879    function scrollHandler() {
4880      self.handleScroll()
4881      self.didScroll = false
4882    }
4883
4884    this.adapter.on('scroll.waypoints', function() {
4885      if (!self.didScroll || Waypoint.isTouch) {
4886        self.didScroll = true
4887        Waypoint.requestAnimationFrame(scrollHandler)
4888      }
4889    })
4890  }
4891
4892  /* Private */
4893  Context.prototype.handleResize = function() {
4894    Waypoint.Context.refreshAll()
4895  }
4896
4897  /* Private */
4898  Context.prototype.handleScroll = function() {
4899    var triggeredGroups = {}
4900    var axes = {
4901      horizontal: {
4902        newScroll: this.adapter.scrollLeft(),
4903        oldScroll: this.oldScroll.x,
4904        forward: 'right',
4905        backward: 'left'
4906      },
4907      vertical: {
4908        newScroll: this.adapter.scrollTop(),
4909        oldScroll: this.oldScroll.y,
4910        forward: 'down',
4911        backward: 'up'
4912      }
4913    }
4914
4915    for (var axisKey in axes) {
4916      var axis = axes[axisKey]
4917      var isForward = axis.newScroll > axis.oldScroll
4918      var direction = isForward ? axis.forward : axis.backward
4919
4920      for (var waypointKey in this.waypoints[axisKey]) {
4921        var waypoint = this.waypoints[axisKey][waypointKey]
4922        var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint
4923        var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint
4924        var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint
4925        var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint
4926        if (crossedForward || crossedBackward) {
4927          waypoint.queueTrigger(direction)
4928          triggeredGroups[waypoint.group.id] = waypoint.group
4929        }
4930      }
4931    }
4932
4933    for (var groupKey in triggeredGroups) {
4934      triggeredGroups[groupKey].flushTriggers()
4935    }
4936
4937    this.oldScroll = {
4938      x: axes.horizontal.newScroll,
4939      y: axes.vertical.newScroll
4940    }
4941  }
4942
4943  /* Private */
4944  Context.prototype.innerHeight = function() {
4945    /*eslint-disable eqeqeq */
4946    if (this.element == this.element.window) {
4947      return Waypoint.viewportHeight()
4948    }
4949    /*eslint-enable eqeqeq */
4950    return this.adapter.innerHeight()
4951  }
4952
4953  /* Private */
4954  Context.prototype.remove = function(waypoint) {
4955    delete this.waypoints[waypoint.axis][waypoint.key]
4956    this.checkEmpty()
4957  }
4958
4959  /* Private */
4960  Context.prototype.innerWidth = function() {
4961    /*eslint-disable eqeqeq */
4962    if (this.element == this.element.window) {
4963      return Waypoint.viewportWidth()
4964    }
4965    /*eslint-enable eqeqeq */
4966    return this.adapter.innerWidth()
4967  }
4968
4969  /* Public */
4970  /* http://imakewebthings.com/waypoints/api/context-destroy */
4971  Context.prototype.destroy = function() {
4972    var allWaypoints = []
4973    for (var axis in this.waypoints) {
4974      for (var waypointKey in this.waypoints[axis]) {
4975        allWaypoints.push(this.waypoints[axis][waypointKey])
4976      }
4977    }
4978    for (var i = 0, end = allWaypoints.length; i < end; i++) {
4979      allWaypoints[i].destroy()
4980    }
4981  }
4982
4983  /* Public */
4984  /* http://imakewebthings.com/waypoints/api/context-refresh */
4985  Context.prototype.refresh = function() {
4986    /*eslint-disable eqeqeq */
4987    var isWindow = this.element == this.element.window
4988    /*eslint-enable eqeqeq */
4989    var contextOffset = isWindow ? undefined : this.adapter.offset()
4990    var triggeredGroups = {}
4991    var axes
4992
4993    this.handleScroll()
4994    axes = {
4995      horizontal: {
4996        contextOffset: isWindow ? 0 : contextOffset.left,
4997        contextScroll: isWindow ? 0 : this.oldScroll.x,
4998        contextDimension: this.innerWidth(),
4999        oldScroll: this.oldScroll.x,
5000        forward: 'right',
5001        backward: 'left',
5002        offsetProp: 'left'
5003      },
5004      vertical: {
5005        contextOffset: isWindow ? 0 : contextOffset.top,
5006        contextScroll: isWindow ? 0 : this.oldScroll.y,
5007        contextDimension: this.innerHeight(),
5008        oldScroll: this.oldScroll.y,
5009        forward: 'down',
5010        backward: 'up',
5011        offsetProp: 'top'
5012      }
5013    }
5014
5015    for (var axisKey in axes) {
5016      var axis = axes[axisKey]
5017      for (var waypointKey in this.waypoints[axisKey]) {
5018        var waypoint = this.waypoints[axisKey][waypointKey]
5019        var adjustment = waypoint.options.offset
5020        var oldTriggerPoint = waypoint.triggerPoint
5021        var elementOffset = 0
5022        var freshWaypoint = oldTriggerPoint == null
5023        var contextModifier, wasBeforeScroll, nowAfterScroll
5024        var triggeredBackward, triggeredForward
5025
5026        if (waypoint.element !== waypoint.element.window) {
5027          elementOffset = waypoint.adapter.offset()[axis.offsetProp]
5028        }
5029
5030        if (typeof adjustment === 'function') {
5031          adjustment = adjustment.apply(waypoint)
5032        }
5033        else if (typeof adjustment === 'string') {
5034          adjustment = parseFloat(adjustment)
5035          if (waypoint.options.offset.indexOf('%') > - 1) {
5036            adjustment = Math.ceil(axis.contextDimension * adjustment / 100)
5037          }
5038        }
5039
5040        contextModifier = axis.contextScroll - axis.contextOffset
5041        waypoint.triggerPoint = elementOffset + contextModifier - adjustment
5042        wasBeforeScroll = oldTriggerPoint < axis.oldScroll
5043        nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll
5044        triggeredBackward = wasBeforeScroll && nowAfterScroll
5045        triggeredForward = !wasBeforeScroll && !nowAfterScroll
5046
5047        if (!freshWaypoint && triggeredBackward) {
5048          waypoint.queueTrigger(axis.backward)
5049          triggeredGroups[waypoint.group.id] = waypoint.group
5050        }
5051        else if (!freshWaypoint && triggeredForward) {
5052          waypoint.queueTrigger(axis.forward)
5053          triggeredGroups[waypoint.group.id] = waypoint.group
5054        }
5055        else if (freshWaypoint && axis.oldScroll >= waypoint.triggerPoint) {
5056          waypoint.queueTrigger(axis.forward)
5057          triggeredGroups[waypoint.group.id] = waypoint.group
5058        }
5059      }
5060    }
5061
5062    Waypoint.requestAnimationFrame(function() {
5063      for (var groupKey in triggeredGroups) {
5064        triggeredGroups[groupKey].flushTriggers()
5065      }
5066    })
5067
5068    return this
5069  }
5070
5071  /* Private */
5072  Context.findOrCreateByElement = function(element) {
5073    return Context.findByElement(element) || new Context(element)
5074  }
5075
5076  /* Private */
5077  Context.refreshAll = function() {
5078    for (var contextId in contexts) {
5079      contexts[contextId].refresh()
5080    }
5081  }
5082
5083  /* Public */
5084  /* http://imakewebthings.com/waypoints/api/context-find-by-element */
5085  Context.findByElement = function(element) {
5086    return contexts[element.waypointContextKey]
5087  }
5088
5089  window.onload = function() {
5090    if (oldWindowLoad) {
5091      oldWindowLoad()
5092    }
5093    Context.refreshAll()
5094  }
5095
5096  Waypoint.requestAnimationFrame = function(callback) {
5097    var requestFn = window.requestAnimationFrame ||
5098      window.mozRequestAnimationFrame ||
5099      window.webkitRequestAnimationFrame ||
5100      requestAnimationFrameShim
5101    requestFn.call(window, callback)
5102  }
5103  Waypoint.Context = Context
5104}())
5105;(function() {
5106  'use strict'
5107
5108  function byTriggerPoint(a, b) {
5109    return a.triggerPoint - b.triggerPoint
5110  }
5111
5112  function byReverseTriggerPoint(a, b) {
5113    return b.triggerPoint - a.triggerPoint
5114  }
5115
5116  var groups = {
5117    vertical: {},
5118    horizontal: {}
5119  }
5120  var Waypoint = window.Waypoint
5121
5122  /* http://imakewebthings.com/waypoints/api/group */
5123  function Group(options) {
5124    this.name = options.name
5125    this.axis = options.axis
5126    this.id = this.name + '-' + this.axis
5127    this.waypoints = []
5128    this.clearTriggerQueues()
5129    groups[this.axis][this.name] = this
5130  }
5131
5132  /* Private */
5133  Group.prototype.add = function(waypoint) {
5134    this.waypoints.push(waypoint)
5135  }
5136
5137  /* Private */
5138  Group.prototype.clearTriggerQueues = function() {
5139    this.triggerQueues = {
5140      up: [],
5141      down: [],
5142      left: [],
5143      right: []
5144    }
5145  }
5146
5147  /* Private */
5148  Group.prototype.flushTriggers = function() {
5149    for (var direction in this.triggerQueues) {
5150      var waypoints = this.triggerQueues[direction]
5151      var reverse = direction === 'up' || direction === 'left'
5152      waypoints.sort(reverse ? byReverseTriggerPoint : byTriggerPoint)
5153      for (var i = 0, end = waypoints.length; i < end; i += 1) {
5154        var waypoint = waypoints[i]
5155        if (waypoint.options.continuous || i === waypoints.length - 1) {
5156          waypoint.trigger([direction])
5157        }
5158      }
5159    }
5160    this.clearTriggerQueues()
5161  }
5162
5163  /* Private */
5164  Group.prototype.next = function(waypoint) {
5165    this.waypoints.sort(byTriggerPoint)
5166    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
5167    var isLast = index === this.waypoints.length - 1
5168    return isLast ? null : this.waypoints[index + 1]
5169  }
5170
5171  /* Private */
5172  Group.prototype.previous = function(waypoint) {
5173    this.waypoints.sort(byTriggerPoint)
5174    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
5175    return index ? this.waypoints[index - 1] : null
5176  }
5177
5178  /* Private */
5179  Group.prototype.queueTrigger = function(waypoint, direction) {
5180    this.triggerQueues[direction].push(waypoint)
5181  }
5182
5183  /* Private */
5184  Group.prototype.remove = function(waypoint) {
5185    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
5186    if (index > -1) {
5187      this.waypoints.splice(index, 1)
5188    }
5189  }
5190
5191  /* Public */
5192  /* http://imakewebthings.com/waypoints/api/first */
5193  Group.prototype.first = function() {
5194    return this.waypoints[0]
5195  }
5196
5197  /* Public */
5198  /* http://imakewebthings.com/waypoints/api/last */
5199  Group.prototype.last = function() {
5200    return this.waypoints[this.waypoints.length - 1]
5201  }
5202
5203  /* Private */
5204  Group.findOrCreate = function(options) {
5205    return groups[options.axis][options.name] || new Group(options)
5206  }
5207
5208  Waypoint.Group = Group
5209}())
5210;(function() {
5211  'use strict'
5212
5213  var $ = window.jQuery
5214  var Waypoint = window.Waypoint
5215
5216  function JQueryAdapter(element) {
5217    this.$element = $(element)
5218  }
5219
5220  $.each([
5221    'innerHeight',
5222    'innerWidth',
5223    'off',
5224    'offset',
5225    'on',
5226    'outerHeight',
5227    'outerWidth',
5228    'scrollLeft',
5229    'scrollTop'
5230  ], function(i, method) {
5231    JQueryAdapter.prototype[method] = function() {
5232      var args = Array.prototype.slice.call(arguments)
5233      return this.$element[method].apply(this.$element, args)
5234    }
5235  })
5236
5237  $.each([
5238    'extend',
5239    'inArray',
5240    'isEmptyObject'
5241  ], function(i, method) {
5242    JQueryAdapter[method] = $[method]
5243  })
5244
5245  Waypoint.adapters.push({
5246    name: 'jquery',
5247    Adapter: JQueryAdapter
5248  })
5249  Waypoint.Adapter = JQueryAdapter
5250}())
5251;(function() {
5252  'use strict'
5253
5254  var Waypoint = window.Waypoint
5255
5256  function createExtension(framework) {
5257    return function() {
5258      var waypoints = []
5259      var overrides = arguments[0]
5260
5261      if (framework.isFunction(arguments[0])) {
5262        overrides = framework.extend({}, arguments[1])
5263        overrides.handler = arguments[0]
5264      }
5265
5266      this.each(function() {
5267        var options = framework.extend({}, overrides, {
5268          element: this
5269        })
5270        if (typeof options.context === 'string') {
5271          options.context = framework(this).closest(options.context)[0]
5272        }
5273        waypoints.push(new Waypoint(options))
5274      })
5275
5276      return waypoints
5277    }
5278  }
5279
5280  if (window.jQuery) {
5281    window.jQuery.fn.waypoint = createExtension(window.jQuery)
5282  }
5283  if (window.Zepto) {
5284    window.Zepto.fn.waypoint = createExtension(window.Zepto)
5285  }
5286}())
5287;
5288
5289/*!
5290Waypoints Inview Shortcut - 4.0.0
5291Copyright © 2011-2015 Caleb Troughton
5292Licensed under the MIT license.
5293https://github.com/imakewebthings/waypoints/blob/master/licenses.txt
5294*/
5295(function() {
5296  'use strict'
5297
5298  function noop() {}
5299
5300  var Waypoint = window.Waypoint
5301
5302  /* http://imakewebthings.com/waypoints/shortcuts/inview */
5303  function Inview(options) {
5304    this.options = Waypoint.Adapter.extend({}, Inview.defaults, options)
5305    this.axis = this.options.horizontal ? 'horizontal' : 'vertical'
5306    this.waypoints = []
5307    this.element = this.options.element
5308    this.createWaypoints()
5309  }
5310
5311  /* Private */
5312  Inview.prototype.createWaypoints = function() {
5313    var configs = {
5314      vertical: [{
5315        down: 'enter',
5316        up: 'exited',
5317        offset: '100%'
5318      }, {
5319        down: 'entered',
5320        up: 'exit',
5321        offset: 'bottom-in-view'
5322      }, {
5323        down: 'exit',
5324        up: 'entered',
5325        offset: 0
5326      }, {
5327        down: 'exited',
5328        up: 'enter',
5329        offset: function() {
5330          return -this.adapter.outerHeight()
5331        }
5332      }],
5333      horizontal: [{
5334        right: 'enter',
5335        left: 'exited',
5336        offset: '100%'
5337      }, {
5338        right: 'entered',
5339        left: 'exit',
5340        offset: 'right-in-view'
5341      }, {
5342        right: 'exit',
5343        left: 'entered',
5344        offset: 0
5345      }, {
5346        right: 'exited',
5347        left: 'enter',
5348        offset: function() {
5349          return -this.adapter.outerWidth()
5350        }
5351      }]
5352    }
5353
5354    for (var i = 0, end = configs[this.axis].length; i < end; i++) {
5355      var config = configs[this.axis][i]
5356      this.createWaypoint(config)
5357    }
5358  }
5359
5360  /* Private */
5361  Inview.prototype.createWaypoint = function(config) {
5362    var self = this
5363    this.waypoints.push(new Waypoint({
5364      context: this.options.context,
5365      element: this.options.element,
5366      enabled: this.options.enabled,
5367      handler: (function(config) {
5368        return function(direction) {
5369          self.options[config[direction]].call(self, direction)
5370        }
5371      }(config)),
5372      offset: config.offset,
5373      horizontal: this.options.horizontal
5374    }))
5375  }
5376
5377  /* Public */
5378  Inview.prototype.destroy = function() {
5379    for (var i = 0, end = this.waypoints.length; i < end; i++) {
5380      this.waypoints[i].destroy()
5381    }
5382    this.waypoints = []
5383  }
5384
5385  Inview.prototype.disable = function() {
5386    for (var i = 0, end = this.waypoints.length; i < end; i++) {
5387      this.waypoints[i].disable()
5388    }
5389  }
5390
5391  Inview.prototype.enable = function() {
5392    for (var i = 0, end = this.waypoints.length; i < end; i++) {
5393      this.waypoints[i].enable()
5394    }
5395  }
5396
5397  Inview.defaults = {
5398    context: window,
5399    enabled: true,
5400    enter: noop,
5401    entered: noop,
5402    exit: noop,
5403    exited: noop
5404  }
5405
5406  Waypoint.Inview = Inview
5407}())
5408;
5409
5410/*
5411 * SmartMenus jQuery v0.9.6
5412 * http://www.smartmenus.org/
5413 *
5414 * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd.
5415 * http://vadikom.com/
5416 *
5417 * Released under the MIT license:
5418 * http://www.opensource.org/licenses/MIT
5419 */
5420
5421(function($) {
5422
5423	var menuTrees = [],
5424		IE = !!window.createPopup, // we need to detect it, unfortunately
5425		IElt9 = IE && !document.defaultView,
5426		IElt8 = IE && !document.querySelector,
5427		IE6 = IE && typeof document.documentElement.currentStyle.minWidth == 'undefined',
5428		mouse = false, // optimize for touch by default - we will detect for mouse input
5429		mouseDetectionEnabled = false;
5430
5431	// Handle detection for mouse input (i.e. desktop browsers, tablets with a mouse, etc.)
5432	function initMouseDetection(disable) {
5433		if (!mouseDetectionEnabled && !disable) {
5434			// if we get two consecutive mousemoves within 2 pixels from each other and within 300ms, we assume a real mouse/cursor is present
5435			// in practice, this seems like impossible to trick unintentianally with a real mouse and a pretty safe detection on touch devices (even with older browsers that do not support touch events)
5436			var firstTime = true,
5437				lastMove = null;
5438			$(document).bind({
5439				'mousemove.smartmenus_mouse': function(e) {
5440					var thisMove = { x: e.pageX, y: e.pageY, timeStamp: new Date().getTime() };
5441					if (lastMove) {
5442						var deltaX = Math.abs(lastMove.x - thisMove.x),
5443							deltaY = Math.abs(lastMove.y - thisMove.y);
5444	 					if ((deltaX > 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) {
5445							mouse = true;
5446							// if this is the first check after page load, check if we are not over some item by chance and call the mouseenter handler if yes
5447							if (firstTime) {
5448								var $a = $(e.target).closest('a');
5449								if ($a.is('a')) {
5450									$.each(menuTrees, function() {
5451										if ($.contains(this.$root[0], $a[0])) {
5452											this.itemEnter({ currentTarget: $a[0] });
5453											return false;
5454										}
5455									});
5456								}
5457								firstTime = false;
5458							}
5459						}
5460					}
5461					lastMove = thisMove;
5462				},
5463				'touchstart.smartmenus_mouse pointerover.smartmenus_mouse MSPointerOver.smartmenus_mouse': function(e) {
5464					if (!/^(4|mouse)$/.test(e.originalEvent.pointerType)) {
5465						mouse = false;
5466					}
5467				}
5468			});
5469			mouseDetectionEnabled = true;
5470		} else if (mouseDetectionEnabled && disable) {
5471			$(document).unbind('.smartmenus_mouse');
5472			mouseDetectionEnabled = false;
5473		}
5474	};
5475
5476	$.SmartMenus = function(elm, options) {
5477		this.$root = $(elm);
5478		this.opts = options;
5479		this.rootId = ''; // internal
5480		this.$subArrow = null;
5481		this.subMenus = []; // all sub menus in the tree (UL elms) in no particular order (only real - e.g. UL's in mega sub menus won't be counted)
5482		this.activatedItems = []; // stores last activated A's for each level
5483		this.visibleSubMenus = []; // stores visible sub menus UL's
5484		this.showTimeout = 0;
5485		this.hideTimeout = 0;
5486		this.scrollTimeout = 0;
5487		this.clickActivated = false;
5488		this.zIndexInc = 0;
5489		this.$firstLink = null; // we'll use these for some tests
5490		this.$firstSub = null; // at runtime so we'll cache them
5491		this.disabled = false;
5492		this.$disableOverlay = null;
5493		this.init();
5494	};
5495
5496	$.extend($.SmartMenus, {
5497		hideAll: function() {
5498			$.each(menuTrees, function() {
5499				this.menuHideAll();
5500			});
5501		},
5502		destroy: function() {
5503			while (menuTrees.length) {
5504				menuTrees[0].destroy();
5505			}
5506			initMouseDetection(true);
5507		},
5508		prototype: {
5509			init: function(refresh) {
5510				var self = this;
5511
5512				if (!refresh) {
5513					menuTrees.push(this);
5514
5515					this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, '');
5516
5517					if (this.$root.hasClass('sm-rtl')) {
5518						this.opts.rightToLeftSubMenus = true;
5519					}
5520
5521					// init root (main menu)
5522					this.$root
5523						.data('smartmenus', this)
5524						.attr('data-smartmenus-id', this.rootId)
5525						.dataSM('level', 1)
5526						.bind({
5527							'mouseover.smartmenus focusin.smartmenus': $.proxy(this.rootOver, this),
5528							'mouseout.smartmenus focusout.smartmenus': $.proxy(this.rootOut, this)
5529						})
5530						.delegate('a', {
5531							'mouseenter.smartmenus': $.proxy(this.itemEnter, this),
5532							'mouseleave.smartmenus': $.proxy(this.itemLeave, this),
5533							'mousedown.smartmenus': $.proxy(this.itemDown, this),
5534							'focus.smartmenus': $.proxy(this.itemFocus, this),
5535							'blur.smartmenus': $.proxy(this.itemBlur, this),
5536							'click.smartmenus': $.proxy(this.itemClick, this),
5537							'touchend.smartmenus': $.proxy(this.itemTouchEnd, this)
5538						});
5539
5540					var eNamespace = '.smartmenus' + this.rootId;
5541					// hide menus on tap or click outside the root UL
5542					if (this.opts.hideOnClick) {
5543						$(document).bind('touchstart' + eNamespace, $.proxy(this.docTouchStart, this))
5544							.bind('touchmove' + eNamespace, $.proxy(this.docTouchMove, this))
5545							.bind('touchend' + eNamespace, $.proxy(this.docTouchEnd, this))
5546							// for Opera Mobile < 11.5, webOS browser, etc. we'll check click too
5547							.bind('click' + eNamespace, $.proxy(this.docClick, this));
5548					}
5549					// hide sub menus on resize
5550					$(window).bind('resize' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this));
5551					$(window).bind('scroll' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this));
5552
5553					if (this.opts.subIndicators) {
5554						this.$subArrow = $('<span/>').addClass('sub-arrow');
5555						if (this.opts.subIndicatorsText) {
5556							this.$subArrow.html(this.opts.subIndicatorsText);
5557						}
5558					}
5559
5560					// make sure mouse detection is enabled
5561					initMouseDetection();
5562				}
5563
5564				// init sub menus
5565				this.$firstSub = this.$root.find('ul').each(function() { self.menuInit($(this)); }).eq(0);
5566
5567				this.$firstLink = this.$root.find('a').eq(0);
5568
5569				// find current item
5570				if (this.opts.markCurrentItem) {
5571					var reDefaultDoc = /(index|default)\.[^#\?\/]*/i,
5572						reHash = /#.*/,
5573						locHref = window.location.href.replace(reDefaultDoc, ''),
5574						locHrefNoHash = locHref.replace(reHash, '');
5575					this.$root.find('a').each(function() {
5576						var href = this.href.replace(reDefaultDoc, ''),
5577							$this = $(this);
5578						if (href == locHref || href == locHrefNoHash) {
5579							$this.addClass('current');
5580							if (self.opts.markCurrentTree) {
5581								$this.parents('li').each(function() {
5582									var $this = $(this);
5583									if ($this.dataSM('sub')) {
5584										$this.children('a').addClass('current');
5585									}
5586								});
5587							}
5588						}
5589					});
5590				}
5591			},
5592			destroy: function() {
5593				this.menuHideAll();
5594				this.$root
5595					.removeData('smartmenus')
5596					.removeAttr('data-smartmenus-id')
5597					.removeDataSM('level')
5598					.unbind('.smartmenus')
5599					.undelegate('.smartmenus');
5600				var eNamespace = '.smartmenus' + this.rootId;
5601				$(document).unbind(eNamespace);
5602				$(window).unbind(eNamespace);
5603				if (this.opts.subIndicators) {
5604					this.$subArrow = null;
5605				}
5606				var self = this;
5607				$.each(this.subMenus, function() {
5608					if (this.hasClass('mega-menu')) {
5609						this.find('ul').removeDataSM('in-mega');
5610					}
5611					if (this.dataSM('shown-before')) {
5612						if (IElt8) {
5613							this.children().css({ styleFloat: '', width: '' });
5614						}
5615						if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) {
5616							if (!IE6) {
5617								this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap');
5618							} else {
5619								this.css({ width: '', overflowX: '', overflowY: '' }).children().children('a').css('white-space', '');
5620							}
5621						}
5622						if (this.dataSM('scroll-arrows')) {
5623							this.dataSM('scroll-arrows').remove();
5624						}
5625						this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' });
5626					}
5627					if (self.opts.subIndicators) {
5628						this.dataSM('parent-a').removeClass('has-submenu').children('span.sub-arrow').remove();
5629					}
5630					this.removeDataSM('shown-before')
5631						.removeDataSM('ie-shim')
5632						.removeDataSM('scroll-arrows')
5633						.removeDataSM('parent-a')
5634						.removeDataSM('level')
5635						.removeDataSM('beforefirstshowfired')
5636						.parent().removeDataSM('sub');
5637				});
5638				if (this.opts.markCurrentItem) {
5639					this.$root.find('a.current').removeClass('current');
5640				}
5641				this.$root = null;
5642				this.$firstLink = null;
5643				this.$firstSub = null;
5644				if (this.$disableOverlay) {
5645					this.$disableOverlay.remove();
5646					this.$disableOverlay = null;
5647				}
5648				menuTrees.splice($.inArray(this, menuTrees), 1);
5649			},
5650			disable: function(noOverlay) {
5651				if (!this.disabled) {
5652					this.menuHideAll();
5653					// display overlay over the menu to prevent interaction
5654					if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) {
5655						var pos = this.$root.offset();
5656						this.$disableOverlay = $('<div class="sm-jquery-disable-overlay"/>').css({
5657							position: 'absolute',
5658							top: pos.top,
5659							left: pos.left,
5660							width: this.$root.outerWidth(),
5661							height: this.$root.outerHeight(),
5662							zIndex: this.getStartZIndex() + 1,
5663							opacity: 0
5664						}).appendTo(document.body);
5665					}
5666					this.disabled = true;
5667				}
5668			},
5669			docClick: function(e) {
5670				// hide on any click outside the menu or on a menu link
5671				if (this.visibleSubMenus.length && !$.contains(this.$root[0], e.target) || $(e.target).is('a')) {
5672					this.menuHideAll();
5673				}
5674			},
5675			docTouchEnd: function(e) {
5676				if (!this.lastTouch) {
5677					return;
5678				}
5679				if (this.visibleSubMenus.length && (this.lastTouch.x2 === undefined || this.lastTouch.x1 == this.lastTouch.x2) && (this.lastTouch.y2 === undefined || this.lastTouch.y1 == this.lastTouch.y2) && (!this.lastTouch.target || !$.contains(this.$root[0], this.lastTouch.target))) {
5680					if (this.hideTimeout) {
5681						clearTimeout(this.hideTimeout);
5682						this.hideTimeout = 0;
5683					}
5684					// hide with a delay to prevent triggering accidental unwanted click on some page element
5685					var self = this;
5686					this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, 350);
5687				}
5688				this.lastTouch = null;
5689			},
5690			docTouchMove: function(e) {
5691				if (!this.lastTouch) {
5692					return;
5693				}
5694				var touchPoint = e.originalEvent.touches[0];
5695				this.lastTouch.x2 = touchPoint.pageX;
5696				this.lastTouch.y2 = touchPoint.pageY;
5697			},
5698			docTouchStart: function(e) {
5699				var touchPoint = e.originalEvent.touches[0];
5700				this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target };
5701			},
5702			enable: function() {
5703				if (this.disabled) {
5704					if (this.$disableOverlay) {
5705						this.$disableOverlay.remove();
5706						this.$disableOverlay = null;
5707					}
5708					this.disabled = false;
5709				}
5710			},
5711			getHeight: function($elm) {
5712				return this.getOffset($elm, true);
5713			},
5714			// returns precise width/height float values in IE9+, FF4+, recent WebKit
5715			// http://vadikom.com/dailies/offsetwidth-offsetheight-useless-in-ie9-firefox4/
5716			getOffset: function($elm, height) {
5717				var old;
5718				if ($elm.css('display') == 'none') {
5719					old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility };
5720					$elm.css({ position: 'absolute', visibility: 'hidden' }).show();
5721				}
5722				var defaultView = $elm[0].ownerDocument.defaultView,
5723					compStyle = defaultView && defaultView.getComputedStyle && defaultView.getComputedStyle($elm[0], null),
5724					val = compStyle && parseFloat(compStyle[height ? 'height' : 'width']);
5725				if (val) {
5726					val += parseFloat(compStyle[height ? 'paddingTop' : 'paddingLeft'])
5727	 					+ parseFloat(compStyle[height ? 'paddingBottom' : 'paddingRight'])
5728	 					+ parseInt(compStyle[height ? 'borderTopWidth' : 'borderLeftWidth'])
5729	 					+ parseInt(compStyle[height ? 'borderBottomWidth' : 'borderRightWidth']);
5730				} else {
5731					val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth;
5732				}
5733				if (old) {
5734					$elm.hide().css(old);
5735				}
5736				return val;
5737			},
5738			getWidth: function($elm) {
5739				return this.getOffset($elm);
5740			},
5741			getStartZIndex: function() {
5742				var zIndex = parseInt(this.$root.css('z-index'));
5743				return !isNaN(zIndex) ? zIndex : 1;
5744			},
5745			handleEvents: function() {
5746				return !this.disabled && this.isCSSOn();
5747			},
5748			handleItemEvents: function($a) {
5749				return this.handleEvents() && !this.isLinkInMegaMenu($a);
5750			},
5751			isCollapsible: function() {
5752				return this.$firstSub.css('position') == 'static';
5753			},
5754			isCSSOn: function() {
5755				return this.$firstLink.css('display') == 'block' || this.$firstLink.css('display') == 'inline';
5756			},
5757			isFixed: function() {
5758				return this.$root.css('position') == 'fixed';
5759			},
5760			isLinkInMegaMenu: function($a) {
5761				return !$a.parent().parent().dataSM('level');
5762			},
5763			isTouchMode: function() {
5764				return !mouse || this.isCollapsible();
5765			},
5766			itemActivate: function($a) {
5767				var $li = $a.parent(),
5768					$ul = $li.parent(),
5769					level = $ul.dataSM('level');
5770				// if for some reason the parent item is not activated (e.g. this is an API call to activate the item), activate all parent items first
5771				if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) {
5772					var self = this;
5773					$($ul.parentsUntil('[data-smartmenus-id]', 'ul').get().reverse()).add($ul).each(function() {
5774						self.itemActivate($(this).dataSM('parent-a'));
5775					});
5776				}
5777				// hide any visible deeper level sub menus
5778				if (this.visibleSubMenus.length > level) {
5779					for (var i = this.visibleSubMenus.length - 1, l = !this.activatedItems[level - 1] || this.activatedItems[level - 1][0] != $a[0] ? level - 1 : level; i > l; i--) {
5780						this.menuHide(this.visibleSubMenus[i]);
5781					}
5782				}
5783				// save new active item and sub menu for this level
5784				this.activatedItems[level - 1] = $a;
5785				this.visibleSubMenus[level - 1] = $ul;
5786				if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) {
5787					return;
5788				}
5789				// show the sub menu if this item has one
5790				var $sub = $li.dataSM('sub');
5791				if ($sub && (this.isTouchMode() || (!this.opts.showOnClick || this.clickActivated))) {
5792					this.menuShow($sub);
5793				}
5794			},
5795			itemBlur: function(e) {
5796				var $a = $(e.currentTarget);
5797				if (!this.handleItemEvents($a)) {
5798					return;
5799				}
5800				this.$root.triggerHandler('blur.smapi', $a[0]);
5801			},
5802			itemClick: function(e) {
5803				var $a = $(e.currentTarget);
5804
5805				if (!this.handleItemEvents($a)) {
5806					return;
5807				}
5808				$a.removeDataSM('mousedown');
5809				if (this.$root.triggerHandler('click.smapi', $a[0]) === false) {
5810					return false;
5811				}
5812				var $sub = $a.parent().dataSM('sub');
5813				if (this.isTouchMode()) {
5814					// undo fix: prevent the address bar on iPhone from sliding down when expanding a sub menu
5815					if ($a.dataSM('href')) {
5816						$a.attr('href', $a.dataSM('href')).removeDataSM('href');
5817					}
5818					// if the sub is not visible
5819					if ($sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) {
5820						// try to activate the item and show the sub
5821						this.itemActivate($a);
5822						// if "itemActivate" showed the sub, prevent the click so that the link is not loaded
5823						// if it couldn't show it, then the sub menus are disabled with an !important declaration (e.g. via mobile styles) so let the link get loaded
5824						if ($sub.is(':visible')) {
5825							return false;
5826						}
5827					}
5828				} else if (this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 && $sub) {
5829					this.clickActivated = true;
5830					this.menuShow($sub);
5831					return false;
5832				}
5833				if ($a.hasClass('disabled')) {
5834					return false;
5835				}
5836				if (this.$root.triggerHandler('select.smapi', $a[0]) === false) {
5837					return false;
5838				}
5839			},
5840			itemDown: function(e) {
5841				var $a = $(e.currentTarget);
5842				if (!this.handleItemEvents($a)) {
5843					return;
5844				}
5845				$a.dataSM('mousedown', true);
5846			},
5847			itemEnter: function(e) {
5848				var $a = $(e.currentTarget);
5849				if (!this.handleItemEvents($a)) {
5850					return;
5851				}
5852				if (!this.isTouchMode()) {
5853					if (this.showTimeout) {
5854						clearTimeout(this.showTimeout);
5855						this.showTimeout = 0;
5856					}
5857					var self = this;
5858					this.showTimeout = setTimeout(function() { self.itemActivate($a); }, this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 ? 1 : this.opts.showTimeout);
5859				}
5860				this.$root.triggerHandler('mouseenter.smapi', $a[0]);
5861			},
5862			itemFocus: function(e) {
5863				var $a = $(e.currentTarget);
5864				if (!this.handleItemEvents($a)) {
5865					return;
5866				}
5867				// fix (the mousedown check): in some browsers a tap/click produces consecutive focus + click events so we don't need to activate the item on focus
5868				if ((!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) {
5869					this.itemActivate($a);
5870				}
5871				this.$root.triggerHandler('focus.smapi', $a[0]);
5872			},
5873			itemLeave: function(e) {
5874				var $a = $(e.currentTarget);
5875				if (!this.handleItemEvents($a)) {
5876					return;
5877				}
5878				if (!this.isTouchMode()) {
5879					if ($a[0].blur) {
5880						$a[0].blur();
5881					}
5882					if (this.showTimeout) {
5883						clearTimeout(this.showTimeout);
5884						this.showTimeout = 0;
5885					}
5886				}
5887				$a.removeDataSM('mousedown');
5888				this.$root.triggerHandler('mouseleave.smapi', $a[0]);
5889			},
5890			itemTouchEnd: function(e) {
5891				var $a = $(e.currentTarget);
5892				if (!this.handleItemEvents($a)) {
5893					return;
5894				}
5895				// prevent the address bar on iPhone from sliding down when expanding a sub menu
5896				var $sub = $a.parent().dataSM('sub');
5897				if ($a.attr('href').charAt(0) !== '#' && $sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) {
5898					$a.dataSM('href', $a.attr('href'));
5899					$a.attr('href', '#');
5900				}
5901			},
5902			menuFixLayout: function($ul) {
5903				// fixes a menu that is being shown for the first time
5904				if (!$ul.dataSM('shown-before')) {
5905					$ul.hide().dataSM('shown-before', true);
5906					// fix the layout of the items in IE<8
5907					if (IElt8) {
5908						$ul.children().css({ styleFloat: 'left', width: '100%' });
5909					}
5910				}
5911			},
5912			menuHide: function($sub) {
5913				if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) {
5914					return;
5915				}
5916				$sub.stop(true, true);
5917				if ($sub.is(':visible')) {
5918					var complete = function() {
5919						// unset z-index
5920						if (IElt9) {
5921							$sub.parent().css('z-index', '');
5922						} else {
5923							$sub.css('z-index', '');
5924						}
5925					};
5926					// if ($('html.firefox').length) {
5927					// 	$('#menu-main-menu > li > a').removeAttr('style');
5928					// 	// var menuel = $('.main-menu-container');
5929					// 	// setTimeout(function(){
5930					// 	// 	menuel.data('tempheight',undefined).removeAttr('style');
5931					// 	// }, 300);
5932					// }
5933					// if sub is collapsible (mobile view)
5934					if (this.isCollapsible()) {
5935						if (this.opts.collapsibleHideFunction) {
5936							this.opts.collapsibleHideFunction.call(this, $sub, complete);
5937						} else {
5938							$sub.hide(this.opts.collapsibleHideDuration, complete);
5939						}
5940					} else {
5941						if (this.opts.hideFunction) {
5942							this.opts.hideFunction.call(this, $sub, complete);
5943						} else {
5944							$sub.hide(this.opts.hideDuration, complete);
5945						}
5946					}
5947					// remove IE iframe shim
5948					if ($sub.dataSM('ie-shim')) {
5949						$sub.dataSM('ie-shim').remove();
5950					}
5951					// deactivate scrolling if it is activated for this sub
5952					if ($sub.dataSM('scroll')) {
5953						$sub.unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide();
5954					}
5955					// unhighlight parent item
5956					$sub.dataSM('parent-a').removeClass('highlighted');
5957					var level = $sub.dataSM('level');
5958					this.activatedItems.splice(level - 1, 1);
5959					this.visibleSubMenus.splice(level - 1, 1);
5960					this.$root.triggerHandler('hide.smapi', $sub[0]);
5961				}
5962			},
5963			menuHideAll: function() {
5964				if (this.showTimeout) {
5965					clearTimeout(this.showTimeout);
5966					this.showTimeout = 0;
5967				}
5968				// hide all subs
5969				for (var i = this.visibleSubMenus.length - 1; i > 0; i--) {
5970					this.menuHide(this.visibleSubMenus[i]);
5971				}
5972				// hide root if it's popup
5973				if (this.opts.isPopup) {
5974					this.$root.stop(true, true);
5975					if (this.$root.is(':visible')) {
5976						if (this.opts.hideFunction) {
5977							this.opts.hideFunction.call(this, this.$root);
5978						} else {
5979							this.$root.hide(this.opts.hideDuration);
5980						}
5981						// remove IE iframe shim
5982						if (this.$root.dataSM('ie-shim')) {
5983							this.$root.dataSM('ie-shim').remove();
5984						}
5985					}
5986				}
5987				this.activatedItems = [];
5988				this.visibleSubMenus = [];
5989				this.clickActivated = false;
5990				// reset z-index increment
5991				this.zIndexInc = 0;
5992			},
5993			menuIframeShim: function($ul) {
5994				// create iframe shim for the menu
5995				if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) {
5996					$ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 })
5997						.css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' })
5998					);
5999				}
6000			},
6001			menuInit: function($ul) {
6002				if (!$ul.dataSM('in-mega')) {
6003					this.subMenus.push($ul);
6004					// mark UL's in mega drop downs (if any) so we can neglect them
6005					if ($ul.hasClass('mega-menu')) {
6006						$ul.find('ul').dataSM('in-mega', true);
6007					}
6008					// get level (much faster than, for example, using parentsUntil)
6009					var level = 2,
6010						par = $ul[0];
6011					while ((par = par.parentNode.parentNode) != this.$root[0]) {
6012						level++;
6013					}
6014					// cache stuff
6015					$ul.dataSM('parent-a', $ul.prevAll('a').eq(-1))
6016						.dataSM('level', level)
6017						.parent().dataSM('sub', $ul);
6018					// add sub indicator to parent item
6019					if (this.opts.subIndicators) {
6020						$ul.dataSM('parent-a').addClass('has-submenu')[this.opts.subIndicatorsPos](this.$subArrow.clone());
6021					}
6022				}
6023			},
6024			menuPosition: function($sub) {
6025				var fixIE = $('html.ie').length;
6026				// if (fixIE) {
6027				// 	var $rowParent = $($sub).closest('.main-menu-container');
6028				// 	$rowParent.height($rowParent.height());
6029				// }
6030				var $a = $sub.dataSM('parent-a'),
6031					$li = $sub.parent(),
6032					$ul = $sub.parent().parent(),
6033					$container = $ul.closest('.row-menu-inner'),
6034					level = $sub.dataSM('level'),
6035					subW = this.getWidth($sub),
6036					subH = this.getHeight($sub),
6037					itemOffset = $a.offset(),
6038					itemX = itemOffset.left,
6039					itemY = itemOffset.top,
6040					itemW = this.getWidth($a),
6041					itemH = this.getHeight($a),
6042					$win = $(window),
6043					winX = $win.scrollLeft(),
6044					winY = $win.scrollTop(),
6045					winW = $win.width(),
6046					winH = $win.height(),
6047					containerW = $container.width(),
6048					containerOffsetX = containerW + ((winW - containerW) / 2),
6049					horizontalParent = $ul.hasClass('sm') && !$ul.hasClass('sm-vertical'),
6050					subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX,
6051					subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY,
6052					x, y, leftPos;
6053				if (horizontalParent) {
6054					x = this.opts.rightToLeftSubMenus ? itemW - subW - subOffsetX : subOffsetX;
6055					y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY;
6056				} else {
6057					x = this.opts.rightToLeftSubMenus ? subOffsetX - subW : itemW - subOffsetX;
6058					y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY;
6059				}
6060				if (this.opts.keepInViewport && !this.isCollapsible()) {
6061					if (this.isFixed()) {
6062						itemX -= winX;
6063						itemY -= winY;
6064						winX = winY = 0;
6065					}
6066					var absX = itemX + x,
6067						absY = itemY + y;
6068					if (this.opts.rightToLeftSubMenus && absX < winX) {
6069						x = horizontalParent ? winX - absX + x : itemW - subOffsetX;
6070					} else if (!this.opts.rightToLeftSubMenus && absX + subW > winX + containerOffsetX ) {
6071						x = horizontalParent ? winX + containerOffsetX - subW - absX + x : subOffsetX - subW;
6072					}
6073					if (!horizontalParent) {
6074						if (subH < winH && absY + subH > winY + winH) {
6075							y += winY + winH - subH - absY;
6076						} else if (subH >= winH || absY < winY) {
6077							y += winY - absY;
6078						}
6079					}
6080					// do we need scrolling?
6081					// 0.49 added for the sake of IE9/FF4+ where we might be dealing with float numbers for "subH"
6082					if (mouse && (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49)) {
6083						var self = this;
6084						if (!$sub.dataSM('scroll-arrows')) {
6085							$sub.dataSM('scroll-arrows', $([$('<span class="scroll-up"><span class="scroll-up-arrow"></span></span>')[0], $('<span class="scroll-down"><span class="scroll-down-arrow"></span></span>')[0]])
6086								.bind({
6087									mouseenter: function() { self.menuScroll($sub, $(this).hasClass('scroll-up')); },
6088									mouseleave: function(e) {
6089										self.menuScrollStop($sub);
6090										self.menuScrollOut($sub, e);
6091									},
6092									'mousewheel DOMMouseScroll': function(e) { e.preventDefault(); }
6093								})
6094								.insertAfter($sub)
6095							);
6096						}
6097						// bind events to show/hide arrows on hover and save scrolling data for this sub
6098						var vportY = winY - (itemY + itemH);
6099						$sub.dataSM('scroll', {
6100								vportY: vportY,
6101								subH: subH,
6102								winH: winH,
6103								step: 1
6104							})
6105							.bind({
6106								'mouseover.smartmenus_scroll': function(e) { self.menuScrollOver($sub, e); },
6107								'mouseout.smartmenus_scroll': function(e) { self.menuScrollOut($sub, e); },
6108								'mousewheel.smartmenus_scroll DOMMouseScroll.smartmenus_scroll': function(e) { self.menuScrollMousewheel($sub, e); }
6109							})
6110							.dataSM('scroll-arrows').css({ top: 'auto', left: '0', marginLeft: x + (parseInt($sub.css('border-left-width')) || 0), width: this.getWidth($sub) - (parseInt($sub.css('border-left-width')) || 0) - (parseInt($sub.css('border-right-width')) || 0), zIndex: this.get
6110StartZIndex() + this.zIndexInc })
6111							.eq(0).css('margin-top', vportY).end()
6112							.eq(1).css('margin-top', vportY + winH - this.getHeight($sub.dataSM('scroll-arrows').eq(1))).end()
6113							.eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show();
6114					}
6115				}
6116				// if ($sub.hasClass('mega-menu-inner')) {
6117				// 	if ($('.menu-wrapper .megamenu-diff').length > 0) {
6118				// 		leftPos = parseFloat($('.menu-wrapper .megamenu-diff').outerWidth());
6119				// 		leftPos = -leftPos;
6120				// 	} else leftPos = parseFloat($('.menu-wrapper .main-menu-container').css('paddingLeft'));
6121
6122				// 	if ($('body.header-full-width').length > 0) {
6123				// 		$sub.css({ width: $('.box-container').width()});
6124				// 		leftPos = (leftPos - parseFloat($('.menu-wrapper .row-menu-inner').css('paddingLeft')));
6125				// 	} else $sub.css({ width: containerW});
6126				// 	leftPos = leftPos + 'px';
6127
6128				// } else {
6129				// 	leftPos = $li.position().left + 'px';
6130				// }
6131				if ($sub.hasClass('mega-menu-inner')) {
6132					$sub.css({ width: containerW});
6133					if ($sub.closest('.row-menu-inner').find('.logo-container').length > 0) {
6134						leftPos = - (parseFloat($sub.closest('.row-menu-inner').find('.logo-container').css('paddingRight')) + ($sub.closest('.row-menu-inner').find('.logo-container').width())) + 'px';
6135					} else {
6136						leftPos = '0px';
6137					}
6138				} else {
6139					leftPos = (level > 2 ? $li.position().left - parseFloat($li.closest('ul').css('paddingLeft')) : $li.position().left ) + 'px';
6140					x = (level > 2 && x >= 0) ? x + (parseFloat($li.closest('ul').css('paddingLeft')) * 2) + 1 : x - 1;
6141				}
6142
6143				$sub.css({ top: (level > 2) ? $a[0].offsetTop : (fixIE ? itemH : '100%'), left: leftPos, marginLeft: x, marginTop: (level > 2) ? 0 : y - itemH + ($sub.closest('.menu-mini').length ? 0 : 1) });
6144				// IE iframe shim
6145				this.menuIframeShim($sub);
6146				if ($sub.dataSM('ie-shim')) {
6147					$sub.dataSM('ie-shim').css({ zIndex: $sub.css('z-index'), width: subW, height: subH, marginLeft: x, marginTop: y - itemH + ($sub.closest('.menu-mini').length ? 0 : 1) });
6148				}
6149			},
6150			menuScroll: function($sub, up, wheel) {
6151				var y = parseFloat($sub.css('margin-top')),
6152					scroll = $sub.dataSM('scroll'),
6153					end = scroll.vportY + (up ? 0 : scroll.winH - scroll.subH),
6154					step = wheel || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor($sub.dataSM('scroll').step);
6155				$sub.add($sub.dataSM('ie-shim')).css('margin-top', Math.abs(end - y) > step ? y + (up ? step : -step) : end);
6156				y = parseFloat($sub.css('margin-top'));
6157				// show opposite arrow if appropriate
6158				if (up && y + scroll.subH > scroll.vportY + scroll.winH || !up && y < scroll.vportY) {
6159					$sub.dataSM('scroll-arrows').eq(up ? 1 : 0).show();
6160				}
6161				// accelerate when not using mousewheel to scroll
6162				if (!wheel && this.opts.scrollAccelerate && $sub.dataSM('scroll').step < this.opts.scrollStep) {
6163					$sub.dataSM('scroll').step += 0.5;
6164				}
6165				// "y" and "end" might be float numbers in IE9/FF4+ so this weird way to check is used
6166				if (Math.abs(y - end) < 1) {
6167					$sub.dataSM('scroll-arrows').eq(up ? 0 : 1).hide();
6168					$sub.dataSM('scroll').step = 1;
6169				} else if (!wheel) {
6170					var self = this;
6171					this.scrollTimeout = setTimeout(function() { self.menuScroll($sub, up); }, this.opts.scrollInterval);
6172				}
6173			},
6174			menuScrollMousewheel: function($sub, e) {
6175				var $closestSub = $(e.target).closest('ul');
6176				while ($closestSub.dataSM('in-mega')) {
6177					$closestSub = $closestSub.parent().closest('ul');
6178				}
6179				if ($closestSub[0] == $sub[0]) {
6180					var up = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0;
6181					if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) {
6182						this.menuScroll($sub, up, true);
6183					}
6184				}
6185				e.preventDefault();
6186			},
6187			menuScrollOut: function($sub, e) {
6188				var reClass = /^scroll-(up|down)/,
6189					$closestSub = $(e.relatedTarget).closest('ul');
6190				while ($closestSub.dataSM('in-mega')) {
6191					$closestSub = $closestSub.parent().closest('ul');
6192				}
6193				if (!reClass.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || $closestSub[0] != $sub[0])) {
6194					$sub.dataSM('scroll-arrows').css('visibility', 'hidden');
6195				}
6196			},
6197			menuScrollOver: function($sub, e) {
6198				var reClass = /^scroll-(up|down)/,
6199					$closestSub = $(e.target).closest('ul');
6200				while ($closestSub.dataSM('in-mega')) {
6201					$closestSub = $closestSub.parent().closest('ul');
6202				}
6203				if (!reClass.test(e.target.className) && $closestSub[0] == $sub[0]) {
6204					$sub.dataSM('scroll-arrows').css('visibility', 'visible');
6205				}
6206			},
6207			menuScrollStop: function($sub) {
6208				if (this.scrollTimeout) {
6209					clearTimeout(this.scrollTimeout);
6210					this.scrollTimeout = 0;
6211					$sub.dataSM('scroll').step = 1;
6212				}
6213			},
6214			menuShow: function($sub) {
6215				if (!$sub.dataSM('beforefirstshowfired')) {
6216					$sub.dataSM('beforefirstshowfired', true);
6217					if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) {
6218						return;
6219					}
6220				}
6221				if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) {
6222					return;
6223				}
6224				this.menuFixLayout($sub);
6225				$sub.stop(true, true);
6226				if (!$sub.is(':visible')) {
6227					// if ($('html.firefox').length) {
6228					// 	if ($sub.dataSM('level') == 2) {
6229					// 		$('#menu-main-menu > li > a').css('height','0');
6230					// 		$('#menu-main-menu > li > a').removeAttr('style');
6231					// 		// var menuel = $('.main-menu-container'),
6232					// 		//  menuelHeight = menuel.outerHeight(true);
6233					// 		// menuel.removeAttr('style');
6234					// 		// if (menuel.data('tempheight') == undefined) menuel.data('tempheight',menuelHeight).css('height',menuelHeight+'px');
6235					// 		// else menuel.css('height',menuel.data('tempheight')+'px');
6236					// 	}
6237					// }
6238					// set z-index - for IE < 9 set it to the parent LI
6239					var zIndex = this.getStartZIndex() + (++this.zIndexInc);
6240					if (IElt9) {
6241						$sub.parent().css('z-index', zIndex);
6242					} else {
6243						$sub.css('z-index', zIndex);
6244					}
6245					// highlight parent item
6246					if (this.opts.keepHighlighted || this.isCollapsible()) {
6247						if ($sub.dataSM('parent-a').attr('data-type') != 'title')
6248							$sub.dataSM('parent-a').addClass('highlighted');
6249					}
6250					// min/max-width fix - no way to rely purely on CSS as all UL's are nested
6251					if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) {
6252						if (!IElt8) {
6253							$sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
6254							if (this.opts.subMenusMinWidth) {
6255							 	$sub.css('min-width', this.opts.subMenusMinWidth);
6256							}
6257							if (this.opts.subMenusMaxWidth) {
6258							 	var noMaxWidth = this.getWidth($sub);
6259							 	$sub.css('max-width', this.opts.subMenusMaxWidth);
6260								if (noMaxWidth > this.getWidth($sub)) {
6261									$sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
6262								}
6263							}
6264						// IE6,7
6265 						} else {
6266							$sub.children().css('styleFloat', 'none');
6267							if (IE6) {
6268								$sub.width(this.opts.subMenusMinWidth ? this.opts.subMenusMinWidth : 1)
6269									.children().children('a').css('white-space', 'nowrap');
6270							} else { // IE7
6271								$sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
6272								if (this.opts.subMenusMinWidth) {
6273							    $sub.css('min-width', this.opts.subMenusMinWidth);
6274								}
6275							}
6276							if (this.opts.subMenusMaxWidth) {
6277								var noMaxWidth = $sub.width();
6278								if (IE6) {
6279							 		var maxWidth = $sub.css({ width: this.opts.subMenusMaxWidth, overflowX: 'hidden', overflowY: 'hidden' }).width();
6280									if (noMaxWidth > maxWidth) {
6281										$sub.css({ width: maxWidth, overflowX: 'visible', overflowY: 'visible' }).children().children('a').css('white-space', '');
6282									} else {
6283										$sub.css({ width: noMaxWidth, overflowX: 'visible', overflowY: 'visible' });
6284									}
6285								} else { // IE7
6286									$sub.css('max-width', this.opts.subMenusMaxWidth);
6287									if (noMaxWidth > $sub.width()) {
6288										$sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
6289									} else {
6290										$sub.width(noMaxWidth);
6291									}
6292								}
6293							} else {
6294							 	$sub.width($sub.width());
6295							}
6296							$sub.children().css('styleFloat', 'left');
6297						}
6298					}
6299					this.menuPosition($sub);
6300					// insert IE iframe shim
6301					if ($sub.dataSM('ie-shim')) {
6302						$sub.dataSM('ie-shim').insertBefore($sub);
6303					}
6304					var complete = function() {
6305						// fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used
6306						$sub.css('overflow', '');
6307					};
6308					// if sub is collapsible (mobile view)
6309					if (this.isCollapsible()) {
6310						if (this.opts.collapsibleShowFunction) {
6311							this.opts.collapsibleShowFunction.call(this, $sub, complete);
6312						} else {
6313							$sub.show(this.opts.collapsibleShowDuration, complete);
6314						}
6315					} else {
6316						if (this.opts.showFunction) {
6317							this.opts.showFunction.call(this, $sub, complete);
6318						} else {
6319							$sub.show(this.opts.showDuration, complete);
6320						}
6321					}
6322					// save new sub menu for this level
6323					this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub;
6324					this.$root.triggerHandler('show.smapi', $sub[0]);
6325				}
6326			},
6327			popupHide: function(noHideTimeout) {
6328				if (this.hideTimeout) {
6329					clearTimeout(this.hideTimeout);
6330					this.hideTimeout = 0;
6331				}
6332				var self = this;
6333				this.hideTimeout = setTimeout(function() {
6334					self.menuHideAll();
6335				}, noHideTimeout ? 1 : this.opts.hideTimeout);
6336			},
6337			popupShow: function(left, top) {
6338				if (!this.opts.isPopup) {
6339					alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.');
6340					return;
6341				}
6342				if (this.hideTimeout) {
6343					clearTimeout(this.hideTimeout);
6344					this.hideTimeout = 0;
6345				}
6346				this.menuFixLayout(this.$root);
6347				this.$root.stop(true, true);
6348				if (!this.$root.is(':visible')) {
6349					this.$root.css({ left: left, top: top });
6350					// IE iframe shim
6351					this.menuIframeShim(this.$root);
6352					if (this.$root.dataSM('ie-shim')) {
6353						this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
6353: left, top: top }).insertBefore(this.$root);
6354					}
6355					// show menu
6356					if (this.opts.showFunction) {
6357						this.opts.showFunction.call(this, this.$root);
6358					} else {
6359						this.$root.show(this.opts.showDuration);
6360					}
6361					this.visibleSubMenus[0] = this.$root;
6362				}
6363			},
6364			refresh: function() {
6365				this.menuHideAll();
6366				this.$root.find('ul').each(function() {
6367						var $this = $(this);
6368						if ($this.dataSM('scroll-arrows')) {
6369							$this.dataSM('scroll-arrows').remove();
6370						}
6371					})
6372					.removeDataSM('in-mega')
6373					.removeDataSM('shown-before')
6374					.removeDataSM('ie-shim')
6375					.removeDataSM('scroll-arrows')
6376					.removeDataSM('parent-a')
6377					.removeDataSM('level')
6378					.removeDataSM('beforefirstshowfired');
6379				this.$root.find('a.has-submenu').removeClass('has-submenu')
6380					.parent().removeDataSM('sub');
6381				if (this.opts.subIndicators) {
6382					this.$root.find('span.sub-arrow').remove();
6383				}
6384				if (this.opts.markCurrentItem) {
6385					this.$root.find('a.current').removeClass('current');
6386				}
6387				this.subMenus = [];
6388				this.init(true);
6389			},
6390			rootOut: function(e) {
6391				if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
6392					return;
6393				}
6394				if (this.hideTimeout) {
6395					clearTimeout(this.hideTimeout);
6396					this.hideTimeout = 0;
6397				}
6398				if (!this.opts.showOnClick || !this.opts.hideOnClick) {
6399					var self = this;
6400					this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout);
6401				}
6402			},
6403			rootOver: function(e) {
6404				if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
6405					return;
6406				}
6407				if (this.hideTimeout) {
6408					clearTimeout(this.hideTimeout);
6409					this.hideTimeout = 0;
6410				}
6411			},
6412			winResize: function(e) {
6413				if (!this.handleEvents()) {
6414					// we still need to resize the disable overlay if it's visible
6415					if (this.$disableOverlay) {
6416						var pos = this.$root.offset();
6417	 					this.$disableOverlay.css({
6418							top: pos.top,
6419							left: pos.left,
6420							width: this.$root.outerWidth(),
6421							height: this.$root.outerHeight()
6422						});
6423					}
6424					return;
6425				}
6426				// hide sub menus on resize - on mobile do it only on orientation change
6427				if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) {
6428					if (this.activatedItems.length) {
6429						this.activatedItems[this.activatedItems.length - 1][0].blur();
6430					}
6431					this.menuHideAll();
6432				}
6433			}
6434		}
6435	});
6436
6437	$.fn.dataSM = function(key, val) {
6438		if (val) {
6439			return this.data(key + '_smartmenus', val);
6440		}
6441		return this.data(key + '_smartmenus');
6442	}
6443
6444	$.fn.removeDataSM = function(key) {
6445		return this.removeData(key + '_smartmenus');
6446	}
6447
6448	$.fn.smartmenus = function(options) {
6449		if (typeof options == 'string') {
6450			var args = arguments,
6451				method = options;
6452			Array.prototype.shift.call(args);
6453			return this.each(function() {
6454				var smartmenus = $(this).data('smartmenus');
6455				if (smartmenus && smartmenus[method]) {
6456					smartmenus[method].apply(smartmenus, args);
6457				}
6458			});
6459		}
6460		var opts = $.extend({}, $.fn.smartmenus.defaults, options);
6461		return this.each(function() {
6462			new $.SmartMenus(this, opts);
6463		});
6464	}
6465
6466	// default settings
6467	$.fn.smartmenus.defaults = {
6468		isPopup:		false,		// is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar
6469		mainMenuSubOffsetX:	0,		// pixels offset from default position
6470		mainMenuSubOffsetY:	0,		// pixels offset from default position
6471		subMenusSubOffsetX:	0,		// pixels offset from default position
6472		subMenusSubOffsetY:	0,		// pixels offset from default position
6473		subMenusMinWidth:	'10em',		// min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
6474		subMenusMaxWidth:	'20em',		// max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
6475		subIndicators: 		true,		// create sub menu indicators - creates a SPAN and inserts it in the A
6476		subIndicatorsPos: 	'prepend',	// position of the SPAN relative to the menu item content ('prepend', 'append')
6477		subIndicatorsText:	'+',		// [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too)
6478		scrollStep: 		30,		// pixels step when scrolling long sub menus that do not fit in the viewport height
6479		scrollInterval:		30,		// interval between each scrolling step
6480		scrollAccelerate:	true,		// accelerate scrolling or use a fixed step
6481		showTimeout:		250,		// timeout before showing the sub menus
6482		hideTimeout:		500,		// timeout before hiding the sub menus
6483		showDuration:		0,		// duration for show animation - set to 0 for no animation - matters only if showFunction:null
6484		showFunction:		null,		// custom function to use when showing a sub menu (the default is the jQuery 'show')
6485							// don't forget to call complete() at the end of whatever you do
6486							// e.g.: function($ul, complete) { $ul.fadeIn(250, complete); }
6487		hideDuration:		0,		// duration for hide animation - set to 0 for no animation - matters only if hideFunction:null
6488		hideFunction:		function($ul, complete) { $ul.fadeOut(200, complete); },	// custom function to use when hiding a sub menu (the default is the jQuery 'hide')
6489							// don't forget to call complete() at the end of whatever you do
6490							// e.g.: function($ul, complete) { $ul.fadeOut(250, complete); }
6491		collapsibleShowDuration:0,		// duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null
6492		collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); },	// custom function to use when showing a collapsible sub menu
6493							// (i.e. when mobile styles are used to make the sub menus collapsible)
6494		collapsibleHideDuration:0,		// duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null
6495		collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); },	// custom function to use when hiding a collapsible sub menu
6496							// (i.e. when mobile styles are used to make the sub menus collapsible)
6497		showOnClick:		false,		// show the first-level sub menus onclick instead of onmouseover (matters only for mouse input)
6498		hideOnClick:		true,		// hide the sub menus on click/tap anywhere on the page
6499		keepInViewport:		true,		// reposition the sub menus if needed to make sure they always appear inside the viewport
6500		keepHighlighted:	true,		// keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's)
6501		markCurrentItem:	false,		// automatically add the 'current' class to the A element of the item linking to the current URL
6502		markCurrentTree:	true,		// add the 'current' class also to the A elements of all ancestor items of the current item
6503		rightToLeftSubMenus:	false,		// right to left display of the sub menus (check the CSS for the sub indicators' position)
6504		bottomToTopSubMenus:	false,		// bottom to top display of the sub menus
6505		overlapControlsInIE:	true		// make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.)
6506	};
6507
6508})(jQuery);
6509
6510/*
6511 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
6512 *
6513 * Uses the built in easing capabilities added In jQuery 1.1
6514 * to offer multiple easing options
6515 *
6516 * TERMS OF USE - jQuery Easing
6517 * 
6518 * Open source under the BSD License. 
6519 * 
6520 * Copyright © 2008 George McGinley Smith
6521 * All rights reserved.
6522 * 
6523 * Redistribution and use in source and binary forms, with or without modification, 
6524 * are permitted provided that the following conditions are met:
6525 * 
6526 * Redistributions of source code must retain the above copyright notice, this list of 
6527 * conditions and the following disclaimer.
6528 * Redistributions in binary form must reproduce the above copyright notice, this list 
6529 * of conditions and the following disclaimer in the documentation and/or other materials 
6530 * provided with the distribution.
6531 * 
6532 * Neither the name of the author nor the names of contributors may be used to endorse 
6533 * or promote products derived from this software without specific prior written permission.
6534 * 
6535 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
6536 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
6537 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
6538 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
vendor: 5,091 bytes, lines 6539-6684
6539 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
6540 *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
6541 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
6542 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
6543 * OF THE POSSIBILITY OF SUCH DAMAGE. 
6544 *
6545*/
6546
6547// t: current time, b: begInnIng value, c: change In value, d: duration
6548jQuery.easing['jswing'] = jQuery.easing['swing'];
6549
6550jQuery.extend( jQuery.easing,
6551{
6552	def: 'easeOutQuad',
6553	swing: function (x, t, b, c, d) {
6554		//alert(jQuery.easing.default);
6555		return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
6556	},
6557	easeInQuad: function (x, t, b, c, d) {
6558		return c*(t/=d)*t + b;
6559	},
6560	easeOutQuad: function (x, t, b, c, d) {
6561		return -c *(t/=d)*(t-2) + b;
6562	},
6563	easeInOutQuad: function (x, t, b, c, d) {
6564		if ((t/=d/2) < 1) return c/2*t*t + b;
6565		return -c/2 * ((--t)*(t-2) - 1) + b;
6566	},
6567	easeInCubic: function (x, t, b, c, d) {
6568		return c*(t/=d)*t*t + b;
6569	},
6570	easeOutCubic: function (x, t, b, c, d) {
6571		return c*((t=t/d-1)*t*t + 1) + b;
6572	},
6573	easeInOutCubic: function (x, t, b, c, d) {
6574		if ((t/=d/2) < 1) return c/2*t*t*t + b;
6575		return c/2*((t-=2)*t*t + 2) + b;
6576	},
6577	easeInQuart: function (x, t, b, c, d) {
6578		return c*(t/=d)*t*t*t + b;
6579	},
6580	easeOutQuart: function (x, t, b, c, d) {
6581		return -c * ((t=t/d-1)*t*t*t - 1) + b;
6582	},
6583	easeInOutQuart: function (x, t, b, c, d) {
6584		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
6585		return -c/2 * ((t-=2)*t*t*t - 2) + b;
6586	},
6587	easeInQuint: function (x, t, b, c, d) {
6588		return c*(t/=d)*t*t*t*t + b;
6589	},
6590	easeOutQuint: function (x, t, b, c, d) {
6591		return c*((t=t/d-1)*t*t*t*t + 1) + b;
6592	},
6593	easeInOutQuint: function (x, t, b, c, d) {
6594		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
6595		return c/2*((t-=2)*t*t*t*t + 2) + b;
6596	},
6597	easeInSine: function (x, t, b, c, d) {
6598		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
6599	},
6600	easeOutSine: function (x, t, b, c, d) {
6601		return c * Math.sin(t/d * (Math.PI/2)) + b;
6602	},
6603	easeInOutSine: function (x, t, b, c, d) {
6604		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
6605	},
6606	easeInExpo: function (x, t, b, c, d) {
6607		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
6608	},
6609	easeOutExpo: function (x, t, b, c, d) {
6610		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
6611	},
6612	easeInOutExpo: function (x, t, b, c, d) {
6613		if (t==0) return b;
6614		if (t==d) return b+c;
6615		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
6616		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
6617	},
6618	easeInCirc: function (x, t, b, c, d) {
6619		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
6620	},
6621	easeOutCirc: function (x, t, b, c, d) {
6622		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
6623	},
6624	easeInOutCirc: function (x, t, b, c, d) {
6625		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
6626		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
6627	},
6628	easeInElastic: function (x, t, b, c, d) {
6629		var s=1.70158;var p=0;var a=c;
6630		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
6631		if (a < Math.abs(c)) { a=c; var s=p/4; }
6632		else var s = p/(2*Math.PI) * Math.asin (c/a);
6633		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
6634	},
6635	easeOutElastic: function (x, t, b, c, d) {
6636		var s=1.70158;var p=0;var a=c;
6637		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
6638		if (a < Math.abs(c)) { a=c; var s=p/4; }
6639		else var s = p/(2*Math.PI) * Math.asin (c/a);
6640		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
6641	},
6642	easeInOutElastic: function (x, t, b, c, d) {
6643		var s=1.70158;var p=0;var a=c;
6644		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
6645		if (a < Math.abs(c)) { a=c; var s=p/4; }
6646		else var s = p/(2*Math.PI) * Math.asin (c/a);
6647		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
6648		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
6649	},
6650	easeInBack: function (x, t, b, c, d, s) {
6651		if (s == undefined) s = 1.70158;
6652		return c*(t/=d)*t*((s+1)*t - s) + b;
6653	},
6654	easeOutBack: function (x, t, b, c, d, s) {
6655		if (s == undefined) s = 1.70158;
6656		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
6657	},
6658	easeInOutBack: function (x, t, b, c, d, s) {
6659		if (s == undefined) s = 1.70158; 
6660		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
6661		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
6662	},
6663	easeInBounce: function (x, t, b, c, d) {
6664		return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
6665	},
6666	easeOutBounce: function (x, t, b, c, d) {
6667		if ((t/=d) < (1/2.75)) {
6668			return c*(7.5625*t*t) + b;
6669		} else if (t < (2/2.75)) {
6670			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
6671		} else if (t < (2.5/2.75)) {
6672			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
6673		} else {
6674			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
6675		}
6676	},
6677	easeInOutBounce: function (x, t, b, c, d) {
6678		if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
6679		return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
6680	}
6681});
6682
6683/*
6684 *
6685 * TERMS OF USE - EASING EQUATIONS
6686 * 
6687 * Open source under the BSD License. 
6688 * 
6689 * Copyright © 2001 Robert Penner
6690 * All rights reserved.
6691 * 
6692 * Redistribution and use in source and binary forms, with or without modification, 
6693 * are permitted provided that the following conditions are met:
6694 * 
6695 * Redistributions of source code must retain the above copyright notice, this list of 
6696 * conditions and the following disclaimer.
6697 * Redistributions in binary form must reproduce the above copyright notice, this list 
6698 * of conditions and the following disclaimer in the documentation and/or other materials 
6699 * provided with the distribution.
6700 * 
6701 * Neither the name of the author nor the names of contributors may be used to endorse 
6702 * or promote products derived from this software without specific prior written permission.
6703 * 
6704 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
6705 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
6706 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
6707 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
6708 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
6709 *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
6710 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
6711 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
6712 * OF THE POSSIBILITY OF SUCH DAMAGE. 
6713 *
6714 */
6715
6716(function($, window, undefined) {
6717    // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
6718    // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
6719 
6720    // requestAnimationFrame polyfill by Erik Möller
6721    // fixes from Paul Irish and Tino Zijdel
6722 
6723    var lastTime = 0,
6724        running,
6725        animate = function (elem) {
6726            if (running) {
6727                window.requestAnimationFrame(animate, elem);
6728                jQuery.fx.tick();
6729            }
6730        },
6731        vendors = ['ms', 'moz', 'webkit', 'o'];
6732 
6733    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
6734        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
6735        window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
6736            || window[vendors[x]+'CancelRequestAnimationFrame'];
6737    }
6738 
6739    if (!window.requestAnimationFrame)
6740        window.requestAnimationFrame = function(fn, element) {
6741            var currTime = new Date().getTime(),
6742                delta = currTime - lastTime,
6743                timeToCall = Math.max(0, 16 - delta);
6744 
6745            var id = window.setTimeout(function() {
6746                    fn(currTime + timeToCall);
6747                },
6748                timeToCall
6749            );
6750 
6751            lastTime = currTime + timeToCall;
6752 
6753            return id;
6754        };
6755 
6756    if (!window.cancelAnimationFrame) {
6757        window.cancelAnimationFrame = function(id) {
6758            clearTimeout(id);
6759        };
6760    }
6761 
6762    jQuery.fx.timer = function (timer) {
6763        if (timer() && jQuery.timers.push(timer) && !running) {
6764            running = true;
6765            animate(timer.elem);
6766        }
6767    };
6768 
6769    jQuery.fx.stop = function() {
6770        running = false;
6771    };
6772 
6773}(jQuery, this));
6774
6775/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
6776 * Licensed under the MIT License (LICENSE.txt).
6777 *
6778 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
6779 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
6780 * Thanks to: Seamus Leahy for adding deltaX and deltaY
6781 *
6782 * Version: 3.0.6
6783 *
6784 * Requires: 1.2.2+
6785 */
6786(function($) {
6787    var types = ['DOMMouseScroll', 'mousewheel'];
6788    if ($.event.fixHooks) {
6789        for (var i = types.length; i;) {
6790            $.event.fixHooks[types[--i]] = $.event.mouseHooks;
6791        }
6792    }
6793    $.event.special.mousewheel = {
6794        setup: function() {
6795            if (this.addEventListener) {
6796                for (var i = types.length; i;) {
6797                    this.addEventListener(types[--i], handler, false);
6798                }
6799            } else {
6800                this.onmousewheel = handler;
6801            }
6802        },
6803        teardown: function() {
6804            if (this.removeEventListener) {
6805                for (var i = types.length; i;) {
6806                    this.removeEventListener(types[--i], handler, false);
6807                }
6808            } else {
6809                this.onmousewheel = null;
6810            }
6811        }
6812    };
6813    $.fn.extend({
6814        mousewheel: function(fn) {
6815            return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
6816        },
6817        unmousewheel: function(fn) {
6818            return this.unbind("mousewheel", fn);
6819        }
6820    });
6821
6822    function handler(event) {
6823        var orgEvent = event || window.event,
6824            args = [].slice.call(arguments, 1),
6825            delta = 0,
6826            returnValue = true,
6827            deltaX = 0,
6828            deltaY = 0;
6829        event = $.event.fix(orgEvent);
6830        event.type = "mousewheel";
6831        // Old school scrollwheel delta
6832        if (orgEvent.wheelDelta) {
6833            delta = orgEvent.wheelDelta / 120;
6834        }
6835        if (orgEvent.detail) {
6836            delta = -orgEvent.detail / 3;
6837        }
6838        // New school multidimensional scroll (touchpads) deltas
6839        deltaY = delta;
6840        // Gecko
6841        if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) {
6842            deltaY = 0;
6843            deltaX = -1 * delta;
6844        }
6845        // Webkit
6846        if (orgEvent.wheelDeltaY !== undefined) {
6847            deltaY = orgEvent.wheelDeltaY / 120;
6848        }
6849        if (orgEvent.wheelDeltaX !== undefined) {
6850            deltaX = -1 * orgEvent.wheelDeltaX / 120;
6851        }
6852        // Add event and delta to the front of the arguments
6853        args.unshift(event, delta, deltaX, deltaY);
6854        return ($.event.dispatch || $.event.handle).apply(this, args);
6855    }
6856})(jQuery);
6857
6858/**
6859 * jQuery iLightBox - Revolutionary Lightbox Plugin
6860 * http://www.ilightbox.net/
6861 *
6862 * @version: 2.2.0 - September 23, 2014
6863 *
6864 * @author: Hemn Chawroka
6865 *          http://www.iprodev.com/
6866 *
6867 */
6868(function($, window, undefined) {
6869
6870	var extensions = {
6871			flash: ['swf'],
6872			image: ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'tif', 'jfif', 'jpe'],
6873			iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'jsp', 'php', 'pl', 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml', 'txt'],
6874			video: ['avi', 'mov', 'mpg', 'mpeg', 'movie', 'mp4', 'webm', 'ogv', 'ogg', '3gp', 'm4v']
6875		},
6876
6877		// Global DOM elements
6878		$win = $(window),
6879		$doc = $(document),
6880
6881		// Support indicators
6882		browser,
6883		transform,
6884		gpuAcceleration,
6885		fullScreenApi = '',
6886		supportTouch = !!('ontouchstart' in window) && (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)),
6887
6888		// Events
6889		clickEvent = supportTouch ? "itap.iLightBox" : "click.iLightBox",
6890		touchStartEvent = supportTouch ? "touchstart.iLightBox" : "mousedown.iLightBox",
6891		touchStopEvent = supportTouch ? "touchend.iLightBox" : "mouseup.iLightBox",
6892		touchMoveEvent = supportTouch ? "touchmove.iLightBox" : "mousemove.iLightBox",
6893
6894		// Math shorthands
6895		abs = Math.abs,
6896		sqrt = Math.sqrt,
6897		round = Math.round,
6898		max = Math.max,
6899		min = Math.min,
6900		floor = Math.floor,
6901		random = Math.random,
6902
6903		pluginspages = {
6904			quicktime: 'http://www.apple.com/quicktime/download',
6905			flash: 'http://www.adobe.com/go/getflash'
6906		},
6907
6908		iLightBox = function(el, options, items, instant) {
6909			var iL = this;
6910
6911			iL.options = options,
6912				iL.selector = el.selector || el,
6913				iL.context = el.context,
6914				iL.instant = instant;
6915
6916			if (items.length < 1) iL.attachItems();
6917			else iL.items = items;
6918
6919			iL.vars = {
6920				total: iL.items.length,
6921				start: 0,
6922				current: null,
6923				next: null,
6924				prev: null,
6925				BODY: $('body'),
6926				loadRequests: 0,
6927				overlay: $('<div class="ilightbox-overlay"></div>'),
6928				loader: $('<div class="ilightbox-loader"><div></div></div>'),
6929				toolbar: $('<div class="ilightbox-toolbar"></div>'),
6930				innerToolbar: $('<div class="ilightbox-inner-toolbar"></div>'),
6931				title: $('<div class="ilightbox-title"></div>'),
6932				closeButton: $('<a class="ilightbox-close" title="' + iL.options.text.close + '"></a>'),
6933				fullScreenButton: $('<a class="ilightbox-fullscreen" title="' + iL.options.text.enterFullscreen + '"></a>'),
6934				innerPlayButton: $('<a class="ilightbox-play" title="' + iL.options.text.slideShow + '"></a>'),
6935				innerNextButton: $('<a class="ilightbox-next-button" title="' + iL.options.text.next + '"></a>'),
6936				innerPrevButton: $('<a class="ilightbox-prev-button" title="' + iL.options.text.previous + '"></a>'),
6937				holder: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + '" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
6938				nextPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-next" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
6939				prevPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-prev" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
6940				nextButton: $('<a class="ilightbox-button ilightbox-next-button" ondragstart="return false;" title="' + iL.options.text.next + '"><span></span></a>'),
6941				prevButton: $('<a class="ilightbox-button ilightbox-prev-button" ondragstart="return false;" title="' + iL.options.text.previous + '"><span></span></a>'),
6942				thumbnails: $('<div class="ilightbox-thumbnails" ondragstart="return false;"><div class="ilightbox-thumbnails-container"><a class="ilightbox-thumbnails-dragger"></a><div class="ilightbox-thumbnails-grid"></div></div></div>'),
6943				thumbs: false,
6944				nextLock: false,
6945				prevLock: false,
6946				hashLock: false,
6947				isMobile: false,
6948				mobileMaxWidth: 980,
6949				isInFullScreen: false,
6950				isSwipe: false,
6951				mouseID: 0,
6952				cycleID: 0,
6953				isPaused: 0
6954			};
6955
6956			// Hideable elements with mousemove event
6957			iL.vars.hideableElements = iL.vars.nextButton.add(iL.vars.prevButton);
6958
6959			iL.normalizeItems();
6960
6961			//Check necessary plugins
6962			iL.availPlugins();
6963
6964			//Set startFrom
6965			iL.options.startFrom = (iL.options.startFrom > 0 && iL.options.startFrom >= iL.vars.total) ? iL.vars.total - 1 : iL.options.startFrom;
6966
6967			//If randomStart
6968			iL.options.startFrom = (iL.options.randomStart) ? floor(random() * iL.vars.total) : iL.options.startFrom;
6969			iL.vars.start = iL.options.startFrom;
6970
6971			if (instant) iL.instantCall();
6972			else iL.patchItemsEvents();
6973
6974			if (iL.options.linkId) {
6975				iL.hashChangeHandler();
6976				$win.iLightBoxHashChange(function() {
6977					iL.hashChangeHandler();
6978				});
6979			}
6980
6981			if (supportTouch) {
6982				var RegExp = /(click|mouseenter|mouseleave|mouseover|mouseout)/ig,
6983					replace = "itap";
6984				iL.options.caption.show = iL.options.caption.show.replace(RegExp, replace),
6985					iL.options.caption.hide = iL.options.caption.hide.replace(RegExp, replace),
6986					iL.options.social.show = iL.options.social.show.replace(RegExp, replace),
6987					iL.options.social.hide = iL.options.social.hide.replace(RegExp, replace);
6988			}
6989
6990			if (iL.options.controls.arrows) {
6991				$.extend(iL.options.styles, {
6992					nextOffsetX: 36,
6993					prevOffsetX: 36,
6994					nextOpacity: 0,
6995					prevOpacity: 0
6996				});
6997			}
6998		};
6999
7000	//iLightBox helpers
7001	iLightBox.prototype = {
7002		showLoader: function() {
7003			var iL = this;
7004			iL.vars.loadRequests += 1;
7005			if (iL.options.path.toLowerCase() == "horizontal") iL.vars.loader.stop().animate({
7006				//top: '2px'
7007				opacity: '1'
7008			}, iL.options.show.speed, 'easeOutCirc');
7009			else iL.vars.loader.stop().animate({
7010			//	left: '2px'
7011				opacity: '1'
7012			}, iL.options.show.speed, 'easeOutCirc');
7013		},
7014
7015		hideLoader: function() {
7016			var iL = this;
7017			iL.vars.loadRequests -= 1;
7018			iL.vars.loadRequests = (iL.vars.loadRequests < 0) ? 0 : iL.vars.loadRequests;
7019			if (iL.options.path.toLowerCase() == "horizontal") {
7020				if (iL.vars.loadRequests <= 0) iL.vars.loader.stop().animate({
7021					//top: '-20px'
7022					opacity: '0'
7023				}, iL.options.show.speed, 'easeInCirc');
7024			} else {
7025				if (iL.vars.loadRequests <= 0) iL.vars.loader.stop().animate({
7026					//left: '-20px'
7027					opacity: '0'
7028				}, iL.options.show.speed, 'easeInCirc');
7029			}
7030		},
7031
7032		createUI: function() {
7033			var iL = this;
7034
7035			iL.ui = {
7036				currentElement: iL.vars.holder,
7037				nextElement: iL.vars.nextPhoto,
7038				prevElement: iL.vars.prevPhoto,
7039				currentItem: iL.vars.current,
7040				nextItem: iL.vars.next,
7041				prevItem: iL.vars.prev,
7042				hide: function() {
7043					iL.closeAction();
7044				},
7045				refresh: function() {
7046					(arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto();
7047				},
7048				fullscreen: function() {
7049					iL.fullScreenAction();
7050				}
7051			};
7052		},
7053
7054		attachItems: function() {
7055			var iL = this,
7056				itemsObject = new Array(),
7057				items = new Array();
7058
7059			$(iL.selector, iL.context).each(function() {
7060				var t = $(this),
7061					URL = t.attr(iL.options.attr) || null,
7062					options = t.data("options") && eval("({" + t.data("options") + "})") || {},
7063					caption = t.data('caption'),
7064					title = t.data('title'),
7065					type = t.data('type') || getTypeByExtension(URL);
7066
7067				items.push({
7068					URL: URL,
7069					caption: caption,
7070					title: title,
7071					type: type,
7072					options: options
7073				});
7074
7075				if (!iL.instant) itemsObject.push(t);
7076			});
7077
7078			iL.items = items,
7079				iL.itemsObject = itemsObject;
7080		},
7081
7082		normalizeItems: function() {
7083			var iL = this,
7084				newItems = new Array();
7085
7086			$.each(iL.items, function(key, val) {
7087
7088				if (typeof val == "string") val = {
7089					url: val
7090				};
7091
7092				var URL = val.url || val.URL || null,
7093					options = val.options || {},
7094					caption = val.caption || null,
7095					title = val.title || null,
7096					type = (val.type) ? val.type.toLowerCase() : getTypeByExtension(URL),
7097					ext = (typeof URL != 'object') ? getExtension(URL) : '';
7098
7099				options.thumbnail = options.thumbnail || ((type == "image") ? URL : null),
7100				options.videoType = options.videoType || null,
7101				options.skin = options.skin || iL.options.skin,
7102				options.width = options.width || null,
7103				options.height = options.height || null,
7104				options.mousewheel = (typeof options.mousewheel != 'undefined') ? options.mousewheel : true,
7105				options.swipe = (typeof options.swipe != 'undefined') ? options.swipe : true,
7106				options.social = (typeof options.social != 'undefined') ? options.social : iL.options.social.buttons && $.extend({}, {}, iL.options.social.buttons);
7107
7108				if (type == "video") {
7109					options.html5video = (typeof options.html5video != 'undefined') ? options.html5video : {};
7110
7111					options.html5video.webm = options.html5video.webm || options.html5video.WEBM || null;
7112					options.html5video.controls = (typeof options.html5video.controls != 'undefined') ? options.html5video.controls : "controls";
7113					options.html5video.preload = options.html5video.preload || "metadata";
7114					options.html5video.autoplay = (typeof options.html5video.autoplay != 'undefined') ? options.html5video.autoplay : false;
7115				}
7116
7117				if (!options.width || !options.height) {
7118					if (type == "video") options.width = 1280, options.height = 720;
7119					else if (type == "iframe") options.width = '100%', options.height = '90%';
7120					else if (type == "flash") options.width = 1280, options.height = 720;
7121				}
7122
7123				delete val.url;
7124				val.index = key;
7125				val.URL = URL;
7126				val.caption = caption;
7127				val.title = title;
7128				val.type = type;
7129				val.options = options;
7130				val.ext = ext;
7131
7132				newItems.push(val);
7133			});
7134
7135			iL.items = newItems;
7136		},
7137
7138		instantCall: function() {
7139			var iL = this,
7140				key = iL.vars.start;
7141
7142			iL.vars.current = key;
7143			iL.vars.next = (iL.items[key + 1]) ? key + 1 : null;
7144			iL.vars.prev = (iL.items[key - 1]) ? key - 1 : null;
7145
7146			iL.addContents();
7147			iL.patchEvents();
7148		},
7149
7150		addContents: function() {
7151			var iL = this,
7152				vars = iL.vars,
7153				opts = iL.options,
7154				viewport = getViewport(),
7155				path = opts.path.toLowerCase(),
7156				recognizingItems = vars.total > 0 && iL.items.filter(function(e, i, arr) {
7157					return ['image', 'flash', 'video'].indexOf(e.type) === -1 && typeof e.recognized === 'undefined' && (opts.smartRecognition || e.options.smartRecognition);
7158				}),
7159				needRecognition = recognizingItems.length > 0;
7160
7161			if (opts.mobileOptimizer && !opts.innerToolbar)
7162				vars.isMobile = viewport.width <= vars.mobileMaxWidth;
7163
7164			vars.overlay.addClass(opts.skin).hide().css('opacity', opts.overlay.opacity);
7165
7166			if (opts.linkId)
7167				vars.overlay[0].setAttribute('linkid', opts.linkId);
7168
7169			//Add Toolbar Buttons
7170			if (opts.controls.toolbar) {
7171				vars.toolbar.addClass(opts.skin).append(vars.closeButton);
7172				if (opts.controls.fullscreen)
7173					vars.toolbar.append(vars.fullScreenButton);
7174				if (opts.controls.slideshow)
7175					vars.toolbar.append(vars.innerPlayButton);
7176				if (vars.total > 1)
7177					vars.toolbar.append(vars.innerPrevButton).append(vars.innerNextButton);
7178			}
7179
7180			//Append elements to body
7181			vars.BODY.addClass('ilightbox-noscroll').append(vars.overlay).append(vars.loader).append(vars.holder).append(vars.nextPhoto).append(vars.prevPhoto);
7182
7183			if (!opts.innerToolbar)
7184				vars.BODY.append(vars.toolbar);
7185			if (opts.controls.arrows)
7186				vars.BODY.append(vars.nextButton).append(vars.prevButton);
7187
7188			if (opts.controls.thumbnail && vars.total > 1) {
7189				vars.BODY.append(vars.thumbnails);
7190				vars.thumbnails.addClass(opts.skin).addClass('ilightbox-' + path);
7191				$('div.ilightbox-thumbnails-grid', vars.thumbnails).empty();
7192				vars.thumbs = true;
7193			}
7194
7195			//Configure loader and arrows
7196			var loaderCss = (opts.path.toLowerCase() == "horizontal") ? {
7197				left: parseInt((viewport.width / 2) - (vars.loader.outerWidth() / 2))
7198			} : {
7199				top: parseInt((viewport.height / 2) - (vars.loader.outerHeight() / 2))
7200			};
7201			vars.loader.addClass(opts.skin).css(loaderCss);
7202			vars.nextButton.add(vars.prevButton).addClass(opts.skin);
7203			if (path == "horizontal")
7204				vars.loader.add(vars.nextButton).add(vars.prevButton).addClass('horizontal');
7205
7206			// Configure arrow buttons
7207			vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile');
7208
7209			if (!opts.infinite) {
7210				vars.prevButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
7211
7212				if (vars.current == 0)
7213					vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
7214				if (vars.current >= vars.total - 1)
7215					vars.nextButton.add(vars.innerNextButton).addClass('disabled');
7216			}
7217
7218			if (opts.show.effect) {
7219				vars.overlay.stop().fadeIn(opts.show.speed);
7220				vars.toolbar.stop().fadeIn(opts.show.speed);
7221			} else {
7222				vars.overlay.show();
7223				vars.toolbar.show();
7224			}
7225
7226			var length = recognizingItems.length;
7227			if (needRecognition) {
7228				iL.showLoader();
7229
7230				$.each(recognizingItems, function(key, val) {
7231					var resultFnc = function(result) {
7232							var key = -1,
7233								filter = iL.items.filter(function(e, i, arr) {
7234									if (e.URL == result.url)
7235										key = i;
7236
7237									return e.URL == result.url;
7238								}),
7239								self = iL.items[key];
7240
7241							if (result)
7242								$.extend(true, self, {
7243									URL: result.source,
7244									type: result.type,
7245									recognized: true,
7246									options: {
7247										html5video: result.html5video,
7248										width: (result.type == "image") ? 0 : (result.width || self.width),
7249										height: (result.type == "image") ? 0 : (result.height || self.height),
7250										thumbnail: self.options.thumbnail || result.thumbnail
7251									}
7252								});
7253
7254							length--;
7255
7256							if (length == 0) {
7257								iL.hideLoader();
7258
7259								vars.dontGenerateThumbs = false;
7260								iL.generateThumbnails();
7261
7262								if (opts.show.effect)
7263									setTimeout(function() {
7264										iL.generateBoxes();
7265									}, opts.show.speed);
7266								else
7267									iL.generateBoxes();
7268							}
7269						};
7270
7271					iL.ogpRecognition(this, resultFnc);
7272				});
7273			}
7274			else {
7275				if (opts.show.effect)
7276					setTimeout(function() {
7277						iL.generateBoxes();
7278					}, opts.show.speed);
7279				else
7280					iL.generateBoxes();
7281			}
7282
7283			iL.createUI();
7284
7285			window.iLightBox = {
7286				close: function() {
7287					iL.closeAction();
7288				},
7289				fullscreen: function() {
7290					iL.fullScreenAction();
7291				},
7292				moveNext: function() {
7293					iL.moveTo('next');
7294				},
7295				movePrev: function() {
7296					iL.moveTo('prev');
7297				},
7298				goTo: function(index) {
7299					iL.goTo(index);
7300				},
7301				refresh: function() {
7302					iL.refresh();
7303				},
7304				reposition: function() {
7305					(arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto();
7306				},
7307				setOption: function(options) {
7308					iL.setOption(options);
7309				},
7310				destroy: function() {
7311					iL.closeAction();
7312					iL.dispatchItemsEvents();
7313				}
7314			};
7315
7316			if (opts.linkId) {
7317				vars.hashLock = true;
7318				window.location.hash = opts.linkId + '/' + vars.current;
7319				setTimeout(function() {
7320					vars.hashLock = false;
7321				}, 55);
7322			}
7323
7324			if (!opts.slideshow.startPaused) {
7325				iL.resume();
7326				vars.innerPlayButton.removeClass('ilightbox-play').addClass('ilightbox-pause');
7327			}
7328
7329			//Trigger the onOpen callback
7330			if (typeof iL.options.callback.onOpen == 'function') iL.options.callback.onOpen.call(iL);
7331
7332		},
7333
7334		loadContent: function(obj, opt, speed) {
7335			var iL = this,
7336				holder, item;
7337
7338			iL.createUI();
7339
7340			obj.speed = speed || iL.options.effects.loadedFadeSpeed;
7341
7342			if (opt == 'current') {
7343				if (!obj.options.mousewheel) iL.vars.lockWheel = true;
7344				else iL.vars.lockWheel = false;
7345
7346				if (!obj.options.swipe) iL.vars.lockSwipe = true;
7347				else iL.vars.lockSwipe = false;
7348			}
7349
7350			switch (opt) {
7351				case 'current':
7352					holder = iL.vars.holder, item = iL.vars.current;
7353					break;
7354				case 'next':
7355					holder = iL.vars.nextPhoto, item = iL.vars.next;
7356					break;
7357				case 'prev':
7358					holder = iL.vars.prevPhoto, item = iL.vars.prev;
7359					break;
7360			}
7361
7362			holder.removeAttr('style class').addClass('ilightbox-holder' + (supportTouch ? ' supportTouch' : '')).addClass(obj.options.skin);
7363			$('div.ilightbox-inner-toolbar', holder).remove();
7364
7365			if (obj.title || iL.options.innerToolbar) {
7366				var innerToolbar = iL.vars.innerToolbar.clone();
7367				if (obj.title && iL.options.show.title) {
7368					var title = iL.vars.title.clone();
7369					title.empty().html(obj.title);
7370					innerToolbar.append(title);
7371				}
7372				if (iL.options.innerToolbar) {
7373					innerToolbar.append((iL.vars.total > 1) ? iL.vars.toolbar.clone() : iL.vars.toolbar);
7374				}
7375				holder.prepend(innerToolbar);
7376			}
7377
7378			iL.loadSwitcher(obj, holder, item, opt);
7379		},
7380
7381		loadSwitcher: function(obj, holder, item, opt) {
7382			var iL = this,
7383				opts = iL.options,
7384				api = {
7385					element: holder,
7386					position: item
7387				};
7388
7389			switch (obj.type) {
7390				case 'image':
7391					//Trigger the onBeforeLoad callback
7392					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
7393					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
7394
7395					iL.loadImage(obj.URL, function(img) {
7396						//Trigger the onAfterLoad callback
7397						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
7398						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
7399
7400						var width = (img) ? img.width : 400,
7401							height = (img) ? img.height : 200;
7402
7403						holder.data({
7404							naturalWidth: width,
7405							naturalHeight: height
7406						});
7407						$('div.ilightbox-container', holder).empty().append((img) ? '<img src="' + obj.URL + '" class="ilightbox-image" />' : '<span class="ilightbox-alert">' + opts.errors.loadImage + '</span>');
7408
7409						//Trigger the onRender callback
7410						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
7411						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
7412
7413						iL.configureHolder(obj, opt, holder);
7414					});
7415
7416					break;
7417
7418				case 'video':
7419					holder.data({
7420						naturalWidth: obj.options.width,
7421						naturalHeight: obj.options.height
7422					});
7423
7424					iL.addContent(holder, obj);
7425
7426					//Trigger the onRender callback
7427					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
7428					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
7429
7430					iL.configureHolder(obj, opt, holder);
7431
7432					break;
7433
7434				case 'iframe':
7435					iL.showLoader();
7436					holder.data({
7437						naturalWidth: obj.options.width,
7438						naturalHeight: obj.options.height
7439					});
7440					var el = iL.addContent(holder, obj);
7441
7442					//Trigger the onRender callback
7443					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
7444					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
7445
7446					//Trigger the onBeforeLoad callback
7447					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
7448					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
7449
7450					el.bind('load', function() {
7451						//Trigger the onAfterLoad callback
7452						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
7453						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
7454
7455						iL.hideLoader();
7456						iL.configureHolder(obj, opt, holder);
7457						el.unbind('load');
7458					});
7459
7460					break;
7461
7462				case 'inline':
7463					var el = $(obj.URL),
7464						content = iL.addContent(holder, obj),
7465						images = findImageInElement(holder);
7466
7467					holder.data({
7468						naturalWidth: (iL.items[item].options.width || el.outerWidth()),
7469						naturalHeight: (iL.items[item].options.height || el.outerHeight())
7470					});
7471					content.children().eq(0).show();
7472
7473					//Trigger the onRender callback
7474					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
7475					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
7476
7477					//Trigger the onBeforeLoad callback
7478					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
7479					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
7480
7481					iL.loadImage(images, function() {
7482						//Trigger the onAfterLoad callback
7483						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
7484						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
7485
7486						iL.configureHolder(obj, opt, holder);
7487					});
7488
7489					break;
7490
7491				case 'flash':
7492					var el = iL.addContent(holder, obj);
7493
7494					holder.data({
7495						naturalWidth: (iL.items[item].options.width || el.outerWidth()),
7496						naturalHeight: (iL.items[item].options.height || el.outerHeight())
7497					});
7498
7499					//Trigger the onRender callback
7500					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
7501					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
7502
7503					iL.configureHolder(obj, opt, holder);
7504
7505					break;
7506
7507				case 'ajax':
7508					var ajax = obj.options.ajax || {};
7509					//Trigger the onBeforeLoad callback
7510					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
7511					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
7512
7513					iL.showLoader();
7514					$.ajax({
7515						url: obj.URL || opts.ajaxSetup.url,
7516						data: ajax.data || null,
7517						dataType: ajax.dataType || "html",
7518						type: ajax.type || opts.ajaxSetup.type,
7519						cache: ajax.cache || opts.ajaxSetup.cache,
7520						crossDomain: ajax.crossDomain || opts.ajaxSetup.crossDomain,
7521						global: ajax.global || opts.ajaxSetup.global,
7522						ifModified: ajax.ifModified || opts.ajaxSetup.ifModified,
7523						username: ajax.username || opts.ajaxSetup.username,
7524						password: ajax.password || opts.ajaxSetup.password,
7525						beforeSend: ajax.beforeSend || opts.ajaxSetup.beforeSend,
7526						complete: ajax.complete || opts.ajaxSetup.complete,
7527						success: function(data, textStatus, jqXHR) {
7528							iL.hideLoader();
7529
7530							var el = $(data),
7531								container = $('div.ilightbox-container', holder),
7532								elWidth = iL.items[item].options.width || parseInt(el[0].getAttribute('width')),
7533								elHeight = iL.items[item].options.height || parseInt(el[0].getAttribute('height')),
7534								css = (el[0].getAttribute('width') && el[0].getAttribute('height')) ? {
7535									'overflow': 'hidden'
7536								} : {};
7537
7538							container.empty().append($('<div class="ilightbox-wrapper"></div>').css(css).html(el));
7539							holder.show().data({
7540								naturalWidth: (elWidth || container.outerWidth()),
7541								naturalHeight: (elHeight || container.outerHeight())
7542							}).hide();
7543
7544							//Trigger the onRender callback
7545							if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
7546							if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
7547
7548							var images = findImageInElement(holder);
7549							iL.loadImage(images, function() {
7550								//Trigger the onAfterLoad callback
7551								if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
7552								if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
7553
7554								iL.configureHolder(obj, opt, holder);
7555							});
7556
7557							opts.ajaxSetup.success(data, textStatus, jqXHR);
7558							if (typeof ajax.success == 'function') ajax.success(data, textStatus, jqXHR);
7559						},
7560						error: function(jqXHR, textStatus, errorThrown) {
7561							//Trigger the onAfterLoad callback
7562							if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
7563							if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
7564
7565							iL.hideLoader();
7566							$('div.ilightbox-container', holder).empty().append('<span class="ilightbox-alert">' + opts.errors.loadContents + '</span>');
7567							iL.configureHolder(obj, opt, holder);
7568
7569							opts.ajaxSetup.error(jqXHR, textStatus, errorThrown);
7570							if (typeof ajax.error == 'function') ajax.error(jqXHR, textStatus, errorThrown);
7571						}
7572					});
7573
7574					break;
7575
7576				case 'html':
7577					var object = obj.URL,
7578						el
7579					container = $('div.ilightbox-container', holder);
7580
7581					if (object[0].nodeName) el = object.clone();
7582					else {
7583						var dom = $(object);
7584						if (dom.selector) el = $('<div>' + dom + '</div>');
7585						else el = dom;
7586					}
7587
7588					var elWidth = iL.items[item].options.width || parseInt(el.attr('width')),
7589						elHeight = iL.items[item].options.height || parseInt(el.attr('height'));
7590
7591					iL.addContent(holder, obj);
7592
7593					el.appendTo(document.documentElement).hide();
7594
7595					//Trigger the onRender callback
7596					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
7597					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
7598
7599					var images = findImageInElement(holder);
7600
7601					//Trigger the onBeforeLoad callback
7602					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
7603					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
7604
7605					iL.loadImage(images, function() {
7606						//Trigger the onAfterLoad callback
7607						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
7608						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
7609
7610						holder.show().data({
7611							naturalWidth: (elWidth || container.outerWidth()),
7612							naturalHeight: (elHeight || container.outerHeight())
7613						}).hide();
7614						el.remove();
7615
7616						iL.configureHolder(obj, opt, holder);
7617					});
7618
7619					break;
7620			}
7621		},
7622
7623		configureHolder: function(obj, opt, holder) {
7624			var iL = this,
7625				vars = iL.vars,
7626				opts = iL.options;
7627
7628			if (opt != "current")(opt == "next") ? holder.addClass('ilightbox-next') : holder.addClass('ilightbox-prev');
7629
7630			if (opt == "current")
7631				var item = vars.current;
7632			else if (opt == "next")
7633				var opacity = opts.styles.nextOpacity,
7634					item = vars.next;
7635			else
7636				var opacity = opts.styles.prevOpacity,
7637					item = vars.prev;
7638
7639			var api = {
7640				element: holder,
7641				position: item
7642			};
7643
7644			iL.items[item].options.width = iL.items[item].options.width || 0,
7645				iL.items[item].options.height = iL.items[item].options.height || 0;
7646
7647			if (opt == "current") {
7648				if (opts.show.effect) holder.css(transform, gpuAcceleration).fadeIn(obj.speed, function() {
7649					holder.css(transform, '');
7650					if (obj.caption) {
7651						iL.setCaption(obj, holder);
7652						var caption = $('div.ilightbox-caption', holder),
7653							percent = parseInt((caption.outerHeight() / holder.outerHeight()) * 100);
7654						if (opts.caption.start & percent <= 50) caption.fadeIn(opts.effects.fade
7654Speed);
7655					}
7656
7657					var social = obj.options.social;
7658					if (social) {
7659						iL.setSocial(social, obj.URL, holder);
7660						if (opts.social.start) $('div.ilightbox-social', holder).fadeIn(opts.effects.fadeSpeed);
7661					}
7662
7663					//Generate thumbnails
7664					iL.generateThumbnails();
7665
7666					//Trigger the onShow callback
7667					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
7668					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
7669				});
7670				else {
7671					holder.show();
7672
7673					//Generate thumbnails
7674					iL.generateThumbnails();
7675
7676					//Trigger the onShow callback
7677					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
7678					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
7679				}
7680			} else {
7681				if (opts.show.effect) holder.fadeTo(obj.speed, opacity, function() {
7682					if (opt == "next") vars.nextLock = false;
7683					else vars.prevLock = false;
7684
7685					//Generate thumbnails
7686					iL.generateThumbnails();
7687
7688					//Trigger the onShow callback
7689					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
7690					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
7691				});
7692				else {
7693					holder.css({
7694						opacity: opacity
7695					}).show();
7696					if (opt == "next") vars.nextLock = false;
7697					else vars.prevLock = false;
7698
7699					//Generate thumbnails
7700					iL.generateThumbnails();
7701
7702					//Trigger the onShow callback
7703					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
7704					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
7705				}
7706			}
7707
7708			setTimeout(function() {
7709				iL.repositionPhoto();
7710			}, 0);
7711		},
7712
7713		generateBoxes: function() {
7714			var iL = this,
7715				vars = iL.vars,
7716				opts = iL.options;
7717
7718			if (opts.infinite && vars.total >= 3) {
7719				if (vars.current == vars.total - 1) vars.next = 0;
7720				if (vars.current == 0) vars.prev = vars.total - 1;
7721			} else opts.infinite = false;
7722
7723			iL.loadContent(iL.items[vars.current], 'current', opts.show.speed);
7724
7725			if (iL.items[vars.next]) iL.loadContent(iL.items[vars.next], 'next', opts.show.speed);
7726			if (iL.items[vars.prev]) iL.loadContent(iL.items[vars.prev], 'prev', opts.show.speed);
7727		},
7728
7729		generateThumbnails: function() {
7730			var iL = this,
7731				vars = iL.vars,
7732				opts = iL.options,
7733				timeOut = null;
7734
7735			if (vars.thumbs && !iL.vars.dontGenerateThumbs) {
7736				var thumbnails = vars.thumbnails,
7737					container = $('div.ilightbox-thumbnails-container', thumbnails),
7738					grid = $('div.ilightbox-thumbnails-grid', container),
7739					i = 0;
7740
7741				grid.removeAttr('style').empty();
7742
7743				$.each(iL.items, function(key, val) {
7744					var isActive = (vars.current == key) ? 'ilightbox-active' : '',
7745						opacity = (vars.current == key) ? opts.thumbnails.activeOpacity : opts.thumbnails.normalOpacity,
7746						thumb = val.options.thumbnail,
7747						thumbnail = $('<div class="ilightbox-thumbnail"></div>'),
7748						icon = $('<div class="ilightbox-thumbnail-icon"></div>');
7749
7750					thumbnail.css({
7751						opacity: 0
7752					}).addClass(isActive);
7753
7754					if ((val.type == "video" || val.type == "flash") && typeof val.options.icon == 'undefined') {
7755						icon.addClass('ilightbox-thumbnail-video');
7756						thumbnail.append(icon);
7757					} else if (val.options.icon) {
7758						icon.addClass('ilightbox-thumbnail-' + val.options.icon);
7759						thumbnail.append(icon);
7760					}
7761
7762					if (thumb) iL.loadImage(thumb, function(img) {
7763						i++;
7764						if (img) thumbnail.data({
7765							naturalWidth: img.width,
7766							naturalHeight: img.height
7767						}).append('<img src="' + thumb + '" border="0" />');
7768						else thumbnail.data({
7769							naturalWidth: opts.thumbnails.maxWidth,
7770							naturalHeight: opts.thumbnails.maxHeight
7771						});
7772
7773						clearTimeout(timeOut);
7774						timeOut = setTimeout(function() {
7775							iL.positionThumbnails(thumbnails, container, grid);
7776						}, 20);
7777						setTimeout(function() {
7778							thumbnail.fadeTo(opts.effects.loadedFadeSpeed, opacity);
7779						}, i * 20);
7780					});
7781
7782					grid.append(thumbnail);
7783				});
7784				iL.vars.dontGenerateThumbs = true;
7785			}
7786		},
7787
7788		positionThumbnails: function(thumbnails, container, grid) {
7789			var iL = this,
7790				vars = iL.vars,
7791				opts = iL.options,
7792				viewport = getViewport(),
7793				path = opts.path.toLowerCase();
7794
7795			if (!thumbnails) thumbnails = vars.thumbnails;
7796			if (!container) container = $('div.ilightbox-thumbnails-container', thumbnails);
7797			if (!grid) grid = $('div.ilightbox-thumbnails-grid', container);
7798
7799			var thumbs = $('.ilightbox-thumbnail', grid),
7800				widthAvail = (path == 'horizontal') ? viewport.width - opts.styles.pageOffsetX : thumbs.eq(0).outerWidth() - opts.styles.pageOffsetX,
7801				heightAvail = (path == 'horizontal') ? thumbs.eq(0).outerHeight() - opts.styles.pageOffsetY : viewport.height - opts.styles.pageOffsetY,
7802				gridWidth = (path == 'horizontal') ? 0 : widthAvail,
7803				gridHeight = (path == 'horizontal') ? heightAvail : 0,
7804				active = $('.ilightbox-active', grid),
7805				gridCss = {},
7806				css = {};
7807
7808			if (arguments.length < 3) {
7809				thumbs.css({
7810					opacity: opts.thumbnails.normalOpacity
7811				});
7812				active.css({
7813					opacity: opts.thumbnails.activeOpacity
7814				});
7815			}
7816
7817			thumbs.each(function(i) {
7818				var t = $(this),
7819					data = t.data(),
7820					width = (path == 'horizontal') ? 0 : opts.thumbnails.maxWidth;
7821				height = (path == 'horizontal') ? opts.thumbnails.maxHeight : 0;
7822				dims = iL.getNewDimenstions(width, height, data.naturalWidth, data.naturalHeight, true);
7823
7824				t.css({
7825					width: dims.width,
7826					height: dims.height
7827				});
7828				if (path == 'horizontal') t.css({
7829					'float': 'left'
7830				});
7831
7832				(path == 'horizontal') ? (
7833					gridWidth += t.outerWidth()
7834				) : (
7835					gridHeight += t.outerHeight()
7836				);
7837			});
7838
7839			gridCss = {
7840				width: gridWidth,
7841				height: gridHeight
7842			};
7843
7844			grid.css(gridCss);
7845
7846			gridCss = {};
7847
7848			var gridOffset = grid.offset(),
7849				activeOffset = (active.length) ? active.offset() : {
7850					top: parseInt(heightAvail / 2),
7851					left: parseInt(widthAvail / 2)
7852				};
7853
7854			gridOffset.top = (gridOffset.top - $doc.scrollTop()),
7855				gridOffset.left = (gridOffset.left - $doc.scrollLeft()),
7856				activeOffset.top = (activeOffset.top - gridOffset.top - $doc.scrollTop()),
7857				activeOffset.left = (activeOffset.left - gridOffset.left - $doc.scrollLeft());
7858
7859			(path == 'horizontal') ? (
7860				gridCss.top = 0,
7861				gridCss.left = parseInt((widthAvail / 2) - activeOffset.left - (active.outerWidth() / 2))
7862			) : (
7863				gridCss.top = parseInt(((heightAvail / 2) - activeOffset.top - (active.outerHeight() / 2))),
7864				gridCss.left = 0
7865			);
7866
7867			if (arguments.length < 3) grid.stop().animate(gridCss, opts.effects.repositionSpeed, 'easeOutCirc');
7868			else grid.css(gridCss);
7869		},
7870
7871		loadImage: function(image, callback) {
7872			if (!$.isArray(image)) image = [image];
7873
7874			var iL = this,
7875				length = image.length;
7876
7877			if (length > 0) {
7878				iL.showLoader();
7879				$.each(image, function(index, value) {
7880					var img = new Image();
7881					img.onload = function() {
7882						length -= 1;
7883						if (length == 0) {
7884							iL.hideLoader();
7885							callback(img);
7886						}
7887					};
7888					img.onerror = img.onabort = function() {
7889						length -= 1;
7890						if (length == 0) {
7891							iL.hideLoader();
7892							callback(false);
7893						}
7894					};
7895					img.src = image[index];
7896				});
7897			} else callback(false);
7898		},
7899
7900		patchItemsEvents: function() {
7901			var iL = this,
7902				vars = iL.vars,
7903				clickEvent = supportTouch ? "itap.iL" : "click.iL",
7904				vEvent = supportTouch ? "click.iL" : "itap.iL";
7905
7906			if (iL.context && iL.selector) {
7907				var $items = $(iL.selector, iL.context);
7908
7909				$(iL.context).on(clickEvent, iL.selector, function() {
7910
7911					var $this = $(this),
7912						key = $items.index($this);
7913					if (UNCODE.isMobile) {
7914						var isCarousel = $this.closest('.owl-carousel');
7915						if (isCarousel.length) {
7916							if (isCarousel.hasClass('owl-translating')) return false;
7917						}
7918					}
7919
7920					vars.current = key;
7921					vars.next = iL.items[key + 1] ? key + 1 : null;
7922					vars.prev = iL.items[key - 1] ? key - 1 : null;
7923
7924					iL.addContents();
7925					iL.patchEvents();
7926
7927					return false;
7928				}).on(vEvent, iL.selector, function() {
7929					return false;
7930				});
7931			} else
7932				$.each(iL.itemsObject, function(key, val) {
7933					val.on(clickEvent, function() {
7934						vars.current = key;
7935						vars.next = iL.items[key + 1] ? key + 1 : null;
7936						vars.prev = iL.items[key - 1] ? key - 1 : null;
7937
7938						iL.addContents();
7939						iL.patchEvents();
7940
7941						return false;
7942					}).on(vEvent, function() {
7943						return false;
7944					});
7945				});
7946		},
7947
7948		dispatchItemsEvents: function() {
7949			var iL = this,
7950				vars = iL.vars,
7951				opts = iL.options;
7952
7953			if (iL.context && iL.selector)
7954				$(iL.context).off('.iL', iL.selector);
7955			else
7956				$.each(iL.itemsObject, function(key, val) {
7957					val.off('.iL');
7958				});
7959		},
7960
7961		refresh: function() {
7962			var iL = this;
7963
7964			iL.dispatchItemsEvents();
7965			iL.attachItems();
7966			iL.normalizeItems();
7967			iL.patchItemsEvents();
7968		},
7969
7970		patchEvents: function() {
7971			var iL = this,
7972				vars = iL.vars,
7973				opts = iL.options,
7974				path = opts.path.toLowerCase(),
7975				holders = $('.ilightbox-holder'),
7976				fullscreenEvent = fullScreenApi.fullScreenEventName + '.iLightBox',
7977				durationThreshold = 1000,
7978				horizontalDistanceThreshold =
7979				verticalDistanceThreshold = 100,
7980				buttonsArray = [vars.nextButton[0], vars.prevButton[0], vars.nextButton[0].firstChild, vars.prevButton[0].firstChild];
7981
7982			$win.bind('resize.iLightBox', function() {
7983				var viewport = getViewport();
7984
7985				if (opts.mobileOptimizer && !opts.innerToolbar) vars.isMobile = viewport.width <= vars.mobileMaxWidth;
7986				vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile');
7987
7988				iL.repositionPhoto(null);
7989				if (supportTouch) {
7990					clearTimeout(vars.setTime);
7991					vars.setTime = setTimeout(function() {
7992						var scrollTop = getScrollXY().y;
7993						window.scrollTo(0, scrollTop - 30);
7994						window.scrollTo(0, scrollTop + 30);
7995						window.scrollTo(0, scrollTop);
7996					}, 2000);
7997				}
7998				if (vars.thumbs) iL.positionThumbnails();
7999			}).bind('keydown.iLightBox', function(event) {
8000				if (opts.controls.keyboard) {
8001					switch (event.keyCode) {
8002						case 13:
8003							if (event.shiftKey && opts.keyboard.shift_enter) iL.fullScreenAction();
8004							break;
8005						case 27:
8006							if (opts.keyboard.esc) iL.closeAction();
8007							break;
8008						case 37:
8009							if (opts.keyboard.left && !vars.lockKey) iL.moveTo('prev');
8010							break;
8011						case 38:
8012							if (opts.keyboard.up && !vars.lockKey) iL.moveTo('prev');
8013							break;
8014						case 39:
8015							if (opts.keyboard.right && !vars.lockKey) iL.moveTo('next');
8016							break;
8017						case 40:
8018							if (opts.keyboard.down && !vars.lockKey) iL.moveTo('next');
8019							break;
8020					}
8021				}
8022			});
8023
8024			if (fullScreenApi.supportsFullScreen) $win.bind(fullscreenEvent, function() {
8025				iL.doFullscreen();
8026			});
8027
8028			var holderEventsArr = [opts.caption.show + '.iLightBox', opts.caption.hide + '.iLightBox', opts.social.show + '.iLightBox', opts.social.hide + '.iLightBox'].filter(function(e, i, arr) {
8029					return arr.lastIndexOf(e) === i;
8030				}),
8031				holderEvents = "";
8032
8033			$.each(holderEventsArr, function(key, val) {
8034				if (key != 0) holderEvents += ' ';
8035				holderEvents += val;
8036			});
8037
8038			$doc.on(clickEvent, '.ilightbox-overlay', function() {
8039				if (opts.overlay.blur) iL.closeAction();
8040			}).on(clickEvent, '.ilightbox-next, .ilightbox-next-button', function() {
8041				iL.moveTo('next');
8042			}).on(clickEvent, '.ilightbox-prev, .ilightbox-prev-button', function() {
8043				iL.moveTo('prev');
8044			}).on(clickEvent, '.ilightbox-thumbnail', function() {
8045				var t = $(this),
8046					thumbs = $('.ilightbox-thumbnail', vars.thumbnails),
8047					index = thumbs.index(t);
8048
8049				if (index != vars.current) iL.goTo(index);
8050			}).on(holderEvents, '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) {
8051				var caption = $('div.ilightbox-caption', vars.holder),
8052					social = $('div.ilightbox-social', vars.holder),
8053					fadeSpeed = opts.effects.fadeSpeed;
8054
8055				if (vars.nextLock || vars.prevLock) {
8056					if (e.type == opts.caption.show && !caption.is(':visible')) caption.fadeIn(fadeSpeed);
8057					else if (e.type == opts.caption.hide && caption.is(':visible')) caption.fadeOut(fadeSpeed);
8058
8059					if (e.type == opts.social.show && !social.is(':visible')) social.fadeIn(fadeSpeed);
8060					else if (e.type == opts.social.hide && social.is(':visible')) social.fadeOut(fadeSpeed);
8061				} else {
8062					if (e.type == opts.caption.show && !caption.is(':visible')) caption.stop().fadeIn(fadeSpeed);
8063					else if (e.type == opts.caption.hide && caption.is(':visible')) caption.stop().fadeOut(fadeSpeed);
8064
8065					if (e.type == opts.social.show && !social.is(':visible')) social.stop().fadeIn(fadeSpeed);
8066					else if (e.type == opts.social.hide && social.is(':visible')) social.stop().fadeOut(fadeSpeed);
8067				}
8068			}).on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-wrapper', function(e) {
8069				if (e.type == 'mouseenter') vars.lockWheel = true;
8070				else vars.lockWheel = false;
8071			}).on(clickEvent, '.ilightbox-toolbar a.ilightbox-close, .ilightbox-toolbar a.ilightbox-fullscreen, .ilightbox-toolbar a.ilightbox-play, .ilightbox-toolbar a.ilightbox-pause', function() {
8072				var t = $(this);
8073
8074				if (t.hasClass('ilightbox-fullscreen')) iL.fullScreenAction();
8075				else if (t.hasClass('ilightbox-play')) {
8076					iL.resume();
8077					t.addClass('ilightbox-pause').removeClass('ilightbox-play');
8078				} else if (t.hasClass('ilightbox-pause')) {
8079					iL.pause();
8080					t.addClass('ilightbox-play').removeClass('ilightbox-pause');
8081				} else iL.closeAction();
8082			}).on(touchMoveEvent, '.ilightbox-overlay, .ilightbox-thumbnails-container', function(e) {
8083				// prevent scrolling
8084				e.preventDefault();
8085			});
8086
8087			function mouseMoveHandler(e) {
8088				if (!vars.isMobile) {
8089					if (!vars.mouseID) {
8090						vars.hideableElements.show();
8091					}
8092
8093					vars.mouseID = clearTimeout(vars.mouseID);
8094
8095					if (buttonsArray.indexOf(e.target) === -1)
8096						vars.mouseID = setTimeout(function() {
8097							vars.hideableElements.hide();
8098							vars.mouseID = clearTimeout(vars.mouseID);
8099						}, 3000);
8100				}
8101			}
8102
8103			if (opts.controls.arrows && !supportTouch) $doc.on('mousemove.iLightBox', mouseMoveHandler);
8104
8105			if (opts.controls.slideshow && opts.slideshow.pauseOnHover) $doc.on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) {
8106				if (e.type == 'mouseenter' && vars.cycleID) iL.pause();
8107				else if (e.type == 'mouseleave' && vars.isPaused) iL.resume();
8108			});
8109
8110			var switchers = $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails');
8111
8112			if (opts.controls.mousewheel) switchers.on('mousewheel.iLightBox', function(event, delta) {
8113				if (!vars.lockWheel) {
8114					event.preventDefault();
8115					if (delta < 0) iL.moveTo('next');
8116					else if (delta > 0) iL.moveTo('prev');
8117				}
8118			});
8119
8120			if (opts.controls.swipe) holders.on(touchStartEvent, function(event) {
8121				if (vars.nextLock || vars.prevLock || vars.total == 1 || vars.lockSwipe) return;
8122
8123				vars.BODY.addClass('ilightbox-closedhand');
8124
8125				var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event,
8126					scrollTop = $doc.scrollTop(),
8127					scrollLeft = $doc.scrollLeft(),
8128					offsets = [
8129						holders.eq(0).offset(),
8130						holders.eq(1).offset(),
8131						holders.eq(2).offset()
8132					],
8133					offSet = [{
8134						top: offsets[0].top - scrollTop,
8135						left: offsets[0].left - scrollLeft
8136					}, {
8137						top: offsets[1].top - scrollTop,
8138						left: offsets[1].left - scrollLeft
8139					}, {
8140						top: offsets[2].top - scrollTop,
8141						left: offsets[2].left - scrollLeft
8142					}],
8143					start = {
8144						time: (new Date()).getTime(),
8145						coords: [data.pageX - scrollLeft, data.pageY - scrollTop]
8146					},
8147					stop;
8148
8149				function moveEachHandler(i) {
8150					var t = $(this),
8151						offset = offSet[i],
8152						scroll = [(start.coords[0] - stop.coords[0]), (start.coords[1] - stop.coords[1])];
8153
8154					t[0].style[path == "horizontal" ? 'left' : 'top'] = (path == "horizontal" ? offset.left - scroll[0] : offset.top - scroll[1]) + 'px';
8155				}
8156
8157				function moveHandler(event) {
8158
8159					if (!start) return;
8160
8161					var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event;
8162
8163					stop = {
8164						time: (new Date()).getTime(),
8165						coords: [data.pageX - scrollLeft, data.pageY - scrollTop]
8166					};
8167
8168					holders.each(moveEachHandler);
8169
8170					// prevent scrolling
8171					event.preventDefault();
8172				}
8173
8174				function repositionHolders() {
8175					holders.each(function() {
8176						var t = $(this),
8177							offset = t.data('offset') || {
8178								top: t.offset().top - scrollTop,
8179								left: t.offset().left - scrollLeft
8180							},
8181							top = offset.top,
8182							left = offset.left;
8183
8184						t.css(transform, gpuAcceleration).stop().animate({
8185							top: top,
8186							left: left
8187						}, 500, 'easeOutCirc', function() {
8188							t.css(transform, '');
8189						});
8190					});
8191				}
8192
8193				holders.bind(touchMoveEvent, moveHandler);
8194				$doc.one(touchStopEvent, function(event) {
8195					holders.unbind(touchMoveEvent, moveHandler);
8196
8197					vars.BODY.removeClass('ilightbox-closedhand');
8198
8199					if (start && stop) {
8200						if (path == "horizontal" && stop.time - start.time < durationThreshold && abs(start.coords[0] - stop.coords[0]) > horizontalDistanceThreshold && abs(start.coords[1] - stop.coords[1]) < verticalDistanceThreshold) {
8201							if (start.coords[0] > stop.coords[0]) {
8202								if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders();
8203								else {
8204									vars.isSwipe = true;
8205									iL.moveTo('next');
8206								}
8207							} else {
8208								if (vars.current == 0 && !opts.infinite) repositionHolders();
8209								else {
8210									vars.isSwipe = true;
8211									iL.moveTo('prev');
8212								}
8213							}
8214						} else if (path == "vertical" && stop.time - start.time < durationThreshold && abs(start.coords[1] - stop.coords[1]) > horizontalDistanceThreshold && abs(start.coords[0] - stop.coords[0]) < verticalDistanceThreshold) {
8215							if (start.coords[1] > stop.coords[1]) {
8216								if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders();
8217								else {
8218									vars.isSwipe = true;
8219									iL.moveTo('next');
8220								}
8221							} else {
8222								if (vars.current == 0 && !opts.infinite) repositionHolders();
8223								else {
8224									vars.isSwipe = true;
8225									iL.moveTo('prev');
8226								}
8227							}
8228						} else repositionHolders();
8229					}
8230					start = stop = undefined;
8231				});
8232			});
8233
8234		},
8235
8236		goTo: function(index) {
8237			var iL = this,
8238				vars = iL.vars,
8239				opts = iL.options,
8240				diff = (index - vars.current);
8241
8242			if (opts.infinite) {
8243				if (index == vars.total - 1 && vars.current == 0) diff = -1;
8244				if (vars.current == vars.total - 1 && index == 0) diff = 1;
8245			}
8246
8247			if (diff == 1) iL.moveTo('next');
8248			else if (diff == -1) iL.moveTo('prev');
8249			else {
8250
8251				if (vars.nextLock || vars.prevLock) return false;
8252
8253				//Trigger the onBeforeChange callback
8254				if (typeof opts.callback.onBeforeChange == 'function') opts.callback.onBeforeChange.call(iL, iL.ui);
8255
8256				if (opts.linkId) {
8257					vars.hashLock = true;
8258					window.location.hash = opts.linkId + '/' + index;
8259				}
8260
8261				if (iL.items[index]) {
8262					if (!iL.items[index].options.mousewheel) vars.lockWheel = true;
8263					else iL.vars.lockWheel = false;
8264
8265					if (!iL.items[index].options.swipe) vars.lockSwipe = true;
8266					else vars.lockSwipe = false;
8267				}
8268
8269				$.each([vars.holder, vars.nextPhoto, vars.prevPhoto], function(key, val) {
8270					val.css(transform, gpuAcceleration).fadeOut(opts.effects.loadedFadeSpeed);
8271				});
8272
8273				vars.current = index;
8274				vars.next = index + 1;
8275				vars.prev = index - 1;
8276
8277				iL.createUI();
8278
8279				setTimeout(function() {
8280					iL.generateBoxes();
8281				}, opts.effects.loadedFadeSpeed + 50);
8282
8283				$('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(index).addClass('ilightbox-active');
8284				iL.positionThumbnails();
8285
8286				if (opts.linkId) setTimeout(function() {
8287					vars.hashLock = false;
8288				}, 55);
8289
8290				// Configure arrow buttons
8291				if (!opts.infinite) {
8292					vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
8293
8294					if (vars.current == 0) {
8295						vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
8296					}
8297					if (vars.current >= vars.total - 1) {
8298						vars.nextButton.add(vars.innerNextButton).addClass('disabled');
8299					}
8300				}
8301
8302				// Reset next cycle timeout
8303				iL.resetCycle();
8304
8305				//Trigger the onAfterChange callback
8306				if (typeof opts.callback.onAfterChange == 'function') opts.callback.onAfterChange.call(iL, iL.ui);
8307			}
8308		},
8309
8310		moveTo: function(side) {
8311			var iL = this,
8312				vars = iL.vars,
8313				opts = iL.options,
8314				path = opts.path.toLowerCase(),
8315				viewport = getViewport(),
8316				switchSpeed = opts.effects.switchSpeed;
8317
8318			if (vars.nextLock || vars.prevLock) return false;
8319			else {
8320
8321				var item = (side == "next") ? vars.next : vars.prev;
8322
8323				if (opts.linkId) {
8324					vars.hashLock = true;
8325					window.location.hash = opts.linkId + '/' + item;
8326				}
8327
8328				if (side == "next") {
8329					if (!iL.items[item]) return false;
8330					var firstHolder = vars.nextPhoto,
8331						secondHolder = vars.holder,
8332						lastHolder = vars.prevPhoto,
8333						firstClass = 'ilightbox-prev',
8334						secondClass = 'ilightbox-next';
8335				} else if (side == "prev") {
8336					if (!iL.items[item]) return false;
8337					var firstHolder = vars.prevPhoto,
8338						secondHolder = vars.holder,
8339						lastHolder = vars.nextPhoto,
8340						firstClass = 'ilightbox-next',
8341						secondClass = 'ilightbox-prev';
8342				}
8343
8344				//Trigger the onBeforeChange callback
8345				if (typeof opts.callback.onBeforeChange == 'function')
8346					opts.callback.onBeforeChange.call(iL, iL.ui);
8347
8348				(side == "next") ? vars.nextLock = true: vars.prevLock = true;
8349
8350				var captionFirst = $('div.ilightbox-caption', secondHolder),
8351					socialFirst = $('div.ilightbox-social', secondHolder);
8352
8353				if (captionFirst.length)
8354					captionFirst.stop().fadeOut(switchSpeed, function() {
8355						$(this).remove();
8356					});
8357				if (socialFirst.length)
8358					socialFirst.stop().fadeOut(switchSpeed, function() {
8359						$(this).remove();
8360					});
8361
8362				if (iL.items[item].caption) {
8363					iL.setCaption(iL.items[item], firstHolder);
8364					var caption = $('div.ilightbox-caption', firstHolder),
8365						percent = parseInt((caption.outerHeight() / firstHolder.outerHeight()) * 100);
8366					if (opts.caption.start && percent <= 50) caption.fadeIn(switchSpeed);
8367				}
8368
8369				var social = iL.items[item].options.social;
8370				if (social) {
8371					iL.setSocial(social, iL.items[item].URL, firstHolder);
8372					if (opts.social.start) $('div.ilightbox-social', firstHolder).fadeIn(opts.effects.fadeSpeed);
8373				}
8374
8375				$.each([firstHolder, secondHolder, lastHolder], function(key, val) {
8376					val.removeClass('ilightbox-next ilightbox-prev');
8377				});
8378
8379				var firstOffset = firstHolder.data('offset'),
8380					winW = (viewport.width - (opts.styles.pageOffsetX)),
8381					winH = (viewport.height - (opts.styles.pageOffsetY)),
8382					width = firstOffset.newDims.width,
8383					height = firstOffset.newDims.height,
8384					thumbsOffset = firstOffset.thumbsOffset,
8385					diff = firstOffset.diff,
8386					top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)),
8387					left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2));
8388
8389				firstHolder.css(transform, gpuAcceleration).animate({
8390					top: top,
8391					left: left,
8392					opacity: 1
8393				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
8394					firstHolder.css(transform, '');
8395				});
8396
8397				$('div.ilightbox-container', firstHolder).animate({
8398					width: width,
8399					height: height
8400				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc');
8401
8402				var secondOffset = secondHolder.data('offset'),
8403					object = secondOffset.object;
8404
8405				diff = secondOffset.diff;
8406
8407				width = secondOffset.newDims.width,
8408					height = secondOffset.newDims.height;
8409
8410				width = parseInt(width * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']),
8411					height = parseInt(height * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']),
8412					top = (path == 'horizontal') ? parseInt((winH / 2) - object.offsetY - (height / 2) - diff.H - (thumbsOffset.H / 2)) : parseInt(winH - object.offsetX - diff.H - (thumbsOffset.H / 2));
8413
8414				if (side == 'prev')
8415					left = (path == 'horizontal') ? parseInt(winW - object.offsetX - diff.W - (thumbsOffset.W / 2)) : parseInt((winW / 2) - (width / 2) - diff.W - object.offsetY - (thumbsOffset.W / 2));
8416				else {
8417					top = (path == 'horizontal') ? top : parseInt(object.offsetX - diff.H - height - (thumbsOffset.H / 2)),
8418						left = (path == 'horizontal') ? parseInt(object.offsetX - diff.W - width - (thumbsOffset.W / 2)) : parseInt((winW / 2) - object.offsetY - (width / 2) - diff.W - (thumbsOffset.W / 2));
8419				}
8420
8421				$('div.ilightbox-container', secondHolder).animate({
8422					width: width,
8423					height: height
8424				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc');
8425
8426				secondHolder.addClass(firstClass).css(transform, gpuAcceleration).animate({
8427					top: top,
8428					left: left,
8429					opacity: opts.styles.prevOpacity
8430				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
8431					secondHolder.css(transform, '');
8432
8433					$('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(item).addClass('ilightbox-active');
8434					iL.positionThumbnails();
8435
8436					if (iL.items[item]) {
8437						if (!iL.items[item].options.mousewheel) vars.lockWheel = true;
8438						else vars.lockWheel = false;
8439
8440						if (!iL.items[item].options.swipe) vars.lockSwipe = true;
8441						else vars.lockSwipe = false;
8442					}
8443
8444					vars.isSwipe = false;
8445
8446					if (side == "next") {
8447						vars.nextPhoto = lastHolder,
8448							vars.prevPhoto = secondHolder,
8449							vars.holder = firstHolder;
8450
8451						vars.nextPhoto.hide();
8452
8453						vars.next = vars.next + 1,
8454							vars.prev = vars.current,
8455							vars.current = vars.current + 1;
8456
8457						if (opts.infinite) {
8458							if (vars.current > vars.total - 1) vars.current = 0;
8459							if (vars.current == vars.total - 1) vars.next = 0;
8460							if (vars.current == 0) vars.prev = vars.total - 1;
8461						}
8462
8463						iL.createUI();
8464
8465						if (!iL.items[vars.next])
8466							vars.nextLock = false;
8467						else
8468							iL.loadContent(iL.items[vars.next], 'next');
8469					} else {
8470						vars.prevPhoto = lastHolder;
8471						vars.nextPhoto = secondHolder;
8472						vars.holder = firstHolder;
8473
8474						vars.prevPhoto.hide();
8475
8476						vars.next = vars.current;
8477						vars.current = vars.prev;
8478						vars.prev = vars.current - 1;
8479
8480						if (opts.infinite) {
8481							if (vars.current == vars.total - 1) vars.next = 0;
8482							if (vars.current == 0) vars.prev = vars.total - 1;
8483						}
8484
8485						iL.createUI();
8486
8487						if (!iL.items[vars.prev])
8488							vars.prevLock = false;
8489						else
8490							iL.loadContent(iL.items[vars.prev], 'prev');
8491					}
8492
8493					if (opts.linkId) setTimeout(function() {
8494						vars.hashLock = false;
8495					}, 55);
8496
8497					// Configure arrow buttons
8498					if (!opts.infinite) {
8499						vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
8500
8501						if (vars.current == 0)
8502							vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
8503						if (vars.current >= vars.total - 1)
8504							vars.nextButton.add(vars.innerNextButton).addClass('disabled');
8505					}
8506
8507					iL.repositionPhoto();
8508
8509					// Reset next cycle timeout
8510					iL.resetCycle();
8511
8512					//Trigger the onAfterChange callback
8513					if (typeof opts.callback.onAfterChange == 'function')
8514						opts.callback.onAfterChange.call(iL, iL.ui);
8515				});
8516
8517				top = (path == 'horizontal') ? getPixel(lastHolder, 'top') : ((side == "next") ? parseInt(-(winH / 2) - lastHolder.outerHeight()) : parseInt(top * 2)),
8518					left = (path == 'horizontal') ? ((side == "next") ? parseInt(-(winW / 2) - lastHolder.outerWidth()) : parseInt(left * 2)) : getPixel(lastHolder, 'left');
8519
8520				lastHolder.css(transform, gpuAcceleration).animate({
8521					top: top,
8522					left: left,
8523					opacity: opts.styles.nextOpacity
8524				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
8525					lastHolder.css(transform, '');
8526				}).addClass(secondClass);
8527
8528			}
8529		},
8530
8531		setCaption: function(obj, target) {
8532			var iL = this,
8533				caption = $('<div class="ilightbox-caption"></div>');
8534
8535			if (obj.caption) {
8536				caption.html(obj.caption);
8537				$('div.ilightbox-container', target).append(caption);
8538			}
8539		},
8540
8541		normalizeSocial: function(obj, url) {
8542			var iL = this,
8543				vars = iL.vars,
8544				opts = iL.options,
8545				baseURL = window.location.href;
8546
8547			$.each(obj, function(key, value) {
8548				if (!value)
8549					return true;
8550
8551				var item = key.toLowerCase(),
8552					source, text;
8553
8554				switch (item) {
8555					case 'facebook':
8556						source = "http://www.facebook.com/share.php?v=4&src=bm&u={URL}",
8557							text = "Share on Facebook";
8558						break;
8559					case 'twitter':
8560						source = "http://twitter.com/home?status={URL}",
8561							text = "Share on Twitter";
8562						break;
8563					case 'googleplus':
8564						source = "https://plus.google.com/share?url={URL}",
8565							text = "Share on Google+";
8566						break;
8567					case 'delicious':
8568						source = "http://delicious.com/post?url={URL}",
8569							text = "Share on Delicious";
8570						break;
8571					case 'digg':
8572						source = "http://digg.com/submit?phase=2&url={URL}",
8573							text = "Share on Digg";
8574						break;
8575					case 'reddit':
8576						source = "http://reddit.com/submit?url={URL}",
8577							text = "Share on reddit";
8578						break;
8579				}
8580
8581				obj[key] = {
8582					URL: value.URL && absolutizeURI(baseURL, value.URL) || opts.linkId && window.location.href || typeof url !== 'string' && baseURL || url && absolutizeURI(baseURL, url) || baseURL,
8583					source: value.source || source || value.URL && absolutizeURI(baseURL, value.URL) || url && absolutizeURI(baseURL, url),
8584					text: value.text || text || "Share on " + key,
8585					width: (typeof(value.width) != 'undefined' && !isNaN(value.width)) ? parseInt(value.width) : 640,
8586					height: value.height || 360
8587				};
8588
8589			});
8590
8591			return obj;
8592		},
8593
8594		setSocial: function(obj, url, target) {
8595			var iL = this,
8596				socialBar = $('<div class="ilightbox-social"></div>'),
8597				buttons = '<ul>';
8598
8599			obj = iL.normalizeSocial(obj, url);
8600
8601			$.each(obj, function(key, value) {
8602				var item = key.toLowerCase(),
8603					source = value.source.replace(/\{URL\}/g, encodeURIComponent(value.URL).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A').replace(/%20/g, '+'));
8604				buttons += '<li class="' + key + '"><a href="' + source + '" onclick="javascript:window.open(this.href' + ((value.width <= 0 || value.height <= 0) ? '' : ', \'\', \'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=' + value.height + ',width=' + value.width + ',left=40,top=40\'') + ');return false;" title="' + value.text + '" target="_blank"></a></li>';
8605			});
8606
8607			buttons += '</ul>';
8608
8609			socialBar.html(buttons);
8610			$('div.ilightbox-container', target).append(socialBar);
8611		},
8612
8613		fullScreenAction: function() {
8614			var iL = this,
8615				vars = iL.vars;
8616
8617			if (fullScreenApi.supportsFullScreen) {
8618				if (fullScreenApi.isFullScreen()) fullScreenApi.cancelFullScreen(document.documentElement);
8619				else fullScreenApi.requestFullScreen(document.documentElement);
8620			} else {
8621				iL.doFullscreen();
8622			}
8623		},
8624
8625		doFullscreen: function() {
8626			var iL = this,
8627				vars = iL.vars,
8628				viewport = getViewport(),
8629				opts = iL.options;
8630
8631			if (opts.fullAlone) {
8632				var currentHolder = vars.holder,
8633					current = iL.items[vars.current],
8634					windowWidth = viewport.width,
8635					windowHeight = viewport.height,
8636					elements = [currentHolder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.overlay, vars.toolbar, vars.thumbnails, vars.loader],
8637					hideElements = [vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails];
8638
8639				if (!vars.isInFullScreen) {
8640					vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = true;
8641					vars.overlay.css({
8642						opacity: 1
8643					});
8644
8645					$.each(hideElements, function(i, element) {
8646						element.hide();
8647					});
8648
8649					vars.fullScreenButton.attr('title', opts.text.exitFullscreen);
8650
8651					if (opts.fullStretchTypes.indexOf(current.type) != -1) currentHolder.data({
8652						naturalWidthOld: currentHolder.data('naturalWidth'),
8653						naturalHeightOld: currentHolder.data('naturalHeight'),
8654						naturalWidth: windowWidth,
8655						naturalHeight: windowHeight
8656					});
8657					else {
8658						var viewport = current.options.fullViewPort || opts.fullViewPort || '',
8659							newWidth = windowWidth,
8660							newHeight = windowHeight,
8661							width = currentHolder.data('naturalWidth'),
8662							height = currentHolder.data('naturalHeight');
8663
8664						if (viewport.toLowerCase() == 'fill') {
8665							newHeight = (newWidth / width) * height;
8666
8667							if (newHeight < windowHeight) {
8668								newWidth = (windowHeight / height) * width,
8669									newHeight = windowHeight;
8670							}
8671						} else if (viewport.toLowerCase() == 'fit') {
8672							var dims = iL.getNewDimenstions(newWidth, newHeight, width, height, true);
8673
8674							newWidth = dims.width,
8675								newHeight = dims.height;
8676						} else if (viewport.toLowerCase() == 'stretch') {
8677							newWidth = newWidth,
8678								newHeight = newHeight;
8679						} else {
8680							var scale = (width > newWidth || height > newHeight) ? true : false,
8681								dims = iL.getNewDimenstions(newWidth, newHeight, width, height, scale);
8682							newWidth = dims.width,
8683								newHeight = dims.height;
8684						}
8685
8686						currentHolder.data({
8687							naturalWidthOld: currentHolder.data('naturalWidth'),
8688							naturalHeightOld: currentHolder.data('naturalHeight'),
8689							naturalWidth: newWidth,
8690							naturalHeight: newHeight
8691						});
8692					}
8693
8694					$.each(elements, function(key, val) {
8695						val.addClass('ilightbox-fullscreen');
8696					});
8697
8698					//Trigger the onEnterFullScreen callback
8699					if (typeof opts.callback.onEnterFullScreen == 'function') opts.callback.onEnterFullScreen.call(iL, iL.ui);
8700				} else {
8701					vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = false;
8702					vars.overlay.css({
8703						opacity: iL.options.overlay.opacity
8704					});
8705
8706					$.each(hideElements, function(i, element) {
8707						element.show();
8708					});
8709
8710					vars.fullScreenButton.attr('title', opts.text.enterFullscreen);
8711
8712					currentHolder.data({
8713						naturalWidth: currentHolder.data('naturalWidthOld'),
8714						naturalHeight: currentHolder.data('naturalHeightOld'),
8715						naturalWidthOld: null,
8716						naturalHeightOld: null
8717					});
8718
8719					$.each(elements, function(key, val) {
8720						val.removeClass('ilightbox-fullscreen');
8721					});
8722
8723					//Trigger the onExitFullScreen callback
8724					if (typeof opts.callback.onExitFullScreen == 'function') opts.callback.onExitFullScreen.call(iL, iL.ui);
8725				}
8726			} else {
8727				if (!vars.isInFullScreen) vars.isInFullScreen = true;
8728				else vars.isInFullScreen = false;
8729			}
8730			iL.repositionPhoto(true);
8731		},
8732
8733		closeAction: function() {
8734			var iL = this,
8735				vars = iL.vars,
8736				opts = iL.options;
8737
8738			$win.unbind('.iLightBox');
8739			$doc.off('.iLightBox');
8740
8741			if (vars.isInFullScreen) fullScreenApi.cancelFullScreen(document.documentElement);
8742
8743			$('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails').off('.iLightBox');
8744
8745			if (opts.hide.effect) vars.overlay.stop().fadeOut(opts.hide.speed, function() {
8746				vars.overlay.remove();
8747				vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox');
8748			});
8749			else {
8750				vars.overlay.remove();
8751				vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox');
8752			}
8753
8754			var fadeOuts = [vars.toolbar, vars.holder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails];
8755
8756			$.each(fadeOuts, function(i, element) {
8757				element.removeAttr('style').remove();
8758			});
8759
8760			vars.dontGenerateThumbs = vars.isInFullScreen = false;
8761
8762			window.iLightBox = null;
8763
8764			if (opts.linkId) {
8765				vars.hashLock = true;
8766				removeHash();
8767				setTimeout(function() {
8768					vars.hashLock = false;
8769				}, 55);
8770			}
8771
8772			//Trigger the onHide callback
8773			if (typeof opts.callback.onHide == 'function') opts.callback.onHide.call(iL, iL.ui);
8774		},
8775
8776		repositionPhoto: function() {
8777			var iL = this,
8778				vars = iL.vars,
8779				opts = iL.options,
8780				path = opts.path.toLowerCase(),
8781				viewport = getViewport(),
8782				winWidth = viewport.width,
8783				winHeight = viewport.height;
8784
8785			var thumbsOffsetW = (vars.isInFullScreen && opts.fullAlone || vars.isMobile) ? 0 : ((path == 'horizontal') ? 0 : vars.thumbnails.outerWidth()),
8786				thumbsOffsetH = vars.isMobile ? vars.toolbar.outerHeight() : ((vars.isInFullScreen && opts.fullAlone) ? 0 : ((path == 'horizontal') ? vars.thumbnails.outerHeight() : 0)),
8787				width = (vars.isInFullScreen && opts.fullAlone) ? winWidth : (winWidth - (opts.styles.pageOffsetX)),
8788				height = (vars.isInFullScreen && opts.fullAlone) ? winHeight : (winHeight - (opts.styles.pageOffsetY)),
8789				offsetW = (path == 'horizontal') ? parseInt((iL.items[vars.next] || iL.items[vars.prev]) ? ((opts.styles.nextOffsetX + opts.styles.prevOffsetX)) * 2 : (((width / 10) <= 30) ? 30 : (width / 10))) : parseInt(((width / 10) <= 30) ? 30 : (width / 10)) + thumbsOffsetW,
8790				offsetH = (path == 'horizontal') ? parseInt(((height / 10) <= 30) ? 30 : (height / 10)) + thumbsOffsetH : parseInt((iL.items[vars.next] || iL.items[vars.prev]) ? ((opts.styles.nextOffsetX + opts.styles.prevOffsetX)) * 2 : (((height / 10) <= 30) ? 30 : (height / 10)));
8791
8792			var elObject = {
8793				type: 'current',
8794				width: width,
8795				height: height,
8796				item: iL.items[vars.current],
8797				offsetW: offsetW,
8798				offsetH: offsetH,
8799				thumbsOffsetW: thumbsOffsetW,
8800				thumbsOffsetH: thumbsOffsetH,
8801				animate: arguments.length,
8802				holder: vars.holder
8803			};
8804
8805			iL.repositionEl(elObject);
8806
8807			if (iL.items[vars.next]) {
8808				elObject = $.extend(elObject, {
8809					type: 'next',
8810					item: iL.items[vars.next],
8811					offsetX: opts.styles.nextOffsetX,
8812					offsetY: opts.styles.nextOffsetY,
8813					holder: vars.nextPhoto
8814				});
8815
8816				iL.repositionEl(elObject);
8817			}
8818
8819			if (iL.items[vars.prev]) {
8820				elObject = $.extend(elObject, {
8821					type: 'prev',
8822					item: iL.items[vars.prev],
8823					offsetX: opts.styles.prevOffsetX,
8824					offsetY: opts.styles.prevOffsetY,
8825					holder: vars.prevPhoto
8826				});
8827
8828				iL.repositionEl(elObject);
8829			}
8830
8831			var loaderCss = (path == "horizontal") ? {
8832				left: parseInt((width / 2) - (vars.loader.outerWidth() / 2))
8833			} : {
8834				top: parseInt((height / 2) - (vars.loader.outerHeight() / 2))
8835			};
8836			vars.loader.css(loaderCss);
8837		},
8838
8839		repositionEl: function(obj) {
8840			var iL = this,
8841				vars = iL.vars,
8842				opts = iL.options,
8843				path = opts.path.toLowerCase(),
8844				widthAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.width : (obj.width - obj.offsetW)) : (obj.width - obj.offsetW),
8845				heightAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.height : (obj.height - obj.offsetH)) : (obj.height - obj.offsetH),
8846				itemParent = obj.item,
8847				item = obj.item.options,
8848				holder = obj.holder,
8849				offsetX = obj.offsetX || 0,
8850				offsetY = obj.offsetY || 0,
8851				thumbsOffsetW = obj.thumbsOffsetW,
8852				thumbsOffsetH = obj.thumbsOffsetH;
8853
8854			if (obj.type == 'current') {
8855				if (typeof item.width == 'number' && item.width) widthAvail = ((vars.isInFullScreen && opts.fullAlone) && (opts.fullStretchTypes.indexOf(itemParent.type) != -1 || item.fullViewPort || opts.fullViewPort)) ? widthAvail : ((item.width > widthAvail) ? widthAvail : item.width);
8856				if (typeof item.height == 'number' && item.height) heightAvail = ((vars.isInFullScreen && opts.fullAlone) && (opts.fullStretchTypes.indexOf(itemParent.type) != -1 || item.fullViewPort || opts.fullViewPort)) ? heightAvail : ((item.height > heightAvail) ? heightAvail : item.height);
8857			} else {
8858				if (typeof item.width == 'number' && item.width) widthAvail = (item.width > widthAvail) ? widthAvail : item.width;
8859				if (typeof item.height == 'number' && item.height) heightAvail = (item.height > heightAvail) ? heightAvail : item.height;
8860			}
8861
8862			heightAvail = parseInt(heightAvail - $('.ilightbox-inner-toolbar', holder).outerHeight());
8863
8864			var width = (typeof item.width == 'string' && item.width.indexOf('%') != -1) ? percentToValue(parseInt(item.width.replace('%', '')), obj.width) : holder.data('naturalWidth'),
8865				height = (typeof item.height == 'string' && item.height.indexOf('%') != -1) ? percentToValue(parseInt(item.height.replace('%', '')), obj.height) : holder.data('naturalHeight');
8866
8867			var dims = ((typeof item.width == 'string' && item.width.indexOf('%') != -1 || typeof item.height == 'string' && item.height.indexOf('%') != -1) ? {
8868					width: width,
8869					height: height
8870				} : iL.getNewDimenstions(widthAvail, heightAvail, width, height)),
8871				newDims = $.extend({}, dims, {});
8872
8873			if (obj.type == 'prev' || obj.type == 'next')
8874				width = parseInt(dims.width * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)),
8875				height = parseInt(dims.height * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale));
8876			else
8877				width = dims.width,
8878				height = dims.height;
8879
8880			var widthDiff = parseInt((getPixel(holder, 'padding-left') + getPixel(holder, 'padding-right') + getPixel(holder, 'border-left-width') + getPixel(holder, 'border-right-width')) / 2),
8881				heightDiff = parseInt((getPixel(holder, 'padding-top') + getPixel(holder, 'padding-bottom') + getPixel(holder, 'border-top-width') + getPixel(holder, 'border-bottom-width') + $('.ilightbox-inner-toolbar', holder).outerHeight()) / 2);
8882
8883			switch (obj.type) {
8884				case 'current':
8885					var top = parseInt((obj.height / 2) - (height / 2) - heightDiff - (thumbsOffsetH / 2)),
8886						left = parseInt((obj.width / 2) - (width / 2) - widthDiff - (thumbsOffsetW / 2));
8887					break;
8888
8889				case 'next':
8890					var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(obj.height - offsetX - heightDiff - (thumbsOffsetH / 2)),
8891						left = (path == 'horizontal') ? parseInt(obj.width - offsetX - widthDiff - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - (width / 2) - widthDiff - offsetY - (thumbsOffsetW / 2));
8892					break;
8893
8894				case 'prev':
8895					var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(offsetX - heightDiff - height - (thumbsOffsetH / 2)),
8896						left = (path == 'horizontal') ? parseInt(offsetX - widthDiff - width - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - offsetY - (width / 2) - widthDiff - (thumbsOffsetW / 2));
8897					break;
8898			}
8899
8900			holder.data('offset', {
8901				top: top,
8902				left: left,
8903				newDims: newDims,
8904				diff: {
8905					W: widthDiff,
8906					H: heightDiff
8907				},
8908				thumbsOffset: {
8909					W: thumbsOffsetW,
8910					H: thumbsOffsetH
8911				},
8912				object: obj
8913			});
8914
8915			if (obj.animate > 0 && opts.effects.reposition) {
8916				holder.css(transform, gpuAcceleration).stop().animate({
8917					top: top,
8918					left: left
8919				}, opts.effects.repositionSpeed, 'easeOutCirc', function() {
8920					holder.css(transform, '');
8921				});
8922				$('div.ilightbox-container', holder).stop().animate({
8923					width: width,
8924					height: height
8925				}, opts.effects.repositionSpeed, 'easeOutCirc');
8926				$('div.ilightbox-inner-toolbar', holder).stop().animate({
8927					width: width
8928				}, opts.effects.repositionSpeed, 'easeOutCirc', function() {
8929					$(this).css('overflow', 'visible');
8930				});
8931			} else {
8932				holder.css({
8933					top: top,
8934					left: left
8935				});
8936				$('div.ilightbox-container', holder).css({
8937					width: width,
8938					height: height
8939				});
8940				$('div.ilightbox-inner-toolbar', holder).css({
8941					width: width
8942				});
8943			}
8944		},
8945
8946		resume: function(priority) {
8947			var iL = this,
8948				vars = iL.vars,
8949				opts = iL.options;
8950
8951			if (!opts.slideshow.pauseTime || opts.controls.slideshow && vars.total <= 1 || priority < vars.isPaused) {
8952				return;
8953			}
8954
8955			vars.isPaused = 0;
8956
8957			if (vars.cycleID) {
8958				vars.cycleID = clearTimeout(vars.cycleID);
8959			}
8960
8961			vars.cycleID = setTimeout(function() {
8962				if (vars.current == vars.total - 1) iL.goTo(0);
8963				else iL.moveTo('next');
8964			}, opts.slideshow.pauseTime);
8965		},
8966
8967		pause: function(priority) {
8968			var iL = this,
8969				vars = iL.vars,
8970				opts = iL.options;
8971
8972			if (priority < vars.isPaused) {
8973				return;
8974			}
8975
8976			vars.isPaused = priority || 100;
8977
8978			if (vars.cycleID) {
8979				vars.cycleID = clearTimeout(vars.cycleID);
8980			}
8981		},
8982
8983		resetCycle: function() {
8984			var iL = this,
8985				vars = iL.vars,
8986				opts = iL.options;
8987
8988			if (opts.controls.slideshow && vars.cycleID && !vars.isPaused) {
8989				iL.resume();
8990			}
8991		},
8992
8993		getNewDimenstions: function(width, height, width_old, height_old, thumb) {
8994			var iL = this;
8995
8996			if (!width) factor = height / height_old;
8997			else if (!height) factor = width / width_old;
8998			else factor = min(width / width_old, height / height_old);
8999
9000			if (!thumb) {
9001				if (factor > iL.options.maxScale) factor = iL.options.maxScale;
9002				else if (factor < iL.options.minScale) factor = iL.options.minScale;
9003			}
9004
9005			var final_width = (iL.options.keepAspectRatio) ? round(width_old * factor) : width,
9006				final_height = (iL.options.keepAspectRatio) ? round(height_old * factor) : height;
9007
9008			return {
9009				width: final_width,
9010				height: final_height,
9011				ratio: factor
9012			};
9013		},
9014
9015		setOption: function(options) {
9016			var iL = this;
9017
9018			iL.options = $.extend(true, iL.options, options || {});
9019			iL.refresh();
9020		},
9021
9022		availPlugins: function() {
9023			var iL = this,
9024				testEl = document.createElement("video");
9025
9026			iL.plugins = {
9027				flash: (parseInt(PluginDetect.getVersion("Shockwave")) >= 0 || parseInt(PluginDetect.getVersion("Flash")) >= 0) ? true : false,
9028				quicktime: (parseInt(PluginDetect.getVersion("QuickTime")) >= 0) ? true : false,
9029				html5H264: !!(testEl.canPlayType && testEl.canPlayType('video/mp4').replace(/no/, '')),
9030				html5WebM: !!(testEl.canPlayType && testEl.canPlayType('video/webm').replace(/no/, '')),
9031				html5Vorbis: !!(testEl.canPlayType && testEl.canPlayType('video/ogg').replace(/no/, '')),
9032				html5QuickTime: !!(testEl.canPlayType && testEl.canPlayType('video/quicktime').replace(/no/, ''))
9033			};
9034		},
9035
9036		addContent: function(element, obj) {
9037			var iL = this,
9038				el;
9039
9040			switch (obj.type) {
9041				case 'video':
9042					var HTML5 = false,
9043						videoType = obj.videoType,
9044						html5video = obj.options.html5video;
9045
9046					if (((videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v') || html5video.h264) && iL.plugins.html5H264)
9047						obj.ext = 'mp4',
9048						obj.URL = html5video.h264 || obj.URL;
9049					else if (html5video.webm && iL.plugins.html5WebM)
9050						obj.ext = 'webm',
9051						obj.URL = html5video.webm || obj.URL;
9052					else if (html5video.ogg && iL.plugins.html5Vorbis)
9053						obj.ext = 'ogv',
9054						obj.URL = html5video.ogg || obj.URL;
9055
9056					if (iL.plugins.html5H264 && (videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v')) HTML5 = true, videoType = "video/mp4";
9057					else if (iL.plugins.html5WebM && (videoType == 'video/webm' || obj.ext == 'webm')) HTML5 = true, videoType = "video/webm";
9058					else if (iL.plugins.html5Vorbis && (videoType == 'video/ogg' || obj.ext == 'ogv')) HTML5 = true, videoType = "video/ogg";
9059					else if (iL.plugins.html5QuickTime && (videoType == 'video/quicktime' || obj.ext == 'mov' || obj.ext == 'qt')) HTML5 = true, videoType = "video/quicktime";
9060
9061					if (HTML5) {
9062						el = $('<video />
9062', {
9063							"width": "100%",
9064							"height": "100%",
9065							"preload": html5video.preload,
9066							"autoplay": html5video.autoplay,
9067							"poster": html5video.poster,
9068							"controls": html5video.controls
9069						}).append($('<source />', {
9070							"src": obj.URL,
9071							"type": videoType
9072						}));
9073					} else {
9074						if (!iL.plugins.quicktime) el = $('<span />', {
9075							"class": "ilightbox-alert",
9076							html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.quicktime).replace('{type}', 'QuickTime')
9077						});
9078						else {
9079
9080							el = $('<object />', {
9081								"type": "video/quicktime",
9082								"pluginspage": pluginspages.quicktime
9083							}).attr({
9084								"data": obj.URL,
9085								"width": "100%",
9086								"height": "100%"
9087							}).append($('<param />', {
9088								"name": "src",
9089								"value": obj.URL
9090							})).append($('<param />', {
9091								"name": "autoplay",
9092								"value": "false"
9093							})).append($('<param />', {
9094								"name": "loop",
9095								"value": "false"
9096							})).append($('<param />', {
9097								"name": "scale",
9098								"value": "tofit"
9099							}));
9100
9101							if (browser.msie) el = QT_GenerateOBJECTText(obj.URL, '100%', '100%', '', 'SCALE', 'tofit', 'AUTOPLAY', 'false', 'LOOP', 'false');
9102						}
9103					}
9104
9105					break;
9106
9107				case 'flash':
9108					if (!iL.plugins.flash) el = $('<span />', {
9109						"class": "ilightbox-alert",
9110						html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.flash).replace('{type}', 'Adobe Flash player')
9111					});
9112					else {
9113						var flashvars = "",
9114							i = 0;
9115
9116						if (obj.options.flashvars) $.each(obj.options.flashvars, function(k, v) {
9117							if (i != 0) flashvars += "&";
9118							flashvars += k + "=" + encodeURIComponent(v);
9119							i++;
9120						});
9121						else flashvars = null;
9122
9123						el = $('<embed />').attr({
9124							"type": "application/x-shockwave-flash",
9125							"src": obj.URL,
9126							"width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%",
9127							"height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%",
9128							"quality": "high",
9129							"bgcolor": "#000000",
9130							"play": "true",
9131							"loop": "true",
9132							"menu": "true",
9133							"wmode": "transparent",
9134							"scale": "showall",
9135							"allowScriptAccess": "always",
9136							"allowFullScreen": "true",
9137							"flashvars": flashvars,
9138							"fullscreen": "yes"
9139						});
9140					}
9141
9142					break;
9143
9144				case 'iframe':
9145					el = $('<iframe />').attr({
9146						"width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%",
9147						"height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%",
9148						src: obj.URL,
9149						frameborder: 0,
9150						'hspace': 0,
9151						'vspace': 0,
9152						'scrolling': supportTouch ? 'auto' : 'scroll',
9153						'webkitAllowFullScreen': '',
9154						'mozallowfullscreen': '',
9155						'allowFullScreen': ''
9156					});
9157
9158					break;
9159
9160				case 'inline':
9161					el = $('<div class="ilightbox-wrapper"></div>').html($(obj.URL).clone(true));
9162
9163					break;
9164
9165				case 'html':
9166					var object = obj.URL,
9167						el;
9168
9169					if (object[0].nodeName) {
9170						el = $('<div class="ilightbox-wrapper"></div>').html(object);
9171					} else {
9172						var dom = $(obj.URL),
9173							html = (dom.selector) ? $('<div>' + dom + '</div>') : dom;
9174						el = $('<div class="ilightbox-wrapper"></div>').html(html);
9175					}
9176
9177					break;
9178			}
9179
9180			$('div.ilightbox-container', element).empty().html(el);
9181
9182			// For fixing Chrome about just playing the video for first time
9183			if (el[0].tagName.toLowerCase() === 'video' && browser.webkit) setTimeout(function() {
9184				var src = el[0].currentSrc + '?' + floor(random() * 30000);
9185				el[0].currentSrc = src;
9186				el[0].src = src;
9187			});
9188
9189			return el;
9190		},
9191
9192		ogpRecognition: function(obj, callback) {
9193			var iL = this,
9194				url = obj.URL;
9195
9196			iL.showLoader();
9197			doAjax(url, function(data) {
9198				iL.hideLoader();
9199
9200				if (data) {
9201					var object = new Object();
9202
9203					object.length = false,
9204					object.url = data.url;
9205
9206					if (data.status == 200) {
9207						var result = data.results,
9208							type = result.type,
9209							source = result.source;
9210
9211						object.source = source.src,
9212						object.width = source.width && parseInt(source.width) || 0,
9213						object.height = source.height && parseInt(source.height) || 0,
9214						object.type = type,
9215						object.thumbnail = source.thumbnail || result.images[0],
9216						object.html5video = result.html5video || {},
9217						object.length = true;
9218
9219						if (source.type == 'application/x-shockwave-flash') object.type = "flash";
9220						else if (source.type.indexOf("video/") != -1) object.type = "video";
9221						else if (source.type.indexOf("/html") != -1) object.type = "iframe";
9222						else if (source.type.indexOf("image/") != -1) object.type = "image";
9223
9224					} else if (typeof data.response != 'undefined')
9225						throw data.response;
9226
9227					callback.call(this, object.length ? object : false);
9228				}
9229			});
9230		},
9231
9232		hashChangeHandler: function(url) {
9233			var iL = this,
9234				vars = iL.vars,
9235				opts = iL.options,
9236				URL = url || window.location.href,
9237				hash = parseURI(URL).hash,
9238				split = hash.split('/'),
9239				index = split[1];
9240
9241			if (vars.hashLock || ('#' + opts.linkId != split[0] && hash.length > 1)) return;
9242
9243			if (index) {
9244				var target = split[1] || 0;
9245				if (iL.items[target]) {
9246					var overlay = $('.ilightbox-overlay');
9247					if (overlay.length && overlay.attr('linkid') == opts.linkId) {
9248						iL.goTo(target);
9249					} else {
9250						iL.itemsObject[target].trigger(supportTouch ? 'itap' : 'click');
9251					}
9252				} else {
9253					var overlay = $('.ilightbox-overlay');
9254					if (overlay.length) iL.closeAction();
9255				}
9256			} else {
9257				var overlay = $('.ilightbox-overlay');
9258				if (overlay.length) iL.closeAction();
9259			}
9260		}
9261	};
9262
9263	/**
9264	 * Parse style to pixels.
9265	 *
9266	 * @param {Object}   $element   jQuery object with element.
9267	 * @param {Property} property   CSS property to get the pixels from.
9268	 *
9269	 * @return {Int}
9270	 */
9271	function getPixel($element, property) {
9272		return parseInt($element.css(property), 10) || 0;
9273	}
9274
9275	/**
9276	 * Make sure that number is within the limits.
9277	 *
9278	 * @param {Number} number
9279	 * @param {Number} min
9280	 * @param {Number} max
9281	 *
9282	 * @return {Number}
9283	 */
9284	function within(number, min, max) {
9285		return number < min ? min : number > max ? max : number;
9286	}
9287
9288	/**
9289	 * Get viewport/window size (width and height).
9290	 *
9291	 * @return {Object}
9292	 */
9293	function getViewport() {
9294		var e = window,
9295			a = 'inner';
9296		if (!('innerWidth' in window)) {
9297			a = 'client';
9298			e = document.documentElement || document.body;
9299		}
9300		return {
9301			width: e[a + 'Width'],
9302			height: e[a + 'Height']
9303		}
9304	}
9305
9306	/**
9307	 * Remove hash tag from the URL
9308	 *
9309	 * @return {Void}
9310	 */
9311	function removeHash() {
9312		var scroll = getScrollXY();
9313
9314		window.location.hash = "";
9315
9316		// Restore the scroll offset, should be flicker free
9317		window.scrollTo(scroll.x, scroll.y);
9318	}
9319
9320	/**
9321	 * Do the ajax requests with callback.
9322	 *
9323	 * @param {String}   url
9324	 * @param {Function} callback
9325	 *
9326	 * @return {Void}
9327	 */
9328	function doAjax(url, callback) {
9329		var url = "http://ilightbox.net/getSource/jsonp.php?url=" + encodeURIComponent(url).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A');
9330		$.ajax({
9331			url: url,
9332			dataType: 'jsonp'
9333		});
9334
9335		iLCallback = function(data) {
9336			callback.call(this, data);
9337		};
9338	}
9339
9340	/**
9341	 * Find image from DOM elements
9342	 *
9343	 * @param {Element} element
9344	 *
9345	 * @return {Void}
9346	 */
9347	function findImageInElement(element) {
9348		var elements = $('*', element),
9349			imagesArr = new Array();
9350
9351		elements.each(function() {
9352			var url = "",
9353				element = this;
9354
9355			if ($(element).css("background-image") != "none") {
9356				url = $(element).css("background-image");
9357			} else if (typeof($(element).attr("src")) != "undefined" && element.nodeName.toLowerCase() == "img") {
9358				url = $(element).attr("src");
9359			}
9360
9361			if (url.indexOf("gradient") == -1) {
9362				url = url.replace(/url\(\"/g, "");
9363				url = url.replace(/url\(/g, "");
9364				url = url.replace(/\"\)/g, "");
9365				url = url.replace(/\)/g, "");
9366
9367				var urls = url.split(",");
9368
9369				for (var i = 0; i < urls.length; i++) {
9370					if (urls[i].length > 0 && $.inArray(urls[i], imagesArr) == -1) {
9371						var extra = "";
9372						if (browser.msie && browser.version < 9) {
9373							extra = "?" + floor(random() * 3000);
9374						}
9375						imagesArr.push(urls[i] + extra);
9376					}
9377				}
9378			}
9379		});
9380
9381		return imagesArr;
9382	}
9383
9384	/**
9385	 * Get file extension.
9386	 *
9387	 * @param {String} URL
9388	 *
9389	 * @return {String}
9390	 */
9391	function getExtension(URL) {
9392		if (URL !== null) {
9393			var ext = URL.split('.').pop().toLowerCase(),
9394				extra = ext.indexOf('?') !== -1 ? ext.split('?').pop() : '';
9395
9396			return ext.replace(extra, '');
9397		}
9398	}
9399
9400	/**
9401	 * Get type via extension.
9402	 *
9403	 * @param {String} URL
9404	 *
9405	 * @return {String}
9406	 */
9407	function getTypeByExtension(URL) {
9408		var type,
9409			ext = getExtension(URL);
9410
9411		if (extensions.image.indexOf(ext) !== -1) type = 'image';
9412		else if (extensions.flash.indexOf(ext) !== -1) type = 'flash';
9413		else if (extensions.video.indexOf(ext) !== -1) type = 'video';
9414		else type = 'iframe';
9415
9416		return type;
9417	}
9418
9419	/**
9420	 * Return value from percent of a number.
9421	 *
9422	 * @param {Number} percent
9423	 * @param {Number} total
9424	 *
9425	 * @return {Number}
9426	 */
9427	function percentToValue(percent, total) {
9428		return parseInt((total / 100) * percent);
9429	}
9430
9431	/**
9432	 * A JavaScript equivalent of PHP’s parse_url.
9433	 *
9434	 * @param {String} url           The URL to parse.
9435	 *
9436	 * @return {Mixed}
9437	 */
9438	function parseURI(url) {
9439		var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/);
9440		// authority = '//' + user + ':' + pass '@' + hostname + ':' port
9441		return (m ? {
9442			href: m[0] || '',
9443			protocol: m[1] || '',
9444			authority: m[2] || '',
9445			host: m[3] || '',
9446			hostname: m[4] || '',
9447			port: m[5] || '',
9448			pathname: m[6] || '',
9449			search: m[7] || '',
9450			hash: m[8] || ''
9451		} : null);
9452	}
9453
9454	/**
9455	 * Gets the absolute URI.
9456	 *
9457	 * @param {String} href     The relative URL.
9458	 * @param {String} base     The base URL.
9459	 *
9460	 * @return {String}         The absolute URL.
9461	 */
9462	function absolutizeURI(base, href) { // RFC 3986
9463		var iL = this;
9464
9465		function removeDotSegments(input) {
9466			var output = [];
9467			input.replace(/^(\.\.?(\/|$))+/, '')
9468				.replace(/\/(\.(\/|$))+/g, '/')
9469				.replace(/\/\.\.$/, '/../')
9470				.replace(/\/?[^\/]*/g, function(p) {
9471					if (p === '/..') {
9472						output.pop();
9473					} else {
9474						output.push(p);
9475					}
9476				});
9477			return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : '');
9478		}
9479
9480		href = parseURI(href || '');
9481		base = parseURI(base || '');
9482
9483		return !href || !base ? null : (href.protocol || base.protocol) +
9484			(href.protocol || href.authority ? href.authority : base.authority) +
9485			removeDotSegments(href.protocol || href.authority || href.pathname.charAt(0) === '/' ? href.pathname : (href.pathname ? ((base.authority && !base.pathname ? '/' : '') + base.pathname.slice(0, base.pathname.lastIndexOf('/') + 1) + href.pathname) : base.pathname)) +
9486			(href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) +
9487			href.hash;
9488	}
9489
9490	/**
9491	 * A JavaScript equivalent of PHP’s version_compare.
9492	 *
9493	 * @param {String} v1
9494	 * @param {String} v2
9495	 * @param {String} operator
9496	 *
9497	 * @return {Boolean}
9498	 */
9499	function version_compare(v1, v2, operator) {
9500		this.php_js = this.php_js || {};
9501		this.php_js.ENV = this.php_js.ENV || {};
9502		var i = 0,
9503			x = 0,
9504			compare = 0,
9505			vm = {
9506				'dev': -6,
9507				'alpha': -5,
9508				'a': -5,
9509				'beta': -4,
9510				'b': -4,
9511				'RC': -3,
9512				'rc': -3,
9513				'#': -2,
9514				'p': 1,
9515				'pl': 1
9516			},
9517			prepVersion = function(v) {
9518				v = ('' + v).replace(/[_\-+]/g, '.');
9519				v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.');
9520				return (!v.length ? [-8] : v.split('.'));
9521			},
9522			numVersion = function(v) {
9523				return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10));
9524			};
9525		v1 = prepVersion(v1);
9526		v2 = prepVersion(v2);
9527		x = max(v1.length, v2.length);
9528		for (i = 0; i < x; i++) {
9529			if (v1[i] == v2[i]) {
9530				continue;
9531			}
9532			v1[i] = numVersion(v1[i]);
9533			v2[i] = numVersion(v2[i]);
9534			if (v1[i] < v2[i]) {
9535				compare = -1;
9536				break;
9537			} else if (v1[i] > v2[i]) {
9538				compare = 1;
9539				break;
9540			}
9541		}
9542		if (!operator) {
9543			return compare;
9544		}
9545
9546		switch (operator) {
9547			case '>':
9548			case 'gt':
9549				return (compare > 0);
9550			case '>=':
9551			case 'ge':
9552				return (compare >= 0);
9553			case '<=':
9554			case 'le':
9555				return (compare <= 0);
9556			case '==':
9557			case '=':
9558			case 'eq':
9559				return (compare === 0);
9560			case '<>':
9561			case '!=':
9562			case 'ne':
9563				return (compare !== 0);
9564			case '':
9565			case '<':
9566			case 'lt':
9567				return (compare < 0);
9568			default:
9569				return null;
9570		}
9571	}
9572
9573
9574	// Begin the iLightBox plugin
9575	$.fn.iLightBox = function() {
9576
9577		var args = arguments,
9578			opt = ($.isPlainObject(args[0])) ? args[0] : args[1],
9579			items = ($.isArray(args[0]) || typeof args[0] == 'string') ? args[0] : args[1];
9580
9581		if (!opt) opt = {};
9582
9583		// Default options. Play carefully.
9584		var options = $.extend(true, {
9585			attr: 'href',
9586			path: 'vertical',
9587			skin: 'dark',
9588			linkId: false,
9589			infinite: false,
9590			startFrom: 0,
9591			randomStart: false,
9592			keepAspectRatio: true,
9593			maxScale: 1,
9594			minScale: .2,
9595			innerToolbar: false,
9596			smartRecognition: false,
9597			mobileOptimizer: true,
9598			fullAlone: true,
9599			fullViewPort: null,
9600			fullStretchTypes: 'flash, video',
9601			overlay: {
9602				blur: true,
9603				opacity: .85
9604			},
9605			controls: {
9606				arrows: false,
9607				slideshow: false,
9608				toolbar: true,
9609				fullscreen: true,
9610				thumbnail: true,
9611				keyboard: true,
9612				mousewheel: true,
9613				swipe: true
9614			},
9615			keyboard: {
9616				left: true, // previous
9617				right: true, // next
9618				up: true, // previous
9619				down: true, // next
9620				esc: true, // close
9621				shift_enter: true // fullscreen
9622			},
9623			show: {
9624				effect: true,
9625				speed: 300,
9626				title: true
9627			},
9628			hide: {
9629				effect: true,
9630				speed: 300
9631			},
9632			caption: {
9633				start: true,
9634				show: 'mouseenter',
9635				hide: 'mouseleave'
9636			},
9637			social: {
9638				start: true,
9639				show: 'mouseenter',
9640				hide: 'mouseleave',
9641				buttons: false
9642			},
9643			styles: {
9644				pageOffsetX: 0,
9645				pageOffsetY: 0,
9646				nextOffsetX: 45,
9647				nextOffsetY: 0,
9648				nextOpacity: 1,
9649				nextScale: 1,
9650				prevOffsetX: 45,
9651				prevOffsetY: 0,
9652				prevOpacity: 1,
9653				prevScale: 1
9654			},
9655			thumbnails: {
9656				maxWidth: 120,
9657				maxHeight: 80,
9658				normalOpacity: 1,
9659				activeOpacity: .6
9660			},
9661			effects: {
9662				reposition: true,
9663				repositionSpeed: 200,
9664				switchSpeed: 500,
9665				loadedFadeSpeed: 180,
9666				fadeSpeed: 200
9667			},
9668			slideshow: {
9669				pauseTime: 5000,
9670				pauseOnHover: false,
9671				startPaused: true
9672			},
9673			text: {
9674				close: "Press Esc to close",
9675				enterFullscreen: "Enter Fullscreen (Shift+Enter)",
9676				exitFullscreen: "Exit Fullscreen (Shift+Enter)",
9677				slideShow: "Slideshow",
9678				next: "Next",
9679				previous: "Previous"
9680			},
9681			errors: {
9682				loadImage: "An error occurred when trying to load photo.",
9683				loadContents: "An error occurred when trying to load contents.",
9684				missingPlugin: "The content your are attempting to view requires the <a href='{pluginspage}' target='_blank'>{type} plugin<\/a>."
9685			},
9686			ajaxSetup: {
9687				url: '',
9688				beforeSend: function(jqXHR, settings) {},
9689				cache: false,
9690				complete: function(jqXHR, textStatus) {},
9691				crossDomain: false,
9692				error: function(jqXHR, textStatus, errorThrown) {},
9693				success: function(data, textStatus, jqXHR) {},
9694				global: true,
9695				ifModified: false,
9696				username: null,
9697				password: null,
9698				type: 'GET'
9699			},
9700			callback: {}
9701		}, opt);
9702
9703		var instant = ($.isArray(items) || typeof items == 'string') ? true : false;
9704
9705		items = $.isArray(items) ? items : new Array();
9706
9707		if (typeof args[0] == 'string') items[0] = args[0];
9708
9709		if (version_compare($.fn.jquery, '1.8', '>=')) {
9710			var iLB = new iLightBox($(this), options, items, instant);
9711			return {
9712				close: function() {
9713					iLB.closeAction();
9714				},
9715				fullscreen: function() {
9716					iLB.fullScreenAction();
9717				},
9718				moveNext: function() {
9719					iLB.moveTo('next');
9720				},
9721				movePrev: function() {
9722					iLB.moveTo('prev');
9723				},
9724				goTo: function(index) {
9725					iLB.goTo(index);
9726				},
9727				refresh: function() {
9728					iLB.refresh();
9729				},
9730				reposition: function() {
9731					(arguments.length > 0) ? iLB.repositionPhoto(true): iLB.repositionPhoto();
9732				},
9733				setOption: function(options) {
9734					iLB.setOption(options);
9735				},
9736				destroy: function() {
9737					iLB.closeAction();
9738					iLB.dispatchItemsEvents();
9739				}
9740			};
9741		} else {
9742			throw "The jQuery version that was loaded is too old. iLightBox requires jQuery 1.8+";
9743		}
9744
9745	};
9746
9747
9748	$.iLightBox = function() {
9749		return $.fn.iLightBox(arguments[0], arguments[1]);
9750	};
9751
9752
9753	$.extend($.easing, {
9754		easeInCirc: function(x, t, b, c, d) {
9755			return -c * (sqrt(1 - (t /= d) * t) - 1) + b;
9756		},
9757		easeOutCirc: function(x, t, b, c, d) {
9758			return c * sqrt(1 - (t = t / d - 1) * t) + b;
9759		},
9760		easeInOutCirc: function(x, t, b, c, d) {
9761			if ((t /= d / 2) < 1) return -c / 2 * (sqrt(1 - t * t) - 1) + b;
9762			return c / 2 * (sqrt(1 - (t -= 2) * t) + 1) + b;
9763		}
9764	});
9765
9766	function getScrollXY() {
9767		var scrOfX = 0,
9768			scrOfY = 0;
9769		if (typeof(window.pageYOffset) == 'number') {
9770			//Netscape compliant
9771			scrOfY = window.pageYOffset;
9772			scrOfX = window.pageXOffset;
9773		} else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
9774			//DOM compliant
9775			scrOfY = document.body.scrollTop;
9776			scrOfX = document.body.scrollLeft;
9777		} else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
9778			//IE6 standards compliant mode
9779			scrOfY = document.documentElement.scrollTop;
9780			scrOfX = document.documentElement.scrollLeft;
9781		}
9782		return {
9783			x: scrOfX,
9784			y: scrOfY
9785		};
9786	}
9787
9788	(function() {
9789		// add new event shortcuts
9790		$.each(("touchstart touchmove touchend " +
9791			"tap taphold " +
9792			"swipe swipeleft swiperight " +
9793			"scrollstart scrollstop").split(" "), function(i, name) {
9794
9795			$.fn[name] = function(fn) {
9796				return fn ? this.bind(name, fn) : this.trigger(name);
9797			};
9798
9799			// jQuery < 1.8
9800			if ($.attrFn) {
9801				$.attrFn[name] = true;
9802			}
9803		});
9804
9805		var tapSettings = {
9806			startEvent: 'touchstart.iTap',
9807			endEvent: 'touchend.iTap'
9808		};
9809
9810		// tap Event:
9811		$.event.special.itap = {
9812			setup: function() {
9813
9814				var self = this,
9815					$self = $(this),
9816					start, stop;
9817
9818				$self.bind(tapSettings.startEvent, function(event) {
9819					start = getScrollXY();
9820
9821					$self.one(tapSettings.endEvent, function(event) {
9822						stop = getScrollXY();
9823
9824						var orgEvent = event || window.event;
9825						event = $.event.fix(orgEvent);
9826						event.type = "itap";
9827
9828						if ((start && stop) && (start.x == stop.x && start.y == stop.y))($.event.dispatch || $.event.handle).call(self, event);
9829
9830						start = stop = undefined;
9831					});
9832				});
9833			},
9834
9835			teardown: function() {
9836				$(this).unbind(tapSettings.startEvent);
9837			}
9838		};
9839	}());
9840
9841
9842	//Fullscreen API
9843	(function() {
9844		fullScreenApi = {
9845				supportsFullScreen: false,
9846				isFullScreen: function() {
9847					return false;
9848				},
9849				requestFullScreen: function() {},
9850				cancelFullScreen: function() {},
9851				fullScreenEventName: '',
9852				prefix: ''
9853			},
9854			browserPrefixes = 'webkit moz o ms khtml'.split(' ');
9855
9856		// check for native support
9857		if (typeof document.cancelFullScreen != 'undefined') {
9858			fullScreenApi.supportsFullScreen = true;
9859		} else {
9860			// check for fullscreen support by vendor prefix
9861			for (var i = 0, il = browserPrefixes.length; i < il; i++) {
9862				fullScreenApi.prefix = browserPrefixes[i];
9863
9864				if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') {
9865					fullScreenApi.supportsFullScreen = true;
9866
9867					break;
9868				}
9869			}
9870		}
9871
9872		// update methods to do something useful
9873		if (fullScreenApi.supportsFullScreen) {
9874			fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange';
9875
9876			fullScreenApi.isFullScreen = function() {
9877				switch (this.prefix) {
9878					case '':
9879						return document.fullScreen;
9880					case 'webkit':
9881						return document.webkitIsFullScreen;
9882					default:
9883						return document[this.prefix + 'FullScreen'];
9884				}
9885			}
9886			fullScreenApi.requestFullScreen = function(el) {
9887				return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen']();
9888			}
9889			fullScreenApi.cancelFullScreen = function(el) {
9890				return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen']();
9891			}
9892		}
9893	}());
9894
9895	// Browser detect
9896	(function() {
9897		function uaMatch(ua) {
9898			ua = ua.toLowerCase();
9899
9900			var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
9901				/(webkit)[ \/]([\w.]+)/.exec(ua) ||
9902				/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
9903				/(msie) ([\w.]+)/.exec(ua) ||
9904				ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || [];
9905
9906			return {
9907				browser: match[1] || "",
9908				version: match[2] || "0"
9909			};
9910		}
9911
9912		var matched = uaMatch(navigator.userAgent);
9913		browser = {};
9914
9915		if (matched.browser) {
9916			browser[matched.browser] = true;
9917			browser.version = matched.version;
9918		}
9919
9920		// Chrome is Webkit, but Webkit is also Safari.
9921		if (browser.chrome) {
9922			browser.webkit = true;
9923		} else if (browser.webkit) {
9924			browser.safari = true;
9925		}
9926	}());
9927
9928	// Feature detects
9929	(function() {
9930		var prefixes = ['', 'webkit', 'moz', 'ms', 'o'];
9931		var el = document.createElement('div');
9932
9933		function testProp(prop) {
9934			for (var p = 0, pl = prefixes.length; p < pl; p++) {
9935				var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop;
9936				if (el.style[prefixedProp] !== undefined) {
9937					return prefixedProp;
9938				}
9939			}
9940		}
9941
9942		// Global support indicators
9943		transform = testProp('transform') || '';
9944		gpuAcceleration = testProp('perspective') ? 'translateZ(0) ' : '';
9945	}());
9946
9947
9948	/*
9949		PluginDetect v0.7.9
9950		www.pinlady.net/PluginDetect/license/
9951		[ getVersion onWindowLoaded BetterIE ]
9952		[ Flash QuickTime Shockwave ]
9953	*/
9954	var PluginDetect={version:"0.7.9",name:"PluginDetect",handler:function(c,b,a){return function(){c(b,a)}},openTag:"<",isDefined:function(b){return typeof b!="undefined"},isArray:function(b){return(/array/i).test(Object.prototype.toString.call(b))},isFunc:function(b){return typeof b=="function"},isString:function(b){return typeof b=="string"},isNum:function(b){return typeof b=="number"},isStrNum:function(b){return(typeof b=="string"&&(/\d/).test(b))},getNumRegx:/[\d][\d\.\_,-]*/,splitNumRegx:/[\.\_,-]/g,getNum:function(b,c){var d=this,a=d.isStrNum(b)?(d.isDefined(c)?new RegExp(c):d.getNumRegx).exec(b):null;return a?a[0]:null},compareNums:function(h,f,d){var e=this,c,b,a,g=parseInt;if(e.isStrNum(h)&&e.isStrNum(f)){if(e.isDefined(d)&&d.compareNums){return d.compareNums(h,f)}c=h.split(e.splitNumRegx);b=f.split(e.splitNumRegx);for(a=0;a<min(c.length,b.length);a++){if(g(c[a],10)>g(b[a],10)){return 1}if(g(c[a],10)<g(b[a],10)){return -1}}}return 0},formatNum:function(b,c){var d=this,a,e;if(!d.isStrNum(b)){return null}if(!d.isNum(c)){c=4}c--;e=b.replace(/\s/g,"").split(d.splitNumRegx).concat(["0","0","0","0"]);for(a=0;a<4;a++){if(/^(0+)(.+)$/.test(e[a])){e[a]=RegExp.$2}if(a>c||!(/\d/).test(e[a])){e[a]="0"}}return e.slice(0,4).join(",")},$$hasMimeType:function(a){return function(c){if(!a.isIE&&c){var f,e,b,d=a.isArray(c)?c:(a.isString(c)?[c]:[]);for(b=0;b<d.length;b++){if(a.isString(d[b])&&/[^\s]/.test(d[b])){f=navigator.mimeTypes[d[b]];e=f?f.enabledPlugin:0;if(e&&(e.name||e.description)){return f}}}}return null}},findNavPlugin:function(l,e,c){var j=this,h=new RegExp(l,"i"),d=(!j.isDefined(e)||e)?/\d/:0,k=c?new RegExp(c,"i"):0,a=navigator.plugins,g="",f,b,m;for(f=0;f<a.length;f++){m=a[f].description||g;b=a[f].name||g;if((h.test(m)&&(!d||d.test(RegExp.leftContext+RegExp.rightContext)))||(h.test(b)&&(!d||d.test(RegExp.leftContext+RegExp.rightContext)))){if(!k||!(k.test(m)||k.test(b))){return a[f]}}}return null},getMimeEnabledPlugin:function(k,m,c){var e=this,f,b=new RegExp(m,"i"),h="",g=c?new RegExp(c,"i"):0,a,l,d,j=e.isString(k)?[k]:k;for(d=0;d<j.length;
9954d++){if((f=e.hasMimeType(j[d]))&&(f=f.enabledPlugin)){l=f.description||h;a=f.name||h;if(b.test(l)||b.test(a)){if(!g||!(g.test(l)||g.test(a))){return f}}}}return 0},getPluginFileVersion:function(f,b){var h=this,e,d,g,a,c=-1;if(h.OS>2||!f||!f.version||!(e=h.getNum(f.version))){return b}if(!b){return e}e=h.formatNum(e);b=h.formatNum(b);d=b.split(h.splitNumRegx);g=e.split(h.splitNumRegx);for(a=0;a<d.length;a++){if(c>-1&&a>c&&d[a]!="0"){return b}if(g[a]!=d[a]){if(c==-1){c=a}if(d[a]!="0"){return b}}}return e},AXO:window.ActiveXObject,getAXO:function(a){var f=null,d,b=this,c={};try{f=new b.AXO(a)}catch(d){}return f},convertFuncs:function(f){var a,g,d,b=/^[\$][\$]/,c=this;for(a in f){if(b.test(a)){try{g=a.slice(2);if(g.length>0&&!f[g]){f[g]=f[a](f);delete f[a]}}catch(d){}}}},initObj:function(e,b,d){var a,c;if(e){if(e[b[0]]==1||d){for(a=0;a<b.length;a=a+2){e[b[a]]=b[a+1]}}for(a in e){c=e[a];if(c&&c[b[0]]==1){this.initObj(c,b)}}}},initScript:function(){var d=this,a=navigator,h,i=document,l=a.userAgent||"",j=a.vendor||"",b=a.platform||"",k=a.product||"";d.initObj(d,["$",d]);for(h in d.Plugins){if(d.Plugins[h]){d.initObj(d.Plugins[h],["$",d,"$$",d.Plugins[h]],1)}}d.convertFuncs(d);d.OS=100;if(b){var g=["Win",1,"Mac",2,"Linux",3,"FreeBSD",4,"iPhone",21.1,"iPod",21.2,"iPad",21.3,"Win.*CE",22.1,"Win.*Mobile",22.2,"Pocket\\s*PC",22.3,"",100];for(h=g.length-2;h>=0;h=h-2){if(g[h]&&new RegExp(g[h],"i").test(b)){d.OS=g[h+1];break}}};d.head=i.getElementsByTagName("head")[0]||i.getElementsByTagName("body")[0]||i.body||null;d.isIE=new Function("return/*@cc_on!@*/!1")();d.verIE=d.isIE&&(/MSIE\s*(\d+\.?\d*)/i).test(l)?parseFloat(RegExp.$1,10):null;d.verIEfull=null;d.docModeIE=null;if(d.isIE){var f,n,c=document.createElement("div");try{c.style.behavior="url(#default#clientcaps)";d.verIEfull=(c.getComponentVersion("{89820200-ECBD-11CF-8B85-00AA005B4383}","componentid")).replace(/,/g,".")}catch(f){}n=parseFloat(d.verIEfull||"0",10);d.docModeIE=i.documentMode||((/back/i).test(i.compatMode||"")?5:n)||d.verIE;d.verIE=n||d.docModeIE};d.ActiveXEnabled=false;if(d.isIE){var h,m=["Msxml2.XMLHTTP","Msxml2.DOMDocument","Microsoft.XMLDOM","ShockwaveFlash.ShockwaveFlash","TDCCtl.TDCCtl","Shell.UIHelper","Scripting.Dictionary","wmplayer.ocx"];for(h=0;h<m.length;h++){if(d.getAXO(m[h])){d.ActiveXEnabled=true;break}}};d.isGecko=(/Gecko/i).test(k)&&(/Gecko\s*\/\s*\d/i).test(l);
9954d.verGecko=d.isGecko?d.formatNum((/rv\s*\:\s*([\.\,\d]+)/i).test(l)?RegExp.$1:"0.9"):null;d.isChrome=(/Chrome\s*\/\s*(\d[\d\.]*)/i).test(l);d.verChrome=d.isChrome?d.formatNum(RegExp.$1):null;d.isSafari=((/Apple/i).test(j)||(!j&&!d.isChrome))&&(/Safari\s*\/\s*(\d[\d\.]*)/i).test(l);d.verSafari=d.isSafari&&(/Version\s*\/\s*(\d[\d\.]*)/i).test(l)?d.formatNum(RegExp.$1):null;d.isOpera=(/Opera\s*[\/]?\s*(\d+\.?\d*)/i).test(l);d.verOpera=d.isOpera&&((/Version\s*\/\s*(\d+\.?\d*)/i).test(l)||1)?parseFloat(RegExp.$1,10):null;d.addWinEvent("load",d.handler(d.runWLfuncs,d))},init:function(d){var c=this,b,d,a={status:-3,plugin:0};if(!c.isString(d)){return a}if(d.length==1){c.getVersionDelimiter=d;return a}d=d.toLowerCase().replace(/\s/g,"");b=c.Plugins[d];if(!b||!b.getVersion){return a}a.plugin=b;if(!c.isDefined(b.installed)){b.installed=null;b.version=null;b.version0=null;b.getVersionDone=null;b.pluginName=d}c.garbage=false;if(c.isIE&&!c.ActiveXEnabled&&d!=="java"){a.status=-2;return a}a.status=1;return a},fPush:function(b,a){var c=this;if(c.isArray(a)&&(c.isFunc(b)||(c.isArray(b)&&b.length>0&&c.isFunc(b[0])))){a.push(b)}},callArray:function(b){var c=this,a;if(c.isArray(b)){for(a=0;a<b.length;a++){if(b[a]===null){return}c.call(b[a]);b[a]=null}}},call:function(c){var b=this,a=b.isArray(c)?c.length:-1;if(a>0&&b.isFunc(c[0])){c[0](b,a>1?c[1]:0,a>2?c[2]:0,a>3?c[3]:0)}else{if(b.isFunc(c)){c(b)}}},getVersionDelimiter:",",$$getVersion:function(a){return function(g,d,c){var e=a.init(g),f,b,h={};if(e.status<0){return null};f=e.plugin;if(f.getVersionDone!=1){f.getVersion(null,d,c);if(f.getVersionDone===null){f.getVersionDone=1}}a.cleanup();b=(f.version||f.version0);b=b?b.replace(a.splitNumRegx,a.getVersionDelimiter):b;return b}},cleanup:function(){var a=this;if(a.garbage&&a.isDefined(window.CollectGarbage)){window.CollectGarbage()}},isActiveXObject:function(d,b){var f=this,a=false,g,c='<object width="1" height="1" style="display:none" '+d.getCodeBaseVersion(b)+">"+d.HTML+f.openTag+"/object>";if(!f.head){return a}f.head.insertBefore(document.createElement("object"),f.head.firstChild);f.head.firstChild.outerHTML=c;try{f.head.firstChild.classid=d.classID}catch(g){}try{if(f.head.firstChild.object){a=true}}catch(g){}try{if(a&&f.head.firstChild.readyState<4){f.garbage=true}}catch(g){}f.head.removeChild(f.head.firstChild);return a},codebaseSearch:function(f,b){var c=this;if(!c.ActiveXEnabled||!f){return null}if(f.BIfuncs&&f.BIfuncs.length&&f.BIfuncs[f.BIfuncs.length-1]!==null){c.callArray(f.BIfuncs)}var d,o=f.SEARCH,k={};if(c.isStrNum(b)){if(o.match&&o.min&&c.compareNums(b,o.min)<=0){return true}if(o.match&&o.max&&c.compareNums(b,o.max)>=0){return false}d=c.isActiveXObject(f,b);if(d&&(!o.min||c.compareNums(b,o.min)>0)){o.min=b}if(!d&&(!o.max||c.compareNums(b,o.max)<0)){o.max=b}return d};var e=[0,0,0,0],l=[].concat(o.digits),a=o.min?1:0,j,i,h,g,m,n=function(p,r){var q=[].concat(e);q[p]=r;return c.isActiveXObject(f,q.join(","))};if(o.max){g=o.max.split(c.splitNumRegx);for(j=0;j<g.length;j++){g[j]=parseInt(g[j],10)}if(g[0]<l[0]){l[0]=g[0]}}if(o.min){m=o.min.split(c.splitNumRegx);for(j=0;j<m.length;j++){m[j]=parseInt(m[j],10)}if(m[0]>e[0]){e[0]=m[0]}}if(m&&g){for(j=1;j<m.length;j++){if(m[j-1]!=g[j-1]){break}if(g[j]<l[j]){l[j]=g[j]}if(m[j]>e[j]){e[j]=m[j]}}}if(o.max){for(j=1;j<l.length;j++){if(g[j]>0&&l[j]==0&&l[j-1]<o.digits[j-1]){l[j-1]+=1;break}}};for(j=0;j<l.length;j++){h={};for(i=0;i<20;i++){if(l[j]-e[j]<1){break}d=round((l[j]+e[j])/2);if(h["a"+d]){break}h["a"+d]=1;if(n(j,d)){e[j]=d;a=1}else{l[j]=d}}l[j]=e[j];if(!a&&n(j,e[j])){a=1};if(!a){break}};return a?e.join(","):null},addWinEvent:function(d,c){var e=this,a=window,b;if(e.isFunc(c)){if(a.addEventListener){a.addEventListener(d,c,false)}else{if(a.attachEvent){a.attachEvent("on"+d,c)}else{b=a["on"+d];a["on"+d]=e.winHandler(c,b)}}}},winHandler:function(d,c){return function(){d();if(typeof c=="function"){c()}}},WLfuncs0:[],WLfuncs:[],runWLfuncs:function(a){var b={};a.winLoaded=true;a.callArray(a.WLfuncs0);a.callArray(a.WLfuncs);if(a.onDoneEmptyDiv){a.onDoneEmptyDiv()}},winLoaded:false,$$onWindowLoaded:function(a){return function(b){if(a.winLoaded){a.call(b)}else{a.fPush(b,a.WLfuncs)}}},div:null,divID:"plugindetect",divWidth:50,pluginSize:1,emptyDiv:function(){var d=this,b,h,c,a,f,g;if(d.div&&d.div.childNodes){for(b=d.div.childNodes.length-1;b>=0;b--){c=d.div.childNodes[b];if(c&&c.childNodes){for(h=c.childNodes.length-1;h>=0;h--){g=c.childNodes[h];try{c.removeChild(g)}catch(f){}}}if(c){try{d.div.removeChild(c)}catch(f){}}}}if(!d.div){a=document.getElementById(d.divID);if(a){d.div=a}}if(d.div&&d.div.parentNode){try{d.div.parentNode.removeChild(d.div)}catch(f){}d.div=null}},DONEfuncs:[],onDoneEmptyDiv:function(){var c=this,a,b;if(!c.winLoaded){return}if(c.WLfuncs&&c.WLfuncs.length&&c.WLfuncs[c.WLfuncs.length-1]!==null){return}for(a in c){b=c[a];if(b&&b.funcs){if(b.OTF==3){return}if(b.funcs.length&&b.funcs[b.funcs.length-1]!==null){return}}}for(a=0;a<c.DONEfuncs.length;a++){c.callArray(c.DONEfuncs)}
9954c.emptyDiv()},getWidth:function(c){if(c){var a=c.scrollWidth||c.offsetWidth,b=this;if(b.isNum(a)){return a}}return -1},getTagStatus:function(m,g,a,b){var c=this,f,k=m.span,l=c.getWidth(k),h=a.span,j=c.getWidth(h),d=g.span,i=c.getWidth(d);if(!k||!h||!d||!c.getDOMobj(m)){return -2}if(j<i||l<0||j<0||i<0||i<=c.pluginSize||c.pluginSize<1){return 0}if(l>=i){return -1}try{if(l==c.pluginSize&&(!c.isIE||c.getDOMobj(m).readyState==4)){if(!m.winLoaded&&c.winLoaded){return 1}if(m.winLoaded&&c.isNum(b)){if(!c.isNum(m.count)){m.count=b}if(b-m.count>=10){return 1}}}}catch(f){}return 0},getDOMobj:function(g,a){var f,d=this,c=g?g.span:0,b=c&&c.firstChild?1:0;try{if(b&&a){d.div.focus()}}catch(f){}return b?c.firstChild:null},setStyle:function(b,g){var f=b.style,a,d,c=this;if(f&&g){for(a=0;a<g.length;a=a+2){try{f[g[a]]=g[a+1]}catch(d){}}}},insertDivInBody:function(i,g){var f,c=this,h="pd33993399",b=null,d=g?window.top.document:window.document,a=d.getElementsByTagName("body")[0]||d.body;if(!a){try{d.write('<div id="'+h+'">.'+c.openTag+"/div>");b=d.getElementById(h)}catch(f){}}a=d.getElementsByTagName("body")[0]||d.body;if(a){a.insertBefore(i,a.firstChild);if(b){a.removeChild(b)}}},insertHTML:function(f,b,g,a,k){var l,m=document,j=this,p,o=m.createElement("span"),n,i;var c=["outlineStyle","none","borderStyle","none","padding","0px","margin","0px","visibility","visible"];var h="outline-style:none;border-style:none;padding:0px;margin:0px;visibility:visible;";if(!j.isDefined(a)){a=""}if(j.isString(f)&&(/[^\s]/).test(f)){f=f.toLowerCase().replace(/\s/g,"");p=j.openTag+f+' width="'+j.pluginSize+'" height="'+j.pluginSize+'" ';p+='style="'+h+'display:inline;" ';for(n=0;n<b.length;n=n+2){if(/[^\s]/.test(b[n+1])){p+=b[n]+'="'+b[n+1]+'" '}}p+=">";for(n=0;n<g.length;n=n+2){if(/[^\s]/.test(g[n+1])){p+=j.openTag+'param name="'+g[n]+'" value="'+g[n+1]+'" />'}}p+=a+j.openTag+"/"+f+">"}else{p=a}if(!j.div){i=m.getElementById(j.divID);if(i){j.div=i}else{j.div=m.createElement("div");j.div.id=j.divID}j.setStyle(j.div,c.concat(["width",j.divWidth+"px","height",(j.pluginSize+3)+"px","fontSize",(j.pluginSize+3)+"px","lineHeight",(j.pluginSize+3)+"px","verticalAlign","baseline","display","block"]));if(!i){j.setStyle(j.div,["position","absolute","right","0px","top","0px"]);j.insertDivInBody(j.div)}}if(j.div&&j.div.parentNode){j.setStyle(o,c.concat(["fontSize",(j.pluginSize+3)+"px","lineHeight",(j.pluginSize+3)+"px","verticalAlign","baseline","display","inline"]));try{o.innerHTML=p}catch(l){};try{j.div.appendChild(o)}catch(l){};return{span:o,winLoaded:j.winLoaded,tagName:f,outerHTML:p}}return{span:null,winLoaded:j.winLoaded,tagName:"",outerHTML:p}},Plugins:{quicktime:{mimeType:["video/quicktime","application/x-quicktimeplayer","image/x-macpaint","image/x-quicktime"],progID:"QuickTimeCheckObject.QuickTimeCheck.1",progID0:"QuickTime.QuickTime",classID:"clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B",minIEver:7,HTML:'<param name="src" value="" /><param name="controller" value="false" />',getCodeBaseVersion:function(a){return'codebase="#version='+a+'"'},SEARCH:{min:0,max:0,match:0,digits:[16,128,128,0]},getVersion:function(c){var f=this,d=f.$,a=null,e=null,b;if(!d.isIE){if(d.hasMimeType(f.mimeType)){e=d.OS!=3?d.findNavPlugin("QuickTime.*Plug-?in",0):null;if(e&&e.name){a=d.getNum(e.name)}}}else{if(d.isStrNum(c)){b=c.split(d.splitNumRegx);if(b.length>3&&parseInt(b[3],10)>0){b[3]="9999"}c=b.join(",")}if(d.isStrNum(c)&&d.verIE>=f.minIEver&&f.canUseIsMin()>0){f.installed=f.isMin(c);f.getVersionDone=0;return}f.getVersionDone=1;if(!a&&d.verIE>=f.minIEver){a=f.CDBASE2VER(d.codebaseSearch(f))}if(!a){e=d.getAXO(f.progID);if(e&&e.QuickTimeVersion){a=e.QuickTimeVersion.toString(16);a=parseInt(a.charAt(0),16)+"."+parseInt(a.charAt(1),16)+"."+parseInt(a.charAt(2),16)}}}f.installed=a?1:(e?0:-1);f.version=d.formatNum(a,3)},cdbaseUpper:["7,60,0,0","0,0,0,0"],cdbaseLower:["7,50,0,0",null],cdbase2ver:[function(c,b){var a=b.split(c.$.splitNumRegx);return[a[0],a[1].charAt(0),a[1].charAt(1),a[2]].join(",")},null],CDBASE2VER:function(f){var e=this,c=e.$,b,a=e.cdbaseUpper,d=e.cdbaseLower;
9954if(f){f=c.formatNum(f);for(b=0;b<a.length;b++){if(a[b]&&c.compareNums(f,a[b])<0&&d[b]&&c.compareNums(f,d[b])>=0&&e.cdbase2ver[b]){return e.cdbase2ver[b](e,f)}}}return f},canUseIsMin:function(){var f=this,d=f.$,b,c=f.canUseIsMin,a=f.cdbaseUpper,e=f.cdbaseLower;if(!c.value){c.value=-1;for(b=0;b<a.length;b++){if(a[b]&&d.codebaseSearch(f,a[b])){c.value=1;break}if(e[b]&&d.codebaseSearch(f,e[b])){c.value=-1;break}}}f.SEARCH.match=c.value==1?1:0;return c.value},isMin:function(c){var b=this,a=b.$;return a.codebaseSearch(b,c)?0.7:-1}},flash:{mimeType:"application/x-shockwave-flash",progID:"ShockwaveFlash.ShockwaveFlash",classID:"clsid:D27CDB6E-AE6D-11CF-96B8-444553540000",getVersion:function(){var b=function(i){if(!i){return null}var e=/[\d][\d\,\.\s]*[rRdD]{0,1}[\d\,]*/.exec(i);return e?e[0].replace(/[rRdD\.]/g,",").replace(/\s/g,""):null};var j=this,g=j.$,k,h,l=null,c=null,a=null,f,m,d;if(!g.isIE){m=g.hasMimeType(j.mimeType);if(m){f=g.getDOMobj(g.insertHTML("object",["type",j.mimeType],[],"",j));try{l=g.getNum(f.GetVariable("$version"))}catch(k){}}if(!l){d=m?m.enabledPlugin:null;if(d&&d.description){l=b(d.description)}if(l){l=g.getPluginFileVersion(d,l)}}}else{for(h=15;h>2;h--){c=g.getAXO(j.progID+"."+h);if(c){a=h.toString();break}}if(!c){c=g.getAXO(j.progID)}if(a=="6"){try{c.AllowScriptAccess="always"}catch(k){return"6,0,21,0"}}try{l=b(c.GetVariable("$version"))}catch(k){}if(!l&&a){l=a}}j.installed=l?1:-1;j.version=g.formatNum(l);return true}},shockwave:{mimeType:"application/x-director",progID:"SWCtl.SWCtl",classID:"clsid:166B1BCA-3F9C-11CF-8075-444553540000",getVersion:function(){var a=null,b=null,g,f,d=this,c=d.$;if(!c.isIE){f=c.findNavPlugin("Shockwave\\s*for\\s*Director");if(f&&f.description&&c.hasMimeType(d.mimeType)){a=c.getNum(f.description)}if(a){a=c.getPluginFileVersion(f,a)}}else{try{b=c.getAXO(d.progID).ShockwaveVersion("")}catch(g){}if(c.isString(b)&&b.length>0){a=c.getNum(b)}else{if(c.getAXO(d.progID+".8")){a="8"}else{if(c.getAXO(d.progID+".7")){a="7"}else{if(c.getAXO(d.progID+".1")){a="6"}}}}}d.installed=a?1:-1;d.version=c.formatNum(a)}},zz:0}};PluginDetect.initScript();
9955
9956	var gArgCountErr='The "%%" function requires an even number of arguments.\nArguments should be in the form "atttributeName", "attributeValue", ...',gTagAttrs=null,gQTGeneratorVersion=1;function AC_QuickTimeVersion(){return gQTGeneratorVersion}function _QTComplain(a,b){b=b.replace("%%",a);alert(b)}function _QTAddAttribute(a,b,c){var d;d=gTagAttrs[a+b];null==d&&(d=gTagAttrs[b]);return null!=d?(0==b.indexOf(a)&&null==c&&(c=b.substring(a.length)),null==c&&(c=b),c+'="'+d+'" '):""}function _QTAddObjectAttr(a,b){if(0==a.indexOf("emb#"))return"";0==a.indexOf("obj#")&&null==b&&(b=a.substring(4));return _QTAddAttribute("obj#",a,b)}function _QTAddEmbedAttr(a,b){if(0==a.indexOf("obj#"))return"";0==a.indexOf("emb#")&&null==b&&(b=a.substring(4));return _QTAddAttribute("emb#",a,b)}function _QTAddObjectParam(a,b){var c,d="",e=b?" />":">";-1==a.indexOf("emb#")&&(c=gTagAttrs["obj#"+a],null==c&&(c=gTagAttrs[a]),0==a.indexOf("obj#")&&(a=a.substring(4)),null!=c&&(d='  <param name="'+a+'" value="'+c+'"'+e+"\n"));return d}function _QTDeleteTagAttrs(){for(var a=0;a<arguments.length;a++){var b=arguments[a];delete gTagAttrs[b];delete gTagAttrs["emb#"+b];delete gTagAttrs["obj#"+b]}}function _QTGenerate(a,b,c){if(4>c.length||0!=c.length%2)return _QTComplain(a,gArgCountErr),"";gTagAttrs=[];gTagAttrs.src=c[0];gTagAttrs.width=c[1];gTagAttrs.height=c[2];gTagAttrs.classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B";gTagAttrs.pluginspage="http://www.apple.com/quicktime/download/";a=c[3];if(null==a||""==a)a="6,0,2,0";gTagAttrs.codebase="http://www.apple.com/qtactivex/qtplugin.cab#version="+a;for(var d,e=4;e<c.length;e+=2)d=c[e].toLowerCase(),a=c[e+1],"name"==d||"id"==d?gTagAttrs.name=a:gTagAttrs[d]=a;c="<object "+_QTAddObjectAttr("classid")+_QTAddObjectAttr("width")+_QTAddObjectAttr("height")+_QTAddObjectAttr("codebase")+_QTAddObjectAttr("name","id")+_QTAddObjectAttr("tabindex")+_QTAddObjectAttr("hspace")+_QTAddObjectAttr("vspace")+_QTAddObjectAttr("border")+_QTAddObjectAttr("align")+_QTAddObjectAttr("class")+_QTAddObjectAttr("title")+_QTAddObjectAttr("accesskey")+_QTAddObjectAttr("noexternaldata")+">\n"+_QTAddObjectParam("src",b);e="  <embed "+_QTAddEmbedAttr("src")+_QTAddEmbedAttr("width")+_QTAddEmbedAttr("height")+_QTAddEmbedAttr("pluginspage")+_QTAddEmbedAttr("name")+_QTAddEmbedAttr("align")+_QTAddEmbedAttr("tabindex");_QTDeleteTagAttrs("src","width","height","pluginspage","classid","codebase","name","tabindex","hspace","vspace","border","align","noexternaldata","class","title","accesskey");for(d in gTagAttrs)a=gTagAttrs[d],null!=a&&(e+=_QTAddEmbedAttr(d),c+=_QTAddObjectParam(d,b));return c+e+"> </embed>\n</object>"}function QT_GenerateOBJECTText(){return _QTGenerate("QT_GenerateOBJECTText",!1,arguments)};
9957
9958
9959	/*
9960		jQuery hashchange event v1.3
9961		https://github.com/cowboy/jquery-hashchange
9962		Copyright (c) 2010 "Cowboy" Ben Alman
9963		Dual licensed under the MIT and GPL licenses.
9964	*/
9965	(function(){function e(a){a=a||location.href;return"#"+a.replace(/^[^#]*#?(.*)$/,"$1")}var k=document,b,f=$.event.special,p=k.documentMode,m="oniLightBoxHashChange"in window&&(void 0===p||7<p);$.fn.iLightBoxHashChange=function(a){return a?this.bind("iLightBoxHashChange",a):this.trigger("iLightBoxHashChange")};$.fn.iLightBoxHashChange.delay=50;f.iLightBoxHashChange=$.extend(f.iLightBoxHashChange,{setup:function(){if(m)return!1;$(b.start)},teardown:function(){if(m)return!1;$(b.stop)}});b=function(){function a(){var c=
9966	e(),d=f(l);c!==l?(n(l=c,d),$(window).trigger("iLightBoxHashChange")):d!==l&&(location.href=location.href.replace(/#.*/,"")+d);g=setTimeout(a,$.fn.iLightBoxHashChange.delay)}var h={},g,l=e(),b=function(c){return c},n=b,f=b;h.start=function(){g||a()};h.stop=function(){g&&clearTimeout(g);g=void 0};browser.msie&&!m&&function(){var c,d;h.start=function(){c||(d=(d=$.fn.iLightBoxHashChange.src)&&d+e(),c=$('<iframe tabindex="-1" title="empty"/>').hide().one("load",function(){d||n(e());a()}).attr("src",d||
9967	"javascript:0").insertAfter("body")[0].contentWindow,k.onpropertychange=function(){try{"title"===event.propertyName&&(c.document.title=k.title)}catch(a){}})};h.stop=b;f=function(){return e(c.location.href)};n=function(a,d){var b=c.document,e=$.fn.iLightBoxHashChange.domain;
9967a!==d&&(b.title=k.title,b.open(),e&&b.write('<script>document.domain="'+e+'"\x3c/script>'),b.close(),c.location.hash=a)}}();return h}()})();
9968
9969	if (!Array.prototype.filter) {
9970		Array.prototype.filter = function(fun /*, thisp */ ) {
9971			"use strict";
9972
9973			if (this == null)
9974				throw new TypeError();
9975
9976			var t = Object(this);
9977			var len = t.length >>> 0;
9978			if (typeof fun != "function")
9979				throw new TypeError();
9980
9981			var res = [];
9982			var thisp = arguments[1];
9983			for (var i = 0; i < len; i++) {
9984				if (i in t) {
9985					var val = t[i]; // in case fun mutates this
9986					if (fun.call(thisp, val, i, t))
9987						res.push(val);
9988				}
9989			}
9990
9991			return res;
9992		};
9993	}
9994
9995	if (!Array.prototype.indexOf) {
9996		Array.prototype.indexOf = function(searchElement, fromIndex) {
9997			var k;
9998
9999			if (this == null) {
10000				throw new TypeError('"this" is null or not defined');
10001			}
10002
10003			var O = Object(this);
10004
10005			var len = O.length >>> 0;
10006
10007			if (len === 0) {
10008				return -1;
10009			}
10010
10011			var n = +fromIndex || 0;
10012
10013			if (abs(n) === Infinity) {
10014				n = 0;
10015			}
10016
10017			if (n >= len) {
10018				return -1;
10019			}
10020
10021			k = max(n >= 0 ? n : len - abs(n), 0);
10022
10023			while (k < len) {
10024				var kValue;
10025				if (k in O && O[k] === searchElement) {
10026					return k;
10027				}
10028				k++;
10029			}
10030			return -1;
10031		};
10032	}
10033
10034	if (!Array.prototype.lastIndexOf) {
10035		Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/ ) {
10036			"use strict";
10037
10038			if (this == null)
10039				throw new TypeError();
10040
10041			var t = Object(this);
10042			var len = t.length >>> 0;
10043			if (len === 0)
10044				return -1;
10045
10046			var n = len;
10047			if (arguments.length > 1) {
10048				n = Number(arguments[1]);
10049				if (n != n)
10050					n = 0;
10051				else if (n != 0 && n != (1 / 0) && n != -(1 / 0))
10052					n = (n > 0 || -1) * floor(abs(n));
10053			}
10054
10055			var k = n >= 0 ? min(n, len - 1) : len - abs(n);
10056
10057			for (; k >= 0; k--) {
10058				if (k in t && t[k] === searchElement)
10059					return k;
10060			}
10061			return -1;
10062		};
10063	}
10064})(jQuery, this);
10065
10066
10067/**
10068 * Owl carousel
vendor: 31,056 bytes, lines 10069-11268
10069 * @version 2.0.0-beta.3
10070 * @author Bartosz Wojciechowski
10071 * @license The MIT License (MIT)
10072 * @todo Lazy Load Icon
10073 * @todo prevent animationend bubling
10074 * @todo itemsScaleUp
10075 * @todo Test Zepto
10076 * @todo stagePadding calculate wrong active classes
10077 */
10078;(function($, window, document, undefined) {
10079
10080	/**
10081	 * Creates a carousel.
10082	 * @class The Owl Carousel.
10083	 * @public
10084	 * @param {HTMLElement|jQuery} element - The element to create the carousel for.
10085	 * @param {Object} [options] - The options
10086	 */
10087	function Owl(element, options) {
10088
10089		/**
10090		 * Current settings for the carousel.
10091		 * @public
10092		 */
10093		this.settings = null;
10094
10095		/**
10096		 * Current options set by the caller including defaults.
10097		 * @public
10098		 */
10099		this.options = $.extend({}, Owl.Defaults, options);
10100
10101		/**
10102		 * Plugin element.
10103		 * @public
10104		 */
10105		this.$element = $(element);
10106
10107		/**
10108		 * Proxied event handlers.
10109		 * @protected
10110		 */
10111		this._handlers = {};
10112
10113		/**
10114		 * References to the running plugins of this carousel.
10115		 * @protected
10116		 */
10117		this._plugins = {};
10118
10119		/**
10120		 * Currently suppressed events to prevent them from beeing retriggered.
10121		 * @protected
10122		 */
10123		this._supress = {};
10124
10125		/**
10126		 * Absolute current position.
10127		 * @protected
10128		 */
10129		this._current = null;
10130
10131		/**
10132		 * Animation speed in milliseconds.
10133		 * @protected
10134		 */
10135		this._speed = null;
10136
10137		/**
10138		 * Coordinates of all items in pixel.
10139		 * @todo The name of this member is missleading.
10140		 * @protected
10141		 */
10142		this._coordinates = [];
10143
10144		/**
10145		 * Current breakpoint.
10146		 * @todo Real media queries would be nice.
10147		 * @protected
10148		 */
10149		this._breakpoint = null;
10150
10151		/**
10152		 * Current width of the plugin element.
10153		 */
10154		this._width = null;
10155
10156		/**
10157		 * All real items.
10158		 * @protected
10159		 */
10160		this._items = [];
10161
10162		/**
10163		 * All cloned items.
10164		 * @protected
10165		 */
10166		this._clones = [];
10167
10168		/**
10169		 * Merge values of all items.
10170		 * @todo Maybe this could be part of a plugin.
10171		 * @protected
10172		 */
10173		this._mergers = [];
10174
10175		/**
10176		 * Widths of all items.
10177		 */
10178		this._widths = [];
10179
10180		/**
10181		 * Invalidated parts within the update process.
10182		 * @protected
10183		 */
10184		this._invalidated = {};
10185
10186		/**
10187		 * Ordered list of workers for the update process.
10188		 * @protected
10189		 */
10190		this._pipe = [];
10191
10192		/**
10193		 * Current state information for the drag operation.
10194		 * @todo #261
10195		 * @protected
10196		 */
10197		this._drag = {
10198			time: null,
10199			target: null,
10200			pointer: null,
10201			stage: {
10202				start: null,
10203				current: null
10204			},
10205			direction: null
10206		};
10207
10208		/**
10209		 * Current state information and their tags.
10210		 * @type {Object}
10211		 * @protected
10212		 */
10213		this._states = {
10214			current: {},
10215			tags: {
10216				'initializing': [ 'busy' ],
10217				'animating': [ 'busy' ],
10218				'dragging': [ 'interacting' ]
10219			}
10220		};
10221
10222		$.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) {
10223			this._handlers[handler] = $.proxy(this[handler], this);
10224		}, this));
10225
10226		$.each(Owl.Plugins, $.proxy(function(key, plugin) {
10227			this._plugins[key.charAt(0).toLowerCase() + key.slice(1)]
10228				= new plugin(this);
10229		}, this));
10230
10231		$.each(Owl.Workers, $.proxy(function(priority, worker) {
10232			this._pipe.push({
10233				'filter': worker.filter,
10234				'run': $.proxy(worker.run, this)
10235			});
10236		}, this));
10237
10238		this.setup();
10239		this.initialize();
10240	}
10241
10242	/**
10243	 * Default options for the carousel.
10244	 * @public
10245	 */
10246	Owl.Defaults = {
10247		items: 3,
10248		loop: false,
10249		center: false,
10250		rewind: false,
10251
10252		mouseDrag: true,
10253		touchDrag: true,
10254		pullDrag: true,
10255		freeDrag: false,
10256
10257		margin: 0,
10258		stagePadding: 0,
10259
10260		merge: false,
10261		mergeFit: true,
10262		autoWidth: false,
10263
10264		startPosition: 0,
10265		rtl: false,
10266
10267		smartSpeed: 250,
10268		fluidSpeed: false,
10269		dragEndSpeed: false,
10270
10271		responsive: {},
10272		responsiveRefreshRate: 200,
10273		responsiveBaseElement: window,
10274
10275		fallbackEasing: 'swing',
10276
10277		info: false,
10278
10279		nestedItemSelector: false,
10280		itemElement: 'div',
10281		stageElement: 'div',
10282
10283		refreshClass: 'owl-refresh',
10284		loadedClass: 'owl-loaded',
10285		loadingClass: 'owl-loading',
10286		rtlClass: 'owl-rtl',
10287		responsiveClass: 'owl-responsive',
10288		dragClass: 'owl-drag',
10289		itemClass: 'owl-item',
10290		stageClass: 'owl-stage',
10291		stageOuterClass: 'owl-stage-outer',
10292		grabClass: 'owl-grab'
10293	};
10294
10295	/**
10296	 * Enumeration for width.
10297	 * @public
10298	 * @readonly
10299	 * @enum {String}
10300	 */
10301	Owl.Width = {
10302		Default: 'default',
10303		Inner: 'inner',
10304		Outer: 'outer'
10305	};
10306
10307	/**
10308	 * Enumeration for types.
10309	 * @public
10310	 * @readonly
10311	 * @enum {String}
10312	 */
10313	Owl.Type = {
10314		Event: 'event',
10315		State: 'state'
10316	};
10317
10318	/**
10319	 * Contains all registered plugins.
10320	 * @public
10321	 */
10322	Owl.Plugins = {};
10323
10324	/**
10325	 * List of workers involved in the update process.
10326	 */
10327	Owl.Workers = [ {
10328		filter: [ 'width', 'settings' ],
10329		run: function() {
10330			this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width();
10331			//this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12);
10332		}
10333	}, {
10334		filter: [ 'width', 'items', 'settings' ],
10335		run: function(cache) {
10336			cache.current = this._items && this._items[this.relative(this._current)];
10337		}
10338	}, {
10339		filter: [ 'items', 'settings' ],
10340		run: function() {
10341			this.$stage.children('.cloned').remove();
10342		}
10343	}, {
10344		filter: [ 'width', 'items', 'settings' ],
10345		run: function(cache) {
10346			var margin = this.settings.margin || '',
10347				grid = !this.settings.autoWidth,
10348				rtl = this.settings.rtl,
10349				css = {
10350					'width': 'auto',
10351					'margin-left': rtl ? margin : '',
10352					'margin-right': rtl ? '' : margin
10353				};
10354
10355			!grid && this.$stage.children().css(css);
10356
10357			cache.css = css;
10358		}
10359	}, {
10360		filter: [ 'width', 'items', 'settings' ],
10361		run: function(cache) {
10362			var width = (this.width() / this.settings.items).toFixed(3) - this.settings.margin,
10363				merge = null,
10364				iterator = this._items.length,
10365				grid = !this.settings.autoWidth,
10366				widths = [];
10367
10368			cache.items = {
10369				merge: false,
10370				width: width
10371			};
10372
10373			while (iterator--) {
10374				merge = this._mergers[iterator];
10375				merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge;
10376
10377				cache.items.merge = merge > 1 || cache.items.merge;
10378
10379				widths[iterator] = !grid ? this._items[iterator].width() : width * merge;
10380			}
10381
10382			this._widths = widths;
10383		}
10384	}, {
10385		filter: [ 'items', 'settings' ],
10386		run: function() {
10387			var clones = [],
10388				items = this._items,
10389				settings = this.settings,
10390				view = Math.max(settings.items * 2, 4),
10391				size = Math.ceil(items.length / 2) * 2,
10392				repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0,
10393				append = '',
10394				prepend = '';
10395
10396			repeat /= 2;
10397
10398			while (repeat--) {
10399				clones.push(this.normalize(clones.length / 2, true));
10400				append = append + items[clones[clones.length - 1]][0].outerHTML;
10401				clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true));
10402				prepend = items[clones[clones.length - 1]][0].outerHTML + prepend;
10403			}
10404
10405			this._clones = clones;
10406
10407			// var appendVideo = $(append).find('.uncode-video-container');
10408			// if (appendVideo.length) {
10409			// 	appendVideo.attr('data-id', Math.round(Math.random() * 100000));
10410			// }
10411			// var prependVideo = $(prepend).find('.uncode-video-container');
10412			// if (prependVideo.length) {
10413			// 	prependVideo.attr('data-id', Math.round(Math.random() * 100000));
10414			// }
10415			$(append).addClass('cloned').appendTo(this.$stage);
10416			$(prepend).addClass('cloned').prependTo(this.$stage);
10417		}
10418	}, {
10419		filter: [ 'width', 'items', 'settings' ],
10420		run: function() {
10421			var rtl = this.settings.rtl ? 1 : -1,
10422				size = this._clones.length + this._items.length,
10423				iterator = -1,
10424				previous = 0,
10425				current = 0,
10426				coordinates = [];
10427
10428			while (++iterator < size) {
10429				previous = coordinates[iterator - 1] || 0;
10430				current = this._widths[this.relative(iterator)] + this.settings.margin;
10431				coordinates.push(previous + current * rtl);
10432			}
10433
10434			this._coordinates = coordinates;
10435		}
10436	}, {
10437		filter: [ 'width', 'items', 'settings' ],
10438		run: function() {
10439			var padding = this.settings.stagePadding,
10440				coordinates = this._coordinates,
10441				css = {
10442					'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2,
10443					'padding-left': padding || '',
10444					'padding-right': padding || ''
10445				};
10446
10447			this.$stage.css(css);
10448		}
10449	}, {
10450		filter: [ 'width', 'items', 'settings' ],
10451		run: function(cache) {
10452			var iterator = this._coordinates.length,
10453				grid = !this.settings.autoWidth,
10454				items = this.$stage.children();
10455
10456			if (grid && cache.items.merge) {
10457				while (iterator--) {
10458					cache.css.width = this._widths[this.relative(iterator)];
10459					items.eq(iterator).css(cache.css);
10460				}
10461			} else if (grid) {
10462				cache.css.width = cache.items.width;
10463				items.css(cache.css);
10464			}
10465		}
10466	}, {
10467		filter: [ 'items' ],
10468		run: function() {
10469			this._coordinates.length < 1 && this.$stage.removeAttr('style');
10470		}
10471	}, {
10472		filter: [ 'width', 'items', 'settings' ],
10473		run: function(cache) {
10474			cache.current = cache.current ? this.$stage.children().index(cache.current) : 0;
10475			cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current));
10476			this.reset(cache.current);
10477		}
10478	}, {
10479		filter: [ 'position' ],
10480		run: function() {
10481			this.animate(this.coordinates(this._current));
10482		}
10483	}, {
10484		filter: [ 'width', 'position', 'items', 'settings' ],
10485		run: function() {
10486			var rtl = this.settings.rtl ? 1 : -1,
10487				padding = this.settings.stagePadding * 2,
10488				begin = this.coordinates(this.current()) + padding,
10489				end = begin + this.width() * rtl,
10490				inner, outer, matches = [], i, n;
10491
10492			for (i = 0, n = this._coordinates.length; i < n; i++) {
10493				inner = this._coordinates[i - 1] || 0;
10494				outer = Math.abs(this._coordinates[i]) + padding * rtl;
10495
10496				if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end)))
10497					|| (this.op(outer, '<', begin) && this.op(outer, '>', end))) {
10498					matches.push(i);
10499				}
10500			}
10501
10502			this.$stage.children('.active').removeClass('active');
10503			this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active');
10504
10505			if (this.settings.center) {
10506				this.$stage.children('.center').removeClass('center');
10507				this.$stage.children().eq(this.current()).addClass('center');
10508			}
10509		}
10510	} ];
10511
10512	/**
10513	 * Initializes the carousel.
10514	 * @protected
10515	 */
10516	Owl.prototype.initialize = function() {
10517		this.enter('initializing');
10518		this.trigger('initialize');
10519
10520		this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl);
10521
10522		if (this.settings.autoWidth && !this.is('pre-loading')) {
10523			var imgs, nestedSelector, width;
10524			imgs = this.$element.find('img');
10525			nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined;
10526			width = this.$element.children(nestedSelector).width();
10527
10528			if (imgs.length && width <= 0) {
10529				this.preloadAutoWidthImages(imgs);
10530			}
10531		}
10532
10533		this.$element.addClass(this.options.loadingClass);
10534
10535		// create stage
10536		this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>')
10537			.wrap('<div class="' + this.settings.stageOuterClass + '"/>');
10538
10539		// append stage
10540		this.$element.append(this.$stage.parent());
10541
10542		// append content
10543		this.replace(this.$element.children().not(this.$stage.parent()));
10544
10545		// check visibility
10546		if (this.$element.is(':visible')) {
10547			// update view
10548			this.refresh();
10549		} else {
10550			// invalidate width
10551			this.invalidate('width');
10552		}
10553
10554		this.$element
10555			.removeClass(this.options.loadingClass)
10556			.addClass(this.options.loadedClass);
10557
10558		// register event handlers
10559		this.registerEventHandlers();
10560
10561		this.leave('initializing');
10562		this.trigger('initialized');
10563	};
10564
10565	/**
10566	 * Setups the current settings.
10567	 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8?
10568	 * @todo Support for media queries by using `matchMedia` would be nice.
10569	 * @public
10570	 */
10571	Owl.prototype.setup = function() {
10572		var viewport = this.viewport(),
10573			overwrites = this.options.responsive,
10574			match = -1,
10575			settings = null;
10576
10577		if (!overwrites) {
10578			settings = $.extend({}, this.options);
10579		} else {
10580			$.each(overwrites, function(breakpoint) {
10581				if (breakpoint <= viewport && breakpoint > match) {
10582					match = Number(breakpoint);
10583				}
10584			});
10585
10586			settings = $.extend({}, this.options, overwrites[match]);
10587			delete settings.responsive;
10588
10589			// responsive class
10590			if (settings.responsiveClass) {
10591				this.$element.attr('class',
10592					this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match)
10593				);
10594			}
10595		}
10596
10597		if (this.settings === null || this._breakpoint !== match) {
10598			this.trigger('change', { property: { name: 'settings', value: settings } });
10599			this._breakpoint = match;
10600			this.settings = settings;
10601			this.invalidate('settings');
10602			this.trigger('changed', { property: { name: 'settings', value: this.settings } });
10603		}
10604	};
10605
10606	/**
10607	 * Updates option logic if necessery.
10608	 * @protected
10609	 */
10610	Owl.prototype.optionsLogic = function() {
10611		if (this.settings.autoWidth) {
10612			this.settings.stagePadding = false;
10613			this.settings.merge = false;
10614		}
10615	};
10616
10617	/**
10618	 * Prepares an item before add.
10619	 * @todo Rename event parameter `content` to `item`.
10620	 * @protected
10621	 * @returns {jQuery|HTMLElement} - The item container.
10622	 */
10623	Owl.prototype.prepare = function(item, index) {
10624		var event = this.trigger('prepare', { content: item });
10625		if (!event.data) {
10626			event.data = $('<' + this.settings.itemElement + '/>')
10627				.addClass(this.options.itemClass).attr('data-index', index + 1).append(item)
10628		}
10629
10630		this.trigger('prepared', { content: event.data });
10631
10632		return event.data;
10633	};
10634
10635	/**
10636	 * Updates the view.
10637	 * @public
10638	 */
10639	Owl.prototype.update = function() {
10640		var i = 0,
10641			n = this._pipe.length,
10642			filter = $.proxy(function(p) { return this[p] }, this._invalidated),
10643			cache = {};
10644
10645		while (i < n) {
10646			if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) {
10647				this._pipe[i].run(cache);
10648			}
10649			i++;
10650		}
10651
10652		this._invalidated = {};
10653
10654		!this.is('valid') && this.enter('valid');
10655	};
10656
10657	/**
10658	 * Gets the width of the view.
10659	 * @public
10660	 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return.
10661	 * @returns {Number} - The width of the view in pixel.
10662	 */
10663	Owl.prototype.width = function(dimension) {
10664		dimension = dimension || Owl.Width.Default;
10665		switch (dimension) {
10666			case Owl.Width.Inner:
10667			case Owl.Width.Outer:
10668				return this._width;
10669			default:
10670				return this._width - this.settings.stagePadding * 2 + this.settings.margin;
10671		}
10672	};
10673
10674	/**
10675	 * Refreshes the carousel primarily for adaptive purposes.
10676	 * @public
10677	 */
10678	Owl.prototype.refresh = function() {
10679		this.enter('refreshing');
10680		this.trigger('refresh');
10681
10682		this.setup();
10683
10684		this.optionsLogic();
10685
10686		this.$element.addClass(this.options.refreshClass);
10687
10688		this.update();
10689
10690		this.$element.removeClass(this.options.refreshClass);
10691
10692		this.leave('refreshing');
10693		this.trigger('refreshed');
10694	};
10695
10696	/**
10697	 * Checks window `resize` event.
10698	 * @protected
10699	 */
10700	Owl.prototype.onThrottledResize = function() {
10701		window.clearTimeout(this.resizeTimer);
10702		this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate);
10703	};
10704
10705	/**
10706	 * Checks window `resize` event.
10707	 * @protected
10708	 */
10709	Owl.prototype.onResize = function() {
10710		if (!this._items.length) {
10711			return false;
10712		}
10713
10714		if (this._width === this.$element.width()) {
10715			return false;
10716		}
10717
10718		if (!this.$element.is(':visible')) {
10719			return false;
10720		}
10721
10722		this.enter('resizing');
10723
10724		if (this.trigger('resize').isDefaultPrevented()) {
10725			this.leave('resizing');
10726			return false;
10727		}
10728
10729		this.invalidate('width');
10730
10731		this.refresh();
10732
10733		this.leave('resizing');
10734		this.trigger('resized');
10735	};
10736
10737	/**
10738	 * Registers event handlers.
10739	 * @todo Check `msPointerEnabled`
10740	 * @todo #261
10741	 * @protected
10742	 */
10743	Owl.prototype.registerEventHandlers = function() {
10744		if ($.support.transition) {
10745			this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this));
10746		}
10747
10748		if (this.settings.responsive !== false) {
10749			this.on(window, 'resize', this._handlers.onThrottledResize);
10750		}
10751
10752		if (this.settings.mouseDrag) {
10753			this.$element.addClass(this.options.dragClass);
10754			this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this));
10755			this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false });
10756		}
10757
10758		if (this.settings.touchDrag){
10759			this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this));
10760			this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this));
10761		}
10762	};
10763
10764	/**
10765	 * Handles `touchstart` and `mousedown` events.
10766	 * @todo Horizontal swipe threshold as option
10767	 * @todo #261
10768	 * @protected
10769	 * @param {Event} event - The event arguments.
10770	 */
10771	Owl.prototype.onDragStart = function(event) {
10772		var stage = null;
10773
10774		if (event.which === 3) {
10775			return;
10776		}
10777
10778		if ($.support.transform) {
10779			stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(',');
10780			stage = {
10781				x: stage[stage.length === 16 ? 12 : 4],
10782				y: stage[stage.length === 16 ? 13 : 5]
10783			};
10784		} else {
10785			stage = this.$stage.position();
10786			stage = {
10787				x: this.settings.rtl ?
10788					stage.left + this.$stage.width() - this.width() + this.settings.margin :
10789					stage.left,
10790				y: stage.top
10791			};
10792		}
10793
10794		if (this.is('animating')) {
10795			$.support.transform ? this.animate(stage.x) : this.$stage.stop()
10796			this.invalidate('position');
10797		}
10798
10799		this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown');
10800
10801		this.speed(0);
10802
10803		this._drag.time = new Date().getTime();
10804		this._drag.target = $(event.target);
10805		this._drag.stage.start = stage;
10806		this._drag.stage.current = stage;
10807		this._drag.pointer = this.pointer(event);
10808
10809		$(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this));
10810
10811		$(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) {
10812			var delta = this.difference(this._drag.pointer, this.pointer(event));
10813
10814			$(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this));
10815
10816			if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) {
10817				return;
10818			}
10819
10820			event.preventDefault();
10821
10822			this.enter('dragging');
10823			this.trigger('drag');
10824		}, this));
10825	};
10826
10827	/**
10828	 * Handles the `touchmove` and `mousemove` events.
10829	 * @todo #261
10830	 * @protected
10831	 * @param {Event} event - The event arguments.
10832	 */
10833	Owl.prototype.onDragMove = function(event) {
10834		var minimum = null,
10835			maximum = null,
10836			pull = null,
10837			delta = this.difference(this._drag.pointer, this.pointer(event)),
10838			stage = this.difference(this._drag.stage.start, delta);
10839
10840		if (!this.is('dragging')) {
10841			return;
10842		}
10843
10844		event.preventDefault();
10845
10846		if (this.settings.loop) {
10847			minimum = this.coordinates(this.minimum());
10848			maximum = this.coordinates(this.maximum() + 1) - minimum;
10849			stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum;
10850		} else {
10851			minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum());
10852			maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum());
10853			pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0;
10854			stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull);
10855		}
10856
10857		this._drag.stage.current = stage;
10858
10859		this.animate(stage.x);
10860	};
10861
10862	/**
10863	 * Handles the `touchend` and `mouseup` events.
10864	 * @todo #261
10865	 * @todo Threshold for click event
10866	 * @protected
10867	 * @param {Event} event - The event arguments.
10868	 */
10869	Owl.prototype.onDragEnd = function(event) {
10870		var delta = this.difference(this._drag.pointer, this.pointer(event)),
10871			stage = this._drag.stage.current,
10872			direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right';
10873
10874		$(document).off('.owl.core');
10875
10876		this.$element.removeClass(this.options.grabClass);
10877
10878		if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) {
10879			this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed);
10880			this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction));
10881			this.invalidate('position');
10882			this.update();
10883
10884			this._drag.direction = direction;
10885
10886			if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) {
10887				this._drag.target.one('click.owl.core', function() { return false; });
10888			}
10889		}
10890
10891		if (!this.is('dragging')) {
10892			return;
10893		}
10894
10895		this.leave('dragging');
10896		this.trigger('dragged');
10897	};
10898
10899	/**
10900	 * Gets absolute position of the closest item for a coordinate.
10901	 * @todo Setting `freeDrag` makes `closest` not reusable. See #165.
10902	 * @protected
10903	 * @param {Number} coordinate - The coordinate in pixel.
10904	 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`.
10905	 * @return {Number} - The absolute position of the closest item.
10906	 */
10907	Owl.prototype.closest = function(coordinate, direction) {
10908		var position = -1,
10909			pull = 30,
10910			width = this.width(),
10911			coordinates = this.coordinates();
10912
10913		if (!this.settings.freeDrag) {
10914			// check closest item
10915			$.each(coordinates, $.proxy(function(index, value) {
10916				if (coordinate > value - pull && coordinate < value + pull) {
10917					position = index;
10918				} else if (this.op(coordinate, '<', value)
10919					&& this.op(coordinate, '>', coordinates[index + 1] || value - width)) {
10920					position = direction === 'left' ? index + 1 : index;
10921				}
10922				return position === -1;
10923			}, this));
10924		}
10925
10926		if (!this.settings.loop) {
10927			// non loop boundries
10928			if (this.op(coordinate, '>', coordinates[this.minimum()])) {
10929				position = coordinate = this.minimum();
10930			} else if (this.op(coordinate, '<', coordinates[this.maximum()])) {
10931				position = coordinate = this.maximum();
10932			}
10933		}
10934
10935		return position;
10936	};
10937
10938	/**
10939	 * Animates the stage.
10940	 * @todo #270
10941	 * @public
10942	 * @param {Number} coordinate - The coordinate in pixels.
10943	 */
10944	Owl.prototype.animate = function(coordinate) {
10945		var animate = this.speed() > 0;
10946
10947		this.is('animating') && this.onTransitionEnd();
10948
10949		if (animate) {
10950			this.enter('animating');
10951			this.trigger('translate');
10952		}
10953
10954		if ($.support.transform3d && $.support.transition) {
10955			this.$stage.css({
10956				transform: 'translate3d(' + coordinate + 'px,0px,0px)',
10957				transition: (this.speed() / 1000) + 's'
10958			});
10959		} else if (animate) {
10960			this.$stage.animate({
10961				left: coordinate + 'px'
10962			}, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this));
10963		} else {
10964			this.$stage.css({
10965				left: coordinate + 'px'
10966			});
10967		}
10968	};
10969
10970	/**
10971	 * Checks whether the carousel is in a specific state or not.
10972	 * @param {String} state - The state to check.
10973	 * @returns {Boolean} - The flag which indicates if the carousel is busy.
10974	 */
10975	Owl.prototype.is = function(state) {
10976		return this._states.current[state] && this._states.current[state] > 0;
10977	};
10978
10979	/**
10980	 * Sets the absolute position of the current item.
10981	 * @public
10982	 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged.
10983	 * @returns {Number} - The absolute position of the current item.
10984	 */
10985	Owl.prototype.current = function(position) {
10986		if (position === undefined) {
10987			return this._current;
10988		}
10989
10990		if (this._items.length === 0) {
10991			return undefined;
10992		}
10993
10994		position = this.normalize(position);
10995
10996		if (this._current !== position) {
10997			var event = this.trigger('change', { property: { name: 'position', value: position } });
10998
10999			if (event.data !== undefined) {
11000				position = this.normalize(event.data);
11001			}
11002
11003			this._current = position;
11004
11005			this.invalidate('position');
11006
11007			this.trigger('changed', { property: { name: 'position', value: this._current } });
11008		}
11009
11010		return this._current;
11011	};
11012
11013	/**
11014	 * Invalidates the given part of the update routine.
11015	 * @param {String} [part] - The part to invalidate.
11016	 * @returns {Array.<String>} - The invalidated parts.
11017	 */
11018	Owl.prototype.invalidate = function(part) {
11019		if ($.type(part) === 'string') {
11020			this._invalidated[part] = true;
11021			this.is('valid') && this.leave('valid');
11022		}
11023		return $.map(this._invalidated, function(v, i) { return i });
11024	};
11025
11026	/**
11027	 * Resets the absolute position of the current item.
11028	 * @public
11029	 * @param {Number} position - The absolute position of the new item.
11030	 */
11031	Owl.prototype.reset = function(position) {
11032		position = this.normalize(position);
11033
11034		if (position === undefined) {
11035			return;
11036		}
11037
11038		this._speed = 0;
11039		this._current = position;
11040
11041		this.suppress([ 'translate', 'translated' ]);
11042
11043		this.animate(this.coordinates(position));
11044
11045		this.release([ 'translate', 'translated' ]);
11046	};
11047
11048	/**
11049	 * Normalizes an absolute or a relative position of an item.
11050	 * @public
11051	 * @param {Number} position - The absolute or relative position to normalize.
11052	 * @param {Boolean} [relative=false] - Whether the given position is relative or not.
11053	 * @returns {Number} - The normalized position.
11054	 */
11055	Owl.prototype.normalize = function(position, relative) {
11056		var n = this._items.length,
11057			m = relative ? 0 : this._clones.length;
11058
11059		if (!$.isNumeric(position) || n < 1) {
11060			position = undefined;
11061		} else if (position < 0 || position >= n + m) {
11062			position = ((position - m / 2) % n + n) % n + m / 2;
11063		}
11064
11065		return position;
11066	};
11067
11068	/**
11069	 * Converts an absolute position of an item into a relative one.
11070	 * @public
11071	 * @param {Number} position - The absolute position to convert.
11072	 * @returns {Number} - The converted position.
11073	 */
11074	Owl.prototype.relative = function(position) {
11075		position -= this._clones.length / 2;
11076		return this.normalize(position, true);
11077	};
11078
11079	/**
11080	 * Gets the maximum position for the current item.
11081	 * @public
11082	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
11083	 * @returns {Number}
11084	 */
11085	Owl.prototype.maximum = function(relative) {
11086		var settings = this.settings,
11087			maximum = this._coordinates.length,
11088			boundary = Math.abs(this._coordinates[maximum - 1]) - this._width,
11089			i = -1, j;
11090
11091		if (settings.loop) {
11092			maximum = this._clones.length / 2 + this._items.length - 1;
11093		} else if (settings.autoWidth || settings.merge) {
11094			// binary search
11095			while (maximum - i > 1) {
11096				Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary
11097					? i = j : maximum = j;
11098			}
11099		} else if (settings.center) {
11100			maximum = this._items.length - 1;
11101		} else {
11102			maximum = this._items.length - settings.items;
11103		}
11104
11105		if (relative) {
11106			maximum -= this._clones.length / 2;
11107		}
11108
11109		return Math.max(maximum, 0);
11110	};
11111
11112	/**
11113	 * Gets the minimum position for the current item.
11114	 * @public
11115	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
11116	 * @returns {Number}
11117	 */
11118	Owl.prototype.minimum = function(relative) {
11119		return relative ? 0 : this._clones.length / 2;
11120	};
11121
11122	/**
11123	 * Gets an item at the specified relative position.
11124	 * @public
11125	 * @param {Number} [position] - The relative position of the item.
11126	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
11127	 */
11128	Owl.prototype.items = function(position) {
11129		if (position === undefined) {
11130			return this._items.slice();
11131		}
11132
11133		position = this.normalize(position, true);
11134		return this._items[position];
11135	};
11136
11137	/**
11138	 * Gets an item at the specified relative position.
11139	 * @public
11140	 * @param {Number} [position] - The relative position of the item.
11141	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
11142	 */
11143	Owl.prototype.mergers = function(position) {
11144		if (position === undefined) {
11145			return this._mergers.slice();
11146		}
11147
11148		position = this.normalize(position, true);
11149		return this._mergers[position];
11150	};
11151
11152	/**
11153	 * Gets the absolute positions of clones for an item.
11154	 * @public
11155	 * @param {Number} [position] - The relative position of the item.
11156	 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given.
11157	 */
11158	Owl.prototype.clones = function(position) {
11159		var odd = this._clones.length / 2,
11160			even = odd + this._items.length,
11161			map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 };
11162
11163		if (position === undefined) {
11164			return $.map(this._clones, function(v, i) { return map(i) });
11165		}
11166
11167		return $.map(this._clones, function(v, i) { return v === position ? map(i) : null });
11168	};
11169
11170	/**
11171	 * Sets the current animation speed.
11172	 * @public
11173	 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged.
11174	 * @returns {Number} - The current animation speed in milliseconds.
11175	 */
11176	Owl.prototype.speed = function(speed) {
11177		if (speed !== undefined) {
11178			this._speed = speed;
11179		}
11180
11181		return this._speed;
11182	};
11183
11184	/**
11185	 * Gets the coordinate of an item.
11186	 * @todo The name of this method is missleanding.
11187	 * @public
11188	 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`.
11189	 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates.
11190	 */
11191	Owl.prototype.coordinates = function(position) {
11192		var coordinate = null;
11193
11194		if (position === undefined) {
11195			return $.map(this._coordinates, $.proxy(function(coordinate, index) {
11196				return this.coordinates(index);
11197			}, this));
11198		}
11199
11200		if (this.settings.center) {
11201			coordinate = this._coordinates[position];
11202			coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1);
11203		} else {
11204			coordinate = this._coordinates[position - 1] || 0;
11205		}
11206
11207		return coordinate;
11208	};
11209
11210	/**
11211	 * Calculates the speed for a translation.
11212	 * @protected
11213	 * @param {Number} from - The absolute position of the start item.
11214	 * @param {Number} to - The absolute position of the target item.
11215	 * @param {Number} [factor=undefined] - The time factor in milliseconds.
11216	 * @returns {Number} - The time in milliseconds for the translation.
11217	 */
11218	Owl.prototype.duration = function(from, to, factor) {
11219		return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed));
11220	};
11221
11222	/**
11223	 * Slides to the specified item.
11224	 * @public
11225	 * @param {Number} position - The position of the item.
11226	 * @param {Number} [speed] - The time in milliseconds for the transition.
11227	 */
11228	Owl.prototype.to = function(position, speed) {
11229		var current = this.current(),
11230			revert = null,
11231			distance = position - this.relative(current),
11232			direction = (distance > 0) - (distance < 0),
11233			items = this._items.length,
11234			minimum = this.minimum(),
11235			maximum = this.maximum();
11236
11237		if (this.settings.loop) {
11238			if (!this.settings.rewind && Math.abs(distance) > items / 2) {
11239				distance += direction * -1 * items;
11240			}
11241
11242			position = current + distance;
11243			revert = ((position - minimum) % items + items) % items + minimum;
11244
11245			if (revert !== position && revert - distance <= maximum && revert - distance > 0) {
11246				current = revert - distance;
11247				position = revert;
11248				this.reset(current);
11249			}
11250		} else if (this.settings.rewind) {
11251			maximum += 1;
11252			position = (position % maximum + maximum) % maximum;
11253		} else {
11254			position = Math.max(minimum, Math.min(maximum, position));
11255		}
11256
11257		this.speed(this.duration(current, position, speed));
11258		this.current(position);
11259
11260		if (this.$element.is(':visible')) {
11261			this.update();
11262		}
11263	};
11264
11265	/**
11266	 * Slides to the next item.
11267	 * @public
11268	 * @param {Number}
vendor: 4,086 bytes, lines 11268-11404
11268 [speed] - The time in milliseconds for the transition.
11269	 */
11270	Owl.prototype.next = function(speed) {
11271		speed = speed || false;
11272		this.to(this.relative(this.current()) + 1, speed);
11273	};
11274
11275	/**
11276	 * Slides to the previous item.
11277	 * @public
11278	 * @param {Number} [speed] - The time in milliseconds for the transition.
11279	 */
11280	Owl.prototype.prev = function(speed) {
11281		speed = speed || false;
11282		this.to(this.relative(this.current()) - 1, speed);
11283	};
11284
11285	/**
11286	 * Handles the end of an animation.
11287	 * @protected
11288	 * @param {Event} event - The event arguments.
11289	 */
11290	Owl.prototype.onTransitionEnd = function(event) {
11291
11292		// if css2 animation then event object is undefined
11293		if (event !== undefined) {
11294			event.stopPropagation();
11295
11296			// Catch only owl-stage transitionEnd event
11297			if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) {
11298				return false;
11299			}
11300		}
11301
11302		this.leave('animating');
11303		this.trigger('translated');
11304	};
11305
11306	/**
11307	 * Gets viewport width.
11308	 * @protected
11309	 * @return {Number} - The width in pixel.
11310	 */
11311	Owl.prototype.viewport = function() {
11312		var width;
11313		if (this.options.responsiveBaseElement !== window) {
11314			width = $(this.options.responsiveBaseElement).width();
11315		} else if (window.innerWidth) {
11316			width = window.innerWidth;
11317		} else if (document.documentElement && document.documentElement.clientWidth) {
11318			width = document.documentElement.clientWidth;
11319		} else {
11320			throw 'Can not detect viewport width.';
11321		}
11322
11323		return width;
11324	};
11325
11326	/**
11327	 * Replaces the current content.
11328	 * @public
11329	 * @param {HTMLElement|jQuery|String} content - The new content.
11330	 */
11331	Owl.prototype.replace = function(content) {
11332		this.$stage.empty();
11333		this._items = [];
11334
11335		if (content) {
11336			content = (content instanceof jQuery) ? content : $(content);
11337		}
11338
11339		if (this.settings.nestedItemSelector) {
11340			content = content.find('.' + this.settings.nestedItemSelector);
11341		}
11342
11343		content.filter(function() {
11344			return this.nodeType === 1;
11345		}).each($.proxy(function(index, item) {
11346			item = this.prepare(item, index);
11347			this.$stage.append(item);
11348			this._items.push(item);
11349			this._mergers.push(item.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
11350		}, this));
11351
11352		this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0);
11353
11354		this.invalidate('items');
11355	};
11356
11357	/**
11358	 * Adds an item.
11359	 * @todo Use `item` instead of `content` for the event arguments.
11360	 * @public
11361	 * @param {HTMLElement|jQuery|String} content - The item content to add.
11362	 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end.
11363	 */
11364	Owl.prototype.add = function(content, position) {
11365		var current = this.relative(this._current);
11366
11367		position = position === undefined ? this._items.length : this.normalize(position, true);
11368		content = content instanceof jQuery ? content : $(content);
11369
11370		this.trigger('add', { content: content, position: position });
11371
11372		content = this.prepare(content, this._items[current].index());
11373
11374		if (this._items.length === 0 || position === this._items.length) {
11375			this._items.length === 0 && this.$stage.append(content);
11376			this._items.length !== 0 && this._items[position - 1].after(content);
11377			this._items.push(content);
11378			this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
11379		} else {
11380			this._items[position].before(content);
11381			this._items.splice(position, 0, content);
11382			this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
11383		}
11384
11385		this._items[current] && this.reset(this._items[current].index());
11386
11387		this.invalidate('items');
11388
11389		this.trigger('added', { content: content, position: position });
11390	};
11391
11392	/**
11393	 * Removes an item by its position.
11394	 * @todo Use `item` instead of `content` for the event arguments.
11395	 * @public
11396	 * @param {Number} position - The relative position of the item to remove.
11397	 */
11398	Owl.prototype.remove = function(position) {
11399		position = this.normalize(position, true);
11400
11401		if (position === undefined) {
11402			return;
11403		}
11404
vendor: 40,434 bytes, lines 11405-12971
11405		this.trigger('remove', { content: this._items[position], position: position });
11406
11407		this._items[position].remove();
11408		this._items.splice(position, 1);
11409		this._mergers.splice(position, 1);
11410
11411		this.invalidate('items');
11412
11413		this.trigger('removed', { content: null, position: position });
11414	};
11415
11416	/**
11417	 * Preloads images with auto width.
11418	 * @todo Replace by a more generic approach
11419	 * @protected
11420	 */
11421	Owl.prototype.preloadAutoWidthImages = function(images) {
11422		images.each($.proxy(function(i, element) {
11423			this.enter('pre-loading');
11424			element = $(element);
11425			$(new Image()).one('load', $.proxy(function(e) {
11426				element.attr('src', e.target.src);
11427				element.css('opacity', 1);
11428				this.leave('pre-loading');
11429				!this.is('pre-loading') && !this.is('initializing') && this.refresh();
11430			}, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina'));
11431		}, this));
11432	};
11433
11434	/**
11435	 * Destroys the carousel.
11436	 * @public
11437	 */
11438	Owl.prototype.destroy = function() {
11439
11440		this.$element.off('.owl.core');
11441		this.$stage.off('.owl.core');
11442		$(document).off('.owl.core');
11443
11444		if (this.settings.responsive !== false) {
11445			window.clearTimeout(this.resizeTimer);
11446			this.off(window, 'resize', this._handlers.onThrottledResize);
11447		}
11448
11449		for (var i in this._plugins) {
11450			this._plugins[i].destroy();
11451		}
11452
11453		this.$stage.children('.cloned').remove();
11454
11455		this.$stage.unwrap();
11456		this.$stage.children().contents().unwrap();
11457		this.$stage.children().unwrap();
11458
11459		this.$element
11460			.removeClass(this.options.refreshClass)
11461			.removeClass(this.options.loadingClass)
11462			.removeClass(this.options.loadedClass)
11463			.removeClass(this.options.rtlClass)
11464			.removeClass(this.options.dragClass)
11465			.removeClass(this.options.grabClass)
11466			.attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), ''))
11467			.removeData('owl.carousel');
11468	};
11469
11470	/**
11471	 * Operators to calculate right-to-left and left-to-right.
11472	 * @protected
11473	 * @param {Number} [a] - The left side operand.
11474	 * @param {String} [o] - The operator.
11475	 * @param {Number} [b] - The right side operand.
11476	 */
11477	Owl.prototype.op = function(a, o, b) {
11478		var rtl = this.settings.rtl;
11479		switch (o) {
11480			case '<':
11481				return rtl ? a > b : a < b;
11482			case '>':
11483				return rtl ? a < b : a > b;
11484			case '>=':
11485				return rtl ? a <= b : a >= b;
11486			case '<=':
11487				return rtl ? a >= b : a <= b;
11488			default:
11489				break;
11490		}
11491	};
11492
11493	/**
11494	 * Attaches to an internal event.
11495	 * @protected
11496	 * @param {HTMLElement} element - The event source.
11497	 * @param {String} event - The event name.
11498	 * @param {Function} listener - The event handler to attach.
11499	 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not.
11500	 */
11501	Owl.prototype.on = function(element, event, listener, capture) {
11502		if (element.addEventListener) {
11503			element.addEventListener(event, listener, capture);
11504		} else if (element.attachEvent) {
11505			element.attachEvent('on' + event, listener);
11506		}
11507	};
11508
11509	/**
11510	 * Detaches from an internal event.
11511	 * @protected
11512	 * @param {HTMLElement} element - The event source.
11513	 * @param {String} event - The event name.
11514	 * @param {Function} listener - The attached event handler to detach.
11515	 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not.
11516	 */
11517	Owl.prototype.off = function(element, event, listener, capture) {
11518		if (element.removeEventListener) {
11519			element.removeEventListener(event, listener, capture);
11520		} else if (element.detachEvent) {
11521			element.detachEvent('on' + event, listener);
11522		}
11523	};
11524
11525	/**
11526	 * Triggers a public event.
11527	 * @todo Remove `status`, `relatedTarget` should be used instead.
11528	 * @protected
11529	 * @param {String} name - The event name.
11530	 * @param {*} [data=null] - The event data.
11531	 * @param {String} [namespace=carousel] - The event namespace.
11532	 * @param {String} [state] - The state which is associated with the event.
11533	 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not.
11534	 * @returns {Event} - The event arguments.
11535	 */
11536	Owl.prototype.trigger = function(name, data, namespace, state, enter) {
11537		var status = {
11538			item: { count: this._items.length, index: this.current() }
11539		}, handler = $.camelCase(
11540			$.grep([ 'on', name, namespace ], function(v) { return v })
11541				.join('-').toLowerCase()
11542		), event = $.Event(
11543			[ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(),
11544			$.extend({ relatedTarget: this }, status, data)
11545		);
11546
11547		if (!this._supress[name]) {
11548			$.each(this._plugins, function(name, plugin) {
11549				if (plugin.onTrigger) {
11550					plugin.onTrigger(event);
11551				}
11552			});
11553
11554			this.register({ type: Owl.Type.Event, name: name });
11555			this.$element.trigger(event);
11556
11557			if (this.settings && typeof this.settings[handler] === 'function') {
11558				this.settings[handler].call(this, event);
11559			}
11560		}
11561
11562		return event;
11563	};
11564
11565	/**
11566	 * Enters a state.
11567	 * @param name - The state name.
11568	 */
11569	Owl.prototype.enter = function(name) {
11570		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
11571			if (this._states.current[name] === undefined) {
11572				this._states.current[name] = 0;
11573			}
11574
11575			this._states.current[name]++;
11576		}, this));
11577	};
11578
11579	/**
11580	 * Leaves a state.
11581	 * @param name - The state name.
11582	 */
11583	Owl.prototype.leave = function(name) {
11584		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
11585			this._states.current[name]--;
11586		}, this));
11587	};
11588
11589	/**
11590	 * Registers an event or state.
11591	 * @public
11592	 * @param {Object} object - The event or state to register.
11593	 */
11594	Owl.prototype.register = function(object) {
11595		if (object.type === Owl.Type.Event) {
11596			if (!$.event.special[object.name]) {
11597				$.event.special[object.name] = {};
11598			}
11599
11600			if (!$.event.special[object.name].owl) {
11601				var _default = $.event.special[object.name]._default;
11602				$.event.special[object.name]._default = function(e) {
11603					if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) {
11604						return _default.apply(this, arguments);
11605					}
11606					return e.namespace && e.namespace.indexOf('owl') > -1;
11607				};
11608				$.event.special[object.name].owl = true;
11609			}
11610		} else if (object.type === Owl.Type.State) {
11611			if (!this._states.tags[object.name]) {
11612				this._states.tags[object.name] = object.tags;
11613			} else {
11614				this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags);
11615			}
11616
11617			this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) {
11618				return $.inArray(tag, this._states.tags[object.name]) === i;
11619			}, this));
11620		}
11621	};
11622
11623	/**
11624	 * Suppresses events.
11625	 * @protected
11626	 * @param {Array.<String>} events - The events to suppress.
11627	 */
11628	Owl.prototype.suppress = function(events) {
11629		$.each(events, $.proxy(function(index, event) {
11630			this._supress[event] = true;
11631		}, this));
11632	};
11633
11634	/**
11635	 * Releases suppressed events.
11636	 * @protected
11637	 * @param {Array.<String>} events - The events to release.
11638	 */
11639	Owl.prototype.release = function(events) {
11640		$.each(events, $.proxy(function(index, event) {
11641			delete this._supress[event];
11642		}, this));
11643	};
11644
11645	/**
11646	 * Gets unified pointer coordinates from event.
11647	 * @todo #261
11648	 * @protected
11649	 * @param {Event} - The `mousedown` or `touchstart` event.
11650	 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position.
11651	 */
11652	Owl.prototype.pointer = function(event) {
11653		var result = { x: null, y: null };
11654
11655		event = event.originalEvent || event || window.event;
11656
11657		event = event.touches && event.touches.length ?
11658			event.touches[0] : event.changedTouches && event.changedTouches.length ?
11659				event.changedTouches[0] : event;
11660
11661		if (event.pageX) {
11662			result.x = event.pageX;
11663			result.y = event.pageY;
11664		} else {
11665			result.x = event.clientX;
11666			result.y = event.clientY;
11667		}
11668
11669		return result;
11670	};
11671
11672	/**
11673	 * Gets the difference of two vectors.
11674	 * @todo #261
11675	 * @protected
11676	 * @param {Object} - The first vector.
11677	 * @param {Object} - The second vector.
11678	 * @returns {Object} - The difference.
11679	 */
11680	Owl.prototype.difference = function(first, second) {
11681		return {
11682			x: first.x - second.x,
11683			y: first.y - second.y
11684		};
11685	};
11686
11687	/**
11688	 * The jQuery Plugin for the Owl Carousel
11689	 * @todo Navigation plugin `next` and `prev`
11690	 * @public
11691	 */
11692	$.fn.owlCarousel = function(option) {
11693		var args = Array.prototype.slice.call(arguments, 1);
11694
11695		return this.each(function() {
11696			var $this = $(this),
11697				data = $this.data('owl.carousel');
11698
11699			if (!data) {
11700				data = new Owl(this, typeof option == 'object' && option);
11701				$this.data('owl.carousel', data);
11702
11703				$.each([
11704					'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove'
11705				], function(i, event) {
11706					data.register({ type: Owl.Type.Event, name: event });
11707					data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) {
11708						if (e.namespace && e.relatedTarget !== this) {
11709							this.suppress([ event ]);
11710							data[event].apply(this, [].slice.call(arguments, 1));
11711							this.release([ event ]);
11712						}
11713					}, data));
11714				});
11715			}
11716
11717			if (typeof option == 'string' && option.charAt(0) !== '_') {
11718				data[option].apply(data, args);
11719			}
11720		});
11721	};
11722
11723	/**
11724	 * The constructor for the jQuery Plugin
11725	 * @public
11726	 */
11727	$.fn.owlCarousel.Constructor = Owl;
11728
11729})(window.Zepto || window.jQuery, window, document);
11730
11731/**
11732 * AutoRefresh Plugin
11733 * @version 2.0.0-beta.3
11734 * @author Artus Kolanowski
11735 * @license The MIT License (MIT)
11736 */
11737;(function($, window, document, undefined) {
11738
11739	/**
11740	 * Creates the auto refresh plugin.
11741	 * @class The Auto Refresh Plugin
11742	 * @param {Owl} carousel - The Owl Carousel
11743	 */
11744	var AutoRefresh = function(carousel) {
11745		/**
11746		 * Reference to the core.
11747		 * @protected
11748		 * @type {Owl}
11749		 */
11750		this._core = carousel;
11751
11752		/**
11753		 * Refresh interval.
11754		 * @protected
11755		 * @type {number}
11756		 */
11757		this._interval = null;
11758
11759		/**
11760		 * Whether the element is currently visible or not.
11761		 * @protected
11762		 * @type {Boolean}
11763		 */
11764		this._visible = null;
11765
11766		/**
11767		 * All event handlers.
11768		 * @protected
11769		 * @type {Object}
11770		 */
11771		this._handlers = {
11772			'initialized.owl.carousel': $.proxy(function(e) {
11773				if (e.namespace && this._core.settings.autoRefresh) {
11774					this.watch();
11775				}
11776			}, this)
11777		};
11778
11779		// set default options
11780		this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options);
11781
11782		// register event handlers
11783		this._core.$element.on(this._handlers);
11784	};
11785
11786	/**
11787	 * Default options.
11788	 * @public
11789	 */
11790	AutoRefresh.Defaults = {
11791		autoRefresh: true,
11792		autoRefreshInterval: 500
11793	};
11794
11795	/**
11796	 * Watches the element.
11797	 */
11798	AutoRefresh.prototype.watch = function() {
11799		if (this._interval) {
11800			return;
11801		}
11802
11803		this._visible = this._core.$element.is(':visible');
11804		this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval);
11805	};
11806
11807	/**
11808	 * Refreshes the element.
11809	 */
11810	AutoRefresh.prototype.refresh = function() {
11811		if (this._core.$element.is(':visible') === this._visible) {
11812			return;
11813		}
11814
11815		this._visible = !this._visible;
11816
11817		this._core.$element.toggleClass('owl-hidden', !this._visible);
11818
11819		this._visible && (this._core.invalidate('width') && this._core.refresh());
11820	};
11821
11822	/**
11823	 * Destroys the plugin.
11824	 */
11825	AutoRefresh.prototype.destroy = function() {
11826		var handler, property;
11827
11828		window.clearInterval(this._interval);
11829
11830		for (handler in this._handlers) {
11831			this._core.$element.off(handler, this._handlers[handler]);
11832		}
11833		for (property in Object.getOwnPropertyNames(this)) {
11834			typeof this[property] != 'function' && (this[property] = null);
11835		}
11836	};
11837
11838	$.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh;
11839
11840})(window.Zepto || window.jQuery, window, document);
11841
11842/**
11843 * Lazy Plugin
11844 * @version 2.0.0-beta.3
11845 * @author Bartosz Wojciechowski
11846 * @license The MIT License (MIT)
11847 */
11848;(function($, window, document, undefined) {
11849
11850	/**
11851	 * Creates the lazy plugin.
11852	 * @class The Lazy Plugin
11853	 * @param {Owl} carousel - The Owl Carousel
11854	 */
11855	var Lazy = function(carousel) {
11856
11857		/**
11858		 * Reference to the core.
11859		 * @protected
11860		 * @type {Owl}
11861		 */
11862		this._core = carousel;
11863
11864		/**
11865		 * Already loaded items.
11866		 * @protected
11867		 * @type {Array.<jQuery>}
11868		 */
11869		this._loaded = [];
11870
11871		/**
11872		 * Event handlers.
11873		 * @protected
11874		 * @type {Object}
11875		 */
11876		this._handlers = {
11877			'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) {
11878				if (!e.namespace) {
11879					return;
11880				}
11881
11882				if (!this._core.settings || !this._core.settings.lazyLoad) {
11883					return;
11884				}
11885
11886				if ((e.property && e.property.name == 'position') || e.type == 'initialized') {
11887					var settings = this._core.settings,
11888						n = (settings.center && Math.ceil(settings.items / 2) || settings.items),
11889						i = ((settings.center && n * -1) || 0),
11890						position = ((e.property && e.property.value) || this._core.current()) + i,
11891						clones = this._core.clones().length,
11892						load = $.proxy(function(i, v) { this.load(v) }, this);
11893
11894					while (i++ < n) {
11895						this.load(clones / 2 + this._core.relative(position));
11896						clones && $.each(this._core.clones(this._core.relative(position)), load);
11897						position++;
11898					}
11899				}
11900			}, this)
11901		};
11902
11903		// set the default options
11904		this._core.options = $.extend({}, Lazy.Defaults, this._core.options);
11905
11906		// register event handler
11907		this._core.$element.on(this._handlers);
11908	}
11909
11910	/**
11911	 * Default options.
11912	 * @public
11913	 */
11914	Lazy.Defaults = {
11915		lazyLoad: false
11916	}
11917
11918	/**
11919	 * Loads all resources of an item at the specified position.
11920	 * @param {Number} position - The absolute position of the item.
11921	 * @protected
11922	 */
11923	Lazy.prototype.load = function(position) {
11924		var $item = this._core.$stage.children().eq(position),
11925			$elements = $item && $item.find('.owl-lazy');
11926
11927		if (!$elements || $.inArray($item.get(0), this._loaded) > -1) {
11928			return;
11929		}
11930
11931		$elements.each($.proxy(function(index, element) {
11932			var $element = $(element), image,
11933				url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src');
11934
11935			this._core.trigger('load', { element: $element, url: url }, 'lazy');
11936
11937			if ($element.is('img')) {
11938				$element.one('load.owl.lazy', $.proxy(function() {
11939					$element.css('opacity', 1);
11940					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
11941				}, this)).attr('src', url);
11942			} else {
11943				image = new Image();
11944				image.onload = $.proxy(function() {
11945					$element.css({
11946						'background-image': 'url(' + url + ')',
11947						'opacity': '1'
11948					});
11949					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
11950				}, this);
11951				image.src = url;
11952			}
11953		}, this));
11954
11955		this._loaded.push($item.get(0));
11956	}
11957
11958	/**
11959	 * Destroys the plugin.
11960	 * @public
11961	 */
11962	Lazy.prototype.destroy = function() {
11963		var handler, property;
11964
11965		for (handler in this.handlers) {
11966			this._core.$element.off(handler, this.handlers[handler]);
11967		}
11968		for (property in Object.getOwnPropertyNames(this)) {
11969			typeof this[property] != 'function' && (this[property] = null);
11970		}
11971	};
11972
11973	$.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy;
11974
11975})(window.Zepto || window.jQuery, window, document);
11976
11977/**
11978 * AutoHeight Plugin
11979 * @version 2.0.0-beta.3
11980 * @author Bartosz Wojciechowski
11981 * @license The MIT License (MIT)
11982 */
11983;(function($, window, document, undefined) {
11984
11985	/**
11986	 * Creates the auto height plugin.
11987	 * @class The Auto Height Plugin
11988	 * @param {Owl} carousel - The Owl Carousel
11989	 */
11990	var AutoHeight = function(carousel) {
11991		/**
11992		 * Reference to the core.
11993		 * @protected
11994		 * @type {Owl}
11995		 */
11996		this._core = carousel;
11997
11998		/**
11999		 * All event handlers.
12000		 * @protected
12001		 * @type {Object}
12002		 */
12003		this._handlers = {
12004			'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) {
12005				if (e.namespace && this._core.settings.autoHeight) {
12006					this.update();
12007				}
12008			}, this),
12009			'changed.owl.carousel': $.proxy(function(e) {
12010				if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){
12011					this.update();
12012				}
12013			}, this),
12014			'loaded.owl.lazy': $.proxy(function(e) {
12015				if (e.namespace && this._core.settings.autoHeight
12016					&& e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) {
12017					this.update();
12018				}
12019			}, this)
12020		};
12021
12022		// set default options
12023		this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options);
12024
12025		// register event handlers
12026		this._core.$element.on(this._handlers);
12027	};
12028
12029	/**
12030	 * Default options.
12031	 * @public
12032	 */
12033	AutoHeight.Defaults = {
12034		autoHeight: false,
12035		autoHeightClass: 'owl-height'
12036	};
12037
12038	/**
12039	 * Updates the view.
12040	 */
12041	AutoHeight.prototype.update = function() {
12042		var start = this._core._current,
12043			end = start + this._core.settings.items,
12044			visible = this._core.$stage.children().toArray().slice(start, end);
12045			heights = [],
12046			maxheight = 0;
12047
12048		$.each(visible, function(index, item) {
12049			heights.push($(item).height());
12050		});
12051
12052		maxheight = Math.max.apply(null, heights);
12053
12054		this._core.$stage.parent()
12055			.height(maxheight)
12056			.addClass(this._core.settings.autoHeightClass);
12057	};
12058
12059	AutoHeight.prototype.destroy = function() {
12060		var handler, property;
12061
12062		for (handler in this._handlers) {
12063			this._core.$element.off(handler, this._handlers[handler]);
12064		}
12065		for (property in Object.getOwnPropertyNames(this)) {
12066			typeof this[property] != 'function' && (this[property] = null);
12067		}
12068	};
12069
12070	$.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight;
12071
12072})(window.Zepto || window.jQuery, window, document);
12073
12074/**
12075 * Video Plugin
12076 * @version 2.0.0-beta.3
12077 * @author Bartosz Wojciechowski
12078 * @license The MIT License (MIT)
12079 */
12080;(function($, window, document, undefined) {
12081
12082	/**
12083	 * Creates the video plugin.
12084	 * @class The Video Plugin
12085	 * @param {Owl} carousel - The Owl Carousel
12086	 */
12087	var Video = function(carousel) {
12088		/**
12089		 * Reference to the core.
12090		 * @protected
12091		 * @type {Owl}
12092		 */
12093		this._core = carousel;
12094
12095		/**
12096		 * Cache all video URLs.
12097		 * @protected
12098		 * @type {Object}
12099		 */
12100		this._videos = {};
12101
12102		/**
12103		 * Current playing item.
12104		 * @protected
12105		 * @type {jQuery}
12106		 */
12107		this._playing = null;
12108
12109		/**
12110		 * All event handlers.
12111		 * @todo The cloned content removale is too late
12112		 * @protected
12113		 * @type {Object}
12114		 */
12115		this._handlers = {
12116			'initialized.owl.carousel': $.proxy(function(e) {
12117				if (e.namespace) {
12118					this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] });
12119				}
12120			}, this),
12121			'resize.owl.carousel': $.proxy(function(e) {
12122				if (e.namespace && this._core.settings.video && this.isInFullScreen()) {
12123					e.preventDefault();
12124				}
12125			}, this),
12126			'refreshed.owl.carousel': $.proxy(function(e) {
12127				if (e.namespace && this._core.is('resizing')) {
12128					this._core.$stage.find('.cloned .owl-video-frame').remove();
12129				}
12130			}, this),
12131			'changed.owl.carousel': $.proxy(function(e) {
12132				if (e.namespace && e.property.name === 'position' && this._playing) {
12133					this.stop();
12134				}
12135			}, this),
12136			'prepared.owl.carousel': $.proxy(function(e) {
12137				if (!e.namespace) {
12138					return;
12139				}
12140
12141				var $element = $(e.content).find('.owl-video');
12142
12143				if ($element.length) {
12144					$element.css('display', 'none');
12145					this.fetch($element, $(e.content));
12146				}
12147			}, this)
12148		};
12149
12150		// set default options
12151		this._core.options = $.extend({}, Video.Defaults, this._core.options);
12152
12153		// register event handlers
12154		this._core.$element.on(this._handlers);
12155
12156		this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) {
12157			this.play(e);
12158		}, this));
12159	};
12160
12161	/**
12162	 * Default options.
12163	 * @public
12164	 */
12165	Video.Defaults = {
12166		video: false,
12167		videoHeight: false,
12168		videoWidth: false
12169	};
12170
12171	/**
12172	 * Gets the video ID and the type (YouTube/Vimeo only).
12173	 * @protected
12174	 * @param {jQuery} target - The target containing the video data.
12175	 * @param {jQuery} item - The item containing the video.
12176	 */
12177	Video.prototype.fetch = function(target, item) {
12178		var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube',
12179			id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'),
12180			width = target.attr('data-width') || this._core.settings.videoWidth,
12181			height = target.attr('data-height') || this._core.settings.videoHeight,
12182			url = target.attr('href');
12183
12184		if (url) {
12185			id = url.match(/(http:|https:|)\/\/(player.|www.)?(vimeo\.com|youtu(be\.com|\.be|be\.googleapis\.com))\/(video\/|embed\/|watch\?v=|v\/)?([A-Za-z0-9._%-]*)(\&\S+)?/);
12186
12187			if (id[3].indexOf('youtu') > -1) {
12188				type = 'youtube';
12189			} else if (id[3].indexOf('vimeo') > -1) {
12190				type = 'vimeo';
12191			} else {
12192				throw new Error('Video URL not supported.');
12193			}
12194			id = id[6];
12195		} else {
12196			throw new Error('Missing video URL.');
12197		}
12198
12199		this._videos[url] = {
12200			type: type,
12201			id: id,
12202			width: width,
12203			height: height
12204		};
12205
12206		item.attr('data-video', url);
12207
12208		this.thumbnail(target, this._videos[url]);
12209	};
12210
12211	/**
12212	 * Creates video thumbnail.
12213	 * @protected
12214	 * @param {jQuery} target - The target containing the video data.
12215	 * @param {Object} info - The video info object.
12216	 * @see `fetch`
12217	 */
12218	Video.prototype.thumbnail = function(target, video) {
12219		var tnLink,
12220			icon,
12221			path,
12222			dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '',
12223			customTn = target.find('img'),
12224			srcType = 'src',
12225			lazyClass = '',
12226			settings = this._core.settings,
12227			create = function(path) {
12228				icon = '<div class="owl-video-play-icon"></div>';
12229
12230				if (settings.lazyLoad) {
12231					tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>';
12232				} else {
12233					tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>';
12234				}
12235				target.after(tnLink);
12236				target.after(icon);
12237			};
12238
12239		// wrap video content into owl-video-wrapper div
12240		target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>');
12241
12242		if (this._core.settings.lazyLoad) {
12243			srcType = 'data-src';
12244			lazyClass = 'owl-lazy';
12245		}
12246
12247		// custom thumbnail
12248		if (customTn.length) {
12249			create(customTn.attr(srcType));
12250			customTn.remove();
12251			return false;
12252		}
12253
12254		if (video.type === 'youtube') {
12255			path = "http://img.youtube.com/vi/" + video.id + "/hqdefault.jpg";
12256			create(path);
12257		} else if (video.type === 'vimeo') {
12258			$.ajax({
12259				type: 'GET',
12260				url: 'http://vimeo.com/api/v2/video/' + video.id + '.json',
12261				jsonp: 'callback',
12262				dataType: 'jsonp',
12263				success: function(data) {
12264					path = data[0].thumbnail_large;
12265					create(path);
12266				}
12267			});
12268		}
12269	};
12270
12271	/**
12272	 * Stops the current video.
12273	 * @public
12274	 */
12275	Video.prototype.stop = function() {
12276		this._core.trigger('stop', null, 'video');
12277		this._playing.find('.owl-video-frame').remove();
12278		this._playing.removeClass('owl-video-playing');
12279		this._playing = null;
12280		this._core.leave('playing');
12281		this._core.trigger('stopped', null, 'video');
12282	};
12283
12284	/**
12285	 * Starts the current video.
12286	 * @public
12287	 * @param {Event} event - The event arguments.
12288	 */
12289	Video.prototype.play = function(event) {
12290		var target = $(event.target),
12291			item = target.closest('.' + this._core.settings.itemClass),
12292			video = this._videos[item.attr('data-video')],
12293			width = video.width || '100%',
12294			height = video.height || this._core.$stage.height(),
12295			html;
12296
12297		if (this._playing) {
12298			return;
12299		}
12300
12301		this._core.enter('playing');
12302		this._core.trigger('play', null, 'video');
12303
12304		item = this._core.items(this._core.relative(item.index()));
12305
12306		this._core.reset(item.index());
12307
12308		if (video.type === 'youtube') {
12309			html = '<iframe width="' + width + '" height="' + height + '" src="http://www.youtube.com/embed/' +
12310				video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>';
12311		} else if (video.type === 'vimeo') {
12312			html = '<iframe src="http://player.vimeo.com/video/' + video.id +
12313				'?autoplay=1" width="' + width + '" height="' + height +
12314				'" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>';
12315		}
12316
12317		$('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video'));
12318
12319		this._playing = item.addClass('owl-video-playing');
12320	};
12321
12322	/**
12323	 * Checks whether an video is currently in full screen mode or not.
12324	 * @todo Bad style because looks like a readonly method but changes members.
12325	 * @protected
12326	 * @returns {Boolean}
12327	 */
12328	Video.prototype.isInFullScreen = function() {
12329		var element = document.fullscreenElement || document.mozFullScreenElement ||
12330				document.webkitFullscreenElement;
12331
12332		return element && $(element).parent().hasClass('owl-video-frame');
12333	};
12334
12335	/**
12336	 * Destroys the plugin.
12337	 */
12338	Video.prototype.destroy = function() {
12339		var handler, property;
12340
12341		this._core.$element.off('click.owl.video');
12342
12343		for (handler in this._handlers) {
12344			this._core.$element.off(handler, this._handlers[handler]);
12345		}
12346		for (property in Object.getOwnPropertyNames(this)) {
12347			typeof this[property] != 'function' && (this[property] = null);
12348		}
12349	};
12350
12351	$.fn.owlCarousel.Constructor.Plugins.Video = Video;
12352
12353})(window.Zepto || window.jQuery, window, document);
12354
12355/**
12356 * Animate Plugin
12357 * @version 2.0.0-beta.3
12358 * @author Bartosz Wojciechowski
12359 * @license The MIT License (MIT)
12360 */
12361;(function($, window, document, undefined) {
12362
12363	/**
12364	 * Creates the animate plugin.
12365	 * @class The Navigation Plugin
12366	 * @param {Owl} scope - The Owl Carousel
12367	 */
12368	var Animate = function(scope) {
12369		this.core = scope;
12370		this.core.options = $.extend({}, Animate.Defaults, this.core.options);
12371		this.swapping = true;
12372		this.previous = undefined;
12373		this.next = undefined;
12374
12375		this.handlers = {
12376			'change.owl.carousel': $.proxy(function(e) {
12377				if (e.namespace && e.property.name == 'position') {
12378					this.previous = this.core.current();
12379					this.next = e.property.value;
12380				}
12381			}, this),
12382			'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) {
12383				if (e.namespace) {
12384					this.swapping = e.type == 'translated';
12385				}
12386			}, this),
12387			'translate.owl.carousel': $.proxy(function(e) {
12388				if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) {
12389					this.swap();
12390				}
12391			}, this)
12392		};
12393
12394		this.core.$element.on(this.handlers);
12395	};
12396
12397	/**
12398	 * Default options.
12399	 * @public
12400	 */
12401	Animate.Defaults = {
12402		animateOut: false,
12403		animateIn: false
12404	};
12405
12406	/**
12407	 * Toggles the animation classes whenever an translations starts.
12408	 * @protected
12409	 * @returns {Boolean|undefined}
12410	 */
12411	Animate.prototype.swap = function() {
12412
12413		if (this.core.settings.items !== 1) {
12414			return;
12415		}
12416
12417		if (!$.support.animation || !$.support.transition) {
12418			return;
12419		}
12420
12421		this.core.speed(0);
12422
12423		var left,
12424			clear = $.proxy(this.clear, this),
12425			previous = this.core.$stage.children().eq(this.previous),
12426			next = this.core.$stage.children().eq(this.next),
12427			incoming = this.core.settings.animateIn,
12428			outgoing = this.core.settings.animateOut;
12429
12430		if (this.core.current() === this.previous) {
12431			return;
12432		}
12433
12434		if (outgoing) {
12435			left = this.core.coordinates(this.previous) - this.core.coordinates(this.next);
12436			previous.css( { 'left': left + 'px' } )
12437				.addClass('animated owl-animated-out')
12438				.addClass(outgoing)
12439				.on($.support.animation.end, clear);
12440		}
12441
12442		if (incoming) {
12443			next.addClass('animated owl-animated-in')
12444				.addClass(incoming)
12445				.on($.support.animation.end, clear);
12446		}
12447	};
12448
12449	Animate.prototype.clear = function(e) {
12450		if ($(e.target).hasClass('animated')) {
12451			$(e.target).css( { 'left': '' } )
12452				.removeClass('animated owl-animated-out owl-animated-in')
12453				.removeClass(this.core.settings.animateIn)
12454				.removeClass(this.core.settings.animateOut);
12455			this.core.onTransitionEnd();
12456		}
12457	};
12458
12459	/**
12460	 * Destroys the plugin.
12461	 * @public
12462	 */
12463	Animate.prototype.destroy = function() {
12464		var handler, property;
12465
12466		for (handler in this.handlers) {
12467			this.core.$element.off(handler, this.handlers[handler]);
12468		}
12469		for (property in Object.getOwnPropertyNames(this)) {
12470			typeof this[property] != 'function' && (this[property] = null);
12471		}
12472	};
12473
12474	$.fn.owlCarousel.Constructor.Plugins.Animate = Animate;
12475
12476})(window.Zepto || window.jQuery, window, document);
12477
12478/**
12479 * Autoplay Plugin
12480 * @version 2.0.0-beta.3
12481 * @author Bartosz Wojciechowski
12482 * @author Artus Kolanowski
12483 * @license The MIT License (MIT)
12484 */
12485;(function($, window, document, undefined) {
12486
12487	/**
12488	 * Creates the autoplay plugin.
12489	 * @class The Autoplay Plugin
12490	 * @param {Owl} scope - The Owl Carousel
12491	 */
12492	var Autoplay = function(carousel) {
12493		/**
12494		 * Reference to the core.
12495		 * @protected
12496		 * @type {Owl}
12497		 */
12498		this._core = carousel;
12499
12500		/**
12501		 * The autoplay interval.
12502		 * @type {Number}
12503		 */
12504		this._interval = null;
12505
12506		/**
12507		 * Indicates whenever the autoplay is paused.
12508		 * @type {Boolean}
12509		 */
12510		this._paused = false;
12511
12512		/**
12513		 * All event handlers.
12514		 * @protected
12515		 * @type {Object}
12516		 */
12517		this._handlers = {
12518			'changed.owl.carousel': $.proxy(function(e) {
12519				if (e.namespace && e.property.name === 'settings') {
12520					if (this._core.settings.autoplay) {
12521						this.play();
12522					} else {
12523						this.stop();
12524					}
12525				}
12526			}, this),
12527			'initialized.owl.carousel': $.proxy(function(e) {
12528				if (e.namespace && this._core.settings.autoplay) {
12529					this.play();
12530				}
12531			}, this),
12532			'play.owl.autoplay': $.proxy(function(e, t, s) {
12533				if (e.namespace) {
12534					this.play(t, s);
12535				}
12536			}, this),
12537			'stop.owl.autoplay': $.proxy(function(e) {
12538				if (e.namespace) {
12539					this.stop();
12540				}
12541			}, this),
12542			'mouseover.owl.autoplay': $.proxy(function() {
12543				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
12544					this.pause();
12545				}
12546			}, this),
12547			'mouseleave.owl.autoplay': $.proxy(function() {
12548				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
12549					this.play();
12550				}
12551			}, this)
12552		};
12553
12554		// register event handlers
12555		this._core.$element.on(this._handlers);
12556
12557		// set default options
12558		this._core.options = $.extend({}, Autoplay.Defaults, this._core.options);
12559	};
12560
12561	/**
12562	 * Default options.
12563	 * @public
12564	 */
12565	Autoplay.Defaults = {
12566		autoplay: false,
12567		autoplayTimeout: 5000,
12568		autoplayHoverPause: false,
12569		autoplaySpeed: false
12570	};
12571
12572	/**
12573	 * Starts the autoplay.
12574	 * @public
12575	 * @param {Number} [timeout] - The interval before the next animation starts.
12576	 * @param {Number} [speed] - The animation speed for the animations.
12577	 */
12578	Autoplay.prototype.play = function(timeout, speed) {
12579		this._paused = false;
12580
12581		if (this._core.is('rotating')) {
12582			return;
12583		}
12584
12585		this._core.enter('rotating');
12586
12587		this._interval = window.setInterval($.proxy(function() {
12588			if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) {
12589				return;
12590			}
12591			this._core.next(speed || this._core.settings.autoplaySpeed);
12592		}, this), timeout || this._core.settings.autoplayTimeout);
12593	};
12594
12595	/**
12596	 * Stops the autoplay.
12597	 * @public
12598	 */
12599	Autoplay.prototype.stop = function() {
12600		if (!this._core.is('rotating')) {
12601			return;
12602		}
12603
12604		window.clearInterval(this._interval);
12605		this._core.leave('rotating');
12606	};
12607
12608	/**
12609	 * Stops the autoplay.
12610	 * @public
12611	 */
12612	Autoplay.prototype.pause = function() {
12613		if (!this._core.is('rotating')) {
12614			return;
12615		}
12616
12617		this._paused = true;
12618	};
12619
12620	/**
12621	 * Destroys the plugin.
12622	 */
12623	Autoplay.prototype.destroy = function() {
12624		var handler, property;
12625
12626		this.stop();
12627
12628		for (handler in this._handlers) {
12629			this._core.$element.off(handler, this._handlers[handler]);
12630		}
12631		for (property in Object.getOwnPropertyNames(this)) {
12632			typeof this[property] != 'function' && (this[property] = null);
12633		}
12634	};
12635
12636	$.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay;
12637
12638})(window.Zepto || window.jQuery, window, document);
12639
12640/**
12641 * Navigation Plugin
12642 * @version 2.0.0-beta.3
12643 * @author Artus Kolanowski
12644 * @license The MIT License (MIT)
12645 */
12646;(function($, window, document, undefined) {
12647	'use strict';
12648
12649	/**
12650	 * Creates the navigation plugin.
12651	 * @class The Navigation Plugin
12652	 * @param {Owl} carousel - The Owl Carousel.
12653	 */
12654	var Navigation = function(carousel) {
12655		/**
12656		 * Reference to the core.
12657		 * @protected
12658		 * @type {Owl}
12659		 */
12660		this._core = carousel;
12661
12662		/**
12663		 * Indicates whether the plugin is initialized or not.
12664		 * @protected
12665		 * @type {Boolean}
12666		 */
12667		this._initialized = false;
12668
12669		/**
12670		 * The current paging indexes.
12671		 * @protected
12672		 * @type {Array}
12673		 */
12674		this._pages = [];
12675
12676		/**
12677		 * All DOM elements of the user interface.
12678		 * @protected
12679		 * @type {Object}
12680		 */
12681		this._controls = {};
12682
12683		/**
12684		 * Markup for an indicator.
12685		 * @protected
12686		 * @type {Array.<String>}
12687		 */
12688		this._templates = [];
12689
12690		/**
12691		 * The carousel element.
12692		 * @type {jQuery}
12693		 */
12694		this.$element = this._core.$element;
12695
12696		/**
12697		 * Overridden methods of the carousel.
12698		 * @protected
12699		 * @type {Object}
12700		 */
12701		this._overrides = {
12702			next: this._core.next,
12703			prev: this._core.prev,
12704			to: this._core.to
12705		};
12706
12707		/**
12708		 * All event handlers.
12709		 * @protected
12710		 * @type {Object}
12711		 */
12712		this._handlers = {
12713			'prepared.owl.carousel': $.proxy(function(e) {
12714				if (e.namespace && this._core.settings.dotsData) {
12715					this._templates.push('<div class="' + this._core.settings.dotClass + '">' +
12716						$(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>');
12717				}
12718			}, this),
12719			'added.owl.carousel': $.proxy(function(e) {
12720				if (e.namespace && this._core.settings.dotsData) {
12721					this._templates.splice(e.position, 0, this._templates.pop());
12722				}
12723			}, this),
12724			'remove.owl.carousel': $.proxy(function(e) {
12725				if (e.namespace && this._core.settings.dotsData) {
12726					this._templates.splice(e.position, 1);
12727				}
12728			}, this),
12729			'changed.owl.carousel': $.proxy(function(e) {
12730				if (e.namespace && e.property.name == 'position') {
12731					this.draw();
12732				}
12733			}, this),
12734			'initialized.owl.carousel': $.proxy(function(e) {
12735				if (e.namespace && !this._initialized) {
12736					this._core.trigger('initialize', null, 'navigation');
12737					this.initialize();
12738					this.update();
12739					this.draw();
12740					this._initialized = true;
12741					this._core.trigger('initialized', null, 'navigation');
12742				}
12743			}, this),
12744			'refreshed.owl.carousel': $.proxy(function(e) {
12745				if (e.namespace && this._initialized) {
12746					this._core.trigger('refresh', null, 'navigation');
12747					this.update();
12748					this.draw();
12749					this._core.trigger('refreshed', null, 'navigation');
12750				}
12751			}, this)
12752		};
12753
12754		// set default options
12755		this._core.options = $.extend({}, Navigation.Defaults, this._core.options);
12756
12757		// register event handlers
12758		this.$element.on(this._handlers);
12759	};
12760
12761	/**
12762	 * Default options.
12763	 * @public
12764	 * @todo Rename `slideBy` to `navBy`
12765	 */
12766	Navigation.Defaults = {
12767		nav: false,
12768		navText: [ 'prev', 'next' ],
12769		navSpeed: false,
12770		navElement: 'div',
12771		navContainer: false,
12772		navContainerClass: 'owl-nav',
12773		navClass: [ 'owl-prev', 'owl-next' ],
12774		slideBy: 1,
12775		dotClass: 'owl-dot',
12776		dotsClass: 'owl-dots',
12777		dots: true,
12778		dotsEach: false,
12779		dotsData: false,
12780		dotsSpeed: false,
12781		dotsContainer: false
12782	};
12783
12784	/**
12785	 * Initializes the layout of the plugin and extends the carousel.
12786	 * @protected
12787	 */
12788	Navigation.prototype.initialize = function() {
12789		var override,
12790			settings = this._core.settings;
12791
12792		// create DOM structure for relative navigation
12793		this._controls.$relative = (settings.navContainer ? $(settings.navContainer)
12794			: $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled');
12795
12796		this._controls.$previous = $('<' + settings.navElement + '>')
12797			.addClass(settings.navClass[0])
12798			.html(settings.navText[0])
12799			.prependTo(this._controls.$relative)
12800			.on('click', $.proxy(function(e) {
12801				this.prev(settings.navSpeed);
12802			}, this));
12803		this._controls.$next = $('<' + settings.navElement + '>')
12804			.addClass(settings.navClass[1])
12805			.html(settings.navText[1])
12806			.appendTo(this._controls.$relative)
12807			.on('click', $.proxy(function(e) {
12808				this.next(settings.navSpeed);
12809			}, this));
12810
12811		// create DOM structure for absolute navigation
12812		if (!settings.dotsData) {
12813			this._templates = [ $('<div>')
12814				.addClass(settings.dotClass)
12815				.append($('<span>'))
12816				.prop('outerHTML') ];
12817		}
12818
12819		this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer)
12820			: $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled');
12821
12822		this._controls.$absolute.on('click', 'div', $.proxy(function(e) {
12823			var index = $(e.target).parent().is(this._controls.$absolute)
12824				? $(e.target).index() : $(e.target).parent().index();
12825
12826			e.preventDefault();
12827
12828			this.to(index, settings.dotsSpeed);
12829		}, this));
12830
12831		// override public methods of the carousel
12832		for (override in this._overrides) {
12833			this._core[override] = $.proxy(this[override], this);
12834		}
12835	};
12836
12837	/**
12838	 * Destroys the plugin.
12839	 * @protected
12840	 */
12841	Navigation.prototype.destroy = function() {
12842		var handler, control, property, override;
12843
12844		for (handler in this._handlers) {
12845			this.$element.off(handler, this._handlers[handler]);
12846		}
12847		for (control in this._controls) {
12848			this._controls[control].remove();
12849		}
12850		for (override in this.overides) {
12851			this._core[override] = this._overrides[override];
12852		}
12853		for (property in Object.getOwnPropertyNames(this)) {
12854			typeof this[property] != 'function' && (this[property] = null);
12855		}
12856	};
12857
12858	/**
12859	 * Updates the internal state.
12860	 * @protected
12861	 */
12862	Navigation.prototype.update = function() {
12863		var i, j, k,
12864			lower = this._core.clones().length / 2,
12865			upper = lower + this._core.items().length,
12866			maximum = this._core.maximum(true),
12867			settings = this._core.settings,
12868			size = settings.center || settings.autoWidth || settings.dotsData
12869				? 1 : settings.dotsEach || settings.items;
12870
12871		if (settings.slideBy !== 'page') {
12872			settings.slideBy = Math.min(settings.slideBy, settings.items);
12873		}
12874
12875		if (settings.dots || settings.slideBy == 'page') {
12876			this._pages = [];
12877
12878			for (i = lower, j = 0, k = 0; i < upper; i++) {
12879				if (j >= size || j === 0) {
12880					this._pages.push({
12881						start: Math.min(maximum, i - lower),
12882						end: i - lower + size - 1
12883					});
12884					if (Math.min(maximum, i - lower) === maximum) {
12885						break;
12886					}
12887					j = 0, ++k;
12888				}
12889				j += this._core.mergers(this._core.relative(i));
12890			}
12891		}
12892	};
12893
12894	/**
12895	 * Draws the user interface.
12896	 * @todo The option `dotsData` wont work.
12897	 * @protected
12898	 */
12899	Navigation.prototype.draw = function() {
12900		var difference,
12901			settings = this._core.settings,
12902			disabled = this._core.items().length <= settings.items,
12903			index = this._core.relative(this._core.current()),
12904			loop = settings.loop || settings.rewind;
12905
12906		this._controls.$relative.toggleClass('disabled', !settings.nav || disabled);
12907
12908		if (settings.nav) {
12909			this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true));
12910			this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true));
12911		}
12912
12913		this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled);
12914
12915		if (settings.dots) {
12916			difference = this._pages.length - this._controls.$absolute.children().length;
12917
12918			if (settings.dotsData && difference !== 0) {
12919				this._controls.$absolute.html(this._templates.join(''));
12920			} else if (difference > 0) {
12921				this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0]));
12922			} else if (difference < 0) {
12923				this._controls.$absolute.children().slice(difference).remove();
12924			}
12925
12926			this._controls.$absolute.find('.active').removeClass('active');
12927			this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active');
12928		}
12929	};
12930
12931	/**
12932	 * Extends event data.
12933	 * @protected
12934	 * @param {Event} event - The event object which gets thrown.
12935	 */
12936	Navigation.prototype.onTrigger = function(event) {
12937		var settings = this._core.settings;
12938
12939		event.page = {
12940			index: $.inArray(this.current(), this._pages),
12941			count: this._pages.length,
12942			size: settings && (settings.center || settings.autoWidth || settings.dotsData
12943				? 1 : settings.dotsEach || settings.items)
12944		};
12945	};
12946
12947	/**
12948	 * Gets the current page position of the carousel.
12949	 * @protected
12950	 * @returns {Number}
12951	 */
12952	Navigation.prototype.current = function() {
12953		var current = this._core.relative(this._core.current());
12954		return $.grep(this._pages, $.proxy(function(page, index) {
12955			return page.start <= current && page.end >= current;
12956		}, this)).pop();
12957	};
12958
12959	/**
12960	 * Gets the current succesor/predecessor position.
12961	 * @protected
12962	 * @returns {Number}
12963	 */
12964	Navigation.prototype.getPosition = function(successor) {
12965		var position, length,
12966			settings = this._core.settings;
12967
12968		if (settings.slideBy == 'page') {
12969			position = $.inArray(this.current(), this._pages);
12970			length = this._pages.length;
12971			successor ? ++position : --position;
vendor: 5,670 bytes, lines 12972-13196
12972			position = this._pages[((position % length) + length) % length].start;
12973		} else {
12974			position = this._core.relative(this._core.current());
12975			length = this._core.items().length;
12976			successor ? position += settings.slideBy : position -= settings.slideBy;
12977		}
12978
12979		return position;
12980	};
12981
12982	/**
12983	 * Slides to the next item or page.
12984	 * @public
12985	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
12986	 */
12987	Navigation.prototype.next = function(speed) {
12988		$.proxy(this._overrides.to, this._core)(this.getPosition(true), speed);
12989	};
12990
12991	/**
12992	 * Slides to the previous item or page.
12993	 * @public
12994	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
12995	 */
12996	Navigation.prototype.prev = function(speed) {
12997		$.proxy(this._overrides.to, this._core)(this.getPosition(false), speed);
12998	};
12999
13000	/**
13001	 * Slides to the specified item or page.
13002	 * @public
13003	 * @param {Number} position - The position of the item or page.
13004	 * @param {Number} [speed] - The time in milliseconds for the transition.
13005	 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not.
13006	 */
13007	Navigation.prototype.to = function(position, speed, standard) {
13008		var length;
13009
13010		if (!standard) {
13011			length = this._pages.length;
13012			$.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed);
13013		} else {
13014			$.proxy(this._overrides.to, this._core)(position, speed);
13015		}
13016	};
13017
13018	$.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation;
13019
13020})(window.Zepto || window.jQuery, window, document);
13021
13022/**
13023 * Hash Plugin
13024 * @version 2.0.0-beta.3
13025 * @author Artus Kolanowski
13026 * @license The MIT License (MIT)
13027 */
13028;(function($, window, document, undefined) {
13029	'use strict';
13030
13031	/**
13032	 * Creates the hash plugin.
13033	 * @class The Hash Plugin
13034	 * @param {Owl} carousel - The Owl Carousel
13035	 */
13036	var Hash = function(carousel) {
13037		/**
13038		 * Reference to the core.
13039		 * @protected
13040		 * @type {Owl}
13041		 */
13042		this._core = carousel;
13043
13044		/**
13045		 * Hash index for the items.
13046		 * @protected
13047		 * @type {Object}
13048		 */
13049		this._hashes = {};
13050
13051		/**
13052		 * The carousel element.
13053		 * @type {jQuery}
13054		 */
13055		this.$element = this._core.$element;
13056
13057		/**
13058		 * All event handlers.
13059		 * @protected
13060		 * @type {Object}
13061		 */
13062		this._handlers = {
13063			'initialized.owl.carousel': $.proxy(function(e) {
13064				if (e.namespace && this._core.settings.startPosition === 'URLHash') {
13065					$(window).trigger('hashchange.owl.navigation');
13066				}
13067			}, this),
13068			'prepared.owl.carousel': $.proxy(function(e) {
13069				if (e.namespace) {
13070					var hash = $(e.content).find('[data-hash]').andSelf('[data-hash]').attr('data-hash');
13071
13072					if (!hash) {
13073						return;
13074					}
13075
13076					this._hashes[hash] = e.content;
13077				}
13078			}, this),
13079			'changed.owl.carousel': $.proxy(function(e) {
13080				if (e.namespace && e.property.name === 'position') {
13081					var current = this._core.items(this._core.relative(this._core.current())),
13082						hash = $.map(this._hashes, function(item, hash) {
13083							return item === current ? hash : null;
13084						}).join();
13085
13086					if (!hash || window.location.hash.slice(1) === hash) {
13087						return;
13088					}
13089
13090					window.location.hash = hash;
13091				}
13092			}, this)
13093		};
13094
13095		// set default options
13096		this._core.options = $.extend({}, Hash.Defaults, this._core.options);
13097
13098		// register the event handlers
13099		this.$element.on(this._handlers);
13100
13101		// register event listener for hash navigation
13102		$(window).on('hashchange.owl.navigation', $.proxy(function(e) {
13103			var hash = window.location.hash.substring(1),
13104				items = this._core.$stage.children(),
13105				position = this._hashes[hash] && items.index(this._hashes[hash]);
13106
13107			if (position === undefined || position === this._core.current()) {
13108				return;
13109			}
13110
13111			this._core.to(this._core.relative(position), false, true);
13112		}, this));
13113	};
13114
13115	/**
13116	 * Default options.
13117	 * @public
13118	 */
13119	Hash.Defaults = {
13120		URLhashListener: false
13121	};
13122
13123	/**
13124	 * Destroys the plugin.
13125	 * @public
13126	 */
13127	Hash.prototype.destroy = function() {
13128		var handler, property;
13129
13130		$(window).off('hashchange.owl.navigation');
13131
13132		for (handler in this._handlers) {
13133			this._core.$element.off(handler, this._handlers[handler]);
13134		}
13135		for (property in Object.getOwnPropertyNames(this)) {
13136			typeof this[property] != 'function' && (this[property] = null);
13137		}
13138	};
13139
13140	$.fn.owlCarousel.Constructor.Plugins.Hash = Hash;
13141
13142})(window.Zepto || window.jQuery, window, document);
13143
13144/**
13145 * Support Plugin
13146 *
13147 * @version 2.0.0-beta.3
13148 * @author Vivid Planet Software GmbH
13149 * @author Artus Kolanowski
13150 * @license The MIT License (MIT)
13151 */
13152;(function($, window, document, undefined) {
13153
13154	var style = $('<support>').get(0).style,
13155		prefixes = 'Webkit Moz O ms'.split(' '),
13156		events = {
13157			transition: {
13158				end: {
13159					WebkitTransition: 'webkitTransitionEnd',
13160					MozTransition: 'transitionend',
13161					OTransition: 'oTransitionEnd',
13162					transition: 'transitionend'
13163				}
13164			},
13165			animation: {
13166				end: {
13167					WebkitAnimation: 'webkitAnimationEnd',
13168					MozAnimation: 'animationend',
13169					OAnimation: 'oAnimationEnd',
13170					animation: 'animationend'
13171				}
13172			}
13173		},
13174		tests = {
13175			csstransforms: function() {
13176				return !!test('transform');
13177			},
13178			csstransforms3d: function() {
13179				return !!test('perspective');
13180			},
13181			csstransitions: function() {
13182				return !!test('transition');
13183			},
13184			cssanimations: function() {
13185				return !!test('animation');
13186			}
13187		};
13188
13189	function test(property, prefixed) {
13190		var result = false,
13191			upper = property.charAt(0).toUpperCase() + property.slice(1);
13192
13193		$.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) {
13194			if (style[property] !== undefined) {
13195				result = prefixed ? property : true;
13196				return false;
13197			}
13198		});
13199
13200		return result;
13201	}
13202
13203	function prefixed(property) {
13204		return test(property, true);
13205	}
13206
13207	if (tests.csstransitions()) {
13208		/* jshint -W053 */
13209		$.support.transition = new String(prefixed('transition'))
13210		$.support.transition.end = events.transition.end[ $.support.transition ];
13211	}
13212
13213	if (tests.cssanimations()) {
13214		/* jshint -W053 */
13215		$.support.animation = new String(prefixed('animation'))
13216		$.support.animation.end = events.animation.end[ $.support.animation ];
13217	}
13218
13219	if (tests.csstransforms()) {
13220		/* jshint -W053 */
13221		$.support.transform = new String(prefixed('transform'));
13222		$.support.transform3d = tests.csstransforms3d();
13223	}
13224
13225})(window.Zepto || window.jQuery, window, document);
13226
13227(function(window, document, undefined) {
13228
13229    /**
13230     * Find the absolute position of an element
13231     */
13232    var absPos = function(element) {
13233        var offsetLeft, offsetTop;
13234        offsetLeft = offsetTop = 0;
13235        if (element.offsetParent) {
13236            do {
13237                offsetLeft += element.offsetLeft;
13238                offsetTop += element.offsetTop;
13239            } while (element = element.offsetParent);
13240        }
13241        return [offsetLeft, offsetTop];
13242    };
13243
13244    /**
13245     * @constructor Progress Circle class
13246     * @param params.canvas Canvas on which the circles will be drawn.
13247     * @param params.minRadius Inner radius of the innermost circle, in px.
13248     * @param params.arcWidth Width of each circle(to be more accurate, ring).
13249     * @param params.gapWidth Space between each circle.
13250     * @param params.centerX X coordinate of the center of circles.
13251     * @param params.centerY Y coordinate of the center of circles.
13252     * @param params.infoLineBaseAngle Base angle of the info line.
13253     * @param params.infoLineAngleInterval Angles between the info lines.
13254     */
13255    var ProgressCircle = function(params) {
13256        this.canvas = params.canvas;
13257        this.minRadius = params.minRadius || 15;
13258        this.arcWidth = params.arcWidth || 5;
13259        this.gapWidth = params.gapWidth || 3;
13260        this.centerX = params.centerX || this.canvas.width / 2;
13261        this.centerY = params.centerY || this.canvas.height / 2;
13262        this.infoLineLength = params.infoLineLength || 60;
13263        this.horizLineLength = params.horizLineLength || 10;
13264        this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8;
13265        this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6;
13266
13267        this.context = this.canvas.getContext('2d');
13268
13269        this.width = this.canvas.width;
13270        this.height = this.canvas.height;
13271
13272        this.circles = [];
13273        this.runningCount = 0;
13274    };
13275
13276    ProgressCircle.prototype = {
13277        constructor: ProgressCircle,
13278
13279        /**
13280         * @method Adds an progress monitor entry.
13281         * @param params.fillColor Color to fill in the circle.
13282         * @param params.outlineColor Color to outline the circle.
13283         * @param params.progressListener Callback function to fetch the progress.
13284         * @param params.infoListener Callback function to fetch the info.
13285         * @returns this
13286         */
13287        addEntry: function(params) {
13288            this.circles.push(new Circle({
13289                canvas: this.canvas,
13290                context: this.context,
13291                centerX: this.centerX,
13292                centerY: this.centerY,
13293                innerRadius: this.minRadius + this.circles.length *
13294                    (this.gapWidth + this.arcWidth),
13295                arcWidth: this.arcWidth,
13296                infoLineLength: this.infoLineLength,
13297                horizLineLength: this.horizLineLength,
13298
13299                id: this.circles.length,
13300                fillColor: params.fillColor,
13301                outlineColor: params.outlineColor,
13302                progressListener: params.progressListener,
13303                infoListener: params.infoListener,
13304                infoLineAngle: this.infoLineBaseAngle +
13305                    this.circles.length * this.infoLineAngleInterval,
13306            }));
13307
13308            return this;
13309        },
13310
13311        /**
13312         * @method Starts the monitor and updates with the given interval.
13313         * @param interval Interval between updates, in millisecond.
13314         * @returns this
13315         */
13316        start: function(interval) {
13317            var self = this;
13318            this.timer = setInterval(function() {
13319                self._update();
13320            }, interval || 33);
13321
13322            return this;
13323        },
13324
13325        /**
13326         * @method Stop the animation.
13327         */
13328        stop: function() {
13329            clearTimeout(this.timer);
13330        },
13331
13332        /**
13333         * @private
13334         * @method Call update on each circle and redraw them.
13335         * @returns this
13336         */
13337        _update: function() {
13338            this._clear();
13339            this.circles.forEach(function(circle, idx, array) {
13340                circle.update();
13341            });
13342
13343            return this;
13344        },
13345
13346        /**
13347         * @private
13348         * @method Clear the canvas.
13349         * @returns this
13350         */
13351        _clear: function() {
13352            this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
13353
13354            return this;
13355        },
13356
13357    };
13358
13359    /**
13360     * @private
13361     * @class Individual progress circle.
13362     * @param params.canvas Canvas on which the circle will be drawn.
13363     * @param params.context Context of the canvas.
13364     * @param params.innerRadius Inner radius of the circle, in px.
13365     * @param params.arcWidth Width of each arc(circle).
13366     * @param params.gapWidth Distance between each arc.
13367     * @param params.centerX X coordinate of the center of circles.
13368     * @param params.centerY Y coordinate of the center of circles.
13369     * @param params.fillColor Color to fill in the circle.
13370     * @param params.outlineColor Color to outline the circle.
13371     * @param params.progressListener Callback function to fetch the progress.
13372     * @param params.infoListener Callback function to fetch the info.
13373     * @param params.infoLineAngle Angle of info line.
13374     */
13375    var Circle = function(params) {
13376        this.id = params.id;
13377        this.canvas = params.canvas;
13378        this.context = params.context;
13379        this.centerX = params.centerX;
13380        this.centerY = params.centerY;
13381        this.arcWidth = params.arcWidth;
13382        this.innerRadius = params.innerRadius || 0;
13383        this.fillColor = params.fillColor || '#fff';
13384        this.outlineColor = params.outlineColor || this.fillColor;
13385        this.progressListener = params.progressListener;
13386        this.infoLineLength = params.infoLineLength || 250;
13387        this.horizLineLength = params.horizLineLength || 50;
13388        this.infoListener = params.infoListener;
13389        this.infoLineAngle = params.infoLineAngle;
13390
13391        this.outerRadius = this.innerRadius + this.arcWidth;
13392
13393        // If the info listener is not registered, then don't calculate
13394        // the related coordinates
13395        if (!this.infoListener) return;
13396
13397        // calculate the info-line turning points
13398        var angle = this.infoLineAngle,
13399            arcDistance = (this.innerRadius + this.outerRadius) / 2,
13400
13401            sinA = Math.sin(angle),
13402            cosA = Math.cos(angle);
13403
13404        this.infoLineStartX = this.centerX + sinA * arcDistance;
13405        this.infoLineStartY = this.centerY - cosA * arcDistance;
13406
13407        this.infoLineMidX = this.centerX + sinA * this.infoLineLength;
13408        this.infoLineMidY = this.centerY - cosA * this.infoLineLength;
13409
13410        this.infoLineEndX = this.infoLineMidX +
13411             (sinA < 0 ? -this.horizLineLength : this.horizLineLength);
13412        this.infoLineEndY = this.infoLineMidY;
13413
13414        var infoText = document.createElement('div'),
13415            style = infoText.style;
13416
13417        style.color = this.fillColor;
13418        style.position = 'absolute';
13419        style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px';
13420        // style.top will be calculated in the `drawInfo` method. Since
13421        // user may want to change the size of the font, so the top offset
13422        // must be updated in each loop.
13423        infoText.className = 'ProgressCircleInfo'; // For css styling
13424        infoText.id = 'progress_circle_info_' + this.id;
13425        document.body.appendChild(infoText);
13426        this.infoText = infoText;
13427    };
13428
13429    Circle.prototype = {
13430        constructor: Circle,
13431
13432        update: function() {
13433            this.progress = this.progressListener();
13434            this._draw();
13435
13436            if (this.infoListener) {
13437                this.info = this.infoListener();
13438                this._drawInfo();
13439            }
13440        },
13441
13442        /**
13443         * @private
13444         * @method Draw the circle on the canvas.
13445         * @returns this
13446         */
13447        _draw: function() {
13448            var ctx = this.context,
13449
13450                ANGLE_OFFSET = -Math.PI / 2,
13451
13452                startAngle = 0 + ANGLE_OFFSET,
13453                endAngle= startAngle + this.progress * Math.PI * 2,
13454
13455                x = this.centerX,
13456                y = this.centerY,
13457
13458                innerRadius = this.innerRadius - this.arcWidth - 1,
13459                outerRadius = this.outerRadius - this.arcWidth - 1;
13460
13461            ctx.fillStyle = this.fillColor;
13462            ctx.strokeStyle = this.outlineColor;
13463
13464            ctx.beginPath();
13465            ctx.arc(x, y, innerRadius, startAngle, endAngle, false);
13466            ctx.arc(x, y, outerRadius, endAngle, startAngle, true);
13467            ctx.closePath();
13468            ctx.stroke();
13469            ctx.fill();
13470
13471            return this;
13472        },
13473
13474        /**
13475         * @private
13476         * @method Draw the info lines and info text.
13477         * @returns this
13478         */
13479        _drawInfo: function() {
13480
13481            var pointList, lineHeight;
13482
13483            pointList = [
13484                [this.infoLineStartX, this.infoLineStartY],
13485                [this.infoLineMidX, this.infoLineMidY],
13486                [this.infoLineEndX, this.infoLineEndY],
13487            ];
13488            this._drawSegments(pointList, false);
13489
13490            this.infoText.innerHTML = this.info;
13491
13492            lineHeight = this.infoText.offsetHeight;
13493            this.infoText.style.top = this.infoLineEndY +
13494                absPos(this.canvas)[1] - lineHeight / 2 + 'px';
13495
13496            return this;
13497        },
13498
13499        /**
13500         * @private
13501         * @method Helper function to draw the segments
13502         * @param pointList An array of points in the form of [x, y].
13503         * @param close Whether to connect the first and last point.
13504         */
13505        _drawSegments: function(pointList, close) {
13506            var ctx = this.context;
13507
13508            ctx.beginPath();
13509            ctx.moveTo(pointList[0][0], pointList[0][1]);
13510            for (var i = 1; i < pointList.length; ++i) {
13511                ctx.lineTo(pointList[i][0], pointList[i][1]);
13512            }
13513
13514            if (close) {
13515                ctx.closePath();
13516            }
13517            ctx.stroke();
13518        },
13519    };
13520
13521    window.ProgressCircle = ProgressCircle;
13522
13523})(window, document);
13524
13525
13526
13527
13528/* =========================================================
13529 * jquery.vc_chart.js v1.0
13530 * =========================================================
13531 * Copyright 2013 Wpbakery
13532 *
13533 * Jquery chart plugin for the Visual Composer.
13534 * ========================================================= */
13535(function($){
13536    /**
13537     * Pie chart animated.
13538     * @param element - DOM element
13539     * @param options - settings object.
13540     * @constructor
13541     */
13542    var VcChart = function(element, options) {
13543        this.el = element;
13544        this.$el = $(this.el);
13545        this.options = $.extend({
13546            color: 'wpb_button',
13547            units: '',
13548            width: '',
13549            label_selector: '.vc_pie_chart_value',
13550            back_selector: '.vc_pie_chart_back',
13551            responsive: true
13552        }, options);
13553        this.init();
13554    };
13555    VcChart.prototype = {
13556        constructor: VcChart,
13557        _progress_v: 0,
13558        animated: false,
13559        colors: {
13560            'wpb_button': 'rgba(247, 247, 247, 1)',
13561            'btn-primary': 'rgba(0, 136, 204, 1)',
13562            'btn-info': 'rgba(88, 185, 218, 1)',
13563            'btn-success': 'rgba(106, 177, 101, 1)',
13564            'btn-warning': 'rgba(255, 153, 0, 1)',
13565            'btn-danger': 'rgba(255, 103, 91, 1)',
13566            'btn-inverse': 'rgba(85, 85, 85, 1)'
13567        },
13568        init: function() {
13569            this.setupColor();
13570            this.value = this.$el.data('pie-value')/100;
13571            this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value');
13572            this.$wrapper = $('.vc_pie_wrapper', this.$el);
13573            this.$label = $(this.options.label_selector, this.$el);
13574            this.$back = $(this.options.back_selector, this.$el);
13575            this.$canvas = this.$el.find('canvas');
13576            this.arcWidth = this.$el.data('pie-width') * 2;
13577            this.draw();
13578            this.setWayPoint();
13579            if(this.options.responsive === true) this.setResponsive();
13580            if (UNCODE.isMobile) this._progress_v = this.value;
13581        },
13582        setupColor: function() {
13583            // if(typeof this.colors[this.options.color] !== 'undefined') {
13584            //     this.color = this.colors[this.options.color];
13585            // } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) {
13586            //     this.color = this.options.color;
13587            // } else {
13588            //     this.color = 'rgba(247, 247, 247, 0.2)';
13589            // }
13590            if(typeof this.options.color !== 'undefined') {
13591                this.color = this.options.color;
13592            } else this.color = 'rgba(247, 247, 247, 0.2)';
13593
13594        },
13595        setResponsive: function() {
13596            var that = this;
13597            if (!UNCODE.isMobile) {
13598                $(window).resize(function(){
13599                    if(that.animated === true) that.circle.stop();
13600                    that.draw(true);
13601                });
13602            }
13603        },
13604          draw: function(redraw) {
13605            var w = this.$el.addClass('vc_ready').width() * 2,
13606                border_w = this.arcWidth,
13607                radius;
13608            if(!w) w = this.$el.parents(':visible').first().width()-2;
13609            //w = Math.round(w/100*80);
13610            //if (w < 250) w = 250;
13611            radius = w/2;
13612            this.$wrapper.css({"width" : (w / 2) + "px"});
13613            this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"});
13614            this.$back.css({"width" : (w / 2), "height" : (w / 2)});
13615            this.$canvas.attr({"width" : w + "px", "height" : w + "px"});
13616            this.$el.addClass('vc_ready');
13617            this.circle = new ProgressCircle({
13618                canvas: this.$canvas.get(0),
13619                minRadius: radius,
13620                arcWidth: border_w
13621            });
13622            if(redraw === true && this.animated === true) {
13623                this._progress_v = this.value;
13624                this.circle.addEntry({
13625                    fillColor: this.color,
13626                    progressListener: $.proxy(this.setProgress, this)
13627                }).start();
13628            }
13629        },
13630        setProgress: function() {
13631            if (this._progress_v >= this.value) {
13632                this.circle.stop();
13633                this.$label.html(this.label_value + this.options.units);
13634                return this._progress_v;
13635            }
13636            this._progress_v += 0.01;
13637            if (!isNaN(this.label_value)) {
13638                var label_value = this._progress_v/this.value*this.label_value;
13639                var val = Math.round(label_value) + this.options.units;
13640                this.$label.html(val);
13641            } else this.$label.html(this.label_value + this.options.units);
13642            return this._progress_v;
13643        },
13644        animate: function() {
13645            if(this.animated !== true) {
13646                this.animated = true;
13647                this.circle.addEntry({
13648                    fillColor: this.color,
13649                    progressListener: $.proxy(this.setProgress, this)
13650                }).start(5);
13651            }
13652        },
13653        setWayPoint: function() {
13654            if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) {
13655                this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' });
13656            } else {
13657                this.animate();
13658            }
13659        }
13660    };
13661    /**
13662     * jQuery plugin
13663     * @param option - object with settings
13664     * @return {*}
13665     */
13666    $.fn.vcChat = function(option, value) {
13667        return this.each(function () {
13668            var $this = $(this),
13669                data = $this.data('vc_chart'),
13670                options = typeof option === 'object' ? option : {
13671                    color: $this.data('pie-color'),
13672                    units: $this.data('pie-units')
13673                };
13674            if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options)));
13675            if (typeof option == 'string') data[option](value);
13676        });
13677    };
13678    /**
13679     * Allows users to rewrite function inside theme.
13680     */
13681    if ( typeof window['vc_pieChart'] !== 'function' ) {
13682        window.vc_pieChart = function() {
13683            $('.vc_pie_chart:visible').vcChat();
13684        }
13685    }
13686    $(document).ready(function(){
13687        !window.vc_iframe && vc_pieChart();
13688    });
13689
13690})(window.jQuery);
13691
13692
13693/* Progress bar
13694 ---------------------------------------------------------- */
13695function uncode_progress_bar() {    
13696	jQuery.each(jQuery('.vc_progress_bar'), function(index, val) {
13697		if (!UNCODE.isMobile) {
13698			new Waypoint({
13699				element: val,
13700				handler: function() {
13701					var element = jQuery(this.element);
13702					element.find('.vc_single_bar').each(function(index) {          
13703						var $this = jQuery(this),
13704							            bar = $this.find('.vc_bar'),
13705							            val = bar.data('percentage-value');          
13706						setTimeout(function() {            
13707							bar.css({
13708								"width": val + '%'
13709							});          
13710						}, index * 200);        
13711					});
13712				},
13713				offset: '80%'
13714			});
13715		} else {
13716			var element = jQuery(val);
13717			element.find('.vc_single_bar').each(function(index) {          
13718				var $this = jQuery(this),
13719					            bar = $this.find('.vc_bar'),
13720					            val = bar.data('percentage-value');          
13721				setTimeout(function() {            
13722					bar.css({
13723						"width": val + '%'
13724					});          
13725				}, index * 200);        
13726			});
13727		}
13728	});
13729};
13730uncode_progress_bar();
13731
13732/*!
13733 * jquery.counterup.js 1.0
13734 *
13735 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal
13736 * Released under the GPL v2 License
13737 *
13738 * Date: Nov 26, 2013
13739 */
13740(function($) {
13741	"use strict";
13742	$.fn.counterUp = function(options) {
13743		// Defaults
13744		var settings = $.extend({
13745			'time': 400,
13746			'delay': 10
13747		}, options);
13748		return this.each(function() {
13749			// Store the object
13750			var $this = $(this);
13751			var $settings = settings;
13752			var counterUpper = function() {
13753				var nums = [];
13754				var divisions = $settings.time / $settings.delay;
13755				var num = $this.text();
13756				var isComma = /[0-9]+,[0-9]+/.test(num);
13757				num = num.replace(/,/g, '');
13758				var isInt = /^[0-9]+$/.test(num);
13759				var isFloat = /^[0-9]+\.[0-9]+$/.test(num);
13760				var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0;
13761				// Generate list of incremental numbers to display
13762				for (var i = divisions; i >= 1; i--) {
13763					// Preserve as int if input was int
13764					var newNum = parseInt(num / divisions * i);
13765					// Preserve float if input was float
13766					if (isFloat) {
13767						newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces);
13768					}
13769					// Preserve commas if input had commas
13770					if (isComma) {
13771						while (/(\d+)(\d{3})/.test(newNum.toString())) {
13772							newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2');
13773						}
13774					}
13775					nums.unshift(newNum);
13776				}
13777				nums.push(num);
13778				$this.data('counterup-nums', nums);
13779				$this.text('0');
13780				// Updates the number until we're done
13781				var f = function() {
13782					if ($this.data('counterup-nums') != null) {
13783						$this.text($this.data('counterup-nums').shift());
13784						if ($this.data('counterup-nums').length) {
13785							setTimeout($this.data('counterup-func'), $settings.delay);
13786						} else {
13787							delete $this.data('counterup-nums');
13788							$this.data('counterup-nums', null);
13789							$this.data('counterup-func', null);
13790						}
13791					}
13792				};
13793				$this.data('counterup-func', f);
13794				// Start the count up
13795				setTimeout($this.data('counterup-func'), $settings.delay);
13796			};
13797			// Perform counts when the element gets into view
13798			if (!UNCODE.isMobile) {
13799				new Waypoint({
13800					element: this,
13801					handler: function() {
13802						counterUpper();
13803						this.destroy();
13804					},
13805					offset: '80%'
13806				});
13807			}
13808		});
13809	};
13810})(jQuery);
13811
13812/*!
13813 * The Final Countdown for jQuery v2.0.4 (http://hilios.github.io/jQuery.countdown/)
13814 * Copyright (c) 2014 Edson Hilios
13815 * 
13816 * Permission is hereby granted, free of charge, to any person obtaining a copy of
13817 * this software and associated documentation files (the "Software"), to deal in
13818 * the Software without restriction, including without limitation the rights to
13819 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
13820 * the Software, and to permit persons to whom the Software is furnished to do so,
13821 * subject to the following conditions:
13822 * 
13823 * The above copyright notice and this permission notice shall be included in all
13824 * copies or substantial portions of the Software.
13825 * 
13826 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13827 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
13828 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
13829 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
13830 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
13831 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13832 */
13833!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):a(jQuery)}(function(a){"use strict";function b(a){if(a instanceof Date)return a;
13833if(String(a).match(h))return String(a).match(/^[0-9]*$/)&&(a=Number(a)),String(a).match(/\-/)&&(a=String(a).replace(/\-/g,"/")),new Date(a);throw new Error("Couldn't cast `"+a+"` to a date object.")}function c(a){var b=a.toString().replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1");return new RegExp(b)}function d(a){return function(b){var d=b.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi);if(d)for(var f=0,g=d.length;g>f;++f){var h=d[f].match(/%(-|!)?([a-zA-Z]{1})(:[^;]+;)?/),j=c(h[0]),k=h[1]||"",l=h[3]||"",m=null;h=h[2],i.hasOwnProperty(h)&&(m=i[h],m=Number(a[m])),null!==m&&("!"===k&&(m=e(l,m)),""===k&&10>m&&(m="0"+m.toString()),b=b.replace(j,m.toString()))}return b=b.replace(/%%/,"%")}}function e(a,b){var c="s",d="";return a&&(a=a.replace(/(:|;|\s)/gi,"").split(/\,/),1===a.length?c=a[0]:(d=a[0],c=a[1])),1===Math.abs(b)?d:c}var f=100,g=[],h=[];h.push(/^[0-9]*$/.source),h.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source),h.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source),h=new RegExp(h.join("|"));var i={Y:"years",m:"months",w:"weeks",d:"days",D:"totalDays",H:"hours",M:"minutes",S:"seconds"},j=function(b,c,d){this.el=b,this.$el=a(b),this.interval=null,this.offset={},this.instanceNumber=g.length,g.push(this),this.$el.data("countdown-instance",this.instanceNumber),d&&(this.$el.on("update.countdown",d),this.$el.on("stoped.countdown",d),this.$el.on("finish.countdown",d)),this.setFinalDate(c),this.start()};a.extend(j.prototype,{start:function(){null!==this.interval&&clearInterval(this.interval);var a=this;this.update(),this.interval=setInterval(function(){a.update.call(a)},f)},stop:function(){clearInterval(this.interval),this.interval=null,this.dispatchEvent("stoped")},toggle:function(){this.interval?this.stop():this.start()},pause:function(){this.stop()},resume:function(){this.start()},remove:function(){this.stop.call(this),g[this.instanceNumber]=null,delete this.$el.data().countdownInstance},setFinalDate:function(a){this.finalDate=b(a)},update:function(){return 0===this.$el.closest("html").length?void this.remove():(this.totalSecsLeft=this.finalDate.getTime()-(new Date).getTime(),this.totalSecsLeft=Math.ceil(this.totalSecsLeft/1e3),this.totalSecsLeft=this.totalSecsLeft<0?0:this.totalSecsLeft,this.offset={seconds:this.totalSecsLeft%60,minutes:Math.floor(this.totalSecsLeft/60)%60,hours:Math.floor(this.totalSecsLeft/60/60)%24,days:Math.floor(this.totalSecsLeft/60/60/24)%7,totalDays:Math.floor(this.totalSecsLeft/60/60/24),weeks:Math.floor(this.totalSecsLeft/60/60/24/7),months:Math.floor(this.totalSecsLeft/60/60/24/30),years:Math.floor(this.totalSecsLeft/60/60/24/365)},void(0===this.totalSecsLeft?(this.stop(),this.dispatchEvent("finish")):this.dispatchEvent("update")))},dispatchEvent:function(b){var c=a.Event(b+".countdown");c.finalDate=this.finalDate,c.offset=a.extend({},this.offset),c.strftime=d(this.offset),this.$el.trigger(c)}}),a.fn.countdown=function(){var b=Array.prototype.slice.call(arguments,0);return this.each(function(){var c=a(this).data("countdown-instance");if(void 0!==c){var d=g[c],e=b[0];j.prototype.hasOwnProperty(e)?d[e].apply(d,b.slice(1)):null===String(e).match(/^[$A-Z_][0-9A-Z_$]*$/i)?(d.setFinalDate.call(d,e),d.start()):a.error("Method %s does not exist on jQuery.countdown".replace(/\%s/gi,e))}else new j(this,b[0],b[1])})}});
13834
13835/*! waitForImages jQuery Plugin - v2.0.2 - 2015-05-05
13836* https://github.com/alexanderdickson/waitForImages
13837* Copyright (c) 2015 Alex Dickson; Licensed MIT */
13838;(function (factory) {
13839    if (typeof define === 'function' && define.amd) {
13840        // AMD. Register as an anonymous module.
13841        define(['jquery'], factory);
13842    } else if (typeof exports === 'object') {
13843        // CommonJS / nodejs module
13844        module.exports = factory(require('jquery'));
13845    } else {
13846        // Browser globals
13847        factory(jQuery);
13848    }
13849}(function ($) {
13850    // Namespace all events.
13851    var eventNamespace = 'waitForImages';
13852
13853    // CSS properties which contain references to images.
13854    $.waitForImages = {
13855        hasImageProperties: [
13856            'backgroundImage',
13857            'listStyleImage',
13858            'borderImage',
13859            'borderCornerImage',
13860            'cursor'
13861        ],
13862        hasImageAttributes: ['srcset']
13863    };
13864
13865    // Custom selector to find `img` elements that have a valid `src`
13866    // attribute and have not already loaded.
13867    $.expr[':'].uncached = function (obj) {
13868        // Ensure we are dealing with an `img` element with a valid
13869        // `src` attribute.
13870        if (!$(obj).is('img[src][src!=""]')) {
13871            return false;
13872        }
13873
13874        return !obj.complete;
13875    };
13876
13877    $.fn.waitForImages = function () {
13878
13879        var allImgsLength = 0;
13880        var allImgsLoaded = 0;
13881        var deferred = $.Deferred();
13882
13883        var finishedCallback;
13884        var eachCallback;
13885        var waitForAll;
13886
13887        // Handle options object (if passed).
13888        if ($.isPlainObject(arguments[0])) {
13889
13890            waitForAll = arguments[0].waitForAll;
13891            eachCallback = arguments[0].each;
13892            finishedCallback = arguments[0].finished;
13893
13894        } else {
13895
13896            // Handle if using deferred object and only one param was passed in.
13897            if (arguments.length === 1 && $.type(arguments[0]) === 'boolean') {
13898                waitForAll = arguments[0];
13899            } else {
13900                finishedCallback = arguments[0];
13901                eachCallback = arguments[1];
13902                waitForAll = arguments[2];
13903            }
13904
13905        }
13906
13907        // Handle missing callbacks.
13908        finishedCallback = finishedCallback || $.noop;
13909        eachCallback = eachCallback || $.noop;
13910
13911        // Convert waitForAll to Boolean
13912        waitForAll = !! waitForAll;
13913
13914        // Ensure callbacks are functions.
13915        if (!$.isFunction(finishedCallback) || !$.isFunction(eachCallback)) {
13916            throw new TypeError('An invalid callback was supplied.');
13917        }
13918
13919        this.each(function () {
13920            // Build a list of all imgs, dependent on what images will
13921            // be considered.
13922            var obj = $(this);
13923            var allImgs = [];
13924            // CSS properties which may contain an image.
13925            var hasImgProperties = $.waitForImages.hasImageProperties || [];
13926            // Element attributes which may contain an image.
13927            var hasImageAttributes = $.waitForImages.hasImageAttributes || [];
13928            // To match `url()` references.
13929            // Spec: http://www.w3.org/TR/CSS2/syndata.html#value-def-uri
13930            var matchUrl = /url\(\s*(['"]?)(.*?)\1\s*\)/g;
13931
13932            if (waitForAll) {
13933
13934                // Get all elements (including the original), as any one of
13935                // them could have a background image.
13936                obj.find('*').addBack().each(function () {
13937                    var element = $(this);
13938
13939                    // If an `img` element, add it. But keep iterating in
13940                    // case it has a background image too.
13941                    if (element.is('img:uncached')) {
13942                        allImgs.push({
13943                            src: element.attr('src'),
13944                            element: element[0]
13945                        });
13946                    }
13947
13948                    $.each(hasImgProperties, function (i, property) {
13949                        var propertyValue = element.css(property);
13950                        var match;
13951
13952                        // If it doesn't contain this property, skip.
13953                        if (!propertyValue) {
13954                            return true;
13955                        }
13956
13957                        // Get all url() of this element.
13958                        while (match = matchUrl.exec(propertyValue)) {
13959                            allImgs.push({
13960                                src: match[2],
13961                                element: element[0]
13962                            });
13963                        }
13964                    });
13965
13966                    $.each(hasImageAttributes, function (i, attribute) {
13967                        var attributeValue = element.attr(attribute);
13968                        var attributeValues;
13969
13970                        // If it doesn't contain this property, skip.
13971                        if (!attributeValue) {
13972                            return true;
13973                        }
13974
13975                        // Check for multiple comma separated images
13976                        attributeValues = attributeValue.split(',');
13977
13978                        $.each(attributeValues, function(i, value) {
13979                            // Trim value and get string before first
13980                            // whitespace (for use with srcset).
13981                            value = $.trim(value).split(' ')[0];
13982                            allImgs.push({
13983                                src: value,
13984                                element: element[0]
13985                            });
13986                        });
13987                    });
13988                });
13989            } else {
13990                // For images only, the task is simpler.
13991                obj.find('img:uncached')
13992                    .each(function () {
13993                    allImgs.push({
13994                        src: this.src,
13995                        element: this
13996                    });
13997                });
13998            }
13999
14000            allImgsLength = allImgs.length;
14001            allImgsLoaded = 0;
14002
14003            // If no images found, don't bother.
14004            if (allImgsLength === 0) {
14005                finishedCallback.call(obj[0]);
14006                deferred.resolveWith(obj[0]);
14007            }
14008
14009            $.each(allImgs, function (i, img) {
14010
14011                var image = new Image();
14012                var events =
14013                  'load.' + eventNamespace + ' error.' + eventNamespace;
14014
14015                // Handle the image loading and error with the same callback.
14016                $(image).one(events, function me (event) {
14017                    // If an error occurred with loading the image, set the
14018                    // third argument accordingly.
14019                    var eachArguments = [
14020                        allImgsLoaded,
14021                        allImgsLength,
14022                        event.type == 'load'
14023                    ];
14024                    allImgsLoaded++;
14025
14026                    eachCallback.apply(img.element, eachArguments);
14027                    deferred.notifyWith(img.element, eachArguments);
14028
14029                    // Unbind the event listeners. I use this in addition to
14030                    // `one` as one of those events won't be called (either
14031                    // 'load' or 'error' will be called).
14032                    $(this).off(events, me);
14033
14034                    if (allImgsLoaded == allImgsLength) {
14035                        finishedCallback.call(obj[0]);
14036                        deferred.resolveWith(obj[0]);
14037                        return false;
14038                    }
14039
14040                });
14041
14042                image.src = img.src;
14043            });
14044        });
14045
14046        return deferred.promise();
14047
14048    };
14049}));
14050
14051/**
14052 * @preserve  textfill
14053 * @name      jquery.textfill.js
14054 * @author    Russ Painter
14055 * @author    Yu-Jie Lin
14056 * @author    Alexandre Dantas
14057 * @version   0.6.0
14058 * @date      2014-08-19
14059 * @copyright (c) 2014 Alexandre Dantas
14060 * @copyright (c) 2012-2013 Yu-Jie Lin
14061 * @copyright (c) 2009 Russ Painter
14062 * @license   MIT License
14063 * @homepage  https://github.com/jquery-textfill/jquery-textfill
14064 * @example   http://jquery-textfill.github.io/jquery-textfill/index.html
14065 */
14066; (function($) {
14067
14068	/**
14069	 * Resizes an inner element's font so that the
14070	 * inner element completely fills the outer element.
14071	 *
14072	 * @param {Object} options User options that take
14073	 *                         higher precedence when
14074	 *                         merging with the default ones.
14075	 *
14076	 * @return All outer elements processed
14077	 */
14078	$.fn.textfill = function(options) {
14079
14080		// ______  _______ _______ _______ _     _        _______ _______
14081		// |     \ |______ |______ |_____| |     | |         |    |______
14082		// |_____/ |______ |       |     | |_____| |_____    |    ______|
14083        //
14084		// Merging user options with the default values
14085
14086		var defaults = {
14087			debug            : false,
14088			maxFontPixels    : 40,
14089			minFontPixels    : 4,
14090			innerTag         : 'span',
14091			widthOnly        : false,
14092			success          : null, // callback when a resizing is done
14093			callback         : null, // callback when a resizing is done (deprecated, use success)
14094			fail             : null, // callback when a resizing is failed
14095			complete         : null, // callback when all is done
14096			explicitWidth    : null,
14097			explicitHeight   : null,
14098			changeLineHeight : false
14099		};
14100
14101		var Opts = $.extend(defaults, options);
14102
14103		// _______ _     _ __   _ _______ _______ _____  _____  __   _ _______
14104		// |______ |     | | \  | |          |      |   |     | | \  | |______
14105		// |       |_____| |  \_| |_____     |    __|__ |_____| |  \_| ______|
14106		//
14107		// Predefining the awesomeness
14108
14109		// Output arguments to the Debug console
14110		// if "Debug Mode" is enabled
14111		function _debug() {
14112			if (!Opts.debug
14113				||  typeof console       == 'undefined'
14114				||  typeof console.debug == 'undefined') {
14115				return;
14116			}
14117			console.debug.apply(console, arguments);
14118		}
14119
14120		// Output arguments to the Warning console
14121		function _warn() {
14122			if (typeof console      == 'undefined' ||
14123				typeof console.warn == 'undefined') {
14124				return;
14125			}
14126			console.warn.apply(console, arguments);
14127		}
14128
14129		// Outputs all information on the current sizing
14130		// of the font.
14131		function _debug_sizing(prefix, ourText, maxHeight, maxWidth, minFontPixels, maxFontPixels) {
14132
14133			function _m(v1, v2) {
14134
14135				var marker = ' / ';
14136
14137				if (v1 > v2)
14138					marker = ' > ';
14139
14140				else if (v1 == v2)
14141					marker = ' = ';
14142
14143				return marker;
14144			}
14145
14146			_debug(
14147				'[TextFill] '  + prefix + ' { ' +
14148				'font-size: ' + ourText.css('font-size') + ',' +
14149				'Height: '    + ourText.height() + 'px ' + _m(ourText.height(), maxHeight) + maxHeight + 'px,' +
14150				'Width: '     + ourText.width()  + _m(ourText.width() , maxWidth)  + maxWidth + ',' +
14151				'minFontPixels: ' + minFontPixels + 'px, ' +
14152				'maxFontPixels: ' + maxFontPixels + 'px }'
14153			);
14154		}
14155
14156		/**
14157		 * Calculates which size the font can get resized,
14158		 * according to constrains.
14159		 *
14160		 * @param {String} prefix Gets shown on the console before
14161		 *                        all the arguments, if debug mode is on.
14162		 * @param {Object} ourText The DOM element to resize,
14163		 *                         that contains the text.
14164		 * @param {function} func Function called on `ourText` that's
14165		 *                        used to compare with `max`.
14166		 * @param {number} max Maximum value, that gets compared with
14167		 *                     `func` called on `ourText`.
14168		 * @param {number} minFontPixels Minimum value the font can
14169		 *                               get resized to (in pixels).
14170		 * @param {number} maxFontPixels Maximum value the font can
14171		 *                               get resized to (in pixels).
14172		 *
14173		 * @return Size (in pixels) that the font can be resized.
14174		 */
14175		function _sizing(prefix, ourText, func, max, maxHeight, maxWidth, minFontPixels, maxFontPixels) {
14176
14177			_debug_sizing(
14178				prefix, ourText,
14179				maxHeight, maxWidth,
14180				minFontPixels, maxFontPixels
14181			);
14182
14183			// The kernel of the whole plugin, take most attention
14184			// on this part.
14185			//
14186			// This is a loop that keeps increasing the `font-size`
14187			// until it fits the parent element.
14188			//
14189			// - Start from the minimal allowed value (`minFontPixels`)
14190			// - Guesses an average font size (in pixels) for the font,
14191			// - Resizes the text and sees if its size is within the
14192			//   boundaries (`minFontPixels` and `maxFontPixels`).
14193			//   - If so, keep guessing until we break.
14194			//   - If not, return the last calculated size.
14195			//
14196			// I understand this is not optimized and we should
14197			// consider implementing something akin to
14198			// Daniel Hoffmann's answer here:
14199			//
14200			//     http://stackoverflow.com/a/17433451/1094964
14201			//
14202
14203			while (minFontPixels < (maxFontPixels - 1)) {
14204
14205				var fontSize = Math.floor((minFontPixels + maxFontPixels) / 2);
14206				ourText.css('font-size', fontSize);
14207
14208				if (func.call(ourText) <= max) {
14209					minFontPixels = fontSize;
14210
14211					if (func.call(ourText) == max)
14212						break;
14213				}
14214				else
14215					maxFontPixels = fontSize;
14216
14217				_debug_sizing(
14218					prefix, ourText,
14219					maxHeight, maxWidth,
14220					minFontPixels, maxFontPixels
14221				);
14222			}
14223
14224			ourText.css('font-size', maxFontPixels);
14225
14226			if (func.call(ourText) <= max) {
14227				minFontPixels = maxFontPixels;
14228
14229				_debug_sizing(
14230					prefix + '* ', ourText,
14231					maxHeight, maxWidth,
14232					minFontPixels, maxFontPixels
14233				);
14234			}
14235			return minFontPixels;
14236		}
14237
14238		// _______ _______ _______  ______ _______
14239		// |______    |    |_____| |_____/    |
14240		// ______|    |    |     | |    \_    |
14241        //
14242		// Let's get it started (yeah)!
14243
14244		_debug('[TextFill] Start Debug');
14245
14246		this.each(function() {
14247
14248			// Contains the child element we will resize.
14249			// $(this) means the parent container
14250			var ourText = $(Opts.innerTag + ':visible:first', this);
14251
14252			// Will resize to this dimensions.
14253			// Use explicit dimensions when specified
14254			var maxHeight = Opts.explicitHeight || $(this).height();
14255			var maxWidth  = Opts.explicitWidth  || $(this).width();
14256
14257			var oldFontSize = ourText.css('font-size');
14258
14259			var lineHeight  = parseFloat(ourText.css('line-height')) / parseFloat(oldFontSize);
14260
14261			_debug('[TextFill] Inner text: ' + ourText.text());
14262			_debug('[TextFill] All options: ', Opts);
14263			_debug('[TextFill] Maximum sizes: { ' +
14264				   'Height: ' + maxHeight + 'px, ' +
14265				   'Width: '  + maxWidth  + 'px' + ' }'
14266				  );
14267
14268			var minFontPixels = Opts.minFontPixels;
14269
14270			// Remember, if this `maxFontPixels` is negative,
14271			// the text will resize to as long as the container
14272			// can accomodate
14273			var maxFontPixels = (Opts.maxFontPixels <= 0 ?
14274								 maxHeight :
14275								 Opts.maxFontPixels);
14276
14277
14278			// Let's start it all!
14279
14280			// 1. Calculate which `font-size` would
14281			//    be best for the Height
14282			var fontSizeHeight = undefined;
14283
14284			if (! Opts.widthOnly)
14285				fontSizeHeight = _sizing(
14286					'Height', ourText,
14287					$.fn.height, maxHeight,
14288					maxHeight, maxWidth,
14289					minFontPixels, maxFontPixels
14290				);
14291
14292			// 2. Calculate which `font-size` would
14293			//    be best for the Width
14294			var fontSizeWidth = undefined;
14295
14296			fontSizeWidth = _sizing(
14297				'Width', ourText,
14298				$.fn.width, maxWidth,
14299				maxHeight, maxWidth,
14300				minFontPixels, maxFontPixels
14301			);
14302
14303			// 3. Actually resize the text!
14304
14305			if (Opts.widthOnly) {
14306				ourText.css({
14307					'font-size'  : fontSizeWidth,
14308					'white-space': 'nowrap'
14309				});
14310
14311				if (Opts.changeLineHeight)
14312					ourText.parent().css(
14313						'line-height',
14314						(lineHeight * fontSizeWidth + 'px')
14315					);
14316			}
14317			else {
14318				var fontSizeFinal = Math.min(fontSizeHeight, fontSizeWidth);
14319
14320				ourText.css('font-size', fontSizeFinal);
14321
14322				if (Opts.changeLineHeight)
14323					ourText.parent().css(
14324						'line-height',
14325						(lineHeight * fontSizeFinal) + 'px'
14326					);
14327			}
14328
14329			_debug(
14330				'[TextFill] Finished { ' +
14331				'Old font-size: ' + oldFontSize              + ', ' +
14332				'New font-size: ' + ourText.css('font-size') + ' }'
14333			);
14334
14335			// Oops, something wrong happened!
14336			// We weren't supposed to exceed the original size
14337			if ((ourText.width()  > maxWidth) ||
14338				(ourText.height() > maxHeight && !Opts.widthOnly)) {
14339
14340				ourText.css('font-size', oldFontSize);
14341
14342				// Failure callback
14343				if (Opts.fail)
14344					Opts.fail(this);
14345
14346				_debug(
14347					'[TextFill] Failure { ' +
14348					'Current Width: '  + ourText.width()  + ', ' +
14349					'Maximum Width: '  + maxWidth         + ', ' +
14350					'Current Height: ' + ourText.height() + ', ' +
14351					'Maximum Height: ' + maxHeight        + ' }'
14352				);
14353			}
14354			else if (Opts.success) {
14355				Opts.success(this);
14356			}
14357			else if (Opts.callback) {
14358				_warn('callback is deprecated, use success, instead');
14359
14360				// Success callback
14361				Opts.callback(this);
14362			}
14363		});
14364
14365		// Complete callback
14366		if (Opts.complete)
14367			Opts.complete(this);
14368
14369		_debug('[TextFill] End Debug');
14370		return this;
14371	};
14372
14373})(window.jQuery);
14374
14375
14376!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Share=e()}}(function(){var define,module,exports;
14377function getStyles(config){
14378  // return ""+config.selector+"{width:92px;height:20px;-webkit-touch-callout:none;-khtml-user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}"+config.selector+" [class*=social-]:before{font-family:'uncodeicon'}"+config.selector+" label{font-size:16px;cursor:pointer;margin:0;padding:5px 10px;border-radius:5px;background:#a29baa;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}"+config.selector+" label:hover{opacity:.8}"+config.selector+" label span{text-transform:uppercase;font-size:.9em;font-family:Lato,sans-serif;font-weight:700;-webkit-font-smoothing:antialiased;padding-left:6px}"+config.selector+" .social{opacity:0;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;margin-left:-15px;visibility:hidden}"+config.selector+" .social.top{-webkit-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0;margin-top:-80px}"+config.selector+" .social.bottom{-webkit-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0;margin-top:5px}"+config.selector+" .social.middle{margin-top:-34px}"+config.selector+" .social.middle.right{-webkit-transform-origin:5% 50%;-ms-transform-origin:5% 50%;transform-origin:5% 50%;margin-left:105px}"+config.selector+" .social.middle.left{-webkit-transform-origin:5% 50%;-ms-transform-origin:5% 50%;transform-origin:5% 50%}"+config.selector+" .social.right{margin-left:14px}"+config.selector+" .social.load{-webkit-transition:none!important;transition:none!important}"+config.selector+" .social.networks-1{width:60px}"+config.selector+" .social.networks-1.center,"+config.selector+" .social.networks-1.left{margin-left:14px}"+config.selector+" .social.networks-1.middle.left{margin-left:-70px}"+config.selector+" .social.networks-1 ul{width:60px}"+config.selector+" .social.networks-2{width:120px}"+config.selector+" .social.networks-2.center{margin-left:-13px}"+config.selector+" .social.networks-2.left{margin-left:-44px}"+config.selector+" .social.networks-2.middle.left{margin-left:-130px}"+config.selector+" .social.networks-2 ul{width:120px}"+config.selector+" .social.networks-3{width:180px}"+config.selector+" .social.networks-3.center{margin-left:-45px}"+config.selector+" .social.networks-3.left{margin-left:-102px}"+config.selector+" .social.networks-3.middle.left{margin-left:-190px}"+config.selector+" .social.networks-3 ul{width:180px}"+config.selector+" .social.networks-4{width:240px}"+config.selector+" .social.networks-4.center{margin-left:-75px}"+config.selector+" .social.networks-4.left{margin-left:162px}"+config.selector+" .social.networks-4.middle.left{margin-left:-250px}"+config.selector+" .social.networks-4 ul{width:240px}"+config.selector+" .social.networks-5{width:300px}"+config.selector+" .social.networks-5.center{margin-left:-105px}"+config.selector+" .social.networks-5.left{margin-left:-225px}"+config.selector+" .social.networks-5.middle.left{margin-left:-320px}"+config.selector+" .social.networks-5 ul{width:300px}"+config.selector+" .social.active{opacity:1;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;visibility:visible}"+config.selector+" .social.active.top{-webkit-transform:scale(1) translateY(-20px);-ms-transform:scale(1) translateY(-20px);transform:scale(1) translateY(-20px)}"+config.selector+" .social.active.bottom{-webkit-transform:scale(1) translateY(15px);-ms-transform:scale(1) translateY(15px);transform:scale(1) translateY(15px)}"+config.selector+" .social.active.middle.right{-webkit-transform:scale(1) translateX(10px);-ms-transform:scale(1) translateX(10px);transform:scale(1) translateX(10px)}"+config.selector+" .social.active.middle.left{-webkit-transform:scale(1) translateX(-20px);-ms-transform:scale(1) translateX(-20px);transform:scale(1) translateX(-20px)}"+config.selector+" .social ul{position:relative;
14378left:0;right:0;height:46px;color:#fff;margin:auto;padding:0;list-style:none}"+config.selector+" .social ul li{font-size:20px;cursor:pointer;width:60px;margin:0;padding:12px 0;text-align:center;float:left;display:none;height:22px;position:relative;z-index:2;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}"+config.selector+" .social ul li:hover{}"+config.selector+" .social li[class*=facebook]{display:"+config.networks.facebook.display+"}"+config.selector+" .social li[class*=twitter]{display:"+config.networks.twitter.display+"}"+config.selector+" .social li[class*=gplus]{display:"+config.networks.google_plus.display+"}"+config.selector+" .social li[class*=pinterest]{display:"+config.networks.pinterest.display+"}"+config.selector+" .social li[class*=paper-plane]{display:"+config.networks.email.display+"}"
14379};
14380  var ShareUtils;
14381
14382if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") {
14383  Object.defineProperty(HTMLElement.prototype, "classList", {
14384    get: function() {
14385      var ret, self, update;
14386      update = function(fn) {
14387        return function(value) {
14388          var classes, index;
14389          classes = self.className.split(/\s+/);
14390          index = classes.indexOf(value);
14391          fn(classes, index, value);
14392          self.className = classes.join(" ");
14393        };
14394      };
14395      self = this;
14396      ret = {
14397        add: update(function(classes, index, value) {
14398          ~index || classes.push(value);
14399        }),
14400        remove: update(function(classes, index) {
14401          ~index && classes.splice(index, 1);
14402        }),
14403        toggle: update(function(classes, index, value) {
14404          if (~index) {
14405            classes.splice(index, 1);
14406          } else {
14407            classes.push(value);
14408          }
14409        }),
14410        contains: function(value) {
14411          return !!~self.className.split(/\s+/).indexOf(value);
14412        },
14413        item: function(i) {
14414          return self.className.split(/\s+/)[i] || null;
14415        }
14416      };
14417      Object.defineProperty(ret, "length", {
14418        get: function() {
14419          return self.className.split(/\s+/).length;
14420        }
14421      });
14422      return ret;
14423    }
14424  });
14425}
14426
14427String.prototype.to_rfc3986 = function() {
14428  var tmp;
14429  tmp = encodeURIComponent(this);
14430  return tmp.replace(/[!'()*]/g, function(c) {
14431    return "%" + c.charCodeAt(0).toString(16);
14432  });
14433};
14434
14435ShareUtils = (function() {
14436  function ShareUtils() {}
14437
14438  ShareUtils.prototype.extend = function(to, from, overwrite) {
14439    var hasProp, prop;
14440    for (prop in from) {
14441      hasProp = to[prop] !== undefined;
14442      if (hasProp && typeof from[prop] === "object") {
14443        this.extend(to[prop], from[prop], overwrite);
14444      } else {
14445        if (overwrite || !hasProp) {
14446          to[prop] = from[prop];
14447        }
14448      }
14449    }
14450  };
14451
14452  ShareUtils.prototype.hide = function(el) {
14453    return el.style.display = "none";
14454  };
14455
14456  ShareUtils.prototype.show = function(el) {
14457    return el.style.display = "block";
14458  };
14459
14460  ShareUtils.prototype.has_class = function(el, class_name) {
14461    return el.classList.contains(class_name);
14462  };
14463
14464  ShareUtils.prototype.add_class = function(el, class_name) {
14465    return el.classList.add(class_name);
14466  };
14467
14468  ShareUtils.prototype.remove_class = function(el, class_name) {
14469    return el.classList.remove(class_name);
14470  };
14471
14472  ShareUtils.prototype.is_encoded = function(str) {
14473    str = str.to_rfc3986();
14474    return decodeURIComponent(str) !== str;
14475  };
14476
14477  ShareUtils.prototype.encode = function(str) {
14478    if (typeof str === "undefined" || this.is_encoded(str)) {
14479      return str;
14480    } else {
14481      return str.to_rfc3986();
14482    }
14483  };
14484
14485  ShareUtils.prototype.popup = function(url, params) {
14486    var k, popup, qs, v;
14487    if (params == null) {
14488      params = {};
14489    }
14490    popup = {
14491      width: 500,
14492      height: 350
14493    };
14494    popup.top = (screen.height / 2) - (popup.height / 2);
14495    popup.left = (screen.width / 2) - (popup.width / 2);
14496    qs = ((function() {
14497      var _results;
14498      _results = [];
14499      for (k in params) {
14500        v = params[k];
14501        _results.push("" + k + "=" + (this.encode(v)));
14502      }
14503      return _results;
14504    }).call(this)).join('&');
14505    if (qs) {
14506      qs = "?" + qs;
14507    }
14508    return window.open(url + qs, 'targetWindow', "toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,left=" + popup.left + ",top=" + popup.top + ",width=" 
14508+ popup.width + ",height=" + popup.height);
14509  };
14510
14511  return ShareUtils;
14512
14513})();
14514var Share,
14515  __hasProp = {}.hasOwnProperty,
14516  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
14517
14518Share = (function(_super) {
14519  __extends(Share, _super);
14520
14521  function Share(element, options) {
14522    this.element = element;
14523    this.el = {
14524      head: document.getElementsByTagName('head')[0],
14525      body: document.getElementsByTagName('body')[0]
14526    };
14527    this.config = {
14528      enabled_networks: 0,
14529      protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//',
14530      url: window.location.href,
14531      caption: null,
14532      title: this.default_title(),
14533      image: this.default_image(),
14534      description: this.default_description(),
14535      ui: {
14536        flyout: 'top center',
14537        button_text: 'Share',
14538        button_font: true,
14539        icon_font: true
14540      },
14541      networks: {
14542        google_plus: {
14543          enabled: true,
14544          url: null
14545        },
14546        twitter: {
14547          enabled: true,
14548          url: null,
14549          title: null,
14550          description: null
14551        },
14552        facebook: {
14553          enabled: true,
14554          load_sdk: true,
14555          url: null,
14556          app_id: null,
14557          title: null,
14558          caption: null,
14559          description: null,
14560          image: null
14561        },
14562        pinterest: {
14563          enabled: true,
14564          url: null,
14565          image: null,
14566          description: null
14567        },
14568        reddit: {
14569          enabled: true,
14570          url: null,
14571          title: null
14572        },
14573        linkedin: {
14574          enabled: true,
14575          url: null,
14576          title: null,
14577          description: null
14578        },
14579        xing: {
14580          enabled: true,
14581          url: null,
14582          title: null,
14583          image: null,
14584          description: null
14585        },
14586        whatsapp: {
14587          enabled: true,
14588          description: null,
14589          url: null
14590        },
14591        email: {
14592          enabled: true,
14593          title: null,
14594          description: null,
14595          url: null
14596        }
14597      }
14598    };
14599    this.setup(element, options);
14600    return this;
14601  }
14602
14603  Share.prototype.setup = function(element, opts) {
14604    var index, instance, instances, _i, _len;
14605    instances = document.querySelectorAll(element);
14606    this.extend(this.config, opts, true);
14607    this.set_global_configuration();
14608    this.normalize_network_configuration();
14609    if (this.config.ui.icon_font) {
14610      this.inject_icons();
14611    }
14612    if (this.config.ui.button_font) {
14613      this.inject_fonts();
14614    }
14615    if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) {
14616      this.inject_facebook_sdk();
14617    }
14618    for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) {
14619      instance = instances[index];
14620      this.setup_instance(element, index);
14621    }
14622  };
14623
14624  Share.prototype.setup_instance = function(element, index) {
14625    var button, instance, label, network, networks, _i, _len, _results,
14626      _this = this;
14627    instance = document.querySelectorAll(element)[index];
14628    this.hide(instance);
14629    this.add_class(instance, "sharer-" + index);
14630    instance = document.querySelectorAll(element)[index];
14631    this.inject_css(instance);
14632    this.inject_html(instance);
14633    this.show(instance);
14634    label = instance.getElementsByTagName("label")[0];
14635    button = instance.getElementsByClassName("social")[0];
14636    networks = instance.getElementsByTagName('li');
14637    this.add_class(button, "networks-" + this.config.enabled_networks);
14638    label.addEventListener("click", function() {
14639      return _this.event_toggle(button);
14640    });
14641    _this = this;
14642    _results = [];
14643    for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) {
14644      network = networks[index];
14645      _results.push(network.addEventListener("click", function() {
14646        _this.event_network(instance, this);
14647        return _this.event_close(button);
14648      }));
14649    }
14650    return _results;
14651  };
14652
14653  Share.prototype.event_toggle = function(button) {
14654    if (this.has_class(button, "active")) {
14655      return this.event_close(button);
14656    } else {
14657      return this.event_open(button);
14658    }
14659  };
14660
14661  Share.prototype.event_open = function(button) {
14662    if (this.has_class(button, "load")) {
14663      this.remove_class(button, "load");
14664    }
14665    return this.add_class(button, "active");
14666  };
14667
14668  Share.prototype.event_close = function(button) {
14669    return this.remove_class(button, "active");
14670  };
14671
14672  Share.prototype.event_network = function(instance, network) {
14673    var name;
14674    name = network.getAttribute("data-network");
14675    this.hook("before", name, instance);
14676    this["network_" + name]();
14677    return this.hook("after", name, instance);
14678  };
14679
14680  Share.prototype.open = function() {
14681    return this["public"]("open");
14682  };
14683
14684  Share.prototype.close = function() {
14685    return this["public"]("close");
14686  };
14687
14688  Share.prototype.toggle = function() {
14689    return this["public"]("toggle");
14690  };
14691
14692  Share.prototype["public"] = function(action) {
14693    var button, index, instance, _i, _len, _ref, _results;
14694    _ref = document.querySelectorAll(this.element);
14695    _results = [];
14696    for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
14697      instance = _ref[index];
14698      button = instance.getElementsByClassName("social")[0];
14699      _results.push(this["event_" + action](button));
14700    }
14701    return _results;
14702  };
14703
14704  Share.prototype.network_facebook = function() {
14705    if (this.config.networks.facebook.load_sdk) {
14706      if (!window.FB) {
14707        return console.error("The Facebook JS SDK hasn't loaded yet.");
14708      }
14709      return FB.ui({
14710        method: 'feed',
14711        name: this.config.networks.facebook.title,
14712        link: this.config.networks.facebook.url,
14713        picture: this.config.networks.facebook.image,
14714        caption: this.config.networks.facebook.caption,
14715        description: this.config.networks.facebook.description
14716      });
14717    } else {
14718      return this.popup('https://www.facebook.com/sharer/sharer.php', {
14719        u: this.config.networks.facebook.url
14720      });
14721    }
14722  };
14723
14724  Share.prototype.network_twitter = function() {
14725    return this.popup('https://twitter.com/intent/tweet', {
14726      text: this.config.networks.twitter.title,
14727      url: this.config.networks.twitter.url
14728    });
14729  };
14730
14731  Share.prototype.network_google_plus = function() {
14732    return this.popup('https://plus.google.com/share', {
14733      url: this.config.networks.google_plus.url
14734    });
14735  };
14736
14737  Share.prototype.network_pinterest = function() {
14738    return this.popup('https://www.pinterest.com/pin/create/button', {
14739      url: this.config.networks.pinterest.url,
14740      media: this.config.networks.pinterest.image,
14741      description: this.config.networks.pinterest.description
14742    });
14743  };
14744
14745  Share.prototype.network_linkedin = function() {
14746    return this.popup('https://www.linkedin.com/shareArticle', {
14747      url: this.config.networks.linkedin.url,
14748      title: this.config.networks.linkedin.title,
14749      summary: this.config.networks.linkedin.description
14750    });
14751  }
14752
14753  Share.prototype.network_xing = function() {
14754    return this.popup('https://www.xing.com/spi/shares/new', {
14755      url: this.config.networks.xing.url,
14756      image: this.config.networks.xing.image,
14757      title: this.config.networks.xing.title,
14758      summary: this.config.networks.xing.description
14759    });
14760  }
14761
14762  Share.prototype.network_email = function() {
14763    return this.popup('mailto:', {
14764      subject: this.config.networks.email.title,
14765      body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description,
14766    });
14767  };
14768
14769  Share.prototype.inject_icons = function() {
14770  //  return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css");
14771  };
14772
14773  Share.prototype.inject_fonts = function() {
14774   // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text);
14775  };
14776
14777  Share.prototype.inject_stylesheet = function(url) {
14778    var link;
14779    if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) {
14780      link = document.createElement("link");
14781      link.setAttribute("rel", "stylesheet");
14782      link.setAttribute("href", url);
14783      return this.el.head.appendChild(link);
14784    }
14785  };
14786
14787  Share.prototype.inject_css = function(instance) {
14788    var css, meta, selector, style;
14789    selector = "." + (instance.getAttribute('class').split(" ").join("."));
14790    if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) {
14791      this.config.selector = selector;
14792      css = getStyles(this.config);
14793      style = document.createElement("style");
14794      style.type = "text/css";
14795      if (style.styleSheet) {
14796        style.styleSheet.cssText = css;
14797      } else {
14798        style.appendChild(document.createTextNode(css));
14799      }
14800      this.el.head.appendChild(style);
14801      delete this.config.selector;
14802      meta = document.createElement("meta");
14803      meta.setAttribute("name", "sharer" + selector);
14804      return this.el.head.appendChild(meta);
14805    }
14806  };
14807
14808  Share.prototype.inject_html = function(instance) {
14809    return instance.innerHTML = "<label class='social-export'><span>" + this.config.ui.button_text + "</span></label><div class='social load " + this.config.ui.flyout + "'><ul><li class='social-facebook' data-network='facebook' tabindex='0'></li><li class='social-twitter' data-network='twitter' tabindex='0'></li><li class='social-gplus' data-network='google_plus' tabindex='0'></li><li class='social-pinterest' data-network='pinterest' tabindex='0'></li><li class='social-linkedin' data-network='linkedin' tabindex='0'></li><li class='social-xing' data-network='xing' tabindex='0'></li><li class='social-paper-plane' data-network='email' tabindex='0'></li></ul></div>";
14810  };
14811
14812  Share.prototype.inject_facebook_sdk = function() {
14813    var fb_root, script;
14814    if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) {
14815      script = document.createElement("script");
14816      script.text = "window.fbAsyncInit=function(){FB.init({appId:'" + this.config.networks.facebook.app_id + "',status:true,xfbml:true})};(function(e,t,n){var r,i=e.getElementsByTagName(t)[0];if(e.getElementById(n)){return}r=e.createElement(t);r.id=n;r.src='" + this.config.protocol + "connect.facebook.net/en_US/all.js';i.parentNode.insertBefore(r,i)})(document,'script','facebook-jssdk')";
14817      fb_root = document.createElement("div");
14818      fb_root.id = "fb-root";
14819      this.el.body.appendChild(fb_root);
14820      return this.el.body.appendChild(script);
14821    }
14822  };
14823
14824  Share.prototype.hook = function(type, network, instance) {
14825    var fn, opts;
14826    fn = this.config.networks[network][type];
14827    if (typeof fn === "function") {
14828      opts = fn.call(this.config.networks[network], instance);
14829      if (opts !== void 0) {
14830        opts = this.normalize_filter_config_updates(opts);
14831        this.extend(this.config.networks[network], opts, true);
14832        this.normalize_network_configuration();
14833      }
14834    }
14835  };
14836
14837  Share.prototype.default_title = function() {
14838    var content;
14839    if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) {
14840      return encodeURIComponent(content.getAttribute('content'));
14841    } else if (content = document.querySelector('title')) {
14842      return encodeURIComponent(content.innerText);
14843    }
14844  };
14845
14846  Share.prototype.default_image = function() {
14847    var content;
14848    if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) {
14849      return content.getAttribute('content');
14850    }
14851  };
14852
14853  Share.prototype.default_description = function() {
14854    var content;
14855    if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) {
14856      return content.getAttribute('content');
14857    } else {
14858      return '';
14859    }
14860  };
14861
14862  Share.prototype.set_global_configuration = function() {
14863    var display, network, option, options, _ref, _results;
14864    _ref = this.config.networks;
14865    _results = [];
14866    for (network in _ref) {
14867      options = _ref[network];
14868      for (option in options) {
14869        if (this.config.networks[network][option] == null) {
14870          this.config.networks[network][option] = this.config[option];
14871        }
14872      }
14873      if (this.config.networks[network].enabled) {
14874        display = 'block';
14875        this.config.enabled_networks += 1;
14876      } else {
14877        display = 'none';
14878      }
14879      _results.push(this.config.networks[network].display = display);
14880    }
14881    return _results;
14882  };
14883
14884  Share.prototype.normalize_network_configuration = function() {
14885    if (!this.config.networks.facebook.app_id) {
14886      this.config.networks.facebook.load_sdk = false;
14887    }
14888    if (!this.is_encoded(this.config.networks.twitter.description)) {
14889      this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description);
14890    }
14891    if (typeof this.config.networks.facebook.app_id === 'number') {
14892      return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString();
14893    }
14894  };
14895
14896  Share.prototype.normalize_filter_config_updates = function(opts) {
14897    if (this.config.networks.facebook.app_id !== opts.app_id) {
14898      console.warn("You are unable to change the Facebook app_id after the button has been initialized. Please-in-out update your Facebook filters accordingly.");
14899      delete opts.app_id;
14900    }
14901    if (this.config.networks.facebook.load_sdk !== opts.load_sdk) {
14902      console.warn("You are unable to change the Facebook load_sdk option after the button has been initialized. Please-in-out update your Facebook filters accordingly.");
14903      delete opts.app_id;
14904    }
14905    return opts;
14906  };
14907
14908  return Share;
14909
14910})(ShareUtils);
14911 return Share;
14912});
14913
14914
14915// Generated by CoffeeScript 1.9.2
14916
14917// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net
14918
14919(function() {
14920  var $, win;
14921
14922  $ = this.jQuery || window.jQuery;
14923
14924  win = $(window);
14925
14926  $.fn.stick_in_parent = function(opts) {
14927    var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class;
14928    if (opts == null) {
14929      opts = {};
14930    }
14931    sticky_class = opts.sticky_class, inner_scrolling = opts.inner_scrolling, recalc_every = opts.recalc_every, parent_selector = opts.parent, offset_top = opts.offset_top, manual_spacer = opts.spacer, enable_bottoming = opts.bottoming;
14932    if (offset_top == null) {
14933      offset_top = 0;
14934    }
14935    if (parent_selector == null) {
14936      parent_selector = void 0;
14937    }
14938    if (inner_scrolling == null) {
14939      inner_scrolling = true;
14940    }
14941    if (sticky_class == null) {
14942      sticky_class = "is_stuck";
14943    }
14944    doc = $(document);
14945    if (enable_bottoming == null) {
14946      enable_bottoming = true;
14947    }
14948    outer_width = function(el) {
14949      var _el, computed, w;
14950      if (window.getComputedStyle) {
14951        _el = el[0];
14952        computed = window.getComputedStyle(el[0]);
14953        w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right"));
14954        if (computed.getPropertyValue("box-sizing") !== "border-box") {
14955          w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right"));
14956        }
14957        return w;
14958      } else {
14959        return el.outerWidth(true);
14960      }
14961    };
14962    fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) {
14963      var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick;
14964      if (elm.data("sticky_kit")) {
14965        return;
14966      }
14967      elm.data("sticky_kit", true);
14968      last_scroll_height = doc.height();
14969      parent = elm.parent();
14970      if (parent_selector != null) {
14971        parent = parent.closest(parent_selector);
14972      }
14973      if (!parent.length) {
14974        throw "failed to find stick parent";
14975      }
14976      fixed = false;
14977      bottomed = false;
14978      spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />");
14979      if (spacer) {
14980        spacer.css('position', elm.css('position'));
14981      }
14982      recalc = function() {
14983        var border_top, padding_top, restore;
14984        if (detached) {
14985          return;
14986        }
14987        last_scroll_height = doc.height();
14988        border_top = parseInt(parent.css("border-top-width"), 10);
14989        padding_top = parseInt(parent.css("padding-top"), 10);
14990        padding_bottom = parseInt(parent.css("padding-bottom"), 10);
14991        parent_top = parent.offset().top + border_top + padding_top;
14992        parent_height = parent.height();
14993        if (fixed) {
14994          fixed = false;
14995          bottomed = false;
14996          if (manual_spacer == null) {
14997            elm.insertAfter(spacer);
14998            spacer.detach();
14999          }
15000          elm.css({
15001            position: "",
15002            top: "",
15003            width: "",
15004            bottom: ""
15005          }).removeClass(sticky_class);
15006          restore = true;
15007        }
15008        top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top;
15009        height = elm.outerHeight(true);
15010        el_float = elm.css("float");
15011        if (spacer) {
15012          spacer.css({
15013            width: outer_width(elm),
15014            height: height,
15015            display: elm.css("display"),
15016            "vertical-align": elm.css("vertical-align"),
15017            "float": el_float
15018          });
15019        }
15020        if (restore) {
15021          return tick();
15022        }
15023      };
15024      recalc();
15025      if (height === parent_height) {
15026        return;
15027      }
15028      last_pos = void 0;
15029      offset = offset_top;
15030      recalc_counter = recalc_every;
15031      tick = function() {
15032        var css, delta, recalced, scroll, will_bottom, win_height;
15033        if (detached) {
15034          return;
15035        }
15036        recalced = false;
15037        if (recalc_counter != null) {
15038          recalc_counter -= 1;
15039          if (recalc_counter <= 0) {
15040            recalc_counter = recalc_every;
15041            recalc();
15042            recalced = true;
15043          }
15044        }
15045        if (!recalced && doc.height() !== last_scroll_height) {
15046          recalc();
15047          recalced = true;
15048        }
15049        scroll = win.scrollTop();
15050        if (last_pos != null) {
15051          delta = scroll - last_pos;
15052        }
15053        last_pos = scroll;
15054        if (fixed) {
15055          if (enable_bottoming) {
15056            will_bottom = scroll + height + offset > parent_height + parent_top;
15057            if (bottomed && !will_bottom) {
15058              bottomed = false;
15059              elm.css({
15060                position: "fixed",
15061                bottom: "",
15062                top: offset
15063              }).trigger("sticky_kit:unbottom");
15064            }
15065          }
15066          if (scroll < top) {
15067            fixed = false;
15068            offset = offset_top;
15069            if (manual_spacer == null) {
15070              if (el_float === "left" || el_float === "right") {
15071                elm.insertAfter(spacer);
15072              }
15073              spacer.detach();
15074            }
15075            css = {
15076              position: "",
15077              width: "",
15078              top: ""
15079            };
15080            elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick");
15081          }
15082          if (inner_scrolling) {
15083            win_height = win.height();
15084            if (height + offset_top > win_height) {
15085              if (!bottomed) {
15086                offset -= delta;
15087                offset = Math.max(win_height - height, offset);
15088                offset = Math.min(offset_top, offset);
15089                if (fixed) {
15090                  elm.css({
15091                    top: offset + "px"
15092                  });
15093                }
15094              }
15095            }
15096          }
15097        } else {
15098          if (scroll > top) {
15099            fixed = true;
15100            css = {
15101              position: "fixed",
15102              top: offset
15103            };
15104            css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px";
15105            elm.css(css).addClass(sticky_class);
15106            if (manual_spacer == null) {
15107              elm.after(spacer);
15108              if (el_float === "left" || el_float === "right") {
15109                spacer.append(elm);
15110              }
15111            }
15112            elm.trigger("sticky_kit:stick");
15113          }
15114        }
15115        if (fixed && enable_bottoming) {
15116          if (will_bottom == null) {
15117            will_bottom = scroll + height + offset > parent_height + parent_top;
15118          }
15119          if (!bottomed && will_bottom) {
15120            bottomed = true;
15121            if (parent.css("position") === "static") {
15122              parent.css({
15123                position: "relative"
15124              });
15125            }
15126            return elm.css({
15127              position: "absolute",
15128              bottom: padding_bottom,
15129              top: "auto"
15130            }).trigger("sticky_kit:bottom");
15131          }
15132        }
15133      };
15134      recalc_and_tick = function() {
15135        recalc();
15136        return tick();
15137      };
15138      detach = function() {
15139        detached = true;
15140        win.off("touchmove", tick);
15141        win.off("scroll", tick);
15142        win.off("resize", recalc_and_tick);
15143        $(document.body).off("sticky_kit:recalc", recalc_and_tick);
15144        elm.off("sticky_kit:detach", detach);
15145        elm.removeData("sticky_kit");
15146        elm.css({
15147          position: "",
15148          bottom: "",
15149          top: "",
15150          width: ""
15151        });
15152        parent.position("position", "");
15153        if (fixed) {
15154          if (manual_spacer == null) {
15155            if (el_float === "left" || el_float === "right") {
15156              elm.insertAfter(spacer);
15157            }
15158            spacer.remove();
15159          }
15160          return elm.removeClass(sticky_class);
15161        }
15162      };
15163      win.on("touchmove", tick);
15164      win.on("scroll", tick);
15165      win.on("resize", recalc_and_tick);
15166      $(document.body).on("sticky_kit:recalc", recalc_and_tick);
15167      elm.on("sticky_kit:detach", detach);
15168      return setTimeout(tick, 0);
15169    };
15170    for (i = 0, len = this.length; i < len; i++) {
15171      elm = this[i];
15172      fn($(elm));
15173    }
15174    return this;
15175  };
15176
15177}).call(this);
15178
15179
15180
15181/* ========================================================================
15182 * Bootstrap: collapse.js v3.1.1
15183 * http://getbootstrap.com/javascript/#collapse
15184 * ========================================================================
15185 * Copyright 2011-2014 Twitter, Inc.
15186 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
15187 * ======================================================================== */
15188
15189
15190+function ($) {
15191  'use strict';
15192
15193  // COLLAPSE PUBLIC CLASS DEFINITION
15194  // ================================
15195
15196  var Collapse = function (element, options) {
15197    this.$element      = $(element)
15198    this.options       = $.extend({}, Collapse.DEFAULTS, options)
15199    this.transitioning = null
15200
15201    if (this.options.parent) this.$parent = $(this.options.parent)
15202    if (this.options.toggle) this.toggle()
15203  }
15204
15205  Collapse.DEFAULTS = {
15206    toggle: true
15207  }
15208
15209  Collapse.prototype.dimension = function () {
15210    var hasWidth = this.$element.hasClass('width')
15211    return hasWidth ? 'width' : 'height'
15212  }
15213
15214  Collapse.prototype.show = function () {
15215    if (this.transitioning || this.$element.hasClass('in')) return
15216
15217    var startEvent = $.Event('show.bs.collapse')
15218    this.$element.trigger(startEvent)
15219    if (startEvent.isDefaultPrevented()) return
15220
15221    var actives = this.$parent && this.$parent.find('> .panel > .in')
15222
15223    if (actives && actives.length) {
15224      var hasData = actives.data('bs.collapse')
15225      if (hasData && hasData.transitioning) return
15226      actives.collapse('hide')
15227      hasData || actives.data('bs.collapse', null)
15228    }
15229
15230    var dimension = this.dimension()
15231
15232    this.$element
15233      .removeClass('collapse')
15234      .addClass('collapsing')[dimension](0)
15235
15236    this.transitioning = 1
15237
15238    var complete = function (e) {
15239      if (e && e.target != this.$element[0]) return
15240      this.$element
15241        .removeClass('collapsing')
15242        .addClass('collapse in')[dimension]('auto')
15243      this.transitioning = 0
15244      this.$element.trigger('shown.bs.collapse')
15245    }
15246
15247    if (!$.support.transition) return complete.call(this)
15248
15249    var scrollSize = $.camelCase(['scroll', dimension].join('-'))
15250
15251    this.$element
15252      .one($.support.transition.end, $.proxy(complete, this))
15253      .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
15254  }
15255
15256  Collapse.prototype.hide = function () {
15257    if (this.transitioning || !this.$element.hasClass('in')) return
15258
15259    var startEvent = $.Event('hide.bs.collapse')
15260    this.$element.trigger(startEvent)
15261    if (startEvent.isDefaultPrevented()) return
15262
15263    var dimension = this.dimension()
15264
15265    this.$element[dimension](this.$element[dimension]())[0].offsetHeight
15266
15267    this.$element
15268      .addClass('collapsing')
15269      .removeClass('collapse')
15270      .removeClass('in')
15271
15272    this.transitioning = 1
15273
15274    var complete = function (e) {
15275      if (e && e.target != this.$element[0]) return
15276      this.transitioning = 0
15277      this.$element
15278        .trigger('hidden.bs.collapse')
15279        .removeClass('collapsing')
15280        .addClass('collapse')
15281    }
15282
15283    if (!$.support.transition) return complete.call(this)
15284
15285    this.$element
15286      [dimension](0)
15287      .one($.support.transition.end, $.proxy(complete, this))
15288      .emulateTransitionEnd(350)
15289  }
15290
15291  Collapse.prototype.toggle = function () {
15292    this[this.$element.hasClass('in') ? 'hide' : 'show']()
15293  }
15294
15295
15296  // COLLAPSE PLUGIN DEFINITION
15297  // ==========================
15298
15299  var old = $.fn.collapse
15300
15301  $.fn.collapse = function (option) {
15302    return this.each(function () {
15303      var $this   = $(this)
15304      var data    = $this.data('bs.collapse')
15305      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
15306
15307      if (!data && options.toggle && option == 'show') option = !option
15308      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
15309      if (typeof option == 'string') data[option]()
15310    })
15311  }
15312
15313  $.fn.collapse.Constructor = Collapse
15314
15315
15316  // COLLAPSE NO CONFLICT
15317  // ====================
15318
15319  $.fn.collapse.noConflict = function () {
15320    $.fn.collapse = old
15321    return this
15322  }
15323
15324
15325  // COLLAPSE DATA-API
15326  // =================
15327
15328  $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
15329    var $this   = $(this), href
15330    var target  = $this.attr('data-target')
15331        || e.preventDefault()
15332        || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
15333    var $target = $(target)
15334    var data    = $target.data('bs.collapse')
15335    var option  = data ? 'toggle' : $this.data()
15336    var parent  = $this.attr('data-parent')
15337    var $parent = parent && $(parent)
15338
15339    if (!data || !data.transitioning) {
15340      if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed')
15341      $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
15342    }
15343
15344    $target.collapse(option)
15345  })
15346
15347}(jQuery);
15348
15349
15350/* ========================================================================
15351 * Bootstrap: tab.js v3.1.1
15352 * http://getbootstrap.com/javascript/#tabs
15353 * ========================================================================
15354 * Copyright 2011-2014 Twitter, Inc.
15355 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
15356 * ======================================================================== */
15357
15358
15359+function ($) {
15360  'use strict';
15361
15362  // TAB CLASS DEFINITION
15363  // ====================
15364
15365  var Tab = function (element) {
15366    this.element = $(element)
15367  }
15368
15369  Tab.prototype.show = function () {
15370    var $this    = this.element
15371    var $ul      = $this.closest('ul:not(.dropdown-menu)')
15372    var selector = $this.data('target')
15373
15374    if (!selector) {
15375      selector = $this.attr('href')
15376      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
15377    }
15378
15379    if ($this.parent('li').hasClass('active')) return
15380
15381    var previous = $ul.find('.active:last a')[0]
15382    var e        = $.Event('show.bs.tab', {
15383      relatedTarget: previous
15384    })
15385
15386    $this.trigger(e)
15387
15388    if (e.isDefaultPrevented()) return
15389
15390    var $target = $(selector)
15391
15392    this.activate($this.parent('li'), $ul)
15393    this.activate($target, $target.parent(), function () {
15394      $this.trigger({
15395        type: 'shown.bs.tab',
15396        relatedTarget: previous
15397      })
15398    })
15399  }
15400
15401  Tab.prototype.activate = function (element, container, callback) {
15402    var $active    = container.find('> .active')
15403    var transition = callback
15404      && $.support.transition
15405      && $active.hasClass('fade')
15406
15407    function next() {
15408      $active
15409        .removeClass('active')
15410        .find('> .dropdown-menu > .active')
15411        .removeClass('active')
15412
15413      element.addClass('active')
15414
15415      if (transition) {
15416        element[0].offsetWidth // reflow for transition
15417        element.addClass('in')
15418      } else {
15419        element.removeClass('fade')
15420      }
15421
15422      if (element.parent('.dropdown-menu')) {
15423        element.closest('li.dropdown').addClass('active')
15424      }
15425
15426      callback && callback()
15427    }
15428
15429    transition ?
15430      $active
15431        .one($.support.transition.end, next)
15432        .emulateTransitionEnd(150) :
15433      next()
15434
15435    $active.removeClass('in')
15436  }
15437
15438
15439  // TAB PLUGIN DEFINITION
15440  // =====================
15441
15442  var old = $.fn.tab
15443
15444  $.fn.tab = function ( option ) {
15445    return this.each(function () {
15446      var $this = $(this)
15447      var data  = $this.data('bs.tab')
15448
15449      if (!data) $this.data('bs.tab', (data = new Tab(this)))
15450      if (typeof option == 'string') data[option]()
15451    })
15452  }
15453
15454  $.fn.tab.Constructor = Tab
15455
15456
15457  // TAB NO CONFLICT
15458  // ===============
15459
15460  $.fn.tab.noConflict = function () {
15461    $.fn.tab = old
15462    return this
15463  }
15464
15465
15466  // TAB DATA-API
15467  // ============
15468
15469  $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
15470    e.preventDefault()
15471    $(this).tab('show')
15472  })
15473
15474}(jQuery);
15475
15476
15477/* ========================================================================
15478 * Bootstrap: tooltip.js v3.1.1
15479 * http://getbootstrap.com/javascript/#tooltip
15480 * Inspired by the original jQuery.tipsy by Jason Frame
15481 * ========================================================================
15482 * Copyright 2011-2014 Twitter, Inc.
15483 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
15484 * ======================================================================== */
15485
15486
15487+function ($) {
15488  'use strict';
15489
15490  // TOOLTIP PUBLIC CLASS DEFINITION
15491  // ===============================
15492
15493  var Tooltip = function (element, options) {
15494    this.type       =
15495    this.options    =
15496    this.enabled    =
15497    this.timeout    =
15498    this.hoverState =
15499    this.$element   = null
15500
15501    this.init('tooltip', element, options)
15502  }
15503
15504  Tooltip.DEFAULTS = {
15505    animation: true,
15506    placement: 'top',
15507    selector: false,
15508    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
15509    trigger: 'hover focus',
15510    title: '',
15511    delay: 0,
15512    html: false,
15513    container: false,
15514    viewport: {
15515      selector: 'body',
15516      padding: 0
15517    }
15518  }
15519
15520  Tooltip.prototype.init = function (type, element, options) {
15521    this.enabled   = true
15522    this.type      = type
15523    this.$element  = $(element)
15524    this.options   = this.getOptions(options)
15525    this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
15526
15527    var triggers = this.options.trigger.split(' ')
15528
15529    for (var i = triggers.length; i--;) {
15530      var trigger = triggers[i]
15531
15532      if (trigger == 'click') {
15533        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
15534      } else if (trigger != 'manual') {
15535        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
15536        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
15537
15538        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
15539        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
15540      }
15541    }
15542
15543    this.options.selector ?
15544      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
15545      this.fixTitle()
15546  }
15547
15548  Tooltip.prototype.getDefaults = function () {
15549    return Tooltip.DEFAULTS
15550  }
15551
15552  Tooltip.prototype.getOptions = function (options) {
15553    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
15554
15555    if (options.delay && typeof options.delay == 'number') {
15556      options.delay = {
15557        show: options.delay,
15558        hide: options.delay
15559      }
15560    }
15561
15562    return options
15563  }
15564
15565  Tooltip.prototype.getDelegateOptions = function () {
15566    var options  = {}
15567    var defaults = this.getDefaults()
15568
15569    this._options && $.each(this._options, function (key, value) {
15570      if (defaults[key] != value) options[key] = value
15571    })
15572
15573    return options
15574  }
15575
15576  Tooltip.prototype.enter = function (obj) {
15577    var self = obj instanceof this.con
15577structor ?
15578      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
15579
15580    clearTimeout(self.timeout)
15581
15582    self.hoverState = 'in'
15583
15584    if (!self.options.delay || !self.options.delay.show) return self.show()
15585
15586    self.timeout = setTimeout(function () {
15587      if (self.hoverState == 'in') self.show()
15588    }, self.options.delay.show)
15589  }
15590
15591  Tooltip.prototype.leave = function (obj) {
15592    var self = obj instanceof this.constructor ?
15593      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
15594
15595    clearTimeout(self.timeout)
15596
15597    self.hoverState = 'out'
15598
15599    if (!self.options.delay || !self.options.delay.hide) return self.hide()
15600
15601    self.timeout = setTimeout(function () {
15602      if (self.hoverState == 'out') self.hide()
15603    }, self.options.delay.hide)
15604  }
15605
15606  Tooltip.prototype.show = function () {
15607    var e = $.Event('show.bs.' + this.type)
15608
15609    if (this.hasContent() && this.enabled) {
15610      this.$element.trigger(e)
15611
15612      if (e.isDefaultPrevented()) return
15613      var that = this;
15614
15615      var $tip = this.tip()
15616
15617      this.setContent()
15618
15619      if (this.options.animation) $tip.addClass('fade')
15620
15621      var placement = typeof this.options.placement == 'function' ?
15622        this.options.placement.call(this, $tip[0], this.$element[0]) :
15623        this.options.placement
15624
15625      var autoToken = /\s?auto?\s?/i
15626      var autoPlace = autoToken.test(placement)
15627      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
15628
15629      $tip
15630        .detach()
15631        .css({ top: 0, left: 0, display: 'block' })
15632        .addClass(placement)
15633
15634      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
15635
15636      var pos          = this.getPosition()
15637      var actualWidth  = $tip[0].offsetWidth
15638      var actualHeight = $tip[0].offsetHeight
15639
15640      if (autoPlace) {
15641        var orgPlacement = placement
15642        var $parent      = this.$element.parent()
15643        var parentDim    = this.getPosition($parent)
15644
15645        placement = placement == 'bottom' && pos.top   + pos.height       + actualHeight - parentDim.scroll > parentDim.height ? 'top'    :
15646                    placement == 'top'    && pos.top   - parentDim.scroll - actualHeight < 0                                   ? 'bottom' :
15647                    placement == 'right'  && pos.right + actualWidth      > parentDim.width                                    ? 'left'   :
15648                    placement == 'left'   && pos.left  - actualWidth      < parentDim.left                                     ? 'right'  :
15649                    placement
15650
15651        $tip
15652          .removeClass(orgPlacement)
15653          .addClass(placement)
15654      }
15655
15656      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
15657
15658      this.applyPlacement(calculatedOffset, placement)
15659      this.hoverState = null
15660
15661      var complete = function() {
15662        that.$element.trigger('shown.bs.' + that.type)
15663      }
15664
15665      $.support.transition && this.$tip.hasClass('fade') ?
15666        $tip
15667          .one($.support.transition.end, complete)
15668          .emulateTransitionEnd(150) :
15669        complete()
15670    }
15671  }
15672
15673  Tooltip.prototype.applyPlacement = function (offset, placement) {
15674    var $tip   = this.tip()
15675    var width  = $tip[0].offsetWidth
15676    var height = $tip[0].offsetHeight
15677
15678    // manually read margins because getBoundingClientRect includes difference
15679    var marginTop = parseInt($tip.css('margin-top'), 10)
15680    var marginLeft = parseInt($tip.css('margin-left'), 10)
15681
15682    // we must check for NaN for ie 8/9
15683    if (isNaN(marginTop))  marginTop  = 0
15684    if (isNaN(marginLeft)) marginLeft = 0
15685
15686    offset.top  = offset.top  + marginTop
15687    offset.left = offset.left + marginLeft
15688
15689    // $.fn.offset doesn't round pixel values
15690    // so we use setOffset directly with our own function B-0
15691    $.offset.setOffset($tip[0], $.extend({
15692      using: function (props) {
15693        $tip.css({
15694          top: Math.round(props.top),
15695          left: Math.round(props.left)
15696        })
15697      }
15698    }, offset), 0)
15699
15700    $tip.addClass('in')
15701
15702    // check to see if placing tip in new offset caused the tip to resize itself
15703    var actualWidth  = $tip[0].offsetWidth
15704    var actualHeight = $tip[0].offsetHeight
15705
15706    if (placement == 'top' && actualHeight != height) {
15707      offset.top = offset.top + height - actualHeight
15708    }
15709
15710    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
15711
15712    if (delta.left) offset.left += delta.left
15713    else offset.top += delta.top
15714
15715    var arrowDelta          = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
15716    var arrowPosition       = delta.left ? 'left'        : 'top'
15717    var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
15718
15719    $tip.offset(offset)
15720    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
15721  }
15722
15723  Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
15724    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
15725  }
15726
15727  Tooltip.prototype.setContent = function () {
15728    var $tip  = this.tip()
15729    var title = this.getTitle()
15730
15731    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
15732    $tip.removeClass('fade in top bottom left right')
15733  }
15734
15735  Tooltip.prototype.hide = function () {
15736    var that = this
15737    var $tip = this.tip()
15738    var e    = $.Event('hide.bs.' + this.type)
15739
15740    function complete() {
15741      if (that.hoverState != 'in') $tip.detach()
15742      that.$element.trigger('hidden.bs.' + that.type)
15743    }
15744
15745    this.$element.trigger(e)
15746
15747    if (e.isDefaultPrevented()) return
15748
15749    $tip.removeClass('in')
15750
15751    $.support.transition && this.$tip.hasClass('fade') ?
15752      $tip
15753        .one($.support.transition.end, complete)
15754        .emulateTransitionEnd(150) :
15755      complete()
15756
15757    this.hoverState = null
15758
15759    return this
15760  }
15761
15762  Tooltip.prototype.fixTitle = function () {
15763    var $e = this.$element
15764    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
15765      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
15766    }
15767  }
15768
15769  Tooltip.prototype.hasContent = function () {
15770    return this.getTitle()
15771  }
15772
15773  Tooltip.prototype.getPosition = function ($element) {
15774    $element   = $element || this.$element
15775    var el     = $element[0]
15776    var isBody = el.tagName == 'BODY'
15777    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
15778      scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
15779      width:  isBody ? $(window).width()  : $element.outerWidth(),
15780      height: isBody ? $(window).height() : $element.outerHeight()
15781    }, isBody ? {top: 0, left: 0} : $element.offset())
15782  }
15783
15784  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
15785    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
15786           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
15787           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
15788        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }
15789
15790  }
15791
15792  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
15793    var delta = { top: 0, left: 0 }
15794    if (!this.$viewport) return delta
15795
15796    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
15797    var viewportDimensions = this.getPosition(this.$viewport)
15798
15799    if (/right|left/.test(placement)) {
15800      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
15801      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
15802      if (topEdgeOffset < viewportDimensions.top) { // top overflow
15803        delta.top = viewportDimensions.top - topEdgeOffset
15804      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
15805        delta.top = viewportDimensions.top + viewportDimensions.height - bottom
15805EdgeOffset
15806      }
15807    } else {
15808      var leftEdgeOffset  = pos.left - viewportPadding
15809      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
15810      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
15811        delta.left = viewportDimensions.left - leftEdgeOffset
15812      } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
15813        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
15814      }
15815    }
15816
15817    return delta
15818  }
15819
15820  Tooltip.prototype.getTitle = function () {
15821    var title
15822    var $e = this.$element
15823    var o  = this.options
15824
15825    title = $e.attr('data-original-title')
15826      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
15827
15828    return title
15829  }
15830
15831  Tooltip.prototype.tip = function () {
15832    return this.$tip = this.$tip || $(this.options.template)
15833  }
15834
15835  Tooltip.prototype.arrow = function () {
15836    return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
15837  }
15838
15839  Tooltip.prototype.validate = function () {
15840    if (!this.$element[0].parentNode) {
15841      this.hide()
15842      this.$element = null
15843      this.options  = null
15844    }
15845  }
15846
15847  Tooltip.prototype.enable = function () {
15848    this.enabled = true
15849  }
15850
15851  Tooltip.prototype.disable = function () {
15852    this.enabled = false
15853  }
15854
15855  Tooltip.prototype.toggleEnabled = function () {
15856    this.enabled = !this.enabled
15857  }
15858
15859  Tooltip.prototype.toggle = function (e) {
15860    var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
15861    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
15862  }
15863
15864  Tooltip.prototype.destroy = function () {
15865    clearTimeout(this.timeout)
15866    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
15867  }
15868
15869
15870  // TOOLTIP PLUGIN DEFINITION
15871  // =========================
15872
15873  var old = $.fn.tooltip
15874
15875  $.fn.tooltip = function (option) {
15876    return this.each(function () {
15877      var $this   = $(this)
15878      var data    = $this.data('bs.tooltip')
15879      var options = typeof option == 'object' && option
15880
15881      if (!data && option == 'destroy') return
15882      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
15883      if (typeof option == 'string') data[option]()
15884    })
15885  }
15886
15887  $.fn.tooltip.Constructor = Tooltip
15888
15889
15890  // TOOLTIP NO CONFLICT
15891  // ===================
15892
15893  $.fn.tooltip.noConflict = function () {
15894    $.fn.tooltip = old
15895    return this
15896  }
15897
15898}(jQuery);
15899
15900
15901/* ========================================================================
15902 * Bootstrap: transition.js v3.1.1
15903 * http://getbootstrap.com/javascript/#transitions
15904 * ========================================================================
15905 * Copyright 2011-2014 Twitter, Inc.
15906 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
15907 * ======================================================================== */
15908
15909
15910+function ($) {
15911  'use strict';
15912
15913  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
15914  // ============================================================
15915
15916  function transitionEnd() {
15917    var el = document.createElement('bootstrap')
15918
15919    var transEndEventNames = {
15920      WebkitTransition : 'webkitTransitionEnd',
15921      MozTransition    : 'transitionend',
15922      OTransition      : 'oTransitionEnd otransitionend',
15923      transition       : 'transitionend'
15924    }
15925
15926    for (var name in transEndEventNames) {
15927      if (el.style[name] !== undefined) {
15928        return { end: transEndEventNames[name] }
15929      }
15930    }
15931
15932    return false // explicit for ie8 (  ._.)
15933  }
15934
15935  // http://blog.alexmaccaw.com/css-transitions
15936  $.fn.emulateTransitionEnd = function (duration) {
15937    var called = false, $el = this
15938    $(this).one($.support.transition.end, function () { called = true })
15939    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
15940    setTimeout(callback, duration)
15941    return this
15942  }
15943
15944  $(function () {
15945    $.support.transition = transitionEnd()
15946  })
15947
15948}(jQuery);
15949
15950

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.