/* ==|== 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 ? $("
").append($.parseHTML(responseText)).find(selector).wrap("
").parent().html() : responseText; self.loading = false; self.$element.trigger($.Event(eloaded, { relatedTarget: self.$element[0], loadTarget: target, grid: self.currentGrid })); }); } } } }; // No conflict. var old = $.fn.conditional; // Plug-in definition $.fn.conditional = function (options) { return this.each(function () { var $this = $(this), data = $this.data("r.conditional"), opts = typeof options === "object" ? options : null; if (!data) { // Check the data and reassign if not present. $this.data("r.conditional", (data = new Conditional(this, opts))); } if (options === "resize") { data.resize(); } }); }; // Set the public constructor. $.fn.conditional.Constructor = Conditional; $.fn.conditional.noConflict = function () { $.fn.conditional = old; return this; }; // Data API var init = function () { $(":attrStart(data-conditional)").each(function () { var $this = $(this), loaded = $this.data("r.conditionalLoaded"); if (!loaded) { $this.data("r.conditionalLoaded", true); $this.conditional($.getDataOptions($this, "conditional")); } }); }, debouncedInit = $.debounce(init, 500); $(document).on([eready, echanged].join(" "), function (event) { event.type === "ready" ? init() : debouncedInit(); }); w.RESPONSIVE_CONDITIONAL = true; }(jQuery, window, ".r.conditional", ".data-api")); /* * Responsive Dismiss */ /*global jQuery*/ /*jshint expr:true*/ (function ($, w, ns, da) { "use strict"; if (w.RESPONSIVE_DISMISS) { return; } // General variables. var eready = "ready" + ns + da, echanged = ["domchanged" + ns + da, "shown.r.modal" + da].join(" "), eclick = "click", edismiss = "dismiss" + ns, edismissed = "dismissed" + ns; // Dismiss class definition var Dismiss = function (element, options) { this.defaults = { closeHint: "Click to close" }; this.options = $.extend({}, this.defaults, options); this.$element = $(element).attr({ "type": "button" }); this.$target = this.$element.closest(options.target); this.dismissing = null; // A11y goodness. if (this.$element.is("button")) { $(element).attr({ "type": "button" }); } if (this.$target.hasClass("alert")) { this.$target.attr({ "role": "alert" }); } if (!this.$element.find(".visuallyhidden").length) { $("").addClass("visuallyhidden") .html(this.options.closeHint) .appendTo(this.$element); } // Bind events this.$element.on(eclick, $.proxy(this.click, this)); }; Dismiss.prototype.close = function () { var dismissEvent = $.Event(edismiss), $target = this.$target, self = this, complete = function () { self.dismissing = false; $target.removeClass("fade-out").attr({ "aria-hidden": true, "tabindex": -1 }); self.$element.trigger($.Event(edismissed)); }; this.$element.trigger(dismissEvent); if (this.dismissing || dismissEvent.isDefaultPrevented()) { return; } this.dismissing = true; $target.addClass("fade-in fade-out") .redraw() .removeClass("fade-in"); // Do our callback this.$target.onTransitionEnd(complete); }; Dismiss.prototype.click = function (event) { event.preventDefault(); this.close(); }; // No conflict. var old = $.fn.dismiss; // Plug-in definition $.fn.dismiss = function (options) { return this.each(function () { var $this = $(this), data = $this.data("dismiss"); if (!data) { // Check the data and reassign if not present. $this.data("dismiss", (data = new Dismiss(this, options))); } // Close the element. if (options === "close") { data.close(); } }); }; // Set the public constructor. $.fn.dismiss.Constructor = Dismiss; $.fn.dismiss.noConflict = function () { $.fn.dismiss = old; return this; }; // Data API var init = function () { $("button[data-dismiss-target]").each(function () { var $this = $(this), loaded = $this.data("r.dismissLoaded"); if (!loaded) { $this.data("r.dismissLoaded", true); $this.dismiss($.getDataOptions($this, "dismiss")); } }); }, debouncedInit = $.debounce(init, 500); $(document).on([eready, echanged].join(" "), function (event) { event.type === "ready" ? init() : debouncedInit(); }); w.RESPONSIVE_DISMISS = true; }(jQuery, window, ".r.dismiss", ".data-api")); /* * Responsive Dropdown */ /*jshint expr:true*/ /*global jQuery*/ (function ($, w, ns, da) { "use strict"; if (w.RESPONSIVE_DROPDOWN) { return; } // General variables. var supportTransition = w.getComputedStyle && $.support.transition, rtl = $.support.rtl, eready = "ready" + ns + da, echanged = ["domchanged" + ns + da, "shown.r.modal" + da].join(" "), eclick = "click", ekeydown = "keydown", eshow = "show" + ns, eshown = "shown" + ns, ehide = "hide" + ns, ehidden = "hidden" + ns; var keys = { SPACE: 32, LEFT: 37, RIGHT: 39 }; // The Dropdown class definition var Dropdown = function (element, options) { this.$element = $(element); this.$target = $(options.target); this.defaults = { dimension: "height" }; this.options = $.extend({}, this.defaults, options); this.$parent = null; this.transitioning = null; this.endSize = null; if (this.options.parent) { this.$parent = this.$target.closest(this.options.parent); } // Add accessibility features. if (this.$parent) { this.$parent.attr({ "role": "tablist", "aria-multiselectable": "true" }) .find("div:not(.collapse,.accordion-body)").attr("role", "presentation"); } else { $(".accordion").find("div:not(.collapse,.accordion-body)").addBack().attr("role", "presentation"); } var id = this.$element.attr("id") || "dropdown-" + $.pseudoUnique(), paneId = this.$target.attr("id") || "dropdown-" + $.pseudoUnique(), active = !this.$target.hasClass("collapse"); this.$element.attr({ "id": id, "role": "tab", "aria-controls": paneId, "aria-selected": active, "aria-expanded": active, "tabindex": 0 }); this.$target.attr({ "id": paneId, "role": "tabpanel", "aria-labelledby": id, "aria-hidden": !active, "tabindex": active ? 0 : -1 }); // Bind events. this.$element.on(eclick, $.proxy(this.click, this)); this.$element.on(ekeydown, $.proxy(this.keydown, this)); }; Dropdown.prototype.show = function () { if (this.transitioning || this.$target.hasClass("expand")) { return; } this.transitioning = true; var self = this, dimension = this.options.dimension, size, $actives = []; if (this.$parent) { // Get all the related open panes. $actives = this.$parent.find(" > [role=presentation] > [role=presentation]").children("[role=tab]"); $actives = $.grep($actives, function (a) { var data = $(a).data("r.dropdown"), $target = data && data.$target; return $target && $target.hasClass("dropdown-group") && !$target.hasClass("collapse") && data.$parent && data.$parent[0] === self.$parent[0]; }); } // Set the height/width to zero then to the height/width // so animation can take place. this.$target[dimension](0); if (supportTransition) { // Calculate the height/width. this.$target[dimension]("auto").attr({ "aria-hidden": false }); this.$target.find("[tabindex]:not(.collapse)").attr({ "aria-hidden": false }); size = w.getComputedStyle(this.$target[0])[dimension]; // Reset to zero and force repaint. this.$target[dimension](0).redraw(); } this.$target[dimension](size || ""); this.transition("removeClass", $.Event(eshow), eshown); if ($actives && $actives.length) { $.each($actives, function () { $(this).dropdown("hide"); }); } }; Dropdown.prototype.hide = function () { if (this.transitioning || this.$target.hasClass("collapse")) { return; } this.transitioning = true; // Reset the height/width and then reduce to zero. var dimension = this.options.dimension, size; if (supportTransition) { // Set the height to auto, calculate the height/width and reset. size = w.getComputedStyle(this.$target[0])[dimension]; // Reset the size and force repaint. this.$target[dimension](size).redraw(); // Force reflow ; } this.$target.removeClass("expand"); this.$target[dimension](0); this.transition("addClass", $.Event(ehide), ehidden); }; Dropdown.prototype.toggle = function () { if (this.transitioning) { return; } // Run the correct command based on the presence of the class "collapse". this[this.$target.hasClass("collapse") ? "show" : "hide"](); }; Dropdown.prototype.transition = function (method, startEvent, completeEvent) { var self = this, doShow = method === "removeClass", complete = function () { // The event to expose. var eventToTrigger = $.Event(completeEvent); // Ensure the height/width is set to auto. self.$target.removeClass("trans")[self.options.dimension](""); // Set the correct aria attributes. self.$target.attr({ "aria-hidden": !doShow, "tabindex": doShow ? 0 : -1 }); var $tab = $("#" + self.$target.attr("aria-labelledby")).attr({ "aria-selected": doShow, "aria-expanded": doShow }); if (doShow) { $tab.focus(); } // Toggle any children. self.$target.find("[tabindex]:not(.collapse)").attr({ "aria-hidden": !doShow, "tabindex": doShow ? 0 : -1 }); self.transitioning = false; self.$element.trigger(eventToTrigger); }; this.$element.trigger(startEvent); if (startEvent.isDefaultPrevented()) { return; } // Remove or add the expand classes. this.$target[method]("collapse"); this.$target[startEvent.type === "show" ? "addClass" : "removeClass"]("trans expand"); this.$target.onTransitionEnd(complete); }; Dropdown.prototype.click = function (event) { event.preventDefault(); event.stopPropagation(); this.toggle(); }; Dropdown.prototype.keydown = function (event) { if (/input|textarea/i.test(event.target.tagName)) { return; } var which = event.which; if (which === keys.SPACE || which === keys.LEFT || which === keys.RIGHT) { event.preventDefault(); event.stopPropagation(); var $this = $(event.target); if (which === keys.SPACE) { this.toggle(); return; } var $parent = this.options.parent ? $this.closest("[role=tablist]") : $this.closest(".accordion"), $items = $parent.find(" > [role=presentation] > [role=presentation]").children("[role=tab]"), index = $items.index($items.filter(":focus")), length = $items.length; if (which === keys.LEFT) { rtl ? index += 1 : index -= 1; } else if (which === keys.RIGHT) { rtl ? index -= 1 : index += 1; } // Ensure that the index stays within bounds. if (index === length) { index = 0; } if (index < 0) { index = length - 1; } $($items.eq(index)).data("r.dropdown").show(); } }; // No conflict. var old = $.fn.dropdown; // Plug-in definition $.fn.dropdown = function (options) { return this.each(function () { var $this = $(this), data = $this.data("r.dropdown"), opts = typeof options === "object" ? options : null; if (!data) { // Check the data and reassign if not present. $this.data("r.dropdown", (data = new Dropdown(this, opts))); } // Run the appropriate function if a string is passed. if (typeof options === "string" && /(show|hide|toggle)/.test(options)) { data[options](); } }); }; // Set the public constructor. $.fn.dropdown.Constructor = Dropdown; $.fn.dropdown.noConflict = function () { $.fn.dropdown = old; return this; }; // Data API var init = function () { $(":attrStart(data-dropdown)").each(function () { var $this = $(this), loaded = $this.data("r.dropdownLoaded"); if (!loaded) { $this.data("r.dropdownLoaded", true); $this.dropdown($.getDataOptions($this, "dropdown")); } }); }, debouncedInit = $.debounce(init, 500); $(document).on([eready, echanged].join(" "), function (event) { event.type === "ready" ? init() : debouncedInit(); }); w.RESPONSIVE_DROPDOWN = true; }(jQuery, window, ".r.dropdown", ".data-api")); /*global jQuery*/ /*jshint expr:true*/ (function ($, w, ns, da) { "use strict"; if (w.RESPONSIVE_MODAL) { return; } var $window = $(w), $html = $("html"), $body = $("body"), $overlay = $("
").attr({ "role": "document" }).addClass("modal-overlay modal-loader fade-out"), $modal = $("
").addClass("modal fade-out").appendTo($overlay), $header = $("
").addClass("modal-header fade-out"), $footer = $("
").addClass("modal-footer fade-out"), $close = $("