PageSourceSearch

https://www.fortedifenestrelle.it/wp-content/themes/uncode/library/js/plugins.js?ver=689715088

js fortedifenestrelle.it collected 2026-10-02 06:01:01 UTC 533,864 bytes, 15,965 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($(e.target));
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($(e.target)); }, 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 sub is collapsible (mobile view)
5927					if (this.isCollapsible()) {
5928						if (this.opts.collapsibleHideFunction) {
5929							this.opts.collapsibleHideFunction.call(this, $sub, complete);
5930						} else {
5931							$sub.hide(this.opts.collapsibleHideDuration, complete);
5932						}
5933					} else {
5934						if (this.opts.hideFunction) {
5935							this.opts.hideFunction.call(this, $sub, complete);
5936						} else {
5937							$sub.hide(this.opts.hideDuration, complete);
5938						}
5939					}
5940					// remove IE iframe shim
5941					if ($sub.dataSM('ie-shim')) {
5942						$sub.dataSM('ie-shim').remove();
5943					}
5944					// deactivate scrolling if it is activated for this sub
5945					if ($sub.dataSM('scroll')) {
5946						$sub.unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide();
5947					}
5948					// unhighlight parent item
5949					$sub.dataSM('parent-a').removeClass('highlighted');
5950					var level = $sub.dataSM('level');
5951					this.activatedItems.splice(level - 1, 1);
5952					this.visibleSubMenus.splice(level - 1, 1);
5953					this.$root.triggerHandler('hide.smapi', $sub[0]);
5954				}
5955			},
5956			menuHideAll: function($item) {
5957				if ($item != undefined && $item.parent().hasClass('menu-item') && !$item.parent().hasClass('menu-item-has-children')) return;
5958				if (this.showTimeout) {
5959					clearTimeout(this.showTimeout);
5960					this.showTimeout = 0;
5961				}
5962				// hide all subs
5963				for (var i = this.visibleSubMenus.length - 1; i > 0; i--) {
5964					this.menuHide(this.visibleSubMenus[i]);
5965				}
5966				// hide root if it's popup
5967				if (this.opts.isPopup) {
5968					this.$root.stop(true, true);
5969					if (this.$root.is(':visible')) {
5970						if (this.opts.hideFunction) {
5971							this.opts.hideFunction.call(this, this.$root);
5972						} else {
5973							this.$root.hide(this.opts.hideDuration);
5974						}
5975						// remove IE iframe shim
5976						if (this.$root.dataSM('ie-shim')) {
5977							this.$root.dataSM('ie-shim').remove();
5978						}
5979					}
5980				}
5981				this.activatedItems = [];
5982				this.visibleSubMenus = [];
5983				this.clickActivated = false;
5984				// reset z-index increment
5985				this.zIndexInc = 0;
5986			},
5987			menuIframeShim: function($ul) {
5988				// create iframe shim for the menu
5989				if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) {
5990					$ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 })
5991						.css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' })
5992					);
5993				}
5994			},
5995			menuInit: function($ul) {
5996				if (!$ul.dataSM('in-mega')) {
5997					this.subMenus.push($ul);
5998					// mark UL's in mega drop downs (if any) so we can neglect them
5999					if ($ul.hasClass('mega-menu')) {
6000						$ul.find('ul').dataSM('in-mega', true);
6001					}
6002					// get level (much faster than, for example, using parentsUntil)
6003					var level = 2,
6004						par = $ul[0];
6005					while ((par = par.parentNode.parentNode) != this.$root[0]) {
6006						level++;
6007					}
6008					// cache stuff
6009					$ul.dataSM('parent-a', $ul.prevAll('a').eq(-1))
6010						.dataSM('level', level)
6011						.parent().dataSM('sub', $ul);
6012					// add sub indicator to parent item
6013					if (this.opts.subIndicators) {
6014						$ul.dataSM('parent-a').addClass('has-submenu')[this.opts.subIndicatorsPos](this.$subArrow.clone());
6015					}
6016				}
6017			},
6018			menuPosition: function($sub) {
6019				var fixIE = $('html.ie').length;
6020				// if (fixIE) {
6021				// 	var $rowParent = $($sub).closest('.main-menu-container');
6022				// 	$rowParent.height($rowParent.height());
6023				// }
6024				var $a = $sub.dataSM('parent-a'),
6025					$li = $sub.parent(),
6026					$ul = $sub.parent().parent(),
6027					$container = $ul.closest('.row-menu-inner'),
6028					level = $sub.dataSM('level'),
6029					subW = this.getWidth($sub),
6030					subH = this.getHeight($sub),
6031					itemOffset = $a.offset(),
6032					itemX = itemOffset.left,
6033					itemY = itemOffset.top,
6034					itemW = this.getWidth($a),
6035					itemH = this.getHeight($a),
6036					$win = $(window),
6037					winX = $win.scrollLeft(),
6038					winY = $win.scrollTop(),
6039					winW = $win.width(),
6040					winH = $win.height(),
6041					containerW = $container.width(),
6042					containerOffsetX = containerW + ((winW - containerW) / 2),
6043					horizontalParent = $ul.hasClass('sm') && !$ul.hasClass('sm-vertical'),
6044					subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX,
6045					subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY,
6046					x, y, leftPos;
6047				if (horizontalParent) {
6048					x = this.opts.rightToLeftSubMenus ? itemW - subW - subOffsetX : subOffsetX;
6049					y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY;
6050				} else {
6051					x = this.opts.rightToLeftSubMenus ? subOffsetX - subW : itemW - subOffsetX;
6052					y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY;
6053				}
6054				if (this.opts.keepInViewport && !this.isCollapsible()) {
6055					if (this.isFixed()) {
6056						itemX -= winX;
6057						itemY -= winY;
6058						winX = winY = 0;
6059					}
6060					var absX = itemX + x,
6061						absY = itemY + y;
6062					if (this.opts.rightToLeftSubMenus && absX < winX) {
6063						x = horizontalParent ? winX - absX + x : itemW - subOffsetX;
6064					} else if (!this.opts.rightToLeftSubMenus && absX + subW > winX + containerOffsetX ) {
6065						x = horizontalParent ? winX + containerOffsetX - subW - absX + x : subOffsetX - subW;
6066					}
6067					if (!horizontalParent) {
6068						if (subH < winH && absY + subH > winY + winH) {
6069							y += winY + winH - subH - absY;
6070						} else if (subH >= winH || absY < winY) {
6071							y += winY - absY;
6072						}
6073					}
6074					// do we need scrolling?
6075					// 0.49 added for the sake of IE9/FF4+ where we might be dealing with float numbers for "subH"
6076					if (mouse && (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49)) {
6077						var self = this;
6078						if (!$sub.dataSM('scroll-arrows')) {
6079							$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]])
6080								.bind({
6081									mouseenter: function() { self.menuScroll($sub, $(this).hasClass('scroll-up')); },
6082									mouseleave: function(e) {
6083										self.menuScrollStop($sub);
6084										self.menuScrollOut($sub, e);
6085									},
6086									'mousewheel DOMMouseScroll': function(e) { e.preventDefault(); }
6087								})
6088								.insertAfter($sub)
6089							);
6090						}
6091						// bind events to show/hide arrows on hover and save scrolling data for this sub
6092						var vportY = winY - (itemY + itemH);
6093						$sub.dataSM('scroll', {
6094								vportY: vportY,
6095								subH: subH,
6096								winH: winH,
6097								step: 1
6098							})
6099							.bind({
6100								'mouseover.smartmenus_scroll': function(e) { self.menuScrollOver($sub, e); },
6101								'mouseout.smartmenus_scroll': function(e) { self.menuScrollOut($sub, e); },
6102								'mousewheel.smartmenus_scroll DOMMouseScroll.smartmenus_scroll': function(e) { self.menuScrollMousewheel($sub, e); }
6103							})
6104							.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
6104StartZIndex() + this.zIndexInc })
6105							.eq(0).css('margin-top', vportY).end()
6106							.eq(1).css('margin-top', vportY + winH - this.getHeight($sub.dataSM('scroll-arrows').eq(1))).end()
6107							.eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show();
6108					}
6109				}
6110				// if ($sub.hasClass('mega-menu-inner')) {
6111				// 	if ($('.menu-wrapper .megamenu-diff').length > 0) {
6112				// 		leftPos = parseFloat($('.menu-wrapper .megamenu-diff').outerWidth());
6113				// 		leftPos = -leftPos;
6114				// 	} else leftPos = parseFloat($('.menu-wrapper .main-menu-container').css('paddingLeft'));
6115
6116				// 	if ($('body.header-full-width').length > 0) {
6117				// 		$sub.css({ width: $('.box-container').width()});
6118				// 		leftPos = (leftPos - parseFloat($('.menu-wrapper .row-menu-inner').css('paddingLeft')));
6119				// 	} else $sub.css({ width: containerW});
6120				// 	leftPos = leftPos + 'px';
6121
6122				// } else {
6123				// 	leftPos = $li.position().left + 'px';
6124				// }
6125				if ($sub.hasClass('mega-menu-inner')) {
6126					$sub.css({ width: containerW});
6127					if ($('body.hmenu-center-split').length > 0) {
6128						leftPos = - ($sub.closest('#menu-main-menu')[0].offsetLeft) + 'px';
6129					} else {
6130						if ($sub.closest('.row-menu-inner').find('.logo-container').length > 0) {
6131							leftPos = - (parseFloat($sub.closest('.row-menu-inner').find('.logo-container').css('paddingRight')) + ($sub.closest('.row-menu-inner').find('.logo-container').width())) + 'px';
6132						} else {
6133							leftPos = '0px';
6134						}
6135					}
6136				} else {
6137					leftPos = (level > 2 ? $li.position().left - parseFloat($li.closest('ul').css('paddingLeft')) : $li.position().left ) + 'px';
6138					x = (level > 2 && x >= 0) ? x + (parseFloat($li.closest('ul').css('paddingLeft')) * 2) + 1 : x - 1;
6139				}
6140
6141				$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) });
6142				// IE iframe shim
6143				this.menuIframeShim($sub);
6144				if ($sub.dataSM('ie-shim')) {
6145					$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) });
6146				}
6147			},
6148			menuScroll: function($sub, up, wheel) {
6149				var y = parseFloat($sub.css('margin-top')),
6150					scroll = $sub.dataSM('scroll'),
6151					end = scroll.vportY + (up ? 0 : scroll.winH - scroll.subH),
6152					step = wheel || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor($sub.dataSM('scroll').step);
6153				$sub.add($sub.dataSM('ie-shim')).css('margin-top', Math.abs(end - y) > step ? y + (up ? step : -step) : end);
6154				y = parseFloat($sub.css('margin-top'));
6155				// show opposite arrow if appropriate
6156				if (up && y + scroll.subH > scroll.vportY + scroll.winH || !up && y < scroll.vportY) {
6157					$sub.dataSM('scroll-arrows').eq(up ? 1 : 0).show();
6158				}
6159				// accelerate when not using mousewheel to scroll
6160				if (!wheel && this.opts.scrollAccelerate && $sub.dataSM('scroll').step < this.opts.scrollStep) {
6161					$sub.dataSM('scroll').step += 0.5;
6162				}
6163				// "y" and "end" might be float numbers in IE9/FF4+ so this weird way to check is used
6164				if (Math.abs(y - end) < 1) {
6165					$sub.dataSM('scroll-arrows').eq(up ? 0 : 1).hide();
6166					$sub.dataSM('scroll').step = 1;
6167				} else if (!wheel) {
6168					var self = this;
6169					this.scrollTimeout = setTimeout(function() { self.menuScroll($sub, up); }, this.opts.scrollInterval);
6170				}
6171			},
6172			menuScrollMousewheel: function($sub, e) {
6173				var $closestSub = $(e.target).closest('ul');
6174				while ($closestSub.dataSM('in-mega')) {
6175					$closestSub = $closestSub.parent().closest('ul');
6176				}
6177				if ($closestSub[0] == $sub[0]) {
6178					var up = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0;
6179					if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) {
6180						this.menuScroll($sub, up, true);
6181					}
6182				}
6183				e.preventDefault();
6184			},
6185			menuScrollOut: function($sub, e) {
6186				var reClass = /^scroll-(up|down)/,
6187					$closestSub = $(e.relatedTarget).closest('ul');
6188				while ($closestSub.dataSM('in-mega')) {
6189					$closestSub = $closestSub.parent().closest('ul');
6190				}
6191				if (!reClass.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || $closestSub[0] != $sub[0])) {
6192					$sub.dataSM('scroll-arrows').css('visibility', 'hidden');
6193				}
6194			},
6195			menuScrollOver: function($sub, e) {
6196				var reClass = /^scroll-(up|down)/,
6197					$closestSub = $(e.target).closest('ul');
6198				while ($closestSub.dataSM('in-mega')) {
6199					$closestSub = $closestSub.parent().closest('ul');
6200				}
6201				if (!reClass.test(e.target.className) && $closestSub[0] == $sub[0]) {
6202					$sub.dataSM('scroll-arrows').css('visibility', 'visible');
6203				}
6204			},
6205			menuScrollStop: function($sub) {
6206				if (this.scrollTimeout) {
6207					clearTimeout(this.scrollTimeout);
6208					this.scrollTimeout = 0;
6209					$sub.dataSM('scroll').step = 1;
6210				}
6211			},
6212			menuShow: function($sub) {
6213				if (!$sub.dataSM('beforefirstshowfired')) {
6214					$sub.dataSM('beforefirstshowfired', true);
6215					if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) {
6216						return;
6217					}
6218				}
6219				if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) {
6220					return;
6221				}
6222				this.menuFixLayout($sub);
6223				$sub.stop(true, true);
6224				if (!$sub.is(':visible')) {
6225					// set z-index - for IE < 9 set it to the parent LI
6226					var zIndex = this.getStartZIndex() + (++this.zIndexInc);
6227					if (IElt9) {
6228						$sub.parent().css('z-index', zIndex);
6229					} else {
6230						$sub.css('z-index', zIndex);
6231					}
6232					// highlight parent item
6233					if (this.opts.keepHighlighted || this.isCollapsible()) {
6234						if ($sub.dataSM('parent-a').attr('data-type') != 'title')
6235							$sub.dataSM('parent-a').addClass('highlighted');
6236					}
6237					// min/max-width fix - no way to rely purely on CSS as all UL's are nested
6238					if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) {
6239						if (!IElt8) {
6240							$sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
6241							if (this.opts.subMenusMinWidth) {
6242							 	$sub.css('min-width', this.opts.subMenusMinWidth);
6243							}
6244							if (this.opts.subMenusMaxWidth) {
6245							 	var noMaxWidth = this.getWidth($sub);
6246							 	$sub.css('max-width', this.opts.subMenusMaxWidth);
6247								if (noMaxWidth > this.getWidth($sub)) {
6248									$sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
6249								}
6250							}
6251						// IE6,7
6252 						} else {
6253							$sub.children().css('styleFloat', 'none');
6254							if (IE6) {
6255								$sub.width(this.opts.subMenusMinWidth ? this.opts.subMenusMinWidth : 1)
6256									.children().children('a').css('white-space', 'nowrap');
6257							} else { // IE7
6258								$sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
6259								if (this.opts.subMenusMinWidth) {
6260							    $sub.css('min-width', this.opts.subMenusMinWidth);
6261								}
6262							}
6263							if (this.opts.subMenusMaxWidth) {
6264								var noMaxWidth = $sub.width();
6265								if (IE6) {
6266							 		var maxWidth = $sub.css({ width: this.opts.subMenusMaxWidth, overflowX: 'hidden', overflowY: 'hidden' }).width();
6267									if (noMaxWidth > maxWidth) {
6268										$sub.css({ width: maxWidth, overflowX: 'visible', overflowY: 'visible' }).children().children('a').css('white-space', '');
6269									} else {
6270										$sub.css({ width: noMaxWidth, overflowX: 'visible', overflowY: 'visible' });
6271									}
6272								} else { // IE7
6273									$sub.css('max-width', this.opts.subMenusMaxWidth);
6274									if (noMaxWidth > $sub.width()) {
6275										$sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
6276									} else {
6277										$sub.width(noMaxWidth);
6278									}
6279								}
6280							} else {
6281							 	$sub.width($sub.width());
6282							}
6283							$sub.children().css('styleFloat', 'left');
6284						}
6285					}
6286					this.menuPosition($sub);
6287					// insert IE iframe shim
6288					if ($sub.dataSM('ie-shim')) {
6289						$sub.dataSM('ie-shim').insertBefore($sub);
6290					}
6291					var complete = function() {
6292						// fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used
6293						$sub.css('overflow', '');
6294					};
6295					// if sub is collapsible (mobile view)
6296					if (this.isCollapsible()) {
6297						if (this.opts.collapsibleShowFunction) {
6298							this.opts.collapsibleShowFunction.call(this, $sub, complete);
6299						} else {
6300							$sub.show(this.opts.collapsibleShowDuration, complete);
6301						}
6302					} else {
6303						if (this.opts.showFunction) {
6304							this.opts.showFunction.call(this, $sub, complete);
6305						} else {
6306							$sub.show(this.opts.showDuration, complete);
6307						}
6308					}
6309					// save new sub menu for this level
6310					this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub;
6311					this.$root.triggerHandler('show.smapi', $sub[0]);
6312				}
6313			},
6314			popupHide: function(noHideTimeout) {
6315				if (this.hideTimeout) {
6316					clearTimeout(this.hideTimeout);
6317					this.hideTimeout = 0;
6318				}
6319				var self = this;
6320				this.hideTimeout = setTimeout(function() {
6321					self.menuHideAll();
6322				}, noHideTimeout ? 1 : this.opts.hideTimeout);
6323			},
6324			popupShow: function(left, top) {
6325				if (!this.opts.isPopup) {
6326					alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.');
6327					return;
6328				}
6329				if (this.hideTimeout) {
6330					clearTimeout(this.hideTimeout);
6331					this.hideTimeout = 0;
6332				}
6333				this.menuFixLayout(this.$root);
6334				this.$root.stop(true, true);
6335				if (!this.$root.is(':visible')) {
6336					this.$root.css({ left: left, top: top });
6337					// IE iframe shim
6338					this.menuIframeShim(this.$root);
6339					if (this.$root.dataSM('ie-shim')) {
6340						this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
6340: left, top: top }).insertBefore(this.$root);
6341					}
6342					// show menu
6343					if (this.opts.showFunction) {
6344						this.opts.showFunction.call(this, this.$root);
6345					} else {
6346						this.$root.show(this.opts.showDuration);
6347					}
6348					this.visibleSubMenus[0] = this.$root;
6349				}
6350			},
6351			refresh: function() {
6352				this.menuHideAll();
6353				this.$root.find('ul').each(function() {
6354						var $this = $(this);
6355						if ($this.dataSM('scroll-arrows')) {
6356							$this.dataSM('scroll-arrows').remove();
6357						}
6358					})
6359					.removeDataSM('in-mega')
6360					.removeDataSM('shown-before')
6361					.removeDataSM('ie-shim')
6362					.removeDataSM('scroll-arrows')
6363					.removeDataSM('parent-a')
6364					.removeDataSM('level')
6365					.removeDataSM('beforefirstshowfired');
6366				this.$root.find('a.has-submenu').removeClass('has-submenu')
6367					.parent().removeDataSM('sub');
6368				if (this.opts.subIndicators) {
6369					this.$root.find('span.sub-arrow').remove();
6370				}
6371				if (this.opts.markCurrentItem) {
6372					this.$root.find('a.current').removeClass('current');
6373				}
6374				this.subMenus = [];
6375				this.init(true);
6376			},
6377			rootOut: function(e) {
6378				if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
6379					return;
6380				}
6381				if (this.hideTimeout) {
6382					clearTimeout(this.hideTimeout);
6383					this.hideTimeout = 0;
6384				}
6385				if (!this.opts.showOnClick || !this.opts.hideOnClick) {
6386					var self = this;
6387					this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout);
6388				}
6389			},
6390			rootOver: 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			},
6399			winResize: function(e) {
6400				if (!this.handleEvents()) {
6401					// we still need to resize the disable overlay if it's visible
6402					if (this.$disableOverlay) {
6403						var pos = this.$root.offset();
6404	 					this.$disableOverlay.css({
6405							top: pos.top,
6406							left: pos.left,
6407							width: this.$root.outerWidth(),
6408							height: this.$root.outerHeight()
6409						});
6410					}
6411					return;
6412				}
6413				// hide sub menus on resize - on mobile do it only on orientation change
6414				if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) {
6415					if (this.activatedItems.length) {
6416						this.activatedItems[this.activatedItems.length - 1][0].blur();
6417					}
6418					this.menuHideAll();
6419				}
6420			}
6421		}
6422	});
6423
6424	$.fn.dataSM = function(key, val) {
6425		if (val) {
6426			return this.data(key + '_smartmenus', val);
6427		}
6428		return this.data(key + '_smartmenus');
6429	}
6430
6431	$.fn.removeDataSM = function(key) {
6432		return this.removeData(key + '_smartmenus');
6433	}
6434
6435	$.fn.smartmenus = function(options) {
6436		if (typeof options == 'string') {
6437			var args = arguments,
6438				method = options;
6439			Array.prototype.shift.call(args);
6440			return this.each(function() {
6441				var smartmenus = $(this).data('smartmenus');
6442				if (smartmenus && smartmenus[method]) {
6443					smartmenus[method].apply(smartmenus, args);
6444				}
6445			});
6446		}
6447		var opts = $.extend({}, $.fn.smartmenus.defaults, options);
6448		return this.each(function() {
6449			new $.SmartMenus(this, opts);
6450		});
6451	}
6452
6453	// default settings
6454	$.fn.smartmenus.defaults = {
6455		isPopup:		false,		// is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar
6456		mainMenuSubOffsetX:	0,		// pixels offset from default position
6457		mainMenuSubOffsetY:	0,		// pixels offset from default position
6458		subMenusSubOffsetX:	0,		// pixels offset from default position
6459		subMenusSubOffsetY:	0,		// pixels offset from default position
6460		subMenusMinWidth:	'10em',		// min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
6461		subMenusMaxWidth:	'20em',		// max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
6462		subIndicators: 		true,		// create sub menu indicators - creates a SPAN and inserts it in the A
6463		subIndicatorsPos: 	'prepend',	// position of the SPAN relative to the menu item content ('prepend', 'append')
6464		subIndicatorsText:	'+',		// [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too)
6465		scrollStep: 		30,		// pixels step when scrolling long sub menus that do not fit in the viewport height
6466		scrollInterval:		30,		// interval between each scrolling step
6467		scrollAccelerate:	true,		// accelerate scrolling or use a fixed step
6468		showTimeout:		250,		// timeout before showing the sub menus
6469		hideTimeout:		500,		// timeout before hiding the sub menus
6470		showDuration:		0,		// duration for show animation - set to 0 for no animation - matters only if showFunction:null
6471		showFunction:		null,		// custom function to use when showing a sub menu (the default is the jQuery 'show')
6472							// don't forget to call complete() at the end of whatever you do
6473							// e.g.: function($ul, complete) { $ul.fadeIn(250, complete); }
6474		hideDuration:		0,		// duration for hide animation - set to 0 for no animation - matters only if hideFunction:null
6475		hideFunction:		function($ul, complete) { $ul.fadeOut(200, complete); },	// custom function to use when hiding a sub menu (the default is the jQuery 'hide')
6476							// don't forget to call complete() at the end of whatever you do
6477							// e.g.: function($ul, complete) { $ul.fadeOut(250, complete); }
6478		collapsibleShowDuration:0,		// duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null
6479		collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); },	// custom function to use when showing a collapsible sub menu
6480							// (i.e. when mobile styles are used to make the sub menus collapsible)
6481		collapsibleHideDuration:0,		// duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null
6482		collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); },	// custom function to use when hiding a collapsible sub menu
6483							// (i.e. when mobile styles are used to make the sub menus collapsible)
6484		showOnClick:		false,		// show the first-level sub menus onclick instead of onmouseover (matters only for mouse input)
6485		hideOnClick:		true,		// hide the sub menus on click/tap anywhere on the page
6486		keepInViewport:		true,		// reposition the sub menus if needed to make sure they always appear inside the viewport
6487		keepHighlighted:	true,		// keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's)
6488		markCurrentItem:	false,		// automatically add the 'current' class to the A element of the item linking to the current URL
6489		markCurrentTree:	true,		// add the 'current' class also to the A elements of all ancestor items of the current item
6490		rightToLeftSubMenus:	false,		// right to left display of the sub menus (check the CSS for the sub indicators' position)
6491		bottomToTopSubMenus:	false,		// bottom to top display of the sub menus
6492		overlapControlsInIE:	true		// make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.)
6493	};
6494
6495})(jQuery);
6496
6497/*
6498 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
6499 *
6500 * Uses the built in easing capabilities added In jQuery 1.1
6501 * to offer multiple easing options
6502 *
6503 * TERMS OF USE - jQuery Easing
6504 * 
6505 * Open source under the BSD License. 
6506 * 
6507 * Copyright © 2008 George McGinley Smith
6508 * All rights reserved.
6509 * 
6510 * Redistribution and use in source and binary forms, with or without modification, 
6511 * are permitted provided that the following conditions are met:
6512 * 
6513 * Redistributions of source code must retain the above copyright notice, this list of 
6514 * conditions and the following disclaimer.
6515 * Redistributions in binary form must reproduce the above copyright notice, this list 
6516 * of conditions and the following disclaimer in the documentation and/or other materials 
6517 * provided with the distribution.
6518 * 
6519 * Neither the name of the author nor the names of contributors may be used to endorse 
6520 * or promote products derived from this software without specific prior written permission.
6521 * 
6522 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
6523 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
6524 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
6525 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
vendor: 5,091 bytes, lines 6526-6671
6526 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
6527 *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
6528 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
6529 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
6530 * OF THE POSSIBILITY OF SUCH DAMAGE. 
6531 *
6532*/
6533
6534// t: current time, b: begInnIng value, c: change In value, d: duration
6535jQuery.easing['jswing'] = jQuery.easing['swing'];
6536
6537jQuery.extend( jQuery.easing,
6538{
6539	def: 'easeOutQuad',
6540	swing: function (x, t, b, c, d) {
6541		//alert(jQuery.easing.default);
6542		return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
6543	},
6544	easeInQuad: function (x, t, b, c, d) {
6545		return c*(t/=d)*t + b;
6546	},
6547	easeOutQuad: function (x, t, b, c, d) {
6548		return -c *(t/=d)*(t-2) + b;
6549	},
6550	easeInOutQuad: function (x, t, b, c, d) {
6551		if ((t/=d/2) < 1) return c/2*t*t + b;
6552		return -c/2 * ((--t)*(t-2) - 1) + b;
6553	},
6554	easeInCubic: function (x, t, b, c, d) {
6555		return c*(t/=d)*t*t + b;
6556	},
6557	easeOutCubic: function (x, t, b, c, d) {
6558		return c*((t=t/d-1)*t*t + 1) + b;
6559	},
6560	easeInOutCubic: function (x, t, b, c, d) {
6561		if ((t/=d/2) < 1) return c/2*t*t*t + b;
6562		return c/2*((t-=2)*t*t + 2) + b;
6563	},
6564	easeInQuart: function (x, t, b, c, d) {
6565		return c*(t/=d)*t*t*t + b;
6566	},
6567	easeOutQuart: function (x, t, b, c, d) {
6568		return -c * ((t=t/d-1)*t*t*t - 1) + b;
6569	},
6570	easeInOutQuart: function (x, t, b, c, d) {
6571		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
6572		return -c/2 * ((t-=2)*t*t*t - 2) + b;
6573	},
6574	easeInQuint: function (x, t, b, c, d) {
6575		return c*(t/=d)*t*t*t*t + b;
6576	},
6577	easeOutQuint: function (x, t, b, c, d) {
6578		return c*((t=t/d-1)*t*t*t*t + 1) + b;
6579	},
6580	easeInOutQuint: function (x, t, b, c, d) {
6581		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
6582		return c/2*((t-=2)*t*t*t*t + 2) + b;
6583	},
6584	easeInSine: function (x, t, b, c, d) {
6585		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
6586	},
6587	easeOutSine: function (x, t, b, c, d) {
6588		return c * Math.sin(t/d * (Math.PI/2)) + b;
6589	},
6590	easeInOutSine: function (x, t, b, c, d) {
6591		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
6592	},
6593	easeInExpo: function (x, t, b, c, d) {
6594		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
6595	},
6596	easeOutExpo: function (x, t, b, c, d) {
6597		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
6598	},
6599	easeInOutExpo: function (x, t, b, c, d) {
6600		if (t==0) return b;
6601		if (t==d) return b+c;
6602		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
6603		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
6604	},
6605	easeInCirc: function (x, t, b, c, d) {
6606		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
6607	},
6608	easeOutCirc: function (x, t, b, c, d) {
6609		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
6610	},
6611	easeInOutCirc: function (x, t, b, c, d) {
6612		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
6613		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
6614	},
6615	easeInElastic: function (x, t, b, c, d) {
6616		var s=1.70158;var p=0;var a=c;
6617		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
6618		if (a < Math.abs(c)) { a=c; var s=p/4; }
6619		else var s = p/(2*Math.PI) * Math.asin (c/a);
6620		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
6621	},
6622	easeOutElastic: function (x, t, b, c, d) {
6623		var s=1.70158;var p=0;var a=c;
6624		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
6625		if (a < Math.abs(c)) { a=c; var s=p/4; }
6626		else var s = p/(2*Math.PI) * Math.asin (c/a);
6627		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
6628	},
6629	easeInOutElastic: function (x, t, b, c, d) {
6630		var s=1.70158;var p=0;var a=c;
6631		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
6632		if (a < Math.abs(c)) { a=c; var s=p/4; }
6633		else var s = p/(2*Math.PI) * Math.asin (c/a);
6634		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
6635		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
6636	},
6637	easeInBack: function (x, t, b, c, d, s) {
6638		if (s == undefined) s = 1.70158;
6639		return c*(t/=d)*t*((s+1)*t - s) + b;
6640	},
6641	easeOutBack: function (x, t, b, c, d, s) {
6642		if (s == undefined) s = 1.70158;
6643		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
6644	},
6645	easeInOutBack: function (x, t, b, c, d, s) {
6646		if (s == undefined) s = 1.70158; 
6647		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
6648		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
6649	},
6650	easeInBounce: function (x, t, b, c, d) {
6651		return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
6652	},
6653	easeOutBounce: function (x, t, b, c, d) {
6654		if ((t/=d) < (1/2.75)) {
6655			return c*(7.5625*t*t) + b;
6656		} else if (t < (2/2.75)) {
6657			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
6658		} else if (t < (2.5/2.75)) {
6659			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
6660		} else {
6661			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
6662		}
6663	},
6664	easeInOutBounce: function (x, t, b, c, d) {
6665		if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
6666		return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
6667	}
6668});
6669
6670/*
6671 *
6672 * TERMS OF USE - EASING EQUATIONS
6673 * 
6674 * Open source under the BSD License. 
6675 * 
6676 * Copyright © 2001 Robert Penner
6677 * All rights reserved.
6678 * 
6679 * Redistribution and use in source and binary forms, with or without modification, 
6680 * are permitted provided that the following conditions are met:
6681 * 
6682 * Redistributions of source code must retain the above copyright notice, this list of 
6683 * conditions and the following disclaimer.
6684 * Redistributions in binary form must reproduce the above copyright notice, this list 
6685 * of conditions and the following disclaimer in the documentation and/or other materials 
6686 * provided with the distribution.
6687 * 
6688 * Neither the name of the author nor the names of contributors may be used to endorse 
6689 * or promote products derived from this software without specific prior written permission.
6690 * 
6691 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
6692 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
6693 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
6694 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
6695 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
6696 *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
6697 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
6698 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
6699 * OF THE POSSIBILITY OF SUCH DAMAGE. 
6700 *
6701 */
6702
6703(function($, window, undefined) {
6704    // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
6705    // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
6706 
6707    // requestAnimationFrame polyfill by Erik Möller
6708    // fixes from Paul Irish and Tino Zijdel
6709 
6710    var lastTime = 0,
6711        running,
6712        animate = function (elem) {
6713            if (running) {
6714                window.requestAnimationFrame(animate, elem);
6715                jQuery.fx.tick();
6716            }
6717        },
6718        vendors = ['ms', 'moz', 'webkit', 'o'];
6719 
6720    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
6721        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
6722        window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
6723            || window[vendors[x]+'CancelRequestAnimationFrame'];
6724    }
6725 
6726    if (!window.requestAnimationFrame)
6727        window.requestAnimationFrame = function(fn, element) {
6728            var currTime = new Date().getTime(),
6729                delta = currTime - lastTime,
6730                timeToCall = Math.max(0, 16 - delta);
6731 
6732            var id = window.setTimeout(function() {
6733                    fn(currTime + timeToCall);
6734                },
6735                timeToCall
6736            );
6737 
6738            lastTime = currTime + timeToCall;
6739 
6740            return id;
6741        };
6742 
6743    if (!window.cancelAnimationFrame) {
6744        window.cancelAnimationFrame = function(id) {
6745            clearTimeout(id);
6746        };
6747    }
6748 
6749    jQuery.fx.timer = function (timer) {
6750        if (timer() && jQuery.timers.push(timer) && !running) {
6751            running = true;
6752            animate(timer.elem);
6753        }
6754    };
6755 
6756    jQuery.fx.stop = function() {
6757        running = false;
6758    };
6759 
6760}(jQuery, this));
6761
6762/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
6763 * Licensed under the MIT License (LICENSE.txt).
6764 *
6765 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
6766 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
6767 * Thanks to: Seamus Leahy for adding deltaX and deltaY
6768 *
6769 * Version: 3.0.6
6770 *
6771 * Requires: 1.2.2+
6772 */
6773(function($) {
6774    var types = ['DOMMouseScroll', 'mousewheel'];
6775    if ($.event.fixHooks) {
6776        for (var i = types.length; i;) {
6777            $.event.fixHooks[types[--i]] = $.event.mouseHooks;
6778        }
6779    }
6780    $.event.special.mousewheel = {
6781        setup: function() {
6782            if (this.addEventListener) {
6783                for (var i = types.length; i;) {
6784                    this.addEventListener(types[--i], handler, false);
6785                }
6786            } else {
6787                this.onmousewheel = handler;
6788            }
6789        },
6790        teardown: function() {
6791            if (this.removeEventListener) {
6792                for (var i = types.length; i;) {
6793                    this.removeEventListener(types[--i], handler, false);
6794                }
6795            } else {
6796                this.onmousewheel = null;
6797            }
6798        }
6799    };
6800    $.fn.extend({
6801        mousewheel: function(fn) {
6802            return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
6803        },
6804        unmousewheel: function(fn) {
6805            return this.unbind("mousewheel", fn);
6806        }
6807    });
6808
6809    function handler(event) {
6810        var orgEvent = event || window.event,
6811            args = [].slice.call(arguments, 1),
6812            delta = 0,
6813            returnValue = true,
6814            deltaX = 0,
6815            deltaY = 0;
6816        event = $.event.fix(orgEvent);
6817        event.type = "mousewheel";
6818        // Old school scrollwheel delta
6819        if (orgEvent.wheelDelta) {
6820            delta = orgEvent.wheelDelta / 120;
6821        }
6822        if (orgEvent.detail) {
6823            delta = -orgEvent.detail / 3;
6824        }
6825        // New school multidimensional scroll (touchpads) deltas
6826        deltaY = delta;
6827        // Gecko
6828        if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) {
6829            deltaY = 0;
6830            deltaX = -1 * delta;
6831        }
6832        // Webkit
6833        if (orgEvent.wheelDeltaY !== undefined) {
6834            deltaY = orgEvent.wheelDeltaY / 120;
6835        }
6836        if (orgEvent.wheelDeltaX !== undefined) {
6837            deltaX = -1 * orgEvent.wheelDeltaX / 120;
6838        }
6839        // Add event and delta to the front of the arguments
6840        args.unshift(event, delta, deltaX, deltaY);
6841        return ($.event.dispatch || $.event.handle).apply(this, args);
6842    }
6843})(jQuery);
6844
6845/**
6846 * jQuery iLightBox - Revolutionary Lightbox Plugin
6847 * http://www.ilightbox.net/
6848 *
6849 * @version: 2.2.0 - September 23, 2014
6850 *
6851 * @author: Hemn Chawroka
6852 *          http://www.iprodev.com/
6853 *
6854 */
6855(function($, window, undefined) {
6856
6857	var extensions = {
6858			flash: ['swf'],
6859			image: ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'tif', 'jfif', 'jpe'],
6860			iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'jsp', 'php', 'pl', 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml', 'txt'],
6861			video: ['avi', 'mov', 'mpg', 'mpeg', 'movie', 'mp4', 'webm', 'ogv', 'ogg', '3gp', 'm4v']
6862		},
6863
6864		// Global DOM elements
6865		$win = $(window),
6866		$doc = $(document),
6867
6868		// Support indicators
6869		browser,
6870		transform,
6871		gpuAcceleration,
6872		fullScreenApi = '',
6873		supportTouch = !!('ontouchstart' in window) && (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)),
6874
6875		// Events
6876		clickEvent = supportTouch ? "itap.iLightBox" : "click.iLightBox",
6877		touchStartEvent = supportTouch ? "touchstart.iLightBox" : "mousedown.iLightBox",
6878		touchStopEvent = supportTouch ? "touchend.iLightBox" : "mouseup.iLightBox",
6879		touchMoveEvent = supportTouch ? "touchmove.iLightBox" : "mousemove.iLightBox",
6880
6881		// Math shorthands
6882		abs = Math.abs,
6883		sqrt = Math.sqrt,
6884		round = Math.round,
6885		max = Math.max,
6886		min = Math.min,
6887		floor = Math.floor,
6888		random = Math.random,
6889
6890		pluginspages = {
6891			quicktime: 'http://www.apple.com/quicktime/download',
6892			flash: 'http://www.adobe.com/go/getflash'
6893		},
6894
6895		iLightBox = function(el, options, items, instant) {
6896			var iL = this;
6897
6898			iL.options = options,
6899				iL.selector = el.selector || el,
6900				iL.context = el.context,
6901				iL.instant = instant;
6902
6903			if (items.length < 1) iL.attachItems();
6904			else iL.items = items;
6905
6906			iL.vars = {
6907				total: iL.items.length,
6908				start: 0,
6909				current: null,
6910				next: null,
6911				prev: null,
6912				BODY: $('body'),
6913				loadRequests: 0,
6914				overlay: $('<div class="ilightbox-overlay"></div>'),
6915				loader: $('<div class="ilightbox-loader"><div></div></div>'),
6916				toolbar: $('<div class="ilightbox-toolbar"></div>'),
6917				innerToolbar: $('<div class="ilightbox-inner-toolbar"></div>'),
6918				title: $('<div class="ilightbox-title"></div>'),
6919				closeButton: $('<a class="ilightbox-close" title="' + iL.options.text.close + '"></a>'),
6920				fullScreenButton: $('<a class="ilightbox-fullscreen" title="' + iL.options.text.enterFullscreen + '"></a>'),
6921				innerPlayButton: $('<a class="ilightbox-play" title="' + iL.options.text.slideShow + '"></a>'),
6922				innerNextButton: $('<a class="ilightbox-next-button" title="' + iL.options.text.next + '"></a>'),
6923				innerPrevButton: $('<a class="ilightbox-prev-button" title="' + iL.options.text.previous + '"></a>'),
6924				holder: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + '" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
6925				nextPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-next" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
6926				prevPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-prev" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
6927				nextButton: $('<a class="ilightbox-button ilightbox-next-button" ondragstart="return false;" title="' + iL.options.text.next + '"><span></span></a>'),
6928				prevButton: $('<a class="ilightbox-button ilightbox-prev-button" ondragstart="return false;" title="' + iL.options.text.previous + '"><span></span></a>'),
6929				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>'),
6930				thumbs: false,
6931				nextLock: false,
6932				prevLock: false,
6933				hashLock: false,
6934				isMobile: false,
6935				mobileMaxWidth: 980,
6936				isInFullScreen: false,
6937				isSwipe: false,
6938				mouseID: 0,
6939				cycleID: 0,
6940				isPaused: 0,
6941				captionHeight: 39,
6942			};
6943
6944			// Hideable elements with mousemove event
6945			iL.vars.hideableElements = iL.vars.nextButton.add(iL.vars.prevButton);
6946
6947			iL.normalizeItems();
6948
6949			//Check necessary plugins
6950			iL.availPlugins();
6951
6952			//Set startFrom
6953			iL.options.startFrom = (iL.options.startFrom > 0 && iL.options.startFrom >= iL.vars.total) ? iL.vars.total - 1 : iL.options.startFrom;
6954
6955			//If randomStart
6956			iL.options.startFrom = (iL.options.randomStart) ? floor(random() * iL.vars.total) : iL.options.startFrom;
6957			iL.vars.start = iL.options.startFrom;
6958
6959			if (instant) iL.instantCall();
6960			else iL.patchItemsEvents();
6961
6962			if (iL.options.linkId) {
6963				iL.hashChangeHandler();
6964				$win.iLightBoxHashChange(function() {
6965					iL.hashChangeHandler();
6966				});
6967			}
6968
6969			if (supportTouch) {
6970				var RegExp = /(click|mouseenter|mouseleave|mouseover|mouseout)/ig,
6971					replace = "itap";
6972				iL.options.caption.show = iL.options.caption.show.replace(RegExp, replace),
6973					iL.options.caption.hide = iL.options.caption.hide.replace(RegExp, replace),
6974					iL.options.social.show = iL.options.social.show.replace(RegExp, replace),
6975					iL.options.social.hide = iL.options.social.hide.replace(RegExp, replace);
6976			}
6977
6978			if (iL.options.controls.arrows) {
6979				$.extend(iL.options.styles, {
6980					nextOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4,
6981					prevOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4,
6982					nextOpacity: 0,
6983					prevOpacity: 0
6984				});
6985			}
6986		};
6987
6988	//iLightBox helpers
6989	iLightBox.prototype = {
6990		showLoader: function() {
6991			var iL = this;
6992			iL.vars.loadRequests += 1;
6993			if (iL.options.path.toLowerCase() == "horizontal") iL.vars.loader.stop().animate({
6994				//top: '2px'
6995				opacity: '1'
6996			}, iL.options.show.speed, 'easeOutCirc');
6997			else iL.vars.loader.stop().animate({
6998			//	left: '2px'
6999				opacity: '1'
7000			}, iL.options.show.speed, 'easeOutCirc');
7001		},
7002
7003		hideLoader: function() {
7004			var iL = this;
7005			iL.vars.loadRequests -= 1;
7006			iL.vars.loadRequests = (iL.vars.loadRequests < 0) ? 0 : iL.vars.loadRequests;
7007			if (iL.options.path.toLowerCase() == "horizontal") {
7008				if (iL.vars.loadRequests <= 0) iL.vars.loader.stop().animate({
7009					//top: '-20px'
7010					opacity: '0'
7011				}, iL.options.show.speed, 'easeInCirc');
7012			} else {
7013				if (iL.vars.loadRequests <= 0) iL.vars.loader.stop().animate({
7014					//left: '-20px'
7015					opacity: '0'
7016				}, iL.options.show.speed, 'easeInCirc');
7017			}
7018		},
7019
7020		createUI: function() {
7021			var iL = this;
7022
7023			iL.ui = {
7024				currentElement: iL.vars.holder,
7025				nextElement: iL.vars.nextPhoto,
7026				prevElement: iL.vars.prevPhoto,
7027				currentItem: iL.vars.current,
7028				nextItem: iL.vars.next,
7029				prevItem: iL.vars.prev,
7030				hide: function() {
7031					iL.closeAction();
7032				},
7033				refresh: function() {
7034					(arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto();
7035				},
7036				fullscreen: function() {
7037					iL.fullScreenAction();
7038				}
7039			};
7040		},
7041
7042		attachItems: function() {
7043			var iL = this,
7044				itemsObject = new Array(),
7045				items = new Array();
7046
7047			$(iL.selector, iL.context).each(function() {
7048				var t = $(this),
7049					URL = t.attr(iL.options.attr) || null,
7050					options = t.data("options") && eval("({" + t.data("options") + "})") || {},
7051					caption = t.data('caption'),
7052					title = t.data('title'),
7053					type = t.data('type') || getTypeByExtension(URL),
7054					clone = t.data('lbox-clone') || false;
7055
7056				items.push({
7057					URL: URL,
7058					caption: caption,
7059					title: title,
7060					type: type,
7061					options: options,
7062					clone: clone
7063				});
7064
7065				if (!iL.instant) itemsObject.push(t);
7066			});
7067
7068			if (iL.vars != undefined) iL.vars.total = items.length;
7069
7070			iL.items = items,
7071				iL.itemsObject = itemsObject;
7072		},
7073
7074		normalizeItems: function() {
7075			var iL = this,
7076				newItems = new Array();
7077
7078			$.each(iL.items, function(key, val) {
7079
7080				if (typeof val == "string") val = {
7081					url: val
7082				};
7083
7084				var URL = val.url || val.URL || null,
7085					options = val.options || {},
7086					caption = val.caption || null,
7087					title = val.title || null,
7088					type = (val.type) ? val.type.toLowerCase() : getTypeByExtension(URL),
7089					ext = (typeof URL != 'object') ? getExtension(URL) : '';
7090
7091				options.thumbnail = options.thumbnail || ((type == "image") ? URL : null),
7092				options.videoType = options.videoType || null,
7093				options.skin = options.skin || iL.options.skin,
7094				options.width = options.width || null,
7095				options.height = options.height || null,
7096				options.mousewheel = (typeof options.mousewheel != 'undefined') ? options.mousewheel : true,
7097				options.swipe = (typeof options.swipe != 'undefined') ? options.swipe : true,
7098				options.social = (typeof options.social != 'undefined') ? options.social : iL.options.social.buttons && $.extend({}, {}, iL.options.social.buttons);
7099
7100				if (type == "video") {
7101					options.html5video = (typeof options.html5video != 'undefined') ? options.html5video : {};
7102
7103					options.html5video.webm = options.html5video.webm || options.html5video.WEBM || null;
7104					options.html5video.controls = (typeof options.html5video.controls != 'undefined') ? options.html5video.controls : "controls";
7105					options.html5video.preload = options.html5video.preload || "metadata";
7106					options.html5video.autoplay = (typeof options.html5video.autoplay != 'undefined') ? options.html5video.autoplay : false;
7107				}
7108
7109				if (!options.width || !options.height) {
7110					if (type == "video") options.width = 1280, options.height = 720;
7111					else if (type == "iframe") options.width = '100%', options.height = '90%';
7112					else if (type == "flash") options.width = 1280, options.height = 720;
7113				}
7114
7115				delete val.url;
7116				val.index = key;
7117				val.URL = URL;
7118				val.caption = caption;
7119				val.title = title;
7120				val.type = type;
7121				val.options = options;
7122				val.ext = ext;
7123
7124				newItems.push(val);
7125			});
7126
7127			iL.items = newItems;
7128		},
7129
7130		instantCall: function() {
7131			var iL = this,
7132				key = iL.vars.start;
7133
7134			iL.vars.current = key;
7135			iL.vars.next = (iL.items[key + 1]) ? key + 1 : null;
7136			iL.vars.prev = (iL.items[key - 1]) ? key - 1 : null;
7137
7138			iL.addContents();
7139			iL.patchEvents();
7140		},
7141
7142		addContents: function() {
7143			var iL = this,
7144				vars = iL.vars,
7145				opts = iL.options,
7146				viewport = getViewport(),
7147				path = opts.path.toLowerCase(),
7148				recognizingItems = vars.total > 0 && iL.items.filter(function(e, i, arr) {
7149					return ['image', 'flash', 'video'].indexOf(e.type) === -1 && typeof e.recognized === 'undefined' && (opts.smartRecognition || e.options.smartRecognition);
7150				}),
7151				needRecognition = recognizingItems.length > 0;
7152
7153			if (opts.mobileOptimizer && !opts.innerToolbar)
7154				vars.isMobile = viewport.width <= vars.mobileMaxWidth;
7155
7156			vars.overlay.addClass(opts.skin).hide().css('opacity', opts.overlay.opacity);
7157
7158			if (opts.linkId)
7159				vars.overlay[0].setAttribute('linkid', opts.linkId);
7160
7161			//Add Toolbar Buttons
7162			if (opts.controls.toolbar) {
7163				vars.toolbar.addClass(opts.skin).append(vars.closeButton);
7164				if (opts.controls.fullscreen)
7165					vars.toolbar.append(vars.fullScreenButton);
7166				if (opts.controls.slideshow)
7167					vars.toolbar.append(vars.innerPlayButton);
7168				if (vars.total > 1)
7169					vars.toolbar.append(vars.innerPrevButton).append(vars.innerNextButton);
7170			}
7171
7172			//Append elements to body
7173			vars.BODY.addClass('ilightbox-noscroll').append(vars.overlay).append(vars.loader).append(vars.holder).append(vars.nextPhoto).append(vars.prevPhoto);
7174
7175			if (!opts.innerToolbar)
7176				vars.BODY.append(vars.toolbar);
7177			if (opts.controls.arrows)
7178				vars.BODY.append(vars.nextButton).append(vars.prevButton);
7179
7180			if (opts.controls.thumbnail && vars.total > 1) {
7181				vars.BODY.append(vars.thumbnails);
7182				vars.thumbnails.addClass(opts.skin).addClass('ilightbox-' + path);
7183				$('div.ilightbox-thumbnails-grid', vars.thumbnails).empty();
7184				vars.thumbs = true;
7185			}
7186
7187			//Configure loader and arrows
7188			var loaderCss = (opts.path.toLowerCase() == "horizontal") ? {
7189				left: parseInt((viewport.width / 2) - (vars.loader.outerWidth() / 2))
7190			} : {
7191				top: parseInt((viewport.height / 2) - (vars.loader.outerHeight() / 2))
7192			};
7193			vars.loader.addClass(opts.skin).css(loaderCss);
7194			vars.nextButton.add(vars.prevButton).addClass(opts.skin);
7195			if (path == "horizontal")
7196				vars.loader.add(vars.nextButton).add(vars.prevButton).addClass('horizontal');
7197
7198			// Configure arrow buttons
7199			vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile');
7200
7201			if (!opts.infinite) {
7202				vars.prevButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.nextButton).add(vars.innerNextButton).removeClass('disabled');
7203
7204				if (vars.current == 0)
7205					vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
7206
7207				if (vars.current >= vars.total - 1)
7208					vars.nextButton.add(vars.innerNextButton).addClass('disabled');
7209			}
7210
7211			if (opts.show.effect) {
7212				vars.overlay.stop().fadeIn(opts.show.speed);
7213				vars.toolbar.stop().fadeIn(opts.show.speed);
7214			} else {
7215				vars.overlay.show();
7216				vars.toolbar.show();
7217			}
7218
7219			var length = recognizingItems.length;
7220			if (needRecognition) {
7221				iL.showLoader();
7222
7223				$.each(recognizingItems, function(key, val) {
7224					var resultFnc = function(result) {
7225							var key = -1,
7226								filter = iL.items.filter(function(e, i, arr) {
7227									if (e.URL == result.url)
7228										key = i;
7229
7230									return e.URL == result.url;
7231								}),
7232								self = iL.items[key];
7233
7234							if (result)
7235								$.extend(true, self, {
7236									URL: result.source,
7237									type: result.type,
7238									recognized: true,
7239									options: {
7240										html5video: result.html5video,
7241										width: (result.type == "image") ? 0 : (result.width || self.width),
7242										height: (result.type == "image") ? 0 : (result.height || self.height),
7243										thumbnail: self.options.thumbnail || result.thumbnail
7244									}
7245								});
7246
7247							length--;
7248
7249							if (length == 0) {
7250								iL.hideLoader();
7251
7252								vars.dontGenerateThumbs = false;
7253								iL.generateThumbnails();
7254
7255								if (opts.show.effect)
7256									setTimeout(function() {
7257										iL.generateBoxes();
7258									}, opts.show.speed);
7259								else
7260									iL.generateBoxes();
7261							}
7262						};
7263
7264					iL.ogpRecognition(this, resultFnc);
7265				});
7266			}
7267			else {
7268				if (opts.show.effect)
7269					setTimeout(function() {
7270						iL.generateBoxes();
7271					}, opts.show.speed);
7272				else
7273					iL.generateBoxes();
7274			}
7275
7276			iL.createUI();
7277
7278			window.iLightBox = {
7279				close: function() {
7280					iL.closeAction();
7281				},
7282				fullscreen: function() {
7283					iL.fullScreenAction();
7284				},
7285				moveNext: function() {
7286					iL.moveTo('next');
7287				},
7288				movePrev: function() {
7289					iL.moveTo('prev');
7290				},
7291				goTo: function(index) {
7292					iL.goTo(index);
7293				},
7294				refresh: function() {
7295					iL.refresh();
7296				},
7297				reposition: function() {
7298					(arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto();
7299				},
7300				setOption: function(options) {
7301					iL.setOption(options);
7302				},
7303				destroy: function() {
7304					iL.closeAction();
7305					iL.dispatchItemsEvents();
7306				}
7307			};
7308
7309			if (opts.linkId) {
7310				vars.hashLock = true;
7311				window.location.hash = opts.linkId + '/' + vars.current;
7312				setTimeout(function() {
7313					vars.hashLock = false;
7314				}, 55);
7315			}
7316
7317			if (!opts.slideshow.startPaused) {
7318				iL.resume();
7319				vars.innerPlayButton.removeClass('ilightbox-play').addClass('ilightbox-pause');
7320			}
7321
7322			//Trigger the onOpen callback
7323			if (typeof iL.options.callback.onOpen == 'function') iL.options.callback.onOpen.call(iL);
7324
7325		},
7326
7327		loadContent: function(obj, opt, speed) {
7328			var iL = this,
7329				holder, item;
7330
7331			iL.createUI();
7332
7333			obj.speed = speed || iL.options.effects.loadedFadeSpeed;
7334
7335			if (opt == 'current') {
7336				if (!obj.options.mousewheel) iL.vars.lockWheel = true;
7337				else iL.vars.lockWheel = false;
7338
7339				if (!obj.options.swipe) iL.vars.lockSwipe = true;
7340				else iL.vars.lockSwipe = false;
7341			}
7342
7343			switch (opt) {
7344				case 'current':
7345					holder = iL.vars.holder, item = iL.vars.current;
7346					break;
7347				case 'next':
7348					holder = iL.vars.nextPhoto, item = iL.vars.next;
7349					break;
7350				case 'prev':
7351					holder = iL.vars.prevPhoto, item = iL.vars.prev;
7352					break;
7353			}
7354
7355			holder.removeAttr('style class').addClass('ilightbox-holder' + (supportTouch ? ' supportTouch' : '')).addClass(obj.options.skin);
7356			$('div.ilightbox-inner-toolbar', holder).remove();
7357
7358			if (obj.title || iL.options.innerToolbar) {
7359				var innerToolbar = iL.vars.innerToolbar.clone();
7360				if (obj.title && iL.options.show.title) {
7361					var title = iL.vars.title.clone();
7362					title.empty().html(obj.title);
7363					innerToolbar.append(title);
7364				}
7365				if (iL.options.innerToolbar) {
7366					innerToolbar.append((iL.vars.total > 1) ? iL.vars.toolbar.clone() : iL.vars.toolbar);
7367				}
7368				holder.prepend(innerToolbar);
7369			}
7370
7371			iL.loadSwitcher(obj, holder, item, opt);
7372		},
7373
7374		loadSwitcher: function(obj, holder, item, opt) {
7375			var iL = this,
7376				opts = iL.options,
7377				api = {
7378					element: holder,
7379					position: item
7380				};
7381
7382			switch (obj.type) {
7383				case 'image':
7384					//Trigger the onBeforeLoad callback
7385					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
7386					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
7387
7388					iL.loadImage(obj.URL, function(img) {
7389						//Trigger the onAfterLoad callback
7390						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
7391						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
7392
7393						var width = (img) ? img.width : 400,
7394							height = (img) ? img.height : 200;
7395
7396						holder.data({
7397							naturalWidth: width,
7398							naturalHeight: height
7399						});
7400						$('div.ilightbox-container', holder).empty().append((img) ? '<img src="' + obj.URL + '" class="ilightbox-image" />' : '<span class="ilightbox-alert">' + opts.errors.loadImage + '</span>');
7401
7402						//Trigger the onRender callback
7403						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
7404						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
7405
7406						iL.configureHolder(obj, opt, holder);
7407					});
7408
7409					break;
7410
7411				case 'video':
7412					holder.data({
7413						naturalWidth: obj.options.width,
7414						naturalHeight: obj.options.height
7415					});
7416
7417					iL.addContent(holder, obj);
7418
7419					//Trigger the onRender callback
7420					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
7421					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
7422
7423					iL.configureHolder(obj, opt, holder);
7424
7425					break;
7426
7427				case 'iframe':
7428					iL.showLoader();
7429					holder.data({
7430						naturalWidth: obj.options.width,
7431						naturalHeight: obj.options.height
7432					});
7433					var el = iL.addContent(holder, obj);
7434
7435					//Trigger the onRender callback
7436					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
7437					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
7438
7439					//Trigger the onBeforeLoad callback
7440					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
7441					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
7442
7443					el.bind('load', function() {
7444						//Trigger the onAfterLoad callback
7445						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
7446						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
7447
7448						iL.hideLoader();
7449						iL.configureHolder(obj, opt, holder);
7450						el.unbind('load');
7451					});
7452
7453					break;
7454
7455				case 'inline':
7456					var el = $(obj.URL),
7457						content = iL.addContent(holder, obj),
7458						images = findImageInElement(holder);
7459
7460					holder.data({
7461						naturalWidth: (iL.items[item].options.width || el.outerWidth()),
7462						naturalHeight: (iL.items[item].options.height || el.outerHeight())
7463					});
7464					content.children().eq(0).show();
7465
7466					//Trigger the onRender callback
7467					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
7468					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
7469
7470					//Trigger the onBeforeLoad callback
7471					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
7472					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
7473
7474					iL.loadImage(images, function() {
7475						//Trigger the onAfterLoad callback
7476						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
7477						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
7478
7479						iL.configureHolder(obj, opt, holder);
7480					});
7481
7482					break;
7483
7484				case 'flash':
7485					var el = iL.addContent(holder, obj);
7486
7487					holder.data({
7488						naturalWidth: (iL.items[item].options.width || el.outerWidth()),
7489						naturalHeight: (iL.items[item].options.height || el.outerHeight())
7490					});
7491
7492					//Trigger the onRender callback
7493					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
7494					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
7495
7496					iL.configureHolder(obj, opt, holder);
7497
7498					break;
7499
7500				case 'ajax':
7501					var ajax = obj.options.ajax || {};
7502					//Trigger the onBeforeLoad callback
7503					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
7504					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
7505
7506					iL.showLoader();
7507					$.ajax({
7508						url: obj.URL || opts.ajaxSetup.url,
7509						data: ajax.data || null,
7510						dataType: ajax.dataType || "html",
7511						type: ajax.type || opts.ajaxSetup.type,
7512						cache: ajax.cache || opts.ajaxSetup.cache,
7513						crossDomain: ajax.crossDomain || opts.ajaxSetup.crossDomain,
7514						global: ajax.global || opts.ajaxSetup.global,
7515						ifModified: ajax.ifModified || opts.ajaxSetup.ifModified,
7516						username: ajax.username || opts.ajaxSetup.username,
7517						password: ajax.password || opts.ajaxSetup.password,
7518						beforeSend: ajax.beforeSend || opts.ajaxSetup.beforeSend,
7519						complete: ajax.complete || opts.ajaxSetup.complete,
7520						success: function(data, textStatus, jqXHR) {
7521							iL.hideLoader();
7522
7523							var el = $(data),
7524								container = $('div.ilightbox-container', holder),
7525								elWidth = iL.items[item].options.width || parseInt(el[0].getAttribute('width')),
7526								elHeight = iL.items[item].options.height || parseInt(el[0].getAttribute('height')),
7527								css = (el[0].getAttribute('width') && el[0].getAttribute('height')) ? {
7528									'overflow': 'hidden'
7529								} : {};
7530
7531							container.empty().append($('<div class="ilightbox-wrapper"></div>').css(css).html(el));
7532							holder.show().data({
7533								naturalWidth: (elWidth || container.outerWidth()),
7534								naturalHeight: (elHeight || container.outerHeight())
7535							}).hide();
7536
7537							//Trigger the onRender callback
7538							if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
7539							if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
7540
7541							var images = findImageInElement(holder);
7542							iL.loadImage(images, function() {
7543								//Trigger the onAfterLoad callback
7544								if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
7545								if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
7546
7547								iL.configureHolder(obj, opt, holder);
7548							});
7549
7550							opts.ajaxSetup.success(data, textStatus, jqXHR);
7551							if (typeof ajax.success == 'function') ajax.success(data, textStatus, jqXHR);
7552						},
7553						error: function(jqXHR, textStatus, errorThrown) {
7554							//Trigger the onAfterLoad callback
7555							if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
7556							if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
7557
7558							iL.hideLoader();
7559							$('div.ilightbox-container', holder).empty().append('<span class="ilightbox-alert">' + opts.errors.loadContents + '</span>');
7560							iL.configureHolder(obj, opt, holder);
7561
7562							opts.ajaxSetup.error(jqXHR, textStatus, errorThrown);
7563							if (typeof ajax.error == 'function') ajax.error(jqXHR, textStatus, errorThrown);
7564						}
7565					});
7566
7567					break;
7568
7569				case 'html':
7570					var object = obj.URL,
7571						el
7572					container = $('div.ilightbox-container', holder);
7573
7574					if (object[0].nodeName) el = object.clone();
7575					else {
7576						var dom = $(object);
7577						if (dom.selector) el = $('<div>' + dom + '</div>');
7578						else el = dom;
7579					}
7580
7581					var elWidth = iL.items[item].options.width || parseInt(el.attr('width')),
7582						elHeight = iL.items[item].options.height || parseInt(el.attr('height'));
7583
7584					iL.addContent(holder, obj);
7585
7586					el.appendTo(document.documentElement).hide();
7587
7588					//Trigger the onRender callback
7589					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
7590					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
7591
7592					var images = findImageInElement(holder);
7593
7594					//Trigger the onBeforeLoad callback
7595					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
7596					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
7597
7598					iL.loadImage(images, function() {
7599						//Trigger the onAfterLoad callback
7600						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
7601						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
7602
7603						holder.show().data({
7604							naturalWidth: (elWidth || container.outerWidth()),
7605							naturalHeight: (elHeight || container.outerHeight())
7606						}).hide();
7607						el.remove();
7608
7609						iL.configureHolder(obj, opt, holder);
7610					});
7611
7612					break;
7613			}
7614		},
7615
7616		configureHolder: function(obj, opt, holder) {
7617			var iL = this,
7618				vars = iL.vars,
7619				opts = iL.options;
7620
7621			if (opt != "current")(opt == "next") ? holder.addClass('ilightbox-next') : holder.addClass('ilightbox-prev');
7622
7623			if (opt == "current")
7624				var item = vars.current;
7625			else if (opt == "next")
7626				var opacity = opts.styles.nextOpacity,
7627					item = vars.next;
7628			else
7629				var opacity = opts.styles.prevOpacity,
7630					item = vars.prev;
7631
7632			var api = {
7633				element: holder,
7634				position: item
7635			};
7636
7637			iL.items[item].options.width = iL.items[item].options.width || 0,
7638				iL.items[item].options.height = iL.items[item].options.height || 0;
7639
7640			if (opt == "current") {
7641				if (opts.show.effect) holder.css(transform, gpuAcceleration).fadeIn(obj.speed, function() {
7642					holder.css(transform, '');
7643					if (obj.caption) {
7644						iL.setCaption(obj, holder);
7645						var caption = $('div.ilightbox-caption', holder),
7646							percent = parseInt((caption.outerHeight() / holder.outerHeight()) * 100);
7647						if (opts.caption.start & percent <= 50) caption.fadeIn(opts.effects.fade
7647Speed);
7648					}
7649
7650					var social = obj.options.social;
7651					if (social) {
7652						iL.setSocial(social, obj.URL, holder);
7653						if (opts.social.start) $('div.ilightbox-social', holder).fadeIn(opts.effects.fadeSpeed);
7654					}
7655
7656					//Generate thumbnails
7657					iL.generateThumbnails();
7658
7659					//Trigger the onShow callback
7660					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
7661					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
7662				});
7663				else {
7664					holder.show();
7665
7666					//Generate thumbnails
7667					iL.generateThumbnails();
7668
7669					//Trigger the onShow callback
7670					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
7671					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
7672				}
7673			} else {
7674				if (opts.show.effect) holder.fadeTo(obj.speed, opacity, function() {
7675					if (opt == "next") vars.nextLock = false;
7676					else vars.prevLock = false;
7677
7678					//Generate thumbnails
7679					iL.generateThumbnails();
7680
7681					//Trigger the onShow callback
7682					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
7683					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
7684				});
7685				else {
7686					holder.css({
7687						opacity: opacity
7688					}).show();
7689					if (opt == "next") vars.nextLock = false;
7690					else vars.prevLock = false;
7691
7692					//Generate thumbnails
7693					iL.generateThumbnails();
7694
7695					//Trigger the onShow callback
7696					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
7697					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
7698				}
7699			}
7700
7701			setTimeout(function() {
7702				iL.repositionPhoto();
7703			}, 0);
7704		},
7705
7706		generateBoxes: function() {
7707			var iL = this,
7708				vars = iL.vars,
7709				opts = iL.options;
7710
7711			if (opts.infinite && vars.total >= 3) {
7712				if (vars.current == vars.total - 1) vars.next = 0;
7713				if (vars.current == 0) vars.prev = vars.total - 1;
7714			} else opts.infinite = false;
7715
7716			iL.loadContent(iL.items[vars.current], 'current', opts.show.speed);
7717
7718			if (iL.items[vars.next]) iL.loadContent(iL.items[vars.next], 'next', opts.show.speed);
7719			if (iL.items[vars.prev]) iL.loadContent(iL.items[vars.prev], 'prev', opts.show.speed);
7720		},
7721
7722		generateThumbnails: function() {
7723			var iL = this,
7724				vars = iL.vars,
7725				opts = iL.options,
7726				timeOut = null;
7727
7728			if (vars.thumbs && !iL.vars.dontGenerateThumbs) {
7729				var thumbnails = vars.thumbnails,
7730					container = $('div.ilightbox-thumbnails-container', thumbnails),
7731					grid = $('div.ilightbox-thumbnails-grid', container),
7732					i = 0;
7733
7734				grid.removeAttr('style').empty();
7735
7736				$.each(iL.items, function(key, val) {
7737					var isActive = (vars.current == key) ? 'ilightbox-active' : '',
7738						opacity = (vars.current == key) ? opts.thumbnails.activeOpacity : opts.thumbnails.normalOpacity,
7739						thumb = val.options.thumbnail,
7740						thumbnail = $('<div class="ilightbox-thumbnail"></div>'),
7741						icon = $('<div class="ilightbox-thumbnail-icon"></div>');
7742
7743					thumbnail.css({
7744						opacity: 0
7745					}).addClass(isActive);
7746
7747					if ((val.type == "video" || val.type == "flash") && typeof val.options.icon == 'undefined') {
7748						icon.addClass('ilightbox-thumbnail-video');
7749						thumbnail.append(icon);
7750					} else if (val.options.icon) {
7751						icon.addClass('ilightbox-thumbnail-' + val.options.icon);
7752						thumbnail.append(icon);
7753					}
7754
7755					if (thumb) iL.loadImage(thumb, function(img) {
7756						if (val.clone) return;
7757						i++;
7758						if (img) thumbnail.data({
7759							naturalWidth: img.width,
7760							naturalHeight: img.height
7761						}).append('<img src="' + thumb + '" border="0" />');
7762						else thumbnail.data({
7763							naturalWidth: opts.thumbnails.maxWidth,
7764							naturalHeight: opts.thumbnails.maxHeight
7765						});
7766
7767						clearTimeout(timeOut);
7768						timeOut = setTimeout(function() {
7769							iL.positionThumbnails(thumbnails, container, grid);
7770						}, 20);
7771						setTimeout(function() {
7772							thumbnail.fadeTo(opts.effects.loadedFadeSpeed, opacity);
7773						}, i * 20);
7774					});
7775
7776					grid.append(thumbnail);
7777				});
7778				iL.vars.dontGenerateThumbs = true;
7779			}
7780		},
7781
7782		positionThumbnails: function(thumbnails, container, grid) {
7783			var iL = this,
7784				vars = iL.vars,
7785				opts = iL.options,
7786				viewport = getViewport(),
7787				path = opts.path.toLowerCase();
7788
7789			if (!thumbnails) thumbnails = vars.thumbnails;
7790			if (!container) container = $('div.ilightbox-thumbnails-container', thumbnails);
7791			if (!grid) grid = $('div.ilightbox-thumbnails-grid', container);
7792
7793			var thumbs = $('.ilightbox-thumbnail', grid),
7794				widthAvail = (path == 'horizontal') ? viewport.width - opts.styles.pageOffsetX : thumbs.eq(0).outerWidth() - opts.styles.pageOffsetX,
7795				heightAvail = (path == 'horizontal') ? thumbs.eq(0).outerHeight() - opts.styles.pageOffsetY : viewport.height - opts.styles.pageOffsetY,
7796				gridWidth = (path == 'horizontal') ? 0 : widthAvail,
7797				gridHeight = (path == 'horizontal') ? heightAvail : 0,
7798				active = $('.ilightbox-active', grid),
7799				gridCss = {},
7800				css = {};
7801
7802			if (arguments.length < 3) {
7803				thumbs.css({
7804					opacity: opts.thumbnails.normalOpacity
7805				});
7806				active.css({
7807					opacity: opts.thumbnails.activeOpacity
7808				});
7809			}
7810
7811			thumbs.each(function(i) {
7812				var t = $(this),
7813					data = t.data(),
7814					width = (path == 'horizontal') ? 0 : opts.thumbnails.maxWidth;
7815				height = (path == 'horizontal') ? opts.thumbnails.maxHeight : 0;
7816				dims = iL.getNewDimenstions(width, height, data.naturalWidth, data.naturalHeight, true);
7817
7818				t.css({
7819					width: dims.width,
7820					height: dims.height
7821				});
7822				if (path == 'horizontal') t.css({
7823					'float': 'left'
7824				});
7825
7826				(path == 'horizontal') ? (
7827					gridWidth += t.outerWidth()
7828				) : (
7829					gridHeight += t.outerHeight()
7830				);
7831			});
7832
7833			gridCss = {
7834				width: gridWidth,
7835				height: gridHeight
7836			};
7837
7838			grid.css(gridCss);
7839
7840			gridCss = {};
7841
7842			var gridOffset = grid.offset(),
7843				activeOffset = (active.length) ? active.offset() : {
7844					top: parseInt(heightAvail / 2),
7845					left: parseInt(widthAvail / 2)
7846				};
7847
7848			gridOffset.top = (gridOffset.top - $doc.scrollTop()),
7849				gridOffset.left = (gridOffset.left - $doc.scrollLeft()),
7850				activeOffset.top = (activeOffset.top - gridOffset.top - $doc.scrollTop()),
7851				activeOffset.left = (activeOffset.left - gridOffset.left - $doc.scrollLeft());
7852
7853			(path == 'horizontal') ? (
7854				gridCss.top = 0,
7855				gridCss.left = parseInt((widthAvail / 2) - activeOffset.left - (active.outerWidth() / 2))
7856			) : (
7857				gridCss.top = parseInt(((heightAvail / 2) - activeOffset.top - (active.outerHeight() / 2))),
7858				gridCss.left = 0
7859			);
7860
7861			if (arguments.length < 3) grid.stop().animate(gridCss, opts.effects.repositionSpeed, 'easeOutCirc');
7862			else grid.css(gridCss);
7863		},
7864
7865		loadImage: function(image, callback) {
7866			if (!$.isArray(image)) image = [image];
7867
7868			var iL = this,
7869				length = image.length;
7870
7871			if (length > 0) {
7872				iL.showLoader();
7873				$.each(image, function(index, value) {
7874					var img = new Image();
7875					img.onload = function() {
7876						length -= 1;
7877						if (length == 0) {
7878							iL.hideLoader();
7879							callback(img);
7880						}
7881					};
7882					img.onerror = img.onabort = function() {
7883						length -= 1;
7884						if (length == 0) {
7885							iL.hideLoader();
7886							callback(false);
7887						}
7888					};
7889					img.src = image[index];
7890				});
7891			} else callback(false);
7892		},
7893
7894		patchItemsEvents: function() {
7895			var iL = this,
7896				vars = iL.vars,
7897				clickEvent = supportTouch ? "itap.iL" : "click.iL",
7898				vEvent = supportTouch ? "click.iL" : "itap.iL";
7899
7900			if (iL.context && iL.selector) {
7901				var $items = $(iL.selector, iL.context);
7902				$(iL.context).on(clickEvent, iL.selector, function() {
7903
7904					var $this = $(this),
7905						key = $items.index($this);
7906					if (UNCODE.isMobile) {
7907						var isCarousel = $this.closest('.owl-carousel');
7908						if (isCarousel.length) {
7909							if (isCarousel.hasClass('owl-translating')) return false;
7910						}
7911					}
7912
7913					vars.current = key;
7914					vars.next = iL.items[key + 1] ? key + 1 : null;
7915					vars.prev = iL.items[key - 1] ? key - 1 : null;
7916
7917					iL.addContents();
7918					iL.patchEvents();
7919
7920					return false;
7921				}).on(vEvent, iL.selector, function() {
7922					return false;
7923				});
7924			} else
7925				$.each(iL.itemsObject, function(key, val) {
7926					val.on(clickEvent, function() {
7927						vars.current = key;
7928						vars.next = iL.items[key + 1] ? key + 1 : null;
7929						vars.prev = iL.items[key - 1] ? key - 1 : null;
7930
7931						iL.addContents();
7932						iL.patchEvents();
7933
7934						return false;
7935					}).on(vEvent, function() {
7936						return false;
7937					});
7938				});
7939		},
7940
7941		dispatchItemsEvents: function() {
7942			var iL = this,
7943				vars = iL.vars,
7944				opts = iL.options;
7945
7946			if (iL.context && iL.selector)
7947				$(iL.context).off('.iL', iL.selector);
7948			else
7949				$.each(iL.itemsObject, function(key, val) {
7950					val.off('.iL');
7951				});
7952		},
7953
7954		refresh: function() {
7955			var iL = this;
7956
7957			iL.dispatchItemsEvents();
7958			iL.attachItems();
7959			iL.normalizeItems();
7960			iL.patchItemsEvents();
7961		},
7962
7963		patchEvents: function() {
7964			var iL = this,
7965				vars = iL.vars,
7966				opts = iL.options,
7967				path = opts.path.toLowerCase(),
7968				holders = $('.ilightbox-holder'),
7969				fullscreenEvent = fullScreenApi.fullScreenEventName + '.iLightBox',
7970				durationThreshold = 1000,
7971				horizontalDistanceThreshold =
7972				verticalDistanceThreshold = 100,
7973				buttonsArray = [vars.nextButton[0], vars.prevButton[0], vars.nextButton[0].firstChild, vars.prevButton[0].firstChild];
7974
7975			$win.bind('resize.iLightBox', function() {
7976				var viewport = getViewport();
7977
7978				if (opts.mobileOptimizer && !opts.innerToolbar) vars.isMobile = viewport.width <= vars.mobileMaxWidth;
7979				vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile');
7980
7981				iL.repositionPhoto(null);
7982				if (supportTouch) {
7983					clearTimeout(vars.setTime);
7984					vars.setTime = setTimeout(function() {
7985						var scrollTop = getScrollXY().y;
7986						window.scrollTo(0, scrollTop - 30);
7987						window.scrollTo(0, scrollTop + 30);
7988						window.scrollTo(0, scrollTop);
7989					}, 2000);
7990				}
7991				if (vars.thumbs) iL.positionThumbnails();
7992			}).bind('keydown.iLightBox', function(event) {
7993				if (opts.controls.keyboard) {
7994					switch (event.keyCode) {
7995						case 13:
7996							if (event.shiftKey && opts.keyboard.shift_enter) iL.fullScreenAction();
7997							break;
7998						case 27:
7999							if (opts.keyboard.esc) iL.closeAction();
8000							break;
8001						case 37:
8002							if (opts.keyboard.left && !vars.lockKey) iL.moveTo('prev');
8003							break;
8004						case 38:
8005							if (opts.keyboard.up && !vars.lockKey) iL.moveTo('prev');
8006							break;
8007						case 39:
8008							if (opts.keyboard.right && !vars.lockKey) iL.moveTo('next');
8009							break;
8010						case 40:
8011							if (opts.keyboard.down && !vars.lockKey) iL.moveTo('next');
8012							break;
8013					}
8014				}
8015			});
8016
8017			if (fullScreenApi.supportsFullScreen) $win.bind(fullscreenEvent, function() {
8018				iL.doFullscreen();
8019			});
8020
8021			var holderEventsArr = [opts.caption.show + '.iLightBox', opts.caption.hide + '.iLightBox', opts.social.show + '.iLightBox', opts.social.hide + '.iLightBox'].filter(function(e, i, arr) {
8022					return arr.lastIndexOf(e) === i;
8023				}),
8024				holderEvents = "";
8025
8026			$.each(holderEventsArr, function(key, val) {
8027				if (key != 0) holderEvents += ' ';
8028				holderEvents += val;
8029			});
8030
8031			$doc.on(clickEvent, '.ilightbox-overlay', function() {
8032				if (opts.overlay.blur) iL.closeAction();
8033			}).on(clickEvent, '.ilightbox-next, .ilightbox-next-button', function() {
8034				iL.moveTo('next');
8035			}).on(clickEvent, '.ilightbox-prev, .ilightbox-prev-button', function() {
8036				iL.moveTo('prev');
8037			}).on(clickEvent, '.ilightbox-thumbnail', function() {
8038				var t = $(this),
8039					thumbs = $('.ilightbox-thumbnail', vars.thumbnails),
8040					index = thumbs.index(t);
8041
8042				if (index != vars.current) iL.goTo(index);
8043			}).on(holderEvents, '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) {
8044				var caption = $('div.ilightbox-caption', vars.holder),
8045					social = $('div.ilightbox-social', vars.holder),
8046					fadeSpeed = opts.effects.fadeSpeed;
8047
8048				if (vars.nextLock || vars.prevLock) {
8049					if (e.type == opts.caption.show && !caption.is(':visible')) caption.fadeIn(fadeSpeed);
8050					else if (e.type == opts.caption.hide && caption.is(':visible')) caption.fadeOut(fadeSpeed);
8051
8052					if (e.type == opts.social.show && !social.is(':visible')) social.fadeIn(fadeSpeed);
8053					else if (e.type == opts.social.hide && social.is(':visible')) social.fadeOut(fadeSpeed);
8054				} else {
8055					if (e.type == opts.caption.show && !caption.is(':visible')) caption.stop().fadeIn(fadeSpeed);
8056					else if (e.type == opts.caption.hide && caption.is(':visible')) caption.stop().fadeOut(fadeSpeed);
8057
8058					if (e.type == opts.social.show && !social.is(':visible')) social.stop().fadeIn(fadeSpeed);
8059					else if (e.type == opts.social.hide && social.is(':visible')) social.stop().fadeOut(fadeSpeed);
8060				}
8061			}).on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-wrapper', function(e) {
8062				if (e.type == 'mouseenter') vars.lockWheel = true;
8063				else vars.lockWheel = false;
8064			}).on(clickEvent, '.ilightbox-toolbar a.ilightbox-close, .ilightbox-toolbar a.ilightbox-fullscreen, .ilightbox-toolbar a.ilightbox-play, .ilightbox-toolbar a.ilightbox-pause', function() {
8065				var t = $(this);
8066
8067				if (t.hasClass('ilightbox-fullscreen')) iL.fullScreenAction();
8068				else if (t.hasClass('ilightbox-play')) {
8069					iL.resume();
8070					t.addClass('ilightbox-pause').removeClass('ilightbox-play');
8071				} else if (t.hasClass('ilightbox-pause')) {
8072					iL.pause();
8073					t.addClass('ilightbox-play').removeClass('ilightbox-pause');
8074				} else iL.closeAction();
8075			}).on(touchMoveEvent, '.ilightbox-overlay, .ilightbox-thumbnails-container', function(e) {
8076				// prevent scrolling
8077				e.preventDefault();
8078			});
8079
8080			function mouseMoveHandler(e) {
8081				if (!vars.isMobile) {
8082					if (!vars.mouseID) {
8083						vars.hideableElements.show();
8084					}
8085
8086					vars.mouseID = clearTimeout(vars.mouseID);
8087
8088					if (buttonsArray.indexOf(e.target) === -1)
8089						vars.mouseID = setTimeout(function() {
8090							vars.hideableElements.hide();
8091							vars.mouseID = clearTimeout(vars.mouseID);
8092						}, 3000);
8093				}
8094			}
8095
8096			if (opts.controls.arrows && !supportTouch) $doc.on('mousemove.iLightBox', mouseMoveHandler);
8097
8098			if (opts.controls.slideshow && opts.slideshow.pauseOnHover) $doc.on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) {
8099				if (e.type == 'mouseenter' && vars.cycleID) iL.pause();
8100				else if (e.type == 'mouseleave' && vars.isPaused) iL.resume();
8101			});
8102
8103			var switchers = $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails');
8104
8105			if (opts.controls.mousewheel) switchers.on('mousewheel.iLightBox', function(event, delta) {
8106				if (!vars.lockWheel) {
8107					event.preventDefault();
8108					if (delta < 0) iL.moveTo('next');
8109					else if (delta > 0) iL.moveTo('prev');
8110				}
8111			});
8112
8113			if (opts.controls.swipe) holders.on(touchStartEvent, function(event) {
8114				if (vars.nextLock || vars.prevLock || vars.total == 1 || vars.lockSwipe) return;
8115
8116				vars.BODY.addClass('ilightbox-closedhand');
8117
8118				var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event,
8119					scrollTop = $doc.scrollTop(),
8120					scrollLeft = $doc.scrollLeft(),
8121					offsets = [
8122						holders.eq(0).offset(),
8123						holders.eq(1).offset(),
8124						holders.eq(2).offset()
8125					],
8126					offSet = [{
8127						top: offsets[0].top - scrollTop,
8128						left: offsets[0].left - scrollLeft
8129					}, {
8130						top: offsets[1].top - scrollTop,
8131						left: offsets[1].left - scrollLeft
8132					}, {
8133						top: offsets[2].top - scrollTop,
8134						left: offsets[2].left - scrollLeft
8135					}],
8136					start = {
8137						time: (new Date()).getTime(),
8138						coords: [data.pageX - scrollLeft, data.pageY - scrollTop]
8139					},
8140					stop;
8141
8142				function moveEachHandler(i) {
8143					var t = $(this),
8144						offset = offSet[i],
8145						scroll = [(start.coords[0] - stop.coords[0]), (start.coords[1] - stop.coords[1])];
8146
8147					t[0].style[path == "horizontal" ? 'left' : 'top'] = (path == "horizontal" ? offset.left - scroll[0] : offset.top - scroll[1]) + 'px';
8148				}
8149
8150				function moveHandler(event) {
8151
8152					if (!start) return;
8153
8154					var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event;
8155
8156					stop = {
8157						time: (new Date()).getTime(),
8158						coords: [data.pageX - scrollLeft, data.pageY - scrollTop]
8159					};
8160
8161					holders.each(moveEachHandler);
8162
8163					// prevent scrolling
8164					event.preventDefault();
8165				}
8166
8167				function repositionHolders() {
8168					holders.each(function() {
8169						var t = $(this),
8170							offset = t.data('offset') || {
8171								top: t.offset().top - scrollTop,
8172								left: t.offset().left - scrollLeft
8173							},
8174							top = offset.top,
8175							left = offset.left;
8176
8177						t.css(transform, gpuAcceleration).stop().animate({
8178							top: top,
8179							left: left
8180						}, 500, 'easeOutCirc', function() {
8181							t.css(transform, '');
8182						});
8183					});
8184				}
8185
8186				holders.bind(touchMoveEvent, moveHandler);
8187				$doc.one(touchStopEvent, function(event) {
8188					holders.unbind(touchMoveEvent, moveHandler);
8189
8190					vars.BODY.removeClass('ilightbox-closedhand');
8191
8192					if (start && stop) {
8193						if (path == "horizontal" && stop.time - start.time < durationThreshold && abs(start.coords[0] - stop.coords[0]) > horizontalDistanceThreshold && abs(start.coords[1] - stop.coords[1]) < verticalDistanceThreshold) {
8194							if (start.coords[0] > stop.coords[0]) {
8195								if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders();
8196								else {
8197									vars.isSwipe = true;
8198									iL.moveTo('next');
8199								}
8200							} else {
8201								if (vars.current == 0 && !opts.infinite) repositionHolders();
8202								else {
8203									vars.isSwipe = true;
8204									iL.moveTo('prev');
8205								}
8206							}
8207						} 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) {
8208							if (start.coords[1] > stop.coords[1]) {
8209								if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders();
8210								else {
8211									vars.isSwipe = true;
8212									iL.moveTo('next');
8213								}
8214							} else {
8215								if (vars.current == 0 && !opts.infinite) repositionHolders();
8216								else {
8217									vars.isSwipe = true;
8218									iL.moveTo('prev');
8219								}
8220							}
8221						} else repositionHolders();
8222					}
8223					start = stop = undefined;
8224				});
8225			});
8226
8227		},
8228
8229		goTo: function(index) {
8230			var iL = this,
8231				vars = iL.vars,
8232				opts = iL.options,
8233				diff = (index - vars.current);
8234
8235			if (opts.infinite) {
8236				if (index == vars.total - 1 && vars.current == 0) diff = -1;
8237				if (vars.current == vars.total - 1 && index == 0) diff = 1;
8238			}
8239
8240			if (diff == 1) iL.moveTo('next');
8241			else if (diff == -1) iL.moveTo('prev');
8242			else {
8243
8244				if (vars.nextLock || vars.prevLock) return false;
8245
8246				//Trigger the onBeforeChange callback
8247				if (typeof opts.callback.onBeforeChange == 'function') opts.callback.onBeforeChange.call(iL, iL.ui);
8248
8249				if (opts.linkId) {
8250					vars.hashLock = true;
8251					window.location.hash = opts.linkId + '/' + index;
8252				}
8253
8254				if (iL.items[index]) {
8255					if (!iL.items[index].options.mousewheel) vars.lockWheel = true;
8256					else iL.vars.lockWheel = false;
8257
8258					if (!iL.items[index].options.swipe) vars.lockSwipe = true;
8259					else vars.lockSwipe = false;
8260				}
8261
8262				$.each([vars.holder, vars.nextPhoto, vars.prevPhoto], function(key, val) {
8263					val.css(transform, gpuAcceleration).fadeOut(opts.effects.loadedFadeSpeed);
8264				});
8265
8266				vars.current = index;
8267				vars.next = index + 1;
8268				vars.prev = index - 1;
8269
8270				iL.createUI();
8271
8272				setTimeout(function() {
8273					iL.generateBoxes();
8274				}, opts.effects.loadedFadeSpeed + 50);
8275
8276				$('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(index).addClass('ilightbox-active');
8277				iL.positionThumbnails();
8278
8279				if (opts.linkId) setTimeout(function() {
8280					vars.hashLock = false;
8281				}, 55);
8282
8283				// Configure arrow buttons
8284				if (!opts.infinite) {
8285					vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
8286
8287					if (vars.current == 0) {
8288						vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
8289					}
8290					if (vars.current >= vars.total - 1) {
8291						vars.nextButton.add(vars.innerNextButton).addClass('disabled');
8292					}
8293				}
8294
8295				// Reset next cycle timeout
8296				iL.resetCycle();
8297
8298				//Trigger the onAfterChange callback
8299				if (typeof opts.callback.onAfterChange == 'function') opts.callback.onAfterChange.call(iL, iL.ui);
8300			}
8301		},
8302
8303		moveTo: function(side) {
8304			var iL = this,
8305				vars = iL.vars,
8306				opts = iL.options,
8307				path = opts.path.toLowerCase(),
8308				viewport = getViewport(),
8309				switchSpeed = opts.effects.switchSpeed;
8310
8311			if (vars.nextLock || vars.prevLock) return false;
8312			else {
8313
8314				var item = (side == "next") ? vars.next : vars.prev;
8315
8316				if (opts.linkId) {
8317					vars.hashLock = true;
8318					window.location.hash = opts.linkId + '/' + item;
8319				}
8320
8321				if (side == "next") {
8322					if (!iL.items[item]) return false;
8323					var firstHolder = vars.nextPhoto,
8324						secondHolder = vars.holder,
8325						lastHolder = vars.prevPhoto,
8326						firstClass = 'ilightbox-prev',
8327						secondClass = 'ilightbox-next';
8328				} else if (side == "prev") {
8329					if (!iL.items[item]) return false;
8330					var firstHolder = vars.prevPhoto,
8331						secondHolder = vars.holder,
8332						lastHolder = vars.nextPhoto,
8333						firstClass = 'ilightbox-next',
8334						secondClass = 'ilightbox-prev';
8335				}
8336
8337				//Trigger the onBeforeChange callback
8338				if (typeof opts.callback.onBeforeChange == 'function')
8339					opts.callback.onBeforeChange.call(iL, iL.ui);
8340
8341				(side == "next") ? vars.nextLock = true: vars.prevLock = true;
8342
8343				var captionFirst = $('div.ilightbox-caption', secondHolder),
8344					socialFirst = $('div.ilightbox-social', secondHolder);
8345
8346				if (captionFirst.length)
8347					captionFirst.stop().fadeOut(switchSpeed, function() {
8348						$(this).remove();
8349					});
8350				if (socialFirst.length)
8351					socialFirst.stop().fadeOut(switchSpeed, function() {
8352						$(this).remove();
8353					});
8354
8355				if (iL.items[item].caption) {
8356					iL.setCaption(iL.items[item], firstHolder);
8357					var caption = $('div.ilightbox-caption', firstHolder),
8358						percent = parseInt((caption.outerHeight() / firstHolder.outerHeight()) * 100);
8359					if (opts.caption.start && percent <= 50) caption.fadeIn(switchSpeed);
8360				}
8361
8362				var social = iL.items[item].options.social;
8363				if (social) {
8364					iL.setSocial(social, iL.items[item].URL, firstHolder);
8365					if (opts.social.start) $('div.ilightbox-social', firstHolder).fadeIn(opts.effects.fadeSpeed);
8366				}
8367
8368				$.each([firstHolder, secondHolder, lastHolder], function(key, val) {
8369					val.removeClass('ilightbox-next ilightbox-prev');
8370				});
8371
8372				var firstOffset = firstHolder.data('offset'),
8373					winW = (viewport.width - (opts.styles.pageOffsetX)),
8374					winH = (viewport.height - (opts.styles.pageOffsetY)),
8375					width = firstOffset.newDims.width,
8376					height = firstOffset.newDims.height,
8377					thumbsOffset = firstOffset.thumbsOffset,
8378					diff = firstOffset.diff,
8379					top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)),
8380					left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2));
8381
8382				var secondOffset = secondHolder.data('offset'),
8383					object = secondOffset.object;
8384
8385				if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) {
8386					var objRatio = width / height;
8387					height = height - vars.captionHeight;
8388					width = height * objRatio;
8389					top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)),
8390					left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2));
8391				}
8392
8393				firstHolder.css(transform, gpuAcceleration).animate({
8394					top: top,
8395					left: left,
8396					opacity: 1
8397				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
8398					firstHolder.css(transform, '');
8399				});
8400
8401				$('div.ilightbox-container', firstHolder).animate({
8402					width: width,
8403					height: height
8404				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc');
8405
8406
8407				diff = secondOffset.diff;
8408
8409				width = secondOffset.newDims.width,
8410					height = secondOffset.newDims.height;
8411
8412				width = parseInt(width * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']),
8413					height = parseInt(height * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']),
8414					top = (path == 'horizontal') ? parseInt((winH / 2) - object.offsetY - (height / 2) - diff.H - (thumbsOffset.H / 2)) : parseInt(winH - object.offsetX - diff.H - (thumbsOffset.H / 2));
8415
8416				if (side == 'prev')
8417					left = (path == 'horizontal') ? parseInt(winW - object.offsetX - diff.W - (thumbsOffset.W / 2)) : parseInt((winW / 2) - (width / 2) - diff.W - object.offsetY - (thumbsOffset.W / 2));
8418				else {
8419					top = (path == 'horizontal') ? top : parseInt(object.offsetX - diff.H - height - (thumbsOffset.H / 2)),
8420						left = (path == 'horizontal') ? parseInt(object.offsetX - diff.W - width - (thumbsOffset.W / 2)) : parseInt((winW / 2) - object.offsetY - (width / 2) - diff.W - (thumbsOffset.W / 2));
8421				}
8422
8423				if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) {
8424					var objRatio = width / height;
8425					height = height - vars.captionHeight;
8426					width = height * objRatio;
8427					top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2));
8428				}
8429
8430				$('div.ilightbox-container', secondHolder).animate({
8431					width: width,
8432					height: height
8433				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc');
8434
8435				secondHolder.addClass(firstClass).css(transform, gpuAcceleration).animate({
8436					top: top,
8437					left: left,
8438					opacity: opts.styles.prevOpacity
8439				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
8440					secondHolder.css(transform, '');
8441
8442					$('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(item).addClass('ilightbox-active');
8443					iL.positionThumbnails();
8444
8445					if (iL.items[item]) {
8446						if (!iL.items[item].options.mousewheel) vars.lockWheel = true;
8447						else vars.lockWheel = false;
8448
8449						if (!iL.items[item].options.swipe) vars.lockSwipe = true;
8450						else vars.lockSwipe = false;
8451					}
8452
8453					vars.isSwipe = false;
8454
8455					if (side == "next") {
8456						vars.nextPhoto = lastHolder,
8457							vars.prevPhoto = secondHolder,
8458							vars.holder = firstHolder;
8459
8460						vars.nextPhoto.hide();
8461
8462						vars.next = vars.next + 1,
8463							vars.prev = vars.current,
8464							vars.current = vars.current + 1;
8465
8466						if (opts.infinite) {
8467							if (vars.current > vars.total - 1) vars.current = 0;
8468							if (vars.current == vars.total - 1) vars.next = 0;
8469							if (vars.current == 0) vars.prev = vars.total - 1;
8470						}
8471
8472						iL.createUI();
8473
8474						if (!iL.items[vars.next])
8475							vars.nextLock = false;
8476						else
8477							iL.loadContent(iL.items[vars.next], 'next');
8478					} else {
8479						vars.prevPhoto = lastHolder;
8480						vars.nextPhoto = secondHolder;
8481						vars.holder = firstHolder;
8482
8483						vars.prevPhoto.hide();
8484
8485						vars.next = vars.current;
8486						vars.current = vars.prev;
8487						vars.prev = vars.current - 1;
8488
8489						if (opts.infinite) {
8490							if (vars.current == vars.total - 1) vars.next = 0;
8491							if (vars.current == 0) vars.prev = vars.total - 1;
8492						}
8493
8494						iL.createUI();
8495
8496						if (!iL.items[vars.prev])
8497							vars.prevLock = false;
8498						else
8499							iL.loadContent(iL.items[vars.prev], 'prev');
8500					}
8501
8502					if (opts.linkId) setTimeout(function() {
8503						vars.hashLock = false;
8504					}, 55);
8505
8506					// Configure arrow buttons
8507					if (!opts.infinite) {
8508						vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
8509
8510						if (vars.current == 0)
8511							vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
8512						if (vars.current >= vars.total - 1)
8513							vars.nextButton.add(vars.innerNextButton).addClass('disabled');
8514					}
8515
8516					iL.repositionPhoto();
8517
8518					// Reset next cycle timeout
8519					iL.resetCycle();
8520
8521					//Trigger the onAfterChange callback
8522					if (typeof opts.callback.onAfterChange == 'function')
8523						opts.callback.onAfterChange.call(iL, iL.ui);
8524				});
8525
8526				top = (path == 'horizontal') ? getPixel(lastHolder, 'top') : ((side == "next") ? parseInt(-(winH / 2) - lastHolder.outerHeight()) : parseInt(top * 2)),
8527					left = (path == 'horizontal') ? ((side == "next") ? parseInt(-(winW / 2) - lastHolder.outerWidth()) : parseInt(left * 2)) : getPixel(lastHolder, 'left');
8528
8529				lastHolder.css(transform, gpuAcceleration).animate({
8530					top: top,
8531					left: left,
8532					opacity: opts.styles.nextOpacity
8533				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
8534					lastHolder.css(transform, '');
8535				}).addClass(secondClass);
8536
8537			}
8538		},
8539
8540		setCaption: function(obj, target) {
8541			var iL = this,
8542				caption = $('<div class="ilightbox-caption"></div>');
8543
8544			if (obj.caption) {
8545				caption.html(obj.caption);
8546				$('div.ilightbox-container', target).append(caption);
8547			}
8548		},
8549
8550		normalizeSocial: function(obj, url) {
8551			var iL = this,
8552				vars = iL.vars,
8553				opts = iL.options,
8554				baseURL = window.location.href;
8555
8556			$.each(obj, function(key, value) {
8557				if (!value)
8558					return true;
8559
8560				var item = key.toLowerCase(),
8561					source, text;
8562
8563				switch (item) {
8564					case 'facebook':
8565						source = "http://www.facebook.com/share.php?v=4&src=bm&u={URL}",
8566							text = "Share on Facebook";
8567						break;
8568					case 'twitter':
8569						source = "http://twitter.com/home?status={URL}",
8570							text = "Share on Twitter";
8571						break;
8572					case 'googleplus':
8573						source = "https://plus.google.com/share?url={URL}",
8574							text = "Share on Google+";
8575						break;
8576					case 'delicious':
8577						source = "http://delicious.com/post?url={URL}",
8578							text = "Share on Delicious";
8579						break;
8580					case 'digg':
8581						source = "http://digg.com/submit?phase=2&url={URL}",
8582							text = "Share on Digg";
8583						break;
8584					case 'reddit':
8585						source = "http://reddit.com/submit?url={URL}",
8586							text = "Share on reddit";
8587						break;
8588				}
8589
8590				obj[key] = {
8591					URL: value.URL && absolutizeURI(baseURL, value.URL) || opts.linkId && window.location.href || typeof url !== 'string' && baseURL || url && absolutizeURI(baseURL, url) || baseURL,
8592					source: value.source || source || value.URL && absolutizeURI(baseURL, value.URL) || url && absolutizeURI(baseURL, url),
8593					text: value.text || text || "Share on " + key,
8594					width: (typeof(value.width) != 'undefined' && !isNaN(value.width)) ? parseInt(value.width) : 640,
8595					height: value.height || 360
8596				};
8597
8598			});
8599
8600			return obj;
8601		},
8602
8603		setSocial: function(obj, url, target) {
8604			var iL = this,
8605				socialBar = $('<div class="ilightbox-social"></div>'),
8606				buttons = '<ul>';
8607
8608			obj = iL.normalizeSocial(obj, url);
8609
8610			$.each(obj, function(key, value) {
8611				var item = key.toLowerCase(),
8612					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, '+'));
8613				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>';
8614			});
8615
8616			buttons += '</ul>';
8617
8618			socialBar.html(buttons);
8619			$('div.ilightbox-container', target).append(socialBar);
8620		},
8621
8622		fullScreenAction: function() {
8623			var iL = this,
8624				vars = iL.vars;
8625
8626			if (fullScreenApi.supportsFullScreen) {
8627				if (fullScreenApi.isFullScreen()) fullScreenApi.cancelFullScreen(document.documentElement);
8628				else fullScreenApi.requestFullScreen(document.documentElement);
8629			} else {
8630				iL.doFullscreen();
8631			}
8632		},
8633
8634		doFullscreen: function() {
8635			var iL = this,
8636				vars = iL.vars,
8637				viewport = getViewport(),
8638				opts = iL.options;
8639
8640			if (opts.fullAlone) {
8641				var currentHolder = vars.holder,
8642					current = iL.items[vars.current],
8643					windowWidth = viewport.width,
8644					windowHeight = viewport.height,
8645					elements = [currentHolder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.overlay, vars.toolbar, vars.thumbnails, vars.loader],
8646					hideElements = [vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails];
8647
8648				if (!vars.isInFullScreen) {
8649					vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = true;
8650					vars.overlay.css({
8651						opacity: 1
8652					});
8653
8654					$.each(hideElements, function(i, element) {
8655						element.hide();
8656					});
8657
8658					vars.fullScreenButton.attr('title', opts.text.exitFullscreen);
8659
8660					if (opts.fullStretchTypes.indexOf(current.type) != -1) currentHolder.data({
8661						naturalWidthOld: currentHolder.data('naturalWidth'),
8662						naturalHeightOld: currentHolder.data('naturalHeight'),
8663						naturalWidth: windowWidth,
8664						naturalHeight: windowHeight
8665					});
8666					else {
8667						var viewport = current.options.fullViewPort || opts.fullViewPort || '',
8668							newWidth = windowWidth,
8669							newHeight = windowHeight,
8670							width = currentHolder.data('naturalWidth'),
8671							height = currentHolder.data('naturalHeight');
8672
8673						if (viewport.toLowerCase() == 'fill') {
8674							newHeight = (newWidth / width) * height;
8675
8676							if (newHeight < windowHeight) {
8677								newWidth = (windowHeight / height) * width,
8678									newHeight = windowHeight;
8679							}
8680						} else if (viewport.toLowerCase() == 'fit') {
8681							var dims = iL.getNewDimenstions(newWidth, newHeight, width, height, true);
8682
8683							newWidth = dims.width,
8684								newHeight = dims.height;
8685						} else if (viewport.toLowerCase() == 'stretch') {
8686							newWidth = newWidth,
8687								newHeight = newHeight;
8688						} else {
8689							var scale = (width > newWidth || height > newHeight) ? true : false,
8690								dims = iL.getNewDimenstions(newWidth, newHeight, width, height, scale);
8691							newWidth = dims.width,
8692								newHeight = dims.height;
8693						}
8694
8695						currentHolder.data({
8696							naturalWidthOld: currentHolder.data('naturalWidth'),
8697							naturalHeightOld: currentHolder.data('naturalHeight'),
8698							naturalWidth: newWidth,
8699							naturalHeight: newHeight
8700						});
8701					}
8702
8703					$.each(elements, function(key, val) {
8704						val.addClass('ilightbox-fullscreen');
8705					});
8706
8707					//Trigger the onEnterFullScreen callback
8708					if (typeof opts.callback.onEnterFullScreen == 'function') opts.callback.onEnterFullScreen.call(iL, iL.ui);
8709				} else {
8710					vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = false;
8711					vars.overlay.css({
8712						opacity: iL.options.overlay.opacity
8713					});
8714
8715					$.each(hideElements, function(i, element) {
8716						element.show();
8717					});
8718
8719					vars.fullScreenButton.attr('title', opts.text.enterFullscreen);
8720
8721					currentHolder.data({
8722						naturalWidth: currentHolder.data('naturalWidthOld'),
8723						naturalHeight: currentHolder.data('naturalHeightOld'),
8724						naturalWidthOld: null,
8725						naturalHeightOld: null
8726					});
8727
8728					$.each(elements, function(key, val) {
8729						val.removeClass('ilightbox-fullscreen');
8730					});
8731
8732					//Trigger the onExitFullScreen callback
8733					if (typeof opts.callback.onExitFullScreen == 'function') opts.callback.onExitFullScreen.call(iL, iL.ui);
8734				}
8735			} else {
8736				if (!vars.isInFullScreen) vars.isInFullScreen = true;
8737				else vars.isInFullScreen = false;
8738			}
8739			iL.repositionPhoto(true);
8740		},
8741
8742		closeAction: function() {
8743			var iL = this,
8744				vars = iL.vars,
8745				opts = iL.options;
8746
8747			$win.unbind('.iLightBox');
8748			$doc.off('.iLightBox');
8749
8750			if (vars.isInFullScreen) fullScreenApi.cancelFullScreen(document.documentElement);
8751
8752			$('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails').off('.iLightBox');
8753
8754			if (opts.hide.effect) vars.overlay.stop().fadeOut(opts.hide.speed, function() {
8755				vars.overlay.remove();
8756				vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox');
8757			});
8758			else {
8759				vars.overlay.remove();
8760				vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox');
8761			}
8762
8763			var fadeOuts = [vars.toolbar, vars.holder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails];
8764
8765			$.each(fadeOuts, function(i, element) {
8766				element.removeAttr('style').remove();
8767			});
8768
8769			vars.dontGenerateThumbs = vars.isInFullScreen = false;
8770
8771			window.iLightBox = null;
8772
8773			if (opts.linkId) {
8774				vars.hashLock = true;
8775				removeHash();
8776				setTimeout(function() {
8777					vars.hashLock = false;
8778				}, 55);
8779			}
8780
8781			//Trigger the onHide callback
8782			if (typeof opts.callback.onHide == 'function') opts.callback.onHide.call(iL, iL.ui);
8783		},
8784
8785		repositionPhoto: function() {
8786			var iL = this,
8787				vars = iL.vars,
8788				opts = iL.options,
8789				path = opts.path.toLowerCase(),
8790				viewport = getViewport(),
8791				winWidth = viewport.width,
8792				winHeight = viewport.height;
8793
8794			if (viewport.width < UNCODE.mediaQuery) opts.styles.nextOffsetX = 0;
8795
8796			var thumbsOffsetW = (vars.isInFullScreen && opts.fullAlone || vars.isMobile) ? 0 : ((path == 'horizontal') ? 0 : vars.thumbnails.outerWidth()),
8797				thumbsOffsetH = vars.isMobile ? vars.toolbar.outerHeight() : ((vars.isInFullScreen && opts.fullAlone) ? 0 : ((path == 'horizontal') ? vars.thumbnails.outerHeight() : 0)),
8798				width = (vars.isInFullScreen && opts.fullAlone) ? winWidth : (winWidth - (opts.styles.pageOffsetX)),
8799				height = (vars.isInFullScreen && opts.fullAlone) ? winHeight : (winHeight - (opts.styles.pageOffsetY)),
8800				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,
8801				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)));
8802
8803			var elObject = {
8804				type: 'current',
8805				width: width,
8806				height: height,
8807				item: iL.items[vars.current],
8808				offsetW: offsetW,
8809				offsetH: offsetH,
8810				thumbsOffsetW: thumbsOffsetW,
8811				thumbsOffsetH: thumbsOffsetH,
8812				animate: arguments.length,
8813				holder: vars.holder
8814			};
8815
8816			iL.repositionEl(elObject);
8817			if (iL.items[vars.next]) {
8818				elObject = $.extend(elObject, {
8819					type: 'next',
8820					item: iL.items[vars.next],
8821					offsetX: (viewport.width > UNCODE.mediaQuery) ? opts.styles.nextOffsetX : 0,
8822					offsetY: opts.styles.nextOffsetY,
8823					holder: vars.nextPhoto
8824				});
8825
8826				iL.repositionEl(elObject);
8827			}
8828
8829			if (iL.items[vars.prev]) {
8830				elObject = $.extend(elObject, {
8831					type: 'prev',
8832					item: iL.items[vars.prev],
8833					offsetX: (viewport.width > UNCODE.mediaQuery) ? opts.styles.prevOffsetX : 0,
8834					offsetY: opts.styles.prevOffsetY,
8835					holder: vars.prevPhoto
8836				});
8837
8838				iL.repositionEl(elObject);
8839			}
8840
8841			var loaderCss = (path == "horizontal") ? {
8842				left: parseInt((width / 2) - (vars.loader.outerWidth() / 2))
8843			} : {
8844				top: parseInt((height / 2) - (vars.loader.outerHeight() / 2))
8845			};
8846			vars.loader.css(loaderCss);
8847		},
8848
8849		repositionEl: function(obj) {
8850			var iL = this,
8851				vars = iL.vars,
8852				opts = iL.options,
8853				path = opts.path.toLowerCase(),
8854				widthAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.width : (obj.width - obj.offsetW)) : (obj.width - obj.offsetW),
8855				heightAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.height : (obj.height - obj.offsetH)) : (obj.height - obj.offsetH),
8856				itemParent = obj.item,
8857				item = obj.item.options,
8858				holder = obj.holder,
8859				offsetX = obj.offsetX || 0,
8860				offsetY = obj.offsetY || 0,
8861				thumbsOffsetW = obj.thumbsOffsetW,
8862				thumbsOffsetH = obj.thumbsOffsetH;
8863
8864			if (obj.type == 'current') {
8865				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);
8866				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);
8867			} else {
8868				if (typeof item.width == 'number' && item.width) widthAvail = (item.width > widthAvail) ? widthAvail : item.width;
8869				if (typeof item.height == 'number' && item.height) heightAvail = (item.height > heightAvail) ? heightAvail : item.height;
8870			}
8871
8872			heightAvail = parseInt(heightAvail - $('.ilightbox-inner-toolbar', holder).outerHeight());
8873
8874			var width = (typeof item.width == 'string' && item.width.indexOf('%') != -1) ? percentToValue(parseInt(item.width.replace('%', '')), obj.width) : holder.data('naturalWidth'),
8875				height = (typeof item.height == 'string' && item.height.indexOf('%') != -1) ? percentToValue(parseInt(item.height.replace('%', '')), obj.height) : holder.data('naturalHeight');
8876
8877			var dims = ((typeof item.width == 'string' && item.width.indexOf('%') != -1 || typeof item.height == 'string' && item.height.indexOf('%') != -1) ? {
8878					width: width,
8879					height: height
8880				} : iL.getNewDimenstions(widthAvail, heightAvail, width, height)),
8881				newDims = $.extend({}, dims, {});
8882
8883			if (obj.type == 'prev' || obj.type == 'next')
8884				width = parseInt(dims.width * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)),
8885				height = parseInt(dims.height * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale));
8886			else
8887				width = dims.width,
8888				height = dims.height;
8889
8890			var widthDiff = parseInt((getPixel(holder, 'padding-left') + getPixel(holder, 'padding-right') + getPixel(holder, 'border-left-width') + getPixel(holder, 'border-right-width')) / 2),
8891				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);
8892
8893			if (obj.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) {
8894				var objRatio = width / height;
8895				height = height - vars.captionHeight;
8896				width = height * objRatio;
8897			}
8898
8899			switch (obj.type) {
8900				case 'current':
8901					var top = parseInt((obj.height / 2) - (height / 2) - heightDiff - (thumbsOffsetH / 2)),
8902						left = parseInt((obj.width / 2) - (width / 2) - widthDiff - (thumbsOffsetW / 2));
8903					break;
8904
8905				case 'next':
8906					var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(obj.height - offsetX - heightDiff - (thumbsOffsetH / 2)),
8907						left = (path == 'horizontal') ? parseInt(obj.width - offsetX - widthDiff - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - (width / 2) - widthDiff - offsetY - (thumbsOffsetW / 2));
8908					break;
8909
8910				case 'prev':
8911					var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(offsetX - heightDiff - height - (thumbsOffsetH / 2)),
8912						left = (path == 'horizontal') ? parseInt(offsetX - widthDiff - width - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - offsetY - (width / 2) - widthDiff - (thumbsOffsetW / 2));
8913					break;
8914			}
8915
8916			holder.data('offset', {
8917				top: top,
8918				left: left,
8919				newDims: newDims,
8920				diff: {
8921					W: widthDiff,
8922					H: heightDiff
8923				},
8924				thumbsOffset: {
8925					W: thumbsOffsetW,
8926					H: thumbsOffsetH
8927				},
8928				object: obj
8929			});
8930
8931			if (obj.animate > 0 && opts.effects.reposition) {
8932				holder.css(transform, gpuAcceleration).stop().animate({
8933					top: top,
8934					left: left
8935				}, opts.effects.repositionSpeed, 'easeOutCirc', function() {
8936					holder.css(transform, '');
8937				});
8938				$('div.ilightbox-container', holder).stop().animate({
8939					width: width,
8940					height: height
8941				}, opts.effects.repositionSpeed, 'easeOutCirc');
8942				$('div.ilightbox-inner-toolbar', holder).stop().animate({
8943					width: width
8944				}, opts.effects.repositionSpeed, 'easeOutCirc', function() {
8945					$(this).css('overflow', 'visible');
8946				});
8947			} else {
8948				holder.css({
8949					top: top,
8950					left: left
8951				});
8952				$('div.ilightbox-container', holder).css({
8953					width: width,
8954					height: height
8955				});
8956				$('div.ilightbox-inner-toolbar', holder).css({
8957					width: width
8958				});
8959			}
8960		},
8961
8962		resume: function(priority) {
8963			var iL = this,
8964				vars = iL.vars,
8965				opts = iL.options;
8966
8967			if (!opts.slideshow.pauseTime || opts.controls.slideshow && vars.total <= 1 || priority < vars.isPaused) {
8968				return;
8969			}
8970
8971			vars.isPaused = 0;
8972
8973			if (vars.cycleID) {
8974				vars.cycleID = clearTimeout(vars.cycleID);
8975			}
8976
8977			vars.cycleID = setTimeout(function() {
8978				if (vars.current == vars.total - 1) iL.goTo(0);
8979				else iL.moveTo('next');
8980			}, opts.slideshow.pauseTime);
8981		},
8982
8983		pause: function(priority) {
8984			var iL = this,
8985				vars = iL.vars,
8986				opts = iL.options;
8987
8988			if (priority < vars.isPaused) {
8989				return;
8990			}
8991
8992			vars.isPaused = priority || 100;
8993
8994			if (vars.cycleID) {
8995				vars.cycleID = clearTimeout(vars.cycleID);
8996			}
8997		},
8998
8999		resetCycle: function() {
9000			var iL = this,
9001				vars = iL.vars,
9002				opts = iL.options;
9003
9004			if (opts.controls.slideshow && vars.cycleID && !vars.isPaused) {
9005				iL.resume();
9006			}
9007		},
9008
9009		getNewDimenstions: function(width, height, width_old, height_old, thumb) {
9010			var iL = this;
9011
9012			if (!width) factor = height / height_old;
9013			else if (!height) factor = width / width_old;
9014			else factor = min(width / width_old, height / height_old);
9015
9016			if (!thumb) {
9017				if (factor > iL.options.maxScale) factor = iL.options.maxScale;
9018				else if (factor < iL.options.minScale) factor = iL.options.minScale;
9019			}
9020
9021			var final_width = (iL.options.keepAspectRatio) ? round(width_old * factor) : width,
9022				final_height = (iL.options.keepAspectRatio) ? round(height_old * factor) : height;
9023
9024			return {
9025				width: final_width,
9026				height: final_height,
9027				ratio: factor
9028			};
9029		},
9030
9031		setOption: function(options) {
9032			var iL = this;
9033
9034			iL.options = $.extend(true, iL.options, options || {});
9035			iL.refresh();
9036		},
9037
9038		availPlugins: function() {
9039			var iL = this,
9040				testEl = document.createElement("video");
9041
9042			iL.plugins = {
9043				flash: false,
9044				quicktime: (parseInt(PluginDetect.getVersion("QuickTime")) >= 0) ? true : false,
9045				html5H264: !!(testEl.canPlayType && testEl.canPlayType('video/mp4').replace(/no/, '')),
9046				html5WebM: !!(testEl.canPlayType && testEl.canPlayType('video/webm').replace(/no/, '')),
9047				html5Vorbis: !!(testEl.canPlayType && testEl.canPlayType('video/ogg').replace(/no/, '')),
9048				html5QuickTime: !!(testEl.canPlayType && testEl.canPlayType('video/quicktime').replace(/no/, ''))
9049			};
9050		},
9051
9052		addContent: function(element, obj) {
9053			var iL = this,
9054				el;
9055
9056			switch (obj.type) {
9057				case 'video':
9058					var HTML5 = false,
9059						videoType = obj.videoType,
9060						html5video = obj.options.html5video;
9061
9062					if (((videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v') || html5video.h264) && iL.plugins.html5H264)
9063						obj.ext = 'mp4',
9064						obj.URL = html5video.h264 || obj.URL;
9065					else if (html5video.webm && iL.plugins.html5WebM)
9066						obj.ext = 'webm',
9067						obj.URL = html5video.webm || obj.URL;
9068					else if (html5video.ogg && iL.plugins.html5Vorbis)
9069						obj.ext = 'ogv',
9070						obj.URL = html5video.ogg || obj.URL;
9071
9072					if (iL.plugins.html5H264 && (videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v')) HTML5 = true, videoType = "video/mp4";
9073					else if (iL.plugins.html5WebM && (videoType == 'video/webm' || obj.ext == 'webm')) HTML5 = true, videoType = "video/webm";
9074					else if (iL.plugins.html5Vorbis && (videoType == 'video/ogg' || obj.ext == 'ogv')) HTML5 = true, videoType = "video/ogg";
9075					else if (iL.plugins.html5QuickTime && (videoType == 'video/quicktime' || obj.ext == 'mov' || obj.ext == 'qt')) HTML5 = true, videoType = "video/quicktime";
9076
9077					if (HTML5) {
9078						el = $('<video />
9078', {
9079							"width": "100%",
9080							"height": "100%",
9081							"preload": html5video.preload,
9082							"autoplay": html5video.autoplay,
9083							"poster": html5video.poster,
9084							"controls": html5video.controls
9085						}).append($('<source />', {
9086							"src": obj.URL,
9087							"type": videoType
9088						}));
9089					} else {
9090						if (!iL.plugins.quicktime) el = $('<span />', {
9091							"class": "ilightbox-alert",
9092							html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.quicktime).replace('{type}', 'QuickTime')
9093						});
9094						else {
9095
9096							el = $('<object />', {
9097								"type": "video/quicktime",
9098								"pluginspage": pluginspages.quicktime
9099							}).attr({
9100								"data": obj.URL,
9101								"width": "100%",
9102								"height": "100%"
9103							}).append($('<param />', {
9104								"name": "src",
9105								"value": obj.URL
9106							})).append($('<param />', {
9107								"name": "autoplay",
9108								"value": "false"
9109							})).append($('<param />', {
9110								"name": "loop",
9111								"value": "false"
9112							})).append($('<param />', {
9113								"name": "scale",
9114								"value": "tofit"
9115							}));
9116
9117							if (browser.msie) el = QT_GenerateOBJECTText(obj.URL, '100%', '100%', '', 'SCALE', 'tofit', 'AUTOPLAY', 'false', 'LOOP', 'false');
9118						}
9119					}
9120
9121					break;
9122
9123				case 'flash':
9124					if (!iL.plugins.flash) el = $('<span />', {
9125						"class": "ilightbox-alert",
9126						html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.flash).replace('{type}', 'Adobe Flash player')
9127					});
9128					else {
9129						var flashvars = "",
9130							i = 0;
9131
9132						if (obj.options.flashvars) $.each(obj.options.flashvars, function(k, v) {
9133							if (i != 0) flashvars += "&";
9134							flashvars += k + "=" + encodeURIComponent(v);
9135							i++;
9136						});
9137						else flashvars = null;
9138
9139						el = $('<embed />').attr({
9140							"type": "application/x-shockwave-flash",
9141							"src": obj.URL,
9142							"width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%",
9143							"height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%",
9144							"quality": "high",
9145							"bgcolor": "#000000",
9146							"play": "true",
9147							"loop": "true",
9148							"menu": "true",
9149							"wmode": "transparent",
9150							"scale": "showall",
9151							"allowScriptAccess": "always",
9152							"allowFullScreen": "true",
9153							"flashvars": flashvars,
9154							"fullscreen": "yes"
9155						});
9156					}
9157
9158					break;
9159
9160				case 'iframe':
9161					el = $('<iframe />').attr({
9162						"width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%",
9163						"height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%",
9164						src: obj.URL,
9165						frameborder: 0,
9166						'hspace': 0,
9167						'vspace': 0,
9168						'scrolling': supportTouch ? 'auto' : 'scroll',
9169						'webkitAllowFullScreen': '',
9170						'mozallowfullscreen': '',
9171						'allowFullScreen': ''
9172					});
9173
9174					break;
9175
9176				case 'inline':
9177					el = $('<div class="ilightbox-wrapper"></div>').html($(obj.URL).clone(true));
9178
9179					break;
9180
9181				case 'html':
9182					var object = obj.URL,
9183						el;
9184
9185					if (object[0].nodeName) {
9186						el = $('<div class="ilightbox-wrapper"></div>').html(object);
9187					} else {
9188						var dom = $(obj.URL),
9189							html = (dom.selector) ? $('<div>' + dom + '</div>') : dom;
9190						el = $('<div class="ilightbox-wrapper"></div>').html(html);
9191					}
9192
9193					break;
9194			}
9195
9196			$('div.ilightbox-container', element).empty().html(el);
9197
9198			// For fixing Chrome about just playing the video for first time
9199			if (el[0].tagName.toLowerCase() === 'video' && browser.webkit) setTimeout(function() {
9200				var src = el[0].currentSrc + '?' + floor(random() * 30000);
9201				el[0].currentSrc = src;
9202				el[0].src = src;
9203			});
9204
9205			return el;
9206		},
9207
9208		ogpRecognition: function(obj, callback) {
9209			var iL = this,
9210				url = obj.URL;
9211
9212			iL.showLoader();
9213			doAjax(url, function(data) {
9214				iL.hideLoader();
9215
9216				if (data) {
9217					var object = new Object();
9218
9219					object.length = false,
9220					object.url = data.url;
9221
9222					if (data.status == 200) {
9223						var result = data.results,
9224							type = result.type,
9225							source = result.source;
9226
9227						object.source = source.src,
9228						object.width = source.width && parseInt(source.width) || 0,
9229						object.height = source.height && parseInt(source.height) || 0,
9230						object.type = type,
9231						object.thumbnail = source.thumbnail || result.images[0],
9232						object.html5video = result.html5video || {},
9233						object.length = true;
9234
9235						if (source.type == 'application/x-shockwave-flash') object.type = "flash";
9236						else if (source.type.indexOf("video/") != -1) object.type = "video";
9237						else if (source.type.indexOf("/html") != -1) object.type = "iframe";
9238						else if (source.type.indexOf("image/") != -1) object.type = "image";
9239
9240					} else if (typeof data.response != 'undefined')
9241						throw data.response;
9242
9243					callback.call(this, object.length ? object : false);
9244				}
9245			});
9246		},
9247
9248		hashChangeHandler: function(url) {
9249			var iL = this,
9250				vars = iL.vars,
9251				opts = iL.options,
9252				URL = url || window.location.href,
9253				hash = parseURI(URL).hash,
9254				split = hash.split('/'),
9255				index = split[1];
9256
9257			if (vars.hashLock || ('#' + opts.linkId != split[0] && hash.length > 1)) return;
9258
9259			if (index) {
9260				var target = split[1] || 0;
9261				if (iL.items[target]) {
9262					var overlay = $('.ilightbox-overlay');
9263					if (overlay.length && overlay.attr('linkid') == opts.linkId) {
9264						iL.goTo(target);
9265					} else {
9266						iL.itemsObject[target].trigger(supportTouch ? 'itap' : 'click');
9267					}
9268				} else {
9269					var overlay = $('.ilightbox-overlay');
9270					if (overlay.length) iL.closeAction();
9271				}
9272			} else {
9273				var overlay = $('.ilightbox-overlay');
9274				if (overlay.length) iL.closeAction();
9275			}
9276		}
9277	};
9278
9279	/**
9280	 * Parse style to pixels.
9281	 *
9282	 * @param {Object}   $element   jQuery object with element.
9283	 * @param {Property} property   CSS property to get the pixels from.
9284	 *
9285	 * @return {Int}
9286	 */
9287	function getPixel($element, property) {
9288		return parseInt($element.css(property), 10) || 0;
9289	}
9290
9291	/**
9292	 * Make sure that number is within the limits.
9293	 *
9294	 * @param {Number} number
9295	 * @param {Number} min
9296	 * @param {Number} max
9297	 *
9298	 * @return {Number}
9299	 */
9300	function within(number, min, max) {
9301		return number < min ? min : number > max ? max : number;
9302	}
9303
9304	/**
9305	 * Get viewport/window size (width and height).
9306	 *
9307	 * @return {Object}
9308	 */
9309	function getViewport() {
9310		var e = window,
9311			a = 'inner';
9312		if (!('innerWidth' in window)) {
9313			a = 'client';
9314			e = document.documentElement || document.body;
9315		}
9316		return {
9317			width: e[a + 'Width'],
9318			height: e[a + 'Height']
9319		}
9320	}
9321
9322	/**
9323	 * Remove hash tag from the URL
9324	 *
9325	 * @return {Void}
9326	 */
9327	function removeHash() {
9328		var scroll = getScrollXY();
9329
9330		window.location.hash = "";
9331
9332		// Restore the scroll offset, should be flicker free
9333		window.scrollTo(scroll.x, scroll.y);
9334	}
9335
9336	/**
9337	 * Do the ajax requests with callback.
9338	 *
9339	 * @param {String}   url
9340	 * @param {Function} callback
9341	 *
9342	 * @return {Void}
9343	 */
9344	function doAjax(url, callback) {
9345		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');
9346		$.ajax({
9347			url: url,
9348			dataType: 'jsonp'
9349		});
9350
9351		iLCallback = function(data) {
9352			callback.call(this, data);
9353		};
9354	}
9355
9356	/**
9357	 * Find image from DOM elements
9358	 *
9359	 * @param {Element} element
9360	 *
9361	 * @return {Void}
9362	 */
9363	function findImageInElement(element) {
9364		var elements = $('*', element),
9365			imagesArr = new Array();
9366
9367		elements.each(function() {
9368			var url = "",
9369				element = this;
9370
9371			if ($(element).css("background-image") != "none") {
9372				url = $(element).css("background-image");
9373			} else if (typeof($(element).attr("src")) != "undefined" && element.nodeName.toLowerCase() == "img") {
9374				url = $(element).attr("src");
9375			}
9376
9377			if (url.indexOf("gradient") == -1) {
9378				url = url.replace(/url\(\"/g, "");
9379				url = url.replace(/url\(/g, "");
9380				url = url.replace(/\"\)/g, "");
9381				url = url.replace(/\)/g, "");
9382
9383				var urls = url.split(",");
9384
9385				for (var i = 0; i < urls.length; i++) {
9386					if (urls[i].length > 0 && $.inArray(urls[i], imagesArr) == -1) {
9387						var extra = "";
9388						if (browser.msie && browser.version < 9) {
9389							extra = "?" + floor(random() * 3000);
9390						}
9391						imagesArr.push(urls[i] + extra);
9392					}
9393				}
9394			}
9395		});
9396
9397		return imagesArr;
9398	}
9399
9400	/**
9401	 * Get file extension.
9402	 *
9403	 * @param {String} URL
9404	 *
9405	 * @return {String}
9406	 */
9407	function getExtension(URL) {
9408		if (URL !== null) {
9409			var ext = URL.split('.').pop().toLowerCase(),
9410				extra = ext.indexOf('?') !== -1 ? ext.split('?').pop() : '';
9411
9412			return ext.replace(extra, '');
9413		}
9414	}
9415
9416	/**
9417	 * Get type via extension.
9418	 *
9419	 * @param {String} URL
9420	 *
9421	 * @return {String}
9422	 */
9423	function getTypeByExtension(URL) {
9424		var type,
9425			ext = getExtension(URL);
9426
9427		if (extensions.image.indexOf(ext) !== -1) type = 'image';
9428		else if (extensions.flash.indexOf(ext) !== -1) type = 'flash';
9429		else if (extensions.video.indexOf(ext) !== -1) type = 'video';
9430		else type = 'iframe';
9431
9432		return type;
9433	}
9434
9435	/**
9436	 * Return value from percent of a number.
9437	 *
9438	 * @param {Number} percent
9439	 * @param {Number} total
9440	 *
9441	 * @return {Number}
9442	 */
9443	function percentToValue(percent, total) {
9444		return parseInt((total / 100) * percent);
9445	}
9446
9447	/**
9448	 * A JavaScript equivalent of PHP’s parse_url.
9449	 *
9450	 * @param {String} url           The URL to parse.
9451	 *
9452	 * @return {Mixed}
9453	 */
9454	function parseURI(url) {
9455		var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/);
9456		// authority = '//' + user + ':' + pass '@' + hostname + ':' port
9457		return (m ? {
9458			href: m[0] || '',
9459			protocol: m[1] || '',
9460			authority: m[2] || '',
9461			host: m[3] || '',
9462			hostname: m[4] || '',
9463			port: m[5] || '',
9464			pathname: m[6] || '',
9465			search: m[7] || '',
9466			hash: m[8] || ''
9467		} : null);
9468	}
9469
9470	/**
9471	 * Gets the absolute URI.
9472	 *
9473	 * @param {String} href     The relative URL.
9474	 * @param {String} base     The base URL.
9475	 *
9476	 * @return {String}         The absolute URL.
9477	 */
9478	function absolutizeURI(base, href) { // RFC 3986
9479		var iL = this;
9480
9481		function removeDotSegments(input) {
9482			var output = [];
9483			input.replace(/^(\.\.?(\/|$))+/, '')
9484				.replace(/\/(\.(\/|$))+/g, '/')
9485				.replace(/\/\.\.$/, '/../')
9486				.replace(/\/?[^\/]*/g, function(p) {
9487					if (p === '/..') {
9488						output.pop();
9489					} else {
9490						output.push(p);
9491					}
9492				});
9493			return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : '');
9494		}
9495
9496		href = parseURI(href || '');
9497		base = parseURI(base || '');
9498
9499		return !href || !base ? null : (href.protocol || base.protocol) +
9500			(href.protocol || href.authority ? href.authority : base.authority) +
9501			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)) +
9502			(href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) +
9503			href.hash;
9504	}
9505
9506	/**
9507	 * A JavaScript equivalent of PHP’s version_compare.
9508	 *
9509	 * @param {String} v1
9510	 * @param {String} v2
9511	 * @param {String} operator
9512	 *
9513	 * @return {Boolean}
9514	 */
9515	function version_compare(v1, v2, operator) {
9516		this.php_js = this.php_js || {};
9517		this.php_js.ENV = this.php_js.ENV || {};
9518		var i = 0,
9519			x = 0,
9520			compare = 0,
9521			vm = {
9522				'dev': -6,
9523				'alpha': -5,
9524				'a': -5,
9525				'beta': -4,
9526				'b': -4,
9527				'RC': -3,
9528				'rc': -3,
9529				'#': -2,
9530				'p': 1,
9531				'pl': 1
9532			},
9533			prepVersion = function(v) {
9534				v = ('' + v).replace(/[_\-+]/g, '.');
9535				v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.');
9536				return (!v.length ? [-8] : v.split('.'));
9537			},
9538			numVersion = function(v) {
9539				return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10));
9540			};
9541		v1 = prepVersion(v1);
9542		v2 = prepVersion(v2);
9543		x = max(v1.length, v2.length);
9544		for (i = 0; i < x; i++) {
9545			if (v1[i] == v2[i]) {
9546				continue;
9547			}
9548			v1[i] = numVersion(v1[i]);
9549			v2[i] = numVersion(v2[i]);
9550			if (v1[i] < v2[i]) {
9551				compare = -1;
9552				break;
9553			} else if (v1[i] > v2[i]) {
9554				compare = 1;
9555				break;
9556			}
9557		}
9558		if (!operator) {
9559			return compare;
9560		}
9561
9562		switch (operator) {
9563			case '>':
9564			case 'gt':
9565				return (compare > 0);
9566			case '>=':
9567			case 'ge':
9568				return (compare >= 0);
9569			case '<=':
9570			case 'le':
9571				return (compare <= 0);
9572			case '==':
9573			case '=':
9574			case 'eq':
9575				return (compare === 0);
9576			case '<>':
9577			case '!=':
9578			case 'ne':
9579				return (compare !== 0);
9580			case '':
9581			case '<':
9582			case 'lt':
9583				return (compare < 0);
9584			default:
9585				return null;
9586		}
9587	}
9588
9589
9590	// Begin the iLightBox plugin
9591	$.fn.iLightBox = function() {
9592
9593		var args = arguments,
9594			opt = ($.isPlainObject(args[0])) ? args[0] : args[1],
9595			items = ($.isArray(args[0]) || typeof args[0] == 'string') ? args[0] : args[1];
9596
9597		if (!opt) opt = {};
9598
9599		// Default options. Play carefully.
9600		var options = $.extend(true, {
9601			attr: 'href',
9602			path: 'vertical',
9603			skin: 'dark',
9604			linkId: false,
9605			infinite: false,
9606			startFrom: 0,
9607			randomStart: false,
9608			keepAspectRatio: true,
9609			maxScale: 1,
9610			minScale: .2,
9611			innerToolbar: false,
9612			smartRecognition: false,
9613			mobileOptimizer: true,
9614			fullAlone: true,
9615			fullViewPort: null,
9616			fullStretchTypes: 'flash, video',
9617			overlay: {
9618				blur: true,
9619				opacity: .85
9620			},
9621			controls: {
9622				arrows: false,
9623				slideshow: false,
9624				toolbar: true,
9625				fullscreen: true,
9626				thumbnail: true,
9627				keyboard: true,
9628				mousewheel: true,
9629				swipe: true
9630			},
9631			keyboard: {
9632				left: true, // previous
9633				right: true, // next
9634				up: true, // previous
9635				down: true, // next
9636				esc: true, // close
9637				shift_enter: true // fullscreen
9638			},
9639			show: {
9640				effect: true,
9641				speed: 300,
9642				title: true
9643			},
9644			hide: {
9645				effect: true,
9646				speed: 300
9647			},
9648			caption: {
9649				start: true,
9650				show: 'mouseenter',
9651				hide: 'mouseleave'
9652			},
9653			social: {
9654				start: true,
9655				show: 'mouseenter',
9656				hide: 'mouseleave',
9657				buttons: false
9658			},
9659			styles: {
9660				pageOffsetX: 0,
9661				pageOffsetY: 0,
9662				nextOffsetX: 45,
9663				nextOffsetY: 0,
9664				nextOpacity: 1,
9665				nextScale: 1,
9666				prevOffsetX: 45,
9667				prevOffsetY: 0,
9668				prevOpacity: 1,
9669				prevScale: 1
9670			},
9671			thumbnails: {
9672				maxWidth: 120,
9673				maxHeight: 80,
9674				normalOpacity: 1,
9675				activeOpacity: .6
9676			},
9677			effects: {
9678				reposition: true,
9679				repositionSpeed: 200,
9680				switchSpeed: 500,
9681				loadedFadeSpeed: 180,
9682				fadeSpeed: 200
9683			},
9684			slideshow: {
9685				pauseTime: 5000,
9686				pauseOnHover: false,
9687				startPaused: true
9688			},
9689			text: {
9690				close: "Press Esc to close",
9691				enterFullscreen: "Enter Fullscreen (Shift+Enter)",
9692				exitFullscreen: "Exit Fullscreen (Shift+Enter)",
9693				slideShow: "Slideshow",
9694				next: "Next",
9695				previous: "Previous"
9696			},
9697			errors: {
9698				loadImage: "An error occurred when trying to load photo.",
9699				loadContents: "An error occurred when trying to load contents.",
9700				missingPlugin: "The content your are attempting to view requires the <a href='{pluginspage}' target='_blank'>{type} plugin<\/a>."
9701			},
9702			ajaxSetup: {
9703				url: '',
9704				beforeSend: function(jqXHR, settings) {},
9705				cache: false,
9706				complete: function(jqXHR, textStatus) {},
9707				crossDomain: false,
9708				error: function(jqXHR, textStatus, errorThrown) {},
9709				success: function(data, textStatus, jqXHR) {},
9710				global: true,
9711				ifModified: false,
9712				username: null,
9713				password: null,
9714				type: 'GET'
9715			},
9716			callback: {}
9717		}, opt);
9718
9719		var instant = ($.isArray(items) || typeof items == 'string') ? true : false;
9720
9721		items = $.isArray(items) ? items : new Array();
9722
9723		if (typeof args[0] == 'string') items[0] = args[0];
9724
9725		if (version_compare($.fn.jquery, '1.8', '>=')) {
9726			var iLB = new iLightBox($(this), options, items, instant);
9727			return {
9728				close: function() {
9729					iLB.closeAction();
9730				},
9731				fullscreen: function() {
9732					iLB.fullScreenAction();
9733				},
9734				moveNext: function() {
9735					iLB.moveTo('next');
9736				},
9737				movePrev: function() {
9738					iLB.moveTo('prev');
9739				},
9740				goTo: function(index) {
9741					iLB.goTo(index);
9742				},
9743				refresh: function() {
9744					iLB.refresh();
9745				},
9746				reposition: function() {
9747					(arguments.length > 0) ? iLB.repositionPhoto(true): iLB.repositionPhoto();
9748				},
9749				setOption: function(options) {
9750					iLB.setOption(options);
9751				},
9752				destroy: function() {
9753					iLB.closeAction();
9754					iLB.dispatchItemsEvents();
9755				}
9756			};
9757		} else {
9758			throw "The jQuery version that was loaded is too old. iLightBox requires jQuery 1.8+";
9759		}
9760
9761	};
9762
9763
9764	$.iLightBox = function() {
9765		return $.fn.iLightBox(arguments[0], arguments[1]);
9766	};
9767
9768
9769	$.extend($.easing, {
9770		easeInCirc: function(x, t, b, c, d) {
9771			return -c * (sqrt(1 - (t /= d) * t) - 1) + b;
9772		},
9773		easeOutCirc: function(x, t, b, c, d) {
9774			return c * sqrt(1 - (t = t / d - 1) * t) + b;
9775		},
9776		easeInOutCirc: function(x, t, b, c, d) {
9777			if ((t /= d / 2) < 1) return -c / 2 * (sqrt(1 - t * t) - 1) + b;
9778			return c / 2 * (sqrt(1 - (t -= 2) * t) + 1) + b;
9779		}
9780	});
9781
9782	function getScrollXY() {
9783		var scrOfX = 0,
9784			scrOfY = 0;
9785		if (typeof(window.pageYOffset) == 'number') {
9786			//Netscape compliant
9787			scrOfY = window.pageYOffset;
9788			scrOfX = window.pageXOffset;
9789		} else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
9790			//DOM compliant
9791			scrOfY = document.body.scrollTop;
9792			scrOfX = document.body.scrollLeft;
9793		} else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
9794			//IE6 standards compliant mode
9795			scrOfY = document.documentElement.scrollTop;
9796			scrOfX = document.documentElement.scrollLeft;
9797		}
9798		return {
9799			x: scrOfX,
9800			y: scrOfY
9801		};
9802	}
9803
9804	(function() {
9805		// add new event shortcuts
9806		$.each(("touchstart touchmove touchend " +
9807			"tap taphold " +
9808			"swipe swipeleft swiperight " +
9809			"scrollstart scrollstop").split(" "), function(i, name) {
9810
9811			$.fn[name] = function(fn) {
9812				return fn ? this.bind(name, fn) : this.trigger(name);
9813			};
9814
9815			// jQuery < 1.8
9816			// if ($.attrFn) {
9817			// 	$.attrFn[name] = true;
9818			// }
9819		});
9820
9821		var tapSettings = {
9822			startEvent: 'touchstart.iTap',
9823			endEvent: 'touchend.iTap'
9824		};
9825
9826		// tap Event:
9827		$.event.special.itap = {
9828			setup: function() {
9829
9830				var self = this,
9831					$self = $(this),
9832					start, stop;
9833
9834				$self.bind(tapSettings.startEvent, function(event) {
9835					start = getScrollXY();
9836
9837					$self.one(tapSettings.endEvent, function(event) {
9838						stop = getScrollXY();
9839
9840						var orgEvent = event || window.event;
9841						event = $.event.fix(orgEvent);
9842						event.type = "itap";
9843
9844						if ((start && stop) && (start.x == stop.x && start.y == stop.y))($.event.dispatch || $.event.handle).call(self, event);
9845
9846						start = stop = undefined;
9847					});
9848				});
9849			},
9850
9851			teardown: function() {
9852				$(this).unbind(tapSettings.startEvent);
9853			}
9854		};
9855	}());
9856
9857
9858	//Fullscreen API
9859	(function() {
9860		fullScreenApi = {
9861				supportsFullScreen: false,
9862				isFullScreen: function() {
9863					return false;
9864				},
9865				requestFullScreen: function() {},
9866				cancelFullScreen: function() {},
9867				fullScreenEventName: '',
9868				prefix: ''
9869			},
9870			browserPrefixes = 'webkit moz o ms khtml'.split(' ');
9871
9872		// check for native support
9873		if (typeof document.cancelFullScreen != 'undefined') {
9874			fullScreenApi.supportsFullScreen = true;
9875		} else {
9876			// check for fullscreen support by vendor prefix
9877			for (var i = 0, il = browserPrefixes.length; i < il; i++) {
9878				fullScreenApi.prefix = browserPrefixes[i];
9879
9880				if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') {
9881					fullScreenApi.supportsFullScreen = true;
9882
9883					break;
9884				}
9885			}
9886		}
9887
9888		// update methods to do something useful
9889		if (fullScreenApi.supportsFullScreen) {
9890			fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange';
9891
9892			fullScreenApi.isFullScreen = function() {
9893				switch (this.prefix) {
9894					case '':
9895						return document.fullScreen;
9896					case 'webkit':
9897						return document.webkitIsFullScreen;
9898					default:
9899						return document[this.prefix + 'FullScreen'];
9900				}
9901			}
9902			fullScreenApi.requestFullScreen = function(el) {
9903				return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen']();
9904			}
9905			fullScreenApi.cancelFullScreen = function(el) {
9906				return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen']();
9907			}
9908		}
9909	}());
9910
9911	// Browser detect
9912	(function() {
9913		function uaMatch(ua) {
9914			ua = ua.toLowerCase();
9915
9916			var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
9917				/(webkit)[ \/]([\w.]+)/.exec(ua) ||
9918				/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
9919				/(msie) ([\w.]+)/.exec(ua) ||
9920				ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || [];
9921
9922			return {
9923				browser: match[1] || "",
9924				version: match[2] || "0"
9925			};
9926		}
9927
9928		var matched = uaMatch(navigator.userAgent);
9929		browser = {};
9930
9931		if (matched.browser) {
9932			browser[matched.browser] = true;
9933			browser.version = matched.version;
9934		}
9935
9936		// Chrome is Webkit, but Webkit is also Safari.
9937		if (browser.chrome) {
9938			browser.webkit = true;
9939		} else if (browser.webkit) {
9940			browser.safari = true;
9941		}
9942	}());
9943
9944	// Feature detects
9945	(function() {
9946		var prefixes = ['', 'webkit', 'moz', 'ms', 'o'];
9947		var el = document.createElement('div');
9948
9949		function testProp(prop) {
9950			for (var p = 0, pl = prefixes.length; p < pl; p++) {
9951				var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop;
9952				if (el.style[prefixedProp] !== undefined) {
9953					return prefixedProp;
9954				}
9955			}
9956		}
9957
9958		// Global support indicators
9959		transform = testProp('transform') || '';
9960		gpuAcceleration = testProp('perspective') ? 'translateZ(0) ' : '';
9961	}());
9962
9963
9964	/*
9965		PluginDetect v0.7.9
9966		www.pinlady.net/PluginDetect/license/
9967		[ getVersion onWindowLoaded BetterIE ]
9968		[ Flash QuickTime Shockwave ]
9969	*/
9970	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;
9970d++){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);
9970d.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)}
9970c.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;
9970if(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();
9971
9972	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)};
9973
9974
9975	/*
9976		jQuery hashchange event v1.3
9977		https://github.com/cowboy/jquery-hashchange
9978		Copyright (c) 2010 "Cowboy" Ben Alman
9979		Dual licensed under the MIT and GPL licenses.
9980	*/
9981	(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=
9982	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||
9983	"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;
9983a!==d&&(b.title=k.title,b.open(),e&&b.write('<script>document.domain="'+e+'"\x3c/script>'),b.close(),c.location.hash=a)}}();return h}()})();
9984
9985	if (!Array.prototype.filter) {
9986		Array.prototype.filter = function(fun /*, thisp */ ) {
9987			"use strict";
9988
9989			if (this == null)
9990				throw new TypeError();
9991
9992			var t = Object(this);
9993			var len = t.length >>> 0;
9994			if (typeof fun != "function")
9995				throw new TypeError();
9996
9997			var res = [];
9998			var thisp = arguments[1];
9999			for (var i = 0; i < len; i++) {
10000				if (i in t) {
10001					var val = t[i]; // in case fun mutates this
10002					if (fun.call(thisp, val, i, t))
10003						res.push(val);
10004				}
10005			}
10006
10007			return res;
10008		};
10009	}
10010
10011	if (!Array.prototype.indexOf) {
10012		Array.prototype.indexOf = function(searchElement, fromIndex) {
10013			var k;
10014
10015			if (this == null) {
10016				throw new TypeError('"this" is null or not defined');
10017			}
10018
10019			var O = Object(this);
10020
10021			var len = O.length >>> 0;
10022
10023			if (len === 0) {
10024				return -1;
10025			}
10026
10027			var n = +fromIndex || 0;
10028
10029			if (abs(n) === Infinity) {
10030				n = 0;
10031			}
10032
10033			if (n >= len) {
10034				return -1;
10035			}
10036
10037			k = max(n >= 0 ? n : len - abs(n), 0);
10038
10039			while (k < len) {
10040				var kValue;
10041				if (k in O && O[k] === searchElement) {
10042					return k;
10043				}
10044				k++;
10045			}
10046			return -1;
10047		};
10048	}
10049
10050	if (!Array.prototype.lastIndexOf) {
10051		Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/ ) {
10052			"use strict";
10053
10054			if (this == null)
10055				throw new TypeError();
10056
10057			var t = Object(this);
10058			var len = t.length >>> 0;
10059			if (len === 0)
10060				return -1;
10061
10062			var n = len;
10063			if (arguments.length > 1) {
10064				n = Number(arguments[1]);
10065				if (n != n)
10066					n = 0;
10067				else if (n != 0 && n != (1 / 0) && n != -(1 / 0))
10068					n = (n > 0 || -1) * floor(abs(n));
10069			}
10070
10071			var k = n >= 0 ? min(n, len - 1) : len - abs(n);
10072
10073			for (; k >= 0; k--) {
10074				if (k in t && t[k] === searchElement)
10075					return k;
10076			}
10077			return -1;
10078		};
10079	}
10080})(jQuery, this);
10081
10082
10083/**
10084 * Owl carousel
vendor: 25,822 bytes, lines 10085-11109
10085 * @version 2.0.0-beta.3
10086 * @author Bartosz Wojciechowski
10087 * @license The MIT License (MIT)
10088 * @todo Lazy Load Icon
10089 * @todo prevent animationend bubling
10090 * @todo itemsScaleUp
10091 * @todo Test Zepto
10092 * @todo stagePadding calculate wrong active classes
10093 */
10094;(function($, window, document, undefined) {
10095
10096	/**
10097	 * Creates a carousel.
10098	 * @class The Owl Carousel.
10099	 * @public
10100	 * @param {HTMLElement|jQuery} element - The element to create the carousel for.
10101	 * @param {Object} [options] - The options
10102	 */
10103	function Owl(element, options) {
10104
10105		/**
10106		 * Current settings for the carousel.
10107		 * @public
10108		 */
10109		this.settings = null;
10110
10111		/**
10112		 * Current options set by the caller including defaults.
10113		 * @public
10114		 */
10115		this.options = $.extend({}, Owl.Defaults, options);
10116
10117		/**
10118		 * Plugin element.
10119		 * @public
10120		 */
10121		this.$element = $(element);
10122
10123		/**
10124		 * Proxied event handlers.
10125		 * @protected
10126		 */
10127		this._handlers = {};
10128
10129		/**
10130		 * References to the running plugins of this carousel.
10131		 * @protected
10132		 */
10133		this._plugins = {};
10134
10135		/**
10136		 * Currently suppressed events to prevent them from beeing retriggered.
10137		 * @protected
10138		 */
10139		this._supress = {};
10140
10141		/**
10142		 * Absolute current position.
10143		 * @protected
10144		 */
10145		this._current = null;
10146
10147		/**
10148		 * Animation speed in milliseconds.
10149		 * @protected
10150		 */
10151		this._speed = null;
10152
10153		/**
10154		 * Coordinates of all items in pixel.
10155		 * @todo The name of this member is missleading.
10156		 * @protected
10157		 */
10158		this._coordinates = [];
10159
10160		/**
10161		 * Current breakpoint.
10162		 * @todo Real media queries would be nice.
10163		 * @protected
10164		 */
10165		this._breakpoint = null;
10166
10167		/**
10168		 * Current width of the plugin element.
10169		 */
10170		this._width = null;
10171
10172		/**
10173		 * All real items.
10174		 * @protected
10175		 */
10176		this._items = [];
10177
10178		/**
10179		 * All cloned items.
10180		 * @protected
10181		 */
10182		this._clones = [];
10183
10184		/**
10185		 * Merge values of all items.
10186		 * @todo Maybe this could be part of a plugin.
10187		 * @protected
10188		 */
10189		this._mergers = [];
10190
10191		/**
10192		 * Widths of all items.
10193		 */
10194		this._widths = [];
10195
10196		/**
10197		 * Invalidated parts within the update process.
10198		 * @protected
10199		 */
10200		this._invalidated = {};
10201
10202		/**
10203		 * Ordered list of workers for the update process.
10204		 * @protected
10205		 */
10206		this._pipe = [];
10207
10208		/**
10209		 * Current state information for the drag operation.
10210		 * @todo #261
10211		 * @protected
10212		 */
10213		this._drag = {
10214			time: null,
10215			target: null,
10216			pointer: null,
10217			stage: {
10218				start: null,
10219				current: null
10220			},
10221			direction: null
10222		};
10223
10224		/**
10225		 * Current state information and their tags.
10226		 * @type {Object}
10227		 * @protected
10228		 */
10229		this._states = {
10230			current: {},
10231			tags: {
10232				'initializing': [ 'busy' ],
10233				'animating': [ 'busy' ],
10234				'dragging': [ 'interacting' ]
10235			}
10236		};
10237
10238		$.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) {
10239			this._handlers[handler] = $.proxy(this[handler], this);
10240		}, this));
10241
10242		$.each(Owl.Plugins, $.proxy(function(key, plugin) {
10243			this._plugins[key.charAt(0).toLowerCase() + key.slice(1)]
10244				= new plugin(this);
10245		}, this));
10246
10247		$.each(Owl.Workers, $.proxy(function(priority, worker) {
10248			this._pipe.push({
10249				'filter': worker.filter,
10250				'run': $.proxy(worker.run, this)
10251			});
10252		}, this));
10253
10254		this.setup();
10255		this.initialize();
10256	}
10257
10258	/**
10259	 * Default options for the carousel.
10260	 * @public
10261	 */
10262	Owl.Defaults = {
10263		items: 3,
10264		loop: false,
10265		center: false,
10266		rewind: false,
10267
10268		mouseDrag: true,
10269		touchDrag: true,
10270		pullDrag: true,
10271		freeDrag: false,
10272
10273		margin: 0,
10274		stagePadding: 0,
10275
10276		merge: false,
10277		mergeFit: true,
10278		autoWidth: false,
10279
10280		startPosition: 0,
10281		rtl: false,
10282
10283		smartSpeed: 250,
10284		fluidSpeed: false,
10285		dragEndSpeed: false,
10286
10287		responsive: {},
10288		responsiveRefreshRate: 200,
10289		responsiveBaseElement: window,
10290
10291		fallbackEasing: 'swing',
10292
10293		info: false,
10294
10295		nestedItemSelector: false,
10296		itemElement: 'div',
10297		stageElement: 'div',
10298
10299		refreshClass: 'owl-refresh',
10300		loadedClass: 'owl-loaded',
10301		loadingClass: 'owl-loading',
10302		rtlClass: 'owl-rtl',
10303		responsiveClass: 'owl-responsive',
10304		dragClass: 'owl-drag',
10305		itemClass: 'owl-item',
10306		stageClass: 'owl-stage',
10307		stageOuterClass: 'owl-stage-outer',
10308		grabClass: 'owl-grab'
10309	};
10310
10311	/**
10312	 * Enumeration for width.
10313	 * @public
10314	 * @readonly
10315	 * @enum {String}
10316	 */
10317	Owl.Width = {
10318		Default: 'default',
10319		Inner: 'inner',
10320		Outer: 'outer'
10321	};
10322
10323	/**
10324	 * Enumeration for types.
10325	 * @public
10326	 * @readonly
10327	 * @enum {String}
10328	 */
10329	Owl.Type = {
10330		Event: 'event',
10331		State: 'state'
10332	};
10333
10334	/**
10335	 * Contains all registered plugins.
10336	 * @public
10337	 */
10338	Owl.Plugins = {};
10339
10340	/**
10341	 * List of workers involved in the update process.
10342	 */
10343	Owl.Workers = [ {
10344		filter: [ 'width', 'settings' ],
10345		run: function() {
10346			this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width();
10347			//this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12);
10348		}
10349	}, {
10350		filter: [ 'width', 'items', 'settings' ],
10351		run: function(cache) {
10352			cache.current = this._items && this._items[this.relative(this._current)];
10353		}
10354	}, {
10355		filter: [ 'items', 'settings' ],
10356		run: function() {
10357			this.$stage.children('.cloned').remove();
10358		}
10359	}, {
10360		filter: [ 'width', 'items', 'settings' ],
10361		run: function(cache) {
10362			var margin = this.settings.margin || '',
10363				grid = !this.settings.autoWidth,
10364				rtl = this.settings.rtl,
10365				css = {
10366					'width': 'auto',
10367					'margin-left': rtl ? margin : '',
10368					'margin-right': rtl ? '' : margin
10369				};
10370
10371			!grid && this.$stage.children().css(css);
10372
10373			cache.css = css;
10374		}
10375	}, {
10376		filter: [ 'width', 'items', 'settings' ],
10377		run: function(cache) {
10378			var width = (this.width() / this.settings.items).toFixed(3) - this.settings.margin,
10379				merge = null,
10380				iterator = this._items.length,
10381				grid = !this.settings.autoWidth,
10382				widths = [];
10383
10384			cache.items = {
10385				merge: false,
10386				width: width
10387			};
10388
10389			while (iterator--) {
10390				merge = this._mergers[iterator];
10391				merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge;
10392
10393				cache.items.merge = merge > 1 || cache.items.merge;
10394
10395				widths[iterator] = !grid ? this._items[iterator].width() : width * merge;
10396			}
10397
10398			this._widths = widths;
10399		}
10400	}, {
10401		filter: [ 'items', 'settings' ],
10402		run: function() {
10403			var clones = [],
10404				items = this._items,
10405				settings = this.settings,
10406				view = Math.max(settings.items * 2, 4),
10407				size = Math.ceil(items.length / 2) * 2,
10408				repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0,
10409				append = '',
10410				prepend = '';
10411
10412			repeat /= 2;
10413
10414			while (repeat--) {
10415				clones.push(this.normalize(clones.length / 2, true));
10416				append = append + items[clones[clones.length - 1]][0].outerHTML;
10417				clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true));
10418				prepend = items[clones[clones.length - 1]][0].outerHTML + prepend;
10419			}
10420
10421			this._clones = clones;
10422
10423			// var appendVideo = $(append).find('.uncode-video-container');
10424			// if (appendVideo.length) {
10425			// 	appendVideo.attr('data-id', Math.round(Math.random() * 100000));
10426			// }
10427			// var prependVideo = $(prepend).find('.uncode-video-container');
10428			// if (prependVideo.length) {
10429			// 	prependVideo.attr('data-id', Math.round(Math.random() * 100000));
10430			// }
10431			$(append).addClass('cloned').appendTo(this.$stage);
10432			$(prepend).addClass('cloned').prependTo(this.$stage);
10433		}
10434	}, {
10435		filter: [ 'width', 'items', 'settings' ],
10436		run: function() {
10437			var rtl = this.settings.rtl ? 1 : -1,
10438				size = this._clones.length + this._items.length,
10439				iterator = -1,
10440				previous = 0,
10441				current = 0,
10442				coordinates = [];
10443
10444			while (++iterator < size) {
10445				previous = coordinates[iterator - 1] || 0;
10446				current = this._widths[this.relative(iterator)] + this.settings.margin;
10447				coordinates.push(previous + current * rtl);
10448			}
10449
10450			this._coordinates = coordinates;
10451		}
10452	}, {
10453		filter: [ 'width', 'items', 'settings' ],
10454		run: function() {
10455			var padding = this.settings.stagePadding,
10456				coordinates = this._coordinates,
10457				css = {
10458					'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2,
10459					'padding-left': padding || '',
10460					'padding-right': padding || ''
10461				};
10462
10463			this.$stage.css(css);
10464		}
10465	}, {
10466		filter: [ 'width', 'items', 'settings' ],
10467		run: function(cache) {
10468			var iterator = this._coordinates.length,
10469				grid = !this.settings.autoWidth,
10470				items = this.$stage.children();
10471
10472			if (grid && cache.items.merge) {
10473				while (iterator--) {
10474					cache.css.width = this._widths[this.relative(iterator)];
10475					items.eq(iterator).css(cache.css);
10476				}
10477			} else if (grid) {
10478				cache.css.width = cache.items.width;
10479				items.css(cache.css);
10480			}
10481		}
10482	}, {
10483		filter: [ 'items' ],
10484		run: function() {
10485			this._coordinates.length < 1 && this.$stage.removeAttr('style');
10486		}
10487	}, {
10488		filter: [ 'width', 'items', 'settings' ],
10489		run: function(cache) {
10490			cache.current = cache.current ? this.$stage.children().index(cache.current) : 0;
10491			cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current));
10492			this.reset(cache.current);
10493		}
10494	}, {
10495		filter: [ 'position' ],
10496		run: function() {
10497			this.animate(this.coordinates(this._current));
10498		}
10499	}, {
10500		filter: [ 'width', 'position', 'items', 'settings' ],
10501		run: function() {
10502			var rtl = this.settings.rtl ? 1 : -1,
10503				padding = this.settings.stagePadding * 2,
10504				begin = this.coordinates(this.current()) + padding,
10505				end = begin + this.width() * rtl,
10506				inner, outer, matches = [], i, n;
10507
10508			for (i = 0, n = this._coordinates.length; i < n; i++) {
10509				inner = this._coordinates[i - 1] || 0;
10510				outer = Math.abs(this._coordinates[i]) + padding * rtl;
10511
10512				if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end)))
10513					|| (this.op(outer, '<', begin) && this.op(outer, '>', end))) {
10514					matches.push(i);
10515				}
10516			}
10517
10518			this.$stage.children('.active').removeClass('active');
10519			this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active');
10520
10521			if (this.settings.center) {
10522				this.$stage.children('.center').removeClass('center');
10523				this.$stage.children().eq(this.current()).addClass('center');
10524			}
10525		}
10526	} ];
10527
10528	/**
10529	 * Initializes the carousel.
10530	 * @protected
10531	 */
10532	Owl.prototype.initialize = function() {
10533		this.enter('initializing');
10534		this.trigger('initialize');
10535
10536		this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl);
10537
10538		if (this.settings.autoWidth && !this.is('pre-loading')) {
10539			var imgs, nestedSelector, width;
10540			imgs = this.$element.find('img');
10541			nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined;
10542			width = this.$element.children(nestedSelector).width();
10543
10544			if (imgs.length && width <= 0) {
10545				this.preloadAutoWidthImages(imgs);
10546			}
10547		}
10548
10549		this.$element.addClass(this.options.loadingClass);
10550
10551		// create stage
10552		this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>')
10553			.wrap('<div class="' + this.settings.stageOuterClass + '"/>');
10554
10555		// append stage
10556		this.$element.append(this.$stage.parent());
10557
10558		// append content
10559		this.replace(this.$element.children().not(this.$stage.parent()));
10560
10561		// check visibility
10562		if (this.$element.is(':visible')) {
10563			// update view
10564			this.refresh();
10565		} else {
10566			// invalidate width
10567			this.invalidate('width');
10568		}
10569
10570		this.$element
10571			.removeClass(this.options.loadingClass)
10572			.addClass(this.options.loadedClass);
10573
10574		// register event handlers
10575		this.registerEventHandlers();
10576
10577		this.leave('initializing');
10578		this.trigger('initialized');
10579	};
10580
10581	/**
10582	 * Setups the current settings.
10583	 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8?
10584	 * @todo Support for media queries by using `matchMedia` would be nice.
10585	 * @public
10586	 */
10587	Owl.prototype.setup = function() {
10588		var viewport = this.viewport(),
10589			overwrites = this.options.responsive,
10590			match = -1,
10591			settings = null;
10592
10593		if (!overwrites) {
10594			settings = $.extend({}, this.options);
10595		} else {
10596			$.each(overwrites, function(breakpoint) {
10597				if (breakpoint <= viewport && breakpoint > match) {
10598					match = Number(breakpoint);
10599				}
10600			});
10601
10602			settings = $.extend({}, this.options, overwrites[match]);
10603			delete settings.responsive;
10604
10605			// responsive class
10606			if (settings.responsiveClass) {
10607				this.$element.attr('class',
10608					this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match)
10609				);
10610			}
10611		}
10612
10613		if (this.settings === null || this._breakpoint !== match) {
10614			this.trigger('change', { property: { name: 'settings', value: settings } });
10615			this._breakpoint = match;
10616			this.settings = settings;
10617			this.invalidate('settings');
10618			this.trigger('changed', { property: { name: 'settings', value: this.settings } });
10619		}
10620	};
10621
10622	/**
10623	 * Updates option logic if necessery.
10624	 * @protected
10625	 */
10626	Owl.prototype.optionsLogic = function() {
10627		if (this.settings.autoWidth) {
10628			this.settings.stagePadding = false;
10629			this.settings.merge = false;
10630		}
10631	};
10632
10633	/**
10634	 * Prepares an item before add.
10635	 * @todo Rename event parameter `content` to `item`.
10636	 * @protected
10637	 * @returns {jQuery|HTMLElement} - The item container.
10638	 */
10639	Owl.prototype.prepare = function(item, index) {
10640		var event = this.trigger('prepare', { content: item });
10641		if (!event.data) {
10642			event.data = $('<' + this.settings.itemElement + '/>')
10643				.addClass(this.options.itemClass).attr('data-index', index + 1).append(item)
10644		}
10645
10646		this.trigger('prepared', { content: event.data });
10647
10648		return event.data;
10649	};
10650
10651	/**
10652	 * Updates the view.
10653	 * @public
10654	 */
10655	Owl.prototype.update = function() {
10656		var i = 0,
10657			n = this._pipe.length,
10658			filter = $.proxy(function(p) { return this[p] }, this._invalidated),
10659			cache = {};
10660
10661		while (i < n) {
10662			if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) {
10663				this._pipe[i].run(cache);
10664			}
10665			i++;
10666		}
10667
10668		this._invalidated = {};
10669
10670		!this.is('valid') && this.enter('valid');
10671	};
10672
10673	/**
10674	 * Gets the width of the view.
10675	 * @public
10676	 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return.
10677	 * @returns {Number} - The width of the view in pixel.
10678	 */
10679	Owl.prototype.width = function(dimension) {
10680		dimension = dimension || Owl.Width.Default;
10681		switch (dimension) {
10682			case Owl.Width.Inner:
10683			case Owl.Width.Outer:
10684				return this._width;
10685			default:
10686				return this._width - this.settings.stagePadding * 2 + this.settings.margin;
10687		}
10688	};
10689
10690	/**
10691	 * Refreshes the carousel primarily for adaptive purposes.
10692	 * @public
10693	 */
10694	Owl.prototype.refresh = function() {
10695		this.enter('refreshing');
10696		this.trigger('refresh');
10697
10698		this.setup();
10699
10700		this.optionsLogic();
10701
10702		this.$element.addClass(this.options.refreshClass);
10703
10704		this.update();
10705
10706		this.$element.removeClass(this.options.refreshClass);
10707
10708		this.leave('refreshing');
10709		this.trigger('refreshed');
10710	};
10711
10712	/**
10713	 * Checks window `resize` event.
10714	 * @protected
10715	 */
10716	Owl.prototype.onThrottledResize = function() {
10717		window.clearTimeout(this.resizeTimer);
10718		this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate);
10719	};
10720
10721	/**
10722	 * Checks window `resize` event.
10723	 * @protected
10724	 */
10725	Owl.prototype.onResize = function() {
10726		if (!this._items.length) {
10727			return false;
10728		}
10729
10730		if (this._width === this.$element.width()) {
10731			return false;
10732		}
10733
10734		if (!this.$element.is(':visible')) {
10735			return false;
10736		}
10737
10738		this.enter('resizing');
10739
10740		if (this.trigger('resize').isDefaultPrevented()) {
10741			this.leave('resizing');
10742			return false;
10743		}
10744
10745		this.invalidate('width');
10746
10747		this.refresh();
10748
10749		this.leave('resizing');
10750		this.trigger('resized');
10751	};
10752
10753	/**
10754	 * Registers event handlers.
10755	 * @todo Check `msPointerEnabled`
10756	 * @todo #261
10757	 * @protected
10758	 */
10759	Owl.prototype.registerEventHandlers = function() {
10760		if ($.support.transition) {
10761			this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this));
10762		}
10763
10764		if (this.settings.responsive !== false) {
10765			this.on(window, 'resize', this._handlers.onThrottledResize);
10766		}
10767
10768		if (this.settings.mouseDrag) {
10769			this.$element.addClass(this.options.dragClass);
10770			this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this));
10771			this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false });
10772		}
10773
10774		if (this.settings.touchDrag){
10775			this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this));
10776			this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this));
10777		}
10778	};
10779
10780	/**
10781	 * Handles `touchstart` and `mousedown` events.
10782	 * @todo Horizontal swipe threshold as option
10783	 * @todo #261
10784	 * @protected
10785	 * @param {Event} event - The event arguments.
10786	 */
10787	Owl.prototype.onDragStart = function(event) {
10788		var stage = null;
10789
10790		if (event.which === 3) {
10791			return;
10792		}
10793
10794		if ($.support.transform) {
10795			stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(',');
10796			stage = {
10797				x: stage[stage.length === 16 ? 12 : 4],
10798				y: stage[stage.length === 16 ? 13 : 5]
10799			};
10800		} else {
10801			stage = this.$stage.position();
10802			stage = {
10803				x: this.settings.rtl ?
10804					stage.left + this.$stage.width() - this.width() + this.settings.margin :
10805					stage.left,
10806				y: stage.top
10807			};
10808		}
10809
10810		if (this.is('animating')) {
10811			$.support.transform ? this.animate(stage.x) : this.$stage.stop()
10812			this.invalidate('position');
10813		}
10814
10815		this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown');
10816
10817		this.speed(0);
10818
10819		this._drag.time = new Date().getTime();
10820		this._drag.target = $(event.target);
10821		this._drag.stage.start = stage;
10822		this._drag.stage.current = stage;
10823		this._drag.pointer = this.pointer(event);
10824
10825		$(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this));
10826
10827		$(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) {
10828			var delta = this.difference(this._drag.pointer, this.pointer(event));
10829
10830			$(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this));
10831
10832			if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) {
10833				return;
10834			}
10835
10836			event.preventDefault();
10837
10838			this.enter('dragging');
10839			this.trigger('drag');
10840		}, this));
10841	};
10842
10843	/**
10844	 * Handles the `touchmove` and `mousemove` events.
10845	 * @todo #261
10846	 * @protected
10847	 * @param {Event} event - The event arguments.
10848	 */
10849	Owl.prototype.onDragMove = function(event) {
10850		var minimum = null,
10851			maximum = null,
10852			pull = null,
10853			delta = this.difference(this._drag.pointer, this.pointer(event)),
10854			stage = this.difference(this._drag.stage.start, delta);
10855
10856		if (!this.is('dragging')) {
10857			return;
10858		}
10859
10860		event.preventDefault();
10861
10862		if (this.settings.loop) {
10863			minimum = this.coordinates(this.minimum());
10864			maximum = this.coordinates(this.maximum() + 1) - minimum;
10865			stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum;
10866		} else {
10867			minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum());
10868			maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum());
10869			pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0;
10870			stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull);
10871		}
10872
10873		this._drag.stage.current = stage;
10874
10875		this.animate(stage.x);
10876	};
10877
10878	/**
10879	 * Handles the `touchend` and `mouseup` events.
10880	 * @todo #261
10881	 * @todo Threshold for click event
10882	 * @protected
10883	 * @param {Event} event - The event arguments.
10884	 */
10885	Owl.prototype.onDragEnd = function(event) {
10886		var delta = this.difference(this._drag.pointer, this.pointer(event)),
10887			stage = this._drag.stage.current,
10888			direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right';
10889
10890		$(document).off('.owl.core');
10891
10892		this.$element.removeClass(this.options.grabClass);
10893
10894		if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) {
10895			this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed);
10896			this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction));
10897			this.invalidate('position');
10898			this.update();
10899
10900			this._drag.direction = direction;
10901
10902			if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) {
10903				this._drag.target.one('click.owl.core', function() { return false; });
10904			}
10905		}
10906
10907		if (!this.is('dragging')) {
10908			return;
10909		}
10910
10911		this.leave('dragging');
10912		this.trigger('dragged');
10913	};
10914
10915	/**
10916	 * Gets absolute position of the closest item for a coordinate.
10917	 * @todo Setting `freeDrag` makes `closest` not reusable. See #165.
10918	 * @protected
10919	 * @param {Number} coordinate - The coordinate in pixel.
10920	 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`.
10921	 * @return {Number} - The absolute position of the closest item.
10922	 */
10923	Owl.prototype.closest = function(coordinate, direction) {
10924		var position = -1,
10925			pull = 30,
10926			width = this.width(),
10927			coordinates = this.coordinates();
10928
10929		if (!this.settings.freeDrag) {
10930			// check closest item
10931			$.each(coordinates, $.proxy(function(index, value) {
10932				if (coordinate > value - pull && coordinate < value + pull) {
10933					position = index;
10934				} else if (this.op(coordinate, '<', value)
10935					&& this.op(coordinate, '>', coordinates[index + 1] || value - width)) {
10936					position = direction === 'left' ? index + 1 : index;
10937				}
10938				return position === -1;
10939			}, this));
10940		}
10941
10942		if (!this.settings.loop) {
10943			// non loop boundries
10944			if (this.op(coordinate, '>', coordinates[this.minimum()])) {
10945				position = coordinate = this.minimum();
10946			} else if (this.op(coordinate, '<', coordinates[this.maximum()])) {
10947				position = coordinate = this.maximum();
10948			}
10949		}
10950
10951		return position;
10952	};
10953
10954	/**
10955	 * Animates the stage.
10956	 * @todo #270
10957	 * @public
10958	 * @param {Number} coordinate - The coordinate in pixels.
10959	 */
10960	Owl.prototype.animate = function(coordinate) {
10961		var animate = this.speed() > 0;
10962
10963		this.is('animating') && this.onTransitionEnd();
10964
10965		if (animate) {
10966			this.enter('animating');
10967			this.trigger('translate');
10968		}
10969
10970		if ($.support.transform3d && $.support.transition) {
10971			this.$stage.css({
10972				transform: 'translate3d(' + coordinate + 'px,0px,0px)',
10973				transition: (this.speed() / 1000) + 's'
10974			});
10975		} else if (animate) {
10976			this.$stage.animate({
10977				left: coordinate + 'px'
10978			}, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this));
10979		} else {
10980			this.$stage.css({
10981				left: coordinate + 'px'
10982			});
10983		}
10984	};
10985
10986	/**
10987	 * Checks whether the carousel is in a specific state or not.
10988	 * @param {String} state - The state to check.
10989	 * @returns {Boolean} - The flag which indicates if the carousel is busy.
10990	 */
10991	Owl.prototype.is = function(state) {
10992		return this._states.current[state] && this._states.current[state] > 0;
10993	};
10994
10995	/**
10996	 * Sets the absolute position of the current item.
10997	 * @public
10998	 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged.
10999	 * @returns {Number} - The absolute position of the current item.
11000	 */
11001	Owl.prototype.current = function(position) {
11002		if (position === undefined) {
11003			return this._current;
11004		}
11005
11006		if (this._items.length === 0) {
11007			return undefined;
11008		}
11009
11010		position = this.normalize(position);
11011
11012		if (this._current !== position) {
11013			var event = this.trigger('change', { property: { name: 'position', value: position } });
11014
11015			if (event.data !== undefined) {
11016				position = this.normalize(event.data);
11017			}
11018
11019			this._current = position;
11020
11021			this.invalidate('position');
11022
11023			this.trigger('changed', { property: { name: 'position', value: this._current } });
11024		}
11025
11026		return this._current;
11027	};
11028
11029	/**
11030	 * Invalidates the given part of the update routine.
11031	 * @param {String} [part] - The part to invalidate.
11032	 * @returns {Array.<String>} - The invalidated parts.
11033	 */
11034	Owl.prototype.invalidate = function(part) {
11035		if ($.type(part) === 'string') {
11036			this._invalidated[part] = true;
11037			this.is('valid') && this.leave('valid');
11038		}
11039		return $.map(this._invalidated, function(v, i) { return i });
11040	};
11041
11042	/**
11043	 * Resets the absolute position of the current item.
11044	 * @public
11045	 * @param {Number} position - The absolute position of the new item.
11046	 */
11047	Owl.prototype.reset = function(position) {
11048		position = this.normalize(position);
11049
11050		if (position === undefined) {
11051			return;
11052		}
11053
11054		this._speed = 0;
11055		this._current = position;
11056
11057		this.suppress([ 'translate', 'translated' ]);
11058
11059		this.animate(this.coordinates(position));
11060
11061		this.release([ 'translate', 'translated' ]);
11062	};
11063
11064	/**
11065	 * Normalizes an absolute or a relative position of an item.
11066	 * @public
11067	 * @param {Number} position - The absolute or relative position to normalize.
11068	 * @param {Boolean} [relative=false] - Whether the given position is relative or not.
11069	 * @returns {Number} - The normalized position.
11070	 */
11071	Owl.prototype.normalize = function(position, relative) {
11072		var n = this._items.length,
11073			m = relative ? 0 : this._clones.length;
11074
11075		if (!$.isNumeric(position) || n < 1) {
11076			position = undefined;
11077		} else if (position < 0 || position >= n + m) {
11078			position = ((position - m / 2) % n + n) % n + m / 2;
11079		}
11080
11081		return position;
11082	};
11083
11084	/**
11085	 * Converts an absolute position of an item into a relative one.
11086	 * @public
11087	 * @param {Number} position - The absolute position to convert.
11088	 * @returns {Number} - The converted position.
11089	 */
11090	Owl.prototype.relative = function(position) {
11091		position -= this._clones.length / 2;
11092		return this.normalize(position, true);
11093	};
11094
11095	/**
11096	 * Gets the maximum position for the current item.
11097	 * @public
11098	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
11099	 * @returns {Number}
11100	 */
11101	Owl.prototype.maximum = function(relative) {
11102		var settings = this.settings,
11103			maximum = this._coordinates.length,
11104			boundary = Math.abs(this._coordinates[maximum - 1]) - this._width,
11105			i = -1, j;
11106
11107		if (settings.loop) {
11108			maximum = this._clones.length / 2 + this._items.length - 1;
11109		} else if (settings.autoWidth || settings.merge) {
11110			// binary search
11111			while (maximum - i > 1) {
11112				Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary
11113					? i = j : maximum = j;
11114			}
11115		} else if (settings.center) {
11116			maximum = this._items.length - 1;
11117		} else {
11118			maximum = this._items.length - settings.items;
11119		}
11120
11121		if (relative) {
11122			maximum -= this._clones.length / 2;
11123		}
11124
11125		return Math.max(maximum, 0);
11126	};
11127
11128	/**
11129	 * Gets the minimum position for the current item.
11130	 * @public
11131	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
11132	 * @returns {Number}
11133	 */
11134	Owl.prototype.minimum = function(relative) {
11135		return relative ? 0 : this._clones.length / 2;
11136	};
11137
11138	/**
11139	 * Gets an item at the specified relative position.
11140	 * @public
11141	 * @param {Number} [position] - The relative position of the item.
11142	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
11143	 */
11144	Owl.prototype.items = function(position) {
11145		if (position === undefined) {
11146			return this._items.slice();
11147		}
11148
11149		position = this.normalize(position, true);
11150		return this._items[position];
11151	};
11152
11153	/**
11154	 * Gets an item at the specified relative position.
11155	 * @public
11156	 * @param {Number} [position] - The relative position of the item.
11157	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
11158	 */
11159	Owl.prototype.mergers = function(position) {
11160		if (position === undefined) {
11161			return this._mergers.slice();
11162		}
11163
11164		position = this.normalize(position, true);
11165		return this._mergers[position];
11166	};
11167
11168	/**
11169	 * Gets the absolute positions of clones for an item.
11170	 * @public
11171	 * @param {Number} [position] - The relative position of the item.
11172	 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given.
11173	 */
11174	Owl.prototype.clones = function(position) {
11175		var odd = this._clones.length / 2,
11176			even = odd + this._items.length,
11177			map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 };
11178
11179		if (position === undefined) {
11180			return $.map(this._clones, function(v, i) { return map(i) });
11181		}
11182
11183		return $.map(this._clones, function(v, i) { return v === position ? map(i) : null });
11184	};
11185
11186	/**
11187	 * Sets the current animation speed.
11188	 * @public
11189	 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged.
11190	 * @returns {Number} - The current animation speed in milliseconds.
11191	 */
11192	Owl.prototype.speed = function(speed) {
11193		if (speed !== undefined) {
11194			this._speed = speed;
11195		}
11196
11197		return this._speed;
11198	};
11199
11200	/**
11201	 * Gets the coordinate of an item.
11202	 * @todo The name of this method is missleanding.
11203	 * @public
11204	 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`.
11205	 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates.
11206	 */
11207	Owl.prototype.coordinates = function(position) {
11208		var coordinate = null;
11209
11210		if (position === undefined) {
11211			return $.map(this._coordinates, $.proxy(function(coordinate, index) {
11212				return this.coordinates(index);
11213			}, this));
11214		}
11215
11216		if (this.settings.center) {
11217			coordinate = this._coordinates[position];
11218			coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1);
11219		} else {
11220			coordinate = this._coordinates[position - 1] || 0;
11221		}
11222
11223		return coordinate;
11224	};
11225
11226	/**
11227	 * Calculates the speed for a translation.
11228	 * @protected
11229	 * @param {Number} from - The absolute position of the start item.
11230	 * @param {Number} to - The absolute position of the target item.
11231	 * @param {Number} [factor=undefined] - The time factor in milliseconds.
11232	 * @returns {Number} - The time in milliseconds for the translation.
11233	 */
11234	Owl.prototype.duration = function(from, to, factor) {
11235		return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed));
11236	};
11237
11238	/**
11239	 * Slides to the specified item.
11240	 * @public
11241	 * @param {Number} position - The position of the item.
11242	 * @param {Number} [speed] - The time in milliseconds for the transition.
11243	 */
11244	Owl.prototype.to = function(position, speed) {
11245		var current = this.current(),
11246			revert = null,
11247			distance = position - this.relative(current),
11248			direction = (distance > 0) - (distance < 0),
11249			items = this._items.length,
11250			minimum = this.minimum(),
11251			maximum = this.maximum();
11252
11253		if (this.settings.loop) {
11254			if (!this.settings.rewind && Math.abs(distance) > items / 2) {
11255				distance += direction * -1 * items;
11256			}
11257
11258			position = current + distance;
11259			revert = ((position - minimum) % items + items) % items + minimum;
11260
11261			if (revert !== position && revert - distance <= maximum && revert - distance > 0) {
11262				current = revert - distance;
11263				position = revert;
11264				this.reset(current);
11265			}
11266		} else if (this.settings.rewind) {
11267			maximum += 1;
11268			position = (position % maximum + maximum) % maximum;
11269		} else {
11270			position = Math.max(minimum, Math.min(maximum, position));
11271		}
11272
11273		this.speed(this.duration(current, position, speed));
11274		this.current(position);
11275
11276		if (this.$element.is(':visible')) {
11277			this.update();
11278		}
11279	};
11280
11281	/**
11282	 * Slides to the next item.
11283	 * @public
11284	 * @param {Number}
vendor: 12,284 bytes, lines 11284-11704
11284 [speed] - The time in milliseconds for the transition.
11285	 */
11286	Owl.prototype.next = function(speed) {
11287		speed = speed || false;
11288		this.to(this.relative(this.current()) + 1, speed);
11289	};
11290
11291	/**
11292	 * Slides to the previous item.
11293	 * @public
11294	 * @param {Number} [speed] - The time in milliseconds for the transition.
11295	 */
11296	Owl.prototype.prev = function(speed) {
11297		speed = speed || false;
11298		this.to(this.relative(this.current()) - 1, speed);
11299	};
11300
11301	/**
11302	 * Handles the end of an animation.
11303	 * @protected
11304	 * @param {Event} event - The event arguments.
11305	 */
11306	Owl.prototype.onTransitionEnd = function(event) {
11307
11308		// if css2 animation then event object is undefined
11309		if (event !== undefined) {
11310			event.stopPropagation();
11311
11312			// Catch only owl-stage transitionEnd event
11313			if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) {
11314				return false;
11315			}
11316		}
11317
11318		this.leave('animating');
11319		this.trigger('translated');
11320	};
11321
11322	/**
11323	 * Gets viewport width.
11324	 * @protected
11325	 * @return {Number} - The width in pixel.
11326	 */
11327	Owl.prototype.viewport = function() {
11328		var width;
11329		if (this.options.responsiveBaseElement !== window) {
11330			width = $(this.options.responsiveBaseElement).width();
11331		} else if (window.innerWidth) {
11332			width = window.innerWidth;
11333		} else if (document.documentElement && document.documentElement.clientWidth) {
11334			width = document.documentElement.clientWidth;
11335		} else {
11336			throw 'Can not detect viewport width.';
11337		}
11338
11339		return width;
11340	};
11341
11342	/**
11343	 * Replaces the current content.
11344	 * @public
11345	 * @param {HTMLElement|jQuery|String} content - The new content.
11346	 */
11347	Owl.prototype.replace = function(content) {
11348		this.$stage.empty();
11349		this._items = [];
11350
11351		if (content) {
11352			content = (content instanceof jQuery) ? content : $(content);
11353		}
11354
11355		if (this.settings.nestedItemSelector) {
11356			content = content.find('.' + this.settings.nestedItemSelector);
11357		}
11358
11359		content.filter(function() {
11360			return this.nodeType === 1;
11361		}).each($.proxy(function(index, item) {
11362			item = this.prepare(item, index);
11363			this.$stage.append(item);
11364			this._items.push(item);
11365			this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
11366		}, this));
11367
11368		this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0);
11369
11370		this.invalidate('items');
11371	};
11372
11373	/**
11374	 * Adds an item.
11375	 * @todo Use `item` instead of `content` for the event arguments.
11376	 * @public
11377	 * @param {HTMLElement|jQuery|String} content - The item content to add.
11378	 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end.
11379	 */
11380	Owl.prototype.add = function(content, position) {
11381		var current = this.relative(this._current);
11382
11383		position = position === undefined ? this._items.length : this.normalize(position, true);
11384		content = content instanceof jQuery ? content : $(content);
11385
11386		this.trigger('add', { content: content, position: position });
11387
11388		content = this.prepare(content, this._items[current].index());
11389
11390		if (this._items.length === 0 || position === this._items.length) {
11391			this._items.length === 0 && this.$stage.append(content);
11392			this._items.length !== 0 && this._items[position - 1].after(content);
11393			this._items.push(content);
11394			this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
11395		} else {
11396			this._items[position].before(content);
11397			this._items.splice(position, 0, content);
11398			this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
11399		}
11400
11401		this._items[current] && this.reset(this._items[current].index());
11402
11403		this.invalidate('items');
11404
11405		this.trigger('added', { content: content, position: position });
11406	};
11407
11408	/**
11409	 * Removes an item by its position.
11410	 * @todo Use `item` instead of `content` for the event arguments.
11411	 * @public
11412	 * @param {Number} position - The relative position of the item to remove.
11413	 */
11414	Owl.prototype.remove = function(position) {
11415		position = this.normalize(position, true);
11416
11417		if (position === undefined) {
11418			return;
11419		}
11420
11421		this.trigger('remove', { content: this._items[position], position: position });
11422
11423		this._items[position].remove();
11424		this._items.splice(position, 1);
11425		this._mergers.splice(position, 1);
11426
11427		this.invalidate('items');
11428
11429		this.trigger('removed', { content: null, position: position });
11430	};
11431
11432	/**
11433	 * Preloads images with auto width.
11434	 * @todo Replace by a more generic approach
11435	 * @protected
11436	 */
11437	Owl.prototype.preloadAutoWidthImages = function(images) {
11438		images.each($.proxy(function(i, element) {
11439			this.enter('pre-loading');
11440			element = $(element);
11441			$(new Image()).one('load', $.proxy(function(e) {
11442				element.attr('src', e.target.src);
11443				element.css('opacity', 1);
11444				this.leave('pre-loading');
11445				!this.is('pre-loading') && !this.is('initializing') && this.refresh();
11446			}, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina'));
11447		}, this));
11448	};
11449
11450	/**
11451	 * Destroys the carousel.
11452	 * @public
11453	 */
11454	Owl.prototype.destroy = function() {
11455
11456		this.$element.off('.owl.core');
11457		this.$stage.off('.owl.core');
11458		$(document).off('.owl.core');
11459
11460		if (this.settings.responsive !== false) {
11461			window.clearTimeout(this.resizeTimer);
11462			this.off(window, 'resize', this._handlers.onThrottledResize);
11463		}
11464
11465		for (var i in this._plugins) {
11466			this._plugins[i].destroy();
11467		}
11468
11469		this.$stage.children('.cloned').remove();
11470
11471		this.$stage.unwrap();
11472		this.$stage.children().contents().unwrap();
11473		this.$stage.children().unwrap();
11474
11475		this.$element
11476			.removeClass(this.options.refreshClass)
11477			.removeClass(this.options.loadingClass)
11478			.removeClass(this.options.loadedClass)
11479			.removeClass(this.options.rtlClass)
11480			.removeClass(this.options.dragClass)
11481			.removeClass(this.options.grabClass)
11482			.attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), ''))
11483			.removeData('owl.carousel');
11484	};
11485
11486	/**
11487	 * Operators to calculate right-to-left and left-to-right.
11488	 * @protected
11489	 * @param {Number} [a] - The left side operand.
11490	 * @param {String} [o] - The operator.
11491	 * @param {Number} [b] - The right side operand.
11492	 */
11493	Owl.prototype.op = function(a, o, b) {
11494		var rtl = this.settings.rtl;
11495		switch (o) {
11496			case '<':
11497				return rtl ? a > b : a < b;
11498			case '>':
11499				return rtl ? a < b : a > b;
11500			case '>=':
11501				return rtl ? a <= b : a >= b;
11502			case '<=':
11503				return rtl ? a >= b : a <= b;
11504			default:
11505				break;
11506		}
11507	};
11508
11509	/**
11510	 * Attaches to an internal event.
11511	 * @protected
11512	 * @param {HTMLElement} element - The event source.
11513	 * @param {String} event - The event name.
11514	 * @param {Function} listener - The event handler to attach.
11515	 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not.
11516	 */
11517	Owl.prototype.on = function(element, event, listener, capture) {
11518		if (element.addEventListener) {
11519			element.addEventListener(event, listener, capture);
11520		} else if (element.attachEvent) {
11521			element.attachEvent('on' + event, listener);
11522		}
11523	};
11524
11525	/**
11526	 * Detaches from an internal event.
11527	 * @protected
11528	 * @param {HTMLElement} element - The event source.
11529	 * @param {String} event - The event name.
11530	 * @param {Function} listener - The attached event handler to detach.
11531	 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not.
11532	 */
11533	Owl.prototype.off = function(element, event, listener, capture) {
11534		if (element.removeEventListener) {
11535			element.removeEventListener(event, listener, capture);
11536		} else if (element.detachEvent) {
11537			element.detachEvent('on' + event, listener);
11538		}
11539	};
11540
11541	/**
11542	 * Triggers a public event.
11543	 * @todo Remove `status`, `relatedTarget` should be used instead.
11544	 * @protected
11545	 * @param {String} name - The event name.
11546	 * @param {*} [data=null] - The event data.
11547	 * @param {String} [namespace=carousel] - The event namespace.
11548	 * @param {String} [state] - The state which is associated with the event.
11549	 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not.
11550	 * @returns {Event} - The event arguments.
11551	 */
11552	Owl.prototype.trigger = function(name, data, namespace, state, enter) {
11553		var status = {
11554			item: { count: this._items.length, index: this.current() }
11555		}, handler = $.camelCase(
11556			$.grep([ 'on', name, namespace ], function(v) { return v })
11557				.join('-').toLowerCase()
11558		), event = $.Event(
11559			[ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(),
11560			$.extend({ relatedTarget: this }, status, data)
11561		);
11562
11563		if (!this._supress[name]) {
11564			$.each(this._plugins, function(name, plugin) {
11565				if (plugin.onTrigger) {
11566					plugin.onTrigger(event);
11567				}
11568			});
11569
11570			this.register({ type: Owl.Type.Event, name: name });
11571			this.$element.trigger(event);
11572
11573			if (this.settings && typeof this.settings[handler] === 'function') {
11574				this.settings[handler].call(this, event);
11575			}
11576		}
11577
11578		return event;
11579	};
11580
11581	/**
11582	 * Enters a state.
11583	 * @param name - The state name.
11584	 */
11585	Owl.prototype.enter = function(name) {
11586		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
11587			if (this._states.current[name] === undefined) {
11588				this._states.current[name] = 0;
11589			}
11590
11591			this._states.current[name]++;
11592		}, this));
11593	};
11594
11595	/**
11596	 * Leaves a state.
11597	 * @param name - The state name.
11598	 */
11599	Owl.prototype.leave = function(name) {
11600		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
11601			this._states.current[name]--;
11602		}, this));
11603	};
11604
11605	/**
11606	 * Registers an event or state.
11607	 * @public
11608	 * @param {Object} object - The event or state to register.
11609	 */
11610	Owl.prototype.register = function(object) {
11611		if (object.type === Owl.Type.Event) {
11612			if (!$.event.special[object.name]) {
11613				$.event.special[object.name] = {};
11614			}
11615
11616			if (!$.event.special[object.name].owl) {
11617				var _default = $.event.special[object.name]._default;
11618				$.event.special[object.name]._default = function(e) {
11619					if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) {
11620						return _default.apply(this, arguments);
11621					}
11622					return e.namespace && e.namespace.indexOf('owl') > -1;
11623				};
11624				$.event.special[object.name].owl = true;
11625			}
11626		} else if (object.type === Owl.Type.State) {
11627			if (!this._states.tags[object.name]) {
11628				this._states.tags[object.name] = object.tags;
11629			} else {
11630				this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags);
11631			}
11632
11633			this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) {
11634				return $.inArray(tag, this._states.tags[object.name]) === i;
11635			}, this));
11636		}
11637	};
11638
11639	/**
11640	 * Suppresses events.
11641	 * @protected
11642	 * @param {Array.<String>} events - The events to suppress.
11643	 */
11644	Owl.prototype.suppress = function(events) {
11645		$.each(events, $.proxy(function(index, event) {
11646			this._supress[event] = true;
11647		}, this));
11648	};
11649
11650	/**
11651	 * Releases suppressed events.
11652	 * @protected
11653	 * @param {Array.<String>} events - The events to release.
11654	 */
11655	Owl.prototype.release = function(events) {
11656		$.each(events, $.proxy(function(index, event) {
11657			delete this._supress[event];
11658		}, this));
11659	};
11660
11661	/**
11662	 * Gets unified pointer coordinates from event.
11663	 * @todo #261
11664	 * @protected
11665	 * @param {Event} - The `mousedown` or `touchstart` event.
11666	 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position.
11667	 */
11668	Owl.prototype.pointer = function(event) {
11669		var result = { x: null, y: null };
11670
11671		event = event.originalEvent || event || window.event;
11672
11673		event = event.touches && event.touches.length ?
11674			event.touches[0] : event.changedTouches && event.changedTouches.length ?
11675				event.changedTouches[0] : event;
11676
11677		if (event.pageX) {
11678			result.x = event.pageX;
11679			result.y = event.pageY;
11680		} else {
11681			result.x = event.clientX;
11682			result.y = event.clientY;
11683		}
11684
11685		return result;
11686	};
11687
11688	/**
11689	 * Gets the difference of two vectors.
11690	 * @todo #261
11691	 * @protected
11692	 * @param {Object} - The first vector.
11693	 * @param {Object} - The second vector.
11694	 * @returns {Object} - The difference.
11695	 */
11696	Owl.prototype.difference = function(first, second) {
11697		return {
11698			x: first.x - second.x,
11699			y: first.y - second.y
11700		};
11701	};
11702
11703	/**
11704	 * The jQuery Plugin for the Owl Carousel
vendor: 32,236 bytes, lines 11705-12987
11705	 * @todo Navigation plugin `next` and `prev`
11706	 * @public
11707	 */
11708	$.fn.owlCarousel = function(option) {
11709		var args = Array.prototype.slice.call(arguments, 1);
11710
11711		return this.each(function() {
11712			var $this = $(this),
11713				data = $this.data('owl.carousel');
11714
11715			if (!data) {
11716				data = new Owl(this, typeof option == 'object' && option);
11717				$this.data('owl.carousel', data);
11718
11719				$.each([
11720					'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove'
11721				], function(i, event) {
11722					data.register({ type: Owl.Type.Event, name: event });
11723					data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) {
11724						if (e.namespace && e.relatedTarget !== this) {
11725							this.suppress([ event ]);
11726							data[event].apply(this, [].slice.call(arguments, 1));
11727							this.release([ event ]);
11728						}
11729					}, data));
11730				});
11731			}
11732
11733			if (typeof option == 'string' && option.charAt(0) !== '_') {
11734				data[option].apply(data, args);
11735			}
11736		});
11737	};
11738
11739	/**
11740	 * The constructor for the jQuery Plugin
11741	 * @public
11742	 */
11743	$.fn.owlCarousel.Constructor = Owl;
11744
11745})(window.Zepto || window.jQuery, window, document);
11746
11747/**
11748 * AutoRefresh Plugin
11749 * @version 2.0.0-beta.3
11750 * @author Artus Kolanowski
11751 * @license The MIT License (MIT)
11752 */
11753;(function($, window, document, undefined) {
11754
11755	/**
11756	 * Creates the auto refresh plugin.
11757	 * @class The Auto Refresh Plugin
11758	 * @param {Owl} carousel - The Owl Carousel
11759	 */
11760	var AutoRefresh = function(carousel) {
11761		/**
11762		 * Reference to the core.
11763		 * @protected
11764		 * @type {Owl}
11765		 */
11766		this._core = carousel;
11767
11768		/**
11769		 * Refresh interval.
11770		 * @protected
11771		 * @type {number}
11772		 */
11773		this._interval = null;
11774
11775		/**
11776		 * Whether the element is currently visible or not.
11777		 * @protected
11778		 * @type {Boolean}
11779		 */
11780		this._visible = null;
11781
11782		/**
11783		 * All event handlers.
11784		 * @protected
11785		 * @type {Object}
11786		 */
11787		this._handlers = {
11788			'initialized.owl.carousel': $.proxy(function(e) {
11789				if (e.namespace && this._core.settings.autoRefresh) {
11790					this.watch();
11791				}
11792			}, this)
11793		};
11794
11795		// set default options
11796		this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options);
11797
11798		// register event handlers
11799		this._core.$element.on(this._handlers);
11800	};
11801
11802	/**
11803	 * Default options.
11804	 * @public
11805	 */
11806	AutoRefresh.Defaults = {
11807		autoRefresh: true,
11808		autoRefreshInterval: 500
11809	};
11810
11811	/**
11812	 * Watches the element.
11813	 */
11814	AutoRefresh.prototype.watch = function() {
11815		if (this._interval) {
11816			return;
11817		}
11818
11819		this._visible = this._core.$element.is(':visible');
11820		this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval);
11821	};
11822
11823	/**
11824	 * Refreshes the element.
11825	 */
11826	AutoRefresh.prototype.refresh = function() {
11827		if (this._core.$element.is(':visible') === this._visible) {
11828			return;
11829		}
11830
11831		this._visible = !this._visible;
11832
11833		this._core.$element.toggleClass('owl-hidden', !this._visible);
11834
11835		this._visible && (this._core.invalidate('width') && this._core.refresh());
11836	};
11837
11838	/**
11839	 * Destroys the plugin.
11840	 */
11841	AutoRefresh.prototype.destroy = function() {
11842		var handler, property;
11843
11844		window.clearInterval(this._interval);
11845
11846		for (handler in this._handlers) {
11847			this._core.$element.off(handler, this._handlers[handler]);
11848		}
11849		for (property in Object.getOwnPropertyNames(this)) {
11850			typeof this[property] != 'function' && (this[property] = null);
11851		}
11852	};
11853
11854	$.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh;
11855
11856})(window.Zepto || window.jQuery, window, document);
11857
11858/**
11859 * Lazy Plugin
11860 * @version 2.0.0-beta.3
11861 * @author Bartosz Wojciechowski
11862 * @license The MIT License (MIT)
11863 */
11864;(function($, window, document, undefined) {
11865
11866	/**
11867	 * Creates the lazy plugin.
11868	 * @class The Lazy Plugin
11869	 * @param {Owl} carousel - The Owl Carousel
11870	 */
11871	var Lazy = function(carousel) {
11872
11873		/**
11874		 * Reference to the core.
11875		 * @protected
11876		 * @type {Owl}
11877		 */
11878		this._core = carousel;
11879
11880		/**
11881		 * Already loaded items.
11882		 * @protected
11883		 * @type {Array.<jQuery>}
11884		 */
11885		this._loaded = [];
11886
11887		/**
11888		 * Event handlers.
11889		 * @protected
11890		 * @type {Object}
11891		 */
11892		this._handlers = {
11893			'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) {
11894				if (!e.namespace) {
11895					return;
11896				}
11897
11898				if (!this._core.settings || !this._core.settings.lazyLoad) {
11899					return;
11900				}
11901
11902				if ((e.property && e.property.name == 'position') || e.type == 'initialized') {
11903					var settings = this._core.settings,
11904						n = (settings.center && Math.ceil(settings.items / 2) || settings.items),
11905						i = ((settings.center && n * -1) || 0),
11906						position = ((e.property && e.property.value) || this._core.current()) + i,
11907						clones = this._core.clones().length,
11908						load = $.proxy(function(i, v) { this.load(v) }, this);
11909
11910					while (i++ < n) {
11911						this.load(clones / 2 + this._core.relative(position));
11912						clones && $.each(this._core.clones(this._core.relative(position)), load);
11913						position++;
11914					}
11915				}
11916			}, this)
11917		};
11918
11919		// set the default options
11920		this._core.options = $.extend({}, Lazy.Defaults, this._core.options);
11921
11922		// register event handler
11923		this._core.$element.on(this._handlers);
11924	}
11925
11926	/**
11927	 * Default options.
11928	 * @public
11929	 */
11930	Lazy.Defaults = {
11931		lazyLoad: false
11932	}
11933
11934	/**
11935	 * Loads all resources of an item at the specified position.
11936	 * @param {Number} position - The absolute position of the item.
11937	 * @protected
11938	 */
11939	Lazy.prototype.load = function(position) {
11940		var $item = this._core.$stage.children().eq(position),
11941			$elements = $item && $item.find('.owl-lazy');
11942
11943		if (!$elements || $.inArray($item.get(0), this._loaded) > -1) {
11944			return;
11945		}
11946
11947		$elements.each($.proxy(function(index, element) {
11948			var $element = $(element), image,
11949				url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src');
11950
11951			this._core.trigger('load', { element: $element, url: url }, 'lazy');
11952
11953			if ($element.is('img')) {
11954				$element.one('load.owl.lazy', $.proxy(function() {
11955					$element.css('opacity', 1);
11956					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
11957				}, this)).attr('src', url);
11958			} else {
11959				image = new Image();
11960				image.onload = $.proxy(function() {
11961					$element.css({
11962						'background-image': 'url(' + url + ')',
11963						'opacity': '1'
11964					});
11965					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
11966				}, this);
11967				image.src = url;
11968			}
11969		}, this));
11970
11971		this._loaded.push($item.get(0));
11972	}
11973
11974	/**
11975	 * Destroys the plugin.
11976	 * @public
11977	 */
11978	Lazy.prototype.destroy = function() {
11979		var handler, property;
11980
11981		for (handler in this.handlers) {
11982			this._core.$element.off(handler, this.handlers[handler]);
11983		}
11984		for (property in Object.getOwnPropertyNames(this)) {
11985			typeof this[property] != 'function' && (this[property] = null);
11986		}
11987	};
11988
11989	$.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy;
11990
11991})(window.Zepto || window.jQuery, window, document);
11992
11993/**
11994 * AutoHeight Plugin
11995 * @version 2.0.0-beta.3
11996 * @author Bartosz Wojciechowski
11997 * @license The MIT License (MIT)
11998 */
11999;(function($, window, document, undefined) {
12000
12001	/**
12002	 * Creates the auto height plugin.
12003	 * @class The Auto Height Plugin
12004	 * @param {Owl} carousel - The Owl Carousel
12005	 */
12006	var AutoHeight = function(carousel) {
12007		/**
12008		 * Reference to the core.
12009		 * @protected
12010		 * @type {Owl}
12011		 */
12012		this._core = carousel;
12013
12014		/**
12015		 * All event handlers.
12016		 * @protected
12017		 * @type {Object}
12018		 */
12019		this._handlers = {
12020			'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) {
12021				if (e.namespace && this._core.settings.autoHeight) {
12022					this.update();
12023				}
12024			}, this),
12025			'changed.owl.carousel': $.proxy(function(e) {
12026				if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){
12027					this.update();
12028				}
12029			}, this),
12030			'loaded.owl.lazy': $.proxy(function(e) {
12031				if (e.namespace && this._core.settings.autoHeight
12032					&& e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) {
12033					this.update();
12034				}
12035			}, this)
12036		};
12037
12038		// set default options
12039		this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options);
12040
12041		// register event handlers
12042		this._core.$element.on(this._handlers);
12043	};
12044
12045	/**
12046	 * Default options.
12047	 * @public
12048	 */
12049	AutoHeight.Defaults = {
12050		autoHeight: false,
12051		autoHeightClass: 'owl-height'
12052	};
12053
12054	/**
12055	 * Updates the view.
12056	 */
12057	AutoHeight.prototype.update = function() {
12058		var start = this._core._current,
12059			end = start + this._core.settings.items,
12060			visible = this._core.$stage.children().toArray().slice(start, end);
12061			heights = [],
12062			maxheight = 0;
12063
12064		$.each(visible, function(index, item) {
12065			heights.push($(item).height());
12066		});
12067
12068		maxheight = Math.max.apply(null, heights);
12069
12070		this._core.$stage.parent()
12071			.height(maxheight)
12072			.addClass(this._core.settings.autoHeightClass);
12073	};
12074
12075	AutoHeight.prototype.destroy = function() {
12076		var handler, property;
12077
12078		for (handler in this._handlers) {
12079			this._core.$element.off(handler, this._handlers[handler]);
12080		}
12081		for (property in Object.getOwnPropertyNames(this)) {
12082			typeof this[property] != 'function' && (this[property] = null);
12083		}
12084	};
12085
12086	$.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight;
12087
12088})(window.Zepto || window.jQuery, window, document);
12089
12090/**
12091 * Video Plugin
12092 * @version 2.0.0-beta.3
12093 * @author Bartosz Wojciechowski
12094 * @license The MIT License (MIT)
12095 */
12096;(function($, window, document, undefined) {
12097
12098	/**
12099	 * Creates the video plugin.
12100	 * @class The Video Plugin
12101	 * @param {Owl} carousel - The Owl Carousel
12102	 */
12103	var Video = function(carousel) {
12104		/**
12105		 * Reference to the core.
12106		 * @protected
12107		 * @type {Owl}
12108		 */
12109		this._core = carousel;
12110
12111		/**
12112		 * Cache all video URLs.
12113		 * @protected
12114		 * @type {Object}
12115		 */
12116		this._videos = {};
12117
12118		/**
12119		 * Current playing item.
12120		 * @protected
12121		 * @type {jQuery}
12122		 */
12123		this._playing = null;
12124
12125		/**
12126		 * All event handlers.
12127		 * @todo The cloned content removale is too late
12128		 * @protected
12129		 * @type {Object}
12130		 */
12131		this._handlers = {
12132			'initialized.owl.carousel': $.proxy(function(e) {
12133				if (e.namespace) {
12134					this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] });
12135				}
12136			}, this),
12137			'resize.owl.carousel': $.proxy(function(e) {
12138				if (e.namespace && this._core.settings.video && this.isInFullScreen()) {
12139					e.preventDefault();
12140				}
12141			}, this),
12142			'refreshed.owl.carousel': $.proxy(function(e) {
12143				if (e.namespace && this._core.is('resizing')) {
12144					this._core.$stage.find('.cloned .owl-video-frame').remove();
12145				}
12146			}, this),
12147			'changed.owl.carousel': $.proxy(function(e) {
12148				if (e.namespace && e.property.name === 'position' && this._playing) {
12149					this.stop();
12150				}
12151			}, this),
12152			'prepared.owl.carousel': $.proxy(function(e) {
12153				if (!e.namespace) {
12154					return;
12155				}
12156
12157				var $element = $(e.content).find('.owl-video');
12158
12159				if ($element.length) {
12160					$element.css('display', 'none');
12161					this.fetch($element, $(e.content));
12162				}
12163			}, this)
12164		};
12165
12166		// set default options
12167		this._core.options = $.extend({}, Video.Defaults, this._core.options);
12168
12169		// register event handlers
12170		this._core.$element.on(this._handlers);
12171
12172		this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) {
12173			this.play(e);
12174		}, this));
12175	};
12176
12177	/**
12178	 * Default options.
12179	 * @public
12180	 */
12181	Video.Defaults = {
12182		video: false,
12183		videoHeight: false,
12184		videoWidth: false
12185	};
12186
12187	/**
12188	 * Gets the video ID and the type (YouTube/Vimeo only).
12189	 * @protected
12190	 * @param {jQuery} target - The target containing the video data.
12191	 * @param {jQuery} item - The item containing the video.
12192	 */
12193	Video.prototype.fetch = function(target, item) {
12194		var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube',
12195			id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'),
12196			width = target.attr('data-width') || this._core.settings.videoWidth,
12197			height = target.attr('data-height') || this._core.settings.videoHeight,
12198			url = target.attr('href');
12199
12200		if (url) {
12201			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+)?/);
12202
12203			if (id[3].indexOf('youtu') > -1) {
12204				type = 'youtube';
12205			} else if (id[3].indexOf('vimeo') > -1) {
12206				type = 'vimeo';
12207			} else {
12208				throw new Error('Video URL not supported.');
12209			}
12210			id = id[6];
12211		} else {
12212			throw new Error('Missing video URL.');
12213		}
12214
12215		this._videos[url] = {
12216			type: type,
12217			id: id,
12218			width: width,
12219			height: height
12220		};
12221
12222		item.attr('data-video', url);
12223
12224		this.thumbnail(target, this._videos[url]);
12225	};
12226
12227	/**
12228	 * Creates video thumbnail.
12229	 * @protected
12230	 * @param {jQuery} target - The target containing the video data.
12231	 * @param {Object} info - The video info object.
12232	 * @see `fetch`
12233	 */
12234	Video.prototype.thumbnail = function(target, video) {
12235		var tnLink,
12236			icon,
12237			path,
12238			dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '',
12239			customTn = target.find('img'),
12240			srcType = 'src',
12241			lazyClass = '',
12242			settings = this._core.settings,
12243			create = function(path) {
12244				icon = '<div class="owl-video-play-icon"></div>';
12245
12246				if (settings.lazyLoad) {
12247					tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>';
12248				} else {
12249					tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>';
12250				}
12251				target.after(tnLink);
12252				target.after(icon);
12253			};
12254
12255		// wrap video content into owl-video-wrapper div
12256		target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>');
12257
12258		if (this._core.settings.lazyLoad) {
12259			srcType = 'data-src';
12260			lazyClass = 'owl-lazy';
12261		}
12262
12263		// custom thumbnail
12264		if (customTn.length) {
12265			create(customTn.attr(srcType));
12266			customTn.remove();
12267			return false;
12268		}
12269
12270		if (video.type === 'youtube') {
12271			path = "http://img.youtube.com/vi/" + video.id + "/hqdefault.jpg";
12272			create(path);
12273		} else if (video.type === 'vimeo') {
12274			$.ajax({
12275				type: 'GET',
12276				url: 'http://vimeo.com/api/v2/video/' + video.id + '.json',
12277				jsonp: 'callback',
12278				dataType: 'jsonp',
12279				success: function(data) {
12280					path = data[0].thumbnail_large;
12281					create(path);
12282				}
12283			});
12284		}
12285	};
12286
12287	/**
12288	 * Stops the current video.
12289	 * @public
12290	 */
12291	Video.prototype.stop = function() {
12292		this._core.trigger('stop', null, 'video');
12293		this._playing.find('.owl-video-frame').remove();
12294		this._playing.removeClass('owl-video-playing');
12295		this._playing = null;
12296		this._core.leave('playing');
12297		this._core.trigger('stopped', null, 'video');
12298	};
12299
12300	/**
12301	 * Starts the current video.
12302	 * @public
12303	 * @param {Event} event - The event arguments.
12304	 */
12305	Video.prototype.play = function(event) {
12306		var target = $(event.target),
12307			item = target.closest('.' + this._core.settings.itemClass),
12308			video = this._videos[item.attr('data-video')],
12309			width = video.width || '100%',
12310			height = video.height || this._core.$stage.height(),
12311			html;
12312
12313		if (this._playing) {
12314			return;
12315		}
12316
12317		this._core.enter('playing');
12318		this._core.trigger('play', null, 'video');
12319
12320		item = this._core.items(this._core.relative(item.index()));
12321
12322		this._core.reset(item.index());
12323
12324		if (video.type === 'youtube') {
12325			html = '<iframe width="' + width + '" height="' + height + '" src="http://www.youtube.com/embed/' +
12326				video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>';
12327		} else if (video.type === 'vimeo') {
12328			html = '<iframe src="http://player.vimeo.com/video/' + video.id +
12329				'?autoplay=1" width="' + width + '" height="' + height +
12330				'" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>';
12331		}
12332
12333		$('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video'));
12334
12335		this._playing = item.addClass('owl-video-playing');
12336	};
12337
12338	/**
12339	 * Checks whether an video is currently in full screen mode or not.
12340	 * @todo Bad style because looks like a readonly method but changes members.
12341	 * @protected
12342	 * @returns {Boolean}
12343	 */
12344	Video.prototype.isInFullScreen = function() {
12345		var element = document.fullscreenElement || document.mozFullScreenElement ||
12346				document.webkitFullscreenElement;
12347
12348		return element && $(element).parent().hasClass('owl-video-frame');
12349	};
12350
12351	/**
12352	 * Destroys the plugin.
12353	 */
12354	Video.prototype.destroy = function() {
12355		var handler, property;
12356
12357		this._core.$element.off('click.owl.video');
12358
12359		for (handler in this._handlers) {
12360			this._core.$element.off(handler, this._handlers[handler]);
12361		}
12362		for (property in Object.getOwnPropertyNames(this)) {
12363			typeof this[property] != 'function' && (this[property] = null);
12364		}
12365	};
12366
12367	$.fn.owlCarousel.Constructor.Plugins.Video = Video;
12368
12369})(window.Zepto || window.jQuery, window, document);
12370
12371/**
12372 * Animate Plugin
12373 * @version 2.0.0-beta.3
12374 * @author Bartosz Wojciechowski
12375 * @license The MIT License (MIT)
12376 */
12377;(function($, window, document, undefined) {
12378
12379	/**
12380	 * Creates the animate plugin.
12381	 * @class The Navigation Plugin
12382	 * @param {Owl} scope - The Owl Carousel
12383	 */
12384	var Animate = function(scope) {
12385		this.core = scope;
12386		this.core.options = $.extend({}, Animate.Defaults, this.core.options);
12387		this.swapping = true;
12388		this.previous = undefined;
12389		this.next = undefined;
12390
12391		this.handlers = {
12392			'change.owl.carousel': $.proxy(function(e) {
12393				if (e.namespace && e.property.name == 'position') {
12394					this.previous = this.core.current();
12395					this.next = e.property.value;
12396				}
12397			}, this),
12398			'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) {
12399				if (e.namespace) {
12400					this.swapping = e.type == 'translated';
12401				}
12402			}, this),
12403			'translate.owl.carousel': $.proxy(function(e) {
12404				if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) {
12405					this.swap();
12406				}
12407			}, this)
12408		};
12409
12410		this.core.$element.on(this.handlers);
12411	};
12412
12413	/**
12414	 * Default options.
12415	 * @public
12416	 */
12417	Animate.Defaults = {
12418		animateOut: false,
12419		animateIn: false
12420	};
12421
12422	/**
12423	 * Toggles the animation classes whenever an translations starts.
12424	 * @protected
12425	 * @returns {Boolean|undefined}
12426	 */
12427	Animate.prototype.swap = function() {
12428
12429		if (this.core.settings.items !== 1) {
12430			return;
12431		}
12432
12433		if (!$.support.animation || !$.support.transition) {
12434			return;
12435		}
12436
12437		this.core.speed(0);
12438
12439		var left,
12440			clear = $.proxy(this.clear, this),
12441			previous = this.core.$stage.children().eq(this.previous),
12442			next = this.core.$stage.children().eq(this.next),
12443			incoming = this.core.settings.animateIn,
12444			outgoing = this.core.settings.animateOut;
12445
12446		if (this.core.current() === this.previous) {
12447			return;
12448		}
12449
12450		if (outgoing) {
12451			left = this.core.coordinates(this.previous) - this.core.coordinates(this.next);
12452			previous.css( { 'left': left + 'px' } )
12453				.addClass('animated owl-animated-out')
12454				.addClass(outgoing)
12455				.on($.support.animation.end, clear);
12456		}
12457
12458		if (incoming) {
12459			next.addClass('animated owl-animated-in')
12460				.addClass(incoming)
12461				.on($.support.animation.end, clear);
12462		}
12463	};
12464
12465	Animate.prototype.clear = function(e) {
12466		if ($(e.target).hasClass('animated')) {
12467			$(e.target).css( { 'left': '' } )
12468				.removeClass('animated owl-animated-out owl-animated-in')
12469				.removeClass(this.core.settings.animateIn)
12470				.removeClass(this.core.settings.animateOut);
12471			this.core.onTransitionEnd();
12472		}
12473	};
12474
12475	/**
12476	 * Destroys the plugin.
12477	 * @public
12478	 */
12479	Animate.prototype.destroy = function() {
12480		var handler, property;
12481
12482		for (handler in this.handlers) {
12483			this.core.$element.off(handler, this.handlers[handler]);
12484		}
12485		for (property in Object.getOwnPropertyNames(this)) {
12486			typeof this[property] != 'function' && (this[property] = null);
12487		}
12488	};
12489
12490	$.fn.owlCarousel.Constructor.Plugins.Animate = Animate;
12491
12492})(window.Zepto || window.jQuery, window, document);
12493
12494/**
12495 * Autoplay Plugin
12496 * @version 2.0.0-beta.3
12497 * @author Bartosz Wojciechowski
12498 * @author Artus Kolanowski
12499 * @license The MIT License (MIT)
12500 */
12501;(function($, window, document, undefined) {
12502
12503	/**
12504	 * Creates the autoplay plugin.
12505	 * @class The Autoplay Plugin
12506	 * @param {Owl} scope - The Owl Carousel
12507	 */
12508	var Autoplay = function(carousel) {
12509		/**
12510		 * Reference to the core.
12511		 * @protected
12512		 * @type {Owl}
12513		 */
12514		this._core = carousel;
12515
12516		/**
12517		 * The autoplay interval.
12518		 * @type {Number}
12519		 */
12520		this._interval = null;
12521
12522		/**
12523		 * Indicates whenever the autoplay is paused.
12524		 * @type {Boolean}
12525		 */
12526		this._paused = false;
12527
12528		/**
12529		 * All event handlers.
12530		 * @protected
12531		 * @type {Object}
12532		 */
12533		this._handlers = {
12534			'changed.owl.carousel': $.proxy(function(e) {
12535				if (e.namespace && e.property.name === 'settings') {
12536					if (this._core.settings.autoplay) {
12537						this.play();
12538					} else {
12539						this.stop();
12540					}
12541				}
12542			}, this),
12543			'initialized.owl.carousel': $.proxy(function(e) {
12544				if (e.namespace && this._core.settings.autoplay) {
12545					this.play();
12546				}
12547			}, this),
12548			'play.owl.autoplay': $.proxy(function(e, t, s) {
12549				if (e.namespace) {
12550					this.play(t, s);
12551				}
12552			}, this),
12553			'stop.owl.autoplay': $.proxy(function(e) {
12554				if (e.namespace) {
12555					this.stop();
12556				}
12557			}, this),
12558			'mouseover.owl.autoplay': $.proxy(function() {
12559				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
12560					this.pause();
12561				}
12562			}, this),
12563			'mouseleave.owl.autoplay': $.proxy(function() {
12564				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
12565					this.play();
12566				}
12567			}, this)
12568		};
12569
12570		// register event handlers
12571		this._core.$element.on(this._handlers);
12572
12573		// set default options
12574		this._core.options = $.extend({}, Autoplay.Defaults, this._core.options);
12575	};
12576
12577	/**
12578	 * Default options.
12579	 * @public
12580	 */
12581	Autoplay.Defaults = {
12582		autoplay: false,
12583		autoplayTimeout: 5000,
12584		autoplayHoverPause: false,
12585		autoplaySpeed: false
12586	};
12587
12588	/**
12589	 * Starts the autoplay.
12590	 * @public
12591	 * @param {Number} [timeout] - The interval before the next animation starts.
12592	 * @param {Number} [speed] - The animation speed for the animations.
12593	 */
12594	Autoplay.prototype.play = function(timeout, speed) {
12595		this._paused = false;
12596
12597		if (this._core.is('rotating')) {
12598			return;
12599		}
12600
12601		this._core.enter('rotating');
12602
12603		this._interval = window.setInterval($.proxy(function() {
12604			if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) {
12605				return;
12606			}
12607			this._core.next(speed || this._core.settings.autoplaySpeed);
12608		}, this), timeout || this._core.settings.autoplayTimeout);
12609	};
12610
12611	/**
12612	 * Stops the autoplay.
12613	 * @public
12614	 */
12615	Autoplay.prototype.stop = function() {
12616		if (!this._core.is('rotating')) {
12617			return;
12618		}
12619
12620		window.clearInterval(this._interval);
12621		this._core.leave('rotating');
12622	};
12623
12624	/**
12625	 * Stops the autoplay.
12626	 * @public
12627	 */
12628	Autoplay.prototype.pause = function() {
12629		if (!this._core.is('rotating')) {
12630			return;
12631		}
12632
12633		this._paused = true;
12634	};
12635
12636	/**
12637	 * Destroys the plugin.
12638	 */
12639	Autoplay.prototype.destroy = function() {
12640		var handler, property;
12641
12642		this.stop();
12643
12644		for (handler in this._handlers) {
12645			this._core.$element.off(handler, this._handlers[handler]);
12646		}
12647		for (property in Object.getOwnPropertyNames(this)) {
12648			typeof this[property] != 'function' && (this[property] = null);
12649		}
12650	};
12651
12652	$.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay;
12653
12654})(window.Zepto || window.jQuery, window, document);
12655
12656/**
12657 * Navigation Plugin
12658 * @version 2.0.0-beta.3
12659 * @author Artus Kolanowski
12660 * @license The MIT License (MIT)
12661 */
12662;(function($, window, document, undefined) {
12663	'use strict';
12664
12665	/**
12666	 * Creates the navigation plugin.
12667	 * @class The Navigation Plugin
12668	 * @param {Owl} carousel - The Owl Carousel.
12669	 */
12670	var Navigation = function(carousel) {
12671		/**
12672		 * Reference to the core.
12673		 * @protected
12674		 * @type {Owl}
12675		 */
12676		this._core = carousel;
12677
12678		/**
12679		 * Indicates whether the plugin is initialized or not.
12680		 * @protected
12681		 * @type {Boolean}
12682		 */
12683		this._initialized = false;
12684
12685		/**
12686		 * The current paging indexes.
12687		 * @protected
12688		 * @type {Array}
12689		 */
12690		this._pages = [];
12691
12692		/**
12693		 * All DOM elements of the user interface.
12694		 * @protected
12695		 * @type {Object}
12696		 */
12697		this._controls = {};
12698
12699		/**
12700		 * Markup for an indicator.
12701		 * @protected
12702		 * @type {Array.<String>}
12703		 */
12704		this._templates = [];
12705
12706		/**
12707		 * The carousel element.
12708		 * @type {jQuery}
12709		 */
12710		this.$element = this._core.$element;
12711
12712		/**
12713		 * Overridden methods of the carousel.
12714		 * @protected
12715		 * @type {Object}
12716		 */
12717		this._overrides = {
12718			next: this._core.next,
12719			prev: this._core.prev,
12720			to: this._core.to
12721		};
12722
12723		/**
12724		 * All event handlers.
12725		 * @protected
12726		 * @type {Object}
12727		 */
12728		this._handlers = {
12729			'prepared.owl.carousel': $.proxy(function(e) {
12730				if (e.namespace && this._core.settings.dotsData) {
12731					this._templates.push('<div class="' + this._core.settings.dotClass + '">' +
12732						$(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>');
12733				}
12734			}, this),
12735			'added.owl.carousel': $.proxy(function(e) {
12736				if (e.namespace && this._core.settings.dotsData) {
12737					this._templates.splice(e.position, 0, this._templates.pop());
12738				}
12739			}, this),
12740			'remove.owl.carousel': $.proxy(function(e) {
12741				if (e.namespace && this._core.settings.dotsData) {
12742					this._templates.splice(e.position, 1);
12743				}
12744			}, this),
12745			'changed.owl.carousel': $.proxy(function(e) {
12746				if (e.namespace && e.property.name == 'position') {
12747					this.draw();
12748				}
12749			}, this),
12750			'initialized.owl.carousel': $.proxy(function(e) {
12751				if (e.namespace && !this._initialized) {
12752					this._core.trigger('initialize', null, 'navigation');
12753					this.initialize();
12754					this.update();
12755					this.draw();
12756					this._initialized = true;
12757					this._core.trigger('initialized', null, 'navigation');
12758				}
12759			}, this),
12760			'refreshed.owl.carousel': $.proxy(function(e) {
12761				if (e.namespace && this._initialized) {
12762					this._core.trigger('refresh', null, 'navigation');
12763					this.update();
12764					this.draw();
12765					this._core.trigger('refreshed', null, 'navigation');
12766				}
12767			}, this)
12768		};
12769
12770		// set default options
12771		this._core.options = $.extend({}, Navigation.Defaults, this._core.options);
12772
12773		// register event handlers
12774		this.$element.on(this._handlers);
12775	};
12776
12777	/**
12778	 * Default options.
12779	 * @public
12780	 * @todo Rename `slideBy` to `navBy`
12781	 */
12782	Navigation.Defaults = {
12783		nav: false,
12784		navText: [ 'prev', 'next' ],
12785		navSpeed: false,
12786		navElement: 'div',
12787		navContainer: false,
12788		navContainerClass: 'owl-nav',
12789		navClass: [ 'owl-prev', 'owl-next' ],
12790		slideBy: 1,
12791		dotClass: 'owl-dot',
12792		dotsClass: 'owl-dots',
12793		dots: true,
12794		dotsEach: false,
12795		dotsData: false,
12796		dotsSpeed: false,
12797		dotsContainer: false
12798	};
12799
12800	/**
12801	 * Initializes the layout of the plugin and extends the carousel.
12802	 * @protected
12803	 */
12804	Navigation.prototype.initialize = function() {
12805		var override,
12806			settings = this._core.settings;
12807
12808		// create DOM structure for relative navigation
12809		this._controls.$relative = (settings.navContainer ? $(settings.navContainer)
12810			: $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled');
12811
12812		this._controls.$previous = $('<' + settings.navElement + '>')
12813			.addClass(settings.navClass[0])
12814			.html(settings.navText[0])
12815			.prependTo(this._controls.$relative)
12816			.on('click', $.proxy(function(e) {
12817				this.prev(settings.navSpeed);
12818			}, this));
12819		this._controls.$next = $('<' + settings.navElement + '>')
12820			.addClass(settings.navClass[1])
12821			.html(settings.navText[1])
12822			.appendTo(this._controls.$relative)
12823			.on('click', $.proxy(function(e) {
12824				this.next(settings.navSpeed);
12825			}, this));
12826
12827		// create DOM structure for absolute navigation
12828		if (!settings.dotsData) {
12829			this._templates = [ $('<div>')
12830				.addClass(settings.dotClass)
12831				.append($('<span>'))
12832				.prop('outerHTML') ];
12833		}
12834
12835		this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer)
12836			: $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled');
12837
12838		this._controls.$absolute.on('click', 'div', $.proxy(function(e) {
12839			var index = $(e.target).parent().is(this._controls.$absolute)
12840				? $(e.target).index() : $(e.target).parent().index();
12841
12842			e.preventDefault();
12843
12844			this.to(index, settings.dotsSpeed);
12845		}, this));
12846
12847		// override public methods of the carousel
12848		for (override in this._overrides) {
12849			this._core[override] = $.proxy(this[override], this);
12850		}
12851	};
12852
12853	/**
12854	 * Destroys the plugin.
12855	 * @protected
12856	 */
12857	Navigation.prototype.destroy = function() {
12858		var handler, control, property, override;
12859
12860		for (handler in this._handlers) {
12861			this.$element.off(handler, this._handlers[handler]);
12862		}
12863		for (control in this._controls) {
12864			this._controls[control].remove();
12865		}
12866		for (override in this.overides) {
12867			this._core[override] = this._overrides[override];
12868		}
12869		for (property in Object.getOwnPropertyNames(this)) {
12870			typeof this[property] != 'function' && (this[property] = null);
12871		}
12872	};
12873
12874	/**
12875	 * Updates the internal state.
12876	 * @protected
12877	 */
12878	Navigation.prototype.update = function() {
12879		var i, j, k,
12880			lower = this._core.clones().length / 2,
12881			upper = lower + this._core.items().length,
12882			maximum = this._core.maximum(true),
12883			settings = this._core.settings,
12884			size = settings.center || settings.autoWidth || settings.dotsData
12885				? 1 : settings.dotsEach || settings.items;
12886
12887		if (settings.slideBy !== 'page') {
12888			settings.slideBy = Math.min(settings.slideBy, settings.items);
12889		}
12890
12891		if (settings.dots || settings.slideBy == 'page') {
12892			this._pages = [];
12893
12894			for (i = lower, j = 0, k = 0; i < upper; i++) {
12895				if (j >= size || j === 0) {
12896					this._pages.push({
12897						start: Math.min(maximum, i - lower),
12898						end: i - lower + size - 1
12899					});
12900					if (Math.min(maximum, i - lower) === maximum) {
12901						break;
12902					}
12903					j = 0, ++k;
12904				}
12905				j += this._core.mergers(this._core.relative(i));
12906			}
12907		}
12908	};
12909
12910	/**
12911	 * Draws the user interface.
12912	 * @todo The option `dotsData` wont work.
12913	 * @protected
12914	 */
12915	Navigation.prototype.draw = function() {
12916		var difference,
12917			settings = this._core.settings,
12918			disabled = this._core.items().length <= settings.items,
12919			index = this._core.relative(this._core.current()),
12920			loop = settings.loop || settings.rewind;
12921
12922		this._controls.$relative.toggleClass('disabled', !settings.nav || disabled);
12923
12924		if (settings.nav) {
12925			this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true));
12926			this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true));
12927		}
12928
12929		this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled);
12930
12931		if (settings.dots) {
12932			difference = this._pages.length - this._controls.$absolute.children().length;
12933
12934			if (settings.dotsData && difference !== 0) {
12935				this._controls.$absolute.html(this._templates.join(''));
12936			} else if (difference > 0) {
12937				this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0]));
12938			} else if (difference < 0) {
12939				this._controls.$absolute.children().slice(difference).remove();
12940			}
12941
12942			this._controls.$absolute.find('.active').removeClass('active');
12943			this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active');
12944		}
12945	};
12946
12947	/**
12948	 * Extends event data.
12949	 * @protected
12950	 * @param {Event} event - The event object which gets thrown.
12951	 */
12952	Navigation.prototype.onTrigger = function(event) {
12953		var settings = this._core.settings;
12954
12955		event.page = {
12956			index: $.inArray(this.current(), this._pages),
12957			count: this._pages.length,
12958			size: settings && (settings.center || settings.autoWidth || settings.dotsData
12959				? 1 : settings.dotsEach || settings.items)
12960		};
12961	};
12962
12963	/**
12964	 * Gets the current page position of the carousel.
12965	 * @protected
12966	 * @returns {Number}
12967	 */
12968	Navigation.prototype.current = function() {
12969		var current = this._core.relative(this._core.current());
12970		return $.grep(this._pages, $.proxy(function(page, index) {
12971			return page.start <= current && page.end >= current;
12972		}, this)).pop();
12973	};
12974
12975	/**
12976	 * Gets the current succesor/predecessor position.
12977	 * @protected
12978	 * @returns {Number}
12979	 */
12980	Navigation.prototype.getPosition = function(successor) {
12981		var position, length,
12982			settings = this._core.settings;
12983
12984		if (settings.slideBy == 'page') {
12985			position = $.inArray(this.current(), this._pages);
12986			length = this._pages.length;
12987			successor ? ++position : --position;
vendor: 5,670 bytes, lines 12988-13212
12988			position = this._pages[((position % length) + length) % length].start;
12989		} else {
12990			position = this._core.relative(this._core.current());
12991			length = this._core.items().length;
12992			successor ? position += settings.slideBy : position -= settings.slideBy;
12993		}
12994
12995		return position;
12996	};
12997
12998	/**
12999	 * Slides to the next item or page.
13000	 * @public
13001	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
13002	 */
13003	Navigation.prototype.next = function(speed) {
13004		$.proxy(this._overrides.to, this._core)(this.getPosition(true), speed);
13005	};
13006
13007	/**
13008	 * Slides to the previous item or page.
13009	 * @public
13010	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
13011	 */
13012	Navigation.prototype.prev = function(speed) {
13013		$.proxy(this._overrides.to, this._core)(this.getPosition(false), speed);
13014	};
13015
13016	/**
13017	 * Slides to the specified item or page.
13018	 * @public
13019	 * @param {Number} position - The position of the item or page.
13020	 * @param {Number} [speed] - The time in milliseconds for the transition.
13021	 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not.
13022	 */
13023	Navigation.prototype.to = function(position, speed, standard) {
13024		var length;
13025
13026		if (!standard) {
13027			length = this._pages.length;
13028			$.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed);
13029		} else {
13030			$.proxy(this._overrides.to, this._core)(position, speed);
13031		}
13032	};
13033
13034	$.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation;
13035
13036})(window.Zepto || window.jQuery, window, document);
13037
13038/**
13039 * Hash Plugin
13040 * @version 2.0.0-beta.3
13041 * @author Artus Kolanowski
13042 * @license The MIT License (MIT)
13043 */
13044;(function($, window, document, undefined) {
13045	'use strict';
13046
13047	/**
13048	 * Creates the hash plugin.
13049	 * @class The Hash Plugin
13050	 * @param {Owl} carousel - The Owl Carousel
13051	 */
13052	var Hash = function(carousel) {
13053		/**
13054		 * Reference to the core.
13055		 * @protected
13056		 * @type {Owl}
13057		 */
13058		this._core = carousel;
13059
13060		/**
13061		 * Hash index for the items.
13062		 * @protected
13063		 * @type {Object}
13064		 */
13065		this._hashes = {};
13066
13067		/**
13068		 * The carousel element.
13069		 * @type {jQuery}
13070		 */
13071		this.$element = this._core.$element;
13072
13073		/**
13074		 * All event handlers.
13075		 * @protected
13076		 * @type {Object}
13077		 */
13078		this._handlers = {
13079			'initialized.owl.carousel': $.proxy(function(e) {
13080				if (e.namespace && this._core.settings.startPosition === 'URLHash') {
13081					$(window).trigger('hashchange.owl.navigation');
13082				}
13083			}, this),
13084			'prepared.owl.carousel': $.proxy(function(e) {
13085				if (e.namespace) {
13086					var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash');
13087
13088					if (!hash) {
13089						return;
13090					}
13091
13092					this._hashes[hash] = e.content;
13093				}
13094			}, this),
13095			'changed.owl.carousel': $.proxy(function(e) {
13096				if (e.namespace && e.property.name === 'position') {
13097					var current = this._core.items(this._core.relative(this._core.current())),
13098						hash = $.map(this._hashes, function(item, hash) {
13099							return item === current ? hash : null;
13100						}).join();
13101
13102					if (!hash || window.location.hash.slice(1) === hash) {
13103						return;
13104					}
13105
13106					window.location.hash = hash;
13107				}
13108			}, this)
13109		};
13110
13111		// set default options
13112		this._core.options = $.extend({}, Hash.Defaults, this._core.options);
13113
13114		// register the event handlers
13115		this.$element.on(this._handlers);
13116
13117		// register event listener for hash navigation
13118		$(window).on('hashchange.owl.navigation', $.proxy(function(e) {
13119			var hash = window.location.hash.substring(1),
13120				items = this._core.$stage.children(),
13121				position = this._hashes[hash] && items.index(this._hashes[hash]);
13122
13123			if (position === undefined || position === this._core.current()) {
13124				return;
13125			}
13126
13127			this._core.to(this._core.relative(position), false, true);
13128		}, this));
13129	};
13130
13131	/**
13132	 * Default options.
13133	 * @public
13134	 */
13135	Hash.Defaults = {
13136		URLhashListener: false
13137	};
13138
13139	/**
13140	 * Destroys the plugin.
13141	 * @public
13142	 */
13143	Hash.prototype.destroy = function() {
13144		var handler, property;
13145
13146		$(window).off('hashchange.owl.navigation');
13147
13148		for (handler in this._handlers) {
13149			this._core.$element.off(handler, this._handlers[handler]);
13150		}
13151		for (property in Object.getOwnPropertyNames(this)) {
13152			typeof this[property] != 'function' && (this[property] = null);
13153		}
13154	};
13155
13156	$.fn.owlCarousel.Constructor.Plugins.Hash = Hash;
13157
13158})(window.Zepto || window.jQuery, window, document);
13159
13160/**
13161 * Support Plugin
13162 *
13163 * @version 2.0.0-beta.3
13164 * @author Vivid Planet Software GmbH
13165 * @author Artus Kolanowski
13166 * @license The MIT License (MIT)
13167 */
13168;(function($, window, document, undefined) {
13169
13170	var style = $('<support>').get(0).style,
13171		prefixes = 'Webkit Moz O ms'.split(' '),
13172		events = {
13173			transition: {
13174				end: {
13175					WebkitTransition: 'webkitTransitionEnd',
13176					MozTransition: 'transitionend',
13177					OTransition: 'oTransitionEnd',
13178					transition: 'transitionend'
13179				}
13180			},
13181			animation: {
13182				end: {
13183					WebkitAnimation: 'webkitAnimationEnd',
13184					MozAnimation: 'animationend',
13185					OAnimation: 'oAnimationEnd',
13186					animation: 'animationend'
13187				}
13188			}
13189		},
13190		tests = {
13191			csstransforms: function() {
13192				return !!test('transform');
13193			},
13194			csstransforms3d: function() {
13195				return !!test('perspective');
13196			},
13197			csstransitions: function() {
13198				return !!test('transition');
13199			},
13200			cssanimations: function() {
13201				return !!test('animation');
13202			}
13203		};
13204
13205	function test(property, prefixed) {
13206		var result = false,
13207			upper = property.charAt(0).toUpperCase() + property.slice(1);
13208
13209		$.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) {
13210			if (style[property] !== undefined) {
13211				result = prefixed ? property : true;
13212				return false;
13213			}
13214		});
13215
13216		return result;
13217	}
13218
13219	function prefixed(property) {
13220		return test(property, true);
13221	}
13222
13223	if (tests.csstransitions()) {
13224		/* jshint -W053 */
13225		$.support.transition = new String(prefixed('transition'))
13226		$.support.transition.end = events.transition.end[ $.support.transition ];
13227	}
13228
13229	if (tests.cssanimations()) {
13230		/* jshint -W053 */
13231		$.support.animation = new String(prefixed('animation'))
13232		$.support.animation.end = events.animation.end[ $.support.animation ];
13233	}
13234
13235	if (tests.csstransforms()) {
13236		/* jshint -W053 */
13237		$.support.transform = new String(prefixed('transform'));
13238		$.support.transform3d = tests.csstransforms3d();
13239	}
13240
13241})(window.Zepto || window.jQuery, window, document);
13242
13243(function(window, document, undefined) {
13244
13245    /**
13246     * Find the absolute position of an element
13247     */
13248    var absPos = function(element) {
13249        var offsetLeft, offsetTop;
13250        offsetLeft = offsetTop = 0;
13251        if (element.offsetParent) {
13252            do {
13253                offsetLeft += element.offsetLeft;
13254                offsetTop += element.offsetTop;
13255            } while (element = element.offsetParent);
13256        }
13257        return [offsetLeft, offsetTop];
13258    };
13259
13260    /**
13261     * @constructor Progress Circle class
13262     * @param params.canvas Canvas on which the circles will be drawn.
13263     * @param params.minRadius Inner radius of the innermost circle, in px.
13264     * @param params.arcWidth Width of each circle(to be more accurate, ring).
13265     * @param params.gapWidth Space between each circle.
13266     * @param params.centerX X coordinate of the center of circles.
13267     * @param params.centerY Y coordinate of the center of circles.
13268     * @param params.infoLineBaseAngle Base angle of the info line.
13269     * @param params.infoLineAngleInterval Angles between the info lines.
13270     */
13271    var ProgressCircle = function(params) {
13272        this.canvas = params.canvas;
13273        this.minRadius = params.minRadius || 15;
13274        this.arcWidth = params.arcWidth || 5;
13275        this.gapWidth = params.gapWidth || 3;
13276        this.centerX = params.centerX || this.canvas.width / 2;
13277        this.centerY = params.centerY || this.canvas.height / 2;
13278        this.infoLineLength = params.infoLineLength || 60;
13279        this.horizLineLength = params.horizLineLength || 10;
13280        this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8;
13281        this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6;
13282
13283        this.context = this.canvas.getContext('2d');
13284
13285        this.width = this.canvas.width;
13286        this.height = this.canvas.height;
13287
13288        this.circles = [];
13289        this.runningCount = 0;
13290    };
13291
13292    ProgressCircle.prototype = {
13293        constructor: ProgressCircle,
13294
13295        /**
13296         * @method Adds an progress monitor entry.
13297         * @param params.fillColor Color to fill in the circle.
13298         * @param params.outlineColor Color to outline the circle.
13299         * @param params.progressListener Callback function to fetch the progress.
13300         * @param params.infoListener Callback function to fetch the info.
13301         * @returns this
13302         */
13303        addEntry: function(params) {
13304            this.circles.push(new Circle({
13305                canvas: this.canvas,
13306                context: this.context,
13307                centerX: this.centerX,
13308                centerY: this.centerY,
13309                innerRadius: this.minRadius + this.circles.length *
13310                    (this.gapWidth + this.arcWidth),
13311                arcWidth: this.arcWidth,
13312                infoLineLength: this.infoLineLength,
13313                horizLineLength: this.horizLineLength,
13314
13315                id: this.circles.length,
13316                fillColor: params.fillColor,
13317                outlineColor: params.outlineColor,
13318                progressListener: params.progressListener,
13319                infoListener: params.infoListener,
13320                infoLineAngle: this.infoLineBaseAngle +
13321                    this.circles.length * this.infoLineAngleInterval,
13322            }));
13323
13324            return this;
13325        },
13326
13327        /**
13328         * @method Starts the monitor and updates with the given interval.
13329         * @param interval Interval between updates, in millisecond.
13330         * @returns this
13331         */
13332        start: function(interval) {
13333            var self = this;
13334            this.timer = setInterval(function() {
13335                self._update();
13336            }, interval || 33);
13337
13338            return this;
13339        },
13340
13341        /**
13342         * @method Stop the animation.
13343         */
13344        stop: function() {
13345            clearTimeout(this.timer);
13346        },
13347
13348        /**
13349         * @private
13350         * @method Call update on each circle and redraw them.
13351         * @returns this
13352         */
13353        _update: function() {
13354            this._clear();
13355            this.circles.forEach(function(circle, idx, array) {
13356                circle.update();
13357            });
13358
13359            return this;
13360        },
13361
13362        /**
13363         * @private
13364         * @method Clear the canvas.
13365         * @returns this
13366         */
13367        _clear: function() {
13368            this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
13369
13370            return this;
13371        },
13372
13373    };
13374
13375    /**
13376     * @private
13377     * @class Individual progress circle.
13378     * @param params.canvas Canvas on which the circle will be drawn.
13379     * @param params.context Context of the canvas.
13380     * @param params.innerRadius Inner radius of the circle, in px.
13381     * @param params.arcWidth Width of each arc(circle).
13382     * @param params.gapWidth Distance between each arc.
13383     * @param params.centerX X coordinate of the center of circles.
13384     * @param params.centerY Y coordinate of the center of circles.
13385     * @param params.fillColor Color to fill in the circle.
13386     * @param params.outlineColor Color to outline the circle.
13387     * @param params.progressListener Callback function to fetch the progress.
13388     * @param params.infoListener Callback function to fetch the info.
13389     * @param params.infoLineAngle Angle of info line.
13390     */
13391    var Circle = function(params) {
13392        this.id = params.id;
13393        this.canvas = params.canvas;
13394        this.context = params.context;
13395        this.centerX = params.centerX;
13396        this.centerY = params.centerY;
13397        this.arcWidth = params.arcWidth;
13398        this.innerRadius = params.innerRadius || 0;
13399        this.fillColor = params.fillColor || '#fff';
13400        this.outlineColor = params.outlineColor || this.fillColor;
13401        this.progressListener = params.progressListener;
13402        this.infoLineLength = params.infoLineLength || 250;
13403        this.horizLineLength = params.horizLineLength || 50;
13404        this.infoListener = params.infoListener;
13405        this.infoLineAngle = params.infoLineAngle;
13406
13407        this.outerRadius = this.innerRadius + this.arcWidth;
13408
13409        // If the info listener is not registered, then don't calculate
13410        // the related coordinates
13411        if (!this.infoListener) return;
13412
13413        // calculate the info-line turning points
13414        var angle = this.infoLineAngle,
13415            arcDistance = (this.innerRadius + this.outerRadius) / 2,
13416
13417            sinA = Math.sin(angle),
13418            cosA = Math.cos(angle);
13419
13420        this.infoLineStartX = this.centerX + sinA * arcDistance;
13421        this.infoLineStartY = this.centerY - cosA * arcDistance;
13422
13423        this.infoLineMidX = this.centerX + sinA * this.infoLineLength;
13424        this.infoLineMidY = this.centerY - cosA * this.infoLineLength;
13425
13426        this.infoLineEndX = this.infoLineMidX +
13427             (sinA < 0 ? -this.horizLineLength : this.horizLineLength);
13428        this.infoLineEndY = this.infoLineMidY;
13429
13430        var infoText = document.createElement('div'),
13431            style = infoText.style;
13432
13433        style.color = this.fillColor;
13434        style.position = 'absolute';
13435        style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px';
13436        // style.top will be calculated in the `drawInfo` method. Since
13437        // user may want to change the size of the font, so the top offset
13438        // must be updated in each loop.
13439        infoText.className = 'ProgressCircleInfo'; // For css styling
13440        infoText.id = 'progress_circle_info_' + this.id;
13441        document.body.appendChild(infoText);
13442        this.infoText = infoText;
13443    };
13444
13445    Circle.prototype = {
13446        constructor: Circle,
13447
13448        update: function() {
13449            this.progress = this.progressListener();
13450            this._draw();
13451
13452            if (this.infoListener) {
13453                this.info = this.infoListener();
13454                this._drawInfo();
13455            }
13456        },
13457
13458        /**
13459         * @private
13460         * @method Draw the circle on the canvas.
13461         * @returns this
13462         */
13463        _draw: function() {
13464            var ctx = this.context,
13465
13466                ANGLE_OFFSET = -Math.PI / 2,
13467
13468                startAngle = 0 + ANGLE_OFFSET,
13469                endAngle= startAngle + this.progress * Math.PI * 2,
13470
13471                x = this.centerX,
13472                y = this.centerY,
13473
13474                innerRadius = this.innerRadius - this.arcWidth - 1,
13475                outerRadius = this.outerRadius - this.arcWidth - 1;
13476
13477            ctx.fillStyle = this.fillColor;
13478            ctx.strokeStyle = this.outlineColor;
13479
13480            ctx.beginPath();
13481            ctx.arc(x, y, innerRadius, startAngle, endAngle, false);
13482            ctx.arc(x, y, outerRadius, endAngle, startAngle, true);
13483            ctx.closePath();
13484            ctx.stroke();
13485            ctx.fill();
13486
13487            return this;
13488        },
13489
13490        /**
13491         * @private
13492         * @method Draw the info lines and info text.
13493         * @returns this
13494         */
13495        _drawInfo: function() {
13496
13497            var pointList, lineHeight;
13498
13499            pointList = [
13500                [this.infoLineStartX, this.infoLineStartY],
13501                [this.infoLineMidX, this.infoLineMidY],
13502                [this.infoLineEndX, this.infoLineEndY],
13503            ];
13504            this._drawSegments(pointList, false);
13505
13506            this.infoText.innerHTML = this.info;
13507
13508            lineHeight = this.infoText.offsetHeight;
13509            this.infoText.style.top = this.infoLineEndY +
13510                absPos(this.canvas)[1] - lineHeight / 2 + 'px';
13511
13512            return this;
13513        },
13514
13515        /**
13516         * @private
13517         * @method Helper function to draw the segments
13518         * @param pointList An array of points in the form of [x, y].
13519         * @param close Whether to connect the first and last point.
13520         */
13521        _drawSegments: function(pointList, close) {
13522            var ctx = this.context;
13523
13524            ctx.beginPath();
13525            ctx.moveTo(pointList[0][0], pointList[0][1]);
13526            for (var i = 1; i < pointList.length; ++i) {
13527                ctx.lineTo(pointList[i][0], pointList[i][1]);
13528            }
13529
13530            if (close) {
13531                ctx.closePath();
13532            }
13533            ctx.stroke();
13534        },
13535    };
13536
13537    window.ProgressCircle = ProgressCircle;
13538
13539})(window, document);
13540
13541
13542
13543
13544/* =========================================================
13545 * jquery.vc_chart.js v1.0
13546 * =========================================================
13547 * Copyright 2013 Wpbakery
13548 *
13549 * Jquery chart plugin for the Visual Composer.
13550 * ========================================================= */
13551(function($){
13552    /**
13553     * Pie chart animated.
13554     * @param element - DOM element
13555     * @param options - settings object.
13556     * @constructor
13557     */
13558    var VcChart = function(element, options) {
13559        this.el = element;
13560        this.$el = $(this.el);
13561        this.options = $.extend({
13562            color: 'wpb_button',
13563            units: '',
13564            width: '',
13565            label_selector: '.vc_pie_chart_value',
13566            back_selector: '.vc_pie_chart_back',
13567            responsive: true
13568        }, options);
13569        this.init();
13570    };
13571    VcChart.prototype = {
13572        constructor: VcChart,
13573        _progress_v: 0,
13574        animated: false,
13575        colors: {
13576            'wpb_button': 'rgba(247, 247, 247, 1)',
13577            'btn-primary': 'rgba(0, 136, 204, 1)',
13578            'btn-info': 'rgba(88, 185, 218, 1)',
13579            'btn-success': 'rgba(106, 177, 101, 1)',
13580            'btn-warning': 'rgba(255, 153, 0, 1)',
13581            'btn-danger': 'rgba(255, 103, 91, 1)',
13582            'btn-inverse': 'rgba(85, 85, 85, 1)'
13583        },
13584        init: function() {
13585            this.setupColor();
13586            this.value = this.$el.data('pie-value')/100;
13587            this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value');
13588            this.$wrapper = $('.vc_pie_wrapper', this.$el);
13589            this.$label = $(this.options.label_selector, this.$el);
13590            this.$back = $(this.options.back_selector, this.$el);
13591            this.$canvas = this.$el.find('canvas');
13592            this.arcWidth = this.$el.data('pie-width') * 2;
13593            this.draw();
13594            this.setWayPoint();
13595            if(this.options.responsive === true) this.setResponsive();
13596            if (UNCODE.isMobile) this._progress_v = this.value;
13597        },
13598        setupColor: function() {
13599            // if(typeof this.colors[this.options.color] !== 'undefined') {
13600            //     this.color = this.colors[this.options.color];
13601            // } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) {
13602            //     this.color = this.options.color;
13603            // } else {
13604            //     this.color = 'rgba(247, 247, 247, 0.2)';
13605            // }
13606            if(typeof this.options.color !== 'undefined') {
13607                this.color = this.options.color;
13608            } else this.color = 'rgba(247, 247, 247, 0.2)';
13609
13610        },
13611        setResponsive: function() {
13612            var that = this;
13613            if (!UNCODE.isMobile) {
13614                $(window).resize(function(){
13615                    if(that.animated === true) that.circle.stop();
13616                    that.draw(true);
13617                });
13618            }
13619        },
13620          draw: function(redraw) {
13621            var w = this.$el.addClass('vc_ready').width() * 2,
13622                border_w = this.arcWidth,
13623                radius;
13624            if(!w) w = this.$el.parents(':visible').first().width()-2;
13625            //w = Math.round(w/100*80);
13626            //if (w < 250) w = 250;
13627            radius = w/2;
13628            this.$wrapper.css({"width" : (w / 2) + "px"});
13629            this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"});
13630            this.$back.css({"width" : (w / 2), "height" : (w / 2)});
13631            this.$canvas.attr({"width" : w + "px", "height" : w + "px"});
13632            this.$el.addClass('vc_ready');
13633            this.circle = new ProgressCircle({
13634                canvas: this.$canvas.get(0),
13635                minRadius: radius,
13636                arcWidth: border_w
13637            });
13638            if(redraw === true && this.animated === true) {
13639                this._progress_v = this.value;
13640                this.circle.addEntry({
13641                    fillColor: this.color,
13642                    progressListener: $.proxy(this.setProgress, this)
13643                }).start();
13644            }
13645        },
13646        setProgress: function() {
13647            if (this._progress_v >= this.value) {
13648                this.circle.stop();
13649                this.$label.html(this.label_value + this.options.units);
13650                return this._progress_v;
13651            }
13652            this._progress_v += 0.01;
13653            if (!isNaN(this.label_value)) {
13654                var label_value = this._progress_v/this.value*this.label_value;
13655                var val = Math.round(label_value) + this.options.units;
13656                this.$label.html(val);
13657            } else this.$label.html(this.label_value + this.options.units);
13658            return this._progress_v;
13659        },
13660        animate: function() {
13661            if(this.animated !== true) {
13662                this.animated = true;
13663                this.circle.addEntry({
13664                    fillColor: this.color,
13665                    progressListener: $.proxy(this.setProgress, this)
13666                }).start(5);
13667            }
13668        },
13669        setWayPoint: function() {
13670            if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) {
13671                this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' });
13672            } else {
13673                this.animate();
13674            }
13675        }
13676    };
13677    /**
13678     * jQuery plugin
13679     * @param option - object with settings
13680     * @return {*}
13681     */
13682    $.fn.vcChat = function(option, value) {
13683        return this.each(function () {
13684            var $this = $(this),
13685                data = $this.data('vc_chart'),
13686                options = typeof option === 'object' ? option : {
13687                    color: $this.data('pie-color'),
13688                    units: $this.data('pie-units')
13689                };
13690            if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options)));
13691            if (typeof option == 'string') data[option](value);
13692        });
13693    };
13694    /**
13695     * Allows users to rewrite function inside theme.
13696     */
13697    if ( typeof window['vc_pieChart'] !== 'function' ) {
13698        window.vc_pieChart = function() {
13699            $('.vc_pie_chart:visible').vcChat();
13700        }
13701    }
13702    $(document).ready(function(){
13703        !window.vc_iframe && vc_pieChart();
13704    });
13705
13706})(window.jQuery);
13707
13708
13709/* Progress bar
13710 ---------------------------------------------------------- */
13711function uncode_progress_bar() {    
13712	jQuery.each(jQuery('.vc_progress_bar'), function(index, val) {
13713		if (!UNCODE.isMobile) {
13714			new Waypoint({
13715				element: val,
13716				handler: function() {
13717					var element = jQuery(this.element);
13718					element.find('.vc_single_bar').each(function(index) {          
13719						var $this = jQuery(this),
13720							            bar = $this.find('.vc_bar'),
13721							            val = bar.data('percentage-value');          
13722						setTimeout(function() {            
13723							bar.css({
13724								"width": val + '%'
13725							});          
13726						}, index * 200);        
13727					});
13728				},
13729				offset: '80%'
13730			});
13731		} else {
13732			var element = jQuery(val);
13733			element.find('.vc_single_bar').each(function(index) {          
13734				var $this = jQuery(this),
13735					            bar = $this.find('.vc_bar'),
13736					            val = bar.data('percentage-value');          
13737				setTimeout(function() {            
13738					bar.css({
13739						"width": val + '%'
13740					});          
13741				}, index * 200);        
13742			});
13743		}
13744	});
13745};
13746uncode_progress_bar();
13747
13748/*!
13749 * jquery.counterup.js 1.0
13750 *
13751 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal
13752 * Released under the GPL v2 License
13753 *
13754 * Date: Nov 26, 2013
13755 */
13756(function($) {
13757	"use strict";
13758	$.fn.counterUp = function(options) {
13759		// Defaults
13760		var settings = $.extend({
13761			'time': 400,
13762			'delay': 10
13763		}, options);
13764		return this.each(function() {
13765			// Store the object
13766			var $this = $(this);
13767			var $settings = settings;
13768			var counterUpper = function() {
13769				var nums = [];
13770				var divisions = $settings.time / $settings.delay;
13771				var numReal = $this.text(),
13772				num = numReal;
13773				var isComma = /[0-9]+,[0-9]+/.test(num);
13774				num = num.replace(/,/g, '');
13775				var isInt = /^[0-9]+$/.test(num);
13776				var isFloat = /^[0-9]+\.[0-9]+$/.test(num);
13777				var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0;
13778				// Generate list of incremental numbers to display
13779				for (var i = divisions; i >= 1; i--) {
13780					// Preserve as int if input was int
13781					var newNum = parseInt(num / divisions * i);
13782					// Preserve float if input was float
13783					if (isFloat) {
13784						newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces);
13785					}
13786					// Preserve commas if input had commas
13787					if (isComma) {
13788						while (/(\d+)(\d{3})/.test(newNum.toString())) {
13789							newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2');
13790						}
13791					}
13792					nums.unshift(newNum);
13793				}
13794				nums.push(numReal);
13795				$this.data('counterup-nums', nums);
13796				$this.text('0');
13797				// Updates the number until we're done
13798				var f = function() {
13799					if ($this.data('counterup-nums') != null) {
13800						$this.text($this.data('counterup-nums').shift());
13801						if ($this.data('counterup-nums').length) {
13802							setTimeout($this.data('counterup-func'), $settings.delay);
13803						} else {
13804							delete $this.data('counterup-nums');
13805							$this.data('counterup-nums', null);
13806							$this.data('counterup-func', null);
13807						}
13808					}
13809				};
13810				$this.data('counterup-func', f);
13811				// Start the count up
13812				setTimeout($this.data('counterup-func'), $settings.delay);
13813			};
13814			// Perform counts when the element gets into view
13815			new Waypoint({
13816				element: this,
13817				handler: function() {
13818					counterUpper();
13819					this.destroy();
13820				},
13821				offset: '80%'
13822			});
13823		});
13824	};
13825})(jQuery);
13826
13827/*!
13828 * The Final Countdown for jQuery v2.0.4 (http://hilios.github.io/jQuery.countdown/)
13829 * Copyright (c) 2014 Edson Hilios
13830 * 
13831 * Permission is hereby granted, free of charge, to any person obtaining a copy of
13832 * this software and associated documentation files (the "Software"), to deal in
13833 * the Software without restriction, including without limitation the rights to
13834 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
13835 * the Software, and to permit persons to whom the Software is furnished to do so,
13836 * subject to the following conditions:
13837 * 
13838 * The above copyright notice and this permission notice shall be included in all
13839 * copies or substantial portions of the Software.
13840 * 
13841 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13842 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
13843 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
13844 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
13845 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
13846 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13847 */
13848!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;
13848if(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])})}});
13849
13850/*! waitForImages jQuery Plugin - v2.0.2 - 2015-05-05
13851* https://github.com/alexanderdickson/waitForImages
13852* Copyright (c) 2015 Alex Dickson; Licensed MIT */
13853;(function (factory) {
13854    if (typeof define === 'function' && define.amd) {
13855        // AMD. Register as an anonymous module.
13856        define(['jquery'], factory);
13857    } else if (typeof exports === 'object') {
13858        // CommonJS / nodejs module
13859        module.exports = factory(require('jquery'));
13860    } else {
13861        // Browser globals
13862        factory(jQuery);
13863    }
13864}(function ($) {
13865    // Namespace all events.
13866    var eventNamespace = 'waitForImages';
13867
13868    // CSS properties which contain references to images.
13869    $.waitForImages = {
13870        hasImageProperties: [
13871            'backgroundImage',
13872            'listStyleImage',
13873            'borderImage',
13874            'borderCornerImage',
13875            'cursor'
13876        ],
13877        hasImageAttributes: ['srcset']
13878    };
13879
13880    // Custom selector to find `img` elements that have a valid `src`
13881    // attribute and have not already loaded.
13882    $.expr[':'].uncached = function (obj) {
13883        // Ensure we are dealing with an `img` element with a valid
13884        // `src` attribute.
13885        if (!$(obj).is('img[src][src!=""]')) {
13886            return false;
13887        }
13888
13889        return !obj.complete;
13890    };
13891
13892    $.fn.waitForImages = function () {
13893
13894        var allImgsLength = 0;
13895        var allImgsLoaded = 0;
13896        var deferred = $.Deferred();
13897
13898        var finishedCallback;
13899        var eachCallback;
13900        var waitForAll;
13901
13902        // Handle options object (if passed).
13903        if ($.isPlainObject(arguments[0])) {
13904
13905            waitForAll = arguments[0].waitForAll;
13906            eachCallback = arguments[0].each;
13907            finishedCallback = arguments[0].finished;
13908
13909        } else {
13910
13911            // Handle if using deferred object and only one param was passed in.
13912            if (arguments.length === 1 && $.type(arguments[0]) === 'boolean') {
13913                waitForAll = arguments[0];
13914            } else {
13915                finishedCallback = arguments[0];
13916                eachCallback = arguments[1];
13917                waitForAll = arguments[2];
13918            }
13919
13920        }
13921
13922        // Handle missing callbacks.
13923        finishedCallback = finishedCallback || $.noop;
13924        eachCallback = eachCallback || $.noop;
13925
13926        // Convert waitForAll to Boolean
13927        waitForAll = !! waitForAll;
13928
13929        // Ensure callbacks are functions.
13930        if (!$.isFunction(finishedCallback) || !$.isFunction(eachCallback)) {
13931            throw new TypeError('An invalid callback was supplied.');
13932        }
13933
13934        this.each(function () {
13935            // Build a list of all imgs, dependent on what images will
13936            // be considered.
13937            var obj = $(this);
13938            var allImgs = [];
13939            // CSS properties which may contain an image.
13940            var hasImgProperties = $.waitForImages.hasImageProperties || [];
13941            // Element attributes which may contain an image.
13942            var hasImageAttributes = $.waitForImages.hasImageAttributes || [];
13943            // To match `url()` references.
13944            // Spec: http://www.w3.org/TR/CSS2/syndata.html#value-def-uri
13945            var matchUrl = /url\(\s*(['"]?)(.*?)\1\s*\)/g;
13946
13947            if (waitForAll) {
13948
13949                // Get all elements (including the original), as any one of
13950                // them could have a background image.
13951                obj.find('*').addBack().each(function () {
13952                    var element = $(this);
13953
13954                    // If an `img` element, add it. But keep iterating in
13955                    // case it has a background image too.
13956                    if (element.is('img:uncached')) {
13957                        allImgs.push({
13958                            src: element.attr('src'),
13959                            element: element[0]
13960                        });
13961                    }
13962
13963                    $.each(hasImgProperties, function (i, property) {
13964                        var propertyValue = element.css(property);
13965                        var match;
13966
13967                        // If it doesn't contain this property, skip.
13968                        if (!propertyValue) {
13969                            return true;
13970                        }
13971
13972                        // Get all url() of this element.
13973                        while (match = matchUrl.exec(propertyValue)) {
13974                            allImgs.push({
13975                                src: match[2],
13976                                element: element[0]
13977                            });
13978                        }
13979                    });
13980
13981                    $.each(hasImageAttributes, function (i, attribute) {
13982                        var attributeValue = element.attr(attribute);
13983                        var attributeValues;
13984
13985                        // If it doesn't contain this property, skip.
13986                        if (!attributeValue) {
13987                            return true;
13988                        }
13989
13990                        // Check for multiple comma separated images
13991                        attributeValues = attributeValue.split(',');
13992
13993                        $.each(attributeValues, function(i, value) {
13994                            // Trim value and get string before first
13995                            // whitespace (for use with srcset).
13996                            value = $.trim(value).split(' ')[0];
13997                            allImgs.push({
13998                                src: value,
13999                                element: element[0]
14000                            });
14001                        });
14002                    });
14003                });
14004            } else {
14005                // For images only, the task is simpler.
14006                obj.find('img:uncached')
14007                    .each(function () {
14008                    allImgs.push({
14009                        src: this.src,
14010                        element: this
14011                    });
14012                });
14013            }
14014
14015            allImgsLength = allImgs.length;
14016            allImgsLoaded = 0;
14017
14018            // If no images found, don't bother.
14019            if (allImgsLength === 0) {
14020                finishedCallback.call(obj[0]);
14021                deferred.resolveWith(obj[0]);
14022            }
14023
14024            $.each(allImgs, function (i, img) {
14025
14026                var image = new Image();
14027                var events =
14028                  'load.' + eventNamespace + ' error.' + eventNamespace;
14029
14030                // Handle the image loading and error with the same callback.
14031                $(image).one(events, function me (event) {
14032                    // If an error occurred with loading the image, set the
14033                    // third argument accordingly.
14034                    var eachArguments = [
14035                        allImgsLoaded,
14036                        allImgsLength,
14037                        event.type == 'load'
14038                    ];
14039                    allImgsLoaded++;
14040
14041                    eachCallback.apply(img.element, eachArguments);
14042                    deferred.notifyWith(img.element, eachArguments);
14043
14044                    // Unbind the event listeners. I use this in addition to
14045                    // `one` as one of those events won't be called (either
14046                    // 'load' or 'error' will be called).
14047                    $(this).off(events, me);
14048
14049                    if (allImgsLoaded == allImgsLength) {
14050                        finishedCallback.call(obj[0]);
14051                        deferred.resolveWith(obj[0]);
14052                        return false;
14053                    }
14054
14055                });
14056
14057                image.src = img.src;
14058            });
14059        });
14060
14061        return deferred.promise();
14062
14063    };
14064}));
14065
14066/**
14067 * @preserve  textfill
14068 * @name      jquery.textfill.js
14069 * @author    Russ Painter
14070 * @author    Yu-Jie Lin
14071 * @author    Alexandre Dantas
14072 * @version   0.6.0
14073 * @date      2014-08-19
14074 * @copyright (c) 2014 Alexandre Dantas
14075 * @copyright (c) 2012-2013 Yu-Jie Lin
14076 * @copyright (c) 2009 Russ Painter
14077 * @license   MIT License
14078 * @homepage  https://github.com/jquery-textfill/jquery-textfill
14079 * @example   http://jquery-textfill.github.io/jquery-textfill/index.html
14080 */
14081; (function($) {
14082
14083	/**
14084	 * Resizes an inner element's font so that the
14085	 * inner element completely fills the outer element.
14086	 *
14087	 * @param {Object} options User options that take
14088	 *                         higher precedence when
14089	 *                         merging with the default ones.
14090	 *
14091	 * @return All outer elements processed
14092	 */
14093	$.fn.textfill = function(options) {
14094
14095		// ______  _______ _______ _______ _     _        _______ _______
14096		// |     \ |______ |______ |_____| |     | |         |    |______
14097		// |_____/ |______ |       |     | |_____| |_____    |    ______|
14098        //
14099		// Merging user options with the default values
14100
14101		var defaults = {
14102			debug            : false,
14103			maxFontPixels    : 40,
14104			minFontPixels    : 4,
14105			innerTag         : 'span',
14106			widthOnly        : false,
14107			success          : null, // callback when a resizing is done
14108			callback         : null, // callback when a resizing is done (deprecated, use success)
14109			fail             : null, // callback when a resizing is failed
14110			complete         : null, // callback when all is done
14111			explicitWidth    : null,
14112			explicitHeight   : null,
14113			changeLineHeight : false
14114		};
14115
14116		var Opts = $.extend(defaults, options);
14117
14118		// _______ _     _ __   _ _______ _______ _____  _____  __   _ _______
14119		// |______ |     | | \  | |          |      |   |     | | \  | |______
14120		// |       |_____| |  \_| |_____     |    __|__ |_____| |  \_| ______|
14121		//
14122		// Predefining the awesomeness
14123
14124		// Output arguments to the Debug console
14125		// if "Debug Mode" is enabled
14126		function _debug() {
14127			if (!Opts.debug
14128				||  typeof console       == 'undefined'
14129				||  typeof console.debug == 'undefined') {
14130				return;
14131			}
14132			console.debug.apply(console, arguments);
14133		}
14134
14135		// Output arguments to the Warning console
14136		function _warn() {
14137			if (typeof console      == 'undefined' ||
14138				typeof console.warn == 'undefined') {
14139				return;
14140			}
14141			console.warn.apply(console, arguments);
14142		}
14143
14144		// Outputs all information on the current sizing
14145		// of the font.
14146		function _debug_sizing(prefix, ourText, maxHeight, maxWidth, minFontPixels, maxFontPixels) {
14147
14148			function _m(v1, v2) {
14149
14150				var marker = ' / ';
14151
14152				if (v1 > v2)
14153					marker = ' > ';
14154
14155				else if (v1 == v2)
14156					marker = ' = ';
14157
14158				return marker;
14159			}
14160
14161			_debug(
14162				'[TextFill] '  + prefix + ' { ' +
14163				'font-size: ' + ourText.css('font-size') + ',' +
14164				'Height: '    + ourText.height() + 'px ' + _m(ourText.height(), maxHeight) + maxHeight + 'px,' +
14165				'Width: '     + ourText.width()  + _m(ourText.width() , maxWidth)  + maxWidth + ',' +
14166				'minFontPixels: ' + minFontPixels + 'px, ' +
14167				'maxFontPixels: ' + maxFontPixels + 'px }'
14168			);
14169		}
14170
14171		/**
14172		 * Calculates which size the font can get resized,
14173		 * according to constrains.
14174		 *
14175		 * @param {String} prefix Gets shown on the console before
14176		 *                        all the arguments, if debug mode is on.
14177		 * @param {Object} ourText The DOM element to resize,
14178		 *                         that contains the text.
14179		 * @param {function} func Function called on `ourText` that's
14180		 *                        used to compare with `max`.
14181		 * @param {number} max Maximum value, that gets compared with
14182		 *                     `func` called on `ourText`.
14183		 * @param {number} minFontPixels Minimum value the font can
14184		 *                               get resized to (in pixels).
14185		 * @param {number} maxFontPixels Maximum value the font can
14186		 *                               get resized to (in pixels).
14187		 *
14188		 * @return Size (in pixels) that the font can be resized.
14189		 */
14190		function _sizing(prefix, ourText, func, max, maxHeight, maxWidth, minFontPixels, maxFontPixels) {
14191
14192			_debug_sizing(
14193				prefix, ourText,
14194				maxHeight, maxWidth,
14195				minFontPixels, maxFontPixels
14196			);
14197
14198			// The kernel of the whole plugin, take most attention
14199			// on this part.
14200			//
14201			// This is a loop that keeps increasing the `font-size`
14202			// until it fits the parent element.
14203			//
14204			// - Start from the minimal allowed value (`minFontPixels`)
14205			// - Guesses an average font size (in pixels) for the font,
14206			// - Resizes the text and sees if its size is within the
14207			//   boundaries (`minFontPixels` and `maxFontPixels`).
14208			//   - If so, keep guessing until we break.
14209			//   - If not, return the last calculated size.
14210			//
14211			// I understand this is not optimized and we should
14212			// consider implementing something akin to
14213			// Daniel Hoffmann's answer here:
14214			//
14215			//     http://stackoverflow.com/a/17433451/1094964
14216			//
14217
14218			while (minFontPixels < (maxFontPixels - 1)) {
14219
14220				var fontSize = Math.floor((minFontPixels + maxFontPixels) / 2);
14221				ourText.css('font-size', fontSize);
14222
14223				if (func.call(ourText) <= max) {
14224					minFontPixels = fontSize;
14225
14226					if (func.call(ourText) == max)
14227						break;
14228				}
14229				else
14230					maxFontPixels = fontSize;
14231
14232				_debug_sizing(
14233					prefix, ourText,
14234					maxHeight, maxWidth,
14235					minFontPixels, maxFontPixels
14236				);
14237			}
14238
14239			ourText.css('font-size', maxFontPixels);
14240
14241			if (func.call(ourText) <= max) {
14242				minFontPixels = maxFontPixels;
14243
14244				_debug_sizing(
14245					prefix + '* ', ourText,
14246					maxHeight, maxWidth,
14247					minFontPixels, maxFontPixels
14248				);
14249			}
14250			return minFontPixels;
14251		}
14252
14253		// _______ _______ _______  ______ _______
14254		// |______    |    |_____| |_____/    |
14255		// ______|    |    |     | |    \_    |
14256        //
14257		// Let's get it started (yeah)!
14258
14259		_debug('[TextFill] Start Debug');
14260
14261		this.each(function() {
14262
14263			// Contains the child element we will resize.
14264			// $(this) means the parent container
14265			var ourText = $(Opts.innerTag + ':visible:first', this);
14266
14267			// Will resize to this dimensions.
14268			// Use explicit dimensions when specified
14269			var maxHeight = Opts.explicitHeight || $(this).height();
14270			var maxWidth  = Opts.explicitWidth  || $(this).width();
14271
14272			var oldFontSize = ourText.css('font-size');
14273
14274			var lineHeight  = parseFloat(ourText.css('line-height')) / parseFloat(oldFontSize);
14275
14276			_debug('[TextFill] Inner text: ' + ourText.text());
14277			_debug('[TextFill] All options: ', Opts);
14278			_debug('[TextFill] Maximum sizes: { ' +
14279				   'Height: ' + maxHeight + 'px, ' +
14280				   'Width: '  + maxWidth  + 'px' + ' }'
14281				  );
14282
14283			var minFontPixels = Opts.minFontPixels;
14284
14285			// Remember, if this `maxFontPixels` is negative,
14286			// the text will resize to as long as the container
14287			// can accomodate
14288			var maxFontPixels = (Opts.maxFontPixels <= 0 ?
14289								 maxHeight :
14290								 Opts.maxFontPixels);
14291
14292
14293			// Let's start it all!
14294
14295			// 1. Calculate which `font-size` would
14296			//    be best for the Height
14297			var fontSizeHeight = undefined;
14298
14299			if (! Opts.widthOnly)
14300				fontSizeHeight = _sizing(
14301					'Height', ourText,
14302					$.fn.height, maxHeight,
14303					maxHeight, maxWidth,
14304					minFontPixels, maxFontPixels
14305				);
14306
14307			// 2. Calculate which `font-size` would
14308			//    be best for the Width
14309			var fontSizeWidth = undefined;
14310
14311			fontSizeWidth = _sizing(
14312				'Width', ourText,
14313				$.fn.width, maxWidth,
14314				maxHeight, maxWidth,
14315				minFontPixels, maxFontPixels
14316			);
14317
14318			// 3. Actually resize the text!
14319
14320			if (Opts.widthOnly) {
14321				ourText.css({
14322					'font-size'  : fontSizeWidth,
14323					'white-space': 'nowrap'
14324				});
14325
14326				if (Opts.changeLineHeight)
14327					ourText.parent().css(
14328						'line-height',
14329						(lineHeight * fontSizeWidth + 'px')
14330					);
14331			}
14332			else {
14333				var fontSizeFinal = Math.min(fontSizeHeight, fontSizeWidth);
14334
14335				ourText.css('font-size', fontSizeFinal);
14336
14337				if (Opts.changeLineHeight)
14338					ourText.parent().css(
14339						'line-height',
14340						(lineHeight * fontSizeFinal) + 'px'
14341					);
14342			}
14343
14344			_debug(
14345				'[TextFill] Finished { ' +
14346				'Old font-size: ' + oldFontSize              + ', ' +
14347				'New font-size: ' + ourText.css('font-size') + ' }'
14348			);
14349
14350			// Oops, something wrong happened!
14351			// We weren't supposed to exceed the original size
14352			if ((ourText.width()  > maxWidth) ||
14353				(ourText.height() > maxHeight && !Opts.widthOnly)) {
14354
14355				ourText.css('font-size', oldFontSize);
14356
14357				// Failure callback
14358				if (Opts.fail)
14359					Opts.fail(this);
14360
14361				_debug(
14362					'[TextFill] Failure { ' +
14363					'Current Width: '  + ourText.width()  + ', ' +
14364					'Maximum Width: '  + maxWidth         + ', ' +
14365					'Current Height: ' + ourText.height() + ', ' +
14366					'Maximum Height: ' + maxHeight        + ' }'
14367				);
14368			}
14369			else if (Opts.success) {
14370				Opts.success(this);
14371			}
14372			else if (Opts.callback) {
14373				_warn('callback is deprecated, use success, instead');
14374
14375				// Success callback
14376				Opts.callback(this);
14377			}
14378		});
14379
14380		// Complete callback
14381		if (Opts.complete)
14382			Opts.complete(this);
14383
14384		_debug('[TextFill] End Debug');
14385		return this;
14386	};
14387
14388})(window.jQuery);
14389
14390
14391!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;
14392function getStyles(config){
14393  // 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;
14393left: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+"}"
14394};
14395  var ShareUtils;
14396
14397if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") {
14398  Object.defineProperty(HTMLElement.prototype, "classList", {
14399    get: function() {
14400      var ret, self, update;
14401      update = function(fn) {
14402        return function(value) {
14403          var classes, index;
14404          classes = self.className.split(/\s+/);
14405          index = classes.indexOf(value);
14406          fn(classes, index, value);
14407          self.className = classes.join(" ");
14408        };
14409      };
14410      self = this;
14411      ret = {
14412        add: update(function(classes, index, value) {
14413          ~index || classes.push(value);
14414        }),
14415        remove: update(function(classes, index) {
14416          ~index && classes.splice(index, 1);
14417        }),
14418        toggle: update(function(classes, index, value) {
14419          if (~index) {
14420            classes.splice(index, 1);
14421          } else {
14422            classes.push(value);
14423          }
14424        }),
14425        contains: function(value) {
14426          return !!~self.className.split(/\s+/).indexOf(value);
14427        },
14428        item: function(i) {
14429          return self.className.split(/\s+/)[i] || null;
14430        }
14431      };
14432      Object.defineProperty(ret, "length", {
14433        get: function() {
14434          return self.className.split(/\s+/).length;
14435        }
14436      });
14437      return ret;
14438    }
14439  });
14440}
14441
14442String.prototype.to_rfc3986 = function() {
14443  var tmp;
14444  tmp = encodeURIComponent(this);
14445  return tmp.replace(/[!'()*]/g, function(c) {
14446    return "%" + c.charCodeAt(0).toString(16);
14447  });
14448};
14449
14450ShareUtils = (function() {
14451  function ShareUtils() {}
14452
14453  ShareUtils.prototype.extend = function(to, from, overwrite) {
14454    var hasProp, prop;
14455    for (prop in from) {
14456      hasProp = to[prop] !== undefined;
14457      if (hasProp && typeof from[prop] === "object") {
14458        this.extend(to[prop], from[prop], overwrite);
14459      } else {
14460        if (overwrite || !hasProp) {
14461          to[prop] = from[prop];
14462        }
14463      }
14464    }
14465  };
14466
14467  ShareUtils.prototype.hide = function(el) {
14468    return el.style.display = "none";
14469  };
14470
14471  ShareUtils.prototype.show = function(el) {
14472    return el.style.display = "block";
14473  };
14474
14475  ShareUtils.prototype.has_class = function(el, class_name) {
14476    return el.classList.contains(class_name);
14477  };
14478
14479  ShareUtils.prototype.add_class = function(el, class_name) {
14480    return el.classList.add(class_name);
14481  };
14482
14483  ShareUtils.prototype.remove_class = function(el, class_name) {
14484    return el.classList.remove(class_name);
14485  };
14486
14487  ShareUtils.prototype.is_encoded = function(str) {
14488    str = str.to_rfc3986();
14489    return decodeURIComponent(str) !== str;
14490  };
14491
14492  ShareUtils.prototype.encode = function(str) {
14493    if (typeof str === "undefined" || this.is_encoded(str)) {
14494      return str;
14495    } else {
14496      return str.to_rfc3986();
14497    }
14498  };
14499
14500  ShareUtils.prototype.popup = function(url, params) {
14501    var k, popup, qs, v;
14502    if (params == null) {
14503      params = {};
14504    }
14505    popup = {
14506      width: 500,
14507      height: 350
14508    };
14509    popup.top = (screen.height / 2) - (popup.height / 2);
14510    popup.left = (screen.width / 2) - (popup.width / 2);
14511    qs = ((function() {
14512      var _results;
14513      _results = [];
14514      for (k in params) {
14515        v = params[k];
14516        _results.push("" + k + "=" + (this.encode(v)));
14517      }
14518      return _results;
14519    }).call(this)).join('&');
14520    if (qs) {
14521      qs = "?" + qs;
14522    }
14523    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=" 
14523+ popup.width + ",height=" + popup.height);
14524  };
14525
14526  return ShareUtils;
14527
14528})();
14529var Share,
14530  __hasProp = {}.hasOwnProperty,
14531  __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; };
14532
14533Share = (function(_super) {
14534  __extends(Share, _super);
14535
14536  function Share(element, options) {
14537    this.element = element;
14538    this.el = {
14539      head: document.getElementsByTagName('head')[0],
14540      body: document.getElementsByTagName('body')[0]
14541    };
14542    this.config = {
14543      enabled_networks: 0,
14544      protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//',
14545      url: window.location.href,
14546      caption: null,
14547      title: this.default_title(),
14548      image: this.default_image(),
14549      description: this.default_description(),
14550      ui: {
14551        flyout: 'top center',
14552        button_text: 'Share',
14553        button_font: true,
14554        icon_font: true
14555      },
14556      networks: {
14557        google_plus: {
14558          enabled: true,
14559          url: null
14560        },
14561        twitter: {
14562          enabled: true,
14563          url: null,
14564          title: null,
14565          description: null
14566        },
14567        facebook: {
14568          enabled: true,
14569          load_sdk: true,
14570          url: null,
14571          app_id: null,
14572          title: null,
14573          caption: null,
14574          description: null,
14575          image: null
14576        },
14577        pinterest: {
14578          enabled: true,
14579          url: null,
14580          image: null,
14581          description: null
14582        },
14583        reddit: {
14584          enabled: true,
14585          url: null,
14586          title: null
14587        },
14588        linkedin: {
14589          enabled: true,
14590          url: null,
14591          title: null,
14592          description: null
14593        },
14594        xing: {
14595          enabled: true,
14596          url: null,
14597          title: null,
14598          image: null,
14599          description: null
14600        },
14601        whatsapp: {
14602          enabled: true,
14603          description: null,
14604          url: null
14605        },
14606        email: {
14607          enabled: true,
14608          title: null,
14609          description: null,
14610          url: null
14611        }
14612      }
14613    };
14614    this.setup(element, options);
14615    return this;
14616  }
14617
14618  Share.prototype.setup = function(element, opts) {
14619    var index, instance, instances, _i, _len;
14620    instances = document.querySelectorAll(element);
14621    this.extend(this.config, opts, true);
14622    this.set_global_configuration();
14623    this.normalize_network_configuration();
14624    if (this.config.ui.icon_font) {
14625      this.inject_icons();
14626    }
14627    if (this.config.ui.button_font) {
14628      this.inject_fonts();
14629    }
14630    if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) {
14631      this.inject_facebook_sdk();
14632    }
14633    for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) {
14634      instance = instances[index];
14635      this.setup_instance(element, index);
14636    }
14637  };
14638
14639  Share.prototype.setup_instance = function(element, index) {
14640    var button, instance, label, network, networks, _i, _len, _results,
14641      _this = this;
14642    instance = document.querySelectorAll(element)[index];
14643    this.hide(instance);
14644    this.add_class(instance, "sharer-" + index);
14645    instance = document.querySelectorAll(element)[index];
14646    this.inject_css(instance);
14647    this.inject_html(instance);
14648    this.show(instance);
14649    label = instance.getElementsByTagName("label")[0];
14650    button = instance.getElementsByClassName("social")[0];
14651    networks = instance.getElementsByTagName('li');
14652    this.add_class(button, "networks-" + this.config.enabled_networks);
14653    label.addEventListener("click", function() {
14654      return _this.event_toggle(button);
14655    });
14656    _this = this;
14657    _results = [];
14658    for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) {
14659      network = networks[index];
14660      _results.push(network.addEventListener("click", function() {
14661        _this.event_network(instance, this);
14662        return _this.event_close(button);
14663      }));
14664    }
14665    return _results;
14666  };
14667
14668  Share.prototype.event_toggle = function(button) {
14669    if (this.has_class(button, "active")) {
14670      return this.event_close(button);
14671    } else {
14672      return this.event_open(button);
14673    }
14674  };
14675
14676  Share.prototype.event_open = function(button) {
14677    if (this.has_class(button, "load")) {
14678      this.remove_class(button, "load");
14679    }
14680    return this.add_class(button, "active");
14681  };
14682
14683  Share.prototype.event_close = function(button) {
14684    return this.remove_class(button, "active");
14685  };
14686
14687  Share.prototype.event_network = function(instance, network) {
14688    var name;
14689    name = network.getAttribute("data-network");
14690    this.hook("before", name, instance);
14691    this["network_" + name]();
14692    return this.hook("after", name, instance);
14693  };
14694
14695  Share.prototype.open = function() {
14696    return this["public"]("open");
14697  };
14698
14699  Share.prototype.close = function() {
14700    return this["public"]("close");
14701  };
14702
14703  Share.prototype.toggle = function() {
14704    return this["public"]("toggle");
14705  };
14706
14707  Share.prototype["public"] = function(action) {
14708    var button, index, instance, _i, _len, _ref, _results;
14709    _ref = document.querySelectorAll(this.element);
14710    _results = [];
14711    for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
14712      instance = _ref[index];
14713      button = instance.getElementsByClassName("social")[0];
14714      _results.push(this["event_" + action](button));
14715    }
14716    return _results;
14717  };
14718
14719  Share.prototype.network_facebook = function() {
14720    if (this.config.networks.facebook.load_sdk) {
14721      if (!window.FB) {
14722        return console.error("The Facebook JS SDK hasn't loaded yet.");
14723      }
14724      return FB.ui({
14725        method: 'feed',
14726        name: this.config.networks.facebook.title,
14727        link: this.config.networks.facebook.url,
14728        picture: this.config.networks.facebook.image,
14729        caption: this.config.networks.facebook.caption,
14730        description: this.config.networks.facebook.description
14731      });
14732    } else {
14733      return this.popup('https://www.facebook.com/sharer/sharer.php', {
14734        u: this.config.networks.facebook.url
14735      });
14736    }
14737  };
14738
14739  Share.prototype.network_twitter = function() {
14740    return this.popup('https://twitter.com/intent/tweet', {
14741      text: this.config.networks.twitter.title,
14742      url: this.config.networks.twitter.url
14743    });
14744  };
14745
14746  Share.prototype.network_google_plus = function() {
14747    return this.popup('https://plus.google.com/share', {
14748      url: this.config.networks.google_plus.url
14749    });
14750  };
14751
14752  Share.prototype.network_pinterest = function() {
14753    return this.popup('https://www.pinterest.com/pin/create/button', {
14754      url: this.config.networks.pinterest.url,
14755      media: this.config.networks.pinterest.image,
14756      description: this.config.networks.pinterest.description
14757    });
14758  };
14759
14760  Share.prototype.network_linkedin = function() {
14761    return this.popup('https://www.linkedin.com/shareArticle', {
14762      url: this.config.networks.linkedin.url,
14763      title: this.config.networks.linkedin.title,
14764      summary: this.config.networks.linkedin.description
14765    });
14766  }
14767
14768  Share.prototype.network_xing = function() {
14769    return this.popup('https://www.xing.com/spi/shares/new', {
14770      url: this.config.networks.xing.url,
14771      image: this.config.networks.xing.image,
14772      title: this.config.networks.xing.title,
14773      summary: this.config.networks.xing.description
14774    });
14775  }
14776
14777  Share.prototype.network_email = function() {
14778    return this.popup('mailto:', {
14779      subject: this.config.networks.email.title,
14780      body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description,
14781    });
14782  };
14783
14784  Share.prototype.inject_icons = function() {
14785  //  return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css");
14786  };
14787
14788  Share.prototype.inject_fonts = function() {
14789   // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text);
14790  };
14791
14792  Share.prototype.inject_stylesheet = function(url) {
14793    var link;
14794    if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) {
14795      link = document.createElement("link");
14796      link.setAttribute("rel", "stylesheet");
14797      link.setAttribute("href", url);
14798      return this.el.head.appendChild(link);
14799    }
14800  };
14801
14802  Share.prototype.inject_css = function(instance) {
14803    var css, meta, selector, style;
14804    selector = "." + (instance.getAttribute('class').split(" ").join("."));
14805    if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) {
14806      this.config.selector = selector;
14807      css = getStyles(this.config);
14808      style = document.createElement("style");
14809      style.type = "text/css";
14810      if (style.styleSheet) {
14811        style.styleSheet.cssText = css;
14812      } else {
14813        style.appendChild(document.createTextNode(css));
14814      }
14815      this.el.head.appendChild(style);
14816      delete this.config.selector;
14817      meta = document.createElement("meta");
14818      meta.setAttribute("name", "sharer" + selector);
14819      return this.el.head.appendChild(meta);
14820    }
14821  };
14822
14823  Share.prototype.inject_html = function(instance) {
14824    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>";
14825  };
14826
14827  Share.prototype.inject_facebook_sdk = function() {
14828    var fb_root, script;
14829    if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) {
14830      script = document.createElement("script");
14831      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')";
14832      fb_root = document.createElement("div");
14833      fb_root.id = "fb-root";
14834      this.el.body.appendChild(fb_root);
14835      return this.el.body.appendChild(script);
14836    }
14837  };
14838
14839  Share.prototype.hook = function(type, network, instance) {
14840    var fn, opts;
14841    fn = this.config.networks[network][type];
14842    if (typeof fn === "function") {
14843      opts = fn.call(this.config.networks[network], instance);
14844      if (opts !== void 0) {
14845        opts = this.normalize_filter_config_updates(opts);
14846        this.extend(this.config.networks[network], opts, true);
14847        this.normalize_network_configuration();
14848      }
14849    }
14850  };
14851
14852  Share.prototype.default_title = function() {
14853    var content;
14854    if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) {
14855      return encodeURIComponent(content.getAttribute('content'));
14856    } else if (content = document.querySelector('title')) {
14857      return encodeURIComponent(content.innerText);
14858    }
14859  };
14860
14861  Share.prototype.default_image = function() {
14862    var content;
14863    if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) {
14864      return content.getAttribute('content');
14865    }
14866  };
14867
14868  Share.prototype.default_description = function() {
14869    var content;
14870    if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) {
14871      return content.getAttribute('content');
14872    } else {
14873      return '';
14874    }
14875  };
14876
14877  Share.prototype.set_global_configuration = function() {
14878    var display, network, option, options, _ref, _results;
14879    _ref = this.config.networks;
14880    _results = [];
14881    for (network in _ref) {
14882      options = _ref[network];
14883      for (option in options) {
14884        if (this.config.networks[network][option] == null) {
14885          this.config.networks[network][option] = this.config[option];
14886        }
14887      }
14888      if (this.config.networks[network].enabled) {
14889        display = 'block';
14890        this.config.enabled_networks += 1;
14891      } else {
14892        display = 'none';
14893      }
14894      _results.push(this.config.networks[network].display = display);
14895    }
14896    return _results;
14897  };
14898
14899  Share.prototype.normalize_network_configuration = function() {
14900    if (!this.config.networks.facebook.app_id) {
14901      this.config.networks.facebook.load_sdk = false;
14902    }
14903    if (!this.is_encoded(this.config.networks.twitter.description)) {
14904      this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description);
14905    }
14906    if (typeof this.config.networks.facebook.app_id === 'number') {
14907      return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString();
14908    }
14909  };
14910
14911  Share.prototype.normalize_filter_config_updates = function(opts) {
14912    if (this.config.networks.facebook.app_id !== opts.app_id) {
14913      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.");
14914      delete opts.app_id;
14915    }
14916    if (this.config.networks.facebook.load_sdk !== opts.load_sdk) {
14917      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.");
14918      delete opts.app_id;
14919    }
14920    return opts;
14921  };
14922
14923  return Share;
14924
14925})(ShareUtils);
14926 return Share;
14927});
14928
14929
14930// Generated by CoffeeScript 1.9.2
14931
14932// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net
14933
14934(function() {
14935  var $, win;
14936
14937  $ = this.jQuery || window.jQuery;
14938
14939  win = $(window);
14940
14941  $.fn.stick_in_parent = function(opts) {
14942    var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class;
14943    if (opts == null) {
14944      opts = {};
14945    }
14946    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;
14947    if (offset_top == null) {
14948      offset_top = 0;
14949    }
14950    if (parent_selector == null) {
14951      parent_selector = void 0;
14952    }
14953    if (inner_scrolling == null) {
14954      inner_scrolling = true;
14955    }
14956    if (sticky_class == null) {
14957      sticky_class = "is_stuck";
14958    }
14959    doc = $(document);
14960    if (enable_bottoming == null) {
14961      enable_bottoming = true;
14962    }
14963    outer_width = function(el) {
14964      var _el, computed, w;
14965      if (window.getComputedStyle) {
14966        _el = el[0];
14967        computed = window.getComputedStyle(el[0]);
14968        w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right"));
14969        if (computed.getPropertyValue("box-sizing") !== "border-box") {
14970          w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right"));
14971        }
14972        return w;
14973      } else {
14974        return el.outerWidth(true);
14975      }
14976    };
14977    fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) {
14978      var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick;
14979      if (elm.data("sticky_kit")) {
14980        return;
14981      }
14982      elm.data("sticky_kit", true);
14983      last_scroll_height = doc.height();
14984      parent = elm.parent();
14985      if (parent_selector != null) {
14986        parent = parent.closest(parent_selector);
14987      }
14988      if (!parent.length) {
14989        throw "failed to find stick parent";
14990      }
14991      fixed = false;
14992      bottomed = false;
14993      spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />");
14994      if (spacer) {
14995        spacer.css('position', elm.css('position'));
14996      }
14997      recalc = function() {
14998        var border_top, padding_top, restore;
14999        if (detached) {
15000          return;
15001        }
15002        last_scroll_height = doc.height();
15003        border_top = parseInt(parent.css("border-top-width"), 10);
15004        padding_top = parseInt(parent.css("padding-top"), 10);
15005        padding_bottom = parseInt(parent.css("padding-bottom"), 10);
15006        parent_top = parent.offset().top + border_top + padding_top;
15007        parent_height = parent.height();
15008        if (fixed) {
15009          fixed = false;
15010          bottomed = false;
15011          if (manual_spacer == null) {
15012            elm.insertAfter(spacer);
15013            spacer.detach();
15014          }
15015          elm.css({
15016            position: "",
15017            top: "",
15018            width: "",
15019            bottom: ""
15020          }).removeClass(sticky_class);
15021          restore = true;
15022        }
15023        top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top;
15024        height = elm.outerHeight(true);
15025        el_float = elm.css("float");
15026        if (spacer) {
15027          spacer.css({
15028            width: outer_width(elm),
15029            height: height,
15030            display: elm.css("display"),
15031            "vertical-align": elm.css("vertical-align"),
15032            "float": el_float
15033          });
15034        }
15035        if (restore) {
15036          return tick();
15037        }
15038      };
15039      recalc();
15040      if (height === parent_height) {
15041        return;
15042      }
15043      last_pos = void 0;
15044      offset = offset_top;
15045      recalc_counter = recalc_every;
15046      tick = function() {
15047        var css, delta, recalced, scroll, will_bottom, win_height;
15048        if (detached) {
15049          return;
15050        }
15051        recalced = false;
15052        if (recalc_counter != null) {
15053          recalc_counter -= 1;
15054          if (recalc_counter <= 0) {
15055            recalc_counter = recalc_every;
15056            recalc();
15057            recalced = true;
15058          }
15059        }
15060        if (!recalced && doc.height() !== last_scroll_height) {
15061          recalc();
15062          recalced = true;
15063        }
15064        scroll = win.scrollTop();
15065        if (last_pos != null) {
15066          delta = scroll - last_pos;
15067        }
15068        last_pos = scroll;
15069        if (fixed) {
15070          if (enable_bottoming) {
15071            will_bottom = scroll + height + offset > parent_height + parent_top;
15072            if (bottomed && !will_bottom) {
15073              bottomed = false;
15074              elm.css({
15075                position: "fixed",
15076                bottom: "",
15077                top: offset
15078              }).trigger("sticky_kit:unbottom");
15079            }
15080          }
15081          if (scroll < top) {
15082            fixed = false;
15083            offset = offset_top;
15084            if (manual_spacer == null) {
15085              if (el_float === "left" || el_float === "right") {
15086                elm.insertAfter(spacer);
15087              }
15088              spacer.detach();
15089            }
15090            css = {
15091              position: "",
15092              width: "",
15093              top: ""
15094            };
15095            elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick");
15096          }
15097          if (inner_scrolling) {
15098            win_height = win.height();
15099            if (height + offset_top > win_height) {
15100              if (!bottomed) {
15101                offset -= delta;
15102                offset = Math.max(win_height - height, offset);
15103                offset = Math.min(offset_top, offset);
15104                if (fixed) {
15105                  elm.css({
15106                    top: offset + "px"
15107                  });
15108                }
15109              }
15110            }
15111          }
15112        } else {
15113          if (scroll > top) {
15114            fixed = true;
15115            css = {
15116              position: "fixed",
15117              top: offset
15118            };
15119            css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px";
15120            elm.css(css).addClass(sticky_class);
15121            if (manual_spacer == null) {
15122              elm.after(spacer);
15123              if (el_float === "left" || el_float === "right") {
15124                spacer.append(elm);
15125              }
15126            }
15127            elm.trigger("sticky_kit:stick");
15128          }
15129        }
15130        if (fixed && enable_bottoming) {
15131          if (will_bottom == null) {
15132            will_bottom = scroll + height + offset > parent_height + parent_top;
15133          }
15134          if (!bottomed && will_bottom) {
15135            bottomed = true;
15136            if (parent.css("position") === "static") {
15137              parent.css({
15138                position: "relative"
15139              });
15140            }
15141            return elm.css({
15142              position: "absolute",
15143              bottom: padding_bottom,
15144              top: "auto"
15145            }).trigger("sticky_kit:bottom");
15146          }
15147        }
15148      };
15149      recalc_and_tick = function() {
15150        recalc();
15151        return tick();
15152      };
15153      detach = function() {
15154        detached = true;
15155        win.off("touchmove", tick);
15156        win.off("scroll", tick);
15157        win.off("resize", recalc_and_tick);
15158        $(document.body).off("sticky_kit:recalc", recalc_and_tick);
15159        elm.off("sticky_kit:detach", detach);
15160        elm.removeData("sticky_kit");
15161        elm.css({
15162          position: "",
15163          bottom: "",
15164          top: "",
15165          width: ""
15166        });
15167        parent.position("position", "");
15168        if (fixed) {
15169          if (manual_spacer == null) {
15170            if (el_float === "left" || el_float === "right") {
15171              elm.insertAfter(spacer);
15172            }
15173            spacer.remove();
15174          }
15175          return elm.removeClass(sticky_class);
15176        }
15177      };
15178      win.on("touchmove", tick);
15179      win.on("scroll", tick);
15180      win.on("resize", recalc_and_tick);
15181      $(document.body).on("sticky_kit:recalc", recalc_and_tick);
15182      elm.on("sticky_kit:detach", detach);
15183      return setTimeout(tick, 0);
15184    };
15185    for (i = 0, len = this.length; i < len; i++) {
15186      elm = this[i];
15187      fn($(elm));
15188    }
15189    return this;
15190  };
15191
15192}).call(this);
15193
15194
15195
15196/* ========================================================================
15197 * Bootstrap: collapse.js v3.1.1
15198 * http://getbootstrap.com/javascript/#collapse
15199 * ========================================================================
15200 * Copyright 2011-2014 Twitter, Inc.
15201 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
15202 * ======================================================================== */
15203
15204
15205+function ($) {
15206  'use strict';
15207
15208  // COLLAPSE PUBLIC CLASS DEFINITION
15209  // ================================
15210
15211  var Collapse = function (element, options) {
15212    this.$element      = $(element)
15213    this.options       = $.extend({}, Collapse.DEFAULTS, options)
15214    this.transitioning = null
15215
15216    if (this.options.parent) this.$parent = $(this.options.parent)
15217    if (this.options.toggle) this.toggle()
15218  }
15219
15220  Collapse.DEFAULTS = {
15221    toggle: true
15222  }
15223
15224  Collapse.prototype.dimension = function () {
15225    var hasWidth = this.$element.hasClass('width')
15226    return hasWidth ? 'width' : 'height'
15227  }
15228
15229  Collapse.prototype.show = function () {
15230    if (this.transitioning || this.$element.hasClass('in')) return
15231
15232    var startEvent = $.Event('show.bs.collapse')
15233    this.$element.trigger(startEvent)
15234    if (startEvent.isDefaultPrevented()) return
15235
15236    var actives = this.$parent && this.$parent.find('> .panel > .in')
15237
15238    if (actives && actives.length) {
15239      var hasData = actives.data('bs.collapse')
15240      if (hasData && hasData.transitioning) return
15241      actives.collapse('hide')
15242      hasData || actives.data('bs.collapse', null)
15243    }
15244
15245    var dimension = this.dimension()
15246
15247    this.$element
15248      .removeClass('collapse')
15249      .addClass('collapsing')[dimension](0)
15250
15251    this.transitioning = 1
15252
15253    var complete = function (e) {
15254      if (e && e.target != this.$element[0]) return
15255      this.$element
15256        .removeClass('collapsing')
15257        .addClass('collapse in')[dimension]('auto')
15258      this.transitioning = 0
15259      this.$element.trigger('shown.bs.collapse')
15260    }
15261
15262    if (!$.support.transition) return complete.call(this)
15263
15264    var scrollSize = $.camelCase(['scroll', dimension].join('-'))
15265
15266    this.$element
15267      .one($.support.transition.end, $.proxy(complete, this))
15268      .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
15269  }
15270
15271  Collapse.prototype.hide = function () {
15272    if (this.transitioning || !this.$element.hasClass('in')) return
15273
15274    var startEvent = $.Event('hide.bs.collapse')
15275    this.$element.trigger(startEvent)
15276    if (startEvent.isDefaultPrevented()) return
15277
15278    var dimension = this.dimension()
15279
15280    this.$element[dimension](this.$element[dimension]())[0].offsetHeight
15281
15282    this.$element
15283      .addClass('collapsing')
15284      .removeClass('collapse')
15285      .removeClass('in')
15286
15287    this.transitioning = 1
15288
15289    var complete = function (e) {
15290      if (e && e.target != this.$element[0]) return
15291      this.transitioning = 0
15292      this.$element
15293        .trigger('hidden.bs.collapse')
15294        .removeClass('collapsing')
15295        .addClass('collapse')
15296    }
15297
15298    if (!$.support.transition) return complete.call(this)
15299
15300    this.$element
15301      [dimension](0)
15302      .one($.support.transition.end, $.proxy(complete, this))
15303      .emulateTransitionEnd(350)
15304  }
15305
15306  Collapse.prototype.toggle = function () {
15307    this[this.$element.hasClass('in') ? 'hide' : 'show']()
15308  }
15309
15310
15311  // COLLAPSE PLUGIN DEFINITION
15312  // ==========================
15313
15314  var old = $.fn.collapse
15315
15316  $.fn.collapse = function (option) {
15317    return this.each(function () {
15318      var $this   = $(this)
15319      var data    = $this.data('bs.collapse')
15320      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
15321
15322      if (!data && options.toggle && option == 'show') option = !option
15323      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
15324      if (typeof option == 'string') data[option]()
15325    })
15326  }
15327
15328  $.fn.collapse.Constructor = Collapse
15329
15330
15331  // COLLAPSE NO CONFLICT
15332  // ====================
15333
15334  $.fn.collapse.noConflict = function () {
15335    $.fn.collapse = old
15336    return this
15337  }
15338
15339
15340  // COLLAPSE DATA-API
15341  // =================
15342
15343  $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
15344    var $this   = $(this), href
15345    var target  = $this.attr('data-target')
15346        || e.preventDefault()
15347        || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
15348    var $target = $(target)
15349    var data    = $target.data('bs.collapse')
15350    var option  = data ? 'toggle' : $this.data()
15351    var parent  = $this.attr('data-parent')
15352    var $parent = parent && $(parent)
15353
15354    if (!data || !data.transitioning) {
15355      if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed')
15356      $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
15357    }
15358
15359    $target.collapse(option)
15360  })
15361
15362}(jQuery);
15363
15364
15365/* ========================================================================
15366 * Bootstrap: tab.js v3.1.1
15367 * http://getbootstrap.com/javascript/#tabs
15368 * ========================================================================
15369 * Copyright 2011-2014 Twitter, Inc.
15370 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
15371 * ======================================================================== */
15372
15373
15374+function ($) {
15375  'use strict';
15376
15377  // TAB CLASS DEFINITION
15378  // ====================
15379
15380  var Tab = function (element) {
15381    this.element = $(element)
15382  }
15383
15384  Tab.prototype.show = function () {
15385    var $this    = this.element
15386    var $ul      = $this.closest('ul:not(.dropdown-menu)')
15387    var selector = $this.data('target')
15388
15389    if (!selector) {
15390      selector = $this.attr('href')
15391      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
15392    }
15393
15394    if ($this.parent('li').hasClass('active')) return
15395
15396    var previous = $ul.find('.active:last a')[0]
15397    var e        = $.Event('show.bs.tab', {
15398      relatedTarget: previous
15399    })
15400
15401    $this.trigger(e)
15402
15403    if (e.isDefaultPrevented()) return
15404
15405    var $target = $(selector)
15406
15407    this.activate($this.parent('li'), $ul)
15408    this.activate($target, $target.parent(), function () {
15409      $this.trigger({
15410        type: 'shown.bs.tab',
15411        relatedTarget: previous
15412      })
15413    })
15414  }
15415
15416  Tab.prototype.activate = function (element, container, callback) {
15417    var $active    = container.find('> .active')
15418    var transition = callback
15419      && $.support.transition
15420      && $active.hasClass('fade')
15421
15422    function next() {
15423      $active
15424        .removeClass('active')
15425        .find('> .dropdown-menu > .active')
15426        .removeClass('active')
15427
15428      element.addClass('active')
15429
15430      if (transition) {
15431        element[0].offsetWidth // reflow for transition
15432        element.addClass('in')
15433      } else {
15434        element.removeClass('fade')
15435      }
15436
15437      if (element.parent('.dropdown-menu')) {
15438        element.closest('li.dropdown').addClass('active')
15439      }
15440
15441      callback && callback()
15442    }
15443
15444    transition ?
15445      $active
15446        .one($.support.transition.end, next)
15447        .emulateTransitionEnd(150) :
15448      next()
15449
15450    $active.removeClass('in')
15451  }
15452
15453
15454  // TAB PLUGIN DEFINITION
15455  // =====================
15456
15457  var old = $.fn.tab
15458
15459  $.fn.tab = function ( option ) {
15460    return this.each(function () {
15461      var $this = $(this)
15462      var data  = $this.data('bs.tab')
15463
15464      if (!data) $this.data('bs.tab', (data = new Tab(this)))
15465      if (typeof option == 'string') data[option]()
15466    })
15467  }
15468
15469  $.fn.tab.Constructor = Tab
15470
15471
15472  // TAB NO CONFLICT
15473  // ===============
15474
15475  $.fn.tab.noConflict = function () {
15476    $.fn.tab = old
15477    return this
15478  }
15479
15480
15481  // TAB DATA-API
15482  // ============
15483
15484  $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
15485    e.preventDefault()
15486    $(this).tab('show')
15487  })
15488
15489}(jQuery);
15490
15491
15492/* ========================================================================
15493 * Bootstrap: tooltip.js v3.1.1
15494 * http://getbootstrap.com/javascript/#tooltip
15495 * Inspired by the original jQuery.tipsy by Jason Frame
15496 * ========================================================================
15497 * Copyright 2011-2014 Twitter, Inc.
15498 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
15499 * ======================================================================== */
15500
15501
15502+function ($) {
15503  'use strict';
15504
15505  // TOOLTIP PUBLIC CLASS DEFINITION
15506  // ===============================
15507
15508  var Tooltip = function (element, options) {
15509    this.type       =
15510    this.options    =
15511    this.enabled    =
15512    this.timeout    =
15513    this.hoverState =
15514    this.$element   = null
15515
15516    this.init('tooltip', element, options)
15517  }
15518
15519  Tooltip.DEFAULTS = {
15520    animation: true,
15521    placement: 'top',
15522    selector: false,
15523    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
15524    trigger: 'hover focus',
15525    title: '',
15526    delay: 0,
15527    html: false,
15528    container: false,
15529    viewport: {
15530      selector: 'body',
15531      padding: 0
15532    }
15533  }
15534
15535  Tooltip.prototype.init = function (type, element, options) {
15536    this.enabled   = true
15537    this.type      = type
15538    this.$element  = $(element)
15539    this.options   = this.getOptions(options)
15540    this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
15541
15542    var triggers = this.options.trigger.split(' ')
15543
15544    for (var i = triggers.length; i--;) {
15545      var trigger = triggers[i]
15546
15547      if (trigger == 'click') {
15548        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
15549      } else if (trigger != 'manual') {
15550        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
15551        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
15552
15553        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
15554        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
15555      }
15556    }
15557
15558    this.options.selector ?
15559      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
15560      this.fixTitle()
15561  }
15562
15563  Tooltip.prototype.getDefaults = function () {
15564    return Tooltip.DEFAULTS
15565  }
15566
15567  Tooltip.prototype.getOptions = function (options) {
15568    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
15569
15570    if (options.delay && typeof options.delay == 'number') {
15571      options.delay = {
15572        show: options.delay,
15573        hide: options.delay
15574      }
15575    }
15576
15577    return options
15578  }
15579
15580  Tooltip.prototype.getDelegateOptions = function () {
15581    var options  = {}
15582    var defaults = this.getDefaults()
15583
15584    this._options && $.each(this._options, function (key, value) {
15585      if (defaults[key] != value) options[key] = value
15586    })
15587
15588    return options
15589  }
15590
15591  Tooltip.prototype.enter = function (obj) {
15592    var self = obj instanceof this.con
15592structor ?
15593      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
15594
15595    clearTimeout(self.timeout)
15596
15597    self.hoverState = 'in'
15598
15599    if (!self.options.delay || !self.options.delay.show) return self.show()
15600
15601    self.timeout = setTimeout(function () {
15602      if (self.hoverState == 'in') self.show()
15603    }, self.options.delay.show)
15604  }
15605
15606  Tooltip.prototype.leave = function (obj) {
15607    var self = obj instanceof this.constructor ?
15608      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
15609
15610    clearTimeout(self.timeout)
15611
15612    self.hoverState = 'out'
15613
15614    if (!self.options.delay || !self.options.delay.hide) return self.hide()
15615
15616    self.timeout = setTimeout(function () {
15617      if (self.hoverState == 'out') self.hide()
15618    }, self.options.delay.hide)
15619  }
15620
15621  Tooltip.prototype.show = function () {
15622    var e = $.Event('show.bs.' + this.type)
15623
15624    if (this.hasContent() && this.enabled) {
15625      this.$element.trigger(e)
15626
15627      if (e.isDefaultPrevented()) return
15628      var that = this;
15629
15630      var $tip = this.tip()
15631
15632      this.setContent()
15633
15634      if (this.options.animation) $tip.addClass('fade')
15635
15636      var placement = typeof this.options.placement == 'function' ?
15637        this.options.placement.call(this, $tip[0], this.$element[0]) :
15638        this.options.placement
15639
15640      var autoToken = /\s?auto?\s?/i
15641      var autoPlace = autoToken.test(placement)
15642      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
15643
15644      $tip
15645        .detach()
15646        .css({ top: 0, left: 0, display: 'block' })
15647        .addClass(placement)
15648
15649      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
15650
15651      var pos          = this.getPosition()
15652      var actualWidth  = $tip[0].offsetWidth
15653      var actualHeight = $tip[0].offsetHeight
15654
15655      if (autoPlace) {
15656        var orgPlacement = placement
15657        var $parent      = this.$element.parent()
15658        var parentDim    = this.getPosition($parent)
15659
15660        placement = placement == 'bottom' && pos.top   + pos.height       + actualHeight - parentDim.scroll > parentDim.height ? 'top'    :
15661                    placement == 'top'    && pos.top   - parentDim.scroll - actualHeight < 0                                   ? 'bottom' :
15662                    placement == 'right'  && pos.right + actualWidth      > parentDim.width                                    ? 'left'   :
15663                    placement == 'left'   && pos.left  - actualWidth      < parentDim.left                                     ? 'right'  :
15664                    placement
15665
15666        $tip
15667          .removeClass(orgPlacement)
15668          .addClass(placement)
15669      }
15670
15671      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
15672
15673      this.applyPlacement(calculatedOffset, placement)
15674      this.hoverState = null
15675
15676      var complete = function() {
15677        that.$element.trigger('shown.bs.' + that.type)
15678      }
15679
15680      $.support.transition && this.$tip.hasClass('fade') ?
15681        $tip
15682          .one($.support.transition.end, complete)
15683          .emulateTransitionEnd(150) :
15684        complete()
15685    }
15686  }
15687
15688  Tooltip.prototype.applyPlacement = function (offset, placement) {
15689    var $tip   = this.tip()
15690    var width  = $tip[0].offsetWidth
15691    var height = $tip[0].offsetHeight
15692
15693    // manually read margins because getBoundingClientRect includes difference
15694    var marginTop = parseInt($tip.css('margin-top'), 10)
15695    var marginLeft = parseInt($tip.css('margin-left'), 10)
15696
15697    // we must check for NaN for ie 8/9
15698    if (isNaN(marginTop))  marginTop  = 0
15699    if (isNaN(marginLeft)) marginLeft = 0
15700
15701    offset.top  = offset.top  + marginTop
15702    offset.left = offset.left + marginLeft
15703
15704    // $.fn.offset doesn't round pixel values
15705    // so we use setOffset directly with our own function B-0
15706    $.offset.setOffset($tip[0], $.extend({
15707      using: function (props) {
15708        $tip.css({
15709          top: Math.round(props.top),
15710          left: Math.round(props.left)
15711        })
15712      }
15713    }, offset), 0)
15714
15715    $tip.addClass('in')
15716
15717    // check to see if placing tip in new offset caused the tip to resize itself
15718    var actualWidth  = $tip[0].offsetWidth
15719    var actualHeight = $tip[0].offsetHeight
15720
15721    if (placement == 'top' && actualHeight != height) {
15722      offset.top = offset.top + height - actualHeight
15723    }
15724
15725    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
15726
15727    if (delta.left) offset.left += delta.left
15728    else offset.top += delta.top
15729
15730    var arrowDelta          = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
15731    var arrowPosition       = delta.left ? 'left'        : 'top'
15732    var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
15733
15734    $tip.offset(offset)
15735    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
15736  }
15737
15738  Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
15739    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
15740  }
15741
15742  Tooltip.prototype.setContent = function () {
15743    var $tip  = this.tip()
15744    var title = this.getTitle()
15745
15746    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
15747    $tip.removeClass('fade in top bottom left right')
15748  }
15749
15750  Tooltip.prototype.hide = function () {
15751    var that = this
15752    var $tip = this.tip()
15753    var e    = $.Event('hide.bs.' + this.type)
15754
15755    function complete() {
15756      if (that.hoverState != 'in') $tip.detach()
15757      that.$element.trigger('hidden.bs.' + that.type)
15758    }
15759
15760    this.$element.trigger(e)
15761
15762    if (e.isDefaultPrevented()) return
15763
15764    $tip.removeClass('in')
15765
15766    $.support.transition && this.$tip.hasClass('fade') ?
15767      $tip
15768        .one($.support.transition.end, complete)
15769        .emulateTransitionEnd(150) :
15770      complete()
15771
15772    this.hoverState = null
15773
15774    return this
15775  }
15776
15777  Tooltip.prototype.fixTitle = function () {
15778    var $e = this.$element
15779    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
15780      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
15781    }
15782  }
15783
15784  Tooltip.prototype.hasContent = function () {
15785    return this.getTitle()
15786  }
15787
15788  Tooltip.prototype.getPosition = function ($element) {
15789    $element   = $element || this.$element
15790    var el     = $element[0]
15791    var isBody = el.tagName == 'BODY'
15792    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
15793      scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
15794      width:  isBody ? $(window).width()  : $element.outerWidth(),
15795      height: isBody ? $(window).height() : $element.outerHeight()
15796    }, isBody ? {top: 0, left: 0} : $element.offset())
15797  }
15798
15799  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
15800    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
15801           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
15802           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
15803        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }
15804
15805  }
15806
15807  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
15808    var delta = { top: 0, left: 0 }
15809    if (!this.$viewport) return delta
15810
15811    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
15812    var viewportDimensions = this.getPosition(this.$viewport)
15813
15814    if (/right|left/.test(placement)) {
15815      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
15816      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
15817      if (topEdgeOffset < viewportDimensions.top) { // top overflow
15818        delta.top = viewportDimensions.top - topEdgeOffset
15819      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
15820        delta.top = viewportDimensions.top + viewportDimensions.height - bottom
15820EdgeOffset
15821      }
15822    } else {
15823      var leftEdgeOffset  = pos.left - viewportPadding
15824      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
15825      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
15826        delta.left = viewportDimensions.left - leftEdgeOffset
15827      } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
15828        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
15829      }
15830    }
15831
15832    return delta
15833  }
15834
15835  Tooltip.prototype.getTitle = function () {
15836    var title
15837    var $e = this.$element
15838    var o  = this.options
15839
15840    title = $e.attr('data-original-title')
15841      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
15842
15843    return title
15844  }
15845
15846  Tooltip.prototype.tip = function () {
15847    return this.$tip = this.$tip || $(this.options.template)
15848  }
15849
15850  Tooltip.prototype.arrow = function () {
15851    return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
15852  }
15853
15854  Tooltip.prototype.validate = function () {
15855    if (!this.$element[0].parentNode) {
15856      this.hide()
15857      this.$element = null
15858      this.options  = null
15859    }
15860  }
15861
15862  Tooltip.prototype.enable = function () {
15863    this.enabled = true
15864  }
15865
15866  Tooltip.prototype.disable = function () {
15867    this.enabled = false
15868  }
15869
15870  Tooltip.prototype.toggleEnabled = function () {
15871    this.enabled = !this.enabled
15872  }
15873
15874  Tooltip.prototype.toggle = function (e) {
15875    var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
15876    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
15877  }
15878
15879  Tooltip.prototype.destroy = function () {
15880    clearTimeout(this.timeout)
15881    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
15882  }
15883
15884
15885  // TOOLTIP PLUGIN DEFINITION
15886  // =========================
15887
15888  var old = $.fn.tooltip
15889
15890  $.fn.tooltip = function (option) {
15891    return this.each(function () {
15892      var $this   = $(this)
15893      var data    = $this.data('bs.tooltip')
15894      var options = typeof option == 'object' && option
15895
15896      if (!data && option == 'destroy') return
15897      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
15898      if (typeof option == 'string') data[option]()
15899    })
15900  }
15901
15902  $.fn.tooltip.Constructor = Tooltip
15903
15904
15905  // TOOLTIP NO CONFLICT
15906  // ===================
15907
15908  $.fn.tooltip.noConflict = function () {
15909    $.fn.tooltip = old
15910    return this
15911  }
15912
15913}(jQuery);
15914
15915
15916/* ========================================================================
15917 * Bootstrap: transition.js v3.1.1
15918 * http://getbootstrap.com/javascript/#transitions
15919 * ========================================================================
15920 * Copyright 2011-2014 Twitter, Inc.
15921 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
15922 * ======================================================================== */
15923
15924
15925+function ($) {
15926  'use strict';
15927
15928  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
15929  // ============================================================
15930
15931  function transitionEnd() {
15932    var el = document.createElement('bootstrap')
15933
15934    var transEndEventNames = {
15935      WebkitTransition : 'webkitTransitionEnd',
15936      MozTransition    : 'transitionend',
15937      OTransition      : 'oTransitionEnd otransitionend',
15938      transition       : 'transitionend'
15939    }
15940
15941    for (var name in transEndEventNames) {
15942      if (el.style[name] !== undefined) {
15943        return { end: transEndEventNames[name] }
15944      }
15945    }
15946
15947    return false // explicit for ie8 (  ._.)
15948  }
15949
15950  // http://blog.alexmaccaw.com/css-transitions
15951  $.fn.emulateTransitionEnd = function (duration) {
15952    var called = false, $el = this
15953    $(this).one($.support.transition.end, function () { called = true })
15954    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
15955    setTimeout(callback, duration)
15956    return this
15957  }
15958
15959  $(function () {
15960    $.support.transition = transitionEnd()
15961  })
15962
15963}(jQuery);
15964
15965

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.