/* ==|== Responsive =============================================================
Author: James South
twitter : http://twitter.com/James_M_South
github : https://github.com/ResponsiveBP/Responsive
Copyright (c), James South.
Licensed under the MIT License.
============================================================================== */
/*! Responsive v4.0.2 | MIT License | responsivebp.com */
/*
* Responsive Core
*/
/*global jQuery*/
/*jshint forin:false, expr:true*/
(function ($, w, d) {
"use strict";
$.pseudoUnique = function (length) {
/// Returns a pseudo unique alpha-numeric string of the given length.
/// The length of the string to return. Defaults to 8.
/// The pseudo unique alpha-numeric string.
var len = length || 8,
text = "",
possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
max = possible.length;
if (len > max) {
len = max;
}
for (var i = 0; i < len; i += 1) {
text += possible.charAt(Math.floor(Math.random() * max));
}
return text;
};
$.support.rtl = (function () {
/// Returns a value indicating whether the current page is setup for right-to-left languages.
///
/// True if right-to-left language support is set up; otherwise false.
///
return $("html[dir=rtl]").length ? true : false;
}());
$.support.currentGrid = (function () {
/// Returns a value indicating what grid range the current browser width is within.
///
/// An object containing two properties.
///
1: grid - The current applied grid; either xxs, xs, s, m, or l.
///
2: index - The index of the current grid in the range.
///
3: range - The available grid range.
///
var $div = $("
").addClass("grid-state-indicator").prependTo("body");
return function () {
// These numbers match values in the css
var grids = ["xxs", "xs", "s", "m", "l"],
key = parseInt($div.width(), 10);
return {
grid: grids[key],
index: key,
range: grids
};
};
}());
$.support.transition = (function () {
/// Returns a value indicating whether the browser supports CSS transitions.
/// True if the current browser supports css transitions.
var transitionEnd = function () {
/// Gets transition end event for the current browser.
/// The transition end event for the current browser.
var div = d.createElement("div"),
transEndEventNames = {
"transition": "transitionend",
"WebkitTransition": "webkitTransitionEnd",
"MozTransition": "transitionend",
"OTransition": "oTransitionEnd otransitionend"
};
// Could use the other method but I'm intentionally keeping them
// separate for now.
for (var name in transEndEventNames) {
if (div.style[name] !== undefined) {
return { end: transEndEventNames[name] };
}
}
return false;
};
return transitionEnd();
}());
$.fn.redraw = function () {
/// Forces the browser to redraw by measuring the given target.
/// The jQuery object for chaining.
var redraw;
return this.each(function () {
redraw = this.offsetWidth;
});
};
$.fn.ensureTransitionEnd = function (duration) {
///
/// Ensures that the transition end callback is triggered.
/// http://blog.alexmaccaw.com/css-transitions
///
if (!$.support.transition) {
return this;
}
var rtransition = /\d+(.\d+)/,
called = false,
$this = $(this),
callback = function () { if (!called) { $this.trigger($.support.transition.end); } };
if (!duration) {
duration = (rtransition.test($this.css("transition-duration")) ? $this.css("transition-duration").match(rtransition)[0] : 0) * 1000;
}
$this.one($.support.transition.end, function () { called = true; });
w.setTimeout(callback, duration);
return this;
};
$.fn.onTransitionEnd = function (callback) {
/// Performs the given callback at the end of a css transition.
/// The function to call on transition end.
/// The jQuery object for chaining.
var supportTransition = $.support.transition;
return this.each(function () {
if (!$.isFunction(callback)) {
return;
}
var $this = $(this).redraw();
supportTransition ? $this.one(supportTransition.end, callback) : callback();
});
};
$.support.touchEvents = (function () {
return ("ontouchstart" in w) || (w.DocumentTouch && d instanceof w.DocumentTouch);
}());
$.support.pointerEvents = (function () {
return (w.PointerEvent || w.MSPointerEvent);
}());
(function () {
var supportTouch = $.support.touchEvents,
supportPointer = $.support.pointerEvents;
var pointerStart = ["pointerdown", "MSPointerDown"],
pointerMove = ["pointermove", "MSPointerMove"],
pointerEnd = ["pointerup", "pointerout", "pointercancel", "pointerleave",
"MSPointerUp", "MSPointerOut", "MSPointerCancel", "MSPointerLeave"];
var touchStart = "touchstart",
touchMove = "touchmove",
touchEnd = ["touchend", "touchleave", "touchcancel"];
var mouseStart = "mousedown",
mouseMove = "mousemove",
mouseEnd = ["mouseup", "mouseleave"];
var getEvents = function (ns) {
var estart,
emove,
eend;
// Keep the events separate since support could be crazy.
if (supportTouch) {
estart = touchStart + ns;
emove = touchMove + ns;
eend = (touchEnd.join(ns + " ")) + ns;
}
else if (supportPointer) {
estart = (pointerStart.join(ns + " ")) + ns;
emove = (pointerMove.join(ns + " ")) + ns;
eend = (pointerEnd.join(ns + " ")) + ns;
} else {
estart = mouseStart + ns;
emove = mouseMove + ns;
eend = (mouseEnd.join(ns + " ")) + ns;
}
return {
start: estart,
move: emove,
end: eend
};
};
var addSwipe = function ($elem, handler) {
/// Adds swiping functionality to the given element.
///
/// The jQuery object representing the given node(s).
///
/// The jQuery object for chaining.
var ns = handler.namespace ? "." + handler.namespace : "",
eswipestart = "swipestart",
eswipemove = "swipemove",
eswipeend = "swipeend",
etouch = getEvents(ns);
// Set the touchAction variable for move.
var touchAction = handler.data && handler.data.touchAction || "none",
sensitivity = handler.data && handler.data.sensitivity || 5;
if (supportPointer) {
// Enable extended touch events on supported browsers before any touch events.
$elem.css({ "-ms-touch-action": "" + touchAction + "", "touch-action": "" + touchAction + "" });
}
return $elem.each(function () {
var $this = $(this);
var start = {},
delta = {},
onMove = function (event) {
// Normalize the variables.
var isMouse = event.type === "mousemove",
isPointer = event.type !== "touchmove" && !isMouse,
original = event.originalEvent,
moveEvent;
// Only left click allowed.
if (isMouse && event.which !== 1) {
return;
}
// One touch allowed.
if (original.touches && original.touches.length > 1) {
return;
}
// Ensure swiping with one touch and not pinching.
if (event.scale && event.scale !== 1) {
return;
}
var dx = (isMouse ? original.pageX : isPointer ? original.clientX : original.touches[0].pageX) - start.x,
dy = (isMouse ? original.pageY : isPointer ? original.clientY : original.touches[0].pageY) - start.y;
var doSwipe,
percentX = Math.abs(parseFloat((dx / $this.width()) * 100)) || 100,
percentY = Math.abs(parseFloat((dy / $this.height()) * 100)) || 100;
// Work out whether to do a scroll based on the sensitivity limit.
switch (touchAction) {
case "pan-x":
if (Math.abs(dy) > Math.abs(dx)) {
event.preventDefault();
}
doSwipe = Math.abs(dy) > Math.abs(dx) && Math.abs(dy) > sensitivity && percentY < 100;
break;
case "pan-y":
if (Math.abs(dx) > Math.abs(dy)) {
event.preventDefault();
}
doSwipe = Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > sensitivity && percentX < 100;
break;
default:
event.preventDefault();
doSwipe = Math.abs(dy) > sensitivity || Math.abs(dx) > sensitivity && percentX < 100 && percentY < 100;
break;
}
event.stopPropagation();
if (!doSwipe) {
return;
}
moveEvent = $.Event(eswipemove, { delta: { x: dx, y: dy } });
$this.trigger(moveEvent);
if (moveEvent.isDefaultPrevented()) {
return;
}
// Measure change in x and y.
delta = {
x: dx,
y: dy
};
},
onEnd = function () {
// Measure duration
var duration = +new Date() - start.time,
endEvent;
// Determine if slide attempt triggers slide.
if (Math.abs(delta.x) > 1 || Math.abs(delta.y) > 1) {
// Set the direction and return it.
var horizontal = delta.x < 0 ? "left" : "right",
vertical = delta.y < 0 ? "up" : "down",
direction = Math.abs(delta.x) > Math.abs(delta.y) ? horizontal : vertical;
endEvent = $.Event(eswipeend, { delta: delta, direction: direction, duration: duration });
$this.trigger(endEvent);
}
// Disable the touch events till next time.
$this.off(etouch.move).off(etouch.end);
};
$this.off(etouch.start).on(etouch.start, function (event) {
// Normalize the variables.
var isMouse = event.type === "mousedown",
isPointer = event.type !== "touchstart" && !isMouse,
original = event.originalEvent;
if ((isPointer || isMouse) && $(event.target).is("img")) {
event.preventDefault();
}
event.stopPropagation();
// Measure start values.
start = {
// Get initial touch coordinates.
x: isMouse ? original.pageX : isPointer ? original.clientX : original.touches[0].pageX,
y: isMouse ? original.pageY : isPointer ? original.clientY : original.touches[0].pageY,
// Store time to determine touch duration.
time: +new Date()
};
var startEvent = $.Event(eswipestart, { start: start });
$this.trigger(startEvent);
if (startEvent.isDefaultPrevented()) {
return;
}
// Reset delta and end measurements.
delta = { x: 0, y: 0 };
// Attach touchmove and touchend listeners.
$this.on(etouch.move, onMove)
.on(etouch.end, onEnd);
});
});
};
var removeSwipe = function ($elem, handler) {
/// Removes swiping functionality from the given element.
var ns = handler.namespace ? "." + handler.namespace : "",
etouch = getEvents(ns);
return $elem.each(function () {
// Disable extended touch events on ie.
// Unbind events.
$(this).css({ "-ms-touch-action": "", "touch-action": "" })
.off(etouch.start).off(etouch.move).off(etouch.end);
});
};
// Create special events so we can use on/off.
$.event.special.swipe = {
add: function (handler) {
addSwipe($(this), handler);
},
remove: function (handler) {
removeSwipe($(this), handler);
}
};
}());
$.extend($.expr[":"], {
attrStart: function (el, i, props) {
/// Custom selector extension to allow attribute starts with selection.
/// The element to test against.
/// The index of the element in the stack.
/// Metadata for the element.
/// True if the element is a match; otherwise, false.
var hasAttribute = false;
$.each(el.attributes, function () {
if (this.name.indexOf(props[3]) === 0) {
hasAttribute = true;
return false; // Exit the iteration.
}
return true;
});
return hasAttribute;
}
});
$.getDataOptions = function ($elem, filter) {
/// Creates an object containing options populated from an elements data attributes.
/// The object representing the DOM element.
/// The prefix with filter to identify the data attribute.
/// The extended object.
var options = {};
$.each($elem.data(), function (key, val) {
if (key.indexOf(filter) === 0 && key.length > filter.length) {
// Build a key with the correct format.
var length = filter.length,
newKey = key.charAt(length).toLowerCase() + key.substring(length + 1);
options[newKey] = val;
}
});
return Object.keys(options).length ? options : $elem.data();
};
$.debounce = function (func, wait, immediate) {
///
/// Returns a function, that, as long as it continues to be invoked, will not
/// be triggered. The function will be called after it stops being called for
/// N milliseconds. If `immediate` is passed, trigger the function on the
/// leading edge, instead of the trailing.
///
///
/// The function to debounce.
///
///
/// The number of milliseconds to delay.
///
///
/// Specify execution on the leading edge of the timeout.
///
/// The function.
var timeout;
return function () {
var context = this, args = arguments;
w.clearTimeout(timeout);
timeout = w.setTimeout(function () {
timeout = null;
if (!immediate) { func.apply(context, args); }
}, wait);
if (immediate && !timeout) { func.apply(context, args); }
};
};
(function (old) {
/// Override the core html method in the jQuery object to fire a domchanged event whenever it is called.
///
/// The jQuery function being overridden.
///
/// The jQuery object for chaining.
var echanged = $.Event("domchanged"),
$d = $(d);
$.fn.html = function () {
// Execute the original html() method using the augmented arguments collection.
var result = old.apply(this, arguments);
if (arguments.length) {
$d.trigger(echanged);
}
return result;
};
})($.fn.html);
}(jQuery, window, document));
/*
* Responsive AutoSize
*/
/*global jQuery*/
/*jshint expr:true*/
(function ($, w, ns, da) {
"use strict";
if (w.RESPONSIVE_AUTOSIZE) {
return;
}
// General variables and methods.
var eready = "ready" + ns + da,
echanged = ["domchanged" + ns + da, "shown.r.modal" + da].join(" "),
eresize = ["resize" + ns, "orientationchange" + ns].join(" "),
einput = "input",
ekeyup = "keyup",
esize = "size" + ns,
esized = "sized" + ns;
(function (oldVal) {
/// Override the core val method in the jQuery object to fire an input event on autosize plugins whenever it is called.
///
/// The jQuery function being overridden.
///
/// The jQuery object for chaining.
$.fn.val = function () {
// Execute the original val() method using the augmented arguments collection.
var result = oldVal.apply(this, arguments);
if (this.data("r.autosize") && arguments.length) {
this.trigger($.Event(einput));
}
return result;
};
})($.fn.val);
// AutoSize class definition
var AutoSize = function (element, options) {
this.$element = $(element);
this.element = element,
this.options = $.extend({}, this.defaults, options);
this.sizing = null;
this.difference = 0;
this.height = this.$element.height();
// Initial setup.
this.init();
// Bind events. Keyup is required for IE9.
this.$element.on([einput, ekeyup].join(" "), $.debounce($.proxy(this.size, this), 100));
$(w).on(eresize, $.debounce($.proxy(this.size, this), 100));
};
AutoSize.prototype.init = function () {
var height = this.$element.outerHeight();
this.difference = parseFloat(this.$element.css("paddingBottom")) +
parseFloat(this.$element.css("paddingTop"));
// Firefox: scrollHeight isn't full height on border-box
if (this.element.scrollHeight + this.difference <= height) {
this.difference = 0;
}
// Only set the height if textarea has value.
if (this.element.value.replace(/\s/g, "").length > 0) {
this.$element.height(this.element.scrollHeight);
}
};
AutoSize.prototype.size = function () {
var self = this,
$element = this.$element,
element = this.element,
sizeEvent = $.Event(esize);
if (this.sizing) {
return;
}
// Check and get the height
$element.height("auto");
var scrollHeight = element.scrollHeight - this.difference,
different = this.height !== scrollHeight;
$element.height(this.height);
// Trigger events if need be.
if (different) {
$element.trigger(sizeEvent);
}
if (this.sizing || sizeEvent.isDefaultPrevented()) {
return;
}
this.sizing = true;
$element.height(scrollHeight);
if (different) {
// Do our callback
$element.onTransitionEnd(function() {
self.sizing = false;
self.height = scrollHeight;
$element.trigger($.Event(esized));
});
return;
}
this.sizing = false;
};
// No conflict.
var old = $.fn.autoSize;
// Plug-in definition
$.fn.autoSize = function (options) {
return this.each(function () {
var $this = $(this),
data = $this.data("r.autosize"),
opts = typeof options === "object" ? options : null;
if (!data) {
// Check the data and reassign if not present.
$this.data("r.autosize", (data = new AutoSize(this, opts)));
}
if (options === "size") {
data.size();
}
});
};
// Set the public constructor.
$.fn.autoSize.Constructor = AutoSize;
$.fn.autoSize.noConflict = function () {
$.fn.autoSize = old;
return this;
};
// Data API
var init = function () {
$("textarea[data-autosize]").each(function () {
var $this = $(this),
loaded = $this.data("r.autosizeLoaded");
if (!loaded) {
$this.data("r.autosizeLoaded", true);
$this.addClass("autosize").autoSize($.getDataOptions($this, "autosize"));
}
});
},
debouncedInit = $.debounce(init, 500);
$(document).on([eready, echanged].join(" "), function (event) {
event.type === "ready" ? init() : debouncedInit();
});
w.RESPONSIVE_AUTOSIZE = true;
}(jQuery, window, ".r.autosize", ".data-api"));
/*
* Responsive Carousel
*/
/*global jQuery*/
/*jshint expr:true*/
(function ($, w, ns, da) {
"use strict";
if (w.RESPONSIVE_CAROUSEL) {
return;
}
// General variables.
var supportTransition = $.support.transition,
rtl = $.support.rtl,
emouseenter = "mouseenter",
emouseleave = "mouseleave",
ekeydown = "keydown",
eclick = "click",
eready = "ready" + ns + da,
echanged = ["domchanged" + ns + da, "shown.r.modal" + da].join(" "),
eslide = "slide" + ns,
eslid = "slid" + ns;
var keys = {
SPACE: 32,
ENTER: 13,
LEFT: 37,
RIGHT: 39
};
// Carousel class definition
var Carousel = function (element, options) {
this.$element = $(element);
this.defaults = {
interval: 0, // Better for a11y
mode: "slide",
pause: "hover",
wrap: true,
keyboard: true,
touch: true,
lazyImages: true,
lazyOnDemand: true,
nextTrigger: null,
nextHint: "Next (" + (rtl ? "Left" : "Right") + " Arrow)",
previousTrigger: null,
previousHint: "Previous (" + (rtl ? "Right" : "Left") + " Arrow)",
indicators: null
};
this.options = $.extend({}, this.defaults, options);
this.paused = null;
this.interval = null;
this.sliding = null;
this.$items = null;
this.keyboardTriggered = null;
this.translationDuration = null;
this.$nextTrigger = this.options.nextTrigger ? $(this.options.nextTrigger) : this.$element.children("button.forward");
this.$previousTrigger = this.options.previousTrigger ? $(this.options.previousTrigger) : this.$element.children("button:not(.forward)");
this.$indicators = this.options.indicators ? $(this.options.indicators) : this.$element.find("> ol > li");
this.id = this.$element.attr("id") || "carousel-" + $.pseudoUnique();
var self = this,
activeIndex = this.activeindex();
// Hide the previous button if no wrapping.
if (!this.options.wrap) {
if (activeIndex === 0) {
this.$previousTrigger.hide().attr("aria-hidden", true);
}
}
// Hide both if one item.
if (this.$items.length === 1) {
this.$previousTrigger.hide().attr("aria-hidden", true);
this.$nextTrigger.hide().attr("aria-hidden", true);
}
// Add the css class to support fade.
this.options.mode === "fade" && this.$element.addClass("carousel-fade");
if (this.options.lazyImages && !this.options.lazyOnDemand) {
$(w).on("load", $.proxy(this.lazyimages), this);
}
// Add a11y features.
this.$element.attr({ "role": "listbox", "aria-live": "polite", "id": this.id });
this.$element.children("figure").each(function (index) {
var active = index === activeIndex;
$(this).attr({
"role": "option",
"aria-selected": active,
"tabindex": active ? 0 : -1
});
});
// Find and add a11y to controls.
var $controls = this.$nextTrigger.add(this.$previousTrigger);
$controls.each(function () {
var $this = $(this).attr({ "tabindex": 0, "aria-controls": self.id });
!$this.is("button") ? $this.attr({ "role": "button" }) : $this.attr({ "type": "button" });
if (!$this.find(".visuallyhidden").length) {
$("").addClass("visuallyhidden")
.html($this.is(self.$nextTrigger.selector) ? self.options.nextHint : self.options.previousHint)
.appendTo($this);
}
});
// Find and a11y indicators.
this.$indicators.attr({ "role": "button", "aria-controls": self.id }).eq(activeIndex).addClass("active");
// Bind events
// Not namespaced as we want to keep behaviour when not using data api.
if (this.options.pause === "hover") {
// Bind the mouse enter/leave events.
if (!$.support.touchEvents && !$.support.pointerEvents) {
this.$element.on(emouseenter, $.proxy(this.pause, this))
.on(emouseleave, $.proxy(this.cycle, this));
}
}
if (this.options.touch) {
// You always have to pass the third parameter if setting data.
this.$element.on("swipe.carousel", { touchAction: "pan-y" }, true)
.on("swipemove.carousel", $.proxy(this.swipemove, this))
.on("swipeend.carousel", $.proxy(this.swipeend, this));
}
if (this.options.keyboard) {
this.$element.on(ekeydown, $.proxy(this.keydown, this));
}
$(document).on(this.options.keyboard ? [eclick, ekeydown].join(" ") : eclick, "[aria-controls=" + this.id + "]", $.proxy(this.click, this));
};
Carousel.prototype.activeindex = function () {
var $activeItem = this.$element.find(".carousel-active");
this.$items = $activeItem.parent().children("figure");
return this.$items.index($activeItem);
};
Carousel.prototype.cycle = function (event) {
if (!event) {
// Flag false when there's no event.
this.paused = false;
}
if (this.interval) {
w.clearInterval(this.interval);
}
if (this.options.interval && !this.paused) {
// Cycle to the next item on the set interval
this.interval = w.setInterval($.proxy(this.next, this), this.options.interval);
}
// Return the carousel for chaining.
return this;
};
Carousel.prototype.to = function (position) {
var activePosition = this.activeindex(),
self = this;
if (position > (this.$items.length - 1) || position < 0) {
return false;
}
if (this.sliding) {
// Fire the slid event.
return this.$element.one(eslid, function () {
// Reset the position.
self.to(position);
});
}
if (activePosition === position) {
return this.pause().cycle();
}
return this.slide(position > activePosition ? "next" : "prev", $(this.$items[position]));
};
Carousel.prototype.pause = function (event) {
if (!event) {
// Mark as paused
this.paused = true;
}
// Ensure that transition end is triggered.
if (this.$element.find(".next, .prev").length && $.support.transition) {
this.$element.trigger($.support.transition.end);
this.cycle(true);
}
// Clear the interval and return the carousel for chaining.
this.interval = w.clearInterval(this.interval);
return this;
};
Carousel.prototype.next = function () {
if (this.sliding) {
return false;
}
return this.slide("next");
};
Carousel.prototype.prev = function () {
if (this.sliding) {
return false;
}
return this.slide("prev");
};
Carousel.prototype.slide = function (type, next) {
var $activeItem = this.$element.children("figure.carousel-active"),
$nextItem = next || $activeItem[type]("figure"),
isCycling = this.interval,
isNext = type === "next",
direction = isNext ? "left" : "right",
fallback = isNext ? "first" : "last",
self = this,
slideEvent,
slidEvent;
if (isCycling) {
// Pause if cycling.
this.pause();
}
// Work out which item to slide to.
if (!$nextItem.length) {
if (!this.options.wrap) {
return false;
}
$nextItem = this.$element.children("figure")[fallback]();
}
if ($nextItem.hasClass("carousel-active")) {
return (this.sliding = false);
}
// Trigger the slide event with positional data.
slideEvent = $.Event(eslide, { relatedTarget: $nextItem[0], direction: direction });
this.$element.trigger(slideEvent);
if (slideEvent.isDefaultPrevented()) {
return false;
}
if (this.options.lazyImages && this.options.lazyOnDemand) {
// Load the next image.
this.lazyimages.call($nextItem);
}
// Good to go? Then let's slide.
this.sliding = true;
if (isCycling) {
this.pause();
}
this.$element.one(eslid, function () {
// Hide the correct trigger if necessary.
if (!self.options.wrap) {
var activePosition = self.activeindex();
if (self.$items && activePosition === self.$items.length - 1) {
self.$nextTrigger.hide().attr("aria-hidden", true);
self.$previousTrigger.show().removeAttr("aria-hidden");
if (self.keyboardTriggered) { self.$previousTrigger.focus(); self.keyboardTriggered = false; }
}
else if (self.$items && activePosition === 0) {
self.$previousTrigger.hide().attr("aria-hidden", true);
self.$nextTrigger.show().removeAttr("aria-hidden");
if (self.keyboardTriggered) { self.$nextTrigger.focus(); self.keyboardTriggered = false; }
} else {
self.$nextTrigger.show().removeAttr("aria-hidden");
self.$previousTrigger.show().removeAttr("aria-hidden");
self.keyboardTriggered = false;
}
}
// Highlight the correct indicator.
self.$indicators.removeClass("active")
.eq(self.activeindex()).addClass("active");
});
var complete = function () {
if (self.$items) {
// Clear the transition properties if set.
self.$items.removeClass("swiping").css({ "transition-duration": "" });
}
$activeItem.removeClass(["carousel-active", direction].join(" "))
.attr({ "aria-selected": false, "tabIndex": -1 });
$nextItem.removeClass([type, direction].join(" ")).addClass("carousel-active")
.attr({ "aria-selected": true, "tabIndex": 0 });
self.sliding = false;
slidEvent = $.Event(eslid, { relatedTarget: $nextItem[0], direction: direction });
self.$element.trigger(slidEvent);
};
// Force reflow.
$nextItem.addClass(type).redraw();
// Do the slide.
$activeItem.addClass(direction);
$nextItem.addClass(direction);
// Clear the added css.
if (this.$items) {
this.$items.each(function () {
$(this).removeClass("swipe swipe-next").css({ "left": "", "right": "", "opacity": "" });
});
}
// We use ensure here as IOS7 can sometimes not fire
// the event if a scroll is accidentally triggered.
$activeItem.onTransitionEnd(complete).ensureTransitionEnd();
// Restart the cycle.
if (isCycling) {
this.cycle();
}
return this;
};
Carousel.prototype.keydown = function (event) {
if (/input|textarea/i.test(event.target.tagName)) {
return;
}
var which = event && event.which;
if (which === keys.LEFT || which === keys.RIGHT) {
this.keyboardTriggered = true;
event.preventDefault();
event.stopPropagation();
// Seek out the correct direction indicator, shift, and focus.
switch (which) {
case keys.LEFT:
if (rtl) {
this.next();
this.$nextTrigger.focus();
} else {
this.prev();
this.$previousTrigger.focus();
}
break;
case keys.RIGHT:
if (rtl) {
this.prev();
this.$previousTrigger.focus();
} else {
this.next();
this.$nextTrigger.focus();
}
break;
}
}
};
Carousel.prototype.click = function (event) {
if (!event) {
return;
}
var which = event.which;
if (which && which !== 1) {
if (which === keys.SPACE || which === keys.ENTER) {
this.keyboardTriggered = true;
} else {
return;
}
}
event.preventDefault();
event.stopPropagation();
var $this = $(event.target);
if ($this.hasClass("forward")) {
this.next();
}
else if ($this.is("button")) {
this.prev();
} else {
this.to($this.index());
}
};
Carousel.prototype.swipemove = function (event) {
if (this.sliding) {
return;
}
this.pause();
// Left is next.
var isNext = event.delta.x < 0,
type = isNext ? (rtl ? "prev" : "next") : (rtl ? "next" : "prev"),
fallback = isNext ? (rtl ? "last" : "first") : (rtl ? "first" : "last"),
activePosition = this.activeindex(),
$activeItem = this.$items.eq(activePosition),
$nextItem = $activeItem[type]("figure");
if (this.$items.length === 1) {
return;
}
if (!$nextItem.length) {
if (!this.options.wrap) {
return;
}
$nextItem = this.$element.children("figure")[fallback]();
}
this.$items.not($activeItem).not($nextItem).removeClass("swipe swiping swipe-next").css({ "left": "", "right": "", "opacity": "" });
if ($nextItem.hasClass("carousel-active")) {
return;
}
if (this.options.lazyImages && this.options.lazyOnDemand) {
// Load the next image.
this.lazyimages.call($nextItem);
}
// Get the distance swiped as a percentage.
var width = $activeItem.width(),
percent = parseFloat((event.delta.x / width) * 100),
diff = isNext ? 100 : -100;
if (rtl) {
percent *= -1;
}
// This is crazy complicated. Basically swipe behaviour change direction in rtl
// So you need to handle that.
this.$element.addClass("no-transition");
if (this.options.mode === "slide") {
if (rtl) {
$activeItem.addClass("swiping").css({ "right": percent + "%" });
$nextItem.addClass("swipe swipe-next").css({ "right": (percent - diff) + "%" });
} else {
$activeItem.addClass("swiping").css({ "left": percent + "%" });
$nextItem.addClass("swipe swipe-next").css({ "left": (percent + diff) + "%" });
}
} else {
$activeItem.addClass("swipe").css({ "opacity": 1 - Math.abs((percent / 100)) });
$nextItem.addClass("swipe swipe-next");
}
};
Carousel.prototype.swipeend = function (event) {
if (this.sliding || !this.$element.hasClass("no-transition")) {
return;
}
var direction = event.direction,
method = "next";
if (direction === "right") {
method = "prev";
}
// Re-enable the transitions.
this.$element.removeClass("no-transition");
if (supportTransition) {
// Trim the animation duration based on the current position.
var activePosition = this.activeindex(),
$activeItem = this.$items.eq(activePosition);
if (!this.translationDuration) {
this.translationDuration = parseFloat($activeItem.css("transition-duration"));
}
// Get the distance and turn it into a percentage
// to calculate the duration. Whichever is lowest is used.
var width = $activeItem.width(),
percentageTravelled = (Math.abs(event.delta.x) / width) * 100,
swipeDuration = (((event.duration / 1000) * 100) / percentageTravelled),
newDuration = (((100 - percentageTravelled) / 100) * (Math.min(this.translationDuration, swipeDuration)));
// Set the new temporary duration.
this.$items.each(function () {
$(this).css({ "transition-duration": newDuration + "s" });
});
}
this.cycle();
this.slide(method, $(this.$items.filter(".swipe-next")));
};
Carousel.prototype.lazyimages = function () {
if (!this.data("lazyLoaded")) {
this.find("img[data-src]").each(function () {
if (this.src.length === 0) {
this.src = this.getAttribute("data-src");
}
});
this.data("lazyLoaded", true);
}
};
// No conflict.
var old = $.fn.carousel;
// Plug-in definition
$.fn.carousel = function (options) {
return this.each(function () {
var $this = $(this),
data = $this.data("r.carousel"),
opts = typeof options === "object" ? options : null;
if (!data) {
// Check the data and reassign if not present.
$this.data("r.carousel", (data = new Carousel(this, opts)));
}
if (typeof options === "number") {
// Cycle to the given number.
data.to(options);
} else if (typeof options === "string" && /(cycle|pause|next|prev)/.test(options) || (options = opts && opts.slide)) {
data[options]();
} else if (data.options.interval) {
data.pause().cycle();
}
});
};
// Set the public constructor.
$.fn.carousel.Constructor = Carousel;
$.fn.carousel.noConflict = function () {
$.fn.carousel = old;
return this;
};
// Data API
var init = function () {
$(".carousel").each(function () {
var $this = $(this),
loaded = $this.data("r.carouselLoaded");
if (!loaded) {
$this.data("r.carouselLoaded", true);
$this.carousel($.getDataOptions($this, "carousel"));
}
});
},
debouncedInit = $.debounce(init, 500);
$(document).on([eready, echanged].join(" "), function (event) {
event.type === "ready" ? init() : debouncedInit();
});
w.RESPONSIVE_CAROUSEL = true;
}(jQuery, window, ".r.carousel", ".data-api"));
/*
* Responsive Conditional
*/
/*global jQuery*/
/*jshint expr:true*/
(function ($, w, ns, da) {
"use strict";
if (w.RESPONSIVE_CONDITIONAL) {
return;
}
// General variables and methods.
var eready = "ready" + ns + da,
echanged = ["domchanged" + ns + da, "shown.r.modal" + da].join(" "),
eresize = ["resize" + ns, "orientationchange" + ns].join(" "),
eload = "load" + ns,
eloaded = "loaded" + ns,
eerror = "error" + ns;
// AutoSize class definition
var Conditional = function (element, options) {
this.$element = $(element);
this.defaults = {
xxs: null,
xs: null,
s: null,
m: null,
l: null,
fallback: null,
errorHint: "
An error has occured.
"
};
this.cache = {};
this.options = $.extend({}, this.defaults, options);
this.currentGrid = null;
this.currentTarget = null;
this.loading = null;
// Bind events.
$(w).on(eresize, $.debounce($.proxy(this.resize, this), 50));
// First Run
this.resize();
};
Conditional.prototype.resize = function () {
var current = $.support.currentGrid(),
grid = current.grid,
range = current.range;
// Check to see if we need to cache the current content.
if (!this.options.fallback) {
for (var level in range) {
if (range.hasOwnProperty(level)) {
var name = range[level];
if (!this.options[name]) {
this.options[name] = "fallback";
this.cache[name] = this.$element.html();
}
}
}
}
if (this.currentGrid !== grid) {
this.currentGrid = grid;
var self = this,
target = this.options[grid] || this.options.fallback;
if (target && target !== this.currentTarget) {
this.currentTarget = target;
var loadEvent = $.Event(eload);
this.$element.trigger(loadEvent);
if (this.loading || loadEvent.isDefaultPrevented()) {
return;
}
this.loading = true;
// First check the cache.
if (this.cache[this.currentGrid]) {
this.$element.empty().html(this.cache[this.currentGrid]);
this.loading = false;
this.$element.trigger($.Event(eloaded, { relatedTarget: self.$element[0], loadTarget: target, grid: this.currentGrid }));
} else {
this.$element.empty().load(target, null, function (responseText, textStatus) {
// Handle errors.
if (textStatus === "error") {
self.$element.trigger($.Event(eerror, { relatedTarget: self.$element[0], loadTarget: target, grid: self.currentGrid }));
self.$element.html(self.options.errorHint);
self.loading = false;
return;
}
var selector, off = target.indexOf(" ");
if (off >= 0) {
selector = $.trim(target.slice(off));
}
// Cache the result so no further requests are made. This uses the internal `parseHTML`
// method so be aware that could one day change.
self.cache[grid] = selector ? $("