vendor/assets/javascripts/furatto.js in furatto-0.0.1 vs vendor/assets/javascripts/furatto.js in furatto-0.0.2

- old
+ new

@@ -1,15 +1,5978 @@ -//= require dropdown -//= require jpanel -//= require jquery.avgrund -//= require jquery.dropkick-1.0.0 -//= require jquery.icheck -//= require jquery.tagsinput -//= require jquery.toolbar -//= require legacy -//= require picker -//= require picker.date -//= require picker.time -//= require rainbow-custom.min -//= require responsive-tables -//= require responsiveslides -//= require tooltip +/* + * Snap.js + * + * Copyright 2013, Jacob Kelley - http://jakiestfu.com/ + * Released under the MIT Licence + * http://opensource.org/licenses/MIT + * + * Github: http://github.com/jakiestfu/Snap.js/ + * Version: 1.9.2 + */ +/*jslint browser: true*/ +/*global define, module, ender*/ +(function(win, doc) { + 'use strict'; + var Snap = Snap || function(userOpts) { + var settings = { + element: null, + dragger: null, + disable: 'none', + addBodyClasses: true, + hyperextensible: true, + resistance: 0.5, + flickThreshold: 50, + transitionSpeed: 0.3, + easing: 'ease', + maxPosition: 266, + minPosition: -266, + tapToClose: true, + touchToDrag: true, + slideIntent: 40, // degrees + minDragDistance: 5 + }, + cache = { + simpleStates: { + opening: null, + towards: null, + hyperExtending: null, + halfway: null, + flick: null, + translation: { + absolute: 0, + relative: 0, + sinceDirectionChange: 0, + percentage: 0 + } + } + }, + eventList = {}, + utils = { + hasTouch: (doc.ontouchstart === null), + eventType: function(action) { + var eventTypes = { + down: (utils.hasTouch ? 'touchstart' : 'mousedown'), + move: (utils.hasTouch ? 'touchmove' : 'mousemove'), + up: (utils.hasTouch ? 'touchend' : 'mouseup'), + out: (utils.hasTouch ? 'touchcancel' : 'mouseout') + }; + return eventTypes[action]; + }, + page: function(t, e){ + return (utils.hasTouch && e.touches.length && e.touches[0]) ? e.touches[0]['page'+t] : e['page'+t]; + }, + klass: { + has: function(el, name){ + return (el.className).indexOf(name) !== -1; + }, + add: function(el, name){ + if(!utils.klass.has(el, name) && settings.addBodyClasses){ + el.className += " "+name; + } + }, + remove: function(el, name){ + if(settings.addBodyClasses){ + el.className = (el.className).replace(name, "").replace(/^\s+|\s+$/g, ''); + } + } + }, + dispatchEvent: function(type) { + if (typeof eventList[type] === 'function') { + return eventList[type].call(); + } + }, + vendor: function(){ + var tmp = doc.createElement("div"), + prefixes = 'webkit Moz O ms'.split(' '), + i; + for (i in prefixes) { + if (typeof tmp.style[prefixes[i] + 'Transition'] !== 'undefined') { + return prefixes[i]; + } + } + }, + transitionCallback: function(){ + return (cache.vendor==='Moz' || cache.vendor==='ms') ? 'transitionend' : cache.vendor+'TransitionEnd'; + }, + canTransform: function(){ + return typeof settings.element.style[cache.vendor+'Transform'] !== 'undefined'; + }, + deepExtend: function(destination, source) { + var property; + for (property in source) { + if (source[property] && source[property].constructor && source[property].constructor === Object) { + destination[property] = destination[property] || {}; + utils.deepExtend(destination[property], source[property]); + } else { + destination[property] = source[property]; + } + } + return destination; + }, + angleOfDrag: function(x, y) { + var degrees, theta; + // Calc Theta + theta = Math.atan2(-(cache.startDragY - y), (cache.startDragX - x)); + if (theta < 0) { + theta += 2 * Math.PI; + } + // Calc Degrees + degrees = Math.floor(theta * (180 / Math.PI) - 180); + if (degrees < 0 && degrees > -180) { + degrees = 360 - Math.abs(degrees); + } + return Math.abs(degrees); + }, + events: { + addEvent: function addEvent(element, eventName, func) { + if (element.addEventListener) { + return element.addEventListener(eventName, func, false); + } else if (element.attachEvent) { + return element.attachEvent("on" + eventName, func); + } + }, + removeEvent: function addEvent(element, eventName, func) { + if (element.addEventListener) { + return element.removeEventListener(eventName, func, false); + } else if (element.attachEvent) { + return element.detachEvent("on" + eventName, func); + } + }, + prevent: function(e) { + if (e.preventDefault) { + e.preventDefault(); + } else { + e.returnValue = false; + } + } + }, + parentUntil: function(el, attr) { + var isStr = typeof attr === 'string'; + while (el.parentNode) { + if (isStr && el.getAttribute && el.getAttribute(attr)){ + return el; + } else if(!isStr && el === attr){ + return el; + } + el = el.parentNode; + } + return null; + } + }, + action = { + translate: { + get: { + matrix: function(index) { + + if( !utils.canTransform() ){ + return parseInt(settings.element.style.left, 10); + } else { + var matrix = win.getComputedStyle(settings.element)[cache.vendor+'Transform'].match(/\((.*)\)/), + ieOffset = 8; + if (matrix) { + matrix = matrix[1].split(','); + if(matrix.length===16){ + index+=ieOffset; + } + return parseInt(matrix[index], 10); + } + return 0; + } + } + }, + easeCallback: function(){ + settings.element.style[cache.vendor+'Transition'] = ''; + cache.translation = action.translate.get.matrix(4); + cache.easing = false; + clearInterval(cache.animatingInterval); + + if(cache.easingTo===0){ + utils.klass.remove(doc.body, 'paneljs-right'); + utils.klass.remove(doc.body, 'paneljs-left'); + } + + utils.dispatchEvent('animated'); + utils.events.removeEvent(settings.element, utils.transitionCallback(), action.translate.easeCallback); + }, + easeTo: function(n) { + + if( !utils.canTransform() ){ + cache.translation = n; + action.translate.x(n); + } else { + cache.easing = true; + cache.easingTo = n; + + settings.element.style[cache.vendor+'Transition'] = 'all ' + settings.transitionSpeed + 's ' + settings.easing; + + cache.animatingInterval = setInterval(function() { + utils.dispatchEvent('animating'); + }, 1); + + utils.events.addEvent(settings.element, utils.transitionCallback(), action.translate.easeCallback); + action.translate.x(n); + } + if(n===0){ + settings.element.style[cache.vendor+'Transform'] = ''; + } + }, + x: function(n) { + if( (settings.disable==='left' && n>0) || + (settings.disable==='right' && n<0) + ){ return; } + + if( !settings.hyperextensible ){ + if( n===settings.maxPosition || n>settings.maxPosition ){ + n=settings.maxPosition; + } else if( n===settings.minPosition || n<settings.minPosition ){ + n=settings.minPosition; + } + } + + n = parseInt(n, 10); + if(isNaN(n)){ + n = 0; + } + + if( utils.canTransform() ){ + var theTranslate = 'translate3d(' + n + 'px, 0,0)'; + settings.element.style[cache.vendor+'Transform'] = theTranslate; + } else { + settings.element.style.width = (win.innerWidth || doc.documentElement.clientWidth)+'px'; + + settings.element.style.left = n+'px'; + settings.element.style.right = ''; + } + } + }, + drag: { + listen: function() { + cache.translation = 0; + cache.easing = false; + utils.events.addEvent(settings.element, utils.eventType('down'), action.drag.startDrag); + utils.events.addEvent(settings.element, utils.eventType('move'), action.drag.dragging); + utils.events.addEvent(settings.element, utils.eventType('up'), action.drag.endDrag); + }, + stopListening: function() { + utils.events.removeEvent(settings.element, utils.eventType('down'), action.drag.startDrag); + utils.events.removeEvent(settings.element, utils.eventType('move'), action.drag.dragging); + utils.events.removeEvent(settings.element, utils.eventType('up'), action.drag.endDrag); + }, + startDrag: function(e) { + // No drag on ignored elements + var target = e.target ? e.target : e.srcElement, + ignoreParent = utils.parentUntil(target, 'data-snap-ignore'); + + if (ignoreParent) { + utils.dispatchEvent('ignore'); + return; + } + + + if(settings.dragger){ + var dragParent = utils.parentUntil(target, settings.dragger); + + // Only use dragger if we're in a closed state + if( !dragParent && + (cache.translation !== settings.minPosition && + cache.translation !== settings.maxPosition + )){ + return; + } + } + + utils.dispatchEvent('start'); + settings.element.style[cache.vendor+'Transition'] = ''; + cache.isDragging = true; + cache.hasIntent = null; + cache.intentChecked = false; + cache.startDragX = utils.page('X', e); + cache.startDragY = utils.page('Y', e); + cache.dragWatchers = { + current: 0, + last: 0, + hold: 0, + state: '' + }; + cache.simpleStates = { + opening: null, + towards: null, + hyperExtending: null, + halfway: null, + flick: null, + translation: { + absolute: 0, + relative: 0, + sinceDirectionChange: 0, + percentage: 0 + } + }; + }, + dragging: function(e) { + if (cache.isDragging && settings.touchToDrag) { + + var thePageX = utils.page('X', e), + thePageY = utils.page('Y', e), + translated = cache.translation, + absoluteTranslation = action.translate.get.matrix(4), + whileDragX = thePageX - cache.startDragX, + openingLeft = absoluteTranslation > 0, + translateTo = whileDragX, + diff; + + // Shown no intent already + if((cache.intentChecked && !cache.hasIntent)){ + return; + } + + if(settings.addBodyClasses){ + if((absoluteTranslation)>0){ + utils.klass.add(doc.body, 'paneljs-left'); + utils.klass.remove(doc.body, 'paneljs-right'); + } else if((absoluteTranslation)<0){ + utils.klass.add(doc.body, 'paneljs-right'); + utils.klass.remove(doc.body, 'paneljs-left'); + } + } + + if (cache.hasIntent === false || cache.hasIntent === null) { + var deg = utils.angleOfDrag(thePageX, thePageY), + inRightRange = (deg >= 0 && deg <= settings.slideIntent) || (deg <= 360 && deg > (360 - settings.slideIntent)), + inLeftRange = (deg >= 180 && deg <= (180 + settings.slideIntent)) || (deg <= 180 && deg >= (180 - settings.slideIntent)); + if (!inLeftRange && !inRightRange) { + cache.hasIntent = false; + } else { + cache.hasIntent = true; + } + cache.intentChecked = true; + } + + if ( + (settings.minDragDistance>=Math.abs(thePageX-cache.startDragX)) || // Has user met minimum drag distance? + (cache.hasIntent === false) + ) { + return; + } + + utils.events.prevent(e); + utils.dispatchEvent('drag'); + + cache.dragWatchers.current = thePageX; + // Determine which direction we are going + if (cache.dragWatchers.last > thePageX) { + if (cache.dragWatchers.state !== 'left') { + cache.dragWatchers.state = 'left'; + cache.dragWatchers.hold = thePageX; + } + cache.dragWatchers.last = thePageX; + } else if (cache.dragWatchers.last < thePageX) { + if (cache.dragWatchers.state !== 'right') { + cache.dragWatchers.state = 'right'; + cache.dragWatchers.hold = thePageX; + } + cache.dragWatchers.last = thePageX; + } + if (openingLeft) { + // Pulling too far to the right + if (settings.maxPosition < absoluteTranslation) { + diff = (absoluteTranslation - settings.maxPosition) * settings.resistance; + translateTo = whileDragX - diff; + } + cache.simpleStates = { + opening: 'left', + towards: cache.dragWatchers.state, + hyperExtending: settings.maxPosition < absoluteTranslation, + halfway: absoluteTranslation > (settings.maxPosition / 2), + flick: Math.abs(cache.dragWatchers.current - cache.dragWatchers.hold) > settings.flickThreshold, + translation: { + absolute: absoluteTranslation, + relative: whileDragX, + sinceDirectionChange: (cache.dragWatchers.current - cache.dragWatchers.hold), + percentage: (absoluteTranslation/settings.maxPosition)*100 + } + }; + } else { + // Pulling too far to the left + if (settings.minPosition > absoluteTranslation) { + diff = (absoluteTranslation - settings.minPosition) * settings.resistance; + translateTo = whileDragX - diff; + } + cache.simpleStates = { + opening: 'right', + towards: cache.dragWatchers.state, + hyperExtending: settings.minPosition > absoluteTranslation, + halfway: absoluteTranslation < (settings.minPosition / 2), + flick: Math.abs(cache.dragWatchers.current - cache.dragWatchers.hold) > settings.flickThreshold, + translation: { + absolute: absoluteTranslation, + relative: whileDragX, + sinceDirectionChange: (cache.dragWatchers.current - cache.dragWatchers.hold), + percentage: (absoluteTranslation/settings.minPosition)*100 + } + }; + } + action.translate.x(translateTo + translated); + } + }, + endDrag: function(e) { + if (cache.isDragging) { + utils.dispatchEvent('end'); + var translated = action.translate.get.matrix(4); + + // Tap Close + if (cache.dragWatchers.current === 0 && translated !== 0 && settings.tapToClose) { + utils.dispatchEvent('close'); + utils.events.prevent(e); + action.translate.easeTo(0); + cache.isDragging = false; + cache.startDragX = 0; + return; + } + + // Revealing Left + if (cache.simpleStates.opening === 'left') { + // Halfway, Flicking, or Too Far Out + if ((cache.simpleStates.halfway || cache.simpleStates.hyperExtending || cache.simpleStates.flick)) { + if (cache.simpleStates.flick && cache.simpleStates.towards === 'left') { // Flicking Closed + action.translate.easeTo(0); + } else if ( + (cache.simpleStates.flick && cache.simpleStates.towards === 'right') || // Flicking Open OR + (cache.simpleStates.halfway || cache.simpleStates.hyperExtending) // At least halfway open OR hyperextending + ) { + action.translate.easeTo(settings.maxPosition); // Open Left + } + } else { + action.translate.easeTo(0); // Close Left + } + // Revealing Right + } else if (cache.simpleStates.opening === 'right') { + // Halfway, Flicking, or Too Far Out + if ((cache.simpleStates.halfway || cache.simpleStates.hyperExtending || cache.simpleStates.flick)) { + if (cache.simpleStates.flick && cache.simpleStates.towards === 'right') { // Flicking Closed + action.translate.easeTo(0); + } else if ( + (cache.simpleStates.flick && cache.simpleStates.towards === 'left') || // Flicking Open OR + (cache.simpleStates.halfway || cache.simpleStates.hyperExtending) // At least halfway open OR hyperextending + ) { + action.translate.easeTo(settings.minPosition); // Open Right + } + } else { + action.translate.easeTo(0); // Close Right + } + } + cache.isDragging = false; + cache.startDragX = utils.page('X', e); + } + } + } + }, + init = function(opts) { + if (opts.element) { + utils.deepExtend(settings, opts); + cache.vendor = utils.vendor(); + action.drag.listen(); + } + }; + /* + * Public + */ + this.open = function(side) { + utils.dispatchEvent('open'); + utils.klass.remove(doc.body, 'paneljs-expand-left'); + utils.klass.remove(doc.body, 'paneljs-expand-right'); + + if (side === 'left') { + cache.simpleStates.opening = 'left'; + cache.simpleStates.towards = 'right'; + utils.klass.add(doc.body, 'paneljs-left'); + utils.klass.remove(doc.body, 'paneljs-right'); + action.translate.easeTo(settings.maxPosition); + } else if (side === 'right') { + cache.simpleStates.opening = 'right'; + cache.simpleStates.towards = 'left'; + utils.klass.remove(doc.body, 'paneljs-left'); + utils.klass.add(doc.body, 'paneljs-right'); + action.translate.easeTo(settings.minPosition); + } + }; + this.close = function() { + utils.dispatchEvent('close'); + action.translate.easeTo(0); + }; + this.expand = function(side){ + var to = win.innerWidth || doc.documentElement.clientWidth; + + if(side==='left'){ + utils.dispatchEvent('expandLeft'); + utils.klass.add(doc.body, 'paneljs-expand-left'); + utils.klass.remove(doc.body, 'paneljs-expand-right'); + } else { + utils.dispatchEvent('expandRight'); + utils.klass.add(doc.body, 'paneljs-expand-right'); + utils.klass.remove(doc.body, 'paneljs-expand-left'); + to *= -1; + } + action.translate.easeTo(to); + }; + + this.on = function(evt, fn) { + eventList[evt] = fn; + return this; + }; + this.off = function(evt) { + if (eventList[evt]) { + eventList[evt] = false; + } + }; + + this.enable = function() { + utils.dispatchEvent('enable'); + action.drag.listen(); + }; + this.disable = function() { + utils.dispatchEvent('disable'); + action.drag.stopListening(); + }; + + this.settings = function(opts){ + utils.deepExtend(settings, opts); + }; + + this.state = function() { + var state, + fromLeft = action.translate.get.matrix(4); + if (fromLeft === settings.maxPosition) { + state = 'left'; + } else if (fromLeft === settings.minPosition) { + state = 'right'; + } else { + state = 'closed'; + } + return { + state: state, + info: cache.simpleStates + }; + }; + init(userOpts); + }; + if ((typeof module !== 'undefined') && module.exports) { + module.exports = Snap; + } + if (typeof ender === 'undefined') { + this.Snap = Snap; + } + if ((typeof define === "function") && define.amd) { + define("snap", [], function() { + return Snap; + }); + } +}).call(this, window, document); +// Generated by CoffeeScript 1.6.3 +(function($, window) { + "use strict"; + var Panel; + Panel = (function() { + Panel.DEFAULTS = { + element: null, + dragger: null, + disable: 'right', + addBodyClasses: true, + hyperextensible: true, + resistance: 0.5, + flickThreshold: 50, + transitionSpeed: 0.3, + easing: 'ease', + maxPosition: 266, + minPosition: -266, + tapToClose: true, + touchToDrag: false, + slideIntent: 40, + minDragDistance: 5 + }; + + function Panel(el, options) { + this.options = $.extend(options, { + element: el + }); + this.menu = $($('[data-toggle="panel"]').data('target')); + this.append_menu_to_panel(); + this.snapper = new Snap(this.options); + } + + Panel.prototype.apply_ios_devices_fix = function() { + if (navigator.userAgent.match(/(iPad|iPhone|iPod)/g)) { + return $('.panel-content').css({ + 'overflow': 'visible' + }); + } + }; + + Panel.prototype.append_menu_to_panel = function() { + return $('.panel-left').html(this.menu.html()); + }; + + Panel.prototype.toggle = function() { + $('.panel').css('display', 'block'); + if (this.snapper.state().state === "left") { + return this.snapper.close(); + } else { + return this.snapper.open('left'); + } + }; + + return Panel; + + })(); + $.fn.panel = function(option) { + return this.each(function() { + var $this, data, options; + $this = $(this); + data = $this.data('Panel'); + options = $.extend({}, Panel.DEFAULTS, $this.data(), typeof option === 'object' && option); + if (!data) { + $this.data('Panel', (data = new Panel(this, options))); + } + if (typeof option === 'string') { + return data[option](); + } + }); + }; + $(document).on('click', '[data-toggle="panel"]', function(e) { + e.preventDefault(); + return $('.panel-content').panel('toggle'); + }); + return $(document).ready(function() { + return $('.panel-content').panel('apply_ios_devices_fix'); + }); +})(window.jQuery, window); +/** + * Toolbar.js + * + * @fileoverview jQuery plugin that creates tooltip style toolbars. + * @link http://paulkinzett.github.com/toolbar/ + * @author Paul Kinzett (http://kinzett.co.nz/) + * @version 1.0.4 + * @requires jQuery 1.7+ + * + * @license jQuery Toolbar Plugin v1.0.4 + * http://paulkinzett.github.com/toolbar/ + * Copyright 2013 Paul Kinzett (http://kinzett.co.nz/) + * Released under the MIT license. + * <https://raw.github.com/paulkinzett/toolbar/master/LICENSE.txt> + */ + +if ( typeof Object.create !== 'function' ) { + Object.create = function( obj ) { + function F() {} + F.prototype = obj; + return new F(); + }; +} + +(function( $, window, document, undefined ) { + + var ToolBar = { + init: function( options, elem ) { + var self = this; + self.elem = elem; + self.$elem = $( elem ); + self.options = $.extend( {}, $.fn.toolbar.options, options ); + self.toolbar = $('<div class="tool-container gradient" />') + .addClass('tool-'+self.options.position) + .addClass('tool-rounded') + .append('<div class="tool-items" />') + .append('<div class="arrow" />') + .appendTo('body') + .css('opacity', 0) + .hide(); + self.toolbar_arrow = self.toolbar.find('.arrow'); + self.initializeToolbar(); + }, + + initializeToolbar: function() { + var self = this; + self.populateContent(); + self.setTrigger(); + self.toolbarWidth = self.toolbar.width(); + }, + + setTrigger: function() { + var self = this; + + self.$elem.on('click', function(event) { + event.preventDefault(); + if(self.$elem.hasClass('pressed')) { + self.hide(); + } else { + self.show(); + } + }); + + if (self.options.hideOnClick) { + $('html').on("click.toolbar", function ( event ) { + if (event.target != self.elem && + self.$elem.has(event.target).length === 0 && + self.toolbar.has(event.target).length === 0 && + self.toolbar.is(":visible")) { + self.hide(); + } + }); + } + + $(window).resize(function( event ) { + event.stopPropagation(); + if ( self.toolbar.is(":visible") ) { + self.toolbarCss = self.getCoordinates(self.options.position, 20); + self.collisionDetection(); + self.toolbar.css( self.toolbarCss ); + self.toolbar_arrow.css( self.arrowCss ); + } + }); + }, + + populateContent: function() { + var self = this; + var location = self.toolbar.find('.tool-items'); + var content = $(self.options.content).clone( true ).find('a').addClass('tool-item gradient'); + location.html(content); + location.find('.tool-item').on('click', function(event) { + event.preventDefault(); + self.$elem.trigger('toolbarItemClick', this); + }); + }, + + calculatePosition: function() { + var self = this; + self.arrowCss = {}; + self.toolbarCss = self.getCoordinates(self.options.position, 0); + self.toolbarCss.position = 'absolute'; + self.toolbarCss.zIndex = self.options.zIndex; + self.collisionDetection(); + self.toolbar.css(self.toolbarCss); + self.toolbar_arrow.css(self.arrowCss); + }, + + getCoordinates: function( position, adjustment ) { + var self = this; + self.coordinates = self.$elem.offset(); + + if (self.options.adjustment && self.options.adjustment[self.options.position]) { + adjustment = self.options.adjustment[self.options.position]; + } + + switch(self.options.position) { + case 'top': + return { + left: self.coordinates.left-(self.toolbar.width()/2)+(self.$elem.outerWidth()/2), + top: self.coordinates.top-self.$elem.height()-adjustment, + right: 'auto' + }; + case 'left': + return { + left: self.coordinates.left-(self.toolbar.width()/2)-(self.$elem.width()/2)-adjustment, + top: self.coordinates.top-(self.toolbar.height()/2)+(self.$elem.outerHeight()/2), + right: 'auto' + }; + case 'right': + return { + left: self.coordinates.left+(self.toolbar.width()/2)+(self.$elem.width()/3)+adjustment, + top: self.coordinates.top-(self.toolbar.height()/2)+(self.$elem.outerHeight()/2), + right: 'auto' + }; + case 'bottom': + return { + left: self.coordinates.left-(self.toolbar.width()/2)+(self.$elem.outerWidth()/2), + top: self.coordinates.top+self.$elem.height()+adjustment, + right: 'auto' + }; + } + }, + + collisionDetection: function() { + var self = this; + var edgeOffset = 20; + if(self.options.position == 'top' || self.options.position == 'bottom') { + self.arrowCss = {left: '50%', right: '50%'}; + if( self.toolbarCss.left < edgeOffset ) { + self.toolbarCss.left = edgeOffset; + self.arrowCss.left = self.$elem.offset().left + self.$elem.width()/2-(edgeOffset); + } + else if(($(window).width() - (self.toolbarCss.left + self.toolbarWidth)) < edgeOffset) { + self.toolbarCss.right = edgeOffset; + self.toolbarCss.left = 'auto'; + self.arrowCss.left = 'auto'; + self.arrowCss.right = ($(window).width()-self.$elem.offset().left)-(self.$elem.width()/2)-(edgeOffset)-5; + } + } + }, + + show: function() { + var self = this; + var animation = {'opacity': 1}; + + self.$elem.addClass('pressed'); + self.calculatePosition(); + + switch(self.options.position) { + case 'top': + animation.top = '-=20'; + break; + case 'left': + animation.left = '-=20'; + break; + case 'right': + animation.left = '+=20'; + break; + case 'bottom': + animation.top = '+=20'; + break; + } + + self.toolbar.show().animate(animation, 200 ); + self.$elem.trigger('toolbarShown'); + }, + + hide: function() { + var self = this; + var animation = {'opacity': 0}; + + self.$elem.removeClass('pressed'); + + switch(self.options.position) { + case 'top': + animation.top = '+=20'; + break; + case 'left': + animation.left = '+=20'; + break; + case 'right': + animation.left = '-=20'; + break; + case 'bottom': + animation.top = '-=20'; + break; + } + + self.toolbar.animate(animation, 200, function() { + self.toolbar.hide(); + }); + + self.$elem.trigger('toolbarHidden'); + }, + + getToolbarElement: function () { + return this.toolbar.find('.tool-items'); + } + }; + + $.fn.toolbar = function( options ) { + if ($.isPlainObject( options )) { + return this.each(function() { + var toolbarObj = Object.create( ToolBar ); + toolbarObj.init( options, this ); + $(this).data('toolbarObj', toolbarObj); + }); + } else if ( typeof options === 'string' && options.indexOf('_') !== 0 ) { + var toolbarObj = $(this).data('toolbarObj'); + var method = toolbarObj[options]; + return method.apply(toolbarObj, $.makeArray(arguments).slice(1)); + } + }; + + $.fn.toolbar.options = { + content: '#myContent', + position: 'top', + hideOnClick: false, + zIndex: 120 + }; + +}) ( jQuery, window, document ); +// Generated by CoffeeScript 1.6.3 +$(document).ready(function() { + return $('[data-furatto="toolbar"]').each(function() { + return $(this).toolbar({ + content: $(this).data('content'), + position: $(this).data('position') || 'top', + hideOnClick: true + }); + }); +}); +/* Rainbow v1.2 rainbowco.de | included languages: generic, shell, javascript, html, css */ +window.Rainbow=function(){function q(a){var b,c=a.getAttribute&&a.getAttribute("data-language")||0;if(!c){a=a.attributes;for(b=0;b<a.length;++b)if("data-language"===a[b].nodeName)return a[b].nodeValue}return c}function B(a){var b=q(a)||q(a.parentNode);if(!b){var c=/\blang(?:uage)?-(\w+)/;(a=a.className.match(c)||a.parentNode.className.match(c))&&(b=a[1])}return b}function C(a,b){for(var c in f[d]){c=parseInt(c,10);if(a==c&&b==f[d][c]?0:a<=c&&b>=f[d][c])delete f[d][c],delete j[d][c];if(a>=c&&a<f[d][c]|| +b>c&&b<f[d][c])return!0}return!1}function r(a,b){return'<span class="'+a.replace(/\./g," ")+(l?" "+l:"")+'">'+b+"</span>"}function s(a,b,c,i){var e=a.exec(c);if(e){++t;!b.name&&"string"==typeof b.matches[0]&&(b.name=b.matches[0],delete b.matches[0]);var k=e[0],g=e.index,u=e[0].length+g,h=function(){function e(){s(a,b,c,i)}t%100>0?e():setTimeout(e,0)};if(C(g,u))h();else{var m=v(b.matches),l=function(a,c,i){if(a>=c.length)i(k);else{var d=e[c[a]];if(d){var g=b.matches[c[a]],f=g.language,h=g.name&&g.matches? +g.matches:g,j=function(b,d,g){var f;f=0;var h;for(h=1;h<c[a];++h)e[h]&&(f=f+e[h].length);d=g?r(g,d):d;k=k.substr(0,f)+k.substr(f).replace(b,d.replace("$'","$$$$'"));l(++a,c,i)};f?n(d,f,function(a){j(d,a)}):typeof g==="string"?j(d,d,g):w(d,h.length?h:[h],function(a){j(d,a,g.matches?g.name:0)})}else l(++a,c,i)}};l(0,m,function(a){b.name&&(a=r(b.name,a));if(!j[d]){j[d]={};f[d]={}}j[d][g]={replace:e[0],"with":a};f[d][g]=u;h()})}}else i()}function v(a){var b=[],c;for(c in a)a.hasOwnProperty(c)&&b.push(c); +return b.sort(function(a,b){return b-a})}function w(a,b,c){function i(b,k){k<b.length?s(b[k].pattern,b[k],a,function(){i(b,++k)}):D(a,function(a){delete j[d];delete f[d];--d;c(a)})}++d;i(b,0)}function D(a,b){function c(a,b,i,f){if(i<b.length){++x;var h=b[i],l=j[d][h],a=a.substr(0,h)+a.substr(h).replace(l.replace,l["with"].replace("$'","$$$$'")),h=function(){c(a,b,++i,f)};0<x%250?h():setTimeout(h,0)}else f(a)}var i=v(j[d]);c(a,i,0,b)}function n(a,b,c){var d=m[b]||[],e=m[y]||[],b=z[b]?d:d.concat(e); +w(a.replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/&(?![\w\#]+;)/g,"&amp;"),b,c)}function o(a,b,c){if(b<a.length){var d=a[b],e=B(d);return!(-1<(" "+d.className+" ").indexOf(" rainbow "))&&e?(e=e.toLowerCase(),d.className+=d.className?" rainbow":"rainbow",n(d.innerHTML,e,function(k){d.innerHTML=k;j={};f={};p&&p(d,e);setTimeout(function(){o(a,++b,c)},0)})):o(a,++b,c)}c&&c()}function A(a,b){var a=a&&"function"==typeof a.getElementsByTagName?a:document,c=a.getElementsByTagName("pre"),d=a.getElementsByTagName("code"), +e,f=[],g=[];for(e=0;e<c.length;++e)c[e].getElementsByTagName("code").length?c[e].innerHTML=c[e].innerHTML.replace(/^\s+/,"").replace(/\s+$/,""):f.push(c[e]);for(e=0;e<d.length;++e)g.push(d[e]);o(g.concat(f),0,b)}var j={},f={},m={},z={},d=0,y=0,t=0,x=0,l,p;return{extend:function(a,b,c){1==arguments.length&&(b=a,a=y);z[a]=c;m[a]=b.concat(m[a]||[])},b:function(a){p=a},a:function(a){l=a},color:function(a,b,c){if("string"==typeof a)return n(a,b,c);if("function"==typeof a)return A(0,a);A(a,b)}}}(); +document.addEventListener?document.addEventListener("DOMContentLoaded",Rainbow.color,!1):window.attachEvent("onload",Rainbow.color);Rainbow.onHighlight=Rainbow.b;Rainbow.addClass=Rainbow.a;Rainbow.extend([{matches:{1:{name:"keyword.operator",pattern:/\=/g},2:{name:"string",matches:{name:"constant.character.escape",pattern:/\\('|"){1}/g}}},pattern:/(\(|\s|\[|\=|:)(('|")([^\\\1]|\\.)*?(\3))/gm},{name:"comment",pattern:/\/\*[\s\S]*?\*\/|(\/\/|\#)[\s\S]*?$/gm},{name:"constant.numeric",pattern:/\b(\d+(\.\d+)?(e(\+|\-)?\d+)?(f|d)?|0x[\da-f]+)\b/gi},{matches:{1:"keyword"},pattern:/\b(and|array|as|b(ool(ean)?|reak)|c(ase|atch|har|lass|on(st|tinue))|d(ef|elete|o(uble)?)|e(cho|lse(if)?|xit|xtends|xcept)|f(inally|loat|or(each)?|unction)|global|if|import|int(eger)?|long|new|object|or|pr(int|ivate|otected)|public|return|self|st(ring|ruct|atic)|switch|th(en|is|row)|try|(un)?signed|var|void|while)(?=\(|\b)/gi}, +{name:"constant.language",pattern:/true|false|null/g},{name:"keyword.operator",pattern:/\+|\!|\-|&(gt|lt|amp);|\||\*|\=/g},{matches:{1:"function.call"},pattern:/(\w+?)(?=\()/g},{matches:{1:"storage.function",2:"entity.name.function"},pattern:/(function)\s(.*?)(?=\()/g}]);Rainbow.extend("shell",[{name:"shell",matches:{1:{language:"shell"}},pattern:/\$\(([\s\S]*?)\)/gm},{matches:{2:"string"},pattern:/(\(|\s|\[|\=)(('|")[\s\S]*?(\3))/gm},{name:"keyword.operator",pattern:/&lt;|&gt;|&amp;/g},{name:"comment",pattern:/\#[\s\S]*?$/gm},{name:"storage.function",pattern:/(.+?)(?=\(\)\s{0,}\{)/g},{name:"support.command",pattern:/\b(echo|rm|ls|(mk|rm)dir|cd|find|cp|exit|pwd|exec|trap|source|shift|unset)/g},{matches:{1:"keyword"},pattern:/\b(break|case|continue|do|done|elif|else|esac|eval|export|fi|for|function|if|in|local|return|set|then|unset|until|while)(?=\(|\b)/g}], +!0);Rainbow.extend("javascript",[{name:"selector",pattern:/(\s|^)\$(?=\.|\()/g},{name:"support",pattern:/\b(window|document)\b/g},{matches:{1:"support.property"},pattern:/\.(length|node(Name|Value))\b/g},{matches:{1:"support.function"},pattern:/(setTimeout|setInterval)(?=\()/g},{matches:{1:"support.method"},pattern:/\.(getAttribute|push|getElementById|getElementsByClassName|log|setTimeout|setInterval)(?=\()/g},{name:"string.regexp",matches:{1:"string.regexp.open",2:{name:"constant.regexp.escape",pattern:/\\(.){1}/g}, +3:"string.regexp.close",4:"string.regexp.modifier"},pattern:/(\/)(?!\*)(.+)(\/)([igm]{0,3})/g},{matches:{1:"storage",3:"entity.function"},pattern:/(var)?(\s|^)(\S*)(?=\s?=\s?function\()/g},{matches:{1:"keyword",2:"entity.function"},pattern:/(new)\s+(.*)(?=\()/g},{name:"entity.function",pattern:/(\w+)(?=:\s{0,}function)/g}]);Rainbow.extend("html",[{name:"source.php.embedded",matches:{2:{language:"php"}},pattern:/&lt;\?=?(?!xml)(php)?([\s\S]*?)(\?&gt;)/gm},{name:"source.css.embedded",matches:{1:{matches:{1:"support.tag.style",2:[{name:"string",pattern:/('|")(.*?)(\1)/g},{name:"entity.tag.style",pattern:/(\w+)/g}],3:"support.tag.style"},pattern:/(&lt;\/?)(style.*?)(&gt;)/g},2:{language:"css"},3:"support.tag.style",4:"entity.tag.style",5:"support.tag.style"},pattern:/(&lt;style.*?&gt;)([\s\S]*?)(&lt;\/)(style)(&gt;)/gm}, +{name:"source.js.embedded",matches:{1:{matches:{1:"support.tag.script",2:[{name:"string",pattern:/('|")(.*?)(\1)/g},{name:"entity.tag.script",pattern:/(\w+)/g}],3:"support.tag.script"},pattern:/(&lt;\/?)(script.*?)(&gt;)/g},2:{language:"javascript"},3:"support.tag.script",4:"entity.tag.script",5:"support.tag.script"},pattern:/(&lt;script(?! src).*?&gt;)([\s\S]*?)(&lt;\/)(script)(&gt;)/gm},{name:"comment.html",pattern:/&lt;\!--[\S\s]*?--&gt;/g},{matches:{1:"support.tag.open",2:"support.tag.close"}, +pattern:/(&lt;)|(\/?\??&gt;)/g},{name:"support.tag",matches:{1:"support.tag",2:"support.tag.special",3:"support.tag-name"},pattern:/(&lt;\??)(\/|\!?)(\w+)/g},{matches:{1:"support.attribute"},pattern:/([a-z-]+)(?=\=)/gi},{matches:{1:"support.operator",2:"string.quote",3:"string.value",4:"string.quote"},pattern:/(=)('|")(.*?)(\2)/g},{matches:{1:"support.operator",2:"support.value"},pattern:/(=)([a-zA-Z\-0-9]*)\b/g},{matches:{1:"support.attribute"},pattern:/\s(\w+)(?=\s|&gt;)(?![\s\S]*&lt;)/g}],!0);Rainbow.extend("css",[{name:"comment",pattern:/\/\*[\s\S]*?\*\//gm},{name:"constant.hex-color",pattern:/#([a-f0-9]{3}|[a-f0-9]{6})(?=;|\s|,|\))/gi},{matches:{1:"constant.numeric",2:"keyword.unit"},pattern:/(\d+)(px|em|cm|s|%)?/g},{name:"string",pattern:/('|")(.*?)\1/g},{name:"support.css-property",matches:{1:"support.vendor-prefix"},pattern:/(-o-|-moz-|-webkit-|-ms-)?[\w-]+(?=\s?:)(?!.*\{)/g},{matches:{1:[{name:"entity.name.sass",pattern:/&amp;/g},{name:"direct-descendant",pattern:/&gt;/g},{name:"entity.name.class", +pattern:/\.[\w\-_]+/g},{name:"entity.name.id",pattern:/\#[\w\-_]+/g},{name:"entity.name.pseudo",pattern:/:[\w\-_]+/g},{name:"entity.name.tag",pattern:/\w+/g}]},pattern:/([\w\ ,\n:\.\#\&\;\-_]+)(?=.*\{)/g},{matches:{2:"support.vendor-prefix",3:"support.css-value"},pattern:/(:|,)\s*(-o-|-moz-|-webkit-|-ms-)?([a-zA-Z-]*)(?=\b)(?!.*\{)/g}],!0); +/* =========================================================== + * bootstrap-tooltip.js v2.3.0 + * http://twitter.github.com/bootstrap/javascript.html#tooltips + * Inspired by the original jQuery.tipsy by Jason Frame + * =========================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* TOOLTIP PUBLIC CLASS DEFINITION + * =============================== */ + + var Tooltip = function (element, options) { + this.init('tooltip', element, options) + } + + Tooltip.prototype = { + + constructor: Tooltip + + , init: function (type, element, options) { + var eventIn + , eventOut + , triggers + , trigger + , i + + this.type = type + this.$element = $(element) + this.options = this.getOptions(options) + this.enabled = true + + triggers = this.options.trigger.split(' ') + + for (i = triggers.length; i--;) { + trigger = triggers[i] + if (trigger == 'click') { + this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) + } else if (trigger != 'manual') { + eventIn = trigger == 'hover' ? 'mouseenter' : 'focus' + eventOut = trigger == 'hover' ? 'mouseleave' : 'blur' + this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) + this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) + } + } + + this.options.selector ? + (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : + this.fixTitle() + } + + , getOptions: function (options) { + options = $.extend({}, $.fn[this.type].defaults, this.$element.data(), options) + + if (options.delay && typeof options.delay == 'number') { + options.delay = { + show: options.delay + , hide: options.delay + } + } + + return options + } + + , enter: function (e) { + var self = $(e.currentTarget)[this.type](this._options).data(this.type) + + if (!self.options.delay || !self.options.delay.show) return self.show() + + clearTimeout(this.timeout) + self.hoverState = 'in' + this.timeout = setTimeout(function() { + if (self.hoverState == 'in') self.show() + }, self.options.delay.show) + } + + , leave: function (e) { + var self = $(e.currentTarget)[this.type](this._options).data(this.type) + + if (this.timeout) clearTimeout(this.timeout) + if (!self.options.delay || !self.options.delay.hide) return self.hide() + + self.hoverState = 'out' + this.timeout = setTimeout(function() { + if (self.hoverState == 'out') self.hide() + }, self.options.delay.hide) + } + + , show: function () { + var $tip + , pos + , actualWidth + , actualHeight + , placement + , tp + , e = $.Event('show') + + if (this.hasContent() && this.enabled) { + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + $tip = this.tip() + this.setContent() + + if (this.options.animation) { + $tip.addClass('fade') + } + + placement = typeof this.options.placement == 'function' ? + this.options.placement.call(this, $tip[0], this.$element[0]) : + this.options.placement + + $tip + .detach() + .css({ top: 0, left: 0, display: 'block' }) + + this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) + + pos = this.getPosition() + + actualWidth = $tip[0].offsetWidth + actualHeight = $tip[0].offsetHeight + + switch (placement) { + case 'bottom': + tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2} + break + case 'top': + tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2} + break + case 'left': + tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth} + break + case 'right': + tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width} + break + } + + this.applyPlacement(tp, placement) + this.$element.trigger('shown') + } + } + + , applyPlacement: function(offset, placement){ + var $tip = this.tip() + , width = $tip[0].offsetWidth + , height = $tip[0].offsetHeight + , actualWidth + , actualHeight + , delta + , replace + + $tip + .offset(offset) + .addClass(placement) + .addClass('in') + + actualWidth = $tip[0].offsetWidth + actualHeight = $tip[0].offsetHeight + + if (placement == 'top' && actualHeight != height) { + offset.top = offset.top + height - actualHeight + replace = true + } + + if (placement == 'bottom' || placement == 'top') { + delta = 0 + + if (offset.left < 0){ + delta = offset.left * -2 + offset.left = 0 + $tip.offset(offset) + actualWidth = $tip[0].offsetWidth + actualHeight = $tip[0].offsetHeight + } + + this.replaceArrow(delta - width + actualWidth, actualWidth, 'left') + } else { + this.replaceArrow(actualHeight - height, actualHeight, 'top') + } + + if (replace) $tip.offset(offset) + } + + , replaceArrow: function(delta, dimension, position){ + this + .arrow() + .css(position, delta ? (50 * (1 - delta / dimension) + "%") : '') + } + + , setContent: function () { + var $tip = this.tip() + , title = this.getTitle() + + $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) + $tip.removeClass('fade in top bottom left right') + } + + , hide: function () { + var that = this + , $tip = this.tip() + , e = $.Event('hide') + + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + + $tip.removeClass('in') + + function removeWithAnimation() { + var timeout = setTimeout(function () { + $tip.off($.support.transition.end).detach() + }, 500) + + $tip.one($.support.transition.end, function () { + clearTimeout(timeout) + $tip.detach() + }) + } + + $.support.transition && this.$tip.hasClass('fade') ? + removeWithAnimation() : + $tip.detach() + + this.$element.trigger('hidden') + + return this + } + + , fixTitle: function () { + var $e = this.$element + if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { + $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') + } + } + + , hasContent: function () { + return this.getTitle() + } + + , getPosition: function () { + var el = this.$element[0] + return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : { + width: el.offsetWidth + , height: el.offsetHeight + }, this.$element.offset()) + } + + , getTitle: function () { + var title + , $e = this.$element + , o = this.options + + title = $e.attr('data-original-title') + || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) + + return title + } + + , tip: function () { + return this.$tip = this.$tip || $(this.options.template) + } + + , arrow: function(){ + return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow") + } + + , validate: function () { + if (!this.$element[0].parentNode) { + this.hide() + this.$element = null + this.options = null + } + } + + , enable: function () { + this.enabled = true + } + + , disable: function () { + this.enabled = false + } + + , toggleEnabled: function () { + this.enabled = !this.enabled + } + + , toggle: function (e) { + var self = e ? $(e.currentTarget)[this.type](this._options).data(this.type) : this + self.tip().hasClass('in') ? self.hide() : self.show() + } + + , destroy: function () { + this.hide().$element.off('.' + this.type).removeData(this.type) + } + + } + + + /* TOOLTIP PLUGIN DEFINITION + * ========================= */ + + var old = $.fn.tooltip + + $.fn.tooltip = function ( option ) { + return this.each(function () { + var $this = $(this) + , data = $this.data('tooltip') + , options = typeof option == 'object' && option + if (!data) $this.data('tooltip', (data = new Tooltip(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.tooltip.Constructor = Tooltip + + $.fn.tooltip.defaults = { + animation: true + , placement: 'top' + , selector: false + , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>' + , trigger: 'hover focus' + , title: '' + , delay: 0 + , html: false + , container: false + } + + + /* TOOLTIP NO CONFLICT + * =================== */ + + $.fn.tooltip.noConflict = function () { + $.fn.tooltip = old + return this + } + +}(window.jQuery); + +/*! + * pickadate.js v3.1.1, 2013/06/28 + * By Amsul, http://amsul.ca + * Hosted on http://amsul.github.io/pickadate.js + * Licensed under MIT + */ + +/*jshint + debug: true, + devel: true, + browser: true, + asi: true, + unused: true, + boss: true, + eqnull: true + */ + + +// Create a global scope. +window.Picker = (function( $, $document, undefined ) { + + +/** + * The picker constructor that creates a blank picker. + */ +function PickerConstructor( ELEMENT, NAME, COMPONENT, OPTIONS ) { + + // If there’s no element, return the picker constructor. + if ( !ELEMENT ) return PickerConstructor + + + var + // The state of the picker. + STATE = { + id: Math.abs( ~~( Math.random() * 1e9 ) ) + }, + + + // Merge the defaults and options passed. + SETTINGS = COMPONENT ? $.extend( true, {}, COMPONENT.defaults, OPTIONS ) : OPTIONS || {}, + + + // Merge the default classes with the settings classes. + CLASSES = $.extend( {}, PickerConstructor.klasses(), SETTINGS.klass ), + + + // The element node wrapper into a jQuery object. + $ELEMENT = $( ELEMENT ), + + + // Pseudo picker constructor. + PickerInstance = function() { + return this.start() + }, + + + // The picker prototype. + P = PickerInstance.prototype = { + + constructor: PickerInstance, + + $node: $ELEMENT, + + + /** + * Initialize everything + */ + start: function() { + + // If it’s already started, do nothing. + if ( STATE && STATE.start ) return P + + + // Update the picker states. + STATE.methods = {} + STATE.start = true + STATE.open = false + STATE.type = ELEMENT.type + + + // Confirm focus state, save original type, convert into text input + // to remove UA stylings, and set as readonly to prevent keyboard popup. + ELEMENT.autofocus = ELEMENT == document.activeElement + ELEMENT.type = 'text' + ELEMENT.readOnly = true + + + // Create a new picker component with the settings. + P.component = new COMPONENT( P, SETTINGS ) + + + // Create the picker root with a new wrapped holder and bind the events. + P.$root = $( PickerConstructor._.node( 'div', createWrappedComponent(), CLASSES.picker ) ).on({ + + // When something within the root is focused, stop from bubbling + // to the doc and remove the “focused” state from the root. + focusin: function( event ) { + P.$root.removeClass( CLASSES.focused ) + event.stopPropagation() + }, + + // If the event is not on the root holder, stop it from bubbling to the doc. + mousedown: function( event ) { + if ( event.target != P.$root.children()[ 0 ] ) { + event.stopPropagation() + } + }, + + // When something within the root holder is clicked, handle the various event. + click: function( event ) { + + var target = event.target, + $target = target.attributes.length ? $( target ) : $( target ).closest( '[data-pick]' ), + targetData = $target.data() + + // If the event is not on the root holder itself, handle the clicks within. + if ( target != P.$root.children()[ 0 ] ) { + + // Stop it from propagating to the doc. + event.stopPropagation() + + // If nothing inside is actively focused, re-focus the element. + if ( !P.$root.find( document.activeElement ).length ) { + ELEMENT.focus() + } + + // If something is superficially changed, update the `highlight` based on the `nav`. + if ( targetData.nav && !$target.hasClass( CLASSES.navDisabled ) ) { + P.set( 'highlight', P.component.item.highlight, { nav: targetData.nav } ) + } + + // If something is picked, set `select` then close with focus. + else if ( PickerConstructor._.isInteger( targetData.pick ) && !$target.hasClass( CLASSES.disabled ) ) { + P.set( 'select', targetData.pick ).close( true ) + } + + // If a “clear” button is pressed, empty the values and close with focus. + else if ( targetData.clear ) { + P.clear().close( true ) + } + } + } + }) //P.$root + + + // If there’s a format for the hidden input element, create the element + // using the name of the original input plus suffix. Otherwise set it to null. + // If the element has a value, use either the `data-value` or `value`. + P._hidden = SETTINGS.formatSubmit ? $( '<input type=hidden name=' + ELEMENT.name + ( SETTINGS.hiddenSuffix || '_submit' ) + ( $ELEMENT.data( 'value' ) ? ' value="' + PickerConstructor._.trigger( P.component.formats.toString, P.component, [ SETTINGS.formatSubmit, P.component.item.select ] ) + '"' : '' ) + '>' )[ 0 ] : undefined + + + // Add the class and bind the events on the element. + $ELEMENT.addClass( CLASSES.input ). + + // On focus/click, open the picker and adjust the root “focused” state. + on( 'focus.P' + STATE.id + ' click.P' + STATE.id, focusToOpen ). + + // If the value changes, update the hidden input with the correct format. + on( 'change.P' + STATE.id, function() { + if ( P._hidden ) { + P._hidden.value = ELEMENT.value ? PickerConstructor._.trigger( P.component.formats.toString, P.component, [ SETTINGS.formatSubmit, P.component.item.select ] ) : '' + } + }). + + // Handle keyboard event based on the picker being opened or not. + on( 'keydown.P' + STATE.id, function( event ) { + + var keycode = event.keyCode, + + // Check if one of the delete keys was pressed. + isKeycodeDelete = /^(8|46)$/.test( keycode ) + + // For some reason IE clears the input value on “escape”. + if ( keycode == 27 ) { + P.close() + return false + } + + // Check if `space` or `delete` was pressed or the picker is closed with a key movement. + if ( keycode == 32 || isKeycodeDelete || !STATE.open && P.component.key[ keycode ] ) { + + // Prevent it from moving the page and bubbling to doc. + event.preventDefault() + event.stopPropagation() + + // If `delete` was pressed, clear the values and close the picker. + // Otherwise open the picker. + if ( isKeycodeDelete ) { P.clear().close() } + else { P.open() } + } + }). + + // If there’s a `data-value`, update the value of the element. + val( $ELEMENT.data( 'value' ) ? PickerConstructor._.trigger( P.component.formats.toString, P.component, [ SETTINGS.format, P.component.item.select ] ) : ELEMENT.value ). + + // Insert the root and hidden input after the element. + after( P.$root, P._hidden ). + + // Store the picker data by component name. + data( NAME, P ) + + + // Bind the default component and settings events. + P.on({ + start: P.component.onStart, + render: P.component.onRender, + stop: P.component.onStop, + open: P.component.onOpen, + close: P.component.onClose, + set: P.component.onSet + }).on({ + start: SETTINGS.onStart, + render: SETTINGS.onRender, + stop: SETTINGS.onStop, + open: SETTINGS.onOpen, + close: SETTINGS.onClose, + set: SETTINGS.onSet + }) + + + // If the element has autofocus, open the picker. + if ( ELEMENT.autofocus ) { + P.open() + } + + + // Trigger queued the “start” and “render” events. + return P.trigger( 'start' ).trigger( 'render' ) + }, //start + + + /** + * Render a new picker within the root + */ + render: function() { + + // Insert a new component holder in the root. + P.$root.html( createWrappedComponent() ) + + // Trigger the queued “render” events. + return P.trigger( 'render' ) + }, //render + + + /** + * Destroy everything + */ + stop: function() { + + // If it’s already stopped, do nothing. + if ( !STATE.start ) return P + + // Then close the picker. + P.close() + + // Remove the hidden field. + if ( P._hidden ) { + P._hidden.parentNode.removeChild( P._hidden ) + } + + // Remove the root. + P.$root.remove() + + // Remove the input class, unbind the events, and remove the stored data. + $ELEMENT.removeClass( CLASSES.input ).off( '.P' + STATE.id ).removeData( NAME ) + + // Restore the element state + ELEMENT.type = STATE.type + ELEMENT.readOnly = false + + // Trigger the queued “stop” events. + P.trigger( 'stop' ) + + // Reset the picker states. + STATE.methods = {} + STATE.start = false + + return P + }, //stop + + + /* + * Open up the picker + */ + open: function( dontGiveFocus ) { + + // If it’s already open, do nothing. + if ( STATE.open ) return P + + // Add the “active” class. + $ELEMENT.addClass( CLASSES.active ) + + // Add the “opened” class to the picker root. + P.$root.addClass( CLASSES.opened ) + + // If we have to give focus, bind the element and doc events. + if ( dontGiveFocus !== false ) { + + // Set it as open. + STATE.open = true + + // Pass focus to the element’s jQuery object. + $ELEMENT.focus() + + // Bind the document events. + $document.on( 'click.P' + STATE.id + ' focusin.P' + STATE.id, function( event ) { + + // If the target of the event is not the element, close the picker picker. + // * Don’t worry about clicks or focusins on the root because those don’t bubble up. + // Also, for Firefox, a click on an `option` element bubbles up directly + // to the doc. So make sure the target wasn't the doc. + if ( event.target != ELEMENT && event.target != document ) P.close() + + }).on( 'keydown.P' + STATE.id, function( event ) { + + var + // Get the keycode. + keycode = event.keyCode, + + // Translate that to a selection change. + keycodeToMove = P.component.key[ keycode ], + + // Grab the target. + target = event.target + + + // On escape, close the picker and give focus. + if ( keycode == 27 ) { + P.close( true ) + } + + + // Check if there is a key movement or “enter” keypress on the element. + else if ( target == ELEMENT && ( keycodeToMove || keycode == 13 ) ) { + + // Prevent the default action to stop page movement. + event.preventDefault() + + // Trigger the key movement action. + if ( keycodeToMove ) { + PickerConstructor._.trigger( P.component.key.go, P, [ keycodeToMove ] ) + } + + // On “enter”, if the highlighted item isn’t disabled, set the value and close. + else if ( !P.$root.find( '.' + CLASSES.highlighted ).hasClass( CLASSES.disabled ) ) { + P.set( 'select', P.component.item.highlight ).close() + } + } + + + // If the target is within the root and “enter” is pressed, + // prevent the default action and trigger a click on the target instead. + else if ( P.$root.find( target ).length && keycode == 13 ) { + event.preventDefault() + target.click() + } + }) + } + + // Trigger the queued “open” events. + return P.trigger( 'open' ) + }, //open + + + /** + * Close the picker + */ + close: function( giveFocus ) { + + // If we need to give focus, do it before changing states. + if ( giveFocus ) { + // ....ah yes! It would’ve been incomplete without a crazy workaround for IE :| + // The focus is triggered *after* the close has completed - causing it + // to open again. So unbind and rebind the event at the next tick. + $ELEMENT.off( 'focus.P' + STATE.id ).focus() + setTimeout( function() { + $ELEMENT.on( 'focus.P' + STATE.id, focusToOpen ) + }, 0 ) + } + + // Remove the “active” class. + $ELEMENT.removeClass( CLASSES.active ) + + // Remove the “opened” and “focused” class from the picker root. + P.$root.removeClass( CLASSES.opened + ' ' + CLASSES.focused ) + + // If it’s open, update the state. + if ( STATE.open ) { + + // Set it as closed. + STATE.open = false + + // Unbind the document events. + $document.off( '.P' + STATE.id ) + } + + // Trigger the queued “close” events. + return P.trigger( 'close' ) + }, //close + + + /** + * Clear the values + */ + clear: function() { + return P.set( 'clear' ) + }, //clear + + + /** + * Set something + */ + set: function( thing, value, options ) { + + var thingItem, thingValue, + thingIsObject = PickerConstructor._.isObject( thing ), + thingObject = thingIsObject ? thing : {} + + if ( thing ) { + + // If the thing isn’t an object, make it one. + if ( !thingIsObject ) { + thingObject[ thing ] = value + } + + // Go through the things of items to set. + for ( thingItem in thingObject ) { + + // Grab the value of the thing. + thingValue = thingObject[ thingItem ] + + // First, if the item exists and there’s a value, set it. + if ( P.component.item[ thingItem ] ) { + P.component.set( thingItem, thingValue, options || {} ) + } + + // Then, check to update the element value and broadcast a change. + if ( thingItem == 'select' || thingItem == 'clear' ) { + $ELEMENT.val( thingItem == 'clear' ? '' : + PickerConstructor._.trigger( P.component.formats.toString, P.component, [ SETTINGS.format, P.component.get( thingItem ) ] ) + ).trigger( 'change' ) + } + } + + // Render a new picker. + P.render() + } + + // Trigger queued “set” events and pass the `thingObject`. + return P.trigger( 'set', thingObject ) + }, //set + + + /** + * Get something + */ + get: function( thing, format ) { + + // Make sure there’s something to get. + thing = thing || 'value' + + // If a picker state exists, return that. + if ( STATE[ thing ] != null ) { + return STATE[ thing ] + } + + // Return the value, if that. + if ( thing == 'value' ) { + return ELEMENT.value + } + + // Check if a component item exists, return that. + if ( P.component.item[ thing ] ) { + if ( typeof format == 'string' ) { + return PickerConstructor._.trigger( P.component.formats.toString, P.component, [ format, P.component.get( thing ) ] ) + } + return P.component.get( thing ) + } + }, //get + + + + /** + * Bind events on the things. + */ + on: function( thing, method ) { + + var thingName, thingMethod, + thingIsObject = PickerConstructor._.isObject( thing ), + thingObject = thingIsObject ? thing : {} + + if ( thing ) { + + // If the thing isn’t an object, make it one. + if ( !thingIsObject ) { + thingObject[ thing ] = method + } + + // Go through the things to bind to. + for ( thingName in thingObject ) { + + // Grab the method of the thing. + thingMethod = thingObject[ thingName ] + + // Make sure the thing methods collection exists. + STATE.methods[ thingName ] = STATE.methods[ thingName ] || [] + + // Add the method to the relative method collection. + STATE.methods[ thingName ].push( thingMethod ) + } + } + + return P + }, //on + + + /** + * Fire off method events. + */ + trigger: function( name, data ) { + var methodList = STATE.methods[ name ] + if ( methodList ) { + methodList.map( function( method ) { + PickerConstructor._.trigger( method, P, [ data ] ) + }) + } + return P + } //trigger + } //PickerInstance.prototype + + + /** + * Wrap the picker holder components together. + */ + function createWrappedComponent() { + + // Create a picker wrapper holder + return PickerConstructor._.node( 'div', + + // Create a picker wrapper node + PickerConstructor._.node( 'div', + + // Create a picker frame + PickerConstructor._.node( 'div', + + // Create a picker box node + PickerConstructor._.node( 'div', + + // Create the components nodes. + P.component.nodes( STATE.open ), + + // The picker box class + CLASSES.box + ), + + // Picker wrap class + CLASSES.wrap + ), + + // Picker frame class + CLASSES.frame + ), + + // Picker holder class + CLASSES.holder + ) //endreturn + } //createWrappedComponent + + + // Separated for IE + function focusToOpen( event ) { + + // Stop the event from propagating to the doc. + event.stopPropagation() + + // If it’s a focus event, add the “focused” class to the root. + if ( event.type == 'focus' ) P.$root.addClass( CLASSES.focused ) + + // And then finally open the picker. + P.open() + } + + + // Return a new picker instance. + return new PickerInstance() +} //PickerConstructor + + + +/** + * The default classes and prefix to use for the HTML classes. + */ +PickerConstructor.klasses = function( prefix ) { + prefix = prefix || 'picker' + return { + + picker: prefix, + opened: prefix + '--opened', + focused: prefix + '--focused', + + input: prefix + '__input', + active: prefix + '__input--active', + + holder: prefix + '__holder', + + frame: prefix + '__frame', + wrap: prefix + '__wrap', + + box: prefix + '__box' + } +} //PickerConstructor.klasses + + + +/** + * PickerConstructor helper methods. + */ +PickerConstructor._ = { + + /** + * Create a group of nodes. Expects: + * ` + { + min: {Integer}, + max: {Integer}, + i: {Integer}, + node: {String}, + item: {Function} + } + * ` + */ + group: function( groupObject ) { + + var + // Scope for the looped object + loopObjectScope, + + // Create the nodes list + nodesList = '', + + // The counter starts from the `min` + counter = PickerConstructor._.trigger( groupObject.min, groupObject ) + + + // Loop from the `min` to `max`, incrementing by `i` + for ( ; counter <= PickerConstructor._.trigger( groupObject.max, groupObject, [ counter ] ); counter += groupObject.i ) { + + // Trigger the `item` function within scope of the object + loopObjectScope = PickerConstructor._.trigger( groupObject.item, groupObject, [ counter ] ) + + // Splice the subgroup and create nodes out of the sub nodes + nodesList += PickerConstructor._.node( + groupObject.node, + loopObjectScope[ 0 ], // the node + loopObjectScope[ 1 ], // the classes + loopObjectScope[ 2 ] // the attributes + ) + } + + // Return the list of nodes + return nodesList + }, //group + + + /** + * Create a dom node string + */ + node: function( wrapper, item, klass, attribute ) { + + // If the item is false-y, just return an empty string + if ( !item ) return '' + + // If the item is an array, do a join + item = Array.isArray( item ) ? item.join( '' ) : item + + // Check for the class + klass = klass ? ' class="' + klass + '"' : '' + + // Check for any attributes + attribute = attribute ? ' ' + attribute : '' + + // Return the wrapped item + return '<' + wrapper + klass + attribute + '>' + item + '</' + wrapper + '>' + }, //node + + + /** + * Lead numbers below 10 with a zero. + */ + lead: function( number ) { + return ( number < 10 ? '0': '' ) + number + }, + + + /** + * Trigger a function otherwise return the value. + */ + trigger: function( callback, scope, args ) { + return typeof callback == 'function' ? callback.apply( scope, args || [] ) : callback + }, + + + /** + * If the second character is a digit, length is 2 otherwise 1. + */ + digits: function( string ) { + return ( /\d/ ).test( string[ 1 ] ) ? 2 : 1 + }, + + + /** + * Tell if something is an object. + */ + isObject: function( value ) { + return {}.toString.call( value ).indexOf( 'Object' ) > -1 + }, + + + /** + * Tell if something is a date object. + */ + isDate: function( value ) { + return {}.toString.call( value ).indexOf( 'Date' ) > -1 && this.isInteger( value.getDate() ) + }, + + + /** + * Tell if something is an integer. + */ + isInteger: function( value ) { + return {}.toString.call( value ).indexOf( 'Number' ) > -1 && value % 1 === 0 + } +} //PickerConstructor._ + + + +/** + * Extend the picker with a component and defaults. + */ +PickerConstructor.extend = function( name, Component ) { + + // Extend jQuery. + $.fn[ name ] = function( options, action ) { + + // Grab the component data. + var componentData = this.data( name ) + + // If the picker is requested, return the data object. + if ( options == 'picker' ) { + return componentData + } + + // If the component data exists and `options` is a string, carry out the action. + if ( componentData && typeof options == 'string' ) { + PickerConstructor._.trigger( componentData[ options ], componentData, [ action ] ) + return this + } + + // Otherwise go through each matched element and if the component + // doesn’t exist, create a new picker using `this` element + // and merging the defaults and options with a deep copy. + return this.each( function() { + var $this = $( this ) + if ( !$this.data( name ) ) { + new PickerConstructor( this, name, Component, options ) + } + }) + } + + // Set the defaults. + $.fn[ name ].defaults = Component.defaults +} //PickerConstructor.extend + + + +// Return the picker constructor. +return PickerConstructor + + +// Close the global scope. +})( jQuery, jQuery( document ) ); + + + + +/*! + * Date picker for pickadate.js v3.1.1 + * http://amsul.github.io/pickadate.js/date.htm + */ + +/*jshint + debug: true, + devel: true, + browser: true, + asi: true, + unused: true, + boss: true + */ + + +// Create a new scope. +(function() { + + +/** + * Globals and constants + */ +var DAYS_IN_WEEK = 7, + WEEKS_IN_CALENDAR = 6 + + + +/** + * The date picker constructor + */ +function DatePicker( picker, settings ) { + + var calendar = this, + elementValue = picker.$node[ 0 ].value, + elementDataValue = picker.$node.data( 'value' ), + valueString = elementDataValue || elementValue, + formatString = elementDataValue ? settings.formatSubmit : settings.format + + calendar.settings = settings + + // The queue of methods that will be used to build item objects. + calendar.queue = { + min: 'measure create', + max: 'measure create', + now: 'now create', + select: 'parse create validate', + highlight: 'navigate create validate', + view: 'create validate viewset', + disable: 'flipItem', + enable: 'flipItem' + } + + // The component's item object. + calendar.item = {} + + calendar.item.disable = ( settings.disable || [] ).slice( 0 ) + calendar.item.enable = -(function( collectionDisabled ) { + return collectionDisabled[ 0 ] === true ? collectionDisabled.shift() : -1 + })( calendar.item.disable ) + + calendar. + set( 'min', settings.min ). + set( 'max', settings.max ). + set( 'now' ). + + // Setting the `select` also sets the `highlight` and `view`. + set( 'select', + + // Use the value provided or default to selecting “today”. + valueString || calendar.item.now, + { + // Use the appropriate format. + format: formatString, + + // Set user-provided month data as true when there is a + // “mm” or “m” used in the relative format string. + data: (function( formatArray ) { + return valueString && ( formatArray.indexOf( 'mm' ) > -1 || formatArray.indexOf( 'm' ) > -1 ) + })( calendar.formats.toArray( formatString ) ) + } + ) + + + // The keycode to movement mapping. + calendar.key = { + 40: 7, // Down + 38: -7, // Up + 39: 1, // Right + 37: -1, // Left + go: function( timeChange ) { + calendar.set( 'highlight', [ calendar.item.highlight.year, calendar.item.highlight.month, calendar.item.highlight.date + timeChange ], { interval: timeChange } ) + this.render() + } + } + + + // Bind some picker events. + picker. + on( 'render', function() { + picker.$root.find( '.' + settings.klass.selectMonth ).on( 'change', function() { + picker.set( 'highlight', [ picker.get( 'view' ).year, this.value, picker.get( 'highlight' ).date ] ) + picker.$root.find( '.' + settings.klass.selectMonth ).focus() + }) + picker.$root.find( '.' + settings.klass.selectYear ).on( 'change', function() { + picker.set( 'highlight', [ this.value, picker.get( 'view' ).month, picker.get( 'highlight' ).date ] ) + picker.$root.find( '.' + settings.klass.selectYear ).focus() + }) + }). + on( 'open', function() { + picker.$root.find( 'button, select' ).attr( 'disabled', false ) + }). + on( 'close', function() { + picker.$root.find( 'button, select' ).attr( 'disabled', true ) + }) + +} //DatePicker + + +/** + * Set a datepicker item object. + */ +DatePicker.prototype.set = function( type, value, options ) { + + var calendar = this + + // Go through the queue of methods, and invoke the function. Update this + // as the time unit, and set the final resultant as this item type. + // * In the case of `enable`, keep the queue but set `disable` instead. + // And in the case of `flip`, keep the queue but set `enable` instead. + calendar.item[ ( type == 'enable' ? 'disable' : type == 'flip' ? 'enable' : type ) ] = calendar.queue[ type ].split( ' ' ).map( function( method ) { + return value = calendar[ method ]( type, value, options ) + }).pop() + + // Check if we need to cascade through more updates. + if ( type == 'select' ) { + calendar.set( 'highlight', calendar.item.select, options ) + } + else if ( type == 'highlight' ) { + calendar.set( 'view', calendar.item.highlight, options ) + } + else if ( ( type == 'flip' || type == 'min' || type == 'max' || type == 'disable' || type == 'enable' ) && calendar.item.select && calendar.item.highlight ) { + calendar. + set( 'select', calendar.item.select, options ). + set( 'highlight', calendar.item.highlight, options ) + } + + return calendar +} //DatePicker.prototype.set + + +/** + * Get a datepicker item object. + */ +DatePicker.prototype.get = function( type ) { + return this.item[ type ] +} //DatePicker.prototype.get + + +/** + * Create a picker date object. + */ +DatePicker.prototype.create = function( type, value, options ) { + + var isInfiniteValue, + calendar = this + + // If there’s no value, use the type as the value. + value = value === undefined ? type : value + + + // If it’s infinity, update the value. + if ( value == -Infinity || value == Infinity ) { + isInfiniteValue = value + } + + // If it’s an object, use the native date object. + else if ( Picker._.isObject( value ) && Picker._.isInteger( value.pick ) ) { + value = value.obj + } + + // If it’s an array, convert it into a date and make sure + // that it’s a valid date – otherwise default to today. + else if ( Array.isArray( value ) ) { + value = new Date( value[ 0 ], value[ 1 ], value[ 2 ] ) + value = Picker._.isDate( value ) ? value : calendar.create().obj + } + + // If it’s a number or date object, make a normalized date. + else if ( Picker._.isInteger( value ) || Picker._.isDate( value ) ) { + value = calendar.normalize( new Date( value ), options ) + } + + // If it’s a literal true or any other case, set it to now. + else /*if ( value === true )*/ { + value = calendar.now( type, value, options ) + } + + // Return the compiled object. + return { + year: isInfiniteValue || value.getFullYear(), + month: isInfiniteValue || value.getMonth(), + date: isInfiniteValue || value.getDate(), + day: isInfiniteValue || value.getDay(), + obj: isInfiniteValue || value, + pick: isInfiniteValue || value.getTime() + } +} //DatePicker.prototype.create + + +/** + * Get the date today. + */ +DatePicker.prototype.now = function( type, value, options ) { + value = new Date() + if ( options && options.rel ) { + value.setDate( value.getDate() + options.rel ) + } + return this.normalize( value, options ) +} //DatePicker.prototype.now + + +/** + * Navigate to next/prev month. + */ +DatePicker.prototype.navigate = function( type, value, options ) { + + if ( Picker._.isObject( value ) ) { + + var targetDateObject = new Date( value.year, value.month + ( options && options.nav ? options.nav : 0 ), 1 ), + year = targetDateObject.getFullYear(), + month = targetDateObject.getMonth(), + date = value.date + + // Make sure the date is valid and if the month we’re going to doesn’t have enough + // days, keep decreasing the date until we reach the month’s last date. + while ( Picker._.isDate( targetDateObject ) && new Date( year, month, date ).getMonth() !== month ) { + date -= 1 + } + + value = [ year, month, date ] + } + + return value +} //DatePicker.prototype.navigate + + +/** + * Normalize a date by setting the hours to midnight. + */ +DatePicker.prototype.normalize = function( value/*, options*/ ) { + value.setHours( 0, 0, 0, 0 ) + return value +} + + +/** + * Measure the range of dates. + */ +DatePicker.prototype.measure = function( type, value/*, options*/ ) { + + var calendar = this + + // If it's anything false-y, remove the limits. + if ( !value ) { + value = type == 'min' ? -Infinity : Infinity + } + + // If it's an integer, get a date relative to today. + else if ( Picker._.isInteger( value ) ) { + value = calendar.now( type, value, { rel: value } ) + } + + return value +} ///DatePicker.prototype.measure + + +/** + * Create a viewset object based on navigation. + */ +DatePicker.prototype.viewset = function( type, dateObject/*, options*/ ) { + return this.create([ dateObject.year, dateObject.month, 1 ]) +} + + +/** + * Validate a date as enabled and shift if needed. + */ +DatePicker.prototype.validate = function( type, dateObject, options ) { + + var calendar = this, + + // Keep a reference to the original date. + originalDateObject = dateObject, + + // Make sure we have an interval. + interval = options && options.interval ? options.interval : 1, + + // Check if the calendar enabled dates are inverted. + isInverted = calendar.item.enable === -1, + + // Check if we have any enabled dates after/before now. + hasEnabledBeforeTarget, hasEnabledAfterTarget, + + // The min & max limits. + minLimitObject = calendar.item.min, + maxLimitObject = calendar.item.max, + + // Check if we’ve reached the limit during shifting. + reachedMin, reachedMax, + + // Check if the calendar is inverted and at least one weekday is enabled. + hasEnabledWeekdays = isInverted && calendar.item.disable.filter( function( value ) { + + // If there’s a date, check where it is relative to the target. + if ( Array.isArray( value ) ) { + var dateTime = calendar.create( value ).pick + if ( dateTime < dateObject.pick ) hasEnabledBeforeTarget = true + else if ( dateTime > dateObject.pick ) hasEnabledAfterTarget = true + } + + // Return only integers for enabled weekdays. + return Picker._.isInteger( value ) + }).length + + + + // Cases to validate for: + // [1] Not inverted and date disabled. + // [2] Inverted and some dates enabled. + // [3] Out of range. + // + // Cases to **not** validate for: + // • Not inverted and date enabled. + // • Inverted and all dates disabled. + // • Navigating months. + // • ..and anything else. + if ( + /* 1 */ ( !isInverted && calendar.disabled( dateObject ) ) || + /* 2 */ ( isInverted && calendar.disabled( dateObject ) && ( hasEnabledWeekdays || hasEnabledBeforeTarget || hasEnabledAfterTarget ) ) || + /* 3 */ ( dateObject.pick <= minLimitObject.pick || dateObject.pick >= maxLimitObject.pick ) + ) { + + + // When inverted, flip the direction if there aren’t any enabled weekdays + // and there are no enabled dates in the direction of the interval. + if ( isInverted && !hasEnabledWeekdays && ( ( !hasEnabledAfterTarget && interval > 0 ) || ( !hasEnabledBeforeTarget && interval < 0 ) ) ) { + interval *= -1 + } + + + // Keep looping until we reach an enabled date. + while ( calendar.disabled( dateObject ) ) { + + + // If we’ve looped into the next/prev month, return to the original date and flatten the interval. + if ( Math.abs( interval ) > 1 && ( dateObject.month < originalDateObject.month || dateObject.month > originalDateObject.month ) ) { + dateObject = originalDateObject + interval = Math.abs( interval ) / interval + } + + + // If we’ve reached the min/max limit, reverse the direction and flatten the interval. + if ( dateObject.pick <= minLimitObject.pick ) { + reachedMin = true + interval = 1 + } + else if ( dateObject.pick >= maxLimitObject.pick ) { + reachedMax = true + interval = -1 + } + + + // If we’ve reached both limits, just break out of the loop. + if ( reachedMin && reachedMax ) { + break + } + + + // Finally, create the shifted date using the interval and keep looping. + dateObject = calendar.create([ dateObject.year, dateObject.month, dateObject.date + interval ]) + } + + } //endif + + + // Return the date object settled on. + return dateObject +} //DatePicker.prototype.validate + + +/** + * Check if an object is disabled. + */ +DatePicker.prototype.disabled = function( dateObject ) { + + var calendar = this, + + // Filter through the disabled dates to check if this is one. + isDisabledDate = calendar.item.disable.filter( function( dateToDisable ) { + + // If the date is a number, match the weekday with 0index and `firstDay` check. + if ( Picker._.isInteger( dateToDisable ) ) { + return dateObject.day === ( calendar.settings.firstDay ? dateToDisable : dateToDisable - 1 ) % 7 + } + + // If it's an array, create the object and match the exact date. + if ( Array.isArray( dateToDisable ) ) { + return dateObject.pick === calendar.create( dateToDisable ).pick + } + }).length + + + // It’s disabled beyond the min/max limits. If within the limits, check the + // calendar “enabled” flag is flipped and respectively flip the condition. + return dateObject.pick < calendar.item.min.pick || + dateObject.pick > calendar.item.max.pick || + calendar.item.enable === -1 ? !isDisabledDate : isDisabledDate +} //DatePicker.prototype.disabled + + +/** + * Parse a string into a usable type. + */ +DatePicker.prototype.parse = function( type, value, options ) { + + var calendar = this, + parsingObject = {} + + if ( !value || Picker._.isInteger( value ) || Array.isArray( value ) || Picker._.isDate( value ) || Picker._.isObject( value ) && Picker._.isInteger( value.pick ) ) { + return value + } + + // We need a `.format` to parse the value. + if ( !( options && options.format ) ) { + // should probably default to the default format. + throw "Need a formatting option to parse this.." + } + + // Convert the format into an array and then map through it. + calendar.formats.toArray( options.format ).map( function( label ) { + + var + // Grab the formatting label. + formattingLabel = calendar.formats[ label ], + + // The format length is from the formatting label function or the + // label length without the escaping exclamation (!) mark. + formatLength = formattingLabel ? Picker._.trigger( formattingLabel, calendar, [ value, parsingObject ] ) : label.replace( /^!/, '' ).length + + // If there's a format label, split the value up to the format length. + // Then add it to the parsing object with appropriate label. + if ( formattingLabel ) { + parsingObject[ label ] = value.substr( 0, formatLength ) + } + + // Update the value as the substring from format length to end. + value = value.substr( formatLength ) + }) + + // If it’s parsing a user provided month value, compensate for month 0index. + return [ parsingObject.yyyy || parsingObject.yy, +( parsingObject.mm || parsingObject.m ) - ( options.data ? 1 : 0 ), parsingObject.dd || parsingObject.d ] +} //DatePicker.prototype.parse + + +/** + * Various formats to display the object in. + */ +DatePicker.prototype.formats = (function() { + + // Return the length of the first word in a collection. + function getWordLengthFromCollection( string, collection, dateObject ) { + + // Grab the first word from the string. + var word = string.match( /\w+/ )[ 0 ] + + // If there's no month index, add it to the date object + if ( !dateObject.mm && !dateObject.m ) { + dateObject.m = collection.indexOf( word ) + } + + // Return the length of the word. + return word.length + } + + // Get the length of the first word in a string. + function getFirstWordLength( string ) { + return string.match( /\w+/ )[ 0 ].length + } + + return { + + d: function( string, dateObject ) { + + // If there's string, then get the digits length. + // Otherwise return the selected date. + return string ? Picker._.digits( string ) : dateObject.date + }, + dd: function( string, dateObject ) { + + // If there's a string, then the length is always 2. + // Otherwise return the selected date with a leading zero. + return string ? 2 : Picker._.lead( dateObject.date ) + }, + ddd: function( string, dateObject ) { + + // If there's a string, then get the length of the first word. + // Otherwise return the short selected weekday. + return string ? getFirstWordLength( string ) : this.settings.weekdaysShort[ dateObject.day ] + }, + dddd: function( string, dateObject ) { + + // If there's a string, then get the length of the first word. + // Otherwise return the full selected weekday. + return string ? getFirstWordLength( string ) : this.settings.weekdaysFull[ dateObject.day ] + }, + m: function( string, dateObject ) { + + // If there's a string, then get the length of the digits + // Otherwise return the selected month with 0index compensation. + return string ? Picker._.digits( string ) : dateObject.month + 1 + }, + mm: function( string, dateObject ) { + + // If there's a string, then the length is always 2. + // Otherwise return the selected month with 0index and leading zero. + return string ? 2 : Picker._.lead( dateObject.month + 1 ) + }, + mmm: function( string, dateObject ) { + + var collection = this.settings.monthsShort + + // If there's a string, get length of the relevant month from the short + // months collection. Otherwise return the selected month from that collection. + return string ? getWordLengthFromCollection( string, collection, dateObject ) : collection[ dateObject.month ] + }, + mmmm: function( string, dateObject ) { + + var collection = this.settings.monthsFull + + // If there's a string, get length of the relevant month from the full + // months collection. Otherwise return the selected month from that collection. + return string ? getWordLengthFromCollection( string, collection, dateObject ) : collection[ dateObject.month ] + }, + yy: function( string, dateObject ) { + + // If there's a string, then the length is always 2. + // Otherwise return the selected year by slicing out the first 2 digits. + return string ? 2 : ( '' + dateObject.year ).slice( 2 ) + }, + yyyy: function( string, dateObject ) { + + // If there's a string, then the length is always 4. + // Otherwise return the selected year. + return string ? 4 : dateObject.year + }, + + // Create an array by splitting the formatting string passed. + toArray: function( formatString ) { return formatString.split( /(d{1,4}|m{1,4}|y{4}|yy|!.)/g ) }, + + // Format an object into a string using the formatting options. + toString: function ( formatString, itemObject ) { + var calendar = this + return calendar.formats.toArray( formatString ).map( function( label ) { + return Picker._.trigger( calendar.formats[ label ], calendar, [ 0, itemObject ] ) || label.replace( /^!/, '' ) + }).join( '' ) + } + } +})() //DatePicker.prototype.formats + + +/** + * Flip an item as enabled or disabled. + */ +DatePicker.prototype.flipItem = function( type, value/*, options*/ ) { + + var calendar = this, + collection = calendar.item.disable, + isInverted = calendar.item.enable === -1 + + // Flip the enabled and disabled dates. + if ( value == 'flip' ) { + calendar.item.enable = isInverted ? 1 : -1 + } + + // Check if we have to add/remove from collection. + else if ( !isInverted && type == 'enable' || isInverted && type == 'disable' ) { + collection = calendar.removeDisabled( collection, value ) + } + else if ( !isInverted && type == 'disable' || isInverted && type == 'enable' ) { + collection = calendar.addDisabled( collection, value ) + } + + return collection +} //DatePicker.prototype.flipItem + + +/** + * Add an item to the disabled collection. + */ +DatePicker.prototype.addDisabled = function( collection, item ) { + var calendar = this + item.map( function( timeUnit ) { + if ( !calendar.filterDisabled( collection, timeUnit ).length ) { + collection.push( timeUnit ) + } + }) + return collection +} //DatePicker.prototype.addDisabled + + +/** + * Remove an item from the disabled collection. + */ +DatePicker.prototype.removeDisabled = function( collection, item ) { + var calendar = this + item.map( function( timeUnit ) { + collection = calendar.filterDisabled( collection, timeUnit, 1 ) + }) + return collection +} //DatePicker.prototype.removeDisabled + + +/** + * Filter through the disabled collection to find a time unit. + */ +DatePicker.prototype.filterDisabled = function( collection, timeUnit, isRemoving ) { + var timeIsArray = Array.isArray( timeUnit ) + return collection.filter( function( disabledTimeUnit ) { + var isMatch = !timeIsArray && timeUnit === disabledTimeUnit || + timeIsArray && Array.isArray( disabledTimeUnit ) && timeUnit.toString() === disabledTimeUnit.toString() + return isRemoving ? !isMatch : isMatch + }) +} //DatePicker.prototype.filterDisabled + + +/** + * Create a string for the nodes in the picker. + */ +DatePicker.prototype.nodes = function( isOpen ) { + + var + calendar = this, + settings = calendar.settings, + nowObject = calendar.item.now, + selectedObject = calendar.item.select, + highlightedObject = calendar.item.highlight, + viewsetObject = calendar.item.view, + disabledCollection = calendar.item.disable, + minLimitObject = calendar.item.min, + maxLimitObject = calendar.item.max, + + + // Create the calendar table head using a copy of weekday labels collection. + // * We do a copy so we don't mutate the original array. + tableHead = (function( collection ) { + + // If the first day should be Monday, move Sunday to the end. + if ( settings.firstDay ) { + collection.push( collection.shift() ) + } + + // Create and return the table head group. + return Picker._.node( + 'thead', + Picker._.group({ + min: 0, + max: DAYS_IN_WEEK - 1, + i: 1, + node: 'th', + item: function( counter ) { + return [ + collection[ counter ], + settings.klass.weekdays + ] + } + }) + ) //endreturn + })( ( settings.showWeekdaysFull ? settings.weekdaysFull : settings.weekdaysShort ).slice( 0 ) ), //tableHead + + + // Create the nav for next/prev month. + createMonthNav = function( next ) { + + // Otherwise, return the created month tag. + return Picker._.node( + 'div', + ' ', + settings.klass[ 'nav' + ( next ? 'Next' : 'Prev' ) ] + ( + + // If the focused month is outside the range, disabled the button. + ( next && viewsetObject.year >= maxLimitObject.year && viewsetObject.month >= maxLimitObject.month ) || + ( !next && viewsetObject.year <= minLimitObject.year && viewsetObject.month <= minLimitObject.month ) ? + ' ' + settings.klass.navDisabled : '' + ), + 'data-nav=' + ( next || -1 ) + ) //endreturn + }, //createMonthNav + + + // Create the month label. + createMonthLabel = function( monthsCollection ) { + + // If there are months to select, add a dropdown menu. + if ( settings.selectMonths ) { + + return Picker._.node( 'select', Picker._.group({ + min: 0, + max: 11, + i: 1, + node: 'option', + item: function( loopedMonth ) { + + return [ + + // The looped month and no classes. + monthsCollection[ loopedMonth ], 0, + + // Set the value and selected index. + 'value=' + loopedMonth + + ( viewsetObject.month == loopedMonth ? ' selected' : '' ) + + ( + ( + ( viewsetObject.year == minLimitObject.year && loopedMonth < minLimitObject.month ) || + ( viewsetObject.year == maxLimitObject.year && loopedMonth > maxLimitObject.month ) + ) ? + ' disabled' : '' + ) + ] + } + }), settings.klass.selectMonth, isOpen ? '' : 'disabled' ) + } + + // If there's a need for a month selector + return Picker._.node( 'div', monthsCollection[ viewsetObject.month ], settings.klass.month ) + }, //createMonthLabel + + + // Create the year label. + createYearLabel = function() { + + var focusedYear = viewsetObject.year, + + // If years selector is set to a literal "true", set it to 5. Otherwise + // divide in half to get half before and half after focused year. + numberYears = settings.selectYears === true ? 5 : ~~( settings.selectYears / 2 ) + + // If there are years to select, add a dropdown menu. + if ( numberYears ) { + + var + minYear = minLimitObject.year, + maxYear = maxLimitObject.year, + lowestYear = focusedYear - numberYears, + highestYear = focusedYear + numberYears + + // If the min year is greater than the lowest year, increase the highest year + // by the difference and set the lowest year to the min year. + if ( minYear > lowestYear ) { + highestYear += minYear - lowestYear + lowestYear = minYear + } + + // If the max year is less than the highest year, decrease the lowest year + // by the lower of the two: available and needed years. Then set the + // highest year to the max year. + if ( maxYear < highestYear ) { + + var availableYears = lowestYear - minYear, + neededYears = highestYear - maxYear + + lowestYear -= availableYears > neededYears ? neededYears : availableYears + highestYear = maxYear + } + + return Picker._.node( 'select', Picker._.group({ + min: lowestYear, + max: highestYear, + i: 1, + node: 'option', + item: function( loopedYear ) { + return [ + + // The looped year and no classes. + loopedYear, 0, + + // Set the value and selected index. + 'value=' + loopedYear + ( focusedYear == loopedYear ? ' selected' : '' ) + ] + } + }), settings.klass.selectYear, isOpen ? '' : 'disabled' ) + } + + // Otherwise just return the year focused + return Picker._.node( 'div', focusedYear, settings.klass.year ) + } //createYearLabel + + + // Create and return the entire calendar. + return Picker._.node( + 'div', + createMonthNav() + createMonthNav( 1 ) + + createMonthLabel( settings.showMonthsShort ? settings.monthsShort : settings.monthsFull ) + + createYearLabel(), + settings.klass.header + ) + Picker._.node( + 'table', + tableHead + + Picker._.node( + 'tbody', + Picker._.group({ + min: 0, + max: WEEKS_IN_CALENDAR - 1, + i: 1, + node: 'tr', + item: function( rowCounter ) { + + // If Monday is the first day and the month starts on Sunday, shift the date back a week. + var shiftDateBy = settings.firstDay && calendar.create([ viewsetObject.year, viewsetObject.month, 1 ]).day === 0 ? -7 : 0 + + return [ + Picker._.group({ + min: DAYS_IN_WEEK * rowCounter - viewsetObject.day + shiftDateBy + 1, // Add 1 for weekday 0index + max: function() { + return this.min + DAYS_IN_WEEK - 1 + }, + i: 1, + node: 'td', + item: function( targetDate ) { + + // Convert the time date from a relative date to a target date. + targetDate = calendar.create([ viewsetObject.year, viewsetObject.month, targetDate + ( settings.firstDay ? 1 : 0 ) ]) + + return [ + Picker._.node( + 'div', + targetDate.date, + (function( klasses ) { + + // Add the `infocus` or `outfocus` classes based on month in view. + klasses.push( viewsetObject.month == targetDate.month ? settings.klass.infocus : settings.klass.outfocus ) + + // Add the `today` class if needed. + if ( nowObject.pick == targetDate.pick ) { + klasses.push( settings.klass.now ) + } + + // Add the `selected` class if something's selected and the time matches. + if ( selectedObject && selectedObject.pick == targetDate.pick ) { + klasses.push( settings.klass.selected ) + } + + // Add the `highlighted` class if something's highlighted and the time matches. + if ( highlightedObject && highlightedObject.pick == targetDate.pick ) { + klasses.push( settings.klass.highlighted ) + } + + // Add the `disabled` class if something's disabled and the object matches. + if ( disabledCollection && calendar.disabled( targetDate ) || targetDate.pick < minLimitObject.pick || targetDate.pick > maxLimitObject.pick ) { + klasses.push( settings.klass.disabled ) + } + + return klasses.join( ' ' ) + })([ settings.klass.day ]), + 'data-pick=' + targetDate.pick + ) + ] //endreturn + } + }) + ] //endreturn + } + }) + ), + settings.klass.table + ) + + + Picker._.node( + 'div', + Picker._.node( 'button', settings.today, settings.klass.buttonToday, 'data-pick=' + nowObject.pick + ( isOpen ? '' : ' disabled' ) ) + + Picker._.node( 'button', settings.clear, settings.klass.buttonClear, 'data-clear=1' + ( isOpen ? '' : ' disabled' ) ), + settings.klass.footer + ) //endreturn +} //DatePicker.prototype.nodes + + + + +/** + * The date picker defaults. + */ +DatePicker.defaults = (function( prefix ) { + + return { + + // Months and weekdays + monthsFull: [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ], + monthsShort: [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ], + weekdaysFull: [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ], + weekdaysShort: [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ], + + // Today and clear + today: 'Today', + clear: 'Clear', + + // The format to show on the `input` element + format: 'd mmmm, yyyy', + + // Classes + klass: { + + table: prefix + 'table', + + header: prefix + 'header', + + navPrev: prefix + 'nav--prev', + navNext: prefix + 'nav--next', + navDisabled: prefix + 'nav--disabled', + + month: prefix + 'month', + year: prefix + 'year', + + selectMonth: prefix + 'select--month', + selectYear: prefix + 'select--year', + + weekdays: prefix + 'weekday', + + day: prefix + 'day', + disabled: prefix + 'day--disabled', + selected: prefix + 'day--selected', + highlighted: prefix + 'day--highlighted', + now: prefix + 'day--today', + infocus: prefix + 'day--infocus', + outfocus: prefix + 'day--outfocus', + + footer: prefix + 'footer', + + buttonClear: prefix + 'button--clear', + buttonToday: prefix + 'button--today' + } + } +})( Picker.klasses().picker + '__' ) + + + + + +/** + * Extend the picker to add the date picker. + */ +Picker.extend( 'pickadate', DatePicker ) + + +// Close the scope. +})(); + + + + +/*jshint + asi: true, + unused: true, + boss: true, + loopfunc: true, + eqnull: true + */ + + +/*! + * Legacy browser support + */ + +// isArray support +if ( !Array.isArray ) { + Array.isArray = function( value ) { + return {}.toString.call( value ) == '[object Array]' + } +} + + +// Map array support +if ( ![].map ) { + Array.prototype.map = function ( callback, self ) { + var array = this, len = array.length, newArray = new Array( len ) + for ( var i = 0; i < len; i++ ) { + if ( i in array ) { + newArray[ i ] = callback.call( self, array[ i ], i, array ) + } + } + return newArray + } +} + + +// Filter array support +if ( ![].filter ) { + Array.prototype.filter = function( callback ) { + if ( this == null ) throw new TypeError() + var t = Object( this ), len = t.length >>> 0 + if ( typeof callback != 'function' ) throw new TypeError() + var newArray = [], thisp = arguments[ 1 ] + for ( var i = 0; i < len; i++ ) { + if ( i in t ) { + var val = t[ i ] + if ( callback.call( thisp, val, i, t ) ) newArray.push( val ) + } + } + return newArray + } +} + + +// Index of array support +if ( ![].indexOf ) { + Array.prototype.indexOf = function( searchElement ) { + if ( this == null ) throw new TypeError() + var t = Object( this ), len = t.length >>> 0 + if ( len === 0 ) return -1 + var n = 0 + if ( arguments.length > 1 ) { + n = Number( arguments[ 1 ] ) + if ( n != n ) { + n = 0 + } + else if ( n !== 0 && n != Infinity && n != -Infinity ) { + n = ( n > 0 || -1 ) * Math.floor( Math.abs( n ) ) + } + } + if ( n >= len ) return -1 + var k = n >= 0 ? n : Math.max( len - Math.abs( n ), 0 ) + for ( ; k < len; k++ ) { + if ( k in t && t[ k ] === searchElement ) return k + } + return -1 + } +} + + +/*! + * Cross-Browser Split 1.1.1 + * Copyright 2007-2012 Steven Levithan <stevenlevithan.com> + * Available under the MIT License + * http://blog.stevenlevithan.com/archives/cross-browser-split + */ +var nativeSplit = String.prototype.split, compliantExecNpcg = /()??/.exec('')[1] === undefined +String.prototype.split = function(separator, limit) { + var str = this + if (Object.prototype.toString.call(separator) !== '[object RegExp]') { + return nativeSplit.call(str, separator, limit) + } + var output = [], + flags = (separator.ignoreCase ? 'i' : '') + + (separator.multiline ? 'm' : '') + + (separator.extended ? 'x' : '') + + (separator.sticky ? 'y' : ''), + lastLastIndex = 0, + separator2, match, lastIndex, lastLength + separator = new RegExp(separator.source, flags + 'g') + str += '' + if (!compliantExecNpcg) { + separator2 = new RegExp('^' + separator.source + '$(?!\\s)', flags) + } + limit = limit === undefined ? -1 >>> 0 : limit >>> 0 + while (match = separator.exec(str)) { + lastIndex = match.index + match[0].length + if (lastIndex > lastLastIndex) { + output.push(str.slice(lastLastIndex, match.index)) + if (!compliantExecNpcg && match.length > 1) { + match[0].replace(separator2, function () { + for (var i = 1; i < arguments.length - 2; i++) { + if (arguments[i] === undefined) { + match[i] = undefined + } + } + }) + } + if (match.length > 1 && match.index < str.length) { + Array.prototype.push.apply(output, match.slice(1)) + } + lastLength = match[0].length + lastLastIndex = lastIndex + if (output.length >= limit) { + break + } + } + if (separator.lastIndex === match.index) { + separator.lastIndex++ + } + } + if (lastLastIndex === str.length) { + if (lastLength || !separator.test('')) { + output.push('') + } + } else { + output.push(str.slice(lastLastIndex)) + } + return output.length > limit ? output.slice(0, limit) : output +} +$(document).ready(function() { + var switched = false; + var updateTables = function() { + if (($(window).width() <= 768) && !switched ){ + console.log('entro'); + switched = true; + $("table.responsive").each(function(i, element) { + splitTable($(element)); + }); + return true; + } + else if (switched && ($(window).width() > 768)) { + switched = false; + $("table.responsive").each(function(i, element) { + unsplitTable($(element)); + }); + } + }; + + $(window).load(updateTables); + $(window).on("redraw",function(){switched=false;updateTables();}); // An event to listen for + $(window).on("resize", updateTables); + + + function splitTable(original) + { + original.wrap("<div class='table-wrapper' />"); + + var copy = original.clone(); + copy.find("td:not(:first-child), th:not(:first-child)").css("display", "none"); + copy.removeClass("responsive"); + + original.closest(".table-wrapper").append(copy); + copy.wrap("<div class='pinned' />"); + original.wrap("<div class='scrollable' />"); + + setCellHeights(original, copy); + } + + function unsplitTable(original) { + original.closest(".table-wrapper").find(".pinned").remove(); + original.unwrap(); + original.unwrap(); + } + + function setCellHeights(original, copy) { + var tr = original.find('tr'), + tr_copy = copy.find('tr'), + heights = []; + + tr.each(function (index) { + var self = $(this), + tx = self.find('th, td'); + + tx.each(function () { + var height = $(this).outerHeight(true); + heights[index] = heights[index] || 0; + if (height > heights[index]) heights[index] = height; + }); + + }); + + tr_copy.each(function (index) { + $(this).height(heights[index]); + }); + } + +}); +/* ============================================================ + * bootstrap-dropdown.js v2.3.2 + * http://twitter.github.com/bootstrap/javascript.html#dropdowns + * ============================================================ + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* DROPDOWN CLASS DEFINITION + * ========================= */ + + var toggle = '[data-toggle=dropdown]' + , Dropdown = function (element) { + var $el = $(element).on('click.dropdown.data-api', this.toggle) + $('html').on('click.dropdown.data-api', function () { + $el.parent().removeClass('open') + }) + } + + Dropdown.prototype = { + + constructor: Dropdown + + , toggle: function (e) { + var $this = $(this) + , $parent + , isActive + + if ($this.is('.disabled, :disabled')) return + + $parent = getParent($this) + + isActive = $parent.hasClass('open') + + clearMenus() + + if (!isActive) { + if ('ontouchstart' in document.documentElement) { + // if mobile we we use a backdrop because click events don't delegate + $('<div class="dropdown-backdrop"/>').insertBefore($(this)).on('click', clearMenus) + } + $parent.toggleClass('open') + } + + $this.focus() + + return false + } + + , keydown: function (e) { + var $this + , $items + , $active + , $parent + , isActive + , index + + if (!/(38|40|27)/.test(e.keyCode)) return + + $this = $(this) + + e.preventDefault() + e.stopPropagation() + + if ($this.is('.disabled, :disabled')) return + + $parent = getParent($this) + + isActive = $parent.hasClass('open') + + if (!isActive || (isActive && e.keyCode == 27)) { + if (e.which == 27) $parent.find(toggle).focus() + return $this.click() + } + + $items = $('[role=menu] li:not(.divider):visible a', $parent) + + if (!$items.length) return + + index = $items.index($items.filter(':focus')) + + if (e.keyCode == 38 && index > 0) index-- // up + if (e.keyCode == 40 && index < $items.length - 1) index++ // down + if (!~index) index = 0 + + $items + .eq(index) + .focus() + } + + } + + function clearMenus() { + $('.dropdown-backdrop').remove() + $(toggle).each(function () { + getParent($(this)).removeClass('open') + }) + } + + function getParent($this) { + var selector = $this.attr('data-target') + , $parent + + if (!selector) { + selector = $this.attr('href') + selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 + } + + $parent = selector && $(selector) + + if (!$parent || !$parent.length) $parent = $this.parent() + + return $parent + } + + + /* DROPDOWN PLUGIN DEFINITION + * ========================== */ + + var old = $.fn.dropdown + + $.fn.dropdown = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('dropdown') + if (!data) $this.data('dropdown', (data = new Dropdown(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + $.fn.dropdown.Constructor = Dropdown + + + /* DROPDOWN NO CONFLICT + * ==================== */ + + $.fn.dropdown.noConflict = function () { + $.fn.dropdown = old + return this + } + + + /* APPLY TO STANDARD DROPDOWN ELEMENTS + * =================================== */ + + $(document) + .on('click.dropdown.data-api', clearMenus) + .on('click.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) + .on('click.dropdown.data-api' , toggle, Dropdown.prototype.toggle) + .on('keydown.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown) + + $(document).ready(function() { + $('.dropdown-toggle').dropdown(); + + $('.dropdown input, .dropdown label').click(function(e){ + e.stopPropagation(); + }); + }) + +}(window.jQuery); +// Generated by CoffeeScript 1.6.3 +var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + +(function($, window) { + var Modal; + Modal = (function() { + function Modal(el, options) { + this.hideOnDocumentClick = __bind(this.hideOnDocumentClick, this); + this.hideOnEsc = __bind(this.hideOnEsc, this); + this.show = __bind(this.show, this); + this.init = __bind(this.init, this); + this.options = $.extend({}, options); + this.$el = $(el); + this.modal = $(this.$el.data('target')); + this.close = this.modal.find('.modal-close'); + this.transition = this.$el.data('transition') || "1"; + this.theme = this.$el.data('theme') || "default"; + this.modal.addClass("modal-effect-" + this.transition); + this.modal.find('.modal-content').addClass("modal-content-" + this.theme); + } + + Modal.prototype.init = function() { + var _this = this; + this.$el.click(this.show); + return this.close.click(function(ev) { + ev.stopPropagation(); + return _this.hide(); + }); + }; + + Modal.prototype.show = function(ev) { + if (this.$el.is('div')) { + this.$el.addClass('modal-show'); + } else { + this.modal.addClass('modal-show'); + } + $('.modal-overlay').addClass('modal-show-overlay'); + $('body').bind('keyup', this.hideOnEsc); + return $('body').bind('click', this.hideOnDocumentClick); + }; + + Modal.prototype.hideOnEsc = function(event) { + if (event.keyCode === 27) { + return this.hide(); + } + }; + + Modal.prototype.hideOnDocumentClick = function(event) { + if ($(event.target).is('.modal-overlay')) { + return this.hide(); + } + }; + + Modal.prototype.hide = function() { + $('.modal-overlay').removeClass('modal-show-overlay'); + if (this.$el.is('div')) { + this.$el.removeClass('modal-show'); + } else { + this.modal.removeClass('modal-show'); + } + $('body').unbind('keyup', this.hideOnEsc); + return $('body').unbind('click', this.hideOnDocumentClick); + }; + + return Modal; + + })(); + $.fn.modal = function(option) { + return this.each(function() { + var $this, data, options; + $this = $(this); + data = $this.data('modal'); + options = $.extend({}, $this.data(), typeof option === 'object' && option); + if (!data) { + $this.data('modal', (data = new Modal(this, options))); + } + if (typeof option === 'string') { + return data[option](); + } + }); + }; + $(document).ready(function() { + $('.panel-content').append('<div class="modal-overlay"></div>'); + return $('[data-furatto="modal"]').each(function() { + var modal; + modal = $(this); + return modal.modal('init'); + }); + }); + return $(document).on('click', '[data-furatto="modal"]', function(e) { + var $this; + $this = $(this); + return $this.modal('init'); + }); +})(window.jQuery, window); +/* + * Swiper 2.1 - Mobile Touch Slider + * http://www.idangero.us/sliders/swiper/ + * + * Copyright 2012-2013, Vladimir Kharlampidi + * The iDangero.us + * http://www.idangero.us/ + * + * Licensed under GPL & MIT + * + * Updated on: August 22, 2013 +*/ +var Swiper = function (selector, params) { + /*========================= + A little bit dirty but required part for IE8 and old FF support + ===========================*/ + if (document.body.__defineGetter__) { + if (HTMLElement) { + var element = HTMLElement.prototype; + if (element.__defineGetter__) { + element.__defineGetter__("outerHTML", function () { return new XMLSerializer().serializeToString(this); } ); + } + } + } + + if (!window.getComputedStyle) { + window.getComputedStyle = function (el, pseudo) { + this.el = el; + this.getPropertyValue = function (prop) { + var re = /(\-([a-z]){1})/g; + if (prop === 'float') prop = 'styleFloat'; + if (re.test(prop)) { + prop = prop.replace(re, function () { + return arguments[2].toUpperCase(); + }); + } + return el.currentStyle[prop] ? el.currentStyle[prop] : null; + } + return this; + } + } + if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function(obj, start) { + for (var i = (start || 0), j = this.length; i < j; i++) { + if (this[i] === obj) { return i; } + } + return -1; + } + } + if (!document.querySelectorAll) { + if (!window.jQuery) return; + } + function $$(s) { + if (document.querySelectorAll) + return document.querySelectorAll(s); + else + return jQuery(s); + } + + /*========================= + Check for correct selector + ===========================*/ + if(typeof selector === 'undefined') return; + + if(!(selector.nodeType)){ + if ($$(selector).length === 0) return; + } + + /*========================= + _this + ===========================*/ + var _this = this; + + /*========================= + Default Flags and vars + ===========================*/ + _this.touches = { + start:0, + startX:0, + startY:0, + current:0, + currentX:0, + currentY:0, + diff:0, + abs:0 + }; + _this.positions = { + start:0, + abs:0, + diff:0, + current:0 + }; + _this.times = { + start:0, + end:0 + }; + + _this.id = (new Date()).getTime(); + _this.container = (selector.nodeType) ? selector : $$(selector)[0]; + _this.isTouched = false; + _this.isMoved = false; + _this.activeIndex = 0; + _this.activeLoaderIndex = 0; + _this.activeLoopIndex = 0; + _this.previousIndex = null; + _this.velocity = 0; + _this.snapGrid = []; + _this.slidesGrid = []; + _this.imagesToLoad = []; + _this.imagesLoaded = 0; + _this.wrapperLeft=0; + _this.wrapperRight=0; + _this.wrapperTop=0; + _this.wrapperBottom=0; + var wrapper, slideSize, wrapperSize, direction, isScrolling, containerSize; + + /*========================= + Default Parameters + ===========================*/ + var defaults = { + mode : 'horizontal', // or 'vertical' + touchRatio : 1, + speed : 300, + freeMode : false, + freeModeFluid : false, + momentumRatio: 1, + momentumBounce: true, + momentumBounceRatio: 1, + slidesPerView : 1, + slidesPerGroup : 1, + simulateTouch : true, + followFinger : true, + shortSwipes : true, + moveStartThreshold:false, + autoplay: false, + onlyExternal : false, + createPagination : true, + pagination : false, + paginationElement: 'span', + paginationClickable: false, + paginationAsRange: true, + resistance : true, // or false or 100% + scrollContainer : false, + preventLinks : true, + noSwiping : false, // or class + noSwipingClass : 'swiper-no-swiping', //:) + initialSlide: 0, + keyboardControl: false, + mousewheelControl : false, + mousewheelDebounce: 600, + useCSS3Transforms : true, + //Loop mode + loop:false, + loopAdditionalSlides:0, + //Auto Height + calculateHeight: false, + //Images Preloader + updateOnImagesReady : true, + //Form elements + releaseFormElements : true, + //Watch for active slide, useful when use effects on different slide states + watchActiveIndex: false, + //Slides Visibility Fit + visibilityFullFit : false, + //Slides Offset + offsetPxBefore : 0, + offsetPxAfter : 0, + offsetSlidesBefore : 0, + offsetSlidesAfter : 0, + centeredSlides: false, + //Queue callbacks + queueStartCallbacks : false, + queueEndCallbacks : false, + //Auto Resize + autoResize : true, + resizeReInit : false, + //DOMAnimation + DOMAnimation : true, + //Slides Loader + loader: { + slides:[], //array with slides + slidesHTMLType:'inner', // or 'outer' + surroundGroups: 1, //keep preloaded slides groups around view + logic: 'reload', //or 'change' + loadAllSlides: false + }, + //Namespace + slideElement : 'div', + slideClass : 'swiper-slide', + slideActiveClass : 'swiper-slide-active', + slideVisibleClass : 'swiper-slide-visible', + wrapperClass : 'swiper-wrapper', + paginationElementClass: 'swiper-pagination-switch', + paginationActiveClass : 'swiper-active-switch', + paginationVisibleClass : 'swiper-visible-switch' + } + params = params || {}; + for (var prop in defaults) { + if (prop in params && typeof params[prop]==='object') { + for (var subProp in defaults[prop]) { + if (! (subProp in params[prop])) { + params[prop][subProp] = defaults[prop][subProp]; + } + } + } + else if (! (prop in params)) { + params[prop] = defaults[prop] + } + } + _this.params = params; + if (params.scrollContainer) { + params.freeMode = true; + params.freeModeFluid = true; + } + if (params.loop) { + params.resistance = '100%'; + } + var isH = params.mode==='horizontal'; + + /*========================= + Define Touch Events + ===========================*/ + + _this.touchEvents = { + touchStart : _this.support.touch || !params.simulateTouch ? 'touchstart' : (_this.browser.ie10 ? 'MSPointerDown' : 'mousedown'), + touchMove : _this.support.touch || !params.simulateTouch ? 'touchmove' : (_this.browser.ie10 ? 'MSPointerMove' : 'mousemove'), + touchEnd : _this.support.touch || !params.simulateTouch ? 'touchend' : (_this.browser.ie10 ? 'MSPointerUp' : 'mouseup') + }; + + /*========================= + Wrapper + ===========================*/ + for (var i = _this.container.childNodes.length - 1; i >= 0; i--) { + if (_this.container.childNodes[i].className) { + var _wrapperClasses = _this.container.childNodes[i].className.split(' ') + for (var j = 0; j < _wrapperClasses.length; j++) { + if (_wrapperClasses[j]===params.wrapperClass) { + wrapper = _this.container.childNodes[i]; + } + }; + } + }; + + _this.wrapper = wrapper; + /*========================= + Slide API + ===========================*/ + _this._extendSwiperSlide = function (el) { + el.append = function () { + if (params.loop) { + el.insertAfter(_this.slides.length-_this.loopedSlides); + _this.removeLoopedSlides(); + _this.calcSlides(); + _this.createLoop(); + } + else { + _this.wrapper.appendChild(el); + } + + _this.reInit(); + return el; + } + el.prepend = function () { + if (params.loop) { + _this.wrapper.insertBefore(el, _this.slides[_this.loopedSlides]); + _this.removeLoopedSlides(); + _this.calcSlides(); + _this.createLoop(); + } + else { + _this.wrapper.insertBefore(el, _this.wrapper.firstChild); + } + _this.reInit(); + return el; + } + el.insertAfter = function (index) { + if(typeof index === 'undefined') return false; + var beforeSlide; + + if (params.loop) { + beforeSlide = _this.slides[index + 1 + _this.loopedSlides]; + _this.wrapper.insertBefore(el, beforeSlide); + _this.removeLoopedSlides(); + _this.calcSlides(); + _this.createLoop(); + } + else { + beforeSlide = _this.slides[index + 1]; + _this.wrapper.insertBefore(el, beforeSlide) + } + _this.reInit(); + return el; + } + el.clone = function () { + return _this._extendSwiperSlide(el.cloneNode(true)) + } + el.remove = function () { + _this.wrapper.removeChild(el); + _this.reInit(); + } + el.html = function (html) { + if (typeof html === 'undefined') { + return el.innerHTML; + } + else { + el.innerHTML = html; + return el; + } + } + el.index = function () { + var index; + for (var i = _this.slides.length - 1; i >= 0; i--) { + if(el === _this.slides[i]) index = i; + } + return index; + } + el.isActive = function () { + if (el.index() === _this.activeIndex) return true; + else return false; + } + if (!el.swiperSlideDataStorage) el.swiperSlideDataStorage={}; + el.getData = function (name) { + return el.swiperSlideDataStorage[name]; + } + el.setData = function (name, value) { + el.swiperSlideDataStorage[name] = value; + return el; + } + el.data = function (name, value) { + if (!value) { + return el.getAttribute('data-'+name); + } + else { + el.setAttribute('data-'+name,value); + return el; + } + } + el.getWidth = function (outer) { + return _this.h.getWidth(el, outer); + } + el.getHeight = function (outer) { + return _this.h.getHeight(el, outer); + } + el.getOffset = function() { + return _this.h.getOffset(el); + } + return el; + } + + //Calculate information about number of slides + _this.calcSlides = function (forceCalcSlides) { + var oldNumber = _this.slides ? _this.slides.length : false; + _this.slides = []; + _this.displaySlides = []; + for (var i = 0; i < _this.wrapper.childNodes.length; i++) { + if (_this.wrapper.childNodes[i].className) { + var _className = _this.wrapper.childNodes[i].className; + var _slideClasses = _className.split(' '); + for (var j = 0; j < _slideClasses.length; j++) { + if(_slideClasses[j]===params.slideClass) { + _this.slides.push(_this.wrapper.childNodes[i]); + } + } + } + } + for (i = _this.slides.length - 1; i >= 0; i--) { + _this._extendSwiperSlide(_this.slides[i]); + } + if (!oldNumber) return; + if(oldNumber!==_this.slides.length || forceCalcSlides) { + // Number of slides has been changed + removeSlideEvents(); + addSlideEvents(); + _this.updateActiveSlide(); + if (params.createPagination && _this.params.pagination) _this.createPagination(); + _this.callPlugins('numberOfSlidesChanged'); + } + } + + //Create Slide + _this.createSlide = function (html, slideClassList, el) { + var slideClassList = slideClassList || _this.params.slideClass; + var el = el||params.slideElement; + var newSlide = document.createElement(el); + newSlide.innerHTML = html||''; + newSlide.className = slideClassList; + return _this._extendSwiperSlide(newSlide); + } + + //Append Slide + _this.appendSlide = function (html, slideClassList, el) { + if (!html) return; + if (html.nodeType) { + return _this._extendSwiperSlide(html).append() + } + else { + return _this.createSlide(html, slideClassList, el).append() + } + } + _this.prependSlide = function (html, slideClassList, el) { + if (!html) return; + if (html.nodeType) { + return _this._extendSwiperSlide(html).prepend() + } + else { + return _this.createSlide(html, slideClassList, el).prepend() + } + } + _this.insertSlideAfter = function (index, html, slideClassList, el) { + if (typeof index === 'undefined') return false; + if (html.nodeType) { + return _this._extendSwiperSlide(html).insertAfter(index); + } + else { + return _this.createSlide(html, slideClassList, el).insertAfter(index); + } + } + _this.removeSlide = function (index) { + if (_this.slides[index]) { + if (params.loop) { + if (!_this.slides[index+_this.loopedSlides]) return false; + _this.slides[index+_this.loopedSlides].remove(); + _this.removeLoopedSlides(); + _this.calcSlides(); + _this.createLoop(); + } + else _this.slides[index].remove(); + return true; + } + else return false; + } + _this.removeLastSlide = function () { + if (_this.slides.length>0) { + if (params.loop) { + _this.slides[_this.slides.length - 1 - _this.loopedSlides].remove(); + _this.removeLoopedSlides(); + _this.calcSlides(); + _this.createLoop(); + } + else _this.slides[ (_this.slides.length-1) ].remove(); + return true; + } + else { + return false; + } + } + _this.removeAllSlides = function () { + for (var i = _this.slides.length - 1; i >= 0; i--) { + _this.slides[i].remove() + } + } + _this.getSlide = function (index) { + return _this.slides[index] + } + _this.getLastSlide = function () { + return _this.slides[ _this.slides.length-1 ] + } + _this.getFirstSlide = function () { + return _this.slides[0] + } + + //Currently Active Slide + _this.activeSlide = function () { + return _this.slides[_this.activeIndex] + } + + /*========================= + Plugins API + ===========================*/ + var _plugins = []; + for (var plugin in _this.plugins) { + if (params[plugin]) { + var p = _this.plugins[plugin](_this, params[plugin]); + if (p) _plugins.push( p ); + } + } + _this.callPlugins = function(method, args) { + if (!args) args = {} + for (var i=0; i<_plugins.length; i++) { + if (method in _plugins[i]) { + _plugins[i][method](args); + } + } + } + + /*========================= + WP8 Fix + ===========================*/ + if (_this.browser.ie10 && !params.onlyExternal) { + if (isH) _this.wrapper.classList.add('swiper-wp8-horizontal'); + else _this.wrapper.classList.add('swiper-wp8-vertical'); + } + + /*========================= + Free Mode Class + ===========================*/ + if (params.freeMode) { + _this.container.className+=' swiper-free-mode'; + } + + /*================================================== + Init/Re-init/Resize Fix + ====================================================*/ + _this.initialized = false; + _this.init = function(force, forceCalcSlides) { + var _width = _this.h.getWidth(_this.container); + var _height = _this.h.getHeight(_this.container); + if (_width===_this.width && _height===_this.height && !force) return; + _this.width = _width; + _this.height = _height; + + containerSize = isH ? _width : _height; + var wrapper = _this.wrapper; + + if (force) { + _this.calcSlides(forceCalcSlides); + } + + if (params.slidesPerView==='auto') { + //Auto mode + var slidesWidth = 0; + var slidesHeight = 0; + + //Unset Styles + if (params.slidesOffset>0) { + wrapper.style.paddingLeft = ''; + wrapper.style.paddingRight = ''; + wrapper.style.paddingTop = ''; + wrapper.style.paddingBottom = ''; + } + wrapper.style.width = ''; + wrapper.style.height = ''; + if (params.offsetPxBefore>0) { + if (isH) _this.wrapperLeft = params.offsetPxBefore; + else _this.wrapperTop = params.offsetPxBefore; + } + if (params.offsetPxAfter>0) { + if (isH) _this.wrapperRight = params.offsetPxAfter; + else _this.wrapperBottom = params.offsetPxAfter; + } + + if (params.centeredSlides) { + if (isH) { + _this.wrapperLeft = (containerSize - this.slides[0].getWidth(true) )/2; + _this.wrapperRight = (containerSize - _this.slides[ _this.slides.length-1 ].getWidth(true))/2; + } + else { + _this.wrapperTop = (containerSize - _this.slides[0].getHeight(true))/2; + _this.wrapperBottom = (containerSize - _this.slides[ _this.slides.length-1 ].getHeight(true))/2; + } + } + + if (isH) { + if (_this.wrapperLeft>=0) wrapper.style.paddingLeft = _this.wrapperLeft+'px'; + if (_this.wrapperRight>=0) wrapper.style.paddingRight = _this.wrapperRight+'px'; + } + else { + if (_this.wrapperTop>=0) wrapper.style.paddingTop = _this.wrapperTop+'px'; + if (_this.wrapperBottom>=0) wrapper.style.paddingBottom = _this.wrapperBottom+'px'; + } + var slideLeft = 0; + var centeredSlideLeft=0; + _this.snapGrid = []; + _this.slidesGrid = []; + + var slideMaxHeight = 0; + for(var i = 0; i<_this.slides.length; i++) { + var slideWidth = _this.slides[i].getWidth(true); + var slideHeight = _this.slides[i].getHeight(true); + if (params.calculateHeight) { + slideMaxHeight = Math.max(slideMaxHeight, slideHeight) + } + var _slideSize = isH ? slideWidth : slideHeight; + if (params.centeredSlides) { + var nextSlideWidth = i === _this.slides.length-1 ? 0 : _this.slides[i+1].getWidth(true); + var nextSlideHeight = i === _this.slides.length-1 ? 0 : _this.slides[i+1].getHeight(true); + var nextSlideSize = isH ? nextSlideWidth : nextSlideHeight; + if (_slideSize>containerSize) { + for (var j=0; j<=Math.floor(_slideSize/(containerSize+_this.wrapperLeft)); j++) { + if (j === 0) _this.snapGrid.push(slideLeft+_this.wrapperLeft); + else _this.snapGrid.push(slideLeft+_this.wrapperLeft+containerSize*j); + } + _this.slidesGrid.push(slideLeft+_this.wrapperLeft); + } + else { + _this.snapGrid.push(centeredSlideLeft); + _this.slidesGrid.push(centeredSlideLeft); + } + + centeredSlideLeft += _slideSize/2 + nextSlideSize/2; + + } + else { + if (_slideSize>containerSize) { + for (var j=0; j<=Math.floor(_slideSize/containerSize); j++) { + _this.snapGrid.push(slideLeft+containerSize*j); + } + } + else { + _this.snapGrid.push(slideLeft); + } + _this.slidesGrid.push(slideLeft); + } + + slideLeft += _slideSize; + + slidesWidth += slideWidth; + slidesHeight += slideHeight; + } + if (params.calculateHeight) _this.height = slideMaxHeight; + if(isH) { + wrapperSize = slidesWidth + _this.wrapperRight + _this.wrapperLeft; + wrapper.style.width = (slidesWidth)+'px'; + wrapper.style.height = (_this.height)+'px'; + } + else { + wrapperSize = slidesHeight + _this.wrapperTop + _this.wrapperBottom; + wrapper.style.width = (_this.width)+'px'; + wrapper.style.height = (slidesHeight)+'px'; + } + + } + else if (params.scrollContainer) { + //Scroll Container + wrapper.style.width = ''; + wrapper.style.height = ''; + var wrapperWidth = _this.slides[0].getWidth(true); + var wrapperHeight = _this.slides[0].getHeight(true); + wrapperSize = isH ? wrapperWidth : wrapperHeight; + wrapper.style.width = wrapperWidth+'px'; + wrapper.style.height = wrapperHeight+'px'; + slideSize = isH ? wrapperWidth : wrapperHeight; + + } + else { + //For usual slides + if (params.calculateHeight) { + var slideMaxHeight = 0; + var wrapperHeight = 0; + //ResetWrapperSize + if (!isH) _this.container.style.height= ''; + wrapper.style.height=''; + + for (var i=0; i<_this.slides.length; i++) { + //ResetSlideSize + _this.slides[i].style.height=''; + slideMaxHeight = Math.max( _this.slides[i].getHeight(true), slideMaxHeight ); + if (!isH) wrapperHeight+=_this.slides[i].getHeight(true); + } + var slideHeight = slideMaxHeight; + _this.height = slideHeight; + + if (isH) wrapperHeight = slideHeight; + else containerSize = slideHeight, _this.container.style.height= containerSize+'px'; + } + else { + var slideHeight = isH ? _this.height : _this.height/params.slidesPerView ; + var wrapperHeight = isH ? _this.height : _this.slides.length*slideHeight; + } + var slideWidth = isH ? _this.width/params.slidesPerView : _this.width; + var wrapperWidth = isH ? _this.slides.length*slideWidth : _this.width; + slideSize = isH ? slideWidth : slideHeight; + + if (params.offsetSlidesBefore>0) { + if (isH) _this.wrapperLeft = slideSize*params.offsetSlidesBefore; + else _this.wrapperTop = slideSize*params.offsetSlidesBefore; + } + if (params.offsetSlidesAfter>0) { + if (isH) _this.wrapperRight = slideSize*params.offsetSlidesAfter; + else _this.wrapperBottom = slideSize*params.offsetSlidesAfter; + } + if (params.offsetPxBefore>0) { + if (isH) _this.wrapperLeft = params.offsetPxBefore; + else _this.wrapperTop = params.offsetPxBefore; + } + if (params.offsetPxAfter>0) { + if (isH) _this.wrapperRight = params.offsetPxAfter; + else _this.wrapperBottom = params.offsetPxAfter; + } + if (params.centeredSlides) { + if (isH) { + _this.wrapperLeft = (containerSize - slideSize)/2; + _this.wrapperRight = (containerSize - slideSize)/2; + } + else { + _this.wrapperTop = (containerSize - slideSize)/2; + _this.wrapperBottom = (containerSize - slideSize)/2; + } + } + if (isH) { + if (_this.wrapperLeft>0) wrapper.style.paddingLeft = _this.wrapperLeft+'px'; + if (_this.wrapperRight>0) wrapper.style.paddingRight = _this.wrapperRight+'px'; + } + else { + if (_this.wrapperTop>0) wrapper.style.paddingTop = _this.wrapperTop+'px'; + if (_this.wrapperBottom>0) wrapper.style.paddingBottom = _this.wrapperBottom+'px'; + } + + wrapperSize = isH ? wrapperWidth + _this.wrapperRight + _this.wrapperLeft : wrapperHeight + _this.wrapperTop + _this.wrapperBottom; + wrapper.style.width = wrapperWidth+'px'; + wrapper.style.height = wrapperHeight+'px'; + var slideLeft = 0; + _this.snapGrid = []; + _this.slidesGrid = []; + for (var i=0; i<_this.slides.length; i++) { + _this.snapGrid.push(slideLeft); + _this.slidesGrid.push(slideLeft); + slideLeft+=slideSize; + _this.slides[i].style.width = slideWidth+'px'; + _this.slides[i].style.height = slideHeight+'px'; + } + + } + + if (!_this.initialized) { + _this.callPlugins('onFirstInit'); + if (params.onFirstInit) params.onFirstInit(_this); + } + else { + _this.callPlugins('onInit'); + if (params.onInit) params.onInit(_this); + } + _this.initialized = true; + } + _this.reInit = function (forceCalcSlides) { + _this.init(true, forceCalcSlides); + } + _this.resizeFix = function(reInit){ + _this.callPlugins('beforeResizeFix'); + _this.init(params.resizeReInit||reInit); + if (!params.freeMode) { + if (params.loop) _this.swipeTo(_this.activeLoopIndex, 0, false); + else _this.swipeTo(_this.activeIndex, 0, false); + } + else { + var pos = isH ? _this.getWrapperTranslate('x') : _this.getWrapperTranslate('y'); + if (pos < -maxWrapperPosition()) { + var x = isH ? -maxWrapperPosition() : 0; + var y = isH ? 0 : -maxWrapperPosition(); + _this.setWrapperTransition(0); + _this.setWrapperTranslate(x,y,0); + } + } + _this.callPlugins('afterResizeFix'); + } + + /*========================================== + Max and Min Positions + ============================================*/ + function maxWrapperPosition() { + var a = (wrapperSize - containerSize); + if (params.freeMode) { + a = wrapperSize - containerSize; + } + // if (params.loop) a -= containerSize; + if (params.slidesPerView > _this.slides.length) a = 0; + if (a<0) a = 0; + return a; + } + function minWrapperPosition() { + var a = 0; + // if (params.loop) a = containerSize; + return a; + } + + /*========================================== + Event Listeners + ============================================*/ + function initEvents() { + //Touch Events + if (!_this.browser.ie10) { + if (_this.support.touch) { + _this.h.addEventListener(_this.wrapper, 'touchstart', onTouchStart, false); + _this.h.addEventListener(_this.wrapper, 'touchmove', onTouchMove, false); + _this.h.addEventListener(_this.wrapper, 'touchend', onTouchEnd, false); + } + if (params.simulateTouch) { + _this.h.addEventListener(_this.wrapper, 'mousedown', onTouchStart, false); + _this.h.addEventListener(document, 'mousemove', onTouchMove, false); + _this.h.addEventListener(document, 'mouseup', onTouchEnd, false); + } + } + else { + _this.h.addEventListener(_this.wrapper, _this.touchEvents.touchStart, onTouchStart, false); + _this.h.addEventListener(document, _this.touchEvents.touchMove, onTouchMove, false); + _this.h.addEventListener(document, _this.touchEvents.touchEnd, onTouchEnd, false); + } + //Resize Event + if (params.autoResize) { + _this.h.addEventListener(window, 'resize', _this.resizeFix, false); + } + //Slide Events + addSlideEvents(); + //Mousewheel + _this._wheelEvent = false; + if (params.mousewheelControl) { + if ( document.onmousewheel !== undefined ) { + _this._wheelEvent = "mousewheel"; + } + try { + WheelEvent("wheel"); + _this._wheelEvent = "wheel"; + } catch (e) {} + if ( !_this._wheelEvent ) { + _this._wheelEvent = "DOMMouseScroll"; + } + + if (_this._wheelEvent) { + _this.h.addEventListener(_this.container, _this._wheelEvent, handleMousewheel, false); + } + } + + //Keyboard + if (params.keyboardControl) { + _this.h.addEventListener(document, 'keydown', handleKeyboardKeys, false); + } + if (params.updateOnImagesReady) { + if (document.querySelectorAll) _this.imagesToLoad = _this.container.querySelectorAll('img'); + else if (window.jQuery) _this.imagesToLoad = $$(_this.container).find('img'); + + for (var i=0; i<_this.imagesToLoad.length; i++) { + _loadImage(_this.imagesToLoad[i].getAttribute('src')) + } + } + function _loadImage(src) { + var image = new Image(); + image.onload = function(){ + _this.imagesLoaded++; + if (_this.imagesLoaded==_this.imagesToLoad.length) { + _this.reInit(); + if (params.onImagesReady) params.onImagesReady(_this); + } + } + image.src = src; + } + } + + + + //Remove Event Listeners + _this.destroy = function(removeResizeFix){ + //Touch Events + if (!_this.browser.ie10) { + if (_this.support.touch) { + _this.h.removeEventListener(_this.wrapper, 'touchstart', onTouchStart, false); + _this.h.removeEventListener(_this.wrapper, 'touchmove', onTouchMove, false); + _this.h.removeEventListener(_this.wrapper, 'touchend', onTouchEnd, false); + } + if (params.simulateTouch) { + _this.h.removeEventListener(_this.wrapper, 'mousedown', onTouchStart, false); + _this.h.removeEventListener(document, 'mousemove', onTouchMove, false); + _this.h.removeEventListener(document, 'mouseup', onTouchEnd, false); + } + } + else { + _this.h.removeEventListener(_this.wrapper, _this.touchEvents.touchStart, onTouchStart, false); + _this.h.removeEventListener(document, _this.touchEvents.touchMove, onTouchMove, false); + _this.h.removeEventListener(document, _this.touchEvents.touchEnd, onTouchEnd, false); + } + //Resize Event + if (params.autoResize) { + _this.h.removeEventListener(window, 'resize', _this.resizeFix, false); + } + //Init Slide Events + removeSlideEvents(); + + //Pagination + if (params.paginationClickable) { + removePaginationEvents(); + } + + //Mousewheel + if (params.mousewheelControl && _this._wheelEvent) { + _this.h.removeEventListener(_this.container, _this._wheelEvent, handleMousewheel, false); + } + + //Keyboard + if (params.keyboardControl) { + _this.h.removeEventListener(document, 'keydown', handleKeyboardKeys, false); + } + + //Stop autoplay + if (params.autoplay) { + _this.stopAutoplay(); + } + _this.callPlugins('onDestroy'); + + //Destroy variable + _this = null; + } + function addSlideEvents() { + //Prevent Links Events + if (params.preventLinks) { + var links = []; + if (document.querySelectorAll) { + links = _this.container.querySelectorAll('a'); + } + else if (window.jQuery) { + links = $$(_this.container).find('a'); + } + for (var i=0; i<links.length; i++) { + _this.h.addEventListener(links[i], 'click', preventClick, false); + } + } + //Release Form Elements + if (params.releaseFormElements) { + var formElements = document.querySelectorAll ? _this.container.querySelectorAll('input, textarea, select') : $$(_this.container).find('input, textarea, select'); + for (var i=0; i<formElements.length; i++) { + _this.h.addEventListener(formElements[i], _this.touchEvents.touchStart, releaseForms, true); + } + } + + //Slide Clicks & Touches + if (params.onSlideClick) { + for (var i=0; i<_this.slides.length; i++) { + _this.h.addEventListener(_this.slides[i], 'click', slideClick, false); + } + } + if (params.onSlideTouch) { + for (var i=0; i<_this.slides.length; i++) { + _this.h.addEventListener(_this.slides[i], _this.touchEvents.touchStart, slideTouch, false); + } + } + } + function removeSlideEvents() { + //Slide Clicks & Touches + if (params.onSlideClick) { + for (var i=0; i<_this.slides.length; i++) { + _this.h.removeEventListener(_this.slides[i], 'click', slideClick, false); + } + } + if (params.onSlideTouch) { + for (var i=0; i<_this.slides.length; i++) { + _this.h.removeEventListener(_this.slides[i], _this.touchEvents.touchStart, slideTouch, false); + } + } + //Release Form Elements + if (params.releaseFormElements) { + var formElements = document.querySelectorAll ? _this.container.querySelectorAll('input, textarea, select') : $$(_this.container).find('input, textarea, select'); + for (var i=0; i<formElements.length; i++) { + _this.h.removeEventListener(formElements[i], _this.touchEvents.touchStart, releaseForms, true); + } + } + //Prevent Links Events + if (params.preventLinks) { + var links = []; + if (document.querySelectorAll) { + links = _this.container.querySelectorAll('a'); + } + else if (window.jQuery) { + links = $$(_this.container).find('a'); + } + for (var i=0; i<links.length; i++) { + _this.h.removeEventListener(links[i], 'click', preventClick, false); + } + } + } + /*========================================== + Keyboard Control + ============================================*/ + function handleKeyboardKeys (e) { + var kc = e.keyCode || e.charCode; + if (kc==37 || kc==39 || kc==38 || kc==40) { + var inView = false; + //Check that swiper should be inside of visible area of window + var swiperOffset = _this.h.getOffset( _this.container ); + var scrollLeft = _this.h.windowScroll().left; + var scrollTop = _this.h.windowScroll().top; + var windowWidth = _this.h.windowWidth(); + var windowHeight = _this.h.windowHeight(); + var swiperCoord = [ + [swiperOffset.left, swiperOffset.top], + [swiperOffset.left + _this.width, swiperOffset.top], + [swiperOffset.left, swiperOffset.top + _this.height], + [swiperOffset.left + _this.width, swiperOffset.top + _this.height] + ] + for (var i=0; i<swiperCoord.length; i++) { + var point = swiperCoord[i]; + if ( + point[0]>=scrollLeft && point[0]<=scrollLeft+windowWidth && + point[1]>=scrollTop && point[1]<=scrollTop+windowHeight + ) { + inView = true; + } + + } + if (!inView) return; + } + if (isH) { + if (kc==37 || kc==39) { + if (e.preventDefault) e.preventDefault(); + else e.returnValue = false; + } + if (kc == 39) _this.swipeNext(); + if (kc == 37) _this.swipePrev(); + } + else { + if (kc==38 || kc==40) { + if (e.preventDefault) e.preventDefault(); + else e.returnValue = false; + } + if (kc == 40) _this.swipeNext(); + if (kc == 38) _this.swipePrev(); + } + } + + /*========================================== + Mousewheel Control + ============================================*/ + var allowScrollChange = true; + function handleMousewheel (e) { + var we = _this._wheelEvent; + var delta; + //Opera & IE + if (e.detail) delta = -e.detail; + //WebKits + else if (we == 'mousewheel') delta = e.wheelDelta; + //Old FireFox + else if (we == 'DOMMouseScroll') delta = -e.detail; + //New FireFox + else if (we == 'wheel') { + delta = Math.abs(e.deltaX)>Math.abs(e.deltaY) ? - e.deltaX : - e.deltaY; + } + if (!params.freeMode) { + if(delta<0) _this.swipeNext(); + else _this.swipePrev(); + } + else { + //Freemode or scrollContainer: + var currentTransform =isH ? _this.getWrapperTranslate('x') : _this.getWrapperTranslate('y'); + var x,y; + if (isH) { + x = _this.getWrapperTranslate('x') + delta; + y = _this.getWrapperTranslate('y'); + if (x>0) x = 0; + if (x<-maxWrapperPosition()) x = -maxWrapperPosition(); + } + else { + x = _this.getWrapperTranslate('x'); + y = _this.getWrapperTranslate('y')+delta; + if (y>0) y = 0; + if (y<-maxWrapperPosition()) y = -maxWrapperPosition(); + } + _this.setWrapperTransition(0); + _this.setWrapperTranslate(x,y,0); + if (isH) _this.updateActiveSlide(x); + else _this.updateActiveSlide(y); + } + if (params.autoplay) _this.stopAutoplay(); + + if(e.preventDefault) e.preventDefault(); + else e.returnValue = false; + return false; + } + + /*========================= + Grab Cursor + ===========================*/ + if (params.grabCursor) { + _this.container.style.cursor = 'move'; + _this.container.style.cursor = 'grab'; + _this.container.style.cursor = '-moz-grab'; + _this.container.style.cursor = '-webkit-grab'; + } + + /*========================= + Slides Events Handlers + ===========================*/ + function findSlide(el) { + var found = false; + while(!found) { + if (el.className.indexOf(params.slideClass)>-1) + { + found = el; + } + el = el.parentElement; + } + return found; + } + _this.allowSlideClick = true; + function slideClick(e) { + if(_this.allowSlideClick) { + if (!e.target) { + _this.clickedSlide = findSlide(e.srcElement); + _this.clickedSlideIndex = _this.slides.indexOf(_this.clickedSlide); + } + else { + _this.clickedSlide = this; + _this.clickedSlideIndex = _this.slides.indexOf(this); + } + params.onSlideClick(_this); + } + } + function slideTouch(e) { + if (!e.target) _this.clickedSlide = findSlide(e.srcElement); + else _this.clickedSlide = this; + _this.clickedSlideIndex = _this.slides.indexOf(_this.clickedSlide); + params.onSlideTouch(_this); + } + _this.allowLinks = true; + function preventClick(e) { + if (!_this.allowLinks) { + if(e.preventDefault) e.preventDefault(); + else e.returnValue = false; + return false; + } + } + function releaseForms(e) { + if (e.stopPropagation) e.stopPropagation(); + else e.returnValue = false; + return false; + } + + /*================================================== + Event Handlers + ====================================================*/ + var isTouchEvent = false; + var allowThresholdMove; + var allowMomentumBounce = true; + function onTouchStart(event) { + if (params.preventLinks) _this.allowLinks = true; + //Exit if slider is already was touched + if (_this.isTouched || params.onlyExternal) { + return false; + } + + if (params.noSwiping && (event.target || event.srcElement) && noSwipingSlide(event.target || event.srcElement)) return false; + allowMomentumBounce = false; + + //Check For Nested Swipers + _this.isTouched = true; + isTouchEvent = event.type=='touchstart'; + + if (!isTouchEvent || event.targetTouches.length == 1 ) { + if (params.loop) _this.fixLoop(); + _this.callPlugins('onTouchStartBegin'); + + if(!isTouchEvent) { + if(event.preventDefault) event.preventDefault(); + else event.returnValue = false; + } + + var pageX = isTouchEvent ? event.targetTouches[0].pageX : (event.pageX || event.clientX); + var pageY = isTouchEvent ? event.targetTouches[0].pageY : (event.pageY || event.clientY); + + //Start Touches to check the scrolling + _this.touches.startX = _this.touches.currentX = pageX; + _this.touches.startY = _this.touches.currentY = pageY; + + _this.touches.start = _this.touches.current = isH ? pageX : pageY ; + + //Set Transition Time to 0 + _this.setWrapperTransition(0); + + //Get Start Translate Position + _this.positions.start = _this.positions.current = isH ? _this.getWrapperTranslate('x') : _this.getWrapperTranslate('y'); + + //Set Transform + if (isH) { + _this.setWrapperTranslate( _this.positions.start, 0, 0); + } + else { + _this.setWrapperTranslate( 0, _this.positions.start, 0); + } + + //TouchStartTime + _this.times.start = (new Date()).getTime(); + + //Unset Scrolling + isScrolling = undefined; + + //Set Treshold + if (params.moveStartThreshold>0) allowThresholdMove = false; + + //CallBack + if (params.onTouchStart) params.onTouchStart(_this); + _this.callPlugins('onTouchStartEnd'); + + } + } + var velocityPrevPosition, velocityPrevTime; + function onTouchMove(event) { + // If slider is not touched - exit + if (!_this.isTouched || params.onlyExternal) return; + if (isTouchEvent && event.type=='mousemove') return; + + var pageX = isTouchEvent ? event.targetTouches[0].pageX : (event.pageX || event.clientX); + var pageY = isTouchEvent ? event.targetTouches[0].pageY : (event.pageY || event.clientY); + + //check for scrolling + if ( typeof isScrolling === 'undefined' && isH) { + isScrolling = !!( isScrolling || Math.abs(pageY - _this.touches.startY) > Math.abs( pageX - _this.touches.startX ) ); + } + if ( typeof isScrolling === 'undefined' && !isH) { + isScrolling = !!( isScrolling || Math.abs(pageY - _this.touches.startY) < Math.abs( pageX - _this.touches.startX ) ); + } + if (isScrolling ) { + _this.isTouched = false; + return + } + + //Check For Nested Swipers + if (event.assignedToSwiper) { + _this.isTouched = false; + return + } + event.assignedToSwiper = true; + + //Moved Flag + _this.isMoved = true; + + //Block inner links + if (params.preventLinks) { + _this.allowLinks = false; + } + if (params.onSlideClick) { + _this.allowSlideClick = false; + } + + //Stop AutoPlay if exist + if (params.autoplay) { + _this.stopAutoplay(); + } + if (!isTouchEvent || event.touches.length == 1) { + + _this.callPlugins('onTouchMoveStart'); + if(event.preventDefault) event.preventDefault(); + else event.returnValue = false; + + _this.touches.current = isH ? pageX : pageY ; + + _this.positions.current = (_this.touches.current - _this.touches.start) * params.touchRatio + _this.positions.start; + + //Resistance Callbacks + if(_this.positions.current > 0 && params.onResistanceBefore) { + params.onResistanceBefore(_this, _this.positions.current); + } + if(_this.positions.current < -maxWrapperPosition() && params.onResistanceAfter) { + params.onResistanceAfter(_this, Math.abs(_this.positions.current + maxWrapperPosition())); + } + //Resistance + if (params.resistance && params.resistance!='100%') { + //Resistance for Negative-Back sliding + if(_this.positions.current > 0) { + var resistance = 1 - _this.positions.current/containerSize/2; + if (resistance < 0.5) + _this.positions.current = (containerSize/2); + else + _this.positions.current = _this.positions.current * resistance; + } + //Resistance for After-End Sliding + if ( _this.positions.current < -maxWrapperPosition() ) { + + var diff = (_this.touches.current - _this.touches.start)*params.touchRatio + (maxWrapperPosition()+_this.positions.start); + var resistance = (containerSize+diff)/(containerSize); + var newPos = _this.positions.current-diff*(1-resistance)/2; + var stopPos = -maxWrapperPosition() - containerSize/2; + + if (newPos < stopPos || resistance<=0) + _this.positions.current = stopPos; + else + _this.positions.current = newPos; + } + } + if (params.resistance && params.resistance=='100%') { + //Resistance for Negative-Back sliding + if(_this.positions.current > 0 && !(params.freeMode&&!params.freeModeFluid)) { + _this.positions.current = 0; + } + //Resistance for After-End Sliding + if ( (_this.positions.current) < -maxWrapperPosition() && !(params.freeMode&&!params.freeModeFluid)) { + _this.positions.current = -maxWrapperPosition(); + } + } + //Move Slides + if (!params.followFinger) return + + if (!params.moveStartThreshold) { + if (isH) _this.setWrapperTranslate( _this.positions.current, 0, 0); + else _this.setWrapperTranslate( 0, _this.positions.current, 0); + } + else { + if ( Math.abs(_this.touches.current - _this.touches.start)>params.moveStartThreshold || allowThresholdMove) { + allowThresholdMove = true; + if (isH) _this.setWrapperTranslate( _this.positions.current, 0, 0); + else _this.setWrapperTranslate( 0, _this.positions.current, 0); + } + else { + _this.positions.current = _this.positions.start; + } + } + + if (params.freeMode || params.watchActiveIndex) { + _this.updateActiveSlide(_this.positions.current); + } + + //Grab Cursor + if (params.grabCursor) { + _this.container.style.cursor = 'move'; + _this.container.style.cursor = 'grabbing'; + _this.container.style.cursor = '-moz-grabbin'; + _this.container.style.cursor = '-webkit-grabbing'; + } + //Velocity + if (!velocityPrevPosition) velocityPrevPosition = _this.touches.current; + if (!velocityPrevTime) velocityPrevTime = (new Date).getTime(); + _this.velocity = (_this.touches.current - velocityPrevPosition)/((new Date).getTime() - velocityPrevTime)/2; + if (Math.abs(_this.touches.current - velocityPrevPosition)<2) _this.velocity=0; + velocityPrevPosition = _this.touches.current; + velocityPrevTime = (new Date).getTime(); + //Callbacks + _this.callPlugins('onTouchMoveEnd'); + if (params.onTouchMove) params.onTouchMove(_this); + + return false; + } + } + function onTouchEnd(event) { + //Check For scrolling + if (isScrolling) { + _this.swipeReset(); + } + // If slider is not touched exit + if ( params.onlyExternal || !_this.isTouched ) return; + _this.isTouched = false + + //Return Grab Cursor + if (params.grabCursor) { + _this.container.style.cursor = 'move'; + _this.container.style.cursor = 'grab'; + _this.container.style.cursor = '-moz-grab'; + _this.container.style.cursor = '-webkit-grab'; + } + + //Check for Current Position + if (!_this.positions.current && _this.positions.current!==0) { + _this.positions.current = _this.positions.start + } + + //For case if slider touched but not moved + if (params.followFinger) { + if (isH) _this.setWrapperTranslate( _this.positions.current, 0, 0) + else _this.setWrapperTranslate( 0, _this.positions.current, 0) + } + //-- + + // TouchEndTime + _this.times.end = (new Date()).getTime(); + + //Difference + _this.touches.diff = _this.touches.current - _this.touches.start + _this.touches.abs = Math.abs(_this.touches.diff) + + _this.positions.diff = _this.positions.current - _this.positions.start + _this.positions.abs = Math.abs(_this.positions.diff) + + var diff = _this.positions.diff ; + var diffAbs =_this.positions.abs ; + var timeDiff = _this.times.end - _this.times.start + + if(diffAbs < 5 && (timeDiff) < 300 && _this.allowLinks == false) { + if (!params.freeMode && diffAbs!=0) _this.swipeReset() + //Release inner links + if (params.preventLinks) { + _this.allowLinks = true; + } + if (params.onSlideClick) { + _this.allowSlideClick = true; + } + } + setTimeout(function(){ + //Release inner links + if (params.preventLinks) { + _this.allowLinks = true; + } + if (params.onSlideClick) { + _this.allowSlideClick = true; + } + },100) + + //Exit if not moved + if (!_this.isMoved) { + _this.isMoved = false; + if (params.onTouchEnd) params.onTouchEnd(_this) + _this.callPlugins('onTouchEnd'); + _this.swipeReset(); + return; + } + _this.isMoved = false; + + var maxPosition = maxWrapperPosition(); + + //Prevent Negative Back Sliding + if (_this.positions.current > 0) { + _this.swipeReset() + if (params.onTouchEnd) params.onTouchEnd(_this) + _this.callPlugins('onTouchEnd'); + return; + } + //Prevent After-End Sliding + if (_this.positions.current < -maxPosition) { + _this.swipeReset() + if (params.onTouchEnd) params.onTouchEnd(_this) + _this.callPlugins('onTouchEnd'); + return; + } + + //Free Mode + if (params.freeMode) { + if ( params.freeModeFluid ) { + var momentumDuration = 1000*params.momentumRatio; + var momentumDistance = _this.velocity*momentumDuration; + var newPosition = _this.positions.current + momentumDistance + var doBounce = false; + var afterBouncePosition; + var bounceAmount = Math.abs( _this.velocity )*20*params.momentumBounceRatio; + if (newPosition < -maxPosition) { + if (params.momentumBounce && _this.support.transitions) { + if (newPosition + maxPosition < -bounceAmount) newPosition = -maxPosition-bounceAmount; + afterBouncePosition = -maxPosition; + doBounce=true; + allowMomentumBounce = true; + } + else newPosition = -maxPosition; + } + if (newPosition > 0) { + if (params.momentumBounce && _this.support.transitions) { + if (newPosition>bounceAmount) newPosition = bounceAmount; + afterBouncePosition = 0 + doBounce = true; + allowMomentumBounce = true; + } + else newPosition = 0; + } + //Fix duration + if (_this.velocity!=0) momentumDuration = Math.abs((newPosition - _this.positions.current)/_this.velocity) + + if (isH) _this.setWrapperTranslate( newPosition, 0, 0); + else _this.setWrapperTranslate( 0, newPosition, 0); + + _this.setWrapperTransition( momentumDuration ); + + if (params.momentumBounce && doBounce) { + _this.wrapperTransitionEnd(function(){ + if (!allowMomentumBounce) return; + if (params.onMomentumBounce) params.onMomentumBounce(_this); + if (isH) _this.setWrapperTranslate(afterBouncePosition, 0, 0); + else _this.setWrapperTranslate(0, afterBouncePosition, 0); + _this.setWrapperTransition(300); + }) + } + + _this.updateActiveSlide(newPosition) + } + if (!params.freeModeFluid || timeDiff >= 300) _this.updateActiveSlide(_this.positions.current) + + if (params.onTouchEnd) params.onTouchEnd(_this) + _this.callPlugins('onTouchEnd'); + return; + } + + //Direction + direction = diff < 0 ? "toNext" : "toPrev" + + //Short Touches + if (direction=="toNext" && ( timeDiff <= 300 ) ) { + if (diffAbs < 30 || !params.shortSwipes) _this.swipeReset() + else _this.swipeNext(true); + } + + if (direction=="toPrev" && ( timeDiff <= 300 ) ) { + if (diffAbs < 30 || !params.shortSwipes) _this.swipeReset() + else _this.swipePrev(true); + } + + //Long Touches + var targetSlideSize = 0; + if(params.slidesPerView == 'auto') { + //Define current slide's width + var currentPosition = Math.abs( isH ? _this.getWrapperTranslate('x') : _this.getWrapperTranslate('y') ); + var slidesOffset = 0; + var _slideSize; + for (var i=0; i<_this.slides.length; i++) { + _slideSize = isH ? _this.slides[i].getWidth(true) : _this.slides[i].getHeight(true); + slidesOffset+= _slideSize; + if (slidesOffset>currentPosition) { + targetSlideSize = _slideSize; + break; + } + } + if (targetSlideSize>containerSize) targetSlideSize = containerSize; + } + else { + targetSlideSize = slideSize * params.slidesPerView; + } + if (direction=="toNext" && ( timeDiff > 300 ) ) { + if (diffAbs >= targetSlideSize*0.5) { + _this.swipeNext(true) + } + else { + _this.swipeReset() + } + } + if (direction=="toPrev" && ( timeDiff > 300 ) ) { + if (diffAbs >= targetSlideSize*0.5) { + _this.swipePrev(true); + } + else { + _this.swipeReset() + } + } + if (params.onTouchEnd) params.onTouchEnd(_this) + _this.callPlugins('onTouchEnd'); + } + + + /*================================================== + noSwiping Bubble Check by Isaac Strack + ====================================================*/ + function noSwipingSlide(el){ + /*This function is specifically designed to check the parent elements for the noSwiping class, up to the wrapper. + We need to check parents because while onTouchStart bubbles, _this.isTouched is checked in onTouchStart, which stops the bubbling. + So, if a text box, for example, is the initial target, and the parent slide container has the noSwiping class, the _this.isTouched + check will never find it, and what was supposed to be noSwiping is able to be swiped. + This function will iterate up and check for the noSwiping class in parents, up through the wrapperClass.*/ + + // First we create a truthy variable, which is that swiping is allowd (noSwiping = false) + var noSwiping = false; + + // Now we iterate up (parentElements) until we reach the node with the wrapperClass. + do{ + + // Each time, we check to see if there's a 'swiper-no-swiping' class (noSwipingClass). + if (el.className.indexOf(params.noSwipingClass)>-1) + { + noSwiping = true; // If there is, we set noSwiping = true; + } + + el = el.parentElement; // now we iterate up (parent node) + + } while(!noSwiping && el.parentElement && el.className.indexOf(params.wrapperClass)==-1); // also include el.parentElement truthy, just in case. + + // because we didn't check the wrapper itself, we do so now, if noSwiping is false: + if (!noSwiping && el.className.indexOf(params.wrapperClass)>-1 && el.className.indexOf(params.noSwipingClass)>-1) + noSwiping = true; // if the wrapper has the noSwipingClass, we set noSwiping = true; + + return noSwiping; + } + + /*================================================== + Swipe Functions + ====================================================*/ + _this.swipeNext = function(internal){ + if (!internal && params.loop) _this.fixLoop(); + _this.callPlugins('onSwipeNext'); + var currentPosition = isH ? _this.getWrapperTranslate('x') : _this.getWrapperTranslate('y'); + var newPosition = currentPosition; + if (params.slidesPerView=='auto') { + for (var i=0; i<_this.snapGrid.length; i++) { + if (-currentPosition >= _this.snapGrid[i] && -currentPosition<_this.snapGrid[i+1]) { + newPosition = -_this.snapGrid[i+1] + break; + } + } + } + else { + var groupSize = slideSize * params.slidesPerGroup; + newPosition = -(Math.floor(Math.abs(currentPosition)/Math.floor(groupSize))*groupSize + groupSize); + } + if (newPosition < - maxWrapperPosition()) { + newPosition = - maxWrapperPosition() + }; + + if (newPosition == currentPosition) return false; + + swipeToPosition(newPosition, 'next'); + return true + } + _this.swipePrev = function(internal){ + if (!internal && params.loop) _this.fixLoop(); + if (!internal && params.autoplay) _this.stopAutoplay(); + _this.callPlugins('onSwipePrev'); + + var currentPosition = Math.ceil( isH ? _this.getWrapperTranslate('x') : _this.getWrapperTranslate('y') ); + var newPosition; + if (params.slidesPerView=='auto') { + newPosition = 0; + for (var i=1; i<_this.snapGrid.length; i++) { + if (-currentPosition == _this.snapGrid[i]) { + newPosition = -_this.snapGrid[i-1] + break; + } + if (-currentPosition > _this.snapGrid[i] && -currentPosition<_this.snapGrid[i+1]) { + newPosition = -_this.snapGrid[i] + break; + } + } + } + else { + var groupSize = slideSize * params.slidesPerGroup; + newPosition = -(Math.ceil(-currentPosition/groupSize)-1)*groupSize; + } + + if (newPosition > 0) newPosition = 0; + + if (newPosition == currentPosition) return false; + swipeToPosition(newPosition, 'prev'); + return true; + + } + _this.swipeReset = function(){ + _this.callPlugins('onSwipeReset'); + var currentPosition = isH ? _this.getWrapperTranslate('x') : _this.getWrapperTranslate('y'); + var groupSize = slideSize * params.slidesPerGroup; + var newPosition; + var maxPosition = -maxWrapperPosition(); + if (params.slidesPerView=='auto') { + newPosition = 0; + for (var i=0; i<_this.snapGrid.length; i++) { + if (-currentPosition===_this.snapGrid[i]) return; + if (-currentPosition >= _this.snapGrid[i] && -currentPosition<_this.snapGrid[i+1]) { + if(_this.positions.diff>0) newPosition = -_this.snapGrid[i+1] + else newPosition = -_this.snapGrid[i] + break; + } + } + if (-currentPosition >= _this.snapGrid[_this.snapGrid.length-1]) newPosition = -_this.snapGrid[_this.snapGrid.length-1]; + if (currentPosition <= -maxWrapperPosition()) newPosition = -maxWrapperPosition() + } + else { + newPosition = currentPosition<0 ? Math.round(currentPosition/groupSize)*groupSize : 0 + } + if (params.scrollContainer) { + newPosition = currentPosition<0 ? currentPosition : 0; + } + if (newPosition < -maxWrapperPosition()) { + newPosition = -maxWrapperPosition() + } + if (params.scrollContainer && (containerSize>slideSize)) { + newPosition = 0; + } + + if (newPosition == currentPosition) return false; + + swipeToPosition(newPosition, 'reset'); + return true; + } + _this.swipeTo = function(index, speed, runCallbacks){ + index = parseInt(index, 10); + _this.callPlugins('onSwipeTo', {index:index, speed:speed}); + if (params.loop) index = index + _this.loopedSlides; + var currentPosition = isH ? _this.getWrapperTranslate('x') : _this.getWrapperTranslate('y'); + if (index > (_this.slides.length-1)) return; + if (index<0) return; + var newPosition + if (params.slidesPerView=='auto') { + newPosition = -_this.slidesGrid[ index ]; + } + else { + newPosition = -index*slideSize; + } + if (newPosition < - maxWrapperPosition()) { + newPosition = - maxWrapperPosition(); + }; + + if (newPosition == currentPosition) return false; + + runCallbacks = runCallbacks===false ? false : true; + swipeToPosition(newPosition, 'to', {index:index, speed:speed, runCallbacks:runCallbacks}); + return true; + } + function swipeToPosition(newPosition, action, toOptions) { + if (_this.support.transitions || !params.DOMAnimation) { + if (isH) _this.setWrapperTranslate(newPosition,0,0); + else _this.setWrapperTranslate(0,newPosition,0); + var speed = (action=='to' && toOptions.speed>=0) ? toOptions.speed : params.speed; + _this.setWrapperTransition(speed); + } + else { + //Try the DOM animation + var currentPosition = isH ? _this.getWrapperTranslate('x') : _this.getWrapperTranslate('y'); + var speed = (action=='to' && toOptions.speed>=0) ? toOptions.speed : params.speed; + var animationStep = Math.ceil( (newPosition - currentPosition)/speed*(1000/60) ); + var direction = currentPosition > newPosition ? 'toNext' : 'toPrev'; + var condition = direction=='toNext' ? currentPosition > newPosition : currentPosition < newPosition; + if (_this._DOMAnimating) return; + + anim() + } + function anim(){ + currentPosition += animationStep; + condition = direction=='toNext' ? currentPosition > newPosition : currentPosition < newPosition; + if (condition) { + if (isH) _this.setWrapperTranslate(Math.round(currentPosition),0) + else _this.setWrapperTranslate(0,Math.round(currentPosition)) + _this._DOMAnimating = true + window.setTimeout(function(){ + anim() + }, 1000 / 60) + } + else { + if (params.onSlideChangeEnd) params.onSlideChangeEnd(_this) + if (isH) _this.setWrapperTranslate(newPosition,0); + else _this.setWrapperTranslate(0, newPosition); + _this._DOMAnimating = false; + } + } + + //Update Active Slide Index + _this.updateActiveSlide(newPosition); + + //Callbacks + if (params.onSlideNext && action=='next') { + params.onSlideNext(_this, newPosition) + } + if (params.onSlidePrev && action=='prev') { + params.onSlidePrev(_this, newPosition) + } + //"Reset" Callback + if (params.onSlideReset && action=='reset') { + params.onSlideReset(_this, newPosition) + } + + //"Next", "Prev" and "To" Callbacks + if (action=='next' || action=='prev' || (action=='to' && toOptions.runCallbacks==true)) + slideChangeCallbacks() + } + /*================================================== + Transition Callbacks + ====================================================*/ + //Prevent Multiple Callbacks + _this._queueStartCallbacks = false; + _this._queueEndCallbacks = false; + function slideChangeCallbacks() { + //Transition Start Callback + _this.callPlugins('onSlideChangeStart'); + if (params.onSlideChangeStart) { + if (params.queueStartCallbacks && _this.support.transitions) { + if (_this._queueStartCallbacks) return; + _this._queueStartCallbacks = true; + params.onSlideChangeStart(_this) + _this.wrapperTransitionEnd(function(){ + _this._queueStartCallbacks = false; + }) + } + else params.onSlideChangeStart(_this) + } + //Transition End Callback + if (params.onSlideChangeEnd) { + if (_this.support.transitions) { + if (params.queueEndCallbacks) { + if (_this._queueEndCallbacks) return; + _this._queueEndCallbacks = true; + _this.wrapperTransitionEnd(params.onSlideChangeEnd) + } + else _this.wrapperTransitionEnd(params.onSlideChangeEnd) + } + else { + if (!params.DOMAnimation) { + setTimeout(function(){ + params.onSlideChangeEnd(_this) + },10) + } + } + } + } + /*================================================== + Update Active Slide Index + ====================================================*/ + _this.updateActiveSlide = function(position) { + if (!_this.initialized) return; + if (_this.slides.length==0) return; + _this.previousIndex = _this.activeIndex; + if (position>0) position=0; + if (typeof position=='undefined') position = isH ? _this.getWrapperTranslate('x') : _this.getWrapperTranslate('y'); + + if (params.slidesPerView == 'auto') { + var slidesOffset = 0; + _this.activeIndex = _this.slidesGrid.indexOf(-position); + if (_this.activeIndex<0) { + for (var i=0; i<_this.slidesGrid.length-1; i++) { + if (-position>_this.slidesGrid[i] && -position<_this.slidesGrid[i+1]) { + break; + } + } + var leftDistance = Math.abs( _this.slidesGrid[i] + position ) + var rightDistance = Math.abs( _this.slidesGrid[i+1] + position ) + if (leftDistance<=rightDistance) _this.activeIndex = i; + else _this.activeIndex = i+1; + } + } + else { + if (params.visibilityFullFit) _this.activeIndex = Math.ceil( -position/slideSize ); + else _this.activeIndex = Math.round( -position/slideSize ); + } + if (_this.activeIndex== _this.slides.length ) _this.activeIndex = _this.slides.length-1; + if (_this.activeIndex<0) _this.activeIndex = 0; + // Check for slide + if (!_this.slides[_this.activeIndex]) return; + // Calc Visible slides + _this.calcVisibleSlides(position); + + // Mark visible and active slides with additonal classes + var activeClassRegexp = new RegExp( "\\s*" + params.slideActiveClass ); + var inViewClassRegexp = new RegExp( "\\s*" + params.slideVisibleClass ); + + for (var i = 0; i < _this.slides.length; i++) { + _this.slides[ i ].className = _this.slides[ i ].className.replace( activeClassRegexp, '' ).replace( inViewClassRegexp, '' ); + if ( _this.visibleSlides.indexOf( _this.slides[ i ] )>=0 ) { + _this.slides[ i ].className += ' ' + params.slideVisibleClass; + } + + } + _this.slides[ _this.activeIndex ].className += ' ' + params.slideActiveClass; + + //Update loop index + if (params.loop) { + var ls = _this.loopedSlides; + _this.activeLoopIndex = _this.activeIndex - ls; + if (_this.activeLoopIndex >= _this.slides.length - ls*2 ) { + _this.activeLoopIndex = _this.slides.length - ls*2 - _this.activeLoopIndex; + } + if (_this.activeLoopIndex<0) { + _this.activeLoopIndex = _this.slides.length - ls*2 + _this.activeLoopIndex; + } + } + else { + _this.activeLoopIndex = _this.activeIndex; + } + //Update Pagination + if (params.pagination) { + _this.updatePagination(position); + } + } + /*================================================== + Pagination + ====================================================*/ + _this.createPagination = function (firstInit) { + if (params.paginationClickable && _this.paginationButtons) { + removePaginationEvents(); + } + var paginationHTML = ""; + var numOfSlides = _this.slides.length; + var numOfButtons = numOfSlides; + if (params.loop) numOfButtons -= _this.loopedSlides*2 + for (var i = 0; i < numOfButtons; i++) { + paginationHTML += '<'+params.paginationElement+' class="'+params.paginationElementClass+'"></'+params.paginationElement+'>' + } + _this.paginationContainer = params.pagination.nodeType ? params.pagination : $$(params.pagination)[0]; + _this.paginationContainer.innerHTML = paginationHTML; + _this.paginationButtons = [] + if (document.querySelectorAll) + _this.paginationButtons = _this.paginationContainer.querySelectorAll('.'+params.paginationElementClass); + else if (window.jQuery) + _this.paginationButtons = $$(_this.paginationContainer).find('.'+params.paginationElementClass); + if (!firstInit) _this.updatePagination() + _this.callPlugins('onCreatePagination'); + if (params.paginationClickable) { + addPaginationEvents(); + } + } + function removePaginationEvents() { + var pagers = _this.paginationButtons; + for (var i=0; i<pagers.length; i++) { + _this.h.removeEventListener(pagers[i],'click', paginationClick, false) + } + } + function addPaginationEvents() { + var pagers = _this.paginationButtons; + for (var i=0; i<pagers.length; i++) { + _this.h.addEventListener(pagers[i],'click', paginationClick, false) + } + } + function paginationClick(e){ + var index; + var target = e.target || e.srcElement; + var pagers = _this.paginationButtons; + for (var i=0; i<pagers.length; i++) { + if (target===pagers[i]) index = i; + } + _this.swipeTo(index) + } + _this.updatePagination = function(position) { + if (!params.pagination) return; + if (_this.slides.length<1) return; + + if (document.querySelectorAll) + var activePagers = _this.paginationContainer.querySelectorAll('.'+params.paginationActiveClass) + else if (window.jQuery) + var activePagers = $$(_this.paginationContainer).find('.'+params.paginationActiveClass); + if(!activePagers) return; + + //Reset all Buttons' class to not active + var pagers = _this.paginationButtons; + if (pagers.length==0) return; + for (var i=0; i < pagers.length; i++) { + pagers[i].className = params.paginationElementClass + } + + var indexOffset = params.loop ? _this.loopedSlides : 0; + if (params.paginationAsRange) { + if (!_this.visibleSlides) _this.calcVisibleSlides(position) + //Get Visible Indexes + var visibleIndexes = []; + for (var i = 0; i < _this.visibleSlides.length; i++) { + var visIndex = _this.slides.indexOf( _this.visibleSlides[i] ) - indexOffset + + if (params.loop && visIndex<0) { + visIndex = _this.slides.length - _this.loopedSlides*2 + visIndex; + } + if (params.loop && visIndex>=_this.slides.length-_this.loopedSlides*2) { + visIndex = _this.slides.length - _this.loopedSlides*2 - visIndex; + visIndex = Math.abs(visIndex) + } + visibleIndexes.push( visIndex ) + } + + for (i=0; i<visibleIndexes.length; i++) { + if (pagers[ visibleIndexes[i] ]) pagers[ visibleIndexes[i] ].className += ' ' + params.paginationVisibleClass; + } + + if (params.loop) { + pagers[ _this.activeLoopIndex ].className += ' ' + params.paginationActiveClass; + } + else { + pagers[ _this.activeIndex ].className += ' ' + params.paginationActiveClass; + } + + } + else { + if (params.loop) { + pagers[ _this.activeLoopIndex ].className+=' '+params.paginationActiveClass+' '+params.paginationVisibleClass; + } + else { + pagers[ _this.activeIndex ].className+=' '+params.paginationActiveClass+' '+params.paginationVisibleClass; + } + + } + + } + _this.calcVisibleSlides = function(position){ + var visibleSlides = []; + var _slideLeft = 0, _slideSize = 0, _slideRight = 0; + if (isH && _this.wrapperLeft>0) position = position+_this.wrapperLeft; + if (!isH && _this.wrapperTop>0) position = position+_this.wrapperTop; + + for (var i=0; i<_this.slides.length; i++) { + _slideLeft += _slideSize; + if (params.slidesPerView == 'auto') + _slideSize = isH ? _this.h.getWidth(_this.slides[i],true) : _this.h.getHeight(_this.slides[i],true); + else _slideSize = slideSize; + + _slideRight = _slideLeft + _slideSize; + var isVisibile = false; + if (params.visibilityFullFit) { + if (_slideLeft >= -position && _slideRight <= -position+containerSize) isVisibile = true; + if (_slideLeft <= -position && _slideRight >= -position+containerSize) isVisibile = true; + } + else { + + if (_slideRight > -position && _slideRight <= ((-position+containerSize))) isVisibile = true; + if (_slideLeft >= -position && _slideLeft < ((-position+containerSize))) isVisibile = true; + if (_slideLeft < -position && _slideRight > ((-position+containerSize))) isVisibile = true; + } + + if (isVisibile) visibleSlides.push(_this.slides[i]) + + } + if (visibleSlides.length==0) visibleSlides = [ _this.slides[ _this.activeIndex ] ] + + _this.visibleSlides = visibleSlides; + } + + /*========================================== + Autoplay + ============================================*/ + _this.autoPlayIntervalId = undefined; + _this.startAutoplay = function () { + if (typeof _this.autoPlayIntervalId !== 'undefined') return false; + if (params.autoplay && !params.loop) { + _this.autoPlayIntervalId = setInterval(function(){ + if (!_this.swipeNext(true)) _this.swipeTo(0); + }, params.autoplay) + } + if (params.autoplay && params.loop) { + _this.autoPlayIntervalId = setInterval(function(){ + _this.swipeNext(); + }, params.autoplay) + } + _this.callPlugins('onAutoplayStart'); + } + _this.stopAutoplay = function () { + if (_this.autoPlayIntervalId) clearInterval(_this.autoPlayIntervalId); + _this.autoPlayIntervalId = undefined; + _this.callPlugins('onAutoplayStop'); + } + /*================================================== + Loop + ====================================================*/ + _this.loopCreated = false; + _this.removeLoopedSlides = function(){ + if (_this.loopCreated) { + for (var i=0; i<_this.slides.length; i++) { + if (_this.slides[i].getData('looped')===true) _this.wrapper.removeChild(_this.slides[i]); + } + } + } + _this.createLoop = function(){ + if (_this.slides.length==0) return; + _this.loopedSlides = params.slidesPerView+params.loopAdditionalSlides; + + var slideFirstHTML = ''; + var slideLastHTML = ''; + + //Grab First Slides + for (var i=0; i<_this.loopedSlides; i++) { + slideFirstHTML+=_this.slides[i].outerHTML + } + //Grab Last Slides + for (i=_this.slides.length-_this.loopedSlides; i<_this.slides.length; i++) { + slideLastHTML+=_this.slides[i].outerHTML + } + wrapper.innerHTML = slideLastHTML + wrapper.innerHTML + slideFirstHTML; + + _this.loopCreated = true; + _this.calcSlides(); + + //Update Looped Slides with special class + for (i=0; i<_this.slides.length; i++) { + if (i<_this.loopedSlides || i>=_this.slides.length-_this.loopedSlides) _this.slides[i].setData('looped', true); + } + _this.callPlugins('onCreateLoop'); + + } + _this.fixLoop = function(){ + //Fix For Negative Oversliding + if (_this.activeIndex < _this.loopedSlides) { + var newIndex = _this.slides.length - _this.loopedSlides*3 + _this.activeIndex; + _this.swipeTo(newIndex, 0, false) + } + //Fix For Positive Oversliding + else if (_this.activeIndex > _this.slides.length - params.slidesPerView*2) { + var newIndex = -_this.slides.length + _this.activeIndex + _this.loopedSlides + _this.swipeTo(newIndex,0, false) + } + } + /*================================================== + Slides Loader + ====================================================*/ + _this.loadSlides = function(){ + var slidesHTML = ''; + _this.activeLoaderIndex = 0; + var slides = params.loader.slides; + var slidesToLoad = params.loader.loadAllSlides ? slides.length : params.slidesPerView*(1+params.loader.surroundGroups); + for (var i=0; i< slidesToLoad; i++) { + if (params.loader.slidesHTMLType=='outer') slidesHTML+=slides[i]; + else { + slidesHTML+='<'+params.slideElement+' class="'+params.slideClass+'" data-swiperindex="'+i+'">'+slides[i]+'</'+params.slideElement+'>'; + } + } + _this.wrapper.innerHTML = slidesHTML; + _this.calcSlides(true); + //Add permanent transitionEnd callback + if (!params.loader.loadAllSlides) { + _this.wrapperTransitionEnd(_this.reloadSlides, true); + } + } + _this.reloadSlides = function(){ + var slides = params.loader.slides; + var newActiveIndex = parseInt(_this.activeSlide().data('swiperindex'),10) + if (newActiveIndex<0 || newActiveIndex>slides.length-1) return //<-- Exit + _this.activeLoaderIndex = newActiveIndex; + var firstIndex = Math.max(0, newActiveIndex - params.slidesPerView*params.loader.surroundGroups) + var lastIndex = Math.min(newActiveIndex+params.slidesPerView*(1+params.loader.surroundGroups)-1, slides.length-1) + //Update Transforms + if (newActiveIndex>0) { + var newTransform = -slideSize*(newActiveIndex-firstIndex) + if (isH) _this.setWrapperTranslate(newTransform,0,0) + else _this.setWrapperTranslate(0,newTransform,0) + _this.setWrapperTransition(0) + } + //New Slides + if (params.loader.logic==='reload') { + _this.wrapper.innerHTML = ''; + var slidesHTML = ''; + for (var i = firstIndex; i<=lastIndex; i++) { + slidesHTML += params.loader.slidesHTMLType == 'outer' ? slides[i] : '<'+params.slideElement+' class="'+params.slideClass+'" data-swiperindex="'+i+'">'+slides[i]+'</'+params.slideElement+'>'; + } + _this.wrapper.innerHTML = slidesHTML; + } + else { + var minExistIndex=1000; + var maxExistIndex=0; + for (var i=0; i<_this.slides.length; i++) { + var index = _this.slides[i].data('swiperindex'); + if (index<firstIndex || index>lastIndex) { + _this.wrapper.removeChild(_this.slides[i]); + } + else { + minExistIndex = Math.min(index, minExistIndex) + maxExistIndex = Math.max(index, maxExistIndex) + } + } + for (var i=firstIndex; i<=lastIndex; i++) { + if (i<minExistIndex) { + var newSlide = document.createElement(params.slideElement); + newSlide.className = params.slideClass; + newSlide.setAttribute('data-swiperindex',i); + newSlide.innerHTML = slides[i]; + _this.wrapper.insertBefore(newSlide, _this.wrapper.firstChild); + } + if (i>maxExistIndex) { + var newSlide = document.createElement(params.slideElement); + newSlide.className = params.slideClass; + newSlide.setAttribute('data-swiperindex',i); + newSlide.innerHTML = slides[i]; + _this.wrapper.appendChild(newSlide); + } + } + } + //reInit + _this.reInit(true); + } + /*================================================== + Make Swiper + ====================================================*/ + function makeSwiper(){ + _this.calcSlides(); + if (params.loader.slides.length>0 && _this.slides.length==0) { + _this.loadSlides(); + } + if (params.loop) { + _this.createLoop(); + } + _this.init(); + initEvents(); + if (params.pagination && params.createPagination) { + _this.createPagination(true); + } + if (params.loop || params.initialSlide>0) { + _this.swipeTo( params.initialSlide, 0, false ); + } + else { + _this.updateActiveSlide(0); + } + if (params.autoplay) { + _this.startAutoplay(); + } + + } + makeSwiper(); +} + +Swiper.prototype = { + plugins : {}, + /*================================================== + Wrapper Operations + ====================================================*/ + wrapperTransitionEnd : function(callback, permanent) { + var a = this + var el = a.wrapper + var events = ['webkitTransitionEnd','transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd']; + function fireCallBack() { + callback(a) + if (a.params.queueEndCallbacks) a._queueEndCallbacks = false + if (!permanent) { + for (var i=0; i<events.length; i++) { + a.h.removeEventListener(el,events[i], fireCallBack, false) + } + } + } + if (callback) { + for (var i=0; i<events.length; i++) { + a.h.addEventListener(el,events[i], fireCallBack, false) + } + } + }, + + getWrapperTranslate : function(axis){ + var el = this.wrapper + var matrix; + var curTransform; + if (window.WebKitCSSMatrix) { + var transformMatrix = new WebKitCSSMatrix(window.getComputedStyle(el, null).webkitTransform) + matrix = transformMatrix.toString().split(','); + } + else { + var transformMatrix = window.getComputedStyle(el, null).MozTransform || window.getComputedStyle(el, null).OTransform || window.getComputedStyle(el, null).MsTransform || window.getComputedStyle(el, null).msTransform || window.getComputedStyle(el, null).transform|| window.getComputedStyle(el, null).getPropertyValue("transform").replace("translate(", "matrix(1, 0, 0, 1,"); + matrix = transformMatrix.toString().split(','); + + } + if (this.params.useCSS3Transforms) { + if (axis=='x') { + //Crazy IE10 Matrix + if (matrix.length==16) + curTransform = parseFloat( matrix[12] ) + //Latest Chrome and webkits Fix + else if (window.WebKitCSSMatrix) + curTransform = transformMatrix.m41 + //Normal Browsers + else + curTransform = parseFloat( matrix[4] ) + } + if (axis=='y') { + //Crazy IE10 Matrix + if (matrix.length==16) + curTransform = parseFloat( matrix[13] ) + //Latest Chrome and webkits Fix + else if (window.WebKitCSSMatrix) + curTransform = transformMatrix.m42 + //Normal Browsers + else + curTransform = parseFloat( matrix[5] ) + } + } + else { + if (axis=='x') curTransform = parseFloat(el.style.left,10) || 0 + if (axis=='y') curTransform = parseFloat(el.style.top,10) || 0 + } + return curTransform || 0; + }, + + setWrapperTranslate : function(x,y,z) { + var es = this.wrapper.style + x=x||0; + y=y||0; + z=z||0; + if (this.params.useCSS3Transforms) { + if (this.support.transforms3d) { + es.webkitTransform = es.MsTransform = es.msTransform = es.MozTransform = es.OTransform = es.transform = 'translate3d('+x+'px, '+y+'px, '+z+'px)' + } + else { + + es.webkitTransform = es.MsTransform = es.msTransform = es.MozTransform = es.OTransform = es.transform = 'translate('+x+'px, '+y+'px)' + if (!this.support.transforms) { + es.left = x+'px' + es.top = y+'px' + } + } + } + else { + es.left = x+'px'; + es.top = y+'px'; + } + this.callPlugins('onSetWrapperTransform', {x:x, y:y, z:z}) + }, + + setWrapperTransition : function(duration) { + var es = this.wrapper.style + es.webkitTransitionDuration = es.MsTransitionDuration = es.msTransitionDuration = es.MozTransitionDuration = es.OTransitionDuration = es.transitionDuration = duration/1000+'s'; + this.callPlugins('onSetWrapperTransition', {duration: duration}) + }, + + /*================================================== + Helpers + ====================================================*/ + h : { + getWidth: function (el, outer) { + var width = window.getComputedStyle(el, null).getPropertyValue('width') + var returnWidth = parseFloat(width); + //IE Fixes + if(isNaN(returnWidth) || width.indexOf('%')>0) { + returnWidth = el.offsetWidth - parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-left')) - parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-right')); + } + if (outer) returnWidth += parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-left')) + parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-right')) + + return returnWidth; + }, + getHeight: function(el, outer) { + if (outer) return el.offsetHeight; + + var height = window.getComputedStyle(el, null).getPropertyValue('height') + var returnHeight = parseFloat(height); + //IE Fixes + if(isNaN(returnHeight) || height.indexOf('%')>0) { + returnHeight = el.offsetHeight - parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-top')) - parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-bottom')); + } + if (outer) returnHeight += parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-top')) + parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-bottom')) + return returnHeight; + }, + getOffset: function(el) { + var box = el.getBoundingClientRect(); + var body = document.body; + var clientTop = el.clientTop || body.clientTop || 0; + var clientLeft = el.clientLeft || body.clientLeft || 0; + var scrollTop = window.pageYOffset || el.scrollTop; + var scrollLeft = window.pageXOffset || el.scrollLeft; + if (document.documentElement && !window.pageYOffset) { + //IE7-8 + scrollTop = document.documentElement.scrollTop; + scrollLeft = document.documentElement.scrollLeft; + } + return { + top: box.top + scrollTop - clientTop, + left: box.left + scrollLeft - clientLeft + }; + }, + windowWidth : function() { + if (window.innerWidth) return window.innerWidth + else if (document.documentElement && document.documentElement.clientWidth) return document.documentElement.clientWidth; + }, + windowHeight : function() { + if (window.innerHeight) return window.innerHeight + else if (document.documentElement && document.documentElement.clientHeight) return document.documentElement.clientHeight; + }, + windowScroll : function() { + var left=0, top=0; + if (typeof pageYOffset != 'undefined') { + return { + left: window.pageXOffset, + top: window.pageYOffset + } + } + else if (document.documentElement) { + return { + left: document.documentElement.scrollLeft, + top: document.documentElement.scrollTop + } + } + }, + + addEventListener : function (el, event, listener, useCapture) { + if (el.addEventListener) { + el.addEventListener(event, listener, useCapture) + } + else if (el.attachEvent) { + el.attachEvent('on'+event, listener) + } + }, + removeEventListener : function (el, event, listener, useCapture) { + if (el.removeEventListener) { + el.removeEventListener(event, listener, useCapture) + } + else if (el.detachEvent) { + el.detachEvent('on'+event, listener) + } + } + }, + setTransform : function (el, transform) { + var es = el.style + es.webkitTransform = es.MsTransform = es.msTransform = es.MozTransform = es.OTransform = es.transform = transform + }, + setTranslate : function (el, translate) { + var es = el.style + var pos = { + x : translate.x || 0, + y : translate.y || 0, + z : translate.z || 0 + }; + var transformString = this.support.transforms3d ? 'translate3d('+(pos.x)+'px,'+(pos.y)+'px,'+(pos.z)+'px)' : 'translate('+(pos.x)+'px,'+(pos.y)+'px)'; + es.webkitTransform = es.MsTransform = es.msTransform = es.MozTransform = es.OTransform = es.transform = transformString; + if (!this.support.transforms) { + es.left = pos.x+'px' + es.top = pos.y+'px' + } + }, + setTransition : function (el, duration) { + var es = el.style + es.webkitTransitionDuration = es.MsTransitionDuration = es.msTransitionDuration = es.MozTransitionDuration = es.OTransitionDuration = es.transitionDuration = duration+'ms'; + }, + /*================================================== + Feature Detection + ====================================================*/ + support: { + + touch : (window.Modernizr && Modernizr.touch===true) || (function() { + return !!(("ontouchstart" in window) || window.DocumentTouch && document instanceof DocumentTouch); + })(), + + transforms3d : (window.Modernizr && Modernizr.csstransforms3d===true) || (function() { + var div = document.createElement('div'); + return ( "webkitPerspective" in div.style || "MozPerspective" in div.style || "OPerspective" in div.style || "MsPerspective" in div.style || "perspective" in div.style ); + })(), + + transforms : (window.Modernizr && Modernizr.csstransforms===true) || (function(){ + var div = document.createElement('div').style + return ('transform' in div) || ('WebkitTransform' in div) || ('MozTransform' in div) || ('msTransform' in div) || ('MsTransform' in div) || ('OTransform' in div); + })(), + + transitions : (window.Modernizr && Modernizr.csstransitions===true) || (function(){ + var div = document.createElement('div').style + return ('transition' in div) || ('WebkitTransition' in div) || ('MozTransition' in div) || ('msTransition' in div) || ('MsTransition' in div) || ('OTransition' in div); + })() + }, + + browser : { + + ie8 : (function(){ + var rv = -1; // Return value assumes failure. + if (navigator.appName == 'Microsoft Internet Explorer') { + var ua = navigator.userAgent; + var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})"); + if (re.exec(ua) != null) + rv = parseFloat(RegExp.$1); + } + return rv != -1 && rv < 9; + })(), + + ie10 : window.navigator.msPointerEnabled + } +} + +/*========================= + jQuery & Zepto Plugins + ===========================*/ +if (window.jQuery||window.Zepto) { + (function($){ + $.fn.swiper = function(params) { + var s = new Swiper($(this)[0], params) + $(this).data('swiper',s); + return s + } + })(window.jQuery||window.Zepto) +} + +// component +if ( typeof( module ) !== 'undefined' ) +{ + module.exports = Swiper; +} +// Generated by CoffeeScript 1.6.3 +(function($, window) { + "use strict"; + var Nav; + Nav = (function() { + function Nav(el, options) { + this.options = $.extend({}, options); + this.$el = $(el); + } + + Nav.prototype.slide = function() { + return this.$el.next('ul').slideToggle(); + }; + + return Nav; + + })(); + $.fn.nav = function(option) { + return this.each(function() { + var $this, data; + $this = $(this); + data = $this.data('Nav'); + if (!data) { + $this.data('Nav', (data = new Nav(this, {}))); + } + if (typeof option === 'string') { + return data[option](); + } + }); + }; + return $(document).on('click', '[data-toggle="nav"]', function(e) { + $(this).nav('slide'); + return e.preventDefault(); + }); +})(window.jQuery, window); +// Generated by CoffeeScript 1.6.3 +jQuery(function() { + var swiper; + $('.close').each(function() { + return $(this).click(function(e) { + e.preventDefault(); + return $(this).parent().fadeOut(); + }); + }); + $("[data-toggle=tooltip]").tooltip(); + $("[data-datepicker]").each(function() { + var input; + input = $(this); + return input.pickadate({ + selectYears: input.data('select-years') || false, + selectMonths: input.data('select-months') || false + }); + }); + swiper = new Swiper('.swiper-container', { + pagination: '.swiper-pagination', + mode: 'horizontal', + loop: true, + calculateHeight: true, + grabCursor: true, + paginationClickable: true, + speed: 600 + }); + $('.swiper-control.left').on('click', function(e) { + e.preventDefault(); + return swiper.swipePrev(); + }); + return $('.swiper-control.right').on('click', function(e) { + e.preventDefault(); + return swiper.swipeNext(); + }); +});